aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShlomo Pongratz <shlomop@mellanox.com>2012-04-29 10:04:27 -0400
committerRoland Dreier <roland@purestorage.com>2012-05-18 20:04:00 -0400
commite605b743f33d697ad885f99ac8aac480ab6aa6de (patch)
treecc4be106da589cc38964b9f15808476140e17d81
parentf4ec9e9531ac79ee2521faf7ad3d98978f747e42 (diff)
IB/mlx4: Increase the number of vectors (EQs) available for ULPs
Enable IB ULPs to use a larger portion of the device EQs (which map to IRQs). The mlx4_ib driver follows the mlx4_core framework of the EQs to be divided among the device ports. In this scheme, for each IB port, the number of allocated EQs follows the number of cores, subject to other system constraints, such as number available MSI-X vectors. Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c3
-rw-r--r--drivers/infiniband/hw/mlx4/main.c84
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h2
3 files changed, 89 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 34ac0e2e97ee..6d4ef71cbcdf 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -222,6 +222,9 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
222 uar = &dev->priv_uar; 222 uar = &dev->priv_uar;
223 } 223 }
224 224
225 if (dev->eq_table)
226 vector = dev->eq_table[vector % ibdev->num_comp_vectors];
227
225 err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, 228 err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
226 cq->db.dma, &cq->mcq, vector, 0); 229 cq->db.dma, &cq->mcq, vector, 0);
227 if (err) 230 if (err)
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index a739d2738331..7dfa7866d594 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -1076,6 +1076,86 @@ static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event
1076 return NOTIFY_DONE; 1076 return NOTIFY_DONE;
1077} 1077}
1078 1078
1079static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
1080{
1081 char name[32];
1082 int eq_per_port = 0;
1083 int added_eqs = 0;
1084 int total_eqs = 0;
1085 int i, j, eq;
1086
1087 /* Init eq table */
1088 ibdev->eq_table = NULL;
1089 ibdev->eq_added = 0;
1090
1091 /* Legacy mode? */
1092 if (dev->caps.comp_pool == 0)
1093 return;
1094
1095 eq_per_port = rounddown_pow_of_two(dev->caps.comp_pool/
1096 dev->caps.num_ports);
1097
1098 /* Init eq table */
1099 added_eqs = 0;
1100 mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
1101 added_eqs += eq_per_port;
1102
1103 total_eqs = dev->caps.num_comp_vectors + added_eqs;
1104
1105 ibdev->eq_table = kzalloc(total_eqs * sizeof(int), GFP_KERNEL);
1106 if (!ibdev->eq_table)
1107 return;
1108
1109 ibdev->eq_added = added_eqs;
1110
1111 eq = 0;
1112 mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) {
1113 for (j = 0; j < eq_per_port; j++) {
1114 sprintf(name, "mlx4-ib-%d-%d@%s",
1115 i, j, dev->pdev->bus->name);
1116 /* Set IRQ for specific name (per ring) */
1117 if (mlx4_assign_eq(dev, name, &ibdev->eq_table[eq])) {
1118 /* Use legacy (same as mlx4_en driver) */
1119 pr_warn("Can't allocate EQ %d; reverting to legacy\n", eq);
1120 ibdev->eq_table[eq] =
1121 (eq % dev->caps.num_comp_vectors);
1122 }
1123 eq++;
1124 }
1125 }
1126
1127 /* Fill the reset of the vector with legacy EQ */
1128 for (i = 0, eq = added_eqs; i < dev->caps.num_comp_vectors; i++)
1129 ibdev->eq_table[eq++] = i;
1130
1131 /* Advertise the new number of EQs to clients */
1132 ibdev->ib_dev.num_comp_vectors = total_eqs;
1133}
1134
1135static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
1136{
1137 int i;
1138 int total_eqs;
1139
1140 /* Reset the advertised EQ number */
1141 ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors;
1142
1143 /* Free only the added eqs */
1144 for (i = 0; i < ibdev->eq_added; i++) {
1145 /* Don't free legacy eqs if used */
1146 if (ibdev->eq_table[i] <= dev->caps.num_comp_vectors)
1147 continue;
1148 mlx4_release_eq(dev, ibdev->eq_table[i]);
1149 }
1150
1151 total_eqs = dev->caps.num_comp_vectors + ibdev->eq_added;
1152 memset(ibdev->eq_table, 0, total_eqs * sizeof(int));
1153 kfree(ibdev->eq_table);
1154
1155 ibdev->eq_table = NULL;
1156 ibdev->eq_added = 0;
1157}
1158
1079static void *mlx4_ib_add(struct mlx4_dev *dev) 1159static void *mlx4_ib_add(struct mlx4_dev *dev)
1080{ 1160{
1081 struct mlx4_ib_dev *ibdev; 1161 struct mlx4_ib_dev *ibdev;
@@ -1210,6 +1290,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
1210 (1ull << IB_USER_VERBS_CMD_CLOSE_XRCD); 1290 (1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
1211 } 1291 }
1212 1292
1293 mlx4_ib_alloc_eqs(dev, ibdev);
1294
1213 spin_lock_init(&iboe->lock); 1295 spin_lock_init(&iboe->lock);
1214 1296
1215 if (init_node_data(ibdev)) 1297 if (init_node_data(ibdev))
@@ -1298,6 +1380,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
1298 mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB) 1380 mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
1299 mlx4_CLOSE_PORT(dev, p); 1381 mlx4_CLOSE_PORT(dev, p);
1300 1382
1383 mlx4_ib_free_eqs(dev, ibdev);
1384
1301 mlx4_uar_free(dev, &ibdev->priv_uar); 1385 mlx4_uar_free(dev, &ibdev->priv_uar);
1302 mlx4_pd_free(dev, ibdev->priv_pdn); 1386 mlx4_pd_free(dev, ibdev->priv_pdn);
1303 ib_dealloc_device(&ibdev->ib_dev); 1387 ib_dealloc_device(&ibdev->ib_dev);
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index ed80345c99ae..e62297cc77cc 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -202,6 +202,8 @@ struct mlx4_ib_dev {
202 bool ib_active; 202 bool ib_active;
203 struct mlx4_ib_iboe iboe; 203 struct mlx4_ib_iboe iboe;
204 int counters[MLX4_MAX_PORTS]; 204 int counters[MLX4_MAX_PORTS];
205 int *eq_table;
206 int eq_added;
205}; 207};
206 208
207static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) 209static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)