diff options
Diffstat (limited to 'drivers/infiniband/ulp/iser/iser_verbs.c')
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_verbs.c | 134 |
1 files changed, 85 insertions, 49 deletions
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 7092503a10e3..89b956044060 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
@@ -129,13 +129,23 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) | |||
129 | { | 129 | { |
130 | struct iser_device *device; | 130 | struct iser_device *device; |
131 | struct ib_qp_init_attr init_attr; | 131 | struct ib_qp_init_attr init_attr; |
132 | int ret; | 132 | int ret = -ENOMEM; |
133 | struct ib_fmr_pool_param params; | 133 | struct ib_fmr_pool_param params; |
134 | 134 | ||
135 | BUG_ON(ib_conn->device == NULL); | 135 | BUG_ON(ib_conn->device == NULL); |
136 | 136 | ||
137 | device = ib_conn->device; | 137 | device = ib_conn->device; |
138 | 138 | ||
139 | ib_conn->login_buf = kmalloc(ISER_RX_LOGIN_SIZE, GFP_KERNEL); | ||
140 | if (!ib_conn->login_buf) { | ||
141 | goto alloc_err; | ||
142 | ret = -ENOMEM; | ||
143 | } | ||
144 | |||
145 | ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device, | ||
146 | (void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE, | ||
147 | DMA_FROM_DEVICE); | ||
148 | |||
139 | ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) + | 149 | ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) + |
140 | (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)), | 150 | (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)), |
141 | GFP_KERNEL); | 151 | GFP_KERNEL); |
@@ -174,7 +184,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) | |||
174 | init_attr.cap.max_send_wr = ISER_QP_MAX_REQ_DTOS; | 184 | init_attr.cap.max_send_wr = ISER_QP_MAX_REQ_DTOS; |
175 | init_attr.cap.max_recv_wr = ISER_QP_MAX_RECV_DTOS; | 185 | init_attr.cap.max_recv_wr = ISER_QP_MAX_RECV_DTOS; |
176 | init_attr.cap.max_send_sge = MAX_REGD_BUF_VECTOR_LEN; | 186 | init_attr.cap.max_send_sge = MAX_REGD_BUF_VECTOR_LEN; |
177 | init_attr.cap.max_recv_sge = 2; | 187 | init_attr.cap.max_recv_sge = 1; |
178 | init_attr.sq_sig_type = IB_SIGNAL_REQ_WR; | 188 | init_attr.sq_sig_type = IB_SIGNAL_REQ_WR; |
179 | init_attr.qp_type = IB_QPT_RC; | 189 | init_attr.qp_type = IB_QPT_RC; |
180 | 190 | ||
@@ -192,6 +202,7 @@ qp_err: | |||
192 | (void)ib_destroy_fmr_pool(ib_conn->fmr_pool); | 202 | (void)ib_destroy_fmr_pool(ib_conn->fmr_pool); |
193 | fmr_pool_err: | 203 | fmr_pool_err: |
194 | kfree(ib_conn->page_vec); | 204 | kfree(ib_conn->page_vec); |
205 | kfree(ib_conn->login_buf); | ||
195 | alloc_err: | 206 | alloc_err: |
196 | iser_err("unable to alloc mem or create resource, err %d\n", ret); | 207 | iser_err("unable to alloc mem or create resource, err %d\n", ret); |
197 | return ret; | 208 | return ret; |
@@ -314,7 +325,7 @@ static void iser_conn_release(struct iser_conn *ib_conn) | |||
314 | mutex_lock(&ig.connlist_mutex); | 325 | mutex_lock(&ig.connlist_mutex); |
315 | list_del(&ib_conn->conn_list); | 326 | list_del(&ib_conn->conn_list); |
316 | mutex_unlock(&ig.connlist_mutex); | 327 | mutex_unlock(&ig.connlist_mutex); |
317 | 328 | iser_free_rx_descriptors(ib_conn); | |
318 | iser_free_ib_conn_res(ib_conn); | 329 | iser_free_ib_conn_res(ib_conn); |
319 | ib_conn->device = NULL; | 330 | ib_conn->device = NULL; |
320 | /* on EVENT_ADDR_ERROR there's no device yet for this conn */ | 331 | /* on EVENT_ADDR_ERROR there's no device yet for this conn */ |
@@ -625,6 +636,60 @@ void iser_unreg_mem(struct iser_mem_reg *reg) | |||
625 | reg->mem_h = NULL; | 636 | reg->mem_h = NULL; |
626 | } | 637 | } |
627 | 638 | ||
639 | int iser_post_recvl(struct iser_conn *ib_conn) | ||
640 | { | ||
641 | struct ib_recv_wr rx_wr, *rx_wr_failed; | ||
642 | struct ib_sge sge; | ||
643 | int ib_ret; | ||
644 | |||
645 | sge.addr = ib_conn->login_dma; | ||
646 | sge.length = ISER_RX_LOGIN_SIZE; | ||
647 | sge.lkey = ib_conn->device->mr->lkey; | ||
648 | |||
649 | rx_wr.wr_id = (unsigned long)ib_conn->login_buf; | ||
650 | rx_wr.sg_list = &sge; | ||
651 | rx_wr.num_sge = 1; | ||
652 | rx_wr.next = NULL; | ||
653 | |||
654 | atomic_inc(&ib_conn->post_recv_buf_count); | ||
655 | ib_ret = ib_post_recv(ib_conn->qp, &rx_wr, &rx_wr_failed); | ||
656 | if (ib_ret) { | ||
657 | iser_err("ib_post_recv failed ret=%d\n", ib_ret); | ||
658 | atomic_dec(&ib_conn->post_recv_buf_count); | ||
659 | } | ||
660 | return ib_ret; | ||
661 | } | ||
662 | |||
663 | int iser_post_recvm(struct iser_conn *ib_conn, int count) | ||
664 | { | ||
665 | struct ib_recv_wr *rx_wr, *rx_wr_failed; | ||
666 | int i, ib_ret; | ||
667 | unsigned int my_rx_head = ib_conn->rx_desc_head; | ||
668 | struct iser_rx_desc *rx_desc; | ||
669 | |||
670 | for (rx_wr = ib_conn->rx_wr, i = 0; i < count; i++, rx_wr++) { | ||
671 | rx_desc = &ib_conn->rx_descs[my_rx_head]; | ||
672 | rx_wr->wr_id = (unsigned long)rx_desc; | ||
673 | rx_wr->sg_list = &rx_desc->rx_sg; | ||
674 | rx_wr->num_sge = 1; | ||
675 | rx_wr->next = rx_wr + 1; | ||
676 | my_rx_head = (my_rx_head + 1) & (ISER_QP_MAX_RECV_DTOS - 1); | ||
677 | } | ||
678 | |||
679 | rx_wr--; | ||
680 | rx_wr->next = NULL; /* mark end of work requests list */ | ||
681 | |||
682 | atomic_add(count, &ib_conn->post_recv_buf_count); | ||
683 | ib_ret = ib_post_recv(ib_conn->qp, ib_conn->rx_wr, &rx_wr_failed); | ||
684 | if (ib_ret) { | ||
685 | iser_err("ib_post_recv failed ret=%d\n", ib_ret); | ||
686 | atomic_sub(count, &ib_conn->post_recv_buf_count); | ||
687 | } else | ||
688 | ib_conn->rx_desc_head = my_rx_head; | ||
689 | return ib_ret; | ||
690 | } | ||
691 | |||
692 | |||
628 | /** | 693 | /** |
629 | * iser_dto_to_iov - builds IOV from a dto descriptor | 694 | * iser_dto_to_iov - builds IOV from a dto descriptor |
630 | */ | 695 | */ |
@@ -665,39 +730,6 @@ static void iser_dto_to_iov(struct iser_dto *dto, struct ib_sge *iov, int iov_le | |||
665 | } | 730 | } |
666 | } | 731 | } |
667 | 732 | ||
668 | /** | ||
669 | * iser_post_recv - Posts a receive buffer. | ||
670 | * | ||
671 | * returns 0 on success, -1 on failure | ||
672 | */ | ||
673 | int iser_post_recv(struct iser_desc *rx_desc) | ||
674 | { | ||
675 | int ib_ret, ret_val = 0; | ||
676 | struct ib_recv_wr recv_wr, *recv_wr_failed; | ||
677 | struct ib_sge iov[2]; | ||
678 | struct iser_conn *ib_conn; | ||
679 | struct iser_dto *recv_dto = &rx_desc->dto; | ||
680 | |||
681 | /* Retrieve conn */ | ||
682 | ib_conn = recv_dto->ib_conn; | ||
683 | |||
684 | iser_dto_to_iov(recv_dto, iov, 2); | ||
685 | |||
686 | recv_wr.next = NULL; | ||
687 | recv_wr.sg_list = iov; | ||
688 | recv_wr.num_sge = recv_dto->regd_vector_len; | ||
689 | recv_wr.wr_id = (unsigned long)rx_desc; | ||
690 | |||
691 | atomic_inc(&ib_conn->post_recv_buf_count); | ||
692 | ib_ret = ib_post_recv(ib_conn->qp, &recv_wr, &recv_wr_failed); | ||
693 | if (ib_ret) { | ||
694 | iser_err("ib_post_recv failed ret=%d\n", ib_ret); | ||
695 | atomic_dec(&ib_conn->post_recv_buf_count); | ||
696 | ret_val = -1; | ||
697 | } | ||
698 | |||
699 | return ret_val; | ||
700 | } | ||
701 | 733 | ||
702 | /** | 734 | /** |
703 | * iser_start_send - Initiate a Send DTO operation | 735 | * iser_start_send - Initiate a Send DTO operation |
@@ -737,18 +769,17 @@ int iser_post_send(struct iser_desc *tx_desc) | |||
737 | return ret_val; | 769 | return ret_val; |
738 | } | 770 | } |
739 | 771 | ||
740 | static void iser_handle_comp_error(struct iser_desc *desc) | 772 | static void iser_handle_comp_error(struct iser_desc *desc, |
773 | struct iser_conn *ib_conn) | ||
741 | { | 774 | { |
742 | struct iser_dto *dto = &desc->dto; | 775 | struct iser_rx_desc *rx = (struct iser_rx_desc *)desc; |
743 | struct iser_conn *ib_conn = dto->ib_conn; | 776 | struct iser_rx_desc *rx_first = ib_conn->rx_descs; |
744 | 777 | struct iser_rx_desc *rx_last = rx_first + (ISER_QP_MAX_RECV_DTOS - 1); | |
745 | iser_dto_buffs_release(dto); | ||
746 | 778 | ||
747 | if (desc->type == ISCSI_RX) { | 779 | if ((char *)desc == ib_conn->login_buf || |
748 | kfree(desc->data); | 780 | (rx_first <= rx && rx <= rx_last)) |
749 | kmem_cache_free(ig.desc_cache, desc); | ||
750 | atomic_dec(&ib_conn->post_recv_buf_count); | 781 | atomic_dec(&ib_conn->post_recv_buf_count); |
751 | } else { /* type is TX control/command/dataout */ | 782 | else { /* type is TX control/command/dataout */ |
752 | if (desc->type == ISCSI_TX_DATAOUT) | 783 | if (desc->type == ISCSI_TX_DATAOUT) |
753 | kmem_cache_free(ig.desc_cache, desc); | 784 | kmem_cache_free(ig.desc_cache, desc); |
754 | atomic_dec(&ib_conn->post_send_buf_count); | 785 | atomic_dec(&ib_conn->post_send_buf_count); |
@@ -780,20 +811,25 @@ static void iser_cq_tasklet_fn(unsigned long data) | |||
780 | struct ib_wc wc; | 811 | struct ib_wc wc; |
781 | struct iser_desc *desc; | 812 | struct iser_desc *desc; |
782 | unsigned long xfer_len; | 813 | unsigned long xfer_len; |
814 | struct iser_conn *ib_conn; | ||
783 | 815 | ||
784 | while (ib_poll_cq(cq, 1, &wc) == 1) { | 816 | while (ib_poll_cq(cq, 1, &wc) == 1) { |
785 | desc = (struct iser_desc *) (unsigned long) wc.wr_id; | 817 | desc = (struct iser_desc *) (unsigned long) wc.wr_id; |
786 | BUG_ON(desc == NULL); | 818 | BUG_ON(desc == NULL); |
819 | ib_conn = wc.qp->qp_context; | ||
787 | 820 | ||
788 | if (wc.status == IB_WC_SUCCESS) { | 821 | if (wc.status == IB_WC_SUCCESS) { |
789 | if (desc->type == ISCSI_RX) { | 822 | if (wc.opcode == IB_WC_RECV) { |
790 | xfer_len = (unsigned long)wc.byte_len; | 823 | xfer_len = (unsigned long)wc.byte_len; |
791 | iser_rcv_completion(desc, xfer_len); | 824 | iser_rcv_completion((struct iser_rx_desc *)desc, |
825 | xfer_len, ib_conn); | ||
792 | } else /* type == ISCSI_TX_CONTROL/SCSI_CMD/DOUT */ | 826 | } else /* type == ISCSI_TX_CONTROL/SCSI_CMD/DOUT */ |
793 | iser_snd_completion(desc); | 827 | iser_snd_completion(desc); |
794 | } else { | 828 | } else { |
795 | iser_err("comp w. error op %d status %d\n",desc->type,wc.status); | 829 | if (wc.status != IB_WC_WR_FLUSH_ERR) |
796 | iser_handle_comp_error(desc); | 830 | iser_err("id %llx status %d vend_err %x\n", |
831 | wc.wr_id, wc.status, wc.vendor_err); | ||
832 | iser_handle_comp_error(desc, ib_conn); | ||
797 | } | 833 | } |
798 | } | 834 | } |
799 | /* #warning "it is assumed here that arming CQ only once its empty" * | 835 | /* #warning "it is assumed here that arming CQ only once its empty" * |