diff options
| -rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 129 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.h | 7 |
2 files changed, 84 insertions, 52 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 77ba96553b27..80dfe173deac 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
| @@ -293,12 +293,31 @@ static int srp_new_cm_id(struct srp_target_port *target) | |||
| 293 | return 0; | 293 | return 0; |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | static struct ib_fmr_pool *srp_alloc_fmr_pool(struct srp_target_port *target) | ||
| 297 | { | ||
| 298 | struct srp_device *dev = target->srp_host->srp_dev; | ||
| 299 | struct ib_fmr_pool_param fmr_param; | ||
| 300 | |||
| 301 | memset(&fmr_param, 0, sizeof(fmr_param)); | ||
| 302 | fmr_param.pool_size = target->scsi_host->can_queue; | ||
| 303 | fmr_param.dirty_watermark = fmr_param.pool_size / 4; | ||
| 304 | fmr_param.cache = 1; | ||
| 305 | fmr_param.max_pages_per_fmr = dev->max_pages_per_fmr; | ||
| 306 | fmr_param.page_shift = ilog2(dev->fmr_page_size); | ||
| 307 | fmr_param.access = (IB_ACCESS_LOCAL_WRITE | | ||
| 308 | IB_ACCESS_REMOTE_WRITE | | ||
| 309 | IB_ACCESS_REMOTE_READ); | ||
| 310 | |||
| 311 | return ib_create_fmr_pool(dev->pd, &fmr_param); | ||
| 312 | } | ||
| 313 | |||
| 296 | static int srp_create_target_ib(struct srp_target_port *target) | 314 | static int srp_create_target_ib(struct srp_target_port *target) |
| 297 | { | 315 | { |
| 298 | struct srp_device *dev = target->srp_host->srp_dev; | 316 | struct srp_device *dev = target->srp_host->srp_dev; |
| 299 | struct ib_qp_init_attr *init_attr; | 317 | struct ib_qp_init_attr *init_attr; |
| 300 | struct ib_cq *recv_cq, *send_cq; | 318 | struct ib_cq *recv_cq, *send_cq; |
| 301 | struct ib_qp *qp; | 319 | struct ib_qp *qp; |
| 320 | struct ib_fmr_pool *fmr_pool = NULL; | ||
| 302 | int ret; | 321 | int ret; |
| 303 | 322 | ||
| 304 | init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); | 323 | init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); |
| @@ -341,6 +360,19 @@ static int srp_create_target_ib(struct srp_target_port *target) | |||
| 341 | if (ret) | 360 | if (ret) |
| 342 | goto err_qp; | 361 | goto err_qp; |
| 343 | 362 | ||
| 363 | if (dev->has_fmr) { | ||
| 364 | fmr_pool = srp_alloc_fmr_pool(target); | ||
| 365 | if (IS_ERR(fmr_pool)) { | ||
| 366 | ret = PTR_ERR(fmr_pool); | ||
| 367 | shost_printk(KERN_WARNING, target->scsi_host, PFX | ||
| 368 | "FMR pool allocation failed (%d)\n", ret); | ||
| 369 | goto err_qp; | ||
| 370 | } | ||
| 371 | if (target->fmr_pool) | ||
| 372 | ib_destroy_fmr_pool(target->fmr_pool); | ||
| 373 | target->fmr_pool = fmr_pool; | ||
| 374 | } | ||
| 375 | |||
| 344 | if (target->qp) | 376 | if (target->qp) |
| 345 | ib_destroy_qp(target->qp); | 377 | ib_destroy_qp(target->qp); |
| 346 | if (target->recv_cq) | 378 | if (target->recv_cq) |
| @@ -377,6 +409,8 @@ static void srp_free_target_ib(struct srp_target_port *target) | |||
| 377 | { | 409 | { |
| 378 | int i; | 410 | int i; |
| 379 | 411 | ||
| 412 | if (target->fmr_pool) | ||
| 413 | ib_destroy_fmr_pool(target->fmr_pool); | ||
| 380 | ib_destroy_qp(target->qp); | 414 | ib_destroy_qp(target->qp); |
| 381 | ib_destroy_cq(target->send_cq); | 415 | ib_destroy_cq(target->send_cq); |
| 382 | ib_destroy_cq(target->recv_cq); | 416 | ib_destroy_cq(target->recv_cq); |
| @@ -623,8 +657,8 @@ static int srp_alloc_req_data(struct srp_target_port *target) | |||
| 623 | req = &target->req_ring[i]; | 657 | req = &target->req_ring[i]; |
| 624 | req->fmr_list = kmalloc(target->cmd_sg_cnt * sizeof(void *), | 658 | req->fmr_list = kmalloc(target->cmd_sg_cnt * sizeof(void *), |
| 625 | GFP_KERNEL); | 659 | GFP_KERNEL); |
| 626 | req->map_page = kmalloc(SRP_FMR_SIZE * sizeof(void *), | 660 | req->map_page = kmalloc(srp_dev->max_pages_per_fmr * |
| 627 | GFP_KERNEL); | 661 | sizeof(void *), GFP_KERNEL); |
| 628 | req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL); | 662 | req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL); |
| 629 | if (!req->fmr_list || !req->map_page || !req->indirect_desc) | 663 | if (!req->fmr_list || !req->map_page || !req->indirect_desc) |
| 630 | goto out; | 664 | goto out; |
| @@ -936,11 +970,10 @@ static void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr, | |||
| 936 | static int srp_map_finish_fmr(struct srp_map_state *state, | 970 | static int srp_map_finish_fmr(struct srp_map_state *state, |
| 937 | struct srp_target_port *target) | 971 | struct srp_target_port *target) |
| 938 | { | 972 | { |
| 939 | struct srp_device *dev = target->srp_host->srp_dev; | ||
| 940 | struct ib_pool_fmr *fmr; | 973 | struct ib_pool_fmr *fmr; |
| 941 | u64 io_addr = 0; | 974 | u64 io_addr = 0; |
| 942 | 975 | ||
| 943 | fmr = ib_fmr_pool_map_phys(dev->fmr_pool, state->pages, | 976 | fmr = ib_fmr_pool_map_phys(target->fmr_pool, state->pages, |
| 944 | state->npages, io_addr); | 977 | state->npages, io_addr); |
| 945 | if (IS_ERR(fmr)) | 978 | if (IS_ERR(fmr)) |
| 946 | return PTR_ERR(fmr); | 979 | return PTR_ERR(fmr); |
| @@ -1033,7 +1066,7 @@ static int srp_map_sg_entry(struct srp_map_state *state, | |||
| 1033 | srp_map_update_start(state, sg, sg_index, dma_addr); | 1066 | srp_map_update_start(state, sg, sg_index, dma_addr); |
| 1034 | 1067 | ||
| 1035 | while (dma_len) { | 1068 | while (dma_len) { |
| 1036 | if (state->npages == SRP_FMR_SIZE) { | 1069 | if (state->npages == dev->max_pages_per_fmr) { |
| 1037 | ret = srp_finish_mapping(state, target); | 1070 | ret = srp_finish_mapping(state, target); |
| 1038 | if (ret) | 1071 | if (ret) |
| 1039 | return ret; | 1072 | return ret; |
| @@ -1077,7 +1110,7 @@ static void srp_map_fmr(struct srp_map_state *state, | |||
| 1077 | state->pages = req->map_page; | 1110 | state->pages = req->map_page; |
| 1078 | state->next_fmr = req->fmr_list; | 1111 | state->next_fmr = req->fmr_list; |
| 1079 | 1112 | ||
| 1080 | use_fmr = dev->fmr_pool ? SRP_MAP_ALLOW_FMR : SRP_MAP_NO_FMR; | 1113 | use_fmr = target->fmr_pool ? SRP_MAP_ALLOW_FMR : SRP_MAP_NO_FMR; |
| 1081 | 1114 | ||
| 1082 | for_each_sg(scat, sg, count, i) { | 1115 | for_each_sg(scat, sg, count, i) { |
| 1083 | if (srp_map_sg_entry(state, target, sg, i, use_fmr)) { | 1116 | if (srp_map_sg_entry(state, target, sg, i, use_fmr)) { |
| @@ -1555,7 +1588,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | |||
| 1555 | struct srp_cmd *cmd; | 1588 | struct srp_cmd *cmd; |
| 1556 | struct ib_device *dev; | 1589 | struct ib_device *dev; |
| 1557 | unsigned long flags; | 1590 | unsigned long flags; |
| 1558 | int len, result; | 1591 | int len, ret; |
| 1559 | const bool in_scsi_eh = !in_interrupt() && current == shost->ehandler; | 1592 | const bool in_scsi_eh = !in_interrupt() && current == shost->ehandler; |
| 1560 | 1593 | ||
| 1561 | /* | 1594 | /* |
| @@ -1567,12 +1600,9 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | |||
| 1567 | if (in_scsi_eh) | 1600 | if (in_scsi_eh) |
| 1568 | mutex_lock(&rport->mutex); | 1601 | mutex_lock(&rport->mutex); |
| 1569 | 1602 | ||
| 1570 | result = srp_chkready(target->rport); | 1603 | scmnd->result = srp_chkready(target->rport); |
| 1571 | if (unlikely(result)) { | 1604 | if (unlikely(scmnd->result)) |
| 1572 | scmnd->result = result; | 1605 | goto err; |
| 1573 | scmnd->scsi_done(scmnd); | ||
| 1574 | goto unlock_rport; | ||
| 1575 | } | ||
| 1576 | 1606 | ||
| 1577 | spin_lock_irqsave(&target->lock, flags); | 1607 | spin_lock_irqsave(&target->lock, flags); |
| 1578 | iu = __srp_get_tx_iu(target, SRP_IU_CMD); | 1608 | iu = __srp_get_tx_iu(target, SRP_IU_CMD); |
| @@ -1587,7 +1617,6 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | |||
| 1587 | ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_iu_len, | 1617 | ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_iu_len, |
| 1588 | DMA_TO_DEVICE); | 1618 | DMA_TO_DEVICE); |
| 1589 | 1619 | ||
| 1590 | scmnd->result = 0; | ||
| 1591 | scmnd->host_scribble = (void *) req; | 1620 | scmnd->host_scribble = (void *) req; |
| 1592 | 1621 | ||
| 1593 | cmd = iu->buf; | 1622 | cmd = iu->buf; |
| @@ -1604,7 +1633,15 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | |||
| 1604 | len = srp_map_data(scmnd, target, req); | 1633 | len = srp_map_data(scmnd, target, req); |
| 1605 | if (len < 0) { | 1634 | if (len < 0) { |
| 1606 | shost_printk(KERN_ERR, target->scsi_host, | 1635 | shost_printk(KERN_ERR, target->scsi_host, |
| 1607 | PFX "Failed to map data\n"); | 1636 | PFX "Failed to map data (%d)\n", len); |
| 1637 | /* | ||
| 1638 | * If we ran out of memory descriptors (-ENOMEM) because an | ||
| 1639 | * application is queuing many requests with more than | ||
| 1640 | * max_pages_per_fmr sg-list elements, tell the SCSI mid-layer | ||
| 1641 | * to reduce queue depth temporarily. | ||
| 1642 | */ | ||
| 1643 | scmnd->result = len == -ENOMEM ? | ||
| 1644 | DID_OK << 16 | QUEUE_FULL << 1 : DID_ERROR << 16; | ||
| 1608 | goto err_iu; | 1645 | goto err_iu; |
| 1609 | } | 1646 | } |
| 1610 | |||
