diff options
author | Yevgeny Petrilin <yevgenyp@mellanox.co.il> | 2008-12-22 10:15:03 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-12-22 10:15:03 -0500 |
commit | b8dd786f9417e5885929bfe33a235c76a9c1c569 (patch) | |
tree | 16b38c672980d142ffa0ac0ccdeb4af19c20cc31 /drivers/net/mlx4/main.c | |
parent | 061e41fdb5047b1fb161e89664057835935ca1d2 (diff) |
mlx4_core: Add support for multiple completion event vectors
When using MSI-X mode, create a completion event queue for each CPU.
Report the number of completion EQs in a new struct mlx4_caps member,
num_comp_vectors, and extend the mlx4_cq_alloc() interface with a
vector parameter so that consumers can specify which completion EQ
should be used to report events for the CQ being created.
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/net/mlx4/main.c')
-rw-r--r-- | drivers/net/mlx4/main.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 90a0281d15ea..710c79e7a2db 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c | |||
@@ -421,9 +421,7 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, | |||
421 | ((u64) (MLX4_CMPT_TYPE_EQ * | 421 | ((u64) (MLX4_CMPT_TYPE_EQ * |
422 | cmpt_entry_sz) << MLX4_CMPT_SHIFT), | 422 | cmpt_entry_sz) << MLX4_CMPT_SHIFT), |
423 | cmpt_entry_sz, | 423 | cmpt_entry_sz, |
424 | roundup_pow_of_two(MLX4_NUM_EQ + | 424 | dev->caps.num_eqs, dev->caps.num_eqs, 0, 0); |
425 | dev->caps.reserved_eqs), | ||
426 | MLX4_NUM_EQ + dev->caps.reserved_eqs, 0, 0); | ||
427 | if (err) | 425 | if (err) |
428 | goto err_cq; | 426 | goto err_cq; |
429 | 427 | ||
@@ -810,12 +808,12 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) | |||
810 | if (dev->flags & MLX4_FLAG_MSI_X) { | 808 | if (dev->flags & MLX4_FLAG_MSI_X) { |
811 | mlx4_warn(dev, "NOP command failed to generate MSI-X " | 809 | mlx4_warn(dev, "NOP command failed to generate MSI-X " |
812 | "interrupt IRQ %d).\n", | 810 | "interrupt IRQ %d).\n", |
813 | priv->eq_table.eq[MLX4_EQ_ASYNC].irq); | 811 | priv->eq_table.eq[dev->caps.num_comp_vectors].irq); |
814 | mlx4_warn(dev, "Trying again without MSI-X.\n"); | 812 | mlx4_warn(dev, "Trying again without MSI-X.\n"); |
815 | } else { | 813 | } else { |
816 | mlx4_err(dev, "NOP command failed to generate interrupt " | 814 | mlx4_err(dev, "NOP command failed to generate interrupt " |
817 | "(IRQ %d), aborting.\n", | 815 | "(IRQ %d), aborting.\n", |
818 | priv->eq_table.eq[MLX4_EQ_ASYNC].irq); | 816 | priv->eq_table.eq[dev->caps.num_comp_vectors].irq); |
819 | mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n"); | 817 | mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n"); |
820 | } | 818 | } |
821 | 819 | ||
@@ -908,31 +906,50 @@ err_uar_table_free: | |||
908 | static void mlx4_enable_msi_x(struct mlx4_dev *dev) | 906 | static void mlx4_enable_msi_x(struct mlx4_dev *dev) |
909 | { | 907 | { |
910 | struct mlx4_priv *priv = mlx4_priv(dev); | 908 | struct mlx4_priv *priv = mlx4_priv(dev); |
911 | struct msix_entry entries[MLX4_NUM_EQ]; | 909 | struct msix_entry *entries; |
910 | int nreq; | ||
912 | int err; | 911 | int err; |
913 | int i; | 912 | int i; |
914 | 913 | ||
915 | if (msi_x) { | 914 | if (msi_x) { |
916 | for (i = 0; i < MLX4_NUM_EQ; ++i) | 915 | nreq = min(dev->caps.num_eqs - dev->caps.reserved_eqs, |
916 | num_possible_cpus() + 1); | ||
917 | entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); | ||
918 | if (!entries) | ||
919 | goto no_msi; | ||
920 | |||
921 | for (i = 0; i < nreq; ++i) | ||
917 | entries[i].entry = i; | 922 | entries[i].entry = i; |
918 | 923 | ||
919 | err = pci_enable_msix(dev->pdev, entries, ARRAY_SIZE(entries)); | 924 | retry: |
925 | err = pci_enable_msix(dev->pdev, entries, nreq); | ||
920 | if (err) { | 926 | if (err) { |
921 | if (err > 0) | 927 | /* Try again if at least 2 vectors are available */ |
922 | mlx4_info(dev, "Only %d MSI-X vectors available, " | 928 | if (err > 1) { |
923 | "not using MSI-X\n", err); | 929 | mlx4_info(dev, "Requested %d vectors, " |
930 | "but only %d MSI-X vectors available, " | ||
931 | "trying again\n", nreq, err); | ||
932 | nreq = err; | ||
933 | goto retry; | ||
934 | } | ||
935 | |||
924 | goto no_msi; | 936 | goto no_msi; |
925 | } | 937 | } |
926 | 938 | ||
927 | for (i = 0; i < MLX4_NUM_EQ; ++i) | 939 | dev->caps.num_comp_vectors = nreq - 1; |
940 | for (i = 0; i < nreq; ++i) | ||
928 | priv->eq_table.eq[i].irq = entries[i].vector; | 941 | priv->eq_table.eq[i].irq = entries[i].vector; |
929 | 942 | ||
930 | dev->flags |= MLX4_FLAG_MSI_X; | 943 | dev->flags |= MLX4_FLAG_MSI_X; |
944 | |||
945 | kfree(entries); | ||
931 | return; | 946 | return; |
932 | } | 947 | } |
933 | 948 | ||
934 | no_msi: | 949 | no_msi: |
935 | for (i = 0; i < MLX4_NUM_EQ; ++i) | 950 | dev->caps.num_comp_vectors = 1; |
951 | |||
952 | for (i = 0; i < 2; ++i) | ||
936 | priv->eq_table.eq[i].irq = dev->pdev->irq; | 953 | priv->eq_table.eq[i].irq = dev->pdev->irq; |
937 | } | 954 | } |
938 | 955 | ||
@@ -1074,6 +1091,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1074 | if (err) | 1091 | if (err) |
1075 | goto err_cmd; | 1092 | goto err_cmd; |
1076 | 1093 | ||
1094 | err = mlx4_alloc_eq_table(dev); | ||
1095 | if (err) | ||
1096 | goto err_close; | ||
1097 | |||
1077 | mlx4_enable_msi_x(dev); | 1098 | mlx4_enable_msi_x(dev); |
1078 | 1099 | ||
1079 | err = mlx4_setup_hca(dev); | 1100 | err = mlx4_setup_hca(dev); |
@@ -1084,7 +1105,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1084 | } | 1105 | } |
1085 | 1106 | ||
1086 | if (err) | 1107 | if (err) |
1087 | goto err_close; | 1108 | goto err_free_eq; |
1088 | 1109 | ||
1089 | for (port = 1; port <= dev->caps.num_ports; port++) { | 1110 | for (port = 1; port <= dev->caps.num_ports; port++) { |
1090 | err = mlx4_init_port_info(dev, port); | 1111 | err = mlx4_init_port_info(dev, port); |
@@ -1114,6 +1135,9 @@ err_port: | |||
1114 | mlx4_cleanup_pd_table(dev); | 1135 | mlx4_cleanup_pd_table(dev); |
1115 | mlx4_cleanup_uar_table(dev); | 1136 | mlx4_cleanup_uar_table(dev); |
1116 | 1137 | ||
1138 | err_free_eq: | ||
1139 | mlx4_free_eq_table(dev); | ||
1140 | |||
1117 | err_close: | 1141 | err_close: |
1118 | if (dev->flags & MLX4_FLAG_MSI_X) | 1142 | if (dev->flags & MLX4_FLAG_MSI_X) |
1119 | pci_disable_msix(pdev); | 1143 | pci_disable_msix(pdev); |
@@ -1177,6 +1201,7 @@ static void mlx4_remove_one(struct pci_dev *pdev) | |||
1177 | iounmap(priv->kar); | 1201 | iounmap(priv->kar); |
1178 | mlx4_uar_free(dev, &priv->driver_uar); | 1202 | mlx4_uar_free(dev, &priv->driver_uar); |
1179 | mlx4_cleanup_uar_table(dev); | 1203 | mlx4_cleanup_uar_table(dev); |
1204 | mlx4_free_eq_table(dev); | ||
1180 | mlx4_close_hca(dev); | 1205 | mlx4_close_hca(dev); |
1181 | mlx4_cmd_cleanup(dev); | 1206 | mlx4_cmd_cleanup(dev); |
1182 | 1207 | ||