| .. | .. |
|---|
| 51 | 51 | |
|---|
| 52 | 52 | /* Name of this kernel module. */ |
|---|
| 53 | 53 | #define DRV_NAME "ib_srpt" |
|---|
| 54 | | -#define DRV_VERSION "2.0.0" |
|---|
| 55 | | -#define DRV_RELDATE "2011-02-14" |
|---|
| 56 | 54 | |
|---|
| 57 | 55 | #define SRPT_ID_STRING "Linux SRP target" |
|---|
| 58 | 56 | |
|---|
| .. | .. |
|---|
| 60 | 58 | #define pr_fmt(fmt) DRV_NAME " " fmt |
|---|
| 61 | 59 | |
|---|
| 62 | 60 | MODULE_AUTHOR("Vu Pham and Bart Van Assche"); |
|---|
| 63 | | -MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol target " |
|---|
| 64 | | - "v" DRV_VERSION " (" DRV_RELDATE ")"); |
|---|
| 61 | +MODULE_DESCRIPTION("SCSI RDMA Protocol target driver"); |
|---|
| 65 | 62 | MODULE_LICENSE("Dual BSD/GPL"); |
|---|
| 66 | 63 | |
|---|
| 67 | 64 | /* |
|---|
| .. | .. |
|---|
| 84 | 81 | |
|---|
| 85 | 82 | static int srpt_get_u64_x(char *buffer, const struct kernel_param *kp) |
|---|
| 86 | 83 | { |
|---|
| 87 | | - return sprintf(buffer, "0x%016llx", *(u64 *)kp->arg); |
|---|
| 84 | + return sprintf(buffer, "0x%016llx\n", *(u64 *)kp->arg); |
|---|
| 88 | 85 | } |
|---|
| 89 | 86 | module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid, |
|---|
| 90 | 87 | 0444); |
|---|
| 91 | 88 | MODULE_PARM_DESC(srpt_service_guid, |
|---|
| 92 | | - "Using this value for ioc_guid, id_ext, and cm_listen_id" |
|---|
| 93 | | - " instead of using the node_guid of the first HCA."); |
|---|
| 89 | + "Using this value for ioc_guid, id_ext, and cm_listen_id instead of using the node_guid of the first HCA."); |
|---|
| 94 | 90 | |
|---|
| 95 | 91 | static struct ib_client srpt_client; |
|---|
| 96 | 92 | /* Protects both rdma_cm_port and rdma_cm_id. */ |
|---|
| .. | .. |
|---|
| 139 | 135 | static void srpt_event_handler(struct ib_event_handler *handler, |
|---|
| 140 | 136 | struct ib_event *event) |
|---|
| 141 | 137 | { |
|---|
| 142 | | - struct srpt_device *sdev; |
|---|
| 138 | + struct srpt_device *sdev = |
|---|
| 139 | + container_of(handler, struct srpt_device, event_handler); |
|---|
| 143 | 140 | struct srpt_port *sport; |
|---|
| 144 | 141 | u8 port_num; |
|---|
| 145 | 142 | |
|---|
| 146 | | - sdev = ib_get_client_data(event->device, &srpt_client); |
|---|
| 147 | | - if (!sdev || sdev->device != event->device) |
|---|
| 148 | | - return; |
|---|
| 149 | | - |
|---|
| 150 | 143 | pr_debug("ASYNC event= %d on device= %s\n", event->event, |
|---|
| 151 | | - sdev->device->name); |
|---|
| 144 | + dev_name(&sdev->device->dev)); |
|---|
| 152 | 145 | |
|---|
| 153 | 146 | switch (event->event) { |
|---|
| 154 | 147 | case IB_EVENT_PORT_ERR: |
|---|
| .. | .. |
|---|
| 221 | 214 | */ |
|---|
| 222 | 215 | static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch) |
|---|
| 223 | 216 | { |
|---|
| 224 | | - pr_debug("QP event %d on ch=%p sess_name=%s state=%d\n", |
|---|
| 225 | | - event->event, ch, ch->sess_name, ch->state); |
|---|
| 217 | + pr_debug("QP event %d on ch=%p sess_name=%s-%d state=%s\n", |
|---|
| 218 | + event->event, ch, ch->sess_name, ch->qp->qp_num, |
|---|
| 219 | + get_ch_state_name(ch->state)); |
|---|
| 226 | 220 | |
|---|
| 227 | 221 | switch (event->event) { |
|---|
| 228 | 222 | case IB_EVENT_COMM_EST: |
|---|
| .. | .. |
|---|
| 462 | 456 | static void srpt_mad_send_handler(struct ib_mad_agent *mad_agent, |
|---|
| 463 | 457 | struct ib_mad_send_wc *mad_wc) |
|---|
| 464 | 458 | { |
|---|
| 465 | | - rdma_destroy_ah(mad_wc->send_buf->ah); |
|---|
| 459 | + rdma_destroy_ah(mad_wc->send_buf->ah, RDMA_DESTROY_AH_SLEEPABLE); |
|---|
| 466 | 460 | ib_free_send_mad(mad_wc->send_buf); |
|---|
| 467 | 461 | } |
|---|
| 468 | 462 | |
|---|
| .. | .. |
|---|
| 529 | 523 | ib_free_send_mad(rsp); |
|---|
| 530 | 524 | |
|---|
| 531 | 525 | err_rsp: |
|---|
| 532 | | - rdma_destroy_ah(ah); |
|---|
| 526 | + rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE); |
|---|
| 533 | 527 | err: |
|---|
| 534 | 528 | ib_free_recv_mad(mad_wc); |
|---|
| 535 | 529 | } |
|---|
| .. | .. |
|---|
| 560 | 554 | struct ib_port_attr port_attr; |
|---|
| 561 | 555 | int ret; |
|---|
| 562 | 556 | |
|---|
| 563 | | - memset(&port_modify, 0, sizeof(port_modify)); |
|---|
| 564 | | - port_modify.set_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP; |
|---|
| 565 | | - port_modify.clr_port_cap_mask = 0; |
|---|
| 566 | | - |
|---|
| 567 | | - ret = ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify); |
|---|
| 568 | | - if (ret) |
|---|
| 569 | | - goto err_mod_port; |
|---|
| 570 | | - |
|---|
| 571 | 557 | ret = ib_query_port(sport->sdev->device, sport->port, &port_attr); |
|---|
| 572 | 558 | if (ret) |
|---|
| 573 | | - goto err_query_port; |
|---|
| 559 | + return ret; |
|---|
| 574 | 560 | |
|---|
| 575 | 561 | sport->sm_lid = port_attr.sm_lid; |
|---|
| 576 | 562 | sport->lid = port_attr.lid; |
|---|
| 577 | 563 | |
|---|
| 578 | 564 | ret = rdma_query_gid(sport->sdev->device, sport->port, 0, &sport->gid); |
|---|
| 579 | 565 | if (ret) |
|---|
| 580 | | - goto err_query_port; |
|---|
| 566 | + return ret; |
|---|
| 581 | 567 | |
|---|
| 582 | | - sport->port_guid_wwn.priv = sport; |
|---|
| 583 | | - srpt_format_guid(sport->port_guid, sizeof(sport->port_guid), |
|---|
| 568 | + srpt_format_guid(sport->guid_name, ARRAY_SIZE(sport->guid_name), |
|---|
| 584 | 569 | &sport->gid.global.interface_id); |
|---|
| 585 | | - sport->port_gid_wwn.priv = sport; |
|---|
| 586 | | - snprintf(sport->port_gid, sizeof(sport->port_gid), |
|---|
| 570 | + snprintf(sport->gid_name, ARRAY_SIZE(sport->gid_name), |
|---|
| 587 | 571 | "0x%016llx%016llx", |
|---|
| 588 | 572 | be64_to_cpu(sport->gid.global.subnet_prefix), |
|---|
| 589 | 573 | be64_to_cpu(sport->gid.global.interface_id)); |
|---|
| 574 | + |
|---|
| 575 | + if (rdma_protocol_iwarp(sport->sdev->device, sport->port)) |
|---|
| 576 | + return 0; |
|---|
| 577 | + |
|---|
| 578 | + memset(&port_modify, 0, sizeof(port_modify)); |
|---|
| 579 | + port_modify.set_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP; |
|---|
| 580 | + port_modify.clr_port_cap_mask = 0; |
|---|
| 581 | + |
|---|
| 582 | + ret = ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify); |
|---|
| 583 | + if (ret) { |
|---|
| 584 | + pr_warn("%s-%d: enabling device management failed (%d). Note: this is expected if SR-IOV is enabled.\n", |
|---|
| 585 | + dev_name(&sport->sdev->device->dev), sport->port, ret); |
|---|
| 586 | + return 0; |
|---|
| 587 | + } |
|---|
| 590 | 588 | |
|---|
| 591 | 589 | if (!sport->mad_agent) { |
|---|
| 592 | 590 | memset(®_req, 0, sizeof(reg_req)); |
|---|
| .. | .. |
|---|
| 603 | 601 | srpt_mad_recv_handler, |
|---|
| 604 | 602 | sport, 0); |
|---|
| 605 | 603 | if (IS_ERR(sport->mad_agent)) { |
|---|
| 606 | | - ret = PTR_ERR(sport->mad_agent); |
|---|
| 604 | + pr_err("%s-%d: MAD agent registration failed (%ld). Note: this is expected if SR-IOV is enabled.\n", |
|---|
| 605 | + dev_name(&sport->sdev->device->dev), sport->port, |
|---|
| 606 | + PTR_ERR(sport->mad_agent)); |
|---|
| 607 | 607 | sport->mad_agent = NULL; |
|---|
| 608 | | - goto err_query_port; |
|---|
| 608 | + memset(&port_modify, 0, sizeof(port_modify)); |
|---|
| 609 | + port_modify.clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP; |
|---|
| 610 | + ib_modify_port(sport->sdev->device, sport->port, 0, |
|---|
| 611 | + &port_modify); |
|---|
| 612 | + |
|---|
| 609 | 613 | } |
|---|
| 610 | 614 | } |
|---|
| 611 | 615 | |
|---|
| 612 | 616 | return 0; |
|---|
| 613 | | - |
|---|
| 614 | | -err_query_port: |
|---|
| 615 | | - |
|---|
| 616 | | - port_modify.set_port_cap_mask = 0; |
|---|
| 617 | | - port_modify.clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP; |
|---|
| 618 | | - ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify); |
|---|
| 619 | | - |
|---|
| 620 | | -err_mod_port: |
|---|
| 621 | | - |
|---|
| 622 | | - return ret; |
|---|
| 623 | 617 | } |
|---|
| 624 | 618 | |
|---|
| 625 | 619 | /** |
|---|
| 626 | 620 | * srpt_unregister_mad_agent - unregister MAD callback functions |
|---|
| 627 | 621 | * @sdev: SRPT HCA pointer. |
|---|
| 622 | + * @port_cnt: number of ports with registered MAD |
|---|
| 628 | 623 | * |
|---|
| 629 | 624 | * Note: It is safe to call this function more than once for the same device. |
|---|
| 630 | 625 | */ |
|---|
| 631 | | -static void srpt_unregister_mad_agent(struct srpt_device *sdev) |
|---|
| 626 | +static void srpt_unregister_mad_agent(struct srpt_device *sdev, int port_cnt) |
|---|
| 632 | 627 | { |
|---|
| 633 | 628 | struct ib_port_modify port_modify = { |
|---|
| 634 | 629 | .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP, |
|---|
| .. | .. |
|---|
| 636 | 631 | struct srpt_port *sport; |
|---|
| 637 | 632 | int i; |
|---|
| 638 | 633 | |
|---|
| 639 | | - for (i = 1; i <= sdev->device->phys_port_cnt; i++) { |
|---|
| 634 | + for (i = 1; i <= port_cnt; i++) { |
|---|
| 640 | 635 | sport = &sdev->port[i - 1]; |
|---|
| 641 | 636 | WARN_ON(sport->port != i); |
|---|
| 642 | | - if (ib_modify_port(sdev->device, i, 0, &port_modify) < 0) |
|---|
| 643 | | - pr_err("disabling MAD processing failed.\n"); |
|---|
| 644 | 637 | if (sport->mad_agent) { |
|---|
| 638 | + ib_modify_port(sdev->device, i, 0, &port_modify); |
|---|
| 645 | 639 | ib_unregister_mad_agent(sport->mad_agent); |
|---|
| 646 | 640 | sport->mad_agent = NULL; |
|---|
| 647 | 641 | } |
|---|
| .. | .. |
|---|
| 652 | 646 | * srpt_alloc_ioctx - allocate a SRPT I/O context structure |
|---|
| 653 | 647 | * @sdev: SRPT HCA pointer. |
|---|
| 654 | 648 | * @ioctx_size: I/O context size. |
|---|
| 655 | | - * @dma_size: Size of I/O context DMA buffer. |
|---|
| 649 | + * @buf_cache: I/O buffer cache. |
|---|
| 656 | 650 | * @dir: DMA data direction. |
|---|
| 657 | 651 | */ |
|---|
| 658 | 652 | static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev, |
|---|
| 659 | | - int ioctx_size, int dma_size, |
|---|
| 653 | + int ioctx_size, |
|---|
| 654 | + struct kmem_cache *buf_cache, |
|---|
| 660 | 655 | enum dma_data_direction dir) |
|---|
| 661 | 656 | { |
|---|
| 662 | 657 | struct srpt_ioctx *ioctx; |
|---|
| 663 | 658 | |
|---|
| 664 | | - ioctx = kmalloc(ioctx_size, GFP_KERNEL); |
|---|
| 659 | + ioctx = kzalloc(ioctx_size, GFP_KERNEL); |
|---|
| 665 | 660 | if (!ioctx) |
|---|
| 666 | 661 | goto err; |
|---|
| 667 | 662 | |
|---|
| 668 | | - ioctx->buf = kmalloc(dma_size, GFP_KERNEL); |
|---|
| 663 | + ioctx->buf = kmem_cache_alloc(buf_cache, GFP_KERNEL); |
|---|
| 669 | 664 | if (!ioctx->buf) |
|---|
| 670 | 665 | goto err_free_ioctx; |
|---|
| 671 | 666 | |
|---|
| 672 | | - ioctx->dma = ib_dma_map_single(sdev->device, ioctx->buf, dma_size, dir); |
|---|
| 667 | + ioctx->dma = ib_dma_map_single(sdev->device, ioctx->buf, |
|---|
| 668 | + kmem_cache_size(buf_cache), dir); |
|---|
| 673 | 669 | if (ib_dma_mapping_error(sdev->device, ioctx->dma)) |
|---|
| 674 | 670 | goto err_free_buf; |
|---|
| 675 | 671 | |
|---|
| 676 | 672 | return ioctx; |
|---|
| 677 | 673 | |
|---|
| 678 | 674 | err_free_buf: |
|---|
| 679 | | - kfree(ioctx->buf); |
|---|
| 675 | + kmem_cache_free(buf_cache, ioctx->buf); |
|---|
| 680 | 676 | err_free_ioctx: |
|---|
| 681 | 677 | kfree(ioctx); |
|---|
| 682 | 678 | err: |
|---|
| .. | .. |
|---|
| 687 | 683 | * srpt_free_ioctx - free a SRPT I/O context structure |
|---|
| 688 | 684 | * @sdev: SRPT HCA pointer. |
|---|
| 689 | 685 | * @ioctx: I/O context pointer. |
|---|
| 690 | | - * @dma_size: Size of I/O context DMA buffer. |
|---|
| 686 | + * @buf_cache: I/O buffer cache. |
|---|
| 691 | 687 | * @dir: DMA data direction. |
|---|
| 692 | 688 | */ |
|---|
| 693 | 689 | static void srpt_free_ioctx(struct srpt_device *sdev, struct srpt_ioctx *ioctx, |
|---|
| 694 | | - int dma_size, enum dma_data_direction dir) |
|---|
| 690 | + struct kmem_cache *buf_cache, |
|---|
| 691 | + enum dma_data_direction dir) |
|---|
| 695 | 692 | { |
|---|
| 696 | 693 | if (!ioctx) |
|---|
| 697 | 694 | return; |
|---|
| 698 | 695 | |
|---|
| 699 | | - ib_dma_unmap_single(sdev->device, ioctx->dma, dma_size, dir); |
|---|
| 700 | | - kfree(ioctx->buf); |
|---|
| 696 | + ib_dma_unmap_single(sdev->device, ioctx->dma, |
|---|
| 697 | + kmem_cache_size(buf_cache), dir); |
|---|
| 698 | + kmem_cache_free(buf_cache, ioctx->buf); |
|---|
| 701 | 699 | kfree(ioctx); |
|---|
| 702 | 700 | } |
|---|
| 703 | 701 | |
|---|
| .. | .. |
|---|
| 706 | 704 | * @sdev: Device to allocate the I/O context ring for. |
|---|
| 707 | 705 | * @ring_size: Number of elements in the I/O context ring. |
|---|
| 708 | 706 | * @ioctx_size: I/O context size. |
|---|
| 709 | | - * @dma_size: DMA buffer size. |
|---|
| 707 | + * @buf_cache: I/O buffer cache. |
|---|
| 708 | + * @alignment_offset: Offset in each ring buffer at which the SRP information |
|---|
| 709 | + * unit starts. |
|---|
| 710 | 710 | * @dir: DMA data direction. |
|---|
| 711 | 711 | */ |
|---|
| 712 | 712 | static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev, |
|---|
| 713 | 713 | int ring_size, int ioctx_size, |
|---|
| 714 | | - int dma_size, enum dma_data_direction dir) |
|---|
| 714 | + struct kmem_cache *buf_cache, |
|---|
| 715 | + int alignment_offset, |
|---|
| 716 | + enum dma_data_direction dir) |
|---|
| 715 | 717 | { |
|---|
| 716 | 718 | struct srpt_ioctx **ring; |
|---|
| 717 | 719 | int i; |
|---|
| 718 | 720 | |
|---|
| 719 | | - WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx) |
|---|
| 720 | | - && ioctx_size != sizeof(struct srpt_send_ioctx)); |
|---|
| 721 | + WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx) && |
|---|
| 722 | + ioctx_size != sizeof(struct srpt_send_ioctx)); |
|---|
| 721 | 723 | |
|---|
| 722 | 724 | ring = kvmalloc_array(ring_size, sizeof(ring[0]), GFP_KERNEL); |
|---|
| 723 | 725 | if (!ring) |
|---|
| 724 | 726 | goto out; |
|---|
| 725 | 727 | for (i = 0; i < ring_size; ++i) { |
|---|
| 726 | | - ring[i] = srpt_alloc_ioctx(sdev, ioctx_size, dma_size, dir); |
|---|
| 728 | + ring[i] = srpt_alloc_ioctx(sdev, ioctx_size, buf_cache, dir); |
|---|
| 727 | 729 | if (!ring[i]) |
|---|
| 728 | 730 | goto err; |
|---|
| 729 | 731 | ring[i]->index = i; |
|---|
| 732 | + ring[i]->offset = alignment_offset; |
|---|
| 730 | 733 | } |
|---|
| 731 | 734 | goto out; |
|---|
| 732 | 735 | |
|---|
| 733 | 736 | err: |
|---|
| 734 | 737 | while (--i >= 0) |
|---|
| 735 | | - srpt_free_ioctx(sdev, ring[i], dma_size, dir); |
|---|
| 738 | + srpt_free_ioctx(sdev, ring[i], buf_cache, dir); |
|---|
| 736 | 739 | kvfree(ring); |
|---|
| 737 | 740 | ring = NULL; |
|---|
| 738 | 741 | out: |
|---|
| .. | .. |
|---|
| 744 | 747 | * @ioctx_ring: I/O context ring to be freed. |
|---|
| 745 | 748 | * @sdev: SRPT HCA pointer. |
|---|
| 746 | 749 | * @ring_size: Number of ring elements. |
|---|
| 747 | | - * @dma_size: Size of I/O context DMA buffer. |
|---|
| 750 | + * @buf_cache: I/O buffer cache. |
|---|
| 748 | 751 | * @dir: DMA data direction. |
|---|
| 749 | 752 | */ |
|---|
| 750 | 753 | static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring, |
|---|
| 751 | 754 | struct srpt_device *sdev, int ring_size, |
|---|
| 752 | | - int dma_size, enum dma_data_direction dir) |
|---|
| 755 | + struct kmem_cache *buf_cache, |
|---|
| 756 | + enum dma_data_direction dir) |
|---|
| 753 | 757 | { |
|---|
| 754 | 758 | int i; |
|---|
| 755 | 759 | |
|---|
| .. | .. |
|---|
| 757 | 761 | return; |
|---|
| 758 | 762 | |
|---|
| 759 | 763 | for (i = 0; i < ring_size; ++i) |
|---|
| 760 | | - srpt_free_ioctx(sdev, ioctx_ring[i], dma_size, dir); |
|---|
| 764 | + srpt_free_ioctx(sdev, ioctx_ring[i], buf_cache, dir); |
|---|
| 761 | 765 | kvfree(ioctx_ring); |
|---|
| 762 | 766 | } |
|---|
| 763 | 767 | |
|---|
| .. | .. |
|---|
| 819 | 823 | struct ib_recv_wr wr; |
|---|
| 820 | 824 | |
|---|
| 821 | 825 | BUG_ON(!sdev); |
|---|
| 822 | | - list.addr = ioctx->ioctx.dma; |
|---|
| 826 | + list.addr = ioctx->ioctx.dma + ioctx->ioctx.offset; |
|---|
| 823 | 827 | list.length = srp_max_req_size; |
|---|
| 824 | 828 | list.lkey = sdev->lkey; |
|---|
| 825 | 829 | |
|---|
| .. | .. |
|---|
| 863 | 867 | |
|---|
| 864 | 868 | static void srpt_zerolength_write_done(struct ib_cq *cq, struct ib_wc *wc) |
|---|
| 865 | 869 | { |
|---|
| 866 | | - struct srpt_rdma_ch *ch = cq->cq_context; |
|---|
| 870 | + struct srpt_rdma_ch *ch = wc->qp->qp_context; |
|---|
| 867 | 871 | |
|---|
| 868 | 872 | pr_debug("%s-%d wc->status %d\n", ch->sess_name, ch->qp->qp_num, |
|---|
| 869 | 873 | wc->status); |
|---|
| .. | .. |
|---|
| 985 | 989 | |
|---|
| 986 | 990 | /** |
|---|
| 987 | 991 | * srpt_get_desc_tbl - parse the data descriptors of a SRP_CMD request |
|---|
| 988 | | - * @ioctx: Pointer to the I/O context associated with the request. |
|---|
| 992 | + * @recv_ioctx: I/O context associated with the received command @srp_cmd. |
|---|
| 993 | + * @ioctx: I/O context that will be used for responding to the initiator. |
|---|
| 989 | 994 | * @srp_cmd: Pointer to the SRP_CMD request data. |
|---|
| 990 | 995 | * @dir: Pointer to the variable to which the transfer direction will be |
|---|
| 991 | 996 | * written. |
|---|
| 992 | | - * @sg: [out] scatterlist allocated for the parsed SRP_CMD. |
|---|
| 997 | + * @sg: [out] scatterlist for the parsed SRP_CMD. |
|---|
| 993 | 998 | * @sg_cnt: [out] length of @sg. |
|---|
| 994 | 999 | * @data_len: Pointer to the variable to which the total data length of all |
|---|
| 995 | 1000 | * descriptors in the SRP_CMD request will be written. |
|---|
| 1001 | + * @imm_data_offset: [in] Offset in SRP_CMD requests at which immediate data |
|---|
| 1002 | + * starts. |
|---|
| 996 | 1003 | * |
|---|
| 997 | 1004 | * This function initializes ioctx->nrbuf and ioctx->r_bufs. |
|---|
| 998 | 1005 | * |
|---|
| 999 | 1006 | * Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors; |
|---|
| 1000 | 1007 | * -ENOMEM when memory allocation fails and zero upon success. |
|---|
| 1001 | 1008 | */ |
|---|
| 1002 | | -static int srpt_get_desc_tbl(struct srpt_send_ioctx *ioctx, |
|---|
| 1009 | +static int srpt_get_desc_tbl(struct srpt_recv_ioctx *recv_ioctx, |
|---|
| 1010 | + struct srpt_send_ioctx *ioctx, |
|---|
| 1003 | 1011 | struct srp_cmd *srp_cmd, enum dma_data_direction *dir, |
|---|
| 1004 | | - struct scatterlist **sg, unsigned *sg_cnt, u64 *data_len) |
|---|
| 1012 | + struct scatterlist **sg, unsigned int *sg_cnt, u64 *data_len, |
|---|
| 1013 | + u16 imm_data_offset) |
|---|
| 1005 | 1014 | { |
|---|
| 1006 | 1015 | BUG_ON(!dir); |
|---|
| 1007 | 1016 | BUG_ON(!data_len); |
|---|
| .. | .. |
|---|
| 1025 | 1034 | |
|---|
| 1026 | 1035 | if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_DIRECT) || |
|---|
| 1027 | 1036 | ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_DIRECT)) { |
|---|
| 1028 | | - struct srp_direct_buf *db = srpt_get_desc_buf(srp_cmd); |
|---|
| 1037 | + struct srp_direct_buf *db = srpt_get_desc_buf(srp_cmd); |
|---|
| 1029 | 1038 | |
|---|
| 1030 | 1039 | *data_len = be32_to_cpu(db->len); |
|---|
| 1031 | 1040 | return srpt_alloc_rw_ctxs(ioctx, db, 1, sg, sg_cnt); |
|---|
| .. | .. |
|---|
| 1037 | 1046 | |
|---|
| 1038 | 1047 | if (nbufs > |
|---|
| 1039 | 1048 | (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) { |
|---|
| 1040 | | - pr_err("received unsupported SRP_CMD request" |
|---|
| 1041 | | - " type (%u out + %u in != %u / %zu)\n", |
|---|
| 1049 | + pr_err("received unsupported SRP_CMD request type (%u out + %u in != %u / %zu)\n", |
|---|
| 1042 | 1050 | srp_cmd->data_out_desc_cnt, |
|---|
| 1043 | 1051 | srp_cmd->data_in_desc_cnt, |
|---|
| 1044 | 1052 | be32_to_cpu(idb->table_desc.len), |
|---|
| .. | .. |
|---|
| 1049 | 1057 | *data_len = be32_to_cpu(idb->len); |
|---|
| 1050 | 1058 | return srpt_alloc_rw_ctxs(ioctx, idb->desc_list, nbufs, |
|---|
| 1051 | 1059 | sg, sg_cnt); |
|---|
| 1060 | + } else if ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_IMM) { |
|---|
| 1061 | + struct srp_imm_buf *imm_buf = srpt_get_desc_buf(srp_cmd); |
|---|
| 1062 | + void *data = (void *)srp_cmd + imm_data_offset; |
|---|
| 1063 | + uint32_t len = be32_to_cpu(imm_buf->len); |
|---|
| 1064 | + uint32_t req_size = imm_data_offset + len; |
|---|
| 1065 | + |
|---|
| 1066 | + if (req_size > srp_max_req_size) { |
|---|
| 1067 | + pr_err("Immediate data (length %d + %d) exceeds request size %d\n", |
|---|
| 1068 | + imm_data_offset, len, srp_max_req_size); |
|---|
| 1069 | + return -EINVAL; |
|---|
| 1070 | + } |
|---|
| 1071 | + if (recv_ioctx->byte_len < req_size) { |
|---|
| 1072 | + pr_err("Received too few data - %d < %d\n", |
|---|
| 1073 | + recv_ioctx->byte_len, req_size); |
|---|
| 1074 | + return -EIO; |
|---|
| 1075 | + } |
|---|
| 1076 | + /* |
|---|
| 1077 | + * The immediate data buffer descriptor must occur before the |
|---|
| 1078 | + * immediate data itself. |
|---|
| 1079 | + */ |
|---|
| 1080 | + if ((void *)(imm_buf + 1) > (void *)data) { |
|---|
| 1081 | + pr_err("Received invalid write request\n"); |
|---|
| 1082 | + return -EINVAL; |
|---|
| 1083 | + } |
|---|
| 1084 | + *data_len = len; |
|---|
| 1085 | + ioctx->recv_ioctx = recv_ioctx; |
|---|
| 1086 | + if ((uintptr_t)data & 511) { |
|---|
| 1087 | + pr_warn_once("Internal error - the receive buffers are not aligned properly.\n"); |
|---|
| 1088 | + return -EINVAL; |
|---|
| 1089 | + } |
|---|
| 1090 | + sg_init_one(&ioctx->imm_sg, data, len); |
|---|
| 1091 | + *sg = &ioctx->imm_sg; |
|---|
| 1092 | + *sg_cnt = 1; |
|---|
| 1093 | + return 0; |
|---|
| 1052 | 1094 | } else { |
|---|
| 1053 | 1095 | *data_len = 0; |
|---|
| 1054 | 1096 | return 0; |
|---|
| .. | .. |
|---|
| 1173 | 1215 | static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) |
|---|
| 1174 | 1216 | { |
|---|
| 1175 | 1217 | struct srpt_send_ioctx *ioctx; |
|---|
| 1176 | | - unsigned long flags; |
|---|
| 1218 | + int tag, cpu; |
|---|
| 1177 | 1219 | |
|---|
| 1178 | 1220 | BUG_ON(!ch); |
|---|
| 1179 | 1221 | |
|---|
| 1180 | | - ioctx = NULL; |
|---|
| 1181 | | - spin_lock_irqsave(&ch->spinlock, flags); |
|---|
| 1182 | | - if (!list_empty(&ch->free_list)) { |
|---|
| 1183 | | - ioctx = list_first_entry(&ch->free_list, |
|---|
| 1184 | | - struct srpt_send_ioctx, free_list); |
|---|
| 1185 | | - list_del(&ioctx->free_list); |
|---|
| 1186 | | - } |
|---|
| 1187 | | - spin_unlock_irqrestore(&ch->spinlock, flags); |
|---|
| 1222 | + tag = sbitmap_queue_get(&ch->sess->sess_tag_pool, &cpu); |
|---|
| 1223 | + if (tag < 0) |
|---|
| 1224 | + return NULL; |
|---|
| 1188 | 1225 | |
|---|
| 1189 | | - if (!ioctx) |
|---|
| 1190 | | - return ioctx; |
|---|
| 1191 | | - |
|---|
| 1226 | + ioctx = ch->ioctx_ring[tag]; |
|---|
| 1192 | 1227 | BUG_ON(ioctx->ch != ch); |
|---|
| 1193 | 1228 | ioctx->state = SRPT_STATE_NEW; |
|---|
| 1229 | + WARN_ON_ONCE(ioctx->recv_ioctx); |
|---|
| 1194 | 1230 | ioctx->n_rdma = 0; |
|---|
| 1195 | 1231 | ioctx->n_rw_ctx = 0; |
|---|
| 1196 | 1232 | ioctx->queue_status_only = false; |
|---|
| .. | .. |
|---|
| 1200 | 1236 | */ |
|---|
| 1201 | 1237 | memset(&ioctx->cmd, 0, sizeof(ioctx->cmd)); |
|---|
| 1202 | 1238 | memset(&ioctx->sense_data, 0, sizeof(ioctx->sense_data)); |
|---|
| 1239 | + ioctx->cmd.map_tag = tag; |
|---|
| 1240 | + ioctx->cmd.map_cpu = cpu; |
|---|
| 1203 | 1241 | |
|---|
| 1204 | 1242 | return ioctx; |
|---|
| 1205 | 1243 | } |
|---|
| .. | .. |
|---|
| 1282 | 1320 | */ |
|---|
| 1283 | 1321 | static void srpt_rdma_read_done(struct ib_cq *cq, struct ib_wc *wc) |
|---|
| 1284 | 1322 | { |
|---|
| 1285 | | - struct srpt_rdma_ch *ch = cq->cq_context; |
|---|
| 1323 | + struct srpt_rdma_ch *ch = wc->qp->qp_context; |
|---|
| 1286 | 1324 | struct srpt_send_ioctx *ioctx = |
|---|
| 1287 | 1325 | container_of(wc->wr_cqe, struct srpt_send_ioctx, rdma_cqe); |
|---|
| 1288 | 1326 | |
|---|
| .. | .. |
|---|
| 1376 | 1414 | BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp)); |
|---|
| 1377 | 1415 | max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp); |
|---|
| 1378 | 1416 | if (sense_data_len > max_sense_len) { |
|---|
| 1379 | | - pr_warn("truncated sense data from %d to %d" |
|---|
| 1380 | | - " bytes\n", sense_data_len, max_sense_len); |
|---|
| 1417 | + pr_warn("truncated sense data from %d to %d bytes\n", |
|---|
| 1418 | + sense_data_len, max_sense_len); |
|---|
| 1381 | 1419 | sense_data_len = max_sense_len; |
|---|
| 1382 | 1420 | } |
|---|
| 1383 | 1421 | |
|---|
| .. | .. |
|---|
| 1457 | 1495 | |
|---|
| 1458 | 1496 | BUG_ON(!send_ioctx); |
|---|
| 1459 | 1497 | |
|---|
| 1460 | | - srp_cmd = recv_ioctx->ioctx.buf; |
|---|
| 1498 | + srp_cmd = recv_ioctx->ioctx.buf + recv_ioctx->ioctx.offset; |
|---|
| 1461 | 1499 | cmd = &send_ioctx->cmd; |
|---|
| 1462 | 1500 | cmd->tag = srp_cmd->tag; |
|---|
| 1463 | 1501 | |
|---|
| .. | .. |
|---|
| 1477 | 1515 | break; |
|---|
| 1478 | 1516 | } |
|---|
| 1479 | 1517 | |
|---|
| 1480 | | - rc = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &sg, &sg_cnt, |
|---|
| 1481 | | - &data_len); |
|---|
| 1518 | + rc = srpt_get_desc_tbl(recv_ioctx, send_ioctx, srp_cmd, &dir, |
|---|
| 1519 | + &sg, &sg_cnt, &data_len, ch->imm_data_offset); |
|---|
| 1482 | 1520 | if (rc) { |
|---|
| 1483 | 1521 | if (rc != -EAGAIN) { |
|---|
| 1484 | 1522 | pr_err("0x%llx: parsing SRP descriptor table failed.\n", |
|---|
| 1485 | 1523 | srp_cmd->tag); |
|---|
| 1486 | 1524 | } |
|---|
| 1487 | | - goto release_ioctx; |
|---|
| 1525 | + goto busy; |
|---|
| 1488 | 1526 | } |
|---|
| 1489 | 1527 | |
|---|
| 1490 | 1528 | rc = target_submit_cmd_map_sgls(cmd, ch->sess, srp_cmd->cdb, |
|---|
| .. | .. |
|---|
| 1495 | 1533 | if (rc != 0) { |
|---|
| 1496 | 1534 | pr_debug("target_submit_cmd() returned %d for tag %#llx\n", rc, |
|---|
| 1497 | 1535 | srp_cmd->tag); |
|---|
| 1498 | | - goto release_ioctx; |
|---|
| 1536 | + goto busy; |
|---|
| 1499 | 1537 | } |
|---|
| 1500 | 1538 | return; |
|---|
| 1501 | 1539 | |
|---|
| 1502 | | -release_ioctx: |
|---|
| 1503 | | - send_ioctx->state = SRPT_STATE_DONE; |
|---|
| 1504 | | - srpt_release_cmd(cmd); |
|---|
| 1540 | +busy: |
|---|
| 1541 | + target_send_busy(cmd); |
|---|
| 1505 | 1542 | } |
|---|
| 1506 | 1543 | |
|---|
| 1507 | 1544 | static int srp_tmr_to_tcm(int fn) |
|---|
| .. | .. |
|---|
| 1545 | 1582 | |
|---|
| 1546 | 1583 | BUG_ON(!send_ioctx); |
|---|
| 1547 | 1584 | |
|---|
| 1548 | | - srp_tsk = recv_ioctx->ioctx.buf; |
|---|
| 1585 | + srp_tsk = recv_ioctx->ioctx.buf + recv_ioctx->ioctx.offset; |
|---|
| 1549 | 1586 | cmd = &send_ioctx->cmd; |
|---|
| 1550 | 1587 | |
|---|
| 1551 | 1588 | pr_debug("recv tsk_mgmt fn %d for task_tag %lld and cmd tag %lld ch %p sess %p\n", |
|---|
| .. | .. |
|---|
| 1561 | 1598 | TARGET_SCF_ACK_KREF); |
|---|
| 1562 | 1599 | if (rc != 0) { |
|---|
| 1563 | 1600 | send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; |
|---|
| 1564 | | - goto fail; |
|---|
| 1601 | + cmd->se_tfo->queue_tm_rsp(cmd); |
|---|
| 1565 | 1602 | } |
|---|
| 1566 | 1603 | return; |
|---|
| 1567 | | -fail: |
|---|
| 1568 | | - transport_send_check_condition_and_sense(cmd, 0, 0); // XXX: |
|---|
| 1569 | 1604 | } |
|---|
| 1570 | 1605 | |
|---|
| 1571 | 1606 | /** |
|---|
| .. | .. |
|---|
| 1588 | 1623 | goto push; |
|---|
| 1589 | 1624 | |
|---|
| 1590 | 1625 | ib_dma_sync_single_for_cpu(ch->sport->sdev->device, |
|---|
| 1591 | | - recv_ioctx->ioctx.dma, srp_max_req_size, |
|---|
| 1626 | + recv_ioctx->ioctx.dma, |
|---|
| 1627 | + recv_ioctx->ioctx.offset + srp_max_req_size, |
|---|
| 1592 | 1628 | DMA_FROM_DEVICE); |
|---|
| 1593 | 1629 | |
|---|
| 1594 | | - srp_cmd = recv_ioctx->ioctx.buf; |
|---|
| 1630 | + srp_cmd = recv_ioctx->ioctx.buf + recv_ioctx->ioctx.offset; |
|---|
| 1595 | 1631 | opcode = srp_cmd->opcode; |
|---|
| 1596 | 1632 | if (opcode == SRP_CMD || opcode == SRP_TSK_MGMT) { |
|---|
| 1597 | 1633 | send_ioctx = srpt_get_send_ioctx(ch); |
|---|
| .. | .. |
|---|
| 1628 | 1664 | break; |
|---|
| 1629 | 1665 | } |
|---|
| 1630 | 1666 | |
|---|
| 1631 | | - srpt_post_recv(ch->sport->sdev, ch, recv_ioctx); |
|---|
| 1667 | + if (!send_ioctx || !send_ioctx->recv_ioctx) |
|---|
| 1668 | + srpt_post_recv(ch->sport->sdev, ch, recv_ioctx); |
|---|
| 1632 | 1669 | res = true; |
|---|
| 1633 | 1670 | |
|---|
| 1634 | 1671 | out: |
|---|
| .. | .. |
|---|
| 1644 | 1681 | |
|---|
| 1645 | 1682 | static void srpt_recv_done(struct ib_cq *cq, struct ib_wc *wc) |
|---|
| 1646 | 1683 | { |
|---|
| 1647 | | - struct srpt_rdma_ch *ch = cq->cq_context; |
|---|
| 1684 | + struct srpt_rdma_ch *ch = wc->qp->qp_context; |
|---|
| 1648 | 1685 | struct srpt_recv_ioctx *ioctx = |
|---|
| 1649 | 1686 | container_of(wc->wr_cqe, struct srpt_recv_ioctx, ioctx.cqe); |
|---|
| 1650 | 1687 | |
|---|
| .. | .. |
|---|
| 1654 | 1691 | req_lim = atomic_dec_return(&ch->req_lim); |
|---|
| 1655 | 1692 | if (unlikely(req_lim < 0)) |
|---|
| 1656 | 1693 | pr_err("req_lim = %d < 0\n", req_lim); |
|---|
| 1694 | + ioctx->byte_len = wc->byte_len; |
|---|
| 1657 | 1695 | srpt_handle_new_iu(ch, ioctx); |
|---|
| 1658 | 1696 | } else { |
|---|
| 1659 | 1697 | pr_info_ratelimited("receiving failed for ioctx %p with status %d\n", |
|---|
| .. | .. |
|---|
| 1704 | 1742 | */ |
|---|
| 1705 | 1743 | static void srpt_send_done(struct ib_cq *cq, struct ib_wc *wc) |
|---|
| 1706 | 1744 | { |
|---|
| 1707 | | - struct srpt_rdma_ch *ch = cq->cq_context; |
|---|
| 1745 | + struct srpt_rdma_ch *ch = wc->qp->qp_context; |
|---|
| 1708 | 1746 | struct srpt_send_ioctx *ioctx = |
|---|
| 1709 | 1747 | container_of(wc->wr_cqe, struct srpt_send_ioctx, ioctx.cqe); |
|---|
| 1710 | 1748 | enum srpt_command_state state; |
|---|
| .. | .. |
|---|
| 1717 | 1755 | atomic_add(1 + ioctx->n_rdma, &ch->sq_wr_avail); |
|---|
| 1718 | 1756 | |
|---|
| 1719 | 1757 | if (wc->status != IB_WC_SUCCESS) |
|---|
| 1720 | | - pr_info("sending response for ioctx 0x%p failed" |
|---|
| 1721 | | - " with status %d\n", ioctx, wc->status); |
|---|
| 1758 | + pr_info("sending response for ioctx 0x%p failed with status %d\n", |
|---|
| 1759 | + ioctx, wc->status); |
|---|
| 1722 | 1760 | |
|---|
| 1723 | 1761 | if (state != SRPT_STATE_DONE) { |
|---|
| 1724 | 1762 | transport_generic_free_cmd(&ioctx->cmd, 0); |
|---|
| 1725 | 1763 | } else { |
|---|
| 1726 | | - pr_err("IB completion has been received too late for" |
|---|
| 1727 | | - " wr_id = %u.\n", ioctx->ioctx.index); |
|---|
| 1764 | + pr_err("IB completion has been received too late for wr_id = %u.\n", |
|---|
| 1765 | + ioctx->ioctx.index); |
|---|
| 1728 | 1766 | } |
|---|
| 1729 | 1767 | |
|---|
| 1730 | 1768 | srpt_process_wait_list(ch); |
|---|
| .. | .. |
|---|
| 1751 | 1789 | goto out; |
|---|
| 1752 | 1790 | |
|---|
| 1753 | 1791 | retry: |
|---|
| 1754 | | - ch->cq = ib_alloc_cq(sdev->device, ch, ch->rq_size + sq_size, |
|---|
| 1755 | | - 0 /* XXX: spread CQs */, IB_POLL_WORKQUEUE); |
|---|
| 1792 | + ch->cq = ib_cq_pool_get(sdev->device, ch->rq_size + sq_size, -1, |
|---|
| 1793 | + IB_POLL_WORKQUEUE); |
|---|
| 1756 | 1794 | if (IS_ERR(ch->cq)) { |
|---|
| 1757 | 1795 | ret = PTR_ERR(ch->cq); |
|---|
| 1758 | 1796 | pr_err("failed to create CQ cqe= %d ret= %d\n", |
|---|
| 1759 | 1797 | ch->rq_size + sq_size, ret); |
|---|
| 1760 | 1798 | goto out; |
|---|
| 1761 | 1799 | } |
|---|
| 1800 | + ch->cq_size = ch->rq_size + sq_size; |
|---|
| 1762 | 1801 | |
|---|
| 1763 | 1802 | qp_init->qp_context = (void *)ch; |
|---|
| 1764 | 1803 | qp_init->event_handler |
|---|
| .. | .. |
|---|
| 1776 | 1815 | */ |
|---|
| 1777 | 1816 | qp_init->cap.max_send_wr = min(sq_size / 2, attrs->max_qp_wr); |
|---|
| 1778 | 1817 | qp_init->cap.max_rdma_ctxs = sq_size / 2; |
|---|
| 1779 | | - qp_init->cap.max_send_sge = min(attrs->max_send_sge, |
|---|
| 1780 | | - SRPT_MAX_SG_PER_WQE); |
|---|
| 1818 | + qp_init->cap.max_send_sge = attrs->max_send_sge; |
|---|
| 1819 | + qp_init->cap.max_recv_sge = 1; |
|---|
| 1781 | 1820 | qp_init->port_num = ch->sport->port; |
|---|
| 1782 | | - if (sdev->use_srq) { |
|---|
| 1821 | + if (sdev->use_srq) |
|---|
| 1783 | 1822 | qp_init->srq = sdev->srq; |
|---|
| 1784 | | - } else { |
|---|
| 1823 | + else |
|---|
| 1785 | 1824 | qp_init->cap.max_recv_wr = ch->rq_size; |
|---|
| 1786 | | - qp_init->cap.max_recv_sge = min(attrs->max_recv_sge, |
|---|
| 1787 | | - SRPT_MAX_SG_PER_WQE); |
|---|
| 1788 | | - } |
|---|
| 1789 | 1825 | |
|---|
| 1790 | 1826 | if (ch->using_rdma_cm) { |
|---|
| 1791 | 1827 | ret = rdma_create_qp(ch->rdma_cm.cm_id, sdev->pd, qp_init); |
|---|
| .. | .. |
|---|
| 1806 | 1842 | if (retry) { |
|---|
| 1807 | 1843 | pr_debug("failed to create queue pair with sq_size = %d (%d) - retrying\n", |
|---|
| 1808 | 1844 | sq_size, ret); |
|---|
| 1809 | | - ib_free_cq(ch->cq); |
|---|
| 1845 | + ib_cq_pool_put(ch->cq, ch->cq_size); |
|---|
| 1810 | 1846 | sq_size = max(sq_size / 2, MIN_SRPT_SQ_SIZE); |
|---|
| 1811 | 1847 | goto retry; |
|---|
| 1812 | 1848 | } else { |
|---|
| .. | .. |
|---|
| 1832 | 1868 | |
|---|
| 1833 | 1869 | err_destroy_cq: |
|---|
| 1834 | 1870 | ch->qp = NULL; |
|---|
| 1835 | | - ib_free_cq(ch->cq); |
|---|
| 1871 | + ib_cq_pool_put(ch->cq, ch->cq_size); |
|---|
| 1836 | 1872 | goto out; |
|---|
| 1837 | 1873 | } |
|---|
| 1838 | 1874 | |
|---|
| 1839 | 1875 | static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch) |
|---|
| 1840 | 1876 | { |
|---|
| 1841 | 1877 | ib_destroy_qp(ch->qp); |
|---|
| 1842 | | - ib_free_cq(ch->cq); |
|---|
| 1878 | + ib_cq_pool_put(ch->cq, ch->cq_size); |
|---|
| 1843 | 1879 | } |
|---|
| 1844 | 1880 | |
|---|
| 1845 | 1881 | /** |
|---|
| .. | .. |
|---|
| 1913 | 1949 | return ret; |
|---|
| 1914 | 1950 | } |
|---|
| 1915 | 1951 | |
|---|
| 1916 | | -static bool srpt_ch_closed(struct srpt_port *sport, struct srpt_rdma_ch *ch) |
|---|
| 1917 | | -{ |
|---|
| 1918 | | - struct srpt_nexus *nexus; |
|---|
| 1919 | | - struct srpt_rdma_ch *ch2; |
|---|
| 1920 | | - bool res = true; |
|---|
| 1921 | | - |
|---|
| 1922 | | - rcu_read_lock(); |
|---|
| 1923 | | - list_for_each_entry(nexus, &sport->nexus_list, entry) { |
|---|
| 1924 | | - list_for_each_entry(ch2, &nexus->ch_list, list) { |
|---|
| 1925 | | - if (ch2 == ch) { |
|---|
| 1926 | | - res = false; |
|---|
| 1927 | | - goto done; |
|---|
| 1928 | | - } |
|---|
| 1929 | | - } |
|---|
| 1930 | | - } |
|---|
| 1931 | | -done: |
|---|
| 1932 | | - rcu_read_unlock(); |
|---|
| 1933 | | - |
|---|
| 1934 | | - return res; |
|---|
| 1935 | | -} |
|---|
| 1936 | | - |
|---|
| 1937 | 1952 | /* Send DREQ and wait for DREP. */ |
|---|
| 1938 | 1953 | static void srpt_disconnect_ch_sync(struct srpt_rdma_ch *ch) |
|---|
| 1939 | 1954 | { |
|---|
| 1955 | + DECLARE_COMPLETION_ONSTACK(closed); |
|---|
| 1940 | 1956 | struct srpt_port *sport = ch->sport; |
|---|
| 1941 | 1957 | |
|---|
| 1942 | 1958 | pr_debug("ch %s-%d state %d\n", ch->sess_name, ch->qp->qp_num, |
|---|
| 1943 | 1959 | ch->state); |
|---|
| 1944 | 1960 | |
|---|
| 1961 | + ch->closed = &closed; |
|---|
| 1962 | + |
|---|
| 1945 | 1963 | mutex_lock(&sport->mutex); |
|---|
| 1946 | 1964 | srpt_disconnect_ch(ch); |
|---|
| 1947 | 1965 | mutex_unlock(&sport->mutex); |
|---|
| 1948 | 1966 | |
|---|
| 1949 | | - while (wait_event_timeout(sport->ch_releaseQ, srpt_ch_closed(sport, ch), |
|---|
| 1950 | | - 5 * HZ) == 0) |
|---|
| 1967 | + while (wait_for_completion_timeout(&closed, 5 * HZ) == 0) |
|---|
| 1951 | 1968 | pr_info("%s(%s-%d state %d): still waiting ...\n", __func__, |
|---|
| 1952 | 1969 | ch->sess_name, ch->qp->qp_num, ch->state); |
|---|
| 1953 | 1970 | |
|---|
| .. | .. |
|---|
| 1963 | 1980 | list_for_each_entry(nexus, &sport->nexus_list, entry) { |
|---|
| 1964 | 1981 | list_for_each_entry(ch, &nexus->ch_list, list) { |
|---|
| 1965 | 1982 | if (srpt_disconnect_ch(ch) >= 0) |
|---|
| 1966 | | - pr_info("Closing channel %s because target %s_%d has been disabled\n", |
|---|
| 1967 | | - ch->sess_name, |
|---|
| 1968 | | - sport->sdev->device->name, sport->port); |
|---|
| 1983 | + pr_info("Closing channel %s-%d because target %s_%d has been disabled\n", |
|---|
| 1984 | + ch->sess_name, ch->qp->qp_num, |
|---|
| 1985 | + dev_name(&sport->sdev->device->dev), |
|---|
| 1986 | + sport->port); |
|---|
| 1969 | 1987 | srpt_close_ch(ch); |
|---|
| 1970 | 1988 | } |
|---|
| 1971 | 1989 | } |
|---|
| .. | .. |
|---|
| 2026 | 2044 | __srpt_close_all_ch(sport); |
|---|
| 2027 | 2045 | } |
|---|
| 2028 | 2046 | |
|---|
| 2047 | +static void srpt_drop_sport_ref(struct srpt_port *sport) |
|---|
| 2048 | +{ |
|---|
| 2049 | + if (atomic_dec_return(&sport->refcount) == 0 && sport->freed_channels) |
|---|
| 2050 | + complete(sport->freed_channels); |
|---|
| 2051 | +} |
|---|
| 2052 | + |
|---|
| 2029 | 2053 | static void srpt_free_ch(struct kref *kref) |
|---|
| 2030 | 2054 | { |
|---|
| 2031 | 2055 | struct srpt_rdma_ch *ch = container_of(kref, struct srpt_rdma_ch, kref); |
|---|
| 2032 | 2056 | |
|---|
| 2057 | + srpt_drop_sport_ref(ch->sport); |
|---|
| 2033 | 2058 | kfree_rcu(ch, rcu); |
|---|
| 2034 | 2059 | } |
|---|
| 2035 | 2060 | |
|---|
| .. | .. |
|---|
| 2073 | 2098 | list_del_rcu(&ch->list); |
|---|
| 2074 | 2099 | mutex_unlock(&sport->mutex); |
|---|
| 2075 | 2100 | |
|---|
| 2101 | + if (ch->closed) |
|---|
| 2102 | + complete(ch->closed); |
|---|
| 2103 | + |
|---|
| 2076 | 2104 | srpt_destroy_ch_ib(ch); |
|---|
| 2077 | 2105 | |
|---|
| 2078 | 2106 | srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring, |
|---|
| 2079 | 2107 | ch->sport->sdev, ch->rq_size, |
|---|
| 2080 | | - ch->max_rsp_size, DMA_TO_DEVICE); |
|---|
| 2108 | + ch->rsp_buf_cache, DMA_TO_DEVICE); |
|---|
| 2109 | + |
|---|
| 2110 | + kmem_cache_destroy(ch->rsp_buf_cache); |
|---|
| 2081 | 2111 | |
|---|
| 2082 | 2112 | srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_recv_ring, |
|---|
| 2083 | 2113 | sdev, ch->rq_size, |
|---|
| 2084 | | - srp_max_req_size, DMA_FROM_DEVICE); |
|---|
| 2114 | + ch->req_buf_cache, DMA_FROM_DEVICE); |
|---|
| 2085 | 2115 | |
|---|
| 2086 | | - wake_up(&sport->ch_releaseQ); |
|---|
| 2116 | + kmem_cache_destroy(ch->req_buf_cache); |
|---|
| 2087 | 2117 | |
|---|
| 2088 | 2118 | kref_put(&ch->kref, srpt_free_ch); |
|---|
| 2089 | 2119 | } |
|---|
| .. | .. |
|---|
| 2120 | 2150 | struct srpt_rdma_ch *ch = NULL; |
|---|
| 2121 | 2151 | char i_port_id[36]; |
|---|
| 2122 | 2152 | u32 it_iu_len; |
|---|
| 2123 | | - int i, ret; |
|---|
| 2153 | + int i, tag_num, tag_size, ret; |
|---|
| 2154 | + struct srpt_tpg *stpg; |
|---|
| 2124 | 2155 | |
|---|
| 2125 | 2156 | WARN_ON_ONCE(irqs_disabled()); |
|---|
| 2126 | | - |
|---|
| 2127 | | - if (WARN_ON(!sdev || !req)) |
|---|
| 2128 | | - return -EINVAL; |
|---|
| 2129 | 2157 | |
|---|
| 2130 | 2158 | it_iu_len = be32_to_cpu(req->req_it_iu_len); |
|---|
| 2131 | 2159 | |
|---|
| .. | .. |
|---|
| 2159 | 2187 | if (!sport->enabled) { |
|---|
| 2160 | 2188 | rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
|---|
| 2161 | 2189 | pr_info("rejected SRP_LOGIN_REQ because target port %s_%d has not yet been enabled\n", |
|---|
| 2162 | | - sport->sdev->device->name, port_num); |
|---|
| 2190 | + dev_name(&sport->sdev->device->dev), port_num); |
|---|
| 2163 | 2191 | goto reject; |
|---|
| 2164 | 2192 | } |
|---|
| 2165 | 2193 | |
|---|
| .. | .. |
|---|
| 2205 | 2233 | INIT_LIST_HEAD(&ch->cmd_wait_list); |
|---|
| 2206 | 2234 | ch->max_rsp_size = ch->sport->port_attrib.srp_max_rsp_size; |
|---|
| 2207 | 2235 | |
|---|
| 2236 | + ch->rsp_buf_cache = kmem_cache_create("srpt-rsp-buf", ch->max_rsp_size, |
|---|
| 2237 | + 512, 0, NULL); |
|---|
| 2238 | + if (!ch->rsp_buf_cache) |
|---|
| 2239 | + goto free_ch; |
|---|
| 2240 | + |
|---|
| 2208 | 2241 | ch->ioctx_ring = (struct srpt_send_ioctx **) |
|---|
| 2209 | 2242 | srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size, |
|---|
| 2210 | 2243 | sizeof(*ch->ioctx_ring[0]), |
|---|
| 2211 | | - ch->max_rsp_size, DMA_TO_DEVICE); |
|---|
| 2244 | + ch->rsp_buf_cache, 0, DMA_TO_DEVICE); |
|---|
| 2212 | 2245 | if (!ch->ioctx_ring) { |
|---|
| 2213 | 2246 | pr_err("rejected SRP_LOGIN_REQ because creating a new QP SQ ring failed.\n"); |
|---|
| 2214 | 2247 | rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
|---|
| 2215 | | - goto free_ch; |
|---|
| 2248 | + goto free_rsp_cache; |
|---|
| 2216 | 2249 | } |
|---|
| 2217 | 2250 | |
|---|
| 2218 | | - INIT_LIST_HEAD(&ch->free_list); |
|---|
| 2219 | | - for (i = 0; i < ch->rq_size; i++) { |
|---|
| 2251 | + for (i = 0; i < ch->rq_size; i++) |
|---|
| 2220 | 2252 | ch->ioctx_ring[i]->ch = ch; |
|---|
| 2221 | | - list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list); |
|---|
| 2222 | | - } |
|---|
| 2223 | 2253 | if (!sdev->use_srq) { |
|---|
| 2254 | + u16 imm_data_offset = req->req_flags & SRP_IMMED_REQUESTED ? |
|---|
| 2255 | + be16_to_cpu(req->imm_data_offset) : 0; |
|---|
| 2256 | + u16 alignment_offset; |
|---|
| 2257 | + u32 req_sz; |
|---|
| 2258 | + |
|---|
| 2259 | + if (req->req_flags & SRP_IMMED_REQUESTED) |
|---|
| 2260 | + pr_debug("imm_data_offset = %d\n", |
|---|
| 2261 | + be16_to_cpu(req->imm_data_offset)); |
|---|
| 2262 | + if (imm_data_offset >= sizeof(struct srp_cmd)) { |
|---|
| 2263 | + ch->imm_data_offset = imm_data_offset; |
|---|
| 2264 | + rsp->rsp_flags |= SRP_LOGIN_RSP_IMMED_SUPP; |
|---|
| 2265 | + } else { |
|---|
| 2266 | + ch->imm_data_offset = 0; |
|---|
| 2267 | + } |
|---|
| 2268 | + alignment_offset = round_up(imm_data_offset, 512) - |
|---|
| 2269 | + imm_data_offset; |
|---|
| 2270 | + req_sz = alignment_offset + imm_data_offset + srp_max_req_size; |
|---|
| 2271 | + ch->req_buf_cache = kmem_cache_create("srpt-req-buf", req_sz, |
|---|
| 2272 | + 512, 0, NULL); |
|---|
| 2273 | + if (!ch->req_buf_cache) |
|---|
| 2274 | + goto free_rsp_ring; |
|---|
| 2275 | + |
|---|
| 2224 | 2276 | ch->ioctx_recv_ring = (struct srpt_recv_ioctx **) |
|---|
| 2225 | 2277 | srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size, |
|---|
| 2226 | 2278 | sizeof(*ch->ioctx_recv_ring[0]), |
|---|
| 2227 | | - srp_max_req_size, |
|---|
| 2279 | + ch->req_buf_cache, |
|---|
| 2280 | + alignment_offset, |
|---|
| 2228 | 2281 | DMA_FROM_DEVICE); |
|---|
| 2229 | 2282 | if (!ch->ioctx_recv_ring) { |
|---|
| 2230 | 2283 | pr_err("rejected SRP_LOGIN_REQ because creating a new QP RQ ring failed.\n"); |
|---|
| 2231 | 2284 | rej->reason = |
|---|
| 2232 | 2285 | cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
|---|
| 2233 | | - goto free_ring; |
|---|
| 2286 | + goto free_recv_cache; |
|---|
| 2234 | 2287 | } |
|---|
| 2235 | 2288 | for (i = 0; i < ch->rq_size; i++) |
|---|
| 2236 | 2289 | INIT_LIST_HEAD(&ch->ioctx_recv_ring[i]->wait_list); |
|---|
| .. | .. |
|---|
| 2248 | 2301 | be64_to_cpu(*(__be64 *)nexus->i_port_id), |
|---|
| 2249 | 2302 | be64_to_cpu(*(__be64 *)(nexus->i_port_id + 8))); |
|---|
| 2250 | 2303 | |
|---|
| 2251 | | - pr_debug("registering session %s\n", ch->sess_name); |
|---|
| 2304 | + pr_debug("registering src addr %s or i_port_id %s\n", ch->sess_name, |
|---|
| 2305 | + i_port_id); |
|---|
| 2252 | 2306 | |
|---|
| 2253 | | - if (sport->port_guid_tpg.se_tpg_wwn) |
|---|
| 2254 | | - ch->sess = target_setup_session(&sport->port_guid_tpg, 0, 0, |
|---|
| 2255 | | - TARGET_PROT_NORMAL, |
|---|
| 2307 | + tag_num = ch->rq_size; |
|---|
| 2308 | + tag_size = 1; /* ib_srpt does not use se_sess->sess_cmd_map */ |
|---|
| 2309 | + |
|---|
| 2310 | + if (sport->guid_id) { |
|---|
| 2311 | + mutex_lock(&sport->guid_id->mutex); |
|---|
| 2312 | + list_for_each_entry(stpg, &sport->guid_id->tpg_list, entry) { |
|---|
| 2313 | + if (!IS_ERR_OR_NULL(ch->sess)) |
|---|
| 2314 | + break; |
|---|
| 2315 | + ch->sess = target_setup_session(&stpg->tpg, tag_num, |
|---|
| 2316 | + tag_size, TARGET_PROT_NORMAL, |
|---|
| 2256 | 2317 | ch->sess_name, ch, NULL); |
|---|
| 2257 | | - if (sport->port_gid_tpg.se_tpg_wwn && IS_ERR_OR_NULL(ch->sess)) |
|---|
| 2258 | | - ch->sess = target_setup_session(&sport->port_gid_tpg, 0, 0, |
|---|
| 2259 | | - TARGET_PROT_NORMAL, i_port_id, ch, |
|---|
| 2260 | | - NULL); |
|---|
| 2261 | | - /* Retry without leading "0x" */ |
|---|
| 2262 | | - if (sport->port_gid_tpg.se_tpg_wwn && IS_ERR_OR_NULL(ch->sess)) |
|---|
| 2263 | | - ch->sess = target_setup_session(&sport->port_gid_tpg, 0, 0, |
|---|
| 2264 | | - TARGET_PROT_NORMAL, |
|---|
| 2318 | + } |
|---|
| 2319 | + mutex_unlock(&sport->guid_id->mutex); |
|---|
| 2320 | + } |
|---|
| 2321 | + |
|---|
| 2322 | + if (sport->gid_id) { |
|---|
| 2323 | + mutex_lock(&sport->gid_id->mutex); |
|---|
| 2324 | + list_for_each_entry(stpg, &sport->gid_id->tpg_list, entry) { |
|---|
| 2325 | + if (!IS_ERR_OR_NULL(ch->sess)) |
|---|
| 2326 | + break; |
|---|
| 2327 | + ch->sess = target_setup_session(&stpg->tpg, tag_num, |
|---|
| 2328 | + tag_size, TARGET_PROT_NORMAL, i_port_id, |
|---|
| 2329 | + ch, NULL); |
|---|
| 2330 | + if (!IS_ERR_OR_NULL(ch->sess)) |
|---|
| 2331 | + break; |
|---|
| 2332 | + /* Retry without leading "0x" */ |
|---|
| 2333 | + ch->sess = target_setup_session(&stpg->tpg, tag_num, |
|---|
| 2334 | + tag_size, TARGET_PROT_NORMAL, |
|---|
| 2265 | 2335 | i_port_id + 2, ch, NULL); |
|---|
| 2336 | + } |
|---|
| 2337 | + mutex_unlock(&sport->gid_id->mutex); |
|---|
| 2338 | + } |
|---|
| 2339 | + |
|---|
| 2266 | 2340 | if (IS_ERR_OR_NULL(ch->sess)) { |
|---|
| 2267 | 2341 | WARN_ON_ONCE(ch->sess == NULL); |
|---|
| 2268 | 2342 | ret = PTR_ERR(ch->sess); |
|---|
| .. | .. |
|---|
| 2275 | 2349 | goto destroy_ib; |
|---|
| 2276 | 2350 | } |
|---|
| 2277 | 2351 | |
|---|
| 2352 | + /* |
|---|
| 2353 | + * Once a session has been created destruction of srpt_rdma_ch objects |
|---|
| 2354 | + * will decrement sport->refcount. Hence increment sport->refcount now. |
|---|
| 2355 | + */ |
|---|
| 2356 | + atomic_inc(&sport->refcount); |
|---|
| 2357 | + |
|---|
| 2278 | 2358 | mutex_lock(&sport->mutex); |
|---|
| 2279 | 2359 | |
|---|
| 2280 | 2360 | if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) { |
|---|
| 2281 | 2361 | struct srpt_rdma_ch *ch2; |
|---|
| 2282 | | - |
|---|
| 2283 | | - rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN; |
|---|
| 2284 | 2362 | |
|---|
| 2285 | 2363 | list_for_each_entry(ch2, &nexus->ch_list, list) { |
|---|
| 2286 | 2364 | if (srpt_disconnect_ch(ch2) < 0) |
|---|
| 2287 | 2365 | continue; |
|---|
| 2288 | 2366 | pr_info("Relogin - closed existing channel %s\n", |
|---|
| 2289 | 2367 | ch2->sess_name); |
|---|
| 2290 | | - rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_TERMINATED; |
|---|
| 2368 | + rsp->rsp_flags |= SRP_LOGIN_RSP_MULTICHAN_TERMINATED; |
|---|
| 2291 | 2369 | } |
|---|
| 2292 | 2370 | } else { |
|---|
| 2293 | | - rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED; |
|---|
| 2371 | + rsp->rsp_flags |= SRP_LOGIN_RSP_MULTICHAN_MAINTAINED; |
|---|
| 2294 | 2372 | } |
|---|
| 2295 | 2373 | |
|---|
| 2296 | 2374 | list_add_tail_rcu(&ch->list, &nexus->ch_list); |
|---|
| .. | .. |
|---|
| 2299 | 2377 | rej->reason = cpu_to_be32( |
|---|
| 2300 | 2378 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
|---|
| 2301 | 2379 | pr_info("rejected SRP_LOGIN_REQ because target %s_%d is not enabled\n", |
|---|
| 2302 | | - sdev->device->name, port_num); |
|---|
| 2380 | + dev_name(&sdev->device->dev), port_num); |
|---|
| 2303 | 2381 | mutex_unlock(&sport->mutex); |
|---|
| 2304 | 2382 | ret = -EINVAL; |
|---|
| 2305 | 2383 | goto reject; |
|---|
| .. | .. |
|---|
| 2321 | 2399 | /* create srp_login_response */ |
|---|
| 2322 | 2400 | rsp->opcode = SRP_LOGIN_RSP; |
|---|
| 2323 | 2401 | rsp->tag = req->tag; |
|---|
| 2324 | | - rsp->max_it_iu_len = req->req_it_iu_len; |
|---|
| 2402 | + rsp->max_it_iu_len = cpu_to_be32(srp_max_req_size); |
|---|
| 2325 | 2403 | rsp->max_ti_iu_len = req->req_it_iu_len; |
|---|
| 2326 | 2404 | ch->max_ti_iu_len = it_iu_len; |
|---|
| 2327 | 2405 | rsp->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | |
|---|
| .. | .. |
|---|
| 2385 | 2463 | free_recv_ring: |
|---|
| 2386 | 2464 | srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_recv_ring, |
|---|
| 2387 | 2465 | ch->sport->sdev, ch->rq_size, |
|---|
| 2388 | | - srp_max_req_size, DMA_FROM_DEVICE); |
|---|
| 2466 | + ch->req_buf_cache, DMA_FROM_DEVICE); |
|---|
| 2389 | 2467 | |
|---|
| 2390 | | -free_ring: |
|---|
| 2468 | +free_recv_cache: |
|---|
| 2469 | + kmem_cache_destroy(ch->req_buf_cache); |
|---|
| 2470 | + |
|---|
| 2471 | +free_rsp_ring: |
|---|
| 2391 | 2472 | srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring, |
|---|
| 2392 | 2473 | ch->sport->sdev, ch->rq_size, |
|---|
| 2393 | | - ch->max_rsp_size, DMA_TO_DEVICE); |
|---|
| 2474 | + ch->rsp_buf_cache, DMA_TO_DEVICE); |
|---|
| 2475 | + |
|---|
| 2476 | +free_rsp_cache: |
|---|
| 2477 | + kmem_cache_destroy(ch->rsp_buf_cache); |
|---|
| 2394 | 2478 | |
|---|
| 2395 | 2479 | free_ch: |
|---|
| 2396 | 2480 | if (rdma_cm_id) |
|---|
| .. | .. |
|---|
| 2410 | 2494 | SRP_BUF_FORMAT_INDIRECT); |
|---|
| 2411 | 2495 | |
|---|
| 2412 | 2496 | if (rdma_cm_id) |
|---|
| 2413 | | - rdma_reject(rdma_cm_id, rej, sizeof(*rej)); |
|---|
| 2497 | + rdma_reject(rdma_cm_id, rej, sizeof(*rej), |
|---|
| 2498 | + IB_CM_REJ_CONSUMER_DEFINED); |
|---|
| 2414 | 2499 | else |
|---|
| 2415 | 2500 | ib_send_cm_rej(ib_cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, |
|---|
| 2416 | 2501 | rej, sizeof(*rej)); |
|---|
| .. | .. |
|---|
| 2452 | 2537 | struct srpt_device *sdev; |
|---|
| 2453 | 2538 | struct srp_login_req req; |
|---|
| 2454 | 2539 | const struct srp_login_req_rdma *req_rdma; |
|---|
| 2540 | + struct sa_path_rec *path_rec = cm_id->route.path_rec; |
|---|
| 2455 | 2541 | char src_addr[40]; |
|---|
| 2456 | 2542 | |
|---|
| 2457 | 2543 | sdev = ib_get_client_data(cm_id->device, &srpt_client); |
|---|
| .. | .. |
|---|
| 2471 | 2557 | req.req_flags = req_rdma->req_flags; |
|---|
| 2472 | 2558 | memcpy(req.initiator_port_id, req_rdma->initiator_port_id, 16); |
|---|
| 2473 | 2559 | memcpy(req.target_port_id, req_rdma->target_port_id, 16); |
|---|
| 2560 | + req.imm_data_offset = req_rdma->imm_data_offset; |
|---|
| 2474 | 2561 | |
|---|
| 2475 | 2562 | snprintf(src_addr, sizeof(src_addr), "%pIS", |
|---|
| 2476 | 2563 | &cm_id->route.addr.src_addr); |
|---|
| 2477 | 2564 | |
|---|
| 2478 | 2565 | return srpt_cm_req_recv(sdev, NULL, cm_id, cm_id->port_num, |
|---|
| 2479 | | - cm_id->route.path_rec->pkey, &req, src_addr); |
|---|
| 2566 | + path_rec ? path_rec->pkey : 0, &req, src_addr); |
|---|
| 2480 | 2567 | } |
|---|
| 2481 | 2568 | |
|---|
| 2482 | 2569 | static void srpt_cm_rej_recv(struct srpt_rdma_ch *ch, |
|---|
| .. | .. |
|---|
| 2640 | 2727 | return ret; |
|---|
| 2641 | 2728 | } |
|---|
| 2642 | 2729 | |
|---|
| 2643 | | -static int srpt_write_pending_status(struct se_cmd *se_cmd) |
|---|
| 2644 | | -{ |
|---|
| 2645 | | - struct srpt_send_ioctx *ioctx; |
|---|
| 2646 | | - |
|---|
| 2647 | | - ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd); |
|---|
| 2648 | | - return ioctx->state == SRPT_STATE_NEED_DATA; |
|---|
| 2649 | | -} |
|---|
| 2650 | | - |
|---|
| 2651 | 2730 | /* |
|---|
| 2652 | 2731 | * srpt_write_pending - Start data transfer from initiator to target (write). |
|---|
| 2653 | 2732 | */ |
|---|
| .. | .. |
|---|
| 2660 | 2739 | struct ib_cqe *cqe = &ioctx->rdma_cqe; |
|---|
| 2661 | 2740 | enum srpt_command_state new_state; |
|---|
| 2662 | 2741 | int ret, i; |
|---|
| 2742 | + |
|---|
| 2743 | + if (ioctx->recv_ioctx) { |
|---|
| 2744 | + srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN); |
|---|
| 2745 | + target_execute_cmd(&ioctx->cmd); |
|---|
| 2746 | + return 0; |
|---|
| 2747 | + } |
|---|
| 2663 | 2748 | |
|---|
| 2664 | 2749 | new_state = srpt_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA); |
|---|
| 2665 | 2750 | WARN_ON(new_state == SRPT_STATE_DONE); |
|---|
| .. | .. |
|---|
| 2724 | 2809 | int resp_len, ret, i; |
|---|
| 2725 | 2810 | u8 srp_tm_status; |
|---|
| 2726 | 2811 | |
|---|
| 2727 | | - BUG_ON(!ch); |
|---|
| 2728 | | - |
|---|
| 2729 | 2812 | state = ioctx->state; |
|---|
| 2730 | 2813 | switch (state) { |
|---|
| 2731 | 2814 | case SRPT_STATE_NEW: |
|---|
| .. | .. |
|---|
| 2741 | 2824 | break; |
|---|
| 2742 | 2825 | } |
|---|
| 2743 | 2826 | |
|---|
| 2744 | | - if (unlikely(WARN_ON_ONCE(state == SRPT_STATE_CMD_RSP_SENT))) |
|---|
| 2827 | + if (WARN_ON_ONCE(state == SRPT_STATE_CMD_RSP_SENT)) |
|---|
| 2745 | 2828 | return; |
|---|
| 2746 | 2829 | |
|---|
| 2747 | 2830 | /* For read commands, transfer the data to the initiator. */ |
|---|
| .. | .. |
|---|
| 2854 | 2937 | srpt_refresh_port(sport); |
|---|
| 2855 | 2938 | } |
|---|
| 2856 | 2939 | |
|---|
| 2857 | | -static bool srpt_ch_list_empty(struct srpt_port *sport) |
|---|
| 2858 | | -{ |
|---|
| 2859 | | - struct srpt_nexus *nexus; |
|---|
| 2860 | | - bool res = true; |
|---|
| 2861 | | - |
|---|
| 2862 | | - rcu_read_lock(); |
|---|
| 2863 | | - list_for_each_entry(nexus, &sport->nexus_list, entry) |
|---|
| 2864 | | - if (!list_empty(&nexus->ch_list)) |
|---|
| 2865 | | - res = false; |
|---|
| 2866 | | - rcu_read_unlock(); |
|---|
| 2867 | | - |
|---|
| 2868 | | - return res; |
|---|
| 2869 | | -} |
|---|
| 2870 | | - |
|---|
| 2871 | 2940 | /** |
|---|
| 2872 | 2941 | * srpt_release_sport - disable login and wait for associated channels |
|---|
| 2873 | 2942 | * @sport: SRPT HCA port. |
|---|
| 2874 | 2943 | */ |
|---|
| 2875 | 2944 | static int srpt_release_sport(struct srpt_port *sport) |
|---|
| 2876 | 2945 | { |
|---|
| 2946 | + DECLARE_COMPLETION_ONSTACK(c); |
|---|
| 2877 | 2947 | struct srpt_nexus *nexus, *next_n; |
|---|
| 2878 | 2948 | struct srpt_rdma_ch *ch; |
|---|
| 2879 | 2949 | |
|---|
| 2880 | 2950 | WARN_ON_ONCE(irqs_disabled()); |
|---|
| 2881 | 2951 | |
|---|
| 2952 | + sport->freed_channels = &c; |
|---|
| 2953 | + |
|---|
| 2882 | 2954 | mutex_lock(&sport->mutex); |
|---|
| 2883 | 2955 | srpt_set_enabled(sport, false); |
|---|
| 2884 | 2956 | mutex_unlock(&sport->mutex); |
|---|
| 2885 | 2957 | |
|---|
| 2886 | | - while (wait_event_timeout(sport->ch_releaseQ, |
|---|
| 2887 | | - srpt_ch_list_empty(sport), 5 * HZ) <= 0) { |
|---|
| 2888 | | - pr_info("%s_%d: waiting for session unregistration ...\n", |
|---|
| 2889 | | - sport->sdev->device->name, sport->port); |
|---|
| 2958 | + while (atomic_read(&sport->refcount) > 0 && |
|---|
| 2959 | + wait_for_completion_timeout(&c, 5 * HZ) <= 0) { |
|---|
| 2960 | + pr_info("%s_%d: waiting for unregistration of %d sessions ...\n", |
|---|
| 2961 | + dev_name(&sport->sdev->device->dev), sport->port, |
|---|
| 2962 | + atomic_read(&sport->refcount)); |
|---|
| 2890 | 2963 | rcu_read_lock(); |
|---|
| 2891 | 2964 | list_for_each_entry(nexus, &sport->nexus_list, entry) { |
|---|
| 2892 | 2965 | list_for_each_entry(ch, &nexus->ch_list, list) { |
|---|
| .. | .. |
|---|
| 2908 | 2981 | return 0; |
|---|
| 2909 | 2982 | } |
|---|
| 2910 | 2983 | |
|---|
| 2911 | | -static struct se_wwn *__srpt_lookup_wwn(const char *name) |
|---|
| 2984 | +struct port_and_port_id { |
|---|
| 2985 | + struct srpt_port *sport; |
|---|
| 2986 | + struct srpt_port_id **port_id; |
|---|
| 2987 | +}; |
|---|
| 2988 | + |
|---|
| 2989 | +static struct port_and_port_id __srpt_lookup_port(const char *name) |
|---|
| 2912 | 2990 | { |
|---|
| 2913 | 2991 | struct ib_device *dev; |
|---|
| 2914 | 2992 | struct srpt_device *sdev; |
|---|
| .. | .. |
|---|
| 2923 | 3001 | for (i = 0; i < dev->phys_port_cnt; i++) { |
|---|
| 2924 | 3002 | sport = &sdev->port[i]; |
|---|
| 2925 | 3003 | |
|---|
| 2926 | | - if (strcmp(sport->port_guid, name) == 0) |
|---|
| 2927 | | - return &sport->port_guid_wwn; |
|---|
| 2928 | | - if (strcmp(sport->port_gid, name) == 0) |
|---|
| 2929 | | - return &sport->port_gid_wwn; |
|---|
| 3004 | + if (strcmp(sport->guid_name, name) == 0) { |
|---|
| 3005 | + kref_get(&sdev->refcnt); |
|---|
| 3006 | + return (struct port_and_port_id){ |
|---|
| 3007 | + sport, &sport->guid_id}; |
|---|
| 3008 | + } |
|---|
| 3009 | + if (strcmp(sport->gid_name, name) == 0) { |
|---|
| 3010 | + kref_get(&sdev->refcnt); |
|---|
| 3011 | + return (struct port_and_port_id){ |
|---|
| 3012 | + sport, &sport->gid_id}; |
|---|
| 3013 | + } |
|---|
| 2930 | 3014 | } |
|---|
| 2931 | 3015 | } |
|---|
| 2932 | 3016 | |
|---|
| 2933 | | - return NULL; |
|---|
| 3017 | + return (struct port_and_port_id){}; |
|---|
| 2934 | 3018 | } |
|---|
| 2935 | 3019 | |
|---|
| 2936 | | -static struct se_wwn *srpt_lookup_wwn(const char *name) |
|---|
| 3020 | +/** |
|---|
| 3021 | + * srpt_lookup_port() - Look up an RDMA port by name |
|---|
| 3022 | + * @name: ASCII port name |
|---|
| 3023 | + * |
|---|
| 3024 | + * Increments the RDMA port reference count if an RDMA port pointer is returned. |
|---|
| 3025 | + * The caller must drop that reference count by calling srpt_port_put_ref(). |
|---|
| 3026 | + */ |
|---|
| 3027 | +static struct port_and_port_id srpt_lookup_port(const char *name) |
|---|
| 2937 | 3028 | { |
|---|
| 2938 | | - struct se_wwn *wwn; |
|---|
| 3029 | + struct port_and_port_id papi; |
|---|
| 2939 | 3030 | |
|---|
| 2940 | 3031 | spin_lock(&srpt_dev_lock); |
|---|
| 2941 | | - wwn = __srpt_lookup_wwn(name); |
|---|
| 3032 | + papi = __srpt_lookup_port(name); |
|---|
| 2942 | 3033 | spin_unlock(&srpt_dev_lock); |
|---|
| 2943 | 3034 | |
|---|
| 2944 | | - return wwn; |
|---|
| 3035 | + return papi; |
|---|
| 2945 | 3036 | } |
|---|
| 2946 | 3037 | |
|---|
| 2947 | 3038 | static void srpt_free_srq(struct srpt_device *sdev) |
|---|
| .. | .. |
|---|
| 2951 | 3042 | |
|---|
| 2952 | 3043 | ib_destroy_srq(sdev->srq); |
|---|
| 2953 | 3044 | srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev, |
|---|
| 2954 | | - sdev->srq_size, srp_max_req_size, DMA_FROM_DEVICE); |
|---|
| 3045 | + sdev->srq_size, sdev->req_buf_cache, |
|---|
| 3046 | + DMA_FROM_DEVICE); |
|---|
| 3047 | + kmem_cache_destroy(sdev->req_buf_cache); |
|---|
| 2955 | 3048 | sdev->srq = NULL; |
|---|
| 2956 | 3049 | } |
|---|
| 2957 | 3050 | |
|---|
| .. | .. |
|---|
| 2976 | 3069 | } |
|---|
| 2977 | 3070 | |
|---|
| 2978 | 3071 | pr_debug("create SRQ #wr= %d max_allow=%d dev= %s\n", sdev->srq_size, |
|---|
| 2979 | | - sdev->device->attrs.max_srq_wr, device->name); |
|---|
| 3072 | + sdev->device->attrs.max_srq_wr, dev_name(&device->dev)); |
|---|
| 3073 | + |
|---|
| 3074 | + sdev->req_buf_cache = kmem_cache_create("srpt-srq-req-buf", |
|---|
| 3075 | + srp_max_req_size, 0, 0, NULL); |
|---|
| 3076 | + if (!sdev->req_buf_cache) |
|---|
| 3077 | + goto free_srq; |
|---|
| 2980 | 3078 | |
|---|
| 2981 | 3079 | sdev->ioctx_ring = (struct srpt_recv_ioctx **) |
|---|
| 2982 | 3080 | srpt_alloc_ioctx_ring(sdev, sdev->srq_size, |
|---|
| 2983 | 3081 | sizeof(*sdev->ioctx_ring[0]), |
|---|
| 2984 | | - srp_max_req_size, DMA_FROM_DEVICE); |
|---|
| 2985 | | - if (!sdev->ioctx_ring) { |
|---|
| 2986 | | - ib_destroy_srq(srq); |
|---|
| 2987 | | - return -ENOMEM; |
|---|
| 2988 | | - } |
|---|
| 3082 | + sdev->req_buf_cache, 0, DMA_FROM_DEVICE); |
|---|
| 3083 | + if (!sdev->ioctx_ring) |
|---|
| 3084 | + goto free_cache; |
|---|
| 2989 | 3085 | |
|---|
| 2990 | 3086 | sdev->use_srq = true; |
|---|
| 2991 | 3087 | sdev->srq = srq; |
|---|
| .. | .. |
|---|
| 2996 | 3092 | } |
|---|
| 2997 | 3093 | |
|---|
| 2998 | 3094 | return 0; |
|---|
| 3095 | + |
|---|
| 3096 | +free_cache: |
|---|
| 3097 | + kmem_cache_destroy(sdev->req_buf_cache); |
|---|
| 3098 | + |
|---|
| 3099 | +free_srq: |
|---|
| 3100 | + ib_destroy_srq(srq); |
|---|
| 3101 | + return -ENOMEM; |
|---|
| 2999 | 3102 | } |
|---|
| 3000 | 3103 | |
|---|
| 3001 | 3104 | static int srpt_use_srq(struct srpt_device *sdev, bool use_srq) |
|---|
| .. | .. |
|---|
| 3009 | 3112 | } else if (use_srq && !sdev->srq) { |
|---|
| 3010 | 3113 | ret = srpt_alloc_srq(sdev); |
|---|
| 3011 | 3114 | } |
|---|
| 3012 | | - pr_debug("%s(%s): use_srq = %d; ret = %d\n", __func__, device->name, |
|---|
| 3013 | | - sdev->use_srq, ret); |
|---|
| 3115 | + pr_debug("%s(%s): use_srq = %d; ret = %d\n", __func__, |
|---|
| 3116 | + dev_name(&device->dev), sdev->use_srq, ret); |
|---|
| 3014 | 3117 | return ret; |
|---|
| 3118 | +} |
|---|
| 3119 | + |
|---|
| 3120 | +static void srpt_free_sdev(struct kref *refcnt) |
|---|
| 3121 | +{ |
|---|
| 3122 | + struct srpt_device *sdev = container_of(refcnt, typeof(*sdev), refcnt); |
|---|
| 3123 | + |
|---|
| 3124 | + kfree(sdev); |
|---|
| 3125 | +} |
|---|
| 3126 | + |
|---|
| 3127 | +static void srpt_sdev_put(struct srpt_device *sdev) |
|---|
| 3128 | +{ |
|---|
| 3129 | + kref_put(&sdev->refcnt, srpt_free_sdev); |
|---|
| 3015 | 3130 | } |
|---|
| 3016 | 3131 | |
|---|
| 3017 | 3132 | /** |
|---|
| 3018 | 3133 | * srpt_add_one - InfiniBand device addition callback function |
|---|
| 3019 | 3134 | * @device: Describes a HCA. |
|---|
| 3020 | 3135 | */ |
|---|
| 3021 | | -static void srpt_add_one(struct ib_device *device) |
|---|
| 3136 | +static int srpt_add_one(struct ib_device *device) |
|---|
| 3022 | 3137 | { |
|---|
| 3023 | 3138 | struct srpt_device *sdev; |
|---|
| 3024 | 3139 | struct srpt_port *sport; |
|---|
| .. | .. |
|---|
| 3029 | 3144 | sdev = kzalloc(struct_size(sdev, port, device->phys_port_cnt), |
|---|
| 3030 | 3145 | GFP_KERNEL); |
|---|
| 3031 | 3146 | if (!sdev) |
|---|
| 3032 | | - goto err; |
|---|
| 3147 | + return -ENOMEM; |
|---|
| 3033 | 3148 | |
|---|
| 3149 | + kref_init(&sdev->refcnt); |
|---|
| 3034 | 3150 | sdev->device = device; |
|---|
| 3035 | 3151 | mutex_init(&sdev->sdev_mutex); |
|---|
| 3036 | 3152 | |
|---|
| 3037 | 3153 | sdev->pd = ib_alloc_pd(device, 0); |
|---|
| 3038 | | - if (IS_ERR(sdev->pd)) |
|---|
| 3154 | + if (IS_ERR(sdev->pd)) { |
|---|
| 3155 | + ret = PTR_ERR(sdev->pd); |
|---|
| 3039 | 3156 | goto free_dev; |
|---|
| 3157 | + } |
|---|
| 3040 | 3158 | |
|---|
| 3041 | 3159 | sdev->lkey = sdev->pd->local_dma_lkey; |
|---|
| 3042 | 3160 | |
|---|
| .. | .. |
|---|
| 3052 | 3170 | if (IS_ERR(sdev->cm_id)) { |
|---|
| 3053 | 3171 | pr_info("ib_create_cm_id() failed: %ld\n", |
|---|
| 3054 | 3172 | PTR_ERR(sdev->cm_id)); |
|---|
| 3173 | + ret = PTR_ERR(sdev->cm_id); |
|---|
| 3055 | 3174 | sdev->cm_id = NULL; |
|---|
| 3056 | 3175 | if (!rdma_cm_id) |
|---|
| 3057 | 3176 | goto err_ring; |
|---|
| 3058 | 3177 | } |
|---|
| 3059 | 3178 | |
|---|
| 3060 | 3179 | /* print out target login information */ |
|---|
| 3061 | | - pr_debug("Target login info: id_ext=%016llx,ioc_guid=%016llx," |
|---|
| 3062 | | - "pkey=ffff,service_id=%016llx\n", srpt_service_guid, |
|---|
| 3063 | | - srpt_service_guid, srpt_service_guid); |
|---|
| 3180 | + pr_debug("Target login info: id_ext=%016llx,ioc_guid=%016llx,pkey=ffff,service_id=%016llx\n", |
|---|
| 3181 | + srpt_service_guid, srpt_service_guid, srpt_service_guid); |
|---|
| 3064 | 3182 | |
|---|
| 3065 | 3183 | /* |
|---|
| 3066 | 3184 | * We do not have a consistent service_id (ie. also id_ext of target_id) |
|---|
| .. | .. |
|---|
| 3084 | 3202 | for (i = 1; i <= sdev->device->phys_port_cnt; i++) { |
|---|
| 3085 | 3203 | sport = &sdev->port[i - 1]; |
|---|
| 3086 | 3204 | INIT_LIST_HEAD(&sport->nexus_list); |
|---|
| 3087 | | - init_waitqueue_head(&sport->ch_releaseQ); |
|---|
| 3088 | 3205 | mutex_init(&sport->mutex); |
|---|
| 3089 | 3206 | sport->sdev = sdev; |
|---|
| 3090 | 3207 | sport->port = i; |
|---|
| .. | .. |
|---|
| 3094 | 3211 | sport->port_attrib.use_srq = false; |
|---|
| 3095 | 3212 | INIT_WORK(&sport->work, srpt_refresh_port_work); |
|---|
| 3096 | 3213 | |
|---|
| 3097 | | - if (srpt_refresh_port(sport)) { |
|---|
| 3214 | + ret = srpt_refresh_port(sport); |
|---|
| 3215 | + if (ret) { |
|---|
| 3098 | 3216 | pr_err("MAD registration failed for %s-%d.\n", |
|---|
| 3099 | | - sdev->device->name, i); |
|---|
| 3100 | | - goto err_event; |
|---|
| 3217 | + dev_name(&sdev->device->dev), i); |
|---|
| 3218 | + i--; |
|---|
| 3219 | + goto err_port; |
|---|
| 3101 | 3220 | } |
|---|
| 3102 | 3221 | } |
|---|
| 3103 | 3222 | |
|---|
| .. | .. |
|---|
| 3105 | 3224 | list_add_tail(&sdev->list, &srpt_dev_list); |
|---|
| 3106 | 3225 | spin_unlock(&srpt_dev_lock); |
|---|
| 3107 | 3226 | |
|---|
| 3108 | | -out: |
|---|
| 3109 | 3227 | ib_set_client_data(device, &srpt_client, sdev); |
|---|
| 3110 | | - pr_debug("added %s.\n", device->name); |
|---|
| 3111 | | - return; |
|---|
| 3228 | + pr_debug("added %s.\n", dev_name(&device->dev)); |
|---|
| 3229 | + return 0; |
|---|
| 3112 | 3230 | |
|---|
| 3113 | | -err_event: |
|---|
| 3231 | +err_port: |
|---|
| 3232 | + srpt_unregister_mad_agent(sdev, i); |
|---|
| 3114 | 3233 | ib_unregister_event_handler(&sdev->event_handler); |
|---|
| 3115 | 3234 | err_cm: |
|---|
| 3116 | 3235 | if (sdev->cm_id) |
|---|
| .. | .. |
|---|
| 3119 | 3238 | srpt_free_srq(sdev); |
|---|
| 3120 | 3239 | ib_dealloc_pd(sdev->pd); |
|---|
| 3121 | 3240 | free_dev: |
|---|
| 3122 | | - kfree(sdev); |
|---|
| 3123 | | -err: |
|---|
| 3124 | | - sdev = NULL; |
|---|
| 3125 | | - pr_info("%s(%s) failed.\n", __func__, device->name); |
|---|
| 3126 | | - goto out; |
|---|
| 3241 | + srpt_sdev_put(sdev); |
|---|
| 3242 | + pr_info("%s(%s) failed.\n", __func__, dev_name(&device->dev)); |
|---|
| 3243 | + return ret; |
|---|
| 3127 | 3244 | } |
|---|
| 3128 | 3245 | |
|---|
| 3129 | 3246 | /** |
|---|
| .. | .. |
|---|
| 3136 | 3253 | struct srpt_device *sdev = client_data; |
|---|
| 3137 | 3254 | int i; |
|---|
| 3138 | 3255 | |
|---|
| 3139 | | - if (!sdev) { |
|---|
| 3140 | | - pr_info("%s(%s): nothing to do.\n", __func__, device->name); |
|---|
| 3141 | | - return; |
|---|
| 3142 | | - } |
|---|
| 3143 | | - |
|---|
| 3144 | | - srpt_unregister_mad_agent(sdev); |
|---|
| 3256 | + srpt_unregister_mad_agent(sdev, sdev->device->phys_port_cnt); |
|---|
| 3145 | 3257 | |
|---|
| 3146 | 3258 | ib_unregister_event_handler(&sdev->event_handler); |
|---|
| 3147 | 3259 | |
|---|
| .. | .. |
|---|
| 3170 | 3282 | |
|---|
| 3171 | 3283 | ib_dealloc_pd(sdev->pd); |
|---|
| 3172 | 3284 | |
|---|
| 3173 | | - kfree(sdev); |
|---|
| 3285 | + srpt_sdev_put(sdev); |
|---|
| 3174 | 3286 | } |
|---|
| 3175 | 3287 | |
|---|
| 3176 | 3288 | static struct ib_client srpt_client = { |
|---|
| .. | .. |
|---|
| 3189 | 3301 | return 0; |
|---|
| 3190 | 3302 | } |
|---|
| 3191 | 3303 | |
|---|
| 3192 | | -static char *srpt_get_fabric_name(void) |
|---|
| 3193 | | -{ |
|---|
| 3194 | | - return "srpt"; |
|---|
| 3195 | | -} |
|---|
| 3196 | | - |
|---|
| 3197 | 3304 | static struct srpt_port *srpt_tpg_to_sport(struct se_portal_group *tpg) |
|---|
| 3198 | 3305 | { |
|---|
| 3199 | 3306 | return tpg->se_tpg_wwn->priv; |
|---|
| 3200 | 3307 | } |
|---|
| 3201 | 3308 | |
|---|
| 3309 | +static struct srpt_port_id *srpt_wwn_to_sport_id(struct se_wwn *wwn) |
|---|
| 3310 | +{ |
|---|
| 3311 | + struct srpt_port *sport = wwn->priv; |
|---|
| 3312 | + |
|---|
| 3313 | + if (sport->guid_id && &sport->guid_id->wwn == wwn) |
|---|
| 3314 | + return sport->guid_id; |
|---|
| 3315 | + if (sport->gid_id && &sport->gid_id->wwn == wwn) |
|---|
| 3316 | + return sport->gid_id; |
|---|
| 3317 | + WARN_ON_ONCE(true); |
|---|
| 3318 | + return NULL; |
|---|
| 3319 | +} |
|---|
| 3320 | + |
|---|
| 3202 | 3321 | static char *srpt_get_fabric_wwn(struct se_portal_group *tpg) |
|---|
| 3203 | 3322 | { |
|---|
| 3204 | | - struct srpt_port *sport = srpt_tpg_to_sport(tpg); |
|---|
| 3323 | + struct srpt_tpg *stpg = container_of(tpg, typeof(*stpg), tpg); |
|---|
| 3205 | 3324 | |
|---|
| 3206 | | - WARN_ON_ONCE(tpg != &sport->port_guid_tpg && |
|---|
| 3207 | | - tpg != &sport->port_gid_tpg); |
|---|
| 3208 | | - return tpg == &sport->port_guid_tpg ? sport->port_guid : |
|---|
| 3209 | | - sport->port_gid; |
|---|
| 3325 | + return stpg->sport_id->name; |
|---|
| 3210 | 3326 | } |
|---|
| 3211 | 3327 | |
|---|
| 3212 | 3328 | static u16 srpt_get_tag(struct se_portal_group *tpg) |
|---|
| .. | .. |
|---|
| 3224 | 3340 | struct srpt_send_ioctx *ioctx = container_of(se_cmd, |
|---|
| 3225 | 3341 | struct srpt_send_ioctx, cmd); |
|---|
| 3226 | 3342 | struct srpt_rdma_ch *ch = ioctx->ch; |
|---|
| 3227 | | - unsigned long flags; |
|---|
| 3343 | + struct srpt_recv_ioctx *recv_ioctx = ioctx->recv_ioctx; |
|---|
| 3228 | 3344 | |
|---|
| 3229 | 3345 | WARN_ON_ONCE(ioctx->state != SRPT_STATE_DONE && |
|---|
| 3230 | 3346 | !(ioctx->cmd.transport_state & CMD_T_ABORTED)); |
|---|
| 3347 | + |
|---|
| 3348 | + if (recv_ioctx) { |
|---|
| 3349 | + WARN_ON_ONCE(!list_empty(&recv_ioctx->wait_list)); |
|---|
| 3350 | + ioctx->recv_ioctx = NULL; |
|---|
| 3351 | + srpt_post_recv(ch->sport->sdev, ch, recv_ioctx); |
|---|
| 3352 | + } |
|---|
| 3231 | 3353 | |
|---|
| 3232 | 3354 | if (ioctx->n_rw_ctx) { |
|---|
| 3233 | 3355 | srpt_free_rw_ctxs(ch, ioctx); |
|---|
| 3234 | 3356 | ioctx->n_rw_ctx = 0; |
|---|
| 3235 | 3357 | } |
|---|
| 3236 | 3358 | |
|---|
| 3237 | | - spin_lock_irqsave(&ch->spinlock, flags); |
|---|
| 3238 | | - list_add(&ioctx->free_list, &ch->free_list); |
|---|
| 3239 | | - spin_unlock_irqrestore(&ch->spinlock, flags); |
|---|
| 3359 | + target_free_tag(se_cmd->se_sess, se_cmd); |
|---|
| 3240 | 3360 | } |
|---|
| 3241 | 3361 | |
|---|
| 3242 | 3362 | /** |
|---|
| .. | .. |
|---|
| 3614 | 3734 | struct se_portal_group *se_tpg = to_tpg(item); |
|---|
| 3615 | 3735 | struct srpt_port *sport = srpt_tpg_to_sport(se_tpg); |
|---|
| 3616 | 3736 | |
|---|
| 3617 | | - return snprintf(page, PAGE_SIZE, "%d\n", (sport->enabled) ? 1: 0); |
|---|
| 3737 | + return snprintf(page, PAGE_SIZE, "%d\n", sport->enabled); |
|---|
| 3618 | 3738 | } |
|---|
| 3619 | 3739 | |
|---|
| 3620 | 3740 | static ssize_t srpt_tpg_enable_store(struct config_item *item, |
|---|
| .. | .. |
|---|
| 3623 | 3743 | struct se_portal_group *se_tpg = to_tpg(item); |
|---|
| 3624 | 3744 | struct srpt_port *sport = srpt_tpg_to_sport(se_tpg); |
|---|
| 3625 | 3745 | unsigned long tmp; |
|---|
| 3626 | | - int ret; |
|---|
| 3746 | + int ret; |
|---|
| 3627 | 3747 | |
|---|
| 3628 | 3748 | ret = kstrtoul(page, 0, &tmp); |
|---|
| 3629 | 3749 | if (ret < 0) { |
|---|
| .. | .. |
|---|
| 3658 | 3778 | static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn, |
|---|
| 3659 | 3779 | const char *name) |
|---|
| 3660 | 3780 | { |
|---|
| 3661 | | - struct srpt_port *sport = wwn->priv; |
|---|
| 3662 | | - static struct se_portal_group *tpg; |
|---|
| 3663 | | - int res; |
|---|
| 3781 | + struct srpt_port_id *sport_id = srpt_wwn_to_sport_id(wwn); |
|---|
| 3782 | + struct srpt_tpg *stpg; |
|---|
| 3783 | + int res = -ENOMEM; |
|---|
| 3664 | 3784 | |
|---|
| 3665 | | - WARN_ON_ONCE(wwn != &sport->port_guid_wwn && |
|---|
| 3666 | | - wwn != &sport->port_gid_wwn); |
|---|
| 3667 | | - tpg = wwn == &sport->port_guid_wwn ? &sport->port_guid_tpg : |
|---|
| 3668 | | - &sport->port_gid_tpg; |
|---|
| 3669 | | - res = core_tpg_register(wwn, tpg, SCSI_PROTOCOL_SRP); |
|---|
| 3670 | | - if (res) |
|---|
| 3785 | + stpg = kzalloc(sizeof(*stpg), GFP_KERNEL); |
|---|
| 3786 | + if (!stpg) |
|---|
| 3671 | 3787 | return ERR_PTR(res); |
|---|
| 3788 | + stpg->sport_id = sport_id; |
|---|
| 3789 | + res = core_tpg_register(wwn, &stpg->tpg, SCSI_PROTOCOL_SRP); |
|---|
| 3790 | + if (res) { |
|---|
| 3791 | + kfree(stpg); |
|---|
| 3792 | + return ERR_PTR(res); |
|---|
| 3793 | + } |
|---|
| 3672 | 3794 | |
|---|
| 3673 | | - return tpg; |
|---|
| 3795 | + mutex_lock(&sport_id->mutex); |
|---|
| 3796 | + list_add_tail(&stpg->entry, &sport_id->tpg_list); |
|---|
| 3797 | + mutex_unlock(&sport_id->mutex); |
|---|
| 3798 | + |
|---|
| 3799 | + return &stpg->tpg; |
|---|
| 3674 | 3800 | } |
|---|
| 3675 | 3801 | |
|---|
| 3676 | 3802 | /** |
|---|
| .. | .. |
|---|
| 3679 | 3805 | */ |
|---|
| 3680 | 3806 | static void srpt_drop_tpg(struct se_portal_group *tpg) |
|---|
| 3681 | 3807 | { |
|---|
| 3808 | + struct srpt_tpg *stpg = container_of(tpg, typeof(*stpg), tpg); |
|---|
| 3809 | + struct srpt_port_id *sport_id = stpg->sport_id; |
|---|
| 3682 | 3810 | struct srpt_port *sport = srpt_tpg_to_sport(tpg); |
|---|
| 3811 | + |
|---|
| 3812 | + mutex_lock(&sport_id->mutex); |
|---|
| 3813 | + list_del(&stpg->entry); |
|---|
| 3814 | + mutex_unlock(&sport_id->mutex); |
|---|
| 3683 | 3815 | |
|---|
| 3684 | 3816 | sport->enabled = false; |
|---|
| 3685 | 3817 | core_tpg_deregister(tpg); |
|---|
| 3818 | + kfree(stpg); |
|---|
| 3686 | 3819 | } |
|---|
| 3687 | 3820 | |
|---|
| 3688 | 3821 | /** |
|---|
| .. | .. |
|---|
| 3695 | 3828 | struct config_group *group, |
|---|
| 3696 | 3829 | const char *name) |
|---|
| 3697 | 3830 | { |
|---|
| 3698 | | - return srpt_lookup_wwn(name) ? : ERR_PTR(-EINVAL); |
|---|
| 3831 | + struct port_and_port_id papi = srpt_lookup_port(name); |
|---|
| 3832 | + struct srpt_port *sport = papi.sport; |
|---|
| 3833 | + struct srpt_port_id *port_id; |
|---|
| 3834 | + |
|---|
| 3835 | + if (!papi.port_id) |
|---|
| 3836 | + return ERR_PTR(-EINVAL); |
|---|
| 3837 | + if (*papi.port_id) { |
|---|
| 3838 | + /* Attempt to create a directory that already exists. */ |
|---|
| 3839 | + WARN_ON_ONCE(true); |
|---|
| 3840 | + return &(*papi.port_id)->wwn; |
|---|
| 3841 | + } |
|---|
| 3842 | + port_id = kzalloc(sizeof(*port_id), GFP_KERNEL); |
|---|
| 3843 | + if (!port_id) { |
|---|
| 3844 | + srpt_sdev_put(sport->sdev); |
|---|
| 3845 | + return ERR_PTR(-ENOMEM); |
|---|
| 3846 | + } |
|---|
| 3847 | + mutex_init(&port_id->mutex); |
|---|
| 3848 | + INIT_LIST_HEAD(&port_id->tpg_list); |
|---|
| 3849 | + port_id->wwn.priv = sport; |
|---|
| 3850 | + memcpy(port_id->name, port_id == sport->guid_id ? sport->guid_name : |
|---|
| 3851 | + sport->gid_name, ARRAY_SIZE(port_id->name)); |
|---|
| 3852 | + |
|---|
| 3853 | + *papi.port_id = port_id; |
|---|
| 3854 | + |
|---|
| 3855 | + return &port_id->wwn; |
|---|
| 3699 | 3856 | } |
|---|
| 3700 | 3857 | |
|---|
| 3701 | 3858 | /** |
|---|
| .. | .. |
|---|
| 3704 | 3861 | */ |
|---|
| 3705 | 3862 | static void srpt_drop_tport(struct se_wwn *wwn) |
|---|
| 3706 | 3863 | { |
|---|
| 3864 | + struct srpt_port_id *port_id = container_of(wwn, typeof(*port_id), wwn); |
|---|
| 3865 | + struct srpt_port *sport = wwn->priv; |
|---|
| 3866 | + |
|---|
| 3867 | + if (sport->guid_id == port_id) |
|---|
| 3868 | + sport->guid_id = NULL; |
|---|
| 3869 | + else if (sport->gid_id == port_id) |
|---|
| 3870 | + sport->gid_id = NULL; |
|---|
| 3871 | + else |
|---|
| 3872 | + WARN_ON_ONCE(true); |
|---|
| 3873 | + |
|---|
| 3874 | + srpt_sdev_put(sport->sdev); |
|---|
| 3875 | + kfree(port_id); |
|---|
| 3707 | 3876 | } |
|---|
| 3708 | 3877 | |
|---|
| 3709 | 3878 | static ssize_t srpt_wwn_version_show(struct config_item *item, char *buf) |
|---|
| 3710 | 3879 | { |
|---|
| 3711 | | - return scnprintf(buf, PAGE_SIZE, "%s\n", DRV_VERSION); |
|---|
| 3880 | + return scnprintf(buf, PAGE_SIZE, "\n"); |
|---|
| 3712 | 3881 | } |
|---|
| 3713 | 3882 | |
|---|
| 3714 | 3883 | CONFIGFS_ATTR_RO(srpt_wwn_, version); |
|---|
| .. | .. |
|---|
| 3720 | 3889 | |
|---|
| 3721 | 3890 | static const struct target_core_fabric_ops srpt_template = { |
|---|
| 3722 | 3891 | .module = THIS_MODULE, |
|---|
| 3723 | | - .name = "srpt", |
|---|
| 3724 | | - .get_fabric_name = srpt_get_fabric_name, |
|---|
| 3892 | + .fabric_name = "srpt", |
|---|
| 3725 | 3893 | .tpg_get_wwn = srpt_get_fabric_wwn, |
|---|
| 3726 | 3894 | .tpg_get_tag = srpt_get_tag, |
|---|
| 3727 | 3895 | .tpg_check_demo_mode = srpt_check_false, |
|---|
| .. | .. |
|---|
| 3735 | 3903 | .sess_get_index = srpt_sess_get_index, |
|---|
| 3736 | 3904 | .sess_get_initiator_sid = NULL, |
|---|
| 3737 | 3905 | .write_pending = srpt_write_pending, |
|---|
| 3738 | | - .write_pending_status = srpt_write_pending_status, |
|---|
| 3739 | 3906 | .set_default_node_attributes = srpt_set_default_node_attrs, |
|---|
| 3740 | 3907 | .get_cmd_state = srpt_get_tcm_cmd_state, |
|---|
| 3741 | 3908 | .queue_data_in = srpt_queue_data_in, |
|---|
| .. | .. |
|---|
| 3772 | 3939 | |
|---|
| 3773 | 3940 | ret = -EINVAL; |
|---|
| 3774 | 3941 | if (srp_max_req_size < MIN_MAX_REQ_SIZE) { |
|---|
| 3775 | | - pr_err("invalid value %d for kernel module parameter" |
|---|
| 3776 | | - " srp_max_req_size -- must be at least %d.\n", |
|---|
| 3942 | + pr_err("invalid value %d for kernel module parameter srp_max_req_size -- must be at least %d.\n", |
|---|
| 3777 | 3943 | srp_max_req_size, MIN_MAX_REQ_SIZE); |
|---|
| 3778 | 3944 | goto out; |
|---|
| 3779 | 3945 | } |
|---|
| 3780 | 3946 | |
|---|
| 3781 | 3947 | if (srpt_srq_size < MIN_SRPT_SRQ_SIZE |
|---|
| 3782 | 3948 | || srpt_srq_size > MAX_SRPT_SRQ_SIZE) { |
|---|
| 3783 | | - pr_err("invalid value %d for kernel module parameter" |
|---|
| 3784 | | - " srpt_srq_size -- must be in the range [%d..%d].\n", |
|---|
| 3949 | + pr_err("invalid value %d for kernel module parameter srpt_srq_size -- must be in the range [%d..%d].\n", |
|---|
| 3785 | 3950 | srpt_srq_size, MIN_SRPT_SRQ_SIZE, MAX_SRPT_SRQ_SIZE); |
|---|
| 3786 | 3951 | goto out; |
|---|
| 3787 | 3952 | } |
|---|