diff options
author | Roland Dreier <rolandd@cisco.com> | 2006-06-17 23:37:29 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-06-17 23:37:29 -0400 |
commit | f5358a172f79e3f995919224401b25637f4324f6 (patch) | |
tree | 52980f6f7707af3fca77958d04e88b9cee3c1a2a | |
parent | a26026c1221c3e78e6e9f156994c41fb74e99022 (diff) |
IB/srp: Use FMRs to map gather/scatter lists
Create an SRP FMR pool on HCAs that support FMRs, and use FMRs to map
gather/scatter lists that have more than one entry into a single
memory region that appears virtually contiguous to the SRP target
(which is the RDMA initiator).
This patch bails out on FMR mapping for SCSI commands where the
gather/scatter list cannot be mapped into a single FMR because there
are sub-page-sized entries in middle of the list. An unaligned
start or end of the list is OK.
Based on a patch by Vu Pham <vuhuong@mellanox.com>.
Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 290 | ||||
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.h | 25 |
2 files changed, 228 insertions, 87 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 9cbdffa08dc2..9c373139ee63 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -105,7 +105,8 @@ static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size, | |||
105 | if (!iu->buf) | 105 | if (!iu->buf) |
106 | goto out_free_iu; | 106 | goto out_free_iu; |
107 | 107 | ||
108 | iu->dma = dma_map_single(host->dev->dma_device, iu->buf, size, direction); | 108 | iu->dma = dma_map_single(host->dev->dev->dma_device, |
109 | iu->buf, size, direction); | ||
109 | if (dma_mapping_error(iu->dma)) | 110 | if (dma_mapping_error(iu->dma)) |
110 | goto out_free_buf; | 111 | goto out_free_buf; |
111 | 112 | ||
@@ -127,7 +128,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu) | |||
127 | if (!iu) | 128 | if (!iu) |
128 | return; | 129 | return; |
129 | 130 | ||
130 | dma_unmap_single(host->dev->dma_device, iu->dma, iu->size, iu->direction); | 131 | dma_unmap_single(host->dev->dev->dma_device, |
132 | iu->dma, iu->size, iu->direction); | ||
131 | kfree(iu->buf); | 133 | kfree(iu->buf); |
132 | kfree(iu); | 134 | kfree(iu); |
133 | } | 135 | } |
@@ -147,7 +149,7 @@ static int srp_init_qp(struct srp_target_port *target, | |||
147 | if (!attr) | 149 | if (!attr) |
148 | return -ENOMEM; | 150 | return -ENOMEM; |
149 | 151 | ||
150 | ret = ib_find_cached_pkey(target->srp_host->dev, | 152 | ret = ib_find_cached_pkey(target->srp_host->dev->dev, |
151 | target->srp_host->port, | 153 | target->srp_host->port, |
152 | be16_to_cpu(target->path.pkey), | 154 | be16_to_cpu(target->path.pkey), |
153 | &attr->pkey_index); | 155 | &attr->pkey_index); |
@@ -179,7 +181,7 @@ static int srp_create_target_ib(struct srp_target_port *target) | |||
179 | if (!init_attr) | 181 | if (!init_attr) |
180 | return -ENOMEM; | 182 | return -ENOMEM; |
181 | 183 | ||
182 | target->cq = ib_create_cq(target->srp_host->dev, srp_completion, | 184 | target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion, |
183 | NULL, target, SRP_CQ_SIZE); | 185 | NULL, target, SRP_CQ_SIZE); |
184 | if (IS_ERR(target->cq)) { | 186 | if (IS_ERR(target->cq)) { |
185 | ret = PTR_ERR(target->cq); | 187 | ret = PTR_ERR(target->cq); |
@@ -198,7 +200,7 @@ static int srp_create_target_ib(struct srp_target_port *target) | |||
198 | init_attr->send_cq = target->cq; | 200 | init_attr->send_cq = target->cq; |
199 | init_attr->recv_cq = target->cq; | 201 | init_attr->recv_cq = target->cq; |
200 | 202 | ||
201 | target->qp = ib_create_qp(target->srp_host->pd, init_attr); | 203 | target->qp = ib_create_qp(target->srp_host->dev->pd, init_attr); |
202 | if (IS_ERR(target->qp)) { | 204 | if (IS_ERR(target->qp)) { |
203 | ret = PTR_ERR(target->qp); | 205 | ret = PTR_ERR(target->qp); |
204 | ib_destroy_cq(target->cq); | 206 | ib_destroy_cq(target->cq); |
@@ -250,7 +252,7 @@ static int srp_lookup_path(struct srp_target_port *target) | |||
250 | 252 | ||
251 | init_completion(&target->done); | 253 | init_completion(&target->done); |
252 | 254 | ||
253 | target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev, | 255 | target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev->dev, |
254 | target->srp_host->port, | 256 | target->srp_host->port, |
255 | &target->path, | 257 | &target->path, |
256 | IB_SA_PATH_REC_DGID | | 258 | IB_SA_PATH_REC_DGID | |
@@ -421,6 +423,11 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, | |||
421 | scmnd->sc_data_direction != DMA_FROM_DEVICE)) | 423 | scmnd->sc_data_direction != DMA_FROM_DEVICE)) |
422 | return; | 424 | return; |
423 | 425 | ||
426 | if (req->fmr) { | ||
427 | ib_fmr_pool_unmap(req->fmr); | ||
428 | req->fmr = NULL; | ||
429 | } | ||
430 | |||
424 | /* | 431 | /* |
425 | * This handling of non-SG commands can be killed when the | 432 | * This handling of non-SG commands can be killed when the |
426 | * SCSI midlayer no longer generates non-SG commands. | 433 | * SCSI midlayer no longer generates non-SG commands. |
@@ -433,7 +440,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, | |||
433 | scat = &req->fake_sg; | 440 | scat = &req->fake_sg; |
434 | } | 441 | } |
435 | 442 | ||
436 | dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents, | 443 | dma_unmap_sg(target->srp_host->dev->dev->dma_device, scat, nents, |
437 | scmnd->sc_data_direction); | 444 | scmnd->sc_data_direction); |
438 | } | 445 | } |
439 | 446 | ||
@@ -459,7 +466,7 @@ static int srp_reconnect_target(struct srp_target_port *target) | |||
459 | * Now get a new local CM ID so that we avoid confusing the | 466 | * Now get a new local CM ID so that we avoid confusing the |
460 | * target in case things are really fouled up. | 467 | * target in case things are really fouled up. |
461 | */ | 468 | */ |
462 | new_cm_id = ib_create_cm_id(target->srp_host->dev, | 469 | new_cm_id = ib_create_cm_id(target->srp_host->dev->dev, |
463 | srp_cm_handler, target); | 470 | srp_cm_handler, target); |
464 | if (IS_ERR(new_cm_id)) { | 471 | if (IS_ERR(new_cm_id)) { |
465 | ret = PTR_ERR(new_cm_id); | 472 | ret = PTR_ERR(new_cm_id); |
@@ -528,14 +535,79 @@ err: | |||
528 | return ret; | 535 | return ret; |
529 | } | 536 | } |
530 | 537 | ||
538 | static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, | ||
539 | int sg_cnt, struct srp_request *req, | ||
540 | struct srp_direct_buf *buf) | ||
541 | { | ||
542 | u64 io_addr = 0; | ||
543 | u64 *dma_pages; | ||
544 | u32 len; | ||
545 | int page_cnt; | ||
546 | int i, j; | ||
547 | int ret; | ||
548 | |||
549 | if (!dev->fmr_pool) | ||
550 | return -ENODEV; | ||
551 | |||
552 | len = page_cnt = 0; | ||
553 | for (i = 0; i < sg_cnt; ++i) { | ||
554 | if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) { | ||
555 | if (i > 0) | ||
556 | return -EINVAL; | ||
557 | else | ||
558 | ++page_cnt; | ||
559 | } | ||
560 | if ((sg_dma_address(&scat[i]) + sg_dma_len(&scat[i])) & | ||
561 | ~dev->fmr_page_mask) { | ||
562 | if (i < sg_cnt - 1) | ||
563 | return -EINVAL; | ||
564 | else | ||
565 | ++page_cnt; | ||
566 | } | ||
567 | |||
568 | len += sg_dma_len(&scat[i]); | ||
569 | } | ||
570 | |||
571 | page_cnt += len >> dev->fmr_page_shift; | ||
572 | if (page_cnt > SRP_FMR_SIZE) | ||
573 | return -ENOMEM; | ||
574 | |||
575 | dma_pages = kmalloc(sizeof (u64) * page_cnt, GFP_ATOMIC); | ||
576 | if (!dma_pages) | ||
577 | return -ENOMEM; | ||
578 | |||
579 | page_cnt = 0; | ||
580 | for (i = 0; i < sg_cnt; ++i) | ||
581 | for (j = 0; j < sg_dma_len(&scat[i]); j += dev->fmr_page_size) | ||
582 | dma_pages[page_cnt++] = | ||
583 | (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j; | ||
584 | |||
585 | req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool, | ||
586 | dma_pages, page_cnt, &io_addr); | ||
587 | if (IS_ERR(req->fmr)) { | ||
588 | ret = PTR_ERR(req->fmr); | ||
589 | goto out; | ||
590 | } | ||
591 | |||
592 | buf->va = cpu_to_be64(sg_dma_address(&scat[0]) & ~dev->fmr_page_mask); | ||
593 | buf->key = cpu_to_be32(req->fmr->fmr->rkey); | ||
594 | buf->len = cpu_to_be32(len); | ||
595 | |||
596 | ret = 0; | ||
597 | |||
598 | out: | ||
599 | kfree(dma_pages); | ||
600 | |||
601 | return ret; | ||
602 | } | ||
603 | |||
531 | static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, | 604 | static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, |
532 | struct srp_request *req) | 605 | struct srp_request *req) |
533 | { | 606 | { |
534 | struct scatterlist *scat; | 607 | struct scatterlist *scat; |
535 | struct srp_cmd *cmd = req->cmd->buf; | 608 | struct srp_cmd *cmd = req->cmd->buf; |
536 | int len, nents, count; | 609 | int len, nents, count; |
537 | int i; | 610 | u8 fmt = SRP_DATA_DESC_DIRECT; |
538 | u8 fmt; | ||
539 | 611 | ||
540 | if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE) | 612 | if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE) |
541 | return sizeof (struct srp_cmd); | 613 | return sizeof (struct srp_cmd); |
@@ -560,53 +632,63 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, | |||
560 | sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen); | 632 | sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen); |
561 | } | 633 | } |
562 | 634 | ||
563 | count = dma_map_sg(target->srp_host->dev->dma_device, scat, nents, | 635 | count = dma_map_sg(target->srp_host->dev->dev->dma_device, |
564 | scmnd->sc_data_direction); | 636 | scat, nents, scmnd->sc_data_direction); |
637 | |||
638 | fmt = SRP_DATA_DESC_DIRECT; | ||
639 | len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf); | ||
565 | 640 | ||
566 | if (count == 1) { | 641 | if (count == 1) { |
642 | /* | ||
643 | * The midlayer only generated a single gather/scatter | ||
644 | * entry, or DMA mapping coalesced everything to a | ||
645 | * single entry. So a direct descriptor along with | ||
646 | * the DMA MR suffices. | ||
647 | */ | ||
567 | struct srp_direct_buf *buf = (void *) cmd->add_data; | 648 | struct srp_direct_buf *buf = (void *) cmd->add_data; |
568 | 649 | ||
569 | fmt = SRP_DATA_DESC_DIRECT; | ||
570 | |||
571 | buf->va = cpu_to_be64(sg_dma_address(scat)); | 650 | buf->va = cpu_to_be64(sg_dma_address(scat)); |
572 | buf->key = cpu_to_be32(target->srp_host->mr->rkey); | 651 | buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey); |
573 | buf->len = cpu_to_be32(sg_dma_len(scat)); | 652 | buf->len = cpu_to_be32(sg_dma_len(scat)); |
574 | 653 | } else if (srp_map_fmr(target->srp_host->dev, scat, count, req, | |
575 | len = sizeof (struct srp_cmd) + | 654 | (void *) cmd->add_data)) { |
576 | sizeof (struct srp_direct_buf); | 655 | /* |
577 | } else { | 656 | * FMR mapping failed, and the scatterlist has more |
657 | * than one entry. Generate an indirect memory | ||
658 | * descriptor. | ||
659 | */ | ||
578 | struct srp_indirect_buf *buf = (void *) cmd->add_data; | 660 | struct srp_indirect_buf *buf = (void *) cmd->add_data; |
579 | u32 datalen = 0; | 661 | u32 datalen = 0; |
662 | int i; | ||
580 | 663 | ||
581 | fmt = SRP_DATA_DESC_INDIRECT; | 664 | fmt = SRP_DATA_DESC_INDIRECT; |
665 | len = sizeof (struct srp_cmd) + | ||
666 | sizeof (struct srp_indirect_buf) + | ||
667 | count * sizeof (struct srp_direct_buf); | ||
668 | |||
669 | for (i = 0; i < count; ++i) { | ||
670 | buf->desc_list[i].va = | ||
671 | cpu_to_be64(sg_dma_address(&scat[i])); | ||
672 | buf->desc_list[i].key = | ||
673 | cpu_to_be32(target->srp_host->dev->mr->rkey); | ||
674 | buf->desc_list[i].len = | ||
675 | cpu_to_be32(sg_dma_len(&scat[i])); | ||
676 | datalen += sg_dma_len(&scat[i]); | ||
677 | } | ||
582 | 678 | ||
583 | if (scmnd->sc_data_direction == DMA_TO_DEVICE) | 679 | if (scmnd->sc_data_direction == DMA_TO_DEVICE) |
584 | cmd->data_out_desc_cnt = count; | 680 | cmd->data_out_desc_cnt = count; |
585 | else | 681 | else |
586 | cmd->data_in_desc_cnt = count; | 682 | cmd->data_in_desc_cnt = count; |
587 | 683 | ||
588 | buf->table_desc.va = cpu_to_be64(req->cmd->dma + | 684 | buf->table_desc.va = |
589 | sizeof *cmd + | 685 | cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf); |
590 | sizeof *buf); | ||
591 | buf->table_desc.key = | 686 | buf->table_desc.key = |
592 | cpu_to_be32(target->srp_host->mr->rkey); | 687 | cpu_to_be32(target->srp_host->dev->mr->rkey); |
593 | buf->table_desc.len = | 688 | buf->table_desc.len = |
594 | cpu_to_be32(count * sizeof (struct srp_direct_buf)); | 689 | cpu_to_be32(count * sizeof (struct srp_direct_buf)); |
595 | 690 | ||
596 | for (i = 0; i < count; ++i) { | ||
597 | buf->desc_list[i].va = cpu_to_be64(sg_dma_address(&scat[i])); | ||
598 | buf->desc_list[i].key = | ||
599 | cpu_to_be32(target->srp_host->mr->rkey); | ||
600 | buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i])); | ||
601 | |||
602 | datalen += sg_dma_len(&scat[i]); | ||
603 | } | ||
604 | |||
605 | buf->len = cpu_to_be32(datalen); | 691 | buf->len = cpu_to_be32(datalen); |
606 | |||
607 | len = sizeof (struct srp_cmd) + | ||
608 | sizeof (struct srp_indirect_buf) + | ||
609 | count * sizeof (struct srp_direct_buf); | ||
610 | } | 692 | } |
611 | 693 | ||
612 | if (scmnd->sc_data_direction == DMA_TO_DEVICE) | 694 | if (scmnd->sc_data_direction == DMA_TO_DEVICE) |
@@ -689,7 +771,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) | |||
689 | 771 | ||
690 | iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV]; | 772 | iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV]; |
691 | 773 | ||
692 | dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma, | 774 | dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma, |
693 | target->max_ti_iu_len, DMA_FROM_DEVICE); | 775 | target->max_ti_iu_len, DMA_FROM_DEVICE); |
694 | 776 | ||
695 | opcode = *(u8 *) iu->buf; | 777 | opcode = *(u8 *) iu->buf; |
@@ -726,7 +808,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) | |||
726 | break; | 808 | break; |
727 | } | 809 | } |
728 | 810 | ||
729 | dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma, | 811 | dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma, |
730 | target->max_ti_iu_len, DMA_FROM_DEVICE); | 812 | target->max_ti_iu_len, DMA_FROM_DEVICE); |
731 | } | 813 | } |
732 | 814 | ||
@@ -770,7 +852,7 @@ static int __srp_post_recv(struct srp_target_port *target) | |||
770 | 852 | ||
771 | list.addr = iu->dma; | 853 | list.addr = iu->dma; |
772 | list.length = iu->size; | 854 | list.length = iu->size; |
773 | list.lkey = target->srp_host->mr->lkey; | 855 | list.lkey = target->srp_host->dev->mr->lkey; |
774 | 856 | ||
775 | wr.next = NULL; | 857 | wr.next = NULL; |
776 | wr.sg_list = &list; | 858 | wr.sg_list = &list; |
@@ -828,7 +910,7 @@ static int __srp_post_send(struct srp_target_port *target, | |||
828 | 910 | ||
829 | list.addr = iu->dma; | 911 | list.addr = iu->dma; |
830 | list.length = len; | 912 | list.length = len; |
831 | list.lkey = target->srp_host->mr->lkey; | 913 | list.lkey = target->srp_host->dev->mr->lkey; |
832 | 914 | ||
833 | wr.next = NULL; | 915 | wr.next = NULL; |
834 | wr.wr_id = target->tx_head & SRP_SQ_SIZE; | 916 | wr.wr_id = target->tx_head & SRP_SQ_SIZE; |
@@ -870,7 +952,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, | |||
870 | if (!iu) | 952 | if (!iu) |
871 | goto err; | 953 | goto err; |
872 | 954 | ||
873 | dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma, | 955 | dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma, |
874 | SRP_MAX_IU_LEN, DMA_TO_DEVICE); | 956 | SRP_MAX_IU_LEN, DMA_TO_DEVICE); |
875 | 957 | ||
876 | req = list_entry(target->free_reqs.next, struct srp_request, list); | 958 | req = list_entry(target->free_reqs.next, struct srp_request, list); |
@@ -903,7 +985,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, | |||
903 | goto err_unmap; | 985 | goto err_unmap; |
904 | } | 986 | } |
905 | 987 | ||
906 | dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma, | 988 | dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma, |
907 | SRP_MAX_IU_LEN, DMA_TO_DEVICE); | 989 | SRP_MAX_IU_LEN, DMA_TO_DEVICE); |
908 | 990 | ||
909 | if (__srp_post_send(target, iu, len)) { | 991 | if (__srp_post_send(target, iu, len)) { |
@@ -1365,7 +1447,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) | |||
1365 | sprintf(target->target_name, "SRP.T10:%016llX", | 1447 | sprintf(target->target_name, "SRP.T10:%016llX", |
1366 | (unsigned long long) be64_to_cpu(target->id_ext)); | 1448 | (unsigned long long) be64_to_cpu(target->id_ext)); |
1367 | 1449 | ||
1368 | if (scsi_add_host(target->scsi_host, host->dev->dma_device)) | 1450 | if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device)) |
1369 | return -ENODEV; | 1451 | return -ENODEV; |
1370 | 1452 | ||
1371 | mutex_lock(&host->target_mutex); | 1453 | mutex_lock(&host->target_mutex); |
@@ -1558,7 +1640,7 @@ static ssize_t srp_create_target(struct class_device *class_dev, | |||
1558 | if (ret) | 1640 | if (ret) |
1559 | goto err; | 1641 | goto err; |
1560 | 1642 | ||
1561 | ib_get_cached_gid(host->dev, host->port, 0, &target->path.sgid); | 1643 | ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid); |
1562 | 1644 | ||
1563 | printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x " | 1645 | printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x " |
1564 | "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | 1646 | "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", |
@@ -1579,7 +1661,7 @@ static ssize_t srp_create_target(struct class_device *class_dev, | |||
1579 | if (ret) | 1661 | if (ret) |
1580 | goto err; | 1662 | goto err; |
1581 | 1663 | ||
1582 | target->cm_id = ib_create_cm_id(host->dev, srp_cm_handler, target); | 1664 | target->cm_id = ib_create_cm_id(host->dev->dev, srp_cm_handler, target); |
1583 | if (IS_ERR(target->cm_id)) { | 1665 | if (IS_ERR(target->cm_id)) { |
1584 | ret = PTR_ERR(target->cm_id); | 1666 | ret = PTR_ERR(target->cm_id); |
1585 | goto err_free; | 1667 | goto err_free; |
@@ -1619,7 +1701,7 @@ static ssize_t show_ibdev(struct class_device *class_dev, char *buf) | |||
1619 | struct srp_host *host = | 1701 | struct srp_host *host = |
1620 | container_of(class_dev, struct srp_host, class_dev); | 1702 | container_of(class_dev, struct srp_host, class_dev); |
1621 | 1703 | ||
1622 | return sprintf(buf, "%s\n", host->dev->name); | 1704 | return sprintf(buf, "%s\n", host->dev->dev->name); |
1623 | } | 1705 | } |
1624 | 1706 | ||
1625 | static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); | 1707 | static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); |
@@ -1634,7 +1716,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf) | |||
1634 | 1716 | ||
1635 | static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); | 1717 | static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); |
1636 | 1718 | ||
1637 | static struct srp_host *srp_add_port(struct ib_device *device, u8 port) | 1719 | static struct srp_host *srp_add_port(struct srp_device *device, u8 port) |
1638 | { | 1720 | { |
1639 | struct srp_host *host; | 1721 | struct srp_host *host; |
1640 | 1722 | ||
@@ -1649,26 +1731,15 @@ static struct srp_host *srp_add_port(struct ib_device *device, u8 port) | |||
1649 | host->port = port; | 1731 | host->port = port; |
1650 | 1732 | ||
1651 | host->initiator_port_id[7] = port; | 1733 | host->initiator_port_id[7] = port; |
1652 | memcpy(host->initiator_port_id + 8, &device->node_guid, 8); | 1734 | memcpy(host->initiator_port_id + 8, &device->dev->node_guid, 8); |
1653 | |||
1654 | host->pd = ib_alloc_pd(device); | ||
1655 | if (IS_ERR(host->pd)) | ||
1656 | goto err_free; | ||
1657 | |||
1658 | host->mr = ib_get_dma_mr(host->pd, | ||
1659 | IB_ACCESS_LOCAL_WRITE | | ||
1660 | IB_ACCESS_REMOTE_READ | | ||
1661 | IB_ACCESS_REMOTE_WRITE); | ||
1662 | if (IS_ERR(host->mr)) | ||
1663 | goto err_pd; | ||
1664 | 1735 | ||
1665 | host->class_dev.class = &srp_class; | 1736 | host->class_dev.class = &srp_class; |
1666 | host->class_dev.dev = device->dma_device; | 1737 | host->class_dev.dev = device->dev->dma_device; |
1667 | snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d", | 1738 | snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d", |
1668 | device->name, port); | 1739 | device->dev->name, port); |
1669 | 1740 | ||
1670 | if (class_device_register(&host->class_dev)) | 1741 | if (class_device_register(&host->class_dev)) |
1671 | goto err_mr; | 1742 | goto free_host; |
1672 | if (class_device_create_file(&host->class_dev, &class_device_attr_add_target)) | 1743 | if (class_device_create_file(&host->class_dev, &class_device_attr_add_target)) |
1673 | goto err_class; | 1744 | goto err_class; |
1674 | if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev)) | 1745 | if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev)) |
@@ -1681,13 +1752,7 @@ static struct srp_host *srp_add_port(struct ib_device *device, u8 port) | |||
1681 | err_class: | 1752 | err_class: |
1682 | class_device_unregister(&host->class_dev); | 1753 | class_device_unregister(&host->class_dev); |
1683 | 1754 | ||
1684 | err_mr: | 1755 | free_host: |
1685 | ib_dereg_mr(host->mr); | ||
1686 | |||
1687 | err_pd: | ||
1688 | ib_dealloc_pd(host->pd); | ||
1689 | |||
1690 | err_free: | ||
1691 | kfree(host); | 1756 | kfree(host); |
1692 | 1757 | ||
1693 | return NULL; | 1758 | return NULL; |
@@ -1695,15 +1760,62 @@ err_free: | |||
1695 | 1760 | ||
1696 | static void srp_add_one(struct ib_device *device) | 1761 | static void srp_add_one(struct ib_device *device) |
1697 | { | 1762 | { |
1698 | struct list_head *dev_list; | 1763 | struct srp_device *srp_dev; |
1764 | struct ib_device_attr *dev_attr; | ||
1765 | struct ib_fmr_pool_param fmr_param; | ||
1699 | struct srp_host *host; | 1766 | struct srp_host *host; |
1700 | int s, e, p; | 1767 | int s, e, p; |
1701 | 1768 | ||
1702 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); | 1769 | dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); |
1703 | if (!dev_list) | 1770 | if (!dev_attr) |
1704 | return; | 1771 | return; |
1705 | 1772 | ||
1706 | INIT_LIST_HEAD(dev_list); | 1773 | if (ib_query_device(device, dev_attr)) { |
1774 | printk(KERN_WARNING PFX "Query device failed for %s\n", | ||
1775 | device->name); | ||
1776 | goto free_attr; | ||
1777 | } | ||
1778 | |||
1779 | srp_dev = kmalloc(sizeof *srp_dev, GFP_KERNEL); | ||
1780 | if (!srp_dev) | ||
1781 | goto free_attr; | ||
1782 | |||
1783 | /* | ||
1784 | * Use the smallest page size supported by the HCA, down to a | ||
1785 | * minimum of 512 bytes (which is the smallest sector that a | ||
1786 | * SCSI command will ever carry). | ||
1787 | */ | ||
1788 | srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1); | ||
1789 | srp_dev->fmr_page_size = 1 << srp_dev->fmr_page_shift; | ||
1790 | srp_dev->fmr_page_mask = ~((unsigned long) srp_dev->fmr_page_size - 1); | ||
1791 | |||
1792 | INIT_LIST_HEAD(&srp_dev->dev_list); | ||
1793 | |||
1794 | srp_dev->dev = device; | ||
1795 | srp_dev->pd = ib_alloc_pd(device); | ||
1796 | if (IS_ERR(srp_dev->pd)) | ||
1797 | goto free_dev; | ||
1798 | |||
1799 | srp_dev->mr = ib_get_dma_mr(srp_dev->pd, | ||
1800 | IB_ACCESS_LOCAL_WRITE | | ||
1801 | IB_ACCESS_REMOTE_READ | | ||
1802 | IB_ACCESS_REMOTE_WRITE); | ||
1803 | if (IS_ERR(srp_dev->mr)) | ||
1804 | goto err_pd; | ||
1805 | |||
1806 | memset(&fmr_param, 0, sizeof fmr_param); | ||
1807 | fmr_param.pool_size = SRP_FMR_POOL_SIZE; | ||
1808 | fmr_param.dirty_watermark = SRP_FMR_DIRTY_SIZE; | ||
1809 | fmr_param.cache = 1; | ||
1810 | fmr_param.max_pages_per_fmr = SRP_FMR_SIZE; | ||
1811 | fmr_param.page_shift = srp_dev->fmr_page_shift; | ||
1812 | fmr_param.access = (IB_ACCESS_LOCAL_WRITE | | ||
1813 | IB_ACCESS_REMOTE_WRITE | | ||
1814 | IB_ACCESS_REMOTE_READ); | ||
1815 | |||
1816 | srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param); | ||
1817 | if (IS_ERR(srp_dev->fmr_pool)) | ||
1818 | srp_dev->fmr_pool = NULL; | ||
1707 | 1819 | ||
1708 | if (device->node_type == IB_NODE_SWITCH) { | 1820 | if (device->node_type == IB_NODE_SWITCH) { |
1709 | s = 0; | 1821 | s = 0; |
@@ -1714,25 +1826,36 @@ static void srp_add_one(struct ib_device *device) | |||
1714 | } | 1826 | } |
1715 | 1827 | ||
1716 | for (p = s; p <= e; ++p) { | 1828 | for (p = s; p <= e; ++p) { |
1717 | host = srp_add_port(device, p); | 1829 | host = srp_add_port(srp_dev, p); |
1718 | if (host) | 1830 | if (host) |
1719 | list_add_tail(&host->list, dev_list); | 1831 | list_add_tail(&host->list, &srp_dev->dev_list); |
1720 | } | 1832 | } |
1721 | 1833 | ||
1722 | ib_set_client_data(device, &srp_client, dev_list); | 1834 | ib_set_client_data(device, &srp_client, srp_dev); |
1835 | |||
1836 | goto free_attr; | ||
1837 | |||
1838 | err_pd: | ||
1839 | ib_dealloc_pd(srp_dev->pd); | ||
1840 | |||
1841 | free_dev: | ||
1842 | kfree(srp_dev); | ||
1843 | |||
1844 | free_attr: | ||
1845 | kfree(dev_attr); | ||
1723 | } | 1846 | } |
1724 | 1847 | ||
1725 | static void srp_remove_one(struct ib_device *device) | 1848 | static void srp_remove_one(struct ib_device *device) |
1726 | { | 1849 | { |
1727 | struct list_head *dev_list; | 1850 | struct srp_device *srp_dev; |
1728 | struct srp_host *host, *tmp_host; | 1851 | struct srp_host *host, *tmp_host; |
1729 | LIST_HEAD(target_list); | 1852 | LIST_HEAD(target_list); |
1730 | struct srp_target_port *target, *tmp_target; | 1853 | struct srp_target_port *target, *tmp_target; |
1731 | unsigned long flags; | 1854 | unsigned long flags; |
1732 | 1855 | ||
1733 | dev_list = ib_get_client_data(device, &srp_client); | 1856 | srp_dev = ib_get_client_data(device, &srp_client); |
1734 | 1857 | ||
1735 | list_for_each_entry_safe(host, tmp_host, dev_list, list) { | 1858 | list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) { |
1736 | class_device_unregister(&host->class_dev); | 1859 | class_device_unregister(&host->class_dev); |
1737 | /* | 1860 | /* |
1738 | * Wait for the sysfs entry to go away, so that no new | 1861 | * Wait for the sysfs entry to go away, so that no new |
@@ -1770,12 +1893,15 @@ static void srp_remove_one(struct ib_device *device) | |||
1770 | scsi_host_put(target->scsi_host); | 1893 | scsi_host_put(target->scsi_host); |
1771 | } | 1894 | } |
1772 | 1895 | ||
1773 | ib_dereg_mr(host->mr); | ||
1774 | ib_dealloc_pd(host->pd); | ||
1775 | kfree(host); | 1896 | kfree(host); |
1776 | } | 1897 | } |
1777 | 1898 | ||
1778 | kfree(dev_list); | 1899 | if (srp_dev->fmr_pool) |
1900 | ib_destroy_fmr_pool(srp_dev->fmr_pool); | ||
1901 | ib_dereg_mr(srp_dev->mr); | ||
1902 | ib_dealloc_pd(srp_dev->pd); | ||
1903 | |||
1904 | kfree(srp_dev); | ||
1779 | } | 1905 | } |
1780 | 1906 | ||
1781 | static int __init srp_init_module(void) | 1907 | static int __init srp_init_module(void) |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index c5cd43aae860..5ecda4ad8906 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <rdma/ib_verbs.h> | 46 | #include <rdma/ib_verbs.h> |
47 | #include <rdma/ib_sa.h> | 47 | #include <rdma/ib_sa.h> |
48 | #include <rdma/ib_cm.h> | 48 | #include <rdma/ib_cm.h> |
49 | #include <rdma/ib_fmr_pool.h> | ||
49 | 50 | ||
50 | enum { | 51 | enum { |
51 | SRP_PATH_REC_TIMEOUT_MS = 1000, | 52 | SRP_PATH_REC_TIMEOUT_MS = 1000, |
@@ -62,7 +63,11 @@ enum { | |||
62 | SRP_SQ_SIZE = SRP_RQ_SIZE - 1, | 63 | SRP_SQ_SIZE = SRP_RQ_SIZE - 1, |
63 | SRP_CQ_SIZE = SRP_SQ_SIZE + SRP_RQ_SIZE, | 64 | SRP_CQ_SIZE = SRP_SQ_SIZE + SRP_RQ_SIZE, |
64 | 65 | ||
65 | SRP_TAG_TSK_MGMT = 1 << (SRP_RQ_SHIFT + 1) | 66 | SRP_TAG_TSK_MGMT = 1 << (SRP_RQ_SHIFT + 1), |
67 | |||
68 | SRP_FMR_SIZE = 256, | ||
69 | SRP_FMR_POOL_SIZE = 1024, | ||
70 | SRP_FMR_DIRTY_SIZE = SRP_FMR_POOL_SIZE / 4 | ||
66 | }; | 71 | }; |
67 | 72 | ||
68 | #define SRP_OP_RECV (1 << 31) | 73 | #define SRP_OP_RECV (1 << 31) |
@@ -77,15 +82,24 @@ enum srp_target_state { | |||
77 | SRP_TARGET_REMOVED | 82 | SRP_TARGET_REMOVED |
78 | }; | 83 | }; |
79 | 84 | ||
80 | struct srp_host { | 85 | struct srp_device { |
81 | u8 initiator_port_id[16]; | 86 | struct list_head dev_list; |
82 | struct ib_device *dev; | 87 | struct ib_device *dev; |
83 | u8 port; | ||
84 | struct ib_pd *pd; | 88 | struct ib_pd *pd; |
85 | struct ib_mr *mr; | 89 | struct ib_mr *mr; |
90 | struct ib_fmr_pool *fmr_pool; | ||
91 | int fmr_page_shift; | ||
92 | int fmr_page_size; | ||
93 | unsigned long fmr_page_mask; | ||
94 | }; | ||
95 | |||
96 | struct srp_host { | ||
97 | u8 initiator_port_id[16]; | ||
98 | struct srp_device *dev; | ||
99 | u8 port; | ||
86 | struct class_device class_dev; | 100 | struct class_device class_dev; |
87 | struct list_head target_list; | 101 | struct list_head target_list; |
88 | struct mutex target_mutex; | 102 | struct mutex target_mutex; |
89 | struct completion released; | 103 | struct completion released; |
90 | struct list_head list; | 104 | struct list_head list; |
91 | }; | 105 | }; |
@@ -95,6 +109,7 @@ struct srp_request { | |||
95 | struct scsi_cmnd *scmnd; | 109 | struct scsi_cmnd *scmnd; |
96 | struct srp_iu *cmd; | 110 | struct srp_iu *cmd; |
97 | struct srp_iu *tsk_mgmt; | 111 | struct srp_iu *tsk_mgmt; |
112 | struct ib_pool_fmr *fmr; | ||
98 | /* | 113 | /* |
99 | * Fake scatterlist used when scmnd->use_sg==0. Can be killed | 114 | * Fake scatterlist used when scmnd->use_sg==0. Can be killed |
100 | * when the SCSI midlayer no longer generates non-SG commands. | 115 | * when the SCSI midlayer no longer generates non-SG commands. |