diff options
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 137 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.h | 1 |
2 files changed, 119 insertions, 19 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index a37a1f9d1204..6a5ccd4c7e63 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -468,7 +468,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch) | |||
468 | struct ib_qp *qp; | 468 | struct ib_qp *qp; |
469 | struct ib_fmr_pool *fmr_pool = NULL; | 469 | struct ib_fmr_pool *fmr_pool = NULL; |
470 | struct srp_fr_pool *fr_pool = NULL; | 470 | struct srp_fr_pool *fr_pool = NULL; |
471 | const int m = dev->use_fast_reg ? 3 : 1; | 471 | const int m = 1 + dev->use_fast_reg * target->mr_per_cmd * 2; |
472 | int ret; | 472 | int ret; |
473 | 473 | ||
474 | init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); | 474 | init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); |
@@ -849,7 +849,7 @@ static int srp_alloc_req_data(struct srp_rdma_ch *ch) | |||
849 | 849 | ||
850 | for (i = 0; i < target->req_ring_size; ++i) { | 850 | for (i = 0; i < target->req_ring_size; ++i) { |
851 | req = &ch->req_ring[i]; | 851 | req = &ch->req_ring[i]; |
852 | mr_list = kmalloc(target->cmd_sg_cnt * sizeof(void *), | 852 | mr_list = kmalloc(target->mr_per_cmd * sizeof(void *), |
853 | GFP_KERNEL); | 853 | GFP_KERNEL); |
854 | if (!mr_list) | 854 | if (!mr_list) |
855 | goto out; | 855 | goto out; |
@@ -1298,9 +1298,16 @@ static void srp_reg_mr_err_done(struct ib_cq *cq, struct ib_wc *wc) | |||
1298 | srp_handle_qp_err(cq, wc, "FAST REG"); | 1298 | srp_handle_qp_err(cq, wc, "FAST REG"); |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | /* | ||
1302 | * Map up to sg_nents elements of state->sg where *sg_offset_p is the offset | ||
1303 | * where to start in the first element. If sg_offset_p != NULL then | ||
1304 | * *sg_offset_p is updated to the offset in state->sg[retval] of the first | ||
1305 | * byte that has not yet been mapped. | ||
1306 | */ | ||
1301 | static int srp_map_finish_fr(struct srp_map_state *state, | 1307 | static int srp_map_finish_fr(struct srp_map_state *state, |
1302 | struct srp_request *req, | 1308 | struct srp_request *req, |
1303 | struct srp_rdma_ch *ch, int sg_nents) | 1309 | struct srp_rdma_ch *ch, int sg_nents, |
1310 | unsigned int *sg_offset_p) | ||
1304 | { | 1311 | { |
1305 | struct srp_target_port *target = ch->target; | 1312 | struct srp_target_port *target = ch->target; |
1306 | struct srp_device *dev = target->srp_host->srp_dev; | 1313 | struct srp_device *dev = target->srp_host->srp_dev; |
@@ -1316,9 +1323,13 @@ static int srp_map_finish_fr(struct srp_map_state *state, | |||
1316 | WARN_ON_ONCE(!dev->use_fast_reg); | 1323 | WARN_ON_ONCE(!dev->use_fast_reg); |
1317 | 1324 | ||
1318 | if (sg_nents == 1 && target->global_mr) { | 1325 | if (sg_nents == 1 && target->global_mr) { |
1319 | srp_map_desc(state, sg_dma_address(state->sg), | 1326 | unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0; |
1320 | sg_dma_len(state->sg), | 1327 | |
1328 | srp_map_desc(state, sg_dma_address(state->sg) + sg_offset, | ||
1329 | sg_dma_len(state->sg) - sg_offset, | ||
1321 | target->global_mr->rkey); | 1330 | target->global_mr->rkey); |
1331 | if (sg_offset_p) | ||
1332 | *sg_offset_p = 0; | ||
1322 | return 1; | 1333 | return 1; |
1323 | } | 1334 | } |
1324 | 1335 | ||
@@ -1329,15 +1340,18 @@ static int srp_map_finish_fr(struct srp_map_state *state, | |||
1329 | rkey = ib_inc_rkey(desc->mr->rkey); | 1340 | rkey = ib_inc_rkey(desc->mr->rkey); |
1330 | ib_update_fast_reg_key(desc->mr, rkey); | 1341 | ib_update_fast_reg_key(desc->mr, rkey); |
1331 | 1342 | ||
1332 | n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, NULL, dev->mr_page_size); | 1343 | n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, sg_offset_p, |
1344 | dev->mr_page_size); | ||
1333 | if (unlikely(n < 0)) { | 1345 | if (unlikely(n < 0)) { |
1334 | srp_fr_pool_put(ch->fr_pool, &desc, 1); | 1346 | srp_fr_pool_put(ch->fr_pool, &desc, 1); |
1335 | pr_debug("%s: ib_map_mr_sg(%d) returned %d.\n", | 1347 | pr_debug("%s: ib_map_mr_sg(%d, %d) returned %d.\n", |
1336 | dev_name(&req->scmnd->device->sdev_gendev), sg_nents, | 1348 | dev_name(&req->scmnd->device->sdev_gendev), sg_nents, |
1337 | n); | 1349 | sg_offset_p ? *sg_offset_p : -1, n); |
1338 | return n; | 1350 | return n; |
1339 | } | 1351 | } |
1340 | 1352 | ||
1353 | WARN_ON_ONCE(desc->mr->length == 0); | ||
1354 | |||
1341 | req->reg_cqe.done = srp_reg_mr_err_done; | 1355 | req->reg_cqe.done = srp_reg_mr_err_done; |
1342 | 1356 | ||
1343 | wr.wr.next = NULL; | 1357 | wr.wr.next = NULL; |
@@ -1358,8 +1372,10 @@ static int srp_map_finish_fr(struct srp_map_state *state, | |||
1358 | desc->mr->length, desc->mr->rkey); | 1372 | desc->mr->length, desc->mr->rkey); |
1359 | 1373 | ||
1360 | err = ib_post_send(ch->qp, &wr.wr, &bad_wr); | 1374 | err = ib_post_send(ch->qp, &wr.wr, &bad_wr); |
1361 | if (unlikely(err)) | 1375 | if (unlikely(err)) { |
1376 | WARN_ON_ONCE(err == -ENOMEM); | ||
1362 | return err; | 1377 | return err; |
1378 | } | ||
1363 | 1379 | ||
1364 | return n; | 1380 | return n; |
1365 | } | 1381 | } |
@@ -1416,7 +1432,7 @@ static int srp_map_sg_fmr(struct srp_map_state *state, struct srp_rdma_ch *ch, | |||
1416 | 1432 | ||
1417 | state->pages = req->map_page; | 1433 | state->pages = req->map_page; |
1418 | state->fmr.next = req->fmr_list; | 1434 | state->fmr.next = req->fmr_list; |
1419 | state->fmr.end = req->fmr_list + ch->target->cmd_sg_cnt; | 1435 | state->fmr.end = req->fmr_list + ch->target->mr_per_cmd; |
1420 | 1436 | ||
1421 | for_each_sg(scat, sg, count, i) { | 1437 | for_each_sg(scat, sg, count, i) { |
1422 | ret = srp_map_sg_entry(state, ch, sg, i); | 1438 | ret = srp_map_sg_entry(state, ch, sg, i); |
@@ -1435,9 +1451,11 @@ static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch, | |||
1435 | struct srp_request *req, struct scatterlist *scat, | 1451 | struct srp_request *req, struct scatterlist *scat, |
1436 | int count) | 1452 | int count) |
1437 | { | 1453 | { |
1454 | unsigned int sg_offset = 0; | ||
1455 | |||
1438 | state->desc = req->indirect_desc; | 1456 | state->desc = req->indirect_desc; |
1439 | state->fr.next = req->fr_list; | 1457 | state->fr.next = req->fr_list; |
1440 | state->fr.end = req->fr_list + ch->target->cmd_sg_cnt; | 1458 | state->fr.end = req->fr_list + ch->target->mr_per_cmd; |
1441 | state->sg = scat; | 1459 | state->sg = scat; |
1442 | 1460 | ||
1443 | if (count == 0) | 1461 | if (count == 0) |
@@ -1446,7 +1464,7 @@ static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch, | |||
1446 | while (count) { | 1464 | while (count) { |
1447 | int i, n; | 1465 | int i, n; |
1448 | 1466 | ||
1449 | n = srp_map_finish_fr(state, req, ch, count); | 1467 | n = srp_map_finish_fr(state, req, ch, count, &sg_offset); |
1450 | if (unlikely(n < 0)) | 1468 | if (unlikely(n < 0)) |
1451 | return n; | 1469 | return n; |
1452 | 1470 | ||
@@ -1511,9 +1529,10 @@ static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req, | |||
1511 | #ifdef CONFIG_NEED_SG_DMA_LENGTH | 1529 | #ifdef CONFIG_NEED_SG_DMA_LENGTH |
1512 | idb_sg->dma_length = idb_sg->length; /* hack^2 */ | 1530 | idb_sg->dma_length = idb_sg->length; /* hack^2 */ |
1513 | #endif | 1531 | #endif |
1514 | ret = srp_map_finish_fr(&state, req, ch, 1); | 1532 | ret = srp_map_finish_fr(&state, req, ch, 1, NULL); |
1515 | if (ret < 0) | 1533 | if (ret < 0) |
1516 | return ret; | 1534 | return ret; |
1535 | WARN_ON_ONCE(ret < 1); | ||
1517 | } else if (dev->use_fmr) { | 1536 | } else if (dev->use_fmr) { |
1518 | state.pages = idb_pages; | 1537 | state.pages = idb_pages; |
1519 | state.pages[0] = (req->indirect_dma_addr & | 1538 | state.pages[0] = (req->indirect_dma_addr & |
@@ -1531,6 +1550,32 @@ static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req, | |||
1531 | return 0; | 1550 | return 0; |
1532 | } | 1551 | } |
1533 | 1552 | ||
1553 | #if defined(DYNAMIC_DATA_DEBUG) | ||
1554 | static void srp_check_mapping(struct srp_map_state *state, | ||
1555 | struct srp_rdma_ch *ch, struct srp_request *req, | ||
1556 | struct scatterlist *scat, int count) | ||
1557 | { | ||
1558 | struct srp_device *dev = ch->target->srp_host->srp_dev; | ||
1559 | struct srp_fr_desc **pfr; | ||
1560 | u64 desc_len = 0, mr_len = 0; | ||
1561 | int i; | ||
1562 | |||
1563 | for (i = 0; i < state->ndesc; i++) | ||
1564 | desc_len += be32_to_cpu(req->indirect_desc[i].len); | ||
1565 | if (dev->use_fast_reg) | ||
1566 | for (i = 0, pfr = req->fr_list; i < state->nmdesc; i++, pfr++) | ||
1567 | mr_len += (*pfr)->mr->length; | ||
1568 | else if (dev->use_fmr) | ||
1569 | for (i = 0; i < state->nmdesc; i++) | ||
1570 | mr_len += be32_to_cpu(req->indirect_desc[i].len); | ||
1571 | if (desc_len != scsi_bufflen(req->scmnd) || | ||
1572 | mr_len > scsi_bufflen(req->scmnd)) | ||
1573 | pr_err("Inconsistent: scsi len %d <> desc len %lld <> mr len %lld; ndesc %d; nmdesc = %d\n", | ||
1574 | scsi_bufflen(req->scmnd), desc_len, mr_len, | ||
1575 | state->ndesc, state->nmdesc); | ||
1576 | } | ||
1577 | #endif | ||
1578 | |||
1534 | /** | 1579 | /** |
1535 | * srp_map_data() - map SCSI data buffer onto an SRP request | 1580 | * srp_map_data() - map SCSI data buffer onto an SRP request |
1536 | * @scmnd: SCSI command to map | 1581 | * @scmnd: SCSI command to map |
@@ -1616,6 +1661,15 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch, | |||
1616 | if (ret < 0) | 1661 | if (ret < 0) |
1617 | goto unmap; | 1662 | goto unmap; |
1618 | 1663 | ||
1664 | #if defined(DYNAMIC_DEBUG) | ||
1665 | { | ||
1666 | DEFINE_DYNAMIC_DEBUG_METADATA(ddm, | ||
1667 | "Memory mapping consistency check"); | ||
1668 | if (unlikely(ddm.flags & _DPRINTK_FLAGS_PRINT)) | ||
1669 | srp_check_mapping(&state, ch, req, scat, count); | ||
1670 | } | ||
1671 | #endif | ||
1672 | |||
1619 | /* We've mapped the request, now pull as much of the indirect | 1673 | /* We've mapped the request, now pull as much of the indirect |
1620 | * descriptor table as we can into the command buffer. If this | 1674 | * descriptor table as we can into the command buffer. If this |
1621 | * target is not using an external indirect table, we are | 1675 | * target is not using an external indirect table, we are |
@@ -2580,6 +2634,20 @@ static int srp_reset_host(struct scsi_cmnd *scmnd) | |||
2580 | return srp_reconnect_rport(target->rport) == 0 ? SUCCESS : FAILED; | 2634 | return srp_reconnect_rport(target->rport) == 0 ? SUCCESS : FAILED; |
2581 | } | 2635 | } |
2582 | 2636 | ||
2637 | static int srp_slave_alloc(struct scsi_device *sdev) | ||
2638 | { | ||
2639 | struct Scsi_Host *shost = sdev->host; | ||
2640 | struct srp_target_port *target = host_to_target(shost); | ||
2641 | struct srp_device *srp_dev = target->srp_host->srp_dev; | ||
2642 | struct ib_device *ibdev = srp_dev->dev; | ||
2643 | |||
2644 | if (!(ibdev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)) | ||
2645 | blk_queue_virt_boundary(sdev->request_queue, | ||
2646 | ~srp_dev->mr_page_mask); | ||
2647 | |||
2648 | return 0; | ||
2649 | } | ||
2650 | |||
2583 | static int srp_slave_configure(struct scsi_device *sdev) | 2651 | static int srp_slave_configure(struct scsi_device *sdev) |
2584 | { | 2652 | { |
2585 | struct Scsi_Host *shost = sdev->host; | 2653 | struct Scsi_Host *shost = sdev->host; |
@@ -2771,6 +2839,7 @@ static struct scsi_host_template srp_template = { | |||
2771 | .module = THIS_MODULE, | 2839 | .module = THIS_MODULE, |
2772 | .name = "InfiniBand SRP initiator", | 2840 | .name = "InfiniBand SRP initiator", |
2773 | .proc_name = DRV_NAME, | 2841 | .proc_name = DRV_NAME, |
2842 | .slave_alloc = srp_slave_alloc, | ||
2774 | .slave_configure = srp_slave_configure, | 2843 | .slave_configure = srp_slave_configure, |
2775 | .info = srp_target_info, | 2844 | .info = srp_target_info, |
2776 | .queuecommand = srp_queuecommand, | 2845 | .queuecommand = srp_queuecommand, |
@@ -3177,6 +3246,7 @@ static ssize_t srp_create_target(struct device *dev, | |||
3177 | struct srp_device *srp_dev = host->srp_dev; | 3246 | struct srp_device *srp_dev = host->srp_dev; |
3178 | struct ib_device *ibdev = srp_dev->dev; | 3247 | struct ib_device *ibdev = srp_dev->dev; |
3179 | int ret, node_idx, node, cpu, i; | 3248 | int ret, node_idx, node, cpu, i; |
3249 | unsigned int max_sectors_per_mr, mr_per_cmd = 0; | ||
3180 | bool multich = false; | 3250 | bool multich = false; |
3181 | 3251 | ||
3182 | target_host = scsi_host_alloc(&srp_template, | 3252 | target_host = scsi_host_alloc(&srp_template, |
@@ -3233,8 +3303,33 @@ static ssize_t srp_create_target(struct device *dev, | |||
3233 | target->sg_tablesize = target->cmd_sg_cnt; | 3303 | target->sg_tablesize = target->cmd_sg_cnt; |
3234 | } | 3304 | } |
3235 | 3305 | ||
3306 | if (srp_dev->use_fast_reg || srp_dev->use_fmr) { | ||
3307 | /* | ||
3308 | * FR and FMR can only map one HCA page per entry. If the | ||
3309 | * start address is not aligned on a HCA page boundary two | ||
3310 | * entries will be used for the head and the tail although | ||
3311 | * these two entries combined contain at most one HCA page of | ||
3312 | * data. Hence the "+ 1" in the calculation below. | ||
3313 | * | ||
3314 | * The indirect data buffer descriptor is contiguous so the | ||
3315 | * memory for that buffer will only be registered if | ||
3316 | * register_always is true. Hence add one to mr_per_cmd if | ||
3317 | * register_always has been set. | ||
3318 | */ | ||
3319 | max_sectors_per_mr = srp_dev->max_pages_per_mr << | ||
3320 | (ilog2(srp_dev->mr_page_size) - 9); | ||
3321 | mr_per_cmd = register_always + | ||
3322 | (target->scsi_host->max_sectors + 1 + | ||
3323 | max_sectors_per_mr - 1) / max_sectors_per_mr; | ||
3324 | pr_debug("max_sectors = %u; max_pages_per_mr = %u; mr_page_size = %u; max_sectors_per_mr = %u; mr_per_cmd = %u\n", | ||
3325 | target->scsi_host->max_sectors, | ||
3326 | srp_dev->max_pages_per_mr, srp_dev->mr_page_size, | ||
3327 | max_sectors_per_mr, mr_per_cmd); | ||
3328 | } | ||
3329 | |||
3236 | target_host->sg_tablesize = target->sg_tablesize; | 3330 | target_host->sg_tablesize = target->sg_tablesize; |
3237 | target->mr_pool_size = target->scsi_host->can_queue; | 3331 | target->mr_pool_size = target->scsi_host->can_queue * mr_per_cmd; |
3332 | target->mr_per_cmd = mr_per_cmd; | ||
3238 | target->indirect_size = target->sg_tablesize * | 3333 | target->indirect_size = target->sg_tablesize * |
3239 | sizeof (struct srp_direct_buf); | 3334 | sizeof (struct srp_direct_buf); |
3240 | target->max_iu_len = sizeof (struct srp_cmd) + | 3335 | target->max_iu_len = sizeof (struct srp_cmd) + |
@@ -3441,6 +3536,9 @@ static void srp_add_one(struct ib_device *device) | |||
3441 | srp_dev->mr_page_mask = ~((u64) srp_dev->mr_page_size - 1); | 3536 | srp_dev->mr_page_mask = ~((u64) srp_dev->mr_page_size - 1); |
3442 | max_pages_per_mr = device->attrs.max_mr_size; | 3537 | max_pages_per_mr = device->attrs.max_mr_size; |
3443 | do_div(max_pages_per_mr, srp_dev->mr_page_size); | 3538 | do_div(max_pages_per_mr, srp_dev->mr_page_size); |
3539 | pr_debug("%s: %llu / %u = %llu <> %u\n", __func__, | ||
3540 | device->attrs.max_mr_size, srp_dev->mr_page_size, | ||
3541 | max_pages_per_mr, SRP_MAX_PAGES_PER_MR); | ||
3444 | srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR, | 3542 | srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR, |
3445 | max_pages_per_mr); | 3543 | max_pages_per_mr); |
3446 | 3544 | ||
@@ -3448,12 +3546,13 @@ static void srp_add_one(struct ib_device *device) | |||
3448 | device->map_phys_fmr && device->unmap_fmr); | 3546 | device->map_phys_fmr && device->unmap_fmr); |
3449 | srp_dev->has_fr = (device->attrs.device_cap_flags & | 3547 | srp_dev->has_fr = (device->attrs.device_cap_flags & |
3450 | IB_DEVICE_MEM_MGT_EXTENSIONS); | 3548 | IB_DEVICE_MEM_MGT_EXTENSIONS); |
3451 | if (!srp_dev->has_fmr && !srp_dev->has_fr) | 3549 | if (!srp_dev->has_fmr && !srp_dev->has_fr) { |
3452 | dev_warn(&device->dev, "neither FMR nor FR is supported\n"); | 3550 | dev_warn(&device->dev, "neither FMR nor FR is supported\n"); |
3453 | 3551 | } else if (device->attrs.max_mr_size >= 2 * srp_dev->mr_page_size) { | |
3454 | srp_dev->use_fast_reg = (srp_dev->has_fr && | 3552 | srp_dev->use_fast_reg = (srp_dev->has_fr && |
3455 | (!srp_dev->has_fmr || prefer_fr)); | 3553 | (!srp_dev->has_fmr || prefer_fr)); |
3456 | srp_dev->use_fmr = !srp_dev->use_fast_reg && srp_dev->has_fmr; | 3554 | srp_dev->use_fmr = !srp_dev->use_fast_reg && srp_dev->has_fmr; |
3555 | } | ||
3457 | 3556 | ||
3458 | if (srp_dev->use_fast_reg) { | 3557 | if (srp_dev->use_fast_reg) { |
3459 | srp_dev->max_pages_per_mr = | 3558 | srp_dev->max_pages_per_mr = |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index a00914cdd44e..26bb9b0a7a63 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h | |||
@@ -203,6 +203,7 @@ struct srp_target_port { | |||
203 | unsigned int scsi_id; | 203 | unsigned int scsi_id; |
204 | unsigned int sg_tablesize; | 204 | unsigned int sg_tablesize; |
205 | int mr_pool_size; | 205 | int mr_pool_size; |
206 | int mr_per_cmd; | ||
206 | int queue_size; | 207 | int queue_size; |
207 | int req_ring_size; | 208 | int req_ring_size; |
208 | int comp_vector; | 209 | int comp_vector; |