| @@ -59,6 +59,8 @@ struct mlx5_eq_table { · 58 unmodified lines |
| 59 | struct mutex lock; /* sync async eqs creations */ | 59 | struct mutex lock; /* sync async eqs creations */ |
| 60 | int num_comp_eqs; | 60 | int num_comp_eqs; |
| 61 | struct mlx5_irq_table *irq_table; | 61 | struct mlx5_irq_table *irq_table; |
| | 62 | struct mlx5_irq **comp_irqs; |
| | 63 | struct mlx5_irq *ctrl_irq; |
| 62 | #ifdef CONFIG_RFS_ACCEL | 64 | #ifdef CONFIG_RFS_ACCEL |
| 63 | struct cpu_rmap *rmap; | 65 | struct cpu_rmap *rmap; |
| 64 | #endif | 66 | #endif |
| @@ -266,8 +268,8 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, · 201 unmodified lines |
| 266 | u32 out[MLX5_ST_SZ_DW(create_eq_out)] = {0}; | 268 | u32 out[MLX5_ST_SZ_DW(create_eq_out)] = {0}; |
| 267 | u8 log_eq_stride = ilog2(MLX5_EQE_SIZE); | 269 | u8 log_eq_stride = ilog2(MLX5_EQE_SIZE); |
| 268 | struct mlx5_priv *priv = &dev->priv; | 270 | struct mlx5_priv *priv = &dev->priv; |
| 269 | u16 vecidx = param->irq_index; | | |
| 270 | __be64 *pas; | 271 | __be64 *pas; |
| | 272 | u16 vecidx; |
| 271 | void *eqc; | 273 | void *eqc; |
| 272 | int inlen; | 274 | int inlen; |
| 273 | u32 *in; | 275 | u32 *in; |
| @@ -289,23 +291,16 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, · 15 unmodified lines |
| 289 | mlx5_init_fbc(eq->frag_buf.frags, log_eq_stride, log_eq_size, &eq->fbc); | 291 | mlx5_init_fbc(eq->frag_buf.frags, log_eq_stride, log_eq_size, &eq->fbc); |
| 290 | init_eq_buf(eq); | 292 | init_eq_buf(eq); |
| 291 | | 293 | |
| 292 | if (vecidx == MLX5_IRQ_EQ_CTRL) | 294 | eq->irq = param->irq; |
| 293 | eq->irq = mlx5_ctrl_irq_request(dev); | | |
| 294 | else | | |
| 295 | eq->irq = mlx5_irq_request(dev, vecidx, param->affinity); | | |
| 296 | if (IS_ERR(eq->irq)) { | | |
| 297 | err = PTR_ERR(eq->irq); | | |
| 298 | goto err_buf; | | |
| 299 | } | | |
| 300 | | | |
| 301 | vecidx = mlx5_irq_get_index(eq->irq); | 295 | vecidx = mlx5_irq_get_index(eq->irq); |
| | 296 | |
| 302 | inlen = MLX5_ST_SZ_BYTES(create_eq_in) + | 297 | inlen = MLX5_ST_SZ_BYTES(create_eq_in) + |
| 303 | MLX5_FLD_SZ_BYTES(create_eq_in, pas[0]) * eq->frag_buf.npages; | 298 | MLX5_FLD_SZ_BYTES(create_eq_in, pas[0]) * eq->frag_buf.npages; |
| 304 | | 299 | |
| 305 | in = kvzalloc(inlen, GFP_KERNEL); | 300 | in = kvzalloc(inlen, GFP_KERNEL); |
| 306 | if (!in) { | 301 | if (!in) { |
| 307 | err = -ENOMEM; | 302 | err = -ENOMEM; |
| 308 | goto err_irq; | 303 | goto err_buf; |
| 309 | } | 304 | } |
| 310 | | 305 | |
| 311 | pas = (__be64 *)MLX5_ADDR_OF(create_eq_in, in, pas); | 306 | pas = (__be64 *)MLX5_ADDR_OF(create_eq_in, in, pas); |
| @@ -349,8 +344,6 @@ err_eq: · 37 unmodified lines |
| 349 | err_in: | 344 | err_in: |
| 350 | kvfree(in); | 345 | kvfree(in); |
| 351 | | 346 | |
| 352 | err_irq: | | |
| 353 | mlx5_irq_release(eq->irq); | | |
| 354 | err_buf: | 347 | err_buf: |
| 355 | mlx5_frag_buf_free(dev, &eq->frag_buf); | 348 | mlx5_frag_buf_free(dev, &eq->frag_buf); |
| 356 | return err; | 349 | return err; |
| @@ -404,7 +397,6 @@ static int destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq) · 47 unmodified lines |
| 404 | if (err) | 397 | if (err) |
| 405 | mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n", | 398 | mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n", |
| 406 | eq->eqn); | 399 | eq->eqn); |
| 407 | mlx5_irq_release(eq->irq); | | |
| 408 | | 400 | |
| 409 | mlx5_frag_buf_free(dev, &eq->frag_buf); | 401 | mlx5_frag_buf_free(dev, &eq->frag_buf); |
| 410 | return err; | 402 | return err; |
| @@ -597,11 +589,8 @@ setup_async_eq(struct mlx5_core_dev *dev, struct mlx5_eq_async *eq, · 186 unmodified lines |
| 597 | | 589 | |
| 598 | eq->irq_nb.notifier_call = mlx5_eq_async_int; | 590 | eq->irq_nb.notifier_call = mlx5_eq_async_int; |
| 599 | spin_lock_init(&eq->lock); | 591 | spin_lock_init(&eq->lock); |
| 600 | if (!zalloc_cpumask_var(¶m->affinity, GFP_KERNEL)) | | |
| 601 | return -ENOMEM; | | |
| 602 | | 592 | |
| 603 | err = create_async_eq(dev, &eq->core, param); | 593 | err = create_async_eq(dev, &eq->core, param); |
| 604 | free_cpumask_var(param->affinity); | | |
| 605 | if (err) { | 594 | if (err) { |
| 606 | mlx5_core_warn(dev, "failed to create %s EQ %d\n", name, err); | 595 | mlx5_core_warn(dev, "failed to create %s EQ %d\n", name, err); |
| 607 | return err; | 596 | return err; |
| @@ -646,11 +635,18 @@ static int create_async_eqs(struct mlx5_core_dev *dev) · 38 unmodified lines |
| 646 | struct mlx5_eq_param param = {}; | 635 | struct mlx5_eq_param param = {}; |
| 647 | int err; | 636 | int err; |
| 648 | | 637 | |
| | 638 | /* All the async_eqs are using single IRQ, request one IRQ and share its |
| | 639 | * index among all the async_eqs of this device. |
| | 640 | */ |
| | 641 | table->ctrl_irq = mlx5_ctrl_irq_request(dev); |
| | 642 | if (IS_ERR(table->ctrl_irq)) |
| | 643 | return PTR_ERR(table->ctrl_irq); |
| | 644 | |
| 649 | MLX5_NB_INIT(&table->cq_err_nb, cq_err_event_notifier, CQ_ERROR); | 645 | MLX5_NB_INIT(&table->cq_err_nb, cq_err_event_notifier, CQ_ERROR); |
| 650 | mlx5_eq_notifier_register(dev, &table->cq_err_nb); | 646 | mlx5_eq_notifier_register(dev, &table->cq_err_nb); |
| 651 | | 647 | |
| 652 | param = (struct mlx5_eq_param) { | 648 | param = (struct mlx5_eq_param) { |
| 653 | .irq_index = MLX5_IRQ_EQ_CTRL, | 649 | .irq = table->ctrl_irq, |
| 654 | .nent = MLX5_NUM_CMD_EQE, | 650 | .nent = MLX5_NUM_CMD_EQE, |
| 655 | .mask[0] = 1ull << MLX5_EVENT_TYPE_CMD, | 651 | .mask[0] = 1ull << MLX5_EVENT_TYPE_CMD, |
| 656 | }; | 652 | }; |
| @@ -663,7 +659,7 @@ static int create_async_eqs(struct mlx5_core_dev *dev) · 6 unmodified lines |
| 663 | mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); | 659 | mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); |
| 664 | | 660 | |
| 665 | param = (struct mlx5_eq_param) { | 661 | param = (struct mlx5_eq_param) { |
| 666 | .irq_index = MLX5_IRQ_EQ_CTRL, | 662 | .irq = table->ctrl_irq, |
| 667 | .nent = async_eq_depth_devlink_param_get(dev), | 663 | .nent = async_eq_depth_devlink_param_get(dev), |
| 668 | }; | 664 | }; |
| 669 | | 665 | |
| @@ -673,7 +669,7 @@ static int create_async_eqs(struct mlx5_core_dev *dev) · 3 unmodified lines |
| 673 | goto err2; | 669 | goto err2; |
| 674 | | 670 | |
| 675 | param = (struct mlx5_eq_param) { | 671 | param = (struct mlx5_eq_param) { |
| 676 | .irq_index = MLX5_IRQ_EQ_CTRL, | 672 | .irq = table->ctrl_irq, |
| 677 | .nent = /* TODO: sriov max_vf + */ 1, | 673 | .nent = /* TODO: sriov max_vf + */ 1, |
| 678 | .mask[0] = 1ull << MLX5_EVENT_TYPE_PAGE_REQUEST, | 674 | .mask[0] = 1ull << MLX5_EVENT_TYPE_PAGE_REQUEST, |
| 679 | }; | 675 | }; |
| @@ -692,6 +688,7 @@ err2: · 12 unmodified lines |
| 692 | err1: | 688 | err1: |
| 693 | mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); | 689 | mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); |
| 694 | mlx5_eq_notifier_unregister(dev, &table->cq_err_nb); | 690 | mlx5_eq_notifier_unregister(dev, &table->cq_err_nb); |
| | 691 | mlx5_ctrl_irq_release(table->ctrl_irq); |
| 695 | return err; | 692 | return err; |
| 696 | } | 693 | } |
| 697 | | 694 | |
| @@ -706,6 +703,7 @@ static void destroy_async_eqs(struct mlx5_core_dev *dev) · 8 unmodified lines |
| 706 | cleanup_async_eq(dev, &table->cmd_eq, "cmd"); | 703 | cleanup_async_eq(dev, &table->cmd_eq, "cmd"); |
| 707 | mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); | 704 | mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL); |
| 708 | mlx5_eq_notifier_unregister(dev, &table->cq_err_nb); | 705 | mlx5_eq_notifier_unregister(dev, &table->cq_err_nb); |
| | 706 | mlx5_ctrl_irq_release(table->ctrl_irq); |
| 709 | } | 707 | } |
| 710 | | 708 | |
| 711 | struct mlx5_eq *mlx5_get_async_eq(struct mlx5_core_dev *dev) | 709 | struct mlx5_eq *mlx5_get_async_eq(struct mlx5_core_dev *dev) |
| @@ -733,12 +731,10 @@ mlx5_eq_create_generic(struct mlx5_core_dev *dev, · 21 unmodified lines |
| 733 | struct mlx5_eq *eq = kvzalloc(sizeof(*eq), GFP_KERNEL); | 731 | struct mlx5_eq *eq = kvzalloc(sizeof(*eq), GFP_KERNEL); |
| 734 | int err; | 732 | int err; |
| 735 | | 733 | |
| 736 | if (!cpumask_available(param->affinity)) | | |
| 737 | return ERR_PTR(-EINVAL); | | |
| 738 | | | |
| 739 | if (!eq) | 734 | if (!eq) |
| 740 | return ERR_PTR(-ENOMEM); | 735 | return ERR_PTR(-ENOMEM); |
| 741 | | 736 | |
| | 737 | param->irq = dev->priv.eq_table->ctrl_irq; |
| 742 | err = create_async_eq(dev, eq, param); | 738 | err = create_async_eq(dev, eq, param); |
| 743 | if (err) { | 739 | if (err) { |
| 744 | kvfree(eq); | 740 | kvfree(eq); |
| @@ -798,6 +794,45 @@ void mlx5_eq_update_ci(struct mlx5_eq *eq, u32 cc, bool arm) · 53 unmodified lines |
| 798 | } | 794 | } |
| 799 | EXPORT_SYMBOL(mlx5_eq_update_ci); | 795 | EXPORT_SYMBOL(mlx5_eq_update_ci); |
| 800 | | 796 | |
| | 797 | static void comp_irqs_release(struct mlx5_core_dev *dev) |
| | 798 | { |
| | 799 | struct mlx5_eq_table *table = dev->priv.eq_table; |
| | 800 | |
| | 801 | mlx5_irqs_release_vectors(table->comp_irqs, table->num_comp_eqs); |
| | 802 | kfree(table->comp_irqs); |
| | 803 | } |
| | 804 | |
| | 805 | static int comp_irqs_request(struct mlx5_core_dev *dev) |
| | 806 | { |
| | 807 | struct mlx5_eq_table *table = dev->priv.eq_table; |
| | 808 | int ncomp_eqs = table->num_comp_eqs; |
| | 809 | u16 *cpus; |
| | 810 | int ret; |
| | 811 | int i; |
| | 812 | |
| | 813 | ncomp_eqs = table->num_comp_eqs; |
| | 814 | table->comp_irqs = kcalloc(ncomp_eqs, sizeof(*table->comp_irqs), GFP_KERNEL); |
| | 815 | if (!table->comp_irqs) |
| | 816 | return -ENOMEM; |
| | 817 | |
| | 818 | cpus = kcalloc(ncomp_eqs, sizeof(*cpus), GFP_KERNEL); |
| | 819 | if (!cpus) { |
| | 820 | ret = -ENOMEM; |
| | 821 | goto free_irqs; |
| | 822 | } |
| | 823 | for (i = 0; i < ncomp_eqs; i++) |
| | 824 | cpus[i] = cpumask_local_spread(i, dev->priv.numa_node); |
| | 825 | ret = mlx5_irqs_request_vectors(dev, cpus, ncomp_eqs, table->comp_irqs); |
| | 826 | kfree(cpus); |
| | 827 | if (ret < 0) |
| | 828 | goto free_irqs; |
| | 829 | return ret; |
| | 830 | |
| | 831 | free_irqs: |
| | 832 | kfree(table->comp_irqs); |
| | 833 | return ret; |
| | 834 | } |
| | 835 | |
| 801 | static void destroy_comp_eqs(struct mlx5_core_dev *dev) | 836 | static void destroy_comp_eqs(struct mlx5_core_dev *dev) |
| 802 | { | 837 | { |
| 803 | struct mlx5_eq_table *table = dev->priv.eq_table; | 838 | struct mlx5_eq_table *table = dev->priv.eq_table; |
| @@ -812,6 +847,7 @@ static void destroy_comp_eqs(struct mlx5_core_dev *dev) · 8 unmodified lines |
| 812 | tasklet_disable(&eq->tasklet_ctx.task); | 847 | tasklet_disable(&eq->tasklet_ctx.task); |
| 813 | kfree(eq); | 848 | kfree(eq); |
| 814 | } | 849 | } |
| | 850 | comp_irqs_release(dev); |
| 815 | } | 851 | } |
| 816 | | 852 | |
| 817 | static u16 comp_eq_depth_devlink_param_get(struct mlx5_core_dev *dev) | 853 | static u16 comp_eq_depth_devlink_param_get(struct mlx5_core_dev *dev) |
| @@ -838,12 +874,13 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) · 20 unmodified lines |
| 838 | int err; | 874 | int err; |
| 839 | int i; | 875 | int i; |
| 840 | | 876 | |
| | 877 | ncomp_eqs = comp_irqs_request(dev); |
| | 878 | if (ncomp_eqs < 0) |
| | 879 | return ncomp_eqs; |
| 841 | INIT_LIST_HEAD(&table->comp_eqs_list); | 880 | INIT_LIST_HEAD(&table->comp_eqs_list); |
| 842 | ncomp_eqs = table->num_comp_eqs; | | |
| 843 | nent = comp_eq_depth_devlink_param_get(dev); | 881 | nent = comp_eq_depth_devlink_param_get(dev); |
| 844 | for (i = 0; i < ncomp_eqs; i++) { | 882 | for (i = 0; i < ncomp_eqs; i++) { |
| 845 | struct mlx5_eq_param param = {}; | 883 | struct mlx5_eq_param param = {}; |
| 846 | int vecidx = i; | | |
| 847 | | 884 | |
| 848 | eq = kzalloc(sizeof(*eq), GFP_KERNEL); | 885 | eq = kzalloc(sizeof(*eq), GFP_KERNEL); |
| 849 | if (!eq) { | 886 | if (!eq) { |
| @@ -858,18 +895,11 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) · 8 unmodified lines |
| 858 | | 895 | |
| 859 | eq->irq_nb.notifier_call = mlx5_eq_comp_int; | 896 | eq->irq_nb.notifier_call = mlx5_eq_comp_int; |
| 860 | param = (struct mlx5_eq_param) { | 897 | param = (struct mlx5_eq_param) { |
| 861 | .irq_index = vecidx, | 898 | .irq = table->comp_irqs[i], |
| 862 | .nent = nent, | 899 | .nent = nent, |
| 863 | }; | 900 | }; |
| 864 | | 901 | |
| 865 | if (!zalloc_cpumask_var(¶m.affinity, GFP_KERNEL)) { | | |
| 866 | err = -ENOMEM; | | |
| 867 | goto clean_eq; | | |
| 868 | } | | |
| 869 | cpumask_set_cpu(cpumask_local_spread(i, dev->priv.numa_node), | | |
| 870 | param.affinity); | | |
| 871 | err = create_map_eq(dev, &eq->core, ¶m); | 902 | err = create_map_eq(dev, &eq->core, ¶m); |
| 872 | free_cpumask_var(param.affinity); | | |
| 873 | if (err) | 903 | if (err) |
| 874 | goto clean_eq; | 904 | goto clean_eq; |
| 875 | err = mlx5_eq_enable(dev, &eq->core, &eq->irq_nb); | 905 | err = mlx5_eq_enable(dev, &eq->core, &eq->irq_nb); |
| @@ -883,7 +913,9 @@ static int create_comp_eqs(struct mlx5_core_dev *dev) · 7 unmodified lines |
| 883 | list_add_tail(&eq->list, &table->comp_eqs_list); | 913 | list_add_tail(&eq->list, &table->comp_eqs_list); |
| 884 | } | 914 | } |
| 885 | | 915 | |
| | 916 | table->num_comp_eqs = ncomp_eqs; |
| 886 | return 0; | 917 | return 0; |
| | 918 | |
| 887 | clean_eq: | 919 | clean_eq: |
| 888 | kfree(eq); | 920 | kfree(eq); |
| 889 | clean: | 921 | clean: |