aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorNaresh Gottumukkala <bgottumukkala@emulex.com>2013-08-26 05:57:41 -0400
committerRoland Dreier <roland@purestorage.com>2013-09-03 00:17:54 -0400
commitc88bd03ffccdb069fd9541bea347bdab8f4e7e6a (patch)
treedb276771ea7ac959dcd4159b1c6077f69eadd2e6 /drivers/infiniband
parentd3cb6c0b2a0d9f507fff8d7c74b2b334d6751bee (diff)
RDMA/ocrdma: Fix to work with even a single MSI-X vector
There are cases like SRIOV where can get only one MSI-X vector allocated for RoCE. In that case we need to use the vector for both data plane and control plane. We need to use EQ create version V2. Signed-off-by: Naresh Gottumukkala <bgottumukkala@emulex.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma.h3
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.c133
2 files changed, 36 insertions, 100 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h
index 634c2e18521b..9cc966ab3b5a 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma.h
@@ -132,8 +132,7 @@ struct ocrdma_dev {
132 struct ocrdma_cq **cq_tbl; 132 struct ocrdma_cq **cq_tbl;
133 struct ocrdma_qp **qp_tbl; 133 struct ocrdma_qp **qp_tbl;
134 134
135 struct ocrdma_eq meq; 135 struct ocrdma_eq *eq_tbl;
136 struct ocrdma_eq *qp_eq_tbl;
137 int eq_cnt; 136 int eq_cnt;
138 u16 base_eqid; 137 u16 base_eqid;
139 u16 max_eq; 138 u16 max_eq;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 6a62b2372fba..1b14ef811b36 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -364,22 +364,6 @@ static void ocrdma_build_q_pages(struct ocrdma_pa *q_pa, int cnt,
364 } 364 }
365} 365}
366 366
367static void ocrdma_assign_eq_vect_gen2(struct ocrdma_dev *dev,
368 struct ocrdma_eq *eq)
369{
370 /* assign vector and update vector id for next EQ */
371 eq->vector = dev->nic_info.msix.start_vector;
372 dev->nic_info.msix.start_vector += 1;
373}
374
375static void ocrdma_free_eq_vect_gen2(struct ocrdma_dev *dev)
376{
377 /* this assumes that EQs are freed in exactly reverse order
378 * as its allocation.
379 */
380 dev->nic_info.msix.start_vector -= 1;
381}
382
383static int ocrdma_mbx_delete_q(struct ocrdma_dev *dev, struct ocrdma_queue_info *q, 367static int ocrdma_mbx_delete_q(struct ocrdma_dev *dev, struct ocrdma_queue_info *q,
384 int queue_type) 368 int queue_type)
385{ 369{
@@ -420,11 +404,8 @@ static int ocrdma_mbx_create_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
420 memset(cmd, 0, sizeof(*cmd)); 404 memset(cmd, 0, sizeof(*cmd));
421 ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_EQ, OCRDMA_SUBSYS_COMMON, 405 ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_EQ, OCRDMA_SUBSYS_COMMON,
422 sizeof(*cmd)); 406 sizeof(*cmd));
423 if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY)
424 cmd->req.rsvd_version = 0;
425 else
426 cmd->req.rsvd_version = 2;
427 407
408 cmd->req.rsvd_version = 2;
428 cmd->num_pages = 4; 409 cmd->num_pages = 4;
429 cmd->valid = OCRDMA_CREATE_EQ_VALID; 410 cmd->valid = OCRDMA_CREATE_EQ_VALID;
430 cmd->cnt = 4 << OCRDMA_CREATE_EQ_CNT_SHIFT; 411 cmd->cnt = 4 << OCRDMA_CREATE_EQ_CNT_SHIFT;
@@ -435,12 +416,7 @@ static int ocrdma_mbx_create_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
435 NULL); 416 NULL);
436 if (!status) { 417 if (!status) {
437 eq->q.id = rsp->vector_eqid & 0xffff; 418 eq->q.id = rsp->vector_eqid & 0xffff;
438 if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) { 419 eq->vector = (rsp->vector_eqid >> 16) & 0xffff;
439 ocrdma_assign_eq_vect_gen2(dev, eq);
440 } else {
441 eq->vector = (rsp->vector_eqid >> 16) & 0xffff;
442 dev->nic_info.msix.start_vector += 1;
443 }
444 eq->q.created = true; 420 eq->q.created = true;
445 } 421 }
446 return status; 422 return status;
@@ -483,8 +459,6 @@ static void _ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
483{ 459{
484 if (eq->q.created) { 460 if (eq->q.created) {
485 ocrdma_mbx_delete_q(dev, &eq->q, QTYPE_EQ); 461 ocrdma_mbx_delete_q(dev, &eq->q, QTYPE_EQ);
486 if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY)
487 ocrdma_free_eq_vect_gen2(dev);
488 ocrdma_free_q(dev, &eq->q); 462 ocrdma_free_q(dev, &eq->q);
489 } 463 }
490} 464}
@@ -503,13 +477,12 @@ static void ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
503 _ocrdma_destroy_eq(dev, eq); 477 _ocrdma_destroy_eq(dev, eq);
504} 478}
505 479
506static void ocrdma_destroy_qp_eqs(struct ocrdma_dev *dev) 480static void ocrdma_destroy_eqs(struct ocrdma_dev *dev)
507{ 481{
508 int i; 482 int i;
509 483
510 /* deallocate the data path eqs */
511 for (i = 0; i < dev->eq_cnt; i++) 484 for (i = 0; i < dev->eq_cnt; i++)
512 ocrdma_destroy_eq(dev, &dev->qp_eq_tbl[i]); 485 ocrdma_destroy_eq(dev, &dev->eq_tbl[i]);
513} 486}
514 487
515static int ocrdma_mbx_mq_cq_create(struct ocrdma_dev *dev, 488static int ocrdma_mbx_mq_cq_create(struct ocrdma_dev *dev,
@@ -598,7 +571,7 @@ static int ocrdma_create_mq(struct ocrdma_dev *dev)
598 if (status) 571 if (status)
599 goto alloc_err; 572 goto alloc_err;
600 573
601 status = ocrdma_mbx_mq_cq_create(dev, &dev->mq.cq, &dev->meq.q); 574 status = ocrdma_mbx_mq_cq_create(dev, &dev->mq.cq, &dev->eq_tbl[0].q);
602 if (status) 575 if (status)
603 goto mbx_cq_free; 576 goto mbx_cq_free;
604 577
@@ -1304,19 +1277,19 @@ static u16 ocrdma_bind_eq(struct ocrdma_dev *dev)
1304 u16 eq_id; 1277 u16 eq_id;
1305 1278
1306 mutex_lock(&dev->dev_lock); 1279 mutex_lock(&dev->dev_lock);
1307 cq_cnt = dev->qp_eq_tbl[0].cq_cnt; 1280 cq_cnt = dev->eq_tbl[0].cq_cnt;
1308 eq_id = dev->qp_eq_tbl[0].q.id; 1281 eq_id = dev->eq_tbl[0].q.id;
1309 /* find the EQ which is has the least number of 1282 /* find the EQ which is has the least number of
1310 * CQs associated with it. 1283 * CQs associated with it.
1311 */ 1284 */
1312 for (i = 0; i < dev->eq_cnt; i++) { 1285 for (i = 0; i < dev->eq_cnt; i++) {
1313 if (dev->qp_eq_tbl[i].cq_cnt < cq_cnt) { 1286 if (dev->eq_tbl[i].cq_cnt < cq_cnt) {
1314 cq_cnt = dev->qp_eq_tbl[i].cq_cnt; 1287 cq_cnt = dev->eq_tbl[i].cq_cnt;
1315 eq_id = dev->qp_eq_tbl[i].q.id; 1288 eq_id = dev->eq_tbl[i].q.id;
1316 selected_eq = i; 1289 selected_eq = i;
1317 } 1290 }
1318 } 1291 }
1319 dev->qp_eq_tbl[selected_eq].cq_cnt += 1; 1292 dev->eq_tbl[selected_eq].cq_cnt += 1;
1320 mutex_unlock(&dev->dev_lock); 1293 mutex_unlock(&dev->dev_lock);
1321 return eq_id; 1294 return eq_id;
1322} 1295}
@@ -1327,9 +1300,9 @@ static void ocrdma_unbind_eq(struct ocrdma_dev *dev, u16 eq_id)
1327 1300
1328 mutex_lock(&dev->dev_lock); 1301 mutex_lock(&dev->dev_lock);
1329 for (i = 0; i < dev->eq_cnt; i++) { 1302 for (i = 0; i < dev->eq_cnt; i++) {
1330 if (dev->qp_eq_tbl[i].q.id != eq_id) 1303 if (dev->eq_tbl[i].q.id != eq_id)
1331 continue; 1304 continue;
1332 dev->qp_eq_tbl[i].cq_cnt -= 1; 1305 dev->eq_tbl[i].cq_cnt -= 1;
1333 break; 1306 break;
1334 } 1307 }
1335 mutex_unlock(&dev->dev_lock); 1308 mutex_unlock(&dev->dev_lock);
@@ -2434,38 +2407,7 @@ int ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
2434 return 0; 2407 return 0;
2435} 2408}
2436 2409
2437static int ocrdma_create_mq_eq(struct ocrdma_dev *dev) 2410static int ocrdma_create_eqs(struct ocrdma_dev *dev)
2438{
2439 int status;
2440 int irq;
2441 unsigned long flags = 0;
2442 int num_eq = 0;
2443
2444 if (dev->nic_info.intr_mode == BE_INTERRUPT_MODE_INTX) {
2445 flags = IRQF_SHARED;
2446 } else {
2447 num_eq = dev->nic_info.msix.num_vectors -
2448 dev->nic_info.msix.start_vector;
2449 /* minimum two vectors/eq are required for rdma to work.
2450 * one for control path and one for data path.
2451 */
2452 if (num_eq < 2)
2453 return -EBUSY;
2454 }
2455
2456 status = ocrdma_create_eq(dev, &dev->meq, OCRDMA_EQ_LEN);
2457 if (status)
2458 return status;
2459 sprintf(dev->meq.irq_name, "ocrdma_mq%d", dev->id);
2460 irq = ocrdma_get_irq(dev, &dev->meq);
2461 status = request_irq(irq, ocrdma_irq_handler, flags, dev->meq.irq_name,
2462 &dev->meq);
2463 if (status)
2464 _ocrdma_destroy_eq(dev, &dev->meq);
2465 return status;
2466}
2467
2468static int ocrdma_create_qp_eqs(struct ocrdma_dev *dev)
2469{ 2411{
2470 int num_eq, i, status = 0; 2412 int num_eq, i, status = 0;
2471 int irq; 2413 int irq;
@@ -2480,46 +2422,43 @@ static int ocrdma_create_qp_eqs(struct ocrdma_dev *dev)
2480 num_eq = min_t(u32, num_eq, num_online_cpus()); 2422 num_eq = min_t(u32, num_eq, num_online_cpus());
2481 } 2423 }
2482 2424
2483 dev->qp_eq_tbl = kzalloc(sizeof(struct ocrdma_eq) * num_eq, GFP_KERNEL); 2425 if (!num_eq)
2484 if (!dev->qp_eq_tbl) 2426 return -EINVAL;
2427
2428 dev->eq_tbl = kzalloc(sizeof(struct ocrdma_eq) * num_eq, GFP_KERNEL);
2429 if (!dev->eq_tbl)
2485 return -ENOMEM; 2430 return -ENOMEM;
2486 2431
2487 for (i = 0; i < num_eq; i++) { 2432 for (i = 0; i < num_eq; i++) {
2488 status = ocrdma_create_eq(dev, &dev->qp_eq_tbl[i], 2433 status = ocrdma_create_eq(dev, &dev->eq_tbl[i],
2489 OCRDMA_EQ_LEN); 2434 OCRDMA_EQ_LEN);
2490 if (status) { 2435 if (status) {
2491 status = -EINVAL; 2436 status = -EINVAL;
2492 break; 2437 break;
2493 } 2438 }
2494 sprintf(dev->qp_eq_tbl[i].irq_name, "ocrdma_qp%d-%d", 2439 sprintf(dev->eq_tbl[i].irq_name, "ocrdma%d-%d",
2495 dev->id, i); 2440 dev->id, i);
2496 irq = ocrdma_get_irq(dev, &dev->qp_eq_tbl[i]); 2441 irq = ocrdma_get_irq(dev, &dev->eq_tbl[i]);
2497 status = request_irq(irq, ocrdma_irq_handler, flags, 2442 status = request_irq(irq, ocrdma_irq_handler, flags,
2498 dev->qp_eq_tbl[i].irq_name, 2443 dev->eq_tbl[i].irq_name,
2499 &dev->qp_eq_tbl[i]); 2444 &dev->eq_tbl[i]);
2500 if (status) { 2445 if (status)
2501 _ocrdma_destroy_eq(dev, &dev->qp_eq_tbl[i]); 2446 goto done;
2502 status = -EINVAL;
2503 break;
2504 }
2505 dev->eq_cnt += 1; 2447 dev->eq_cnt += 1;
2506 } 2448 }
2507 /* one eq is sufficient for data path to work */ 2449 /* one eq is sufficient for data path to work */
2508 if (dev->eq_cnt >= 1) 2450 return 0;
2509 return 0; 2451done:
2510 ocrdma_destroy_qp_eqs(dev); 2452 ocrdma_destroy_eqs(dev);
2511 return status; 2453 return status;
2512} 2454}
2513 2455
2514int ocrdma_init_hw(struct ocrdma_dev *dev) 2456int ocrdma_init_hw(struct ocrdma_dev *dev)
2515{ 2457{
2516 int status; 2458 int status;
2517 /* set up control path eq */ 2459
2518 status = ocrdma_create_mq_eq(dev); 2460 /* create the eqs */
2519 if (status) 2461 status = ocrdma_create_eqs(dev);
2520 return status;
2521 /* set up data path eq */
2522 status = ocrdma_create_qp_eqs(dev);
2523 if (status) 2462 if (status)
2524 goto qpeq_err; 2463 goto qpeq_err;
2525 status = ocrdma_create_mq(dev); 2464 status = ocrdma_create_mq(dev);
@@ -2542,9 +2481,8 @@ int ocrdma_init_hw(struct ocrdma_dev *dev)
2542conf_err: 2481conf_err:
2543 ocrdma_destroy_mq(dev); 2482 ocrdma_destroy_mq(dev);
2544mq_err: 2483mq_err:
2545 ocrdma_destroy_qp_eqs(dev); 2484 ocrdma_destroy_eqs(dev);
2546qpeq_err: 2485qpeq_err:
2547 ocrdma_destroy_eq(dev, &dev->meq);
2548 pr_err("%s() status=%d\n", __func__, status); 2486 pr_err("%s() status=%d\n", __func__, status);
2549 return status; 2487 return status;
2550} 2488}
@@ -2553,10 +2491,9 @@ void ocrdma_cleanup_hw(struct ocrdma_dev *dev)
2553{ 2491{
2554 ocrdma_mbx_delete_ah_tbl(dev); 2492 ocrdma_mbx_delete_ah_tbl(dev);
2555 2493
2556 /* cleanup the data path eqs */ 2494 /* cleanup the eqs */
2557 ocrdma_destroy_qp_eqs(dev); 2495 ocrdma_destroy_eqs(dev);
2558 2496
2559 /* cleanup the control path */ 2497 /* cleanup the control path */
2560 ocrdma_destroy_mq(dev); 2498 ocrdma_destroy_mq(dev);
2561 ocrdma_destroy_eq(dev, &dev->meq);
2562} 2499}