| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1 | /******************************************************************************* | 
|  | 2 | * This file contains iSCSI extentions for RDMA (iSER) Verbs | 
|  | 3 | * | 
| Nicholas Bellinger | 4c76251 | 2013-09-05 15:29:12 -0700 | [diff] [blame] | 4 | * (c) Copyright 2013 Datera, Inc. | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 5 | * | 
|  | 6 | * Nicholas A. Bellinger <nab@linux-iscsi.org> | 
|  | 7 | * | 
|  | 8 | * This program is free software; you can redistribute it and/or modify | 
|  | 9 | * it under the terms of the GNU General Public License as published by | 
|  | 10 | * the Free Software Foundation; either version 2 of the License, or | 
|  | 11 | * (at your option) any later version. | 
|  | 12 | * | 
|  | 13 | * This program is distributed in the hope that it will be useful, | 
|  | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 16 | * GNU General Public License for more details. | 
|  | 17 | ****************************************************************************/ | 
|  | 18 |  | 
|  | 19 | #include <linux/string.h> | 
|  | 20 | #include <linux/module.h> | 
|  | 21 | #include <linux/scatterlist.h> | 
|  | 22 | #include <linux/socket.h> | 
|  | 23 | #include <linux/in.h> | 
|  | 24 | #include <linux/in6.h> | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 25 | #include <linux/llist.h> | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 26 | #include <rdma/ib_verbs.h> | 
|  | 27 | #include <rdma/rdma_cm.h> | 
|  | 28 | #include <target/target_core_base.h> | 
|  | 29 | #include <target/target_core_fabric.h> | 
|  | 30 | #include <target/iscsi/iscsi_transport.h> | 
|  | 31 |  | 
|  | 32 | #include "isert_proto.h" | 
|  | 33 | #include "ib_isert.h" | 
|  | 34 |  | 
|  | 35 | #define	ISERT_MAX_CONN		8 | 
|  | 36 | #define ISER_MAX_RX_CQ_LEN	(ISERT_QP_MAX_RECV_DTOS * ISERT_MAX_CONN) | 
|  | 37 | #define ISER_MAX_TX_CQ_LEN	(ISERT_QP_MAX_REQ_DTOS  * ISERT_MAX_CONN) | 
|  | 38 |  | 
|  | 39 | static DEFINE_MUTEX(device_list_mutex); | 
|  | 40 | static LIST_HEAD(device_list); | 
|  | 41 | static struct workqueue_struct *isert_rx_wq; | 
|  | 42 | static struct workqueue_struct *isert_comp_wq; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 43 |  | 
|  | 44 | static void | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 45 | isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); | 
|  | 46 | static int | 
|  | 47 | isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
|  | 48 | struct isert_rdma_wr *wr); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 49 | static void | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 50 | isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 51 | static int | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 52 | isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
|  | 53 | struct isert_rdma_wr *wr); | 
| Sagi Grimberg | f93f3a7 | 2014-02-19 17:50:24 +0200 | [diff] [blame^] | 54 | static int | 
|  | 55 | isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd); | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 56 |  | 
|  | 57 | static void | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 58 | isert_qp_event_callback(struct ib_event *e, void *context) | 
|  | 59 | { | 
|  | 60 | struct isert_conn *isert_conn = (struct isert_conn *)context; | 
|  | 61 |  | 
|  | 62 | pr_err("isert_qp_event_callback event: %d\n", e->event); | 
|  | 63 | switch (e->event) { | 
|  | 64 | case IB_EVENT_COMM_EST: | 
|  | 65 | rdma_notify(isert_conn->conn_cm_id, IB_EVENT_COMM_EST); | 
|  | 66 | break; | 
|  | 67 | case IB_EVENT_QP_LAST_WQE_REACHED: | 
|  | 68 | pr_warn("Reached TX IB_EVENT_QP_LAST_WQE_REACHED:\n"); | 
|  | 69 | break; | 
|  | 70 | default: | 
|  | 71 | break; | 
|  | 72 | } | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | static int | 
|  | 76 | isert_query_device(struct ib_device *ib_dev, struct ib_device_attr *devattr) | 
|  | 77 | { | 
|  | 78 | int ret; | 
|  | 79 |  | 
|  | 80 | ret = ib_query_device(ib_dev, devattr); | 
|  | 81 | if (ret) { | 
|  | 82 | pr_err("ib_query_device() failed: %d\n", ret); | 
|  | 83 | return ret; | 
|  | 84 | } | 
|  | 85 | pr_debug("devattr->max_sge: %d\n", devattr->max_sge); | 
|  | 86 | pr_debug("devattr->max_sge_rd: %d\n", devattr->max_sge_rd); | 
|  | 87 |  | 
|  | 88 | return 0; | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | static int | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 92 | isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id, | 
|  | 93 | u8 protection) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 94 | { | 
|  | 95 | struct isert_device *device = isert_conn->conn_device; | 
|  | 96 | struct ib_qp_init_attr attr; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 97 | int ret, index, min_index = 0; | 
|  | 98 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 99 | mutex_lock(&device_list_mutex); | 
|  | 100 | for (index = 0; index < device->cqs_used; index++) | 
|  | 101 | if (device->cq_active_qps[index] < | 
|  | 102 | device->cq_active_qps[min_index]) | 
|  | 103 | min_index = index; | 
|  | 104 | device->cq_active_qps[min_index]++; | 
|  | 105 | pr_debug("isert_conn_setup_qp: Using min_index: %d\n", min_index); | 
|  | 106 | mutex_unlock(&device_list_mutex); | 
|  | 107 |  | 
|  | 108 | memset(&attr, 0, sizeof(struct ib_qp_init_attr)); | 
|  | 109 | attr.event_handler = isert_qp_event_callback; | 
|  | 110 | attr.qp_context = isert_conn; | 
|  | 111 | attr.send_cq = device->dev_tx_cq[min_index]; | 
|  | 112 | attr.recv_cq = device->dev_rx_cq[min_index]; | 
|  | 113 | attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS; | 
|  | 114 | attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS; | 
|  | 115 | /* | 
|  | 116 | * FIXME: Use devattr.max_sge - 2 for max_send_sge as | 
|  | 117 | * work-around for RDMA_READ.. | 
|  | 118 | */ | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 119 | attr.cap.max_send_sge = device->dev_attr.max_sge - 2; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 120 | isert_conn->max_sge = attr.cap.max_send_sge; | 
|  | 121 |  | 
|  | 122 | attr.cap.max_recv_sge = 1; | 
|  | 123 | attr.sq_sig_type = IB_SIGNAL_REQ_WR; | 
|  | 124 | attr.qp_type = IB_QPT_RC; | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 125 | if (protection) | 
|  | 126 | attr.create_flags |= IB_QP_CREATE_SIGNATURE_EN; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 127 |  | 
|  | 128 | pr_debug("isert_conn_setup_qp cma_id->device: %p\n", | 
|  | 129 | cma_id->device); | 
|  | 130 | pr_debug("isert_conn_setup_qp conn_pd->device: %p\n", | 
|  | 131 | isert_conn->conn_pd->device); | 
|  | 132 |  | 
|  | 133 | ret = rdma_create_qp(cma_id, isert_conn->conn_pd, &attr); | 
|  | 134 | if (ret) { | 
|  | 135 | pr_err("rdma_create_qp failed for cma_id %d\n", ret); | 
|  | 136 | return ret; | 
|  | 137 | } | 
|  | 138 | isert_conn->conn_qp = cma_id->qp; | 
|  | 139 | pr_debug("rdma_create_qp() returned success >>>>>>>>>>>>>>>>>>>>>>>>>.\n"); | 
|  | 140 |  | 
|  | 141 | return 0; | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 | static void | 
|  | 145 | isert_cq_event_callback(struct ib_event *e, void *context) | 
|  | 146 | { | 
|  | 147 | pr_debug("isert_cq_event_callback event: %d\n", e->event); | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | static int | 
|  | 151 | isert_alloc_rx_descriptors(struct isert_conn *isert_conn) | 
|  | 152 | { | 
|  | 153 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 154 | struct iser_rx_desc *rx_desc; | 
|  | 155 | struct ib_sge *rx_sg; | 
|  | 156 | u64 dma_addr; | 
|  | 157 | int i, j; | 
|  | 158 |  | 
|  | 159 | isert_conn->conn_rx_descs = kzalloc(ISERT_QP_MAX_RECV_DTOS * | 
|  | 160 | sizeof(struct iser_rx_desc), GFP_KERNEL); | 
|  | 161 | if (!isert_conn->conn_rx_descs) | 
|  | 162 | goto fail; | 
|  | 163 |  | 
|  | 164 | rx_desc = isert_conn->conn_rx_descs; | 
|  | 165 |  | 
|  | 166 | for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++)  { | 
|  | 167 | dma_addr = ib_dma_map_single(ib_dev, (void *)rx_desc, | 
|  | 168 | ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE); | 
|  | 169 | if (ib_dma_mapping_error(ib_dev, dma_addr)) | 
|  | 170 | goto dma_map_fail; | 
|  | 171 |  | 
|  | 172 | rx_desc->dma_addr = dma_addr; | 
|  | 173 |  | 
|  | 174 | rx_sg = &rx_desc->rx_sg; | 
|  | 175 | rx_sg->addr = rx_desc->dma_addr; | 
|  | 176 | rx_sg->length = ISER_RX_PAYLOAD_SIZE; | 
|  | 177 | rx_sg->lkey = isert_conn->conn_mr->lkey; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | isert_conn->conn_rx_desc_head = 0; | 
|  | 181 | return 0; | 
|  | 182 |  | 
|  | 183 | dma_map_fail: | 
|  | 184 | rx_desc = isert_conn->conn_rx_descs; | 
|  | 185 | for (j = 0; j < i; j++, rx_desc++) { | 
|  | 186 | ib_dma_unmap_single(ib_dev, rx_desc->dma_addr, | 
|  | 187 | ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE); | 
|  | 188 | } | 
|  | 189 | kfree(isert_conn->conn_rx_descs); | 
|  | 190 | isert_conn->conn_rx_descs = NULL; | 
|  | 191 | fail: | 
|  | 192 | return -ENOMEM; | 
|  | 193 | } | 
|  | 194 |  | 
|  | 195 | static void | 
|  | 196 | isert_free_rx_descriptors(struct isert_conn *isert_conn) | 
|  | 197 | { | 
|  | 198 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 199 | struct iser_rx_desc *rx_desc; | 
|  | 200 | int i; | 
|  | 201 |  | 
|  | 202 | if (!isert_conn->conn_rx_descs) | 
|  | 203 | return; | 
|  | 204 |  | 
|  | 205 | rx_desc = isert_conn->conn_rx_descs; | 
|  | 206 | for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++)  { | 
|  | 207 | ib_dma_unmap_single(ib_dev, rx_desc->dma_addr, | 
|  | 208 | ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE); | 
|  | 209 | } | 
|  | 210 |  | 
|  | 211 | kfree(isert_conn->conn_rx_descs); | 
|  | 212 | isert_conn->conn_rx_descs = NULL; | 
|  | 213 | } | 
|  | 214 |  | 
| Nicholas Bellinger | 2853c2b | 2013-12-11 16:20:13 -0800 | [diff] [blame] | 215 | static void isert_cq_tx_work(struct work_struct *); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 216 | static void isert_cq_tx_callback(struct ib_cq *, void *); | 
| Nicholas Bellinger | 2853c2b | 2013-12-11 16:20:13 -0800 | [diff] [blame] | 217 | static void isert_cq_rx_work(struct work_struct *); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 218 | static void isert_cq_rx_callback(struct ib_cq *, void *); | 
|  | 219 |  | 
|  | 220 | static int | 
|  | 221 | isert_create_device_ib_res(struct isert_device *device) | 
|  | 222 | { | 
|  | 223 | struct ib_device *ib_dev = device->ib_device; | 
|  | 224 | struct isert_cq_desc *cq_desc; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 225 | struct ib_device_attr *dev_attr; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 226 | int ret = 0, i, j; | 
|  | 227 |  | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 228 | dev_attr = &device->dev_attr; | 
|  | 229 | ret = isert_query_device(ib_dev, dev_attr); | 
|  | 230 | if (ret) | 
|  | 231 | return ret; | 
|  | 232 |  | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 233 | /* asign function handlers */ | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 234 | if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) { | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 235 | device->use_fastreg = 1; | 
|  | 236 | device->reg_rdma_mem = isert_reg_rdma; | 
|  | 237 | device->unreg_rdma_mem = isert_unreg_rdma; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 238 | } else { | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 239 | device->use_fastreg = 0; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 240 | device->reg_rdma_mem = isert_map_rdma; | 
|  | 241 | device->unreg_rdma_mem = isert_unmap_cmd; | 
|  | 242 | } | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 243 |  | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 244 | /* Check signature cap */ | 
|  | 245 | device->pi_capable = dev_attr->device_cap_flags & | 
|  | 246 | IB_DEVICE_SIGNATURE_HANDOVER ? true : false; | 
|  | 247 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 248 | device->cqs_used = min_t(int, num_online_cpus(), | 
|  | 249 | device->ib_device->num_comp_vectors); | 
|  | 250 | device->cqs_used = min(ISERT_MAX_CQ, device->cqs_used); | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 251 | pr_debug("Using %d CQs, device %s supports %d vectors support " | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 252 | "Fast registration %d pi_capable %d\n", | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 253 | device->cqs_used, device->ib_device->name, | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 254 | device->ib_device->num_comp_vectors, device->use_fastreg, | 
|  | 255 | device->pi_capable); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 256 | device->cq_desc = kzalloc(sizeof(struct isert_cq_desc) * | 
|  | 257 | device->cqs_used, GFP_KERNEL); | 
|  | 258 | if (!device->cq_desc) { | 
|  | 259 | pr_err("Unable to allocate device->cq_desc\n"); | 
|  | 260 | return -ENOMEM; | 
|  | 261 | } | 
|  | 262 | cq_desc = device->cq_desc; | 
|  | 263 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 264 | for (i = 0; i < device->cqs_used; i++) { | 
|  | 265 | cq_desc[i].device = device; | 
|  | 266 | cq_desc[i].cq_index = i; | 
|  | 267 |  | 
| Nicholas Bellinger | 2853c2b | 2013-12-11 16:20:13 -0800 | [diff] [blame] | 268 | INIT_WORK(&cq_desc[i].cq_rx_work, isert_cq_rx_work); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 269 | device->dev_rx_cq[i] = ib_create_cq(device->ib_device, | 
|  | 270 | isert_cq_rx_callback, | 
|  | 271 | isert_cq_event_callback, | 
|  | 272 | (void *)&cq_desc[i], | 
|  | 273 | ISER_MAX_RX_CQ_LEN, i); | 
| Wei Yongjun | 94a7111 | 2013-10-29 09:56:34 +0800 | [diff] [blame] | 274 | if (IS_ERR(device->dev_rx_cq[i])) { | 
|  | 275 | ret = PTR_ERR(device->dev_rx_cq[i]); | 
|  | 276 | device->dev_rx_cq[i] = NULL; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 277 | goto out_cq; | 
| Wei Yongjun | 94a7111 | 2013-10-29 09:56:34 +0800 | [diff] [blame] | 278 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 279 |  | 
| Nicholas Bellinger | 2853c2b | 2013-12-11 16:20:13 -0800 | [diff] [blame] | 280 | INIT_WORK(&cq_desc[i].cq_tx_work, isert_cq_tx_work); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 281 | device->dev_tx_cq[i] = ib_create_cq(device->ib_device, | 
|  | 282 | isert_cq_tx_callback, | 
|  | 283 | isert_cq_event_callback, | 
|  | 284 | (void *)&cq_desc[i], | 
|  | 285 | ISER_MAX_TX_CQ_LEN, i); | 
| Wei Yongjun | 94a7111 | 2013-10-29 09:56:34 +0800 | [diff] [blame] | 286 | if (IS_ERR(device->dev_tx_cq[i])) { | 
|  | 287 | ret = PTR_ERR(device->dev_tx_cq[i]); | 
|  | 288 | device->dev_tx_cq[i] = NULL; | 
|  | 289 | goto out_cq; | 
|  | 290 | } | 
|  | 291 |  | 
|  | 292 | ret = ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP); | 
|  | 293 | if (ret) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 294 | goto out_cq; | 
|  | 295 |  | 
| Wei Yongjun | 94a7111 | 2013-10-29 09:56:34 +0800 | [diff] [blame] | 296 | ret = ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP); | 
|  | 297 | if (ret) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 298 | goto out_cq; | 
|  | 299 | } | 
|  | 300 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 301 | return 0; | 
|  | 302 |  | 
|  | 303 | out_cq: | 
|  | 304 | for (j = 0; j < i; j++) { | 
|  | 305 | cq_desc = &device->cq_desc[j]; | 
|  | 306 |  | 
|  | 307 | if (device->dev_rx_cq[j]) { | 
|  | 308 | cancel_work_sync(&cq_desc->cq_rx_work); | 
|  | 309 | ib_destroy_cq(device->dev_rx_cq[j]); | 
|  | 310 | } | 
|  | 311 | if (device->dev_tx_cq[j]) { | 
|  | 312 | cancel_work_sync(&cq_desc->cq_tx_work); | 
|  | 313 | ib_destroy_cq(device->dev_tx_cq[j]); | 
|  | 314 | } | 
|  | 315 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 316 | kfree(device->cq_desc); | 
|  | 317 |  | 
|  | 318 | return ret; | 
|  | 319 | } | 
|  | 320 |  | 
|  | 321 | static void | 
|  | 322 | isert_free_device_ib_res(struct isert_device *device) | 
|  | 323 | { | 
|  | 324 | struct isert_cq_desc *cq_desc; | 
|  | 325 | int i; | 
|  | 326 |  | 
|  | 327 | for (i = 0; i < device->cqs_used; i++) { | 
|  | 328 | cq_desc = &device->cq_desc[i]; | 
|  | 329 |  | 
|  | 330 | cancel_work_sync(&cq_desc->cq_rx_work); | 
|  | 331 | cancel_work_sync(&cq_desc->cq_tx_work); | 
|  | 332 | ib_destroy_cq(device->dev_rx_cq[i]); | 
|  | 333 | ib_destroy_cq(device->dev_tx_cq[i]); | 
|  | 334 | device->dev_rx_cq[i] = NULL; | 
|  | 335 | device->dev_tx_cq[i] = NULL; | 
|  | 336 | } | 
|  | 337 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 338 | kfree(device->cq_desc); | 
|  | 339 | } | 
|  | 340 |  | 
|  | 341 | static void | 
|  | 342 | isert_device_try_release(struct isert_device *device) | 
|  | 343 | { | 
|  | 344 | mutex_lock(&device_list_mutex); | 
|  | 345 | device->refcount--; | 
|  | 346 | if (!device->refcount) { | 
|  | 347 | isert_free_device_ib_res(device); | 
|  | 348 | list_del(&device->dev_node); | 
|  | 349 | kfree(device); | 
|  | 350 | } | 
|  | 351 | mutex_unlock(&device_list_mutex); | 
|  | 352 | } | 
|  | 353 |  | 
|  | 354 | static struct isert_device * | 
|  | 355 | isert_device_find_by_ib_dev(struct rdma_cm_id *cma_id) | 
|  | 356 | { | 
|  | 357 | struct isert_device *device; | 
|  | 358 | int ret; | 
|  | 359 |  | 
|  | 360 | mutex_lock(&device_list_mutex); | 
|  | 361 | list_for_each_entry(device, &device_list, dev_node) { | 
|  | 362 | if (device->ib_device->node_guid == cma_id->device->node_guid) { | 
|  | 363 | device->refcount++; | 
|  | 364 | mutex_unlock(&device_list_mutex); | 
|  | 365 | return device; | 
|  | 366 | } | 
|  | 367 | } | 
|  | 368 |  | 
|  | 369 | device = kzalloc(sizeof(struct isert_device), GFP_KERNEL); | 
|  | 370 | if (!device) { | 
|  | 371 | mutex_unlock(&device_list_mutex); | 
|  | 372 | return ERR_PTR(-ENOMEM); | 
|  | 373 | } | 
|  | 374 |  | 
|  | 375 | INIT_LIST_HEAD(&device->dev_node); | 
|  | 376 |  | 
|  | 377 | device->ib_device = cma_id->device; | 
|  | 378 | ret = isert_create_device_ib_res(device); | 
|  | 379 | if (ret) { | 
|  | 380 | kfree(device); | 
|  | 381 | mutex_unlock(&device_list_mutex); | 
|  | 382 | return ERR_PTR(ret); | 
|  | 383 | } | 
|  | 384 |  | 
|  | 385 | device->refcount++; | 
|  | 386 | list_add_tail(&device->dev_node, &device_list); | 
|  | 387 | mutex_unlock(&device_list_mutex); | 
|  | 388 |  | 
|  | 389 | return device; | 
|  | 390 | } | 
|  | 391 |  | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 392 | static void | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 393 | isert_conn_free_fastreg_pool(struct isert_conn *isert_conn) | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 394 | { | 
|  | 395 | struct fast_reg_descriptor *fr_desc, *tmp; | 
|  | 396 | int i = 0; | 
|  | 397 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 398 | if (list_empty(&isert_conn->conn_fr_pool)) | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 399 | return; | 
|  | 400 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 401 | pr_debug("Freeing conn %p fastreg pool", isert_conn); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 402 |  | 
|  | 403 | list_for_each_entry_safe(fr_desc, tmp, | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 404 | &isert_conn->conn_fr_pool, list) { | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 405 | list_del(&fr_desc->list); | 
|  | 406 | ib_free_fast_reg_page_list(fr_desc->data_frpl); | 
|  | 407 | ib_dereg_mr(fr_desc->data_mr); | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 408 | if (fr_desc->pi_ctx) { | 
|  | 409 | ib_free_fast_reg_page_list(fr_desc->pi_ctx->prot_frpl); | 
|  | 410 | ib_dereg_mr(fr_desc->pi_ctx->prot_mr); | 
|  | 411 | ib_destroy_mr(fr_desc->pi_ctx->sig_mr); | 
|  | 412 | kfree(fr_desc->pi_ctx); | 
|  | 413 | } | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 414 | kfree(fr_desc); | 
|  | 415 | ++i; | 
|  | 416 | } | 
|  | 417 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 418 | if (i < isert_conn->conn_fr_pool_size) | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 419 | pr_warn("Pool still has %d regions registered\n", | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 420 | isert_conn->conn_fr_pool_size - i); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 421 | } | 
|  | 422 |  | 
|  | 423 | static int | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 424 | isert_create_fr_desc(struct ib_device *ib_device, struct ib_pd *pd, | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 425 | struct fast_reg_descriptor *fr_desc, u8 protection) | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 426 | { | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 427 | int ret; | 
|  | 428 |  | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 429 | fr_desc->data_frpl = ib_alloc_fast_reg_page_list(ib_device, | 
|  | 430 | ISCSI_ISER_SG_TABLESIZE); | 
|  | 431 | if (IS_ERR(fr_desc->data_frpl)) { | 
|  | 432 | pr_err("Failed to allocate data frpl err=%ld\n", | 
|  | 433 | PTR_ERR(fr_desc->data_frpl)); | 
|  | 434 | return PTR_ERR(fr_desc->data_frpl); | 
|  | 435 | } | 
|  | 436 |  | 
|  | 437 | fr_desc->data_mr = ib_alloc_fast_reg_mr(pd, ISCSI_ISER_SG_TABLESIZE); | 
|  | 438 | if (IS_ERR(fr_desc->data_mr)) { | 
|  | 439 | pr_err("Failed to allocate data frmr err=%ld\n", | 
|  | 440 | PTR_ERR(fr_desc->data_mr)); | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 441 | ret = PTR_ERR(fr_desc->data_mr); | 
|  | 442 | goto err_data_frpl; | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 443 | } | 
|  | 444 | pr_debug("Create fr_desc %p page_list %p\n", | 
|  | 445 | fr_desc, fr_desc->data_frpl->page_list); | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 446 | fr_desc->ind |= ISERT_DATA_KEY_VALID; | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 447 |  | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 448 | if (protection) { | 
|  | 449 | struct ib_mr_init_attr mr_init_attr = {0}; | 
|  | 450 | struct pi_context *pi_ctx; | 
|  | 451 |  | 
|  | 452 | fr_desc->pi_ctx = kzalloc(sizeof(*fr_desc->pi_ctx), GFP_KERNEL); | 
|  | 453 | if (!fr_desc->pi_ctx) { | 
|  | 454 | pr_err("Failed to allocate pi context\n"); | 
|  | 455 | ret = -ENOMEM; | 
|  | 456 | goto err_data_mr; | 
|  | 457 | } | 
|  | 458 | pi_ctx = fr_desc->pi_ctx; | 
|  | 459 |  | 
|  | 460 | pi_ctx->prot_frpl = ib_alloc_fast_reg_page_list(ib_device, | 
|  | 461 | ISCSI_ISER_SG_TABLESIZE); | 
|  | 462 | if (IS_ERR(pi_ctx->prot_frpl)) { | 
|  | 463 | pr_err("Failed to allocate prot frpl err=%ld\n", | 
|  | 464 | PTR_ERR(pi_ctx->prot_frpl)); | 
|  | 465 | ret = PTR_ERR(pi_ctx->prot_frpl); | 
|  | 466 | goto err_pi_ctx; | 
|  | 467 | } | 
|  | 468 |  | 
|  | 469 | pi_ctx->prot_mr = ib_alloc_fast_reg_mr(pd, ISCSI_ISER_SG_TABLESIZE); | 
|  | 470 | if (IS_ERR(pi_ctx->prot_mr)) { | 
|  | 471 | pr_err("Failed to allocate prot frmr err=%ld\n", | 
|  | 472 | PTR_ERR(pi_ctx->prot_mr)); | 
|  | 473 | ret = PTR_ERR(pi_ctx->prot_mr); | 
|  | 474 | goto err_prot_frpl; | 
|  | 475 | } | 
|  | 476 | fr_desc->ind |= ISERT_PROT_KEY_VALID; | 
|  | 477 |  | 
|  | 478 | mr_init_attr.max_reg_descriptors = 2; | 
|  | 479 | mr_init_attr.flags |= IB_MR_SIGNATURE_EN; | 
|  | 480 | pi_ctx->sig_mr = ib_create_mr(pd, &mr_init_attr); | 
|  | 481 | if (IS_ERR(pi_ctx->sig_mr)) { | 
|  | 482 | pr_err("Failed to allocate signature enabled mr err=%ld\n", | 
|  | 483 | PTR_ERR(pi_ctx->sig_mr)); | 
|  | 484 | ret = PTR_ERR(pi_ctx->sig_mr); | 
|  | 485 | goto err_prot_mr; | 
|  | 486 | } | 
|  | 487 | fr_desc->ind |= ISERT_SIG_KEY_VALID; | 
|  | 488 | } | 
|  | 489 | fr_desc->ind &= ~ISERT_PROTECTED; | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 490 |  | 
|  | 491 | return 0; | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 492 | err_prot_mr: | 
|  | 493 | ib_dereg_mr(fr_desc->pi_ctx->prot_mr); | 
|  | 494 | err_prot_frpl: | 
|  | 495 | ib_free_fast_reg_page_list(fr_desc->pi_ctx->prot_frpl); | 
|  | 496 | err_pi_ctx: | 
|  | 497 | kfree(fr_desc->pi_ctx); | 
|  | 498 | err_data_mr: | 
|  | 499 | ib_dereg_mr(fr_desc->data_mr); | 
|  | 500 | err_data_frpl: | 
|  | 501 | ib_free_fast_reg_page_list(fr_desc->data_frpl); | 
|  | 502 |  | 
|  | 503 | return ret; | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 504 | } | 
|  | 505 |  | 
|  | 506 | static int | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 507 | isert_conn_create_fastreg_pool(struct isert_conn *isert_conn, u8 pi_support) | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 508 | { | 
|  | 509 | struct fast_reg_descriptor *fr_desc; | 
|  | 510 | struct isert_device *device = isert_conn->conn_device; | 
|  | 511 | int i, ret; | 
|  | 512 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 513 | INIT_LIST_HEAD(&isert_conn->conn_fr_pool); | 
|  | 514 | isert_conn->conn_fr_pool_size = 0; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 515 | for (i = 0; i < ISCSI_DEF_XMIT_CMDS_MAX; i++) { | 
|  | 516 | fr_desc = kzalloc(sizeof(*fr_desc), GFP_KERNEL); | 
|  | 517 | if (!fr_desc) { | 
|  | 518 | pr_err("Failed to allocate fast_reg descriptor\n"); | 
|  | 519 | ret = -ENOMEM; | 
|  | 520 | goto err; | 
|  | 521 | } | 
|  | 522 |  | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 523 | ret = isert_create_fr_desc(device->ib_device, | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 524 | isert_conn->conn_pd, fr_desc, | 
|  | 525 | pi_support); | 
| Sagi Grimberg | dc87a90 | 2014-01-09 18:40:51 +0200 | [diff] [blame] | 526 | if (ret) { | 
|  | 527 | pr_err("Failed to create fastreg descriptor err=%d\n", | 
|  | 528 | ret); | 
| Nicholas Bellinger | a80e21b | 2014-02-03 12:59:56 -0800 | [diff] [blame] | 529 | kfree(fr_desc); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 530 | goto err; | 
|  | 531 | } | 
|  | 532 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 533 | list_add_tail(&fr_desc->list, &isert_conn->conn_fr_pool); | 
|  | 534 | isert_conn->conn_fr_pool_size++; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 535 | } | 
|  | 536 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 537 | pr_debug("Creating conn %p fastreg pool size=%d", | 
|  | 538 | isert_conn, isert_conn->conn_fr_pool_size); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 539 |  | 
|  | 540 | return 0; | 
|  | 541 |  | 
|  | 542 | err: | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 543 | isert_conn_free_fastreg_pool(isert_conn); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 544 | return ret; | 
|  | 545 | } | 
|  | 546 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 547 | static int | 
|  | 548 | isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | 
|  | 549 | { | 
|  | 550 | struct iscsi_np *np = cma_id->context; | 
|  | 551 | struct isert_np *isert_np = np->np_context; | 
|  | 552 | struct isert_conn *isert_conn; | 
|  | 553 | struct isert_device *device; | 
|  | 554 | struct ib_device *ib_dev = cma_id->device; | 
|  | 555 | int ret = 0; | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 556 | u8 pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 557 |  | 
|  | 558 | pr_debug("Entering isert_connect_request cma_id: %p, context: %p\n", | 
|  | 559 | cma_id, cma_id->context); | 
|  | 560 |  | 
|  | 561 | isert_conn = kzalloc(sizeof(struct isert_conn), GFP_KERNEL); | 
|  | 562 | if (!isert_conn) { | 
|  | 563 | pr_err("Unable to allocate isert_conn\n"); | 
|  | 564 | return -ENOMEM; | 
|  | 565 | } | 
|  | 566 | isert_conn->state = ISER_CONN_INIT; | 
|  | 567 | INIT_LIST_HEAD(&isert_conn->conn_accept_node); | 
|  | 568 | init_completion(&isert_conn->conn_login_comp); | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 569 | init_completion(&isert_conn->conn_wait); | 
|  | 570 | init_completion(&isert_conn->conn_wait_comp_err); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 571 | kref_init(&isert_conn->conn_kref); | 
|  | 572 | kref_get(&isert_conn->conn_kref); | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 573 | mutex_init(&isert_conn->conn_mutex); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 574 | spin_lock_init(&isert_conn->conn_lock); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 575 |  | 
|  | 576 | cma_id->context = isert_conn; | 
|  | 577 | isert_conn->conn_cm_id = cma_id; | 
|  | 578 | isert_conn->responder_resources = event->param.conn.responder_resources; | 
|  | 579 | isert_conn->initiator_depth = event->param.conn.initiator_depth; | 
|  | 580 | pr_debug("Using responder_resources: %u initiator_depth: %u\n", | 
|  | 581 | isert_conn->responder_resources, isert_conn->initiator_depth); | 
|  | 582 |  | 
|  | 583 | isert_conn->login_buf = kzalloc(ISCSI_DEF_MAX_RECV_SEG_LEN + | 
|  | 584 | ISER_RX_LOGIN_SIZE, GFP_KERNEL); | 
|  | 585 | if (!isert_conn->login_buf) { | 
|  | 586 | pr_err("Unable to allocate isert_conn->login_buf\n"); | 
|  | 587 | ret = -ENOMEM; | 
|  | 588 | goto out; | 
|  | 589 | } | 
|  | 590 |  | 
|  | 591 | isert_conn->login_req_buf = isert_conn->login_buf; | 
|  | 592 | isert_conn->login_rsp_buf = isert_conn->login_buf + | 
|  | 593 | ISCSI_DEF_MAX_RECV_SEG_LEN; | 
|  | 594 | pr_debug("Set login_buf: %p login_req_buf: %p login_rsp_buf: %p\n", | 
|  | 595 | isert_conn->login_buf, isert_conn->login_req_buf, | 
|  | 596 | isert_conn->login_rsp_buf); | 
|  | 597 |  | 
|  | 598 | isert_conn->login_req_dma = ib_dma_map_single(ib_dev, | 
|  | 599 | (void *)isert_conn->login_req_buf, | 
|  | 600 | ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_FROM_DEVICE); | 
|  | 601 |  | 
|  | 602 | ret = ib_dma_mapping_error(ib_dev, isert_conn->login_req_dma); | 
|  | 603 | if (ret) { | 
|  | 604 | pr_err("ib_dma_mapping_error failed for login_req_dma: %d\n", | 
|  | 605 | ret); | 
|  | 606 | isert_conn->login_req_dma = 0; | 
|  | 607 | goto out_login_buf; | 
|  | 608 | } | 
|  | 609 |  | 
|  | 610 | isert_conn->login_rsp_dma = ib_dma_map_single(ib_dev, | 
|  | 611 | (void *)isert_conn->login_rsp_buf, | 
|  | 612 | ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE); | 
|  | 613 |  | 
|  | 614 | ret = ib_dma_mapping_error(ib_dev, isert_conn->login_rsp_dma); | 
|  | 615 | if (ret) { | 
|  | 616 | pr_err("ib_dma_mapping_error failed for login_rsp_dma: %d\n", | 
|  | 617 | ret); | 
|  | 618 | isert_conn->login_rsp_dma = 0; | 
|  | 619 | goto out_req_dma_map; | 
|  | 620 | } | 
|  | 621 |  | 
|  | 622 | device = isert_device_find_by_ib_dev(cma_id); | 
|  | 623 | if (IS_ERR(device)) { | 
|  | 624 | ret = PTR_ERR(device); | 
|  | 625 | goto out_rsp_dma_map; | 
|  | 626 | } | 
|  | 627 |  | 
|  | 628 | isert_conn->conn_device = device; | 
| Sagi Grimberg | eb6ab13 | 2014-01-09 18:40:49 +0200 | [diff] [blame] | 629 | isert_conn->conn_pd = ib_alloc_pd(isert_conn->conn_device->ib_device); | 
|  | 630 | if (IS_ERR(isert_conn->conn_pd)) { | 
|  | 631 | ret = PTR_ERR(isert_conn->conn_pd); | 
|  | 632 | pr_err("ib_alloc_pd failed for conn %p: ret=%d\n", | 
|  | 633 | isert_conn, ret); | 
|  | 634 | goto out_pd; | 
|  | 635 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 636 |  | 
| Sagi Grimberg | eb6ab13 | 2014-01-09 18:40:49 +0200 | [diff] [blame] | 637 | isert_conn->conn_mr = ib_get_dma_mr(isert_conn->conn_pd, | 
|  | 638 | IB_ACCESS_LOCAL_WRITE); | 
|  | 639 | if (IS_ERR(isert_conn->conn_mr)) { | 
|  | 640 | ret = PTR_ERR(isert_conn->conn_mr); | 
|  | 641 | pr_err("ib_get_dma_mr failed for conn %p: ret=%d\n", | 
|  | 642 | isert_conn, ret); | 
|  | 643 | goto out_mr; | 
|  | 644 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 645 |  | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 646 | if (pi_support && !device->pi_capable) { | 
|  | 647 | pr_err("Protection information requested but not supported\n"); | 
|  | 648 | ret = -EINVAL; | 
|  | 649 | goto out_mr; | 
|  | 650 | } | 
|  | 651 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 652 | if (device->use_fastreg) { | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 653 | ret = isert_conn_create_fastreg_pool(isert_conn, pi_support); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 654 | if (ret) { | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 655 | pr_err("Conn: %p failed to create fastreg pool\n", | 
|  | 656 | isert_conn); | 
|  | 657 | goto out_fastreg; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 658 | } | 
|  | 659 | } | 
|  | 660 |  | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 661 | ret = isert_conn_setup_qp(isert_conn, cma_id, pi_support); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 662 | if (ret) | 
|  | 663 | goto out_conn_dev; | 
|  | 664 |  | 
|  | 665 | mutex_lock(&isert_np->np_accept_mutex); | 
|  | 666 | list_add_tail(&isert_np->np_accept_list, &isert_conn->conn_accept_node); | 
|  | 667 | mutex_unlock(&isert_np->np_accept_mutex); | 
|  | 668 |  | 
|  | 669 | pr_debug("isert_connect_request() waking up np_accept_wq: %p\n", np); | 
|  | 670 | wake_up(&isert_np->np_accept_wq); | 
|  | 671 | return 0; | 
|  | 672 |  | 
|  | 673 | out_conn_dev: | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 674 | if (device->use_fastreg) | 
|  | 675 | isert_conn_free_fastreg_pool(isert_conn); | 
|  | 676 | out_fastreg: | 
| Sagi Grimberg | eb6ab13 | 2014-01-09 18:40:49 +0200 | [diff] [blame] | 677 | ib_dereg_mr(isert_conn->conn_mr); | 
|  | 678 | out_mr: | 
|  | 679 | ib_dealloc_pd(isert_conn->conn_pd); | 
|  | 680 | out_pd: | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 681 | isert_device_try_release(device); | 
|  | 682 | out_rsp_dma_map: | 
|  | 683 | ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma, | 
|  | 684 | ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE); | 
|  | 685 | out_req_dma_map: | 
|  | 686 | ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma, | 
|  | 687 | ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_FROM_DEVICE); | 
|  | 688 | out_login_buf: | 
|  | 689 | kfree(isert_conn->login_buf); | 
|  | 690 | out: | 
|  | 691 | kfree(isert_conn); | 
|  | 692 | return ret; | 
|  | 693 | } | 
|  | 694 |  | 
|  | 695 | static void | 
|  | 696 | isert_connect_release(struct isert_conn *isert_conn) | 
|  | 697 | { | 
|  | 698 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 699 | struct isert_device *device = isert_conn->conn_device; | 
|  | 700 | int cq_index; | 
|  | 701 |  | 
|  | 702 | pr_debug("Entering isert_connect_release(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); | 
|  | 703 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 704 | if (device && device->use_fastreg) | 
|  | 705 | isert_conn_free_fastreg_pool(isert_conn); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 706 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 707 | if (isert_conn->conn_qp) { | 
|  | 708 | cq_index = ((struct isert_cq_desc *) | 
|  | 709 | isert_conn->conn_qp->recv_cq->cq_context)->cq_index; | 
|  | 710 | pr_debug("isert_connect_release: cq_index: %d\n", cq_index); | 
|  | 711 | isert_conn->conn_device->cq_active_qps[cq_index]--; | 
|  | 712 |  | 
|  | 713 | rdma_destroy_qp(isert_conn->conn_cm_id); | 
|  | 714 | } | 
|  | 715 |  | 
|  | 716 | isert_free_rx_descriptors(isert_conn); | 
|  | 717 | rdma_destroy_id(isert_conn->conn_cm_id); | 
|  | 718 |  | 
| Sagi Grimberg | eb6ab13 | 2014-01-09 18:40:49 +0200 | [diff] [blame] | 719 | ib_dereg_mr(isert_conn->conn_mr); | 
|  | 720 | ib_dealloc_pd(isert_conn->conn_pd); | 
|  | 721 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 722 | if (isert_conn->login_buf) { | 
|  | 723 | ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma, | 
|  | 724 | ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE); | 
|  | 725 | ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma, | 
|  | 726 | ISCSI_DEF_MAX_RECV_SEG_LEN, | 
|  | 727 | DMA_FROM_DEVICE); | 
|  | 728 | kfree(isert_conn->login_buf); | 
|  | 729 | } | 
|  | 730 | kfree(isert_conn); | 
|  | 731 |  | 
|  | 732 | if (device) | 
|  | 733 | isert_device_try_release(device); | 
|  | 734 |  | 
|  | 735 | pr_debug("Leaving isert_connect_release >>>>>>>>>>>>\n"); | 
|  | 736 | } | 
|  | 737 |  | 
|  | 738 | static void | 
|  | 739 | isert_connected_handler(struct rdma_cm_id *cma_id) | 
|  | 740 | { | 
|  | 741 | return; | 
|  | 742 | } | 
|  | 743 |  | 
|  | 744 | static void | 
|  | 745 | isert_release_conn_kref(struct kref *kref) | 
|  | 746 | { | 
|  | 747 | struct isert_conn *isert_conn = container_of(kref, | 
|  | 748 | struct isert_conn, conn_kref); | 
|  | 749 |  | 
|  | 750 | pr_debug("Calling isert_connect_release for final kref %s/%d\n", | 
|  | 751 | current->comm, current->pid); | 
|  | 752 |  | 
|  | 753 | isert_connect_release(isert_conn); | 
|  | 754 | } | 
|  | 755 |  | 
|  | 756 | static void | 
|  | 757 | isert_put_conn(struct isert_conn *isert_conn) | 
|  | 758 | { | 
|  | 759 | kref_put(&isert_conn->conn_kref, isert_release_conn_kref); | 
|  | 760 | } | 
|  | 761 |  | 
|  | 762 | static void | 
|  | 763 | isert_disconnect_work(struct work_struct *work) | 
|  | 764 | { | 
|  | 765 | struct isert_conn *isert_conn = container_of(work, | 
|  | 766 | struct isert_conn, conn_logout_work); | 
|  | 767 |  | 
|  | 768 | pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 769 | mutex_lock(&isert_conn->conn_mutex); | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 770 | if (isert_conn->state == ISER_CONN_UP) | 
|  | 771 | isert_conn->state = ISER_CONN_TERMINATING; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 772 |  | 
|  | 773 | if (isert_conn->post_recv_buf_count == 0 && | 
|  | 774 | atomic_read(&isert_conn->post_send_buf_count) == 0) { | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 775 | mutex_unlock(&isert_conn->conn_mutex); | 
|  | 776 | goto wake_up; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 777 | } | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 778 | if (!isert_conn->conn_cm_id) { | 
|  | 779 | mutex_unlock(&isert_conn->conn_mutex); | 
|  | 780 | isert_put_conn(isert_conn); | 
|  | 781 | return; | 
|  | 782 | } | 
|  | 783 | if (!isert_conn->logout_posted) { | 
|  | 784 | pr_debug("Calling rdma_disconnect for !logout_posted from" | 
|  | 785 | " isert_disconnect_work\n"); | 
|  | 786 | rdma_disconnect(isert_conn->conn_cm_id); | 
|  | 787 | mutex_unlock(&isert_conn->conn_mutex); | 
|  | 788 | iscsit_cause_connection_reinstatement(isert_conn->conn, 0); | 
|  | 789 | goto wake_up; | 
|  | 790 | } | 
|  | 791 | mutex_unlock(&isert_conn->conn_mutex); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 792 |  | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 793 | wake_up: | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 794 | complete(&isert_conn->conn_wait); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 795 | isert_put_conn(isert_conn); | 
|  | 796 | } | 
|  | 797 |  | 
|  | 798 | static void | 
|  | 799 | isert_disconnected_handler(struct rdma_cm_id *cma_id) | 
|  | 800 | { | 
|  | 801 | struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context; | 
|  | 802 |  | 
|  | 803 | INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work); | 
|  | 804 | schedule_work(&isert_conn->conn_logout_work); | 
|  | 805 | } | 
|  | 806 |  | 
|  | 807 | static int | 
|  | 808 | isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | 
|  | 809 | { | 
|  | 810 | int ret = 0; | 
|  | 811 |  | 
|  | 812 | pr_debug("isert_cma_handler: event %d status %d conn %p id %p\n", | 
|  | 813 | event->event, event->status, cma_id->context, cma_id); | 
|  | 814 |  | 
|  | 815 | switch (event->event) { | 
|  | 816 | case RDMA_CM_EVENT_CONNECT_REQUEST: | 
|  | 817 | pr_debug("RDMA_CM_EVENT_CONNECT_REQUEST: >>>>>>>>>>>>>>>\n"); | 
|  | 818 | ret = isert_connect_request(cma_id, event); | 
|  | 819 | break; | 
|  | 820 | case RDMA_CM_EVENT_ESTABLISHED: | 
|  | 821 | pr_debug("RDMA_CM_EVENT_ESTABLISHED >>>>>>>>>>>>>>\n"); | 
|  | 822 | isert_connected_handler(cma_id); | 
|  | 823 | break; | 
|  | 824 | case RDMA_CM_EVENT_DISCONNECTED: | 
|  | 825 | pr_debug("RDMA_CM_EVENT_DISCONNECTED: >>>>>>>>>>>>>>\n"); | 
|  | 826 | isert_disconnected_handler(cma_id); | 
|  | 827 | break; | 
|  | 828 | case RDMA_CM_EVENT_DEVICE_REMOVAL: | 
|  | 829 | case RDMA_CM_EVENT_ADDR_CHANGE: | 
|  | 830 | break; | 
|  | 831 | case RDMA_CM_EVENT_CONNECT_ERROR: | 
|  | 832 | default: | 
|  | 833 | pr_err("Unknown RDMA CMA event: %d\n", event->event); | 
|  | 834 | break; | 
|  | 835 | } | 
|  | 836 |  | 
|  | 837 | if (ret != 0) { | 
|  | 838 | pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n", | 
|  | 839 | event->event, ret); | 
|  | 840 | dump_stack(); | 
|  | 841 | } | 
|  | 842 |  | 
|  | 843 | return ret; | 
|  | 844 | } | 
|  | 845 |  | 
|  | 846 | static int | 
|  | 847 | isert_post_recv(struct isert_conn *isert_conn, u32 count) | 
|  | 848 | { | 
|  | 849 | struct ib_recv_wr *rx_wr, *rx_wr_failed; | 
|  | 850 | int i, ret; | 
|  | 851 | unsigned int rx_head = isert_conn->conn_rx_desc_head; | 
|  | 852 | struct iser_rx_desc *rx_desc; | 
|  | 853 |  | 
|  | 854 | for (rx_wr = isert_conn->conn_rx_wr, i = 0; i < count; i++, rx_wr++) { | 
|  | 855 | rx_desc		= &isert_conn->conn_rx_descs[rx_head]; | 
|  | 856 | rx_wr->wr_id	= (unsigned long)rx_desc; | 
|  | 857 | rx_wr->sg_list	= &rx_desc->rx_sg; | 
|  | 858 | rx_wr->num_sge	= 1; | 
|  | 859 | rx_wr->next	= rx_wr + 1; | 
|  | 860 | rx_head = (rx_head + 1) & (ISERT_QP_MAX_RECV_DTOS - 1); | 
|  | 861 | } | 
|  | 862 |  | 
|  | 863 | rx_wr--; | 
|  | 864 | rx_wr->next = NULL; /* mark end of work requests list */ | 
|  | 865 |  | 
|  | 866 | isert_conn->post_recv_buf_count += count; | 
|  | 867 | ret = ib_post_recv(isert_conn->conn_qp, isert_conn->conn_rx_wr, | 
|  | 868 | &rx_wr_failed); | 
|  | 869 | if (ret) { | 
|  | 870 | pr_err("ib_post_recv() failed with ret: %d\n", ret); | 
|  | 871 | isert_conn->post_recv_buf_count -= count; | 
|  | 872 | } else { | 
|  | 873 | pr_debug("isert_post_recv(): Posted %d RX buffers\n", count); | 
|  | 874 | isert_conn->conn_rx_desc_head = rx_head; | 
|  | 875 | } | 
|  | 876 | return ret; | 
|  | 877 | } | 
|  | 878 |  | 
|  | 879 | static int | 
|  | 880 | isert_post_send(struct isert_conn *isert_conn, struct iser_tx_desc *tx_desc) | 
|  | 881 | { | 
|  | 882 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 883 | struct ib_send_wr send_wr, *send_wr_failed; | 
|  | 884 | int ret; | 
|  | 885 |  | 
|  | 886 | ib_dma_sync_single_for_device(ib_dev, tx_desc->dma_addr, | 
|  | 887 | ISER_HEADERS_LEN, DMA_TO_DEVICE); | 
|  | 888 |  | 
|  | 889 | send_wr.next	= NULL; | 
|  | 890 | send_wr.wr_id	= (unsigned long)tx_desc; | 
|  | 891 | send_wr.sg_list	= tx_desc->tx_sg; | 
|  | 892 | send_wr.num_sge	= tx_desc->num_sge; | 
|  | 893 | send_wr.opcode	= IB_WR_SEND; | 
|  | 894 | send_wr.send_flags = IB_SEND_SIGNALED; | 
|  | 895 |  | 
|  | 896 | atomic_inc(&isert_conn->post_send_buf_count); | 
|  | 897 |  | 
|  | 898 | ret = ib_post_send(isert_conn->conn_qp, &send_wr, &send_wr_failed); | 
|  | 899 | if (ret) { | 
|  | 900 | pr_err("ib_post_send() failed, ret: %d\n", ret); | 
|  | 901 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 902 | } | 
|  | 903 |  | 
|  | 904 | return ret; | 
|  | 905 | } | 
|  | 906 |  | 
|  | 907 | static void | 
|  | 908 | isert_create_send_desc(struct isert_conn *isert_conn, | 
|  | 909 | struct isert_cmd *isert_cmd, | 
|  | 910 | struct iser_tx_desc *tx_desc) | 
|  | 911 | { | 
|  | 912 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 913 |  | 
|  | 914 | ib_dma_sync_single_for_cpu(ib_dev, tx_desc->dma_addr, | 
|  | 915 | ISER_HEADERS_LEN, DMA_TO_DEVICE); | 
|  | 916 |  | 
|  | 917 | memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr)); | 
|  | 918 | tx_desc->iser_header.flags = ISER_VER; | 
|  | 919 |  | 
|  | 920 | tx_desc->num_sge = 1; | 
|  | 921 | tx_desc->isert_cmd = isert_cmd; | 
|  | 922 |  | 
|  | 923 | if (tx_desc->tx_sg[0].lkey != isert_conn->conn_mr->lkey) { | 
|  | 924 | tx_desc->tx_sg[0].lkey = isert_conn->conn_mr->lkey; | 
|  | 925 | pr_debug("tx_desc %p lkey mismatch, fixing\n", tx_desc); | 
|  | 926 | } | 
|  | 927 | } | 
|  | 928 |  | 
|  | 929 | static int | 
|  | 930 | isert_init_tx_hdrs(struct isert_conn *isert_conn, | 
|  | 931 | struct iser_tx_desc *tx_desc) | 
|  | 932 | { | 
|  | 933 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 934 | u64 dma_addr; | 
|  | 935 |  | 
|  | 936 | dma_addr = ib_dma_map_single(ib_dev, (void *)tx_desc, | 
|  | 937 | ISER_HEADERS_LEN, DMA_TO_DEVICE); | 
|  | 938 | if (ib_dma_mapping_error(ib_dev, dma_addr)) { | 
|  | 939 | pr_err("ib_dma_mapping_error() failed\n"); | 
|  | 940 | return -ENOMEM; | 
|  | 941 | } | 
|  | 942 |  | 
|  | 943 | tx_desc->dma_addr = dma_addr; | 
|  | 944 | tx_desc->tx_sg[0].addr	= tx_desc->dma_addr; | 
|  | 945 | tx_desc->tx_sg[0].length = ISER_HEADERS_LEN; | 
|  | 946 | tx_desc->tx_sg[0].lkey = isert_conn->conn_mr->lkey; | 
|  | 947 |  | 
|  | 948 | pr_debug("isert_init_tx_hdrs: Setup tx_sg[0].addr: 0x%llx length: %u" | 
|  | 949 | " lkey: 0x%08x\n", tx_desc->tx_sg[0].addr, | 
|  | 950 | tx_desc->tx_sg[0].length, tx_desc->tx_sg[0].lkey); | 
|  | 951 |  | 
|  | 952 | return 0; | 
|  | 953 | } | 
|  | 954 |  | 
|  | 955 | static void | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 956 | isert_init_send_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | 
|  | 957 | struct ib_send_wr *send_wr, bool coalesce) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 958 | { | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 959 | struct iser_tx_desc *tx_desc = &isert_cmd->tx_desc; | 
|  | 960 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 961 | isert_cmd->rdma_wr.iser_ib_op = ISER_IB_SEND; | 
|  | 962 | send_wr->wr_id = (unsigned long)&isert_cmd->tx_desc; | 
|  | 963 | send_wr->opcode = IB_WR_SEND; | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 964 | send_wr->sg_list = &tx_desc->tx_sg[0]; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 965 | send_wr->num_sge = isert_cmd->tx_desc.num_sge; | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 966 | /* | 
|  | 967 | * Coalesce send completion interrupts by only setting IB_SEND_SIGNALED | 
|  | 968 | * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls. | 
|  | 969 | */ | 
| Nicholas Bellinger | ebbe442 | 2014-03-02 14:51:12 -0800 | [diff] [blame] | 970 | mutex_lock(&isert_conn->conn_mutex); | 
|  | 971 | if (coalesce && isert_conn->state == ISER_CONN_UP && | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 972 | ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) { | 
| Nicholas Bellinger | ebbe442 | 2014-03-02 14:51:12 -0800 | [diff] [blame] | 973 | tx_desc->llnode_active = true; | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 974 | llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist); | 
| Nicholas Bellinger | ebbe442 | 2014-03-02 14:51:12 -0800 | [diff] [blame] | 975 | mutex_unlock(&isert_conn->conn_mutex); | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 976 | return; | 
|  | 977 | } | 
|  | 978 | isert_conn->conn_comp_batch = 0; | 
|  | 979 | tx_desc->comp_llnode_batch = llist_del_all(&isert_conn->conn_comp_llist); | 
| Nicholas Bellinger | ebbe442 | 2014-03-02 14:51:12 -0800 | [diff] [blame] | 980 | mutex_unlock(&isert_conn->conn_mutex); | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 981 |  | 
|  | 982 | send_wr->send_flags = IB_SEND_SIGNALED; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 983 | } | 
|  | 984 |  | 
|  | 985 | static int | 
|  | 986 | isert_rdma_post_recvl(struct isert_conn *isert_conn) | 
|  | 987 | { | 
|  | 988 | struct ib_recv_wr rx_wr, *rx_wr_fail; | 
|  | 989 | struct ib_sge sge; | 
|  | 990 | int ret; | 
|  | 991 |  | 
|  | 992 | memset(&sge, 0, sizeof(struct ib_sge)); | 
|  | 993 | sge.addr = isert_conn->login_req_dma; | 
|  | 994 | sge.length = ISER_RX_LOGIN_SIZE; | 
|  | 995 | sge.lkey = isert_conn->conn_mr->lkey; | 
|  | 996 |  | 
|  | 997 | pr_debug("Setup sge: addr: %llx length: %d 0x%08x\n", | 
|  | 998 | sge.addr, sge.length, sge.lkey); | 
|  | 999 |  | 
|  | 1000 | memset(&rx_wr, 0, sizeof(struct ib_recv_wr)); | 
|  | 1001 | rx_wr.wr_id = (unsigned long)isert_conn->login_req_buf; | 
|  | 1002 | rx_wr.sg_list = &sge; | 
|  | 1003 | rx_wr.num_sge = 1; | 
|  | 1004 |  | 
|  | 1005 | isert_conn->post_recv_buf_count++; | 
|  | 1006 | ret = ib_post_recv(isert_conn->conn_qp, &rx_wr, &rx_wr_fail); | 
|  | 1007 | if (ret) { | 
|  | 1008 | pr_err("ib_post_recv() failed: %d\n", ret); | 
|  | 1009 | isert_conn->post_recv_buf_count--; | 
|  | 1010 | } | 
|  | 1011 |  | 
|  | 1012 | pr_debug("ib_post_recv(): returned success >>>>>>>>>>>>>>>>>>>>>>>>\n"); | 
|  | 1013 | return ret; | 
|  | 1014 | } | 
|  | 1015 |  | 
|  | 1016 | static int | 
|  | 1017 | isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, | 
|  | 1018 | u32 length) | 
|  | 1019 | { | 
|  | 1020 | struct isert_conn *isert_conn = conn->context; | 
|  | 1021 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 1022 | struct iser_tx_desc *tx_desc = &isert_conn->conn_login_tx_desc; | 
|  | 1023 | int ret; | 
|  | 1024 |  | 
|  | 1025 | isert_create_send_desc(isert_conn, NULL, tx_desc); | 
|  | 1026 |  | 
|  | 1027 | memcpy(&tx_desc->iscsi_header, &login->rsp[0], | 
|  | 1028 | sizeof(struct iscsi_hdr)); | 
|  | 1029 |  | 
|  | 1030 | isert_init_tx_hdrs(isert_conn, tx_desc); | 
|  | 1031 |  | 
|  | 1032 | if (length > 0) { | 
|  | 1033 | struct ib_sge *tx_dsg = &tx_desc->tx_sg[1]; | 
|  | 1034 |  | 
|  | 1035 | ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_rsp_dma, | 
|  | 1036 | length, DMA_TO_DEVICE); | 
|  | 1037 |  | 
|  | 1038 | memcpy(isert_conn->login_rsp_buf, login->rsp_buf, length); | 
|  | 1039 |  | 
|  | 1040 | ib_dma_sync_single_for_device(ib_dev, isert_conn->login_rsp_dma, | 
|  | 1041 | length, DMA_TO_DEVICE); | 
|  | 1042 |  | 
|  | 1043 | tx_dsg->addr	= isert_conn->login_rsp_dma; | 
|  | 1044 | tx_dsg->length	= length; | 
|  | 1045 | tx_dsg->lkey	= isert_conn->conn_mr->lkey; | 
|  | 1046 | tx_desc->num_sge = 2; | 
|  | 1047 | } | 
|  | 1048 | if (!login->login_failed) { | 
|  | 1049 | if (login->login_complete) { | 
|  | 1050 | ret = isert_alloc_rx_descriptors(isert_conn); | 
|  | 1051 | if (ret) | 
|  | 1052 | return ret; | 
|  | 1053 |  | 
|  | 1054 | ret = isert_post_recv(isert_conn, ISERT_MIN_POSTED_RX); | 
|  | 1055 | if (ret) | 
|  | 1056 | return ret; | 
|  | 1057 |  | 
|  | 1058 | isert_conn->state = ISER_CONN_UP; | 
|  | 1059 | goto post_send; | 
|  | 1060 | } | 
|  | 1061 |  | 
|  | 1062 | ret = isert_rdma_post_recvl(isert_conn); | 
|  | 1063 | if (ret) | 
|  | 1064 | return ret; | 
|  | 1065 | } | 
|  | 1066 | post_send: | 
|  | 1067 | ret = isert_post_send(isert_conn, tx_desc); | 
|  | 1068 | if (ret) | 
|  | 1069 | return ret; | 
|  | 1070 |  | 
|  | 1071 | return 0; | 
|  | 1072 | } | 
|  | 1073 |  | 
|  | 1074 | static void | 
|  | 1075 | isert_rx_login_req(struct iser_rx_desc *rx_desc, int rx_buflen, | 
|  | 1076 | struct isert_conn *isert_conn) | 
|  | 1077 | { | 
|  | 1078 | struct iscsi_conn *conn = isert_conn->conn; | 
|  | 1079 | struct iscsi_login *login = conn->conn_login; | 
|  | 1080 | int size; | 
|  | 1081 |  | 
|  | 1082 | if (!login) { | 
|  | 1083 | pr_err("conn->conn_login is NULL\n"); | 
|  | 1084 | dump_stack(); | 
|  | 1085 | return; | 
|  | 1086 | } | 
|  | 1087 |  | 
|  | 1088 | if (login->first_request) { | 
|  | 1089 | struct iscsi_login_req *login_req = | 
|  | 1090 | (struct iscsi_login_req *)&rx_desc->iscsi_header; | 
|  | 1091 | /* | 
|  | 1092 | * Setup the initial iscsi_login values from the leading | 
|  | 1093 | * login request PDU. | 
|  | 1094 | */ | 
|  | 1095 | login->leading_connection = (!login_req->tsih) ? 1 : 0; | 
|  | 1096 | login->current_stage = | 
|  | 1097 | (login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) | 
|  | 1098 | >> 2; | 
|  | 1099 | login->version_min	= login_req->min_version; | 
|  | 1100 | login->version_max	= login_req->max_version; | 
|  | 1101 | memcpy(login->isid, login_req->isid, 6); | 
|  | 1102 | login->cmd_sn		= be32_to_cpu(login_req->cmdsn); | 
|  | 1103 | login->init_task_tag	= login_req->itt; | 
|  | 1104 | login->initial_exp_statsn = be32_to_cpu(login_req->exp_statsn); | 
|  | 1105 | login->cid		= be16_to_cpu(login_req->cid); | 
|  | 1106 | login->tsih		= be16_to_cpu(login_req->tsih); | 
|  | 1107 | } | 
|  | 1108 |  | 
|  | 1109 | memcpy(&login->req[0], (void *)&rx_desc->iscsi_header, ISCSI_HDR_LEN); | 
|  | 1110 |  | 
|  | 1111 | size = min(rx_buflen, MAX_KEY_VALUE_PAIRS); | 
|  | 1112 | pr_debug("Using login payload size: %d, rx_buflen: %d MAX_KEY_VALUE_PAIRS: %d\n", | 
|  | 1113 | size, rx_buflen, MAX_KEY_VALUE_PAIRS); | 
|  | 1114 | memcpy(login->req_buf, &rx_desc->data[0], size); | 
|  | 1115 |  | 
| Nicholas Bellinger | 6faaa85 | 2013-08-18 16:35:46 -0700 | [diff] [blame] | 1116 | if (login->first_request) { | 
|  | 1117 | complete(&isert_conn->conn_login_comp); | 
|  | 1118 | return; | 
|  | 1119 | } | 
|  | 1120 | schedule_delayed_work(&conn->login_work, 0); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1121 | } | 
|  | 1122 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1123 | static struct iscsi_cmd | 
| Nicholas Bellinger | 676687c | 2014-01-20 03:36:44 +0000 | [diff] [blame] | 1124 | *isert_allocate_cmd(struct iscsi_conn *conn) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1125 | { | 
|  | 1126 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
|  | 1127 | struct isert_cmd *isert_cmd; | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1128 | struct iscsi_cmd *cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1129 |  | 
| Nicholas Bellinger | 676687c | 2014-01-20 03:36:44 +0000 | [diff] [blame] | 1130 | cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1131 | if (!cmd) { | 
|  | 1132 | pr_err("Unable to allocate iscsi_cmd + isert_cmd\n"); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1133 | return NULL; | 
|  | 1134 | } | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1135 | isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1136 | isert_cmd->conn = isert_conn; | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1137 | isert_cmd->iscsi_cmd = cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1138 |  | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1139 | return cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1140 | } | 
|  | 1141 |  | 
|  | 1142 | static int | 
|  | 1143 | isert_handle_scsi_cmd(struct isert_conn *isert_conn, | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1144 | struct isert_cmd *isert_cmd, struct iscsi_cmd *cmd, | 
|  | 1145 | struct iser_rx_desc *rx_desc, unsigned char *buf) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1146 | { | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1147 | struct iscsi_conn *conn = isert_conn->conn; | 
|  | 1148 | struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf; | 
|  | 1149 | struct scatterlist *sg; | 
|  | 1150 | int imm_data, imm_data_len, unsol_data, sg_nents, rc; | 
|  | 1151 | bool dump_payload = false; | 
|  | 1152 |  | 
|  | 1153 | rc = iscsit_setup_scsi_cmd(conn, cmd, buf); | 
|  | 1154 | if (rc < 0) | 
|  | 1155 | return rc; | 
|  | 1156 |  | 
|  | 1157 | imm_data = cmd->immediate_data; | 
|  | 1158 | imm_data_len = cmd->first_burst_len; | 
|  | 1159 | unsol_data = cmd->unsolicited_data; | 
|  | 1160 |  | 
|  | 1161 | rc = iscsit_process_scsi_cmd(conn, cmd, hdr); | 
|  | 1162 | if (rc < 0) { | 
|  | 1163 | return 0; | 
|  | 1164 | } else if (rc > 0) { | 
|  | 1165 | dump_payload = true; | 
|  | 1166 | goto sequence_cmd; | 
|  | 1167 | } | 
|  | 1168 |  | 
|  | 1169 | if (!imm_data) | 
|  | 1170 | return 0; | 
|  | 1171 |  | 
|  | 1172 | sg = &cmd->se_cmd.t_data_sg[0]; | 
|  | 1173 | sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE)); | 
|  | 1174 |  | 
|  | 1175 | pr_debug("Copying Immediate SG: %p sg_nents: %u from %p imm_data_len: %d\n", | 
|  | 1176 | sg, sg_nents, &rx_desc->data[0], imm_data_len); | 
|  | 1177 |  | 
|  | 1178 | sg_copy_from_buffer(sg, sg_nents, &rx_desc->data[0], imm_data_len); | 
|  | 1179 |  | 
|  | 1180 | cmd->write_data_done += imm_data_len; | 
|  | 1181 |  | 
|  | 1182 | if (cmd->write_data_done == cmd->se_cmd.data_length) { | 
|  | 1183 | spin_lock_bh(&cmd->istate_lock); | 
|  | 1184 | cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT; | 
|  | 1185 | cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT; | 
|  | 1186 | spin_unlock_bh(&cmd->istate_lock); | 
|  | 1187 | } | 
|  | 1188 |  | 
|  | 1189 | sequence_cmd: | 
| Nicholas Bellinger | 561bf15 | 2013-07-03 03:58:58 -0700 | [diff] [blame] | 1190 | rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1191 |  | 
|  | 1192 | if (!rc && dump_payload == false && unsol_data) | 
|  | 1193 | iscsit_set_unsoliticed_dataout(cmd); | 
|  | 1194 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1195 | return 0; | 
|  | 1196 | } | 
|  | 1197 |  | 
|  | 1198 | static int | 
|  | 1199 | isert_handle_iscsi_dataout(struct isert_conn *isert_conn, | 
|  | 1200 | struct iser_rx_desc *rx_desc, unsigned char *buf) | 
|  | 1201 | { | 
|  | 1202 | struct scatterlist *sg_start; | 
|  | 1203 | struct iscsi_conn *conn = isert_conn->conn; | 
|  | 1204 | struct iscsi_cmd *cmd = NULL; | 
|  | 1205 | struct iscsi_data *hdr = (struct iscsi_data *)buf; | 
|  | 1206 | u32 unsol_data_len = ntoh24(hdr->dlength); | 
|  | 1207 | int rc, sg_nents, sg_off, page_off; | 
|  | 1208 |  | 
|  | 1209 | rc = iscsit_check_dataout_hdr(conn, buf, &cmd); | 
|  | 1210 | if (rc < 0) | 
|  | 1211 | return rc; | 
|  | 1212 | else if (!cmd) | 
|  | 1213 | return 0; | 
|  | 1214 | /* | 
|  | 1215 | * FIXME: Unexpected unsolicited_data out | 
|  | 1216 | */ | 
|  | 1217 | if (!cmd->unsolicited_data) { | 
|  | 1218 | pr_err("Received unexpected solicited data payload\n"); | 
|  | 1219 | dump_stack(); | 
|  | 1220 | return -1; | 
|  | 1221 | } | 
|  | 1222 |  | 
|  | 1223 | pr_debug("Unsolicited DataOut unsol_data_len: %u, write_data_done: %u, data_length: %u\n", | 
|  | 1224 | unsol_data_len, cmd->write_data_done, cmd->se_cmd.data_length); | 
|  | 1225 |  | 
|  | 1226 | sg_off = cmd->write_data_done / PAGE_SIZE; | 
|  | 1227 | sg_start = &cmd->se_cmd.t_data_sg[sg_off]; | 
|  | 1228 | sg_nents = max(1UL, DIV_ROUND_UP(unsol_data_len, PAGE_SIZE)); | 
|  | 1229 | page_off = cmd->write_data_done % PAGE_SIZE; | 
|  | 1230 | /* | 
|  | 1231 | * FIXME: Non page-aligned unsolicited_data out | 
|  | 1232 | */ | 
|  | 1233 | if (page_off) { | 
|  | 1234 | pr_err("Received unexpected non-page aligned data payload\n"); | 
|  | 1235 | dump_stack(); | 
|  | 1236 | return -1; | 
|  | 1237 | } | 
|  | 1238 | pr_debug("Copying DataOut: sg_start: %p, sg_off: %u sg_nents: %u from %p %u\n", | 
|  | 1239 | sg_start, sg_off, sg_nents, &rx_desc->data[0], unsol_data_len); | 
|  | 1240 |  | 
|  | 1241 | sg_copy_from_buffer(sg_start, sg_nents, &rx_desc->data[0], | 
|  | 1242 | unsol_data_len); | 
|  | 1243 |  | 
|  | 1244 | rc = iscsit_check_dataout_payload(cmd, hdr, false); | 
|  | 1245 | if (rc < 0) | 
|  | 1246 | return rc; | 
|  | 1247 |  | 
|  | 1248 | return 0; | 
|  | 1249 | } | 
|  | 1250 |  | 
|  | 1251 | static int | 
| Nicholas Bellinger | 778de36 | 2013-06-14 16:07:47 -0700 | [diff] [blame] | 1252 | isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1253 | struct iscsi_cmd *cmd, struct iser_rx_desc *rx_desc, | 
|  | 1254 | unsigned char *buf) | 
| Nicholas Bellinger | 778de36 | 2013-06-14 16:07:47 -0700 | [diff] [blame] | 1255 | { | 
| Nicholas Bellinger | 778de36 | 2013-06-14 16:07:47 -0700 | [diff] [blame] | 1256 | struct iscsi_conn *conn = isert_conn->conn; | 
|  | 1257 | struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf; | 
|  | 1258 | int rc; | 
|  | 1259 |  | 
|  | 1260 | rc = iscsit_setup_nop_out(conn, cmd, hdr); | 
|  | 1261 | if (rc < 0) | 
|  | 1262 | return rc; | 
|  | 1263 | /* | 
|  | 1264 | * FIXME: Add support for NOPOUT payload using unsolicited RDMA payload | 
|  | 1265 | */ | 
|  | 1266 |  | 
|  | 1267 | return iscsit_process_nop_out(conn, cmd, hdr); | 
|  | 1268 | } | 
|  | 1269 |  | 
|  | 1270 | static int | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1271 | isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1272 | struct iscsi_cmd *cmd, struct iser_rx_desc *rx_desc, | 
|  | 1273 | struct iscsi_text *hdr) | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1274 | { | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1275 | struct iscsi_conn *conn = isert_conn->conn; | 
|  | 1276 | u32 payload_length = ntoh24(hdr->dlength); | 
|  | 1277 | int rc; | 
|  | 1278 | unsigned char *text_in; | 
|  | 1279 |  | 
|  | 1280 | rc = iscsit_setup_text_cmd(conn, cmd, hdr); | 
|  | 1281 | if (rc < 0) | 
|  | 1282 | return rc; | 
|  | 1283 |  | 
|  | 1284 | text_in = kzalloc(payload_length, GFP_KERNEL); | 
|  | 1285 | if (!text_in) { | 
|  | 1286 | pr_err("Unable to allocate text_in of payload_length: %u\n", | 
|  | 1287 | payload_length); | 
|  | 1288 | return -ENOMEM; | 
|  | 1289 | } | 
|  | 1290 | cmd->text_in_ptr = text_in; | 
|  | 1291 |  | 
|  | 1292 | memcpy(cmd->text_in_ptr, &rx_desc->data[0], payload_length); | 
|  | 1293 |  | 
|  | 1294 | return iscsit_process_text_cmd(conn, cmd, hdr); | 
|  | 1295 | } | 
|  | 1296 |  | 
|  | 1297 | static int | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1298 | isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, | 
|  | 1299 | uint32_t read_stag, uint64_t read_va, | 
|  | 1300 | uint32_t write_stag, uint64_t write_va) | 
|  | 1301 | { | 
|  | 1302 | struct iscsi_hdr *hdr = &rx_desc->iscsi_header; | 
|  | 1303 | struct iscsi_conn *conn = isert_conn->conn; | 
| Nicholas Bellinger | ca40d24 | 2013-07-07 17:45:08 -0700 | [diff] [blame] | 1304 | struct iscsi_session *sess = conn->sess; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1305 | struct iscsi_cmd *cmd; | 
|  | 1306 | struct isert_cmd *isert_cmd; | 
|  | 1307 | int ret = -EINVAL; | 
|  | 1308 | u8 opcode = (hdr->opcode & ISCSI_OPCODE_MASK); | 
|  | 1309 |  | 
| Nicholas Bellinger | ca40d24 | 2013-07-07 17:45:08 -0700 | [diff] [blame] | 1310 | if (sess->sess_ops->SessionType && | 
|  | 1311 | (!(opcode & ISCSI_OP_TEXT) || !(opcode & ISCSI_OP_LOGOUT))) { | 
|  | 1312 | pr_err("Got illegal opcode: 0x%02x in SessionType=Discovery," | 
|  | 1313 | " ignoring\n", opcode); | 
|  | 1314 | return 0; | 
|  | 1315 | } | 
|  | 1316 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1317 | switch (opcode) { | 
|  | 1318 | case ISCSI_OP_SCSI_CMD: | 
| Nicholas Bellinger | 676687c | 2014-01-20 03:36:44 +0000 | [diff] [blame] | 1319 | cmd = isert_allocate_cmd(conn); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1320 | if (!cmd) | 
|  | 1321 | break; | 
|  | 1322 |  | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1323 | isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1324 | isert_cmd->read_stag = read_stag; | 
|  | 1325 | isert_cmd->read_va = read_va; | 
|  | 1326 | isert_cmd->write_stag = write_stag; | 
|  | 1327 | isert_cmd->write_va = write_va; | 
|  | 1328 |  | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1329 | ret = isert_handle_scsi_cmd(isert_conn, isert_cmd, cmd, | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1330 | rx_desc, (unsigned char *)hdr); | 
|  | 1331 | break; | 
|  | 1332 | case ISCSI_OP_NOOP_OUT: | 
| Nicholas Bellinger | 676687c | 2014-01-20 03:36:44 +0000 | [diff] [blame] | 1333 | cmd = isert_allocate_cmd(conn); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1334 | if (!cmd) | 
|  | 1335 | break; | 
|  | 1336 |  | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1337 | isert_cmd = iscsit_priv_cmd(cmd); | 
|  | 1338 | ret = isert_handle_nop_out(isert_conn, isert_cmd, cmd, | 
| Nicholas Bellinger | 778de36 | 2013-06-14 16:07:47 -0700 | [diff] [blame] | 1339 | rx_desc, (unsigned char *)hdr); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1340 | break; | 
|  | 1341 | case ISCSI_OP_SCSI_DATA_OUT: | 
|  | 1342 | ret = isert_handle_iscsi_dataout(isert_conn, rx_desc, | 
|  | 1343 | (unsigned char *)hdr); | 
|  | 1344 | break; | 
|  | 1345 | case ISCSI_OP_SCSI_TMFUNC: | 
| Nicholas Bellinger | 676687c | 2014-01-20 03:36:44 +0000 | [diff] [blame] | 1346 | cmd = isert_allocate_cmd(conn); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1347 | if (!cmd) | 
|  | 1348 | break; | 
|  | 1349 |  | 
|  | 1350 | ret = iscsit_handle_task_mgt_cmd(conn, cmd, | 
|  | 1351 | (unsigned char *)hdr); | 
|  | 1352 | break; | 
|  | 1353 | case ISCSI_OP_LOGOUT: | 
| Nicholas Bellinger | 676687c | 2014-01-20 03:36:44 +0000 | [diff] [blame] | 1354 | cmd = isert_allocate_cmd(conn); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1355 | if (!cmd) | 
|  | 1356 | break; | 
|  | 1357 |  | 
|  | 1358 | ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr); | 
|  | 1359 | if (ret > 0) | 
|  | 1360 | wait_for_completion_timeout(&conn->conn_logout_comp, | 
|  | 1361 | SECONDS_FOR_LOGOUT_COMP * | 
|  | 1362 | HZ); | 
|  | 1363 | break; | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1364 | case ISCSI_OP_TEXT: | 
| Nicholas Bellinger | 676687c | 2014-01-20 03:36:44 +0000 | [diff] [blame] | 1365 | cmd = isert_allocate_cmd(conn); | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1366 | if (!cmd) | 
|  | 1367 | break; | 
|  | 1368 |  | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1369 | isert_cmd = iscsit_priv_cmd(cmd); | 
|  | 1370 | ret = isert_handle_text_cmd(isert_conn, isert_cmd, cmd, | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1371 | rx_desc, (struct iscsi_text *)hdr); | 
|  | 1372 | break; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1373 | default: | 
|  | 1374 | pr_err("Got unknown iSCSI OpCode: 0x%02x\n", opcode); | 
|  | 1375 | dump_stack(); | 
|  | 1376 | break; | 
|  | 1377 | } | 
|  | 1378 |  | 
|  | 1379 | return ret; | 
|  | 1380 | } | 
|  | 1381 |  | 
|  | 1382 | static void | 
|  | 1383 | isert_rx_do_work(struct iser_rx_desc *rx_desc, struct isert_conn *isert_conn) | 
|  | 1384 | { | 
|  | 1385 | struct iser_hdr *iser_hdr = &rx_desc->iser_header; | 
|  | 1386 | uint64_t read_va = 0, write_va = 0; | 
|  | 1387 | uint32_t read_stag = 0, write_stag = 0; | 
|  | 1388 | int rc; | 
|  | 1389 |  | 
|  | 1390 | switch (iser_hdr->flags & 0xF0) { | 
|  | 1391 | case ISCSI_CTRL: | 
|  | 1392 | if (iser_hdr->flags & ISER_RSV) { | 
|  | 1393 | read_stag = be32_to_cpu(iser_hdr->read_stag); | 
|  | 1394 | read_va = be64_to_cpu(iser_hdr->read_va); | 
|  | 1395 | pr_debug("ISER_RSV: read_stag: 0x%08x read_va: 0x%16llx\n", | 
|  | 1396 | read_stag, (unsigned long long)read_va); | 
|  | 1397 | } | 
|  | 1398 | if (iser_hdr->flags & ISER_WSV) { | 
|  | 1399 | write_stag = be32_to_cpu(iser_hdr->write_stag); | 
|  | 1400 | write_va = be64_to_cpu(iser_hdr->write_va); | 
|  | 1401 | pr_debug("ISER_WSV: write__stag: 0x%08x write_va: 0x%16llx\n", | 
|  | 1402 | write_stag, (unsigned long long)write_va); | 
|  | 1403 | } | 
|  | 1404 |  | 
|  | 1405 | pr_debug("ISER ISCSI_CTRL PDU\n"); | 
|  | 1406 | break; | 
|  | 1407 | case ISER_HELLO: | 
|  | 1408 | pr_err("iSER Hello message\n"); | 
|  | 1409 | break; | 
|  | 1410 | default: | 
|  | 1411 | pr_warn("Unknown iSER hdr flags: 0x%02x\n", iser_hdr->flags); | 
|  | 1412 | break; | 
|  | 1413 | } | 
|  | 1414 |  | 
|  | 1415 | rc = isert_rx_opcode(isert_conn, rx_desc, | 
|  | 1416 | read_stag, read_va, write_stag, write_va); | 
|  | 1417 | } | 
|  | 1418 |  | 
|  | 1419 | static void | 
|  | 1420 | isert_rx_completion(struct iser_rx_desc *desc, struct isert_conn *isert_conn, | 
|  | 1421 | unsigned long xfer_len) | 
|  | 1422 | { | 
|  | 1423 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 1424 | struct iscsi_hdr *hdr; | 
|  | 1425 | u64 rx_dma; | 
|  | 1426 | int rx_buflen, outstanding; | 
|  | 1427 |  | 
|  | 1428 | if ((char *)desc == isert_conn->login_req_buf) { | 
|  | 1429 | rx_dma = isert_conn->login_req_dma; | 
|  | 1430 | rx_buflen = ISER_RX_LOGIN_SIZE; | 
|  | 1431 | pr_debug("ISER login_buf: Using rx_dma: 0x%llx, rx_buflen: %d\n", | 
|  | 1432 | rx_dma, rx_buflen); | 
|  | 1433 | } else { | 
|  | 1434 | rx_dma = desc->dma_addr; | 
|  | 1435 | rx_buflen = ISER_RX_PAYLOAD_SIZE; | 
|  | 1436 | pr_debug("ISER req_buf: Using rx_dma: 0x%llx, rx_buflen: %d\n", | 
|  | 1437 | rx_dma, rx_buflen); | 
|  | 1438 | } | 
|  | 1439 |  | 
|  | 1440 | ib_dma_sync_single_for_cpu(ib_dev, rx_dma, rx_buflen, DMA_FROM_DEVICE); | 
|  | 1441 |  | 
|  | 1442 | hdr = &desc->iscsi_header; | 
|  | 1443 | pr_debug("iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n", | 
|  | 1444 | hdr->opcode, hdr->itt, hdr->flags, | 
|  | 1445 | (int)(xfer_len - ISER_HEADERS_LEN)); | 
|  | 1446 |  | 
|  | 1447 | if ((char *)desc == isert_conn->login_req_buf) | 
|  | 1448 | isert_rx_login_req(desc, xfer_len - ISER_HEADERS_LEN, | 
|  | 1449 | isert_conn); | 
|  | 1450 | else | 
|  | 1451 | isert_rx_do_work(desc, isert_conn); | 
|  | 1452 |  | 
|  | 1453 | ib_dma_sync_single_for_device(ib_dev, rx_dma, rx_buflen, | 
|  | 1454 | DMA_FROM_DEVICE); | 
|  | 1455 |  | 
|  | 1456 | isert_conn->post_recv_buf_count--; | 
|  | 1457 | pr_debug("iSERT: Decremented post_recv_buf_count: %d\n", | 
|  | 1458 | isert_conn->post_recv_buf_count); | 
|  | 1459 |  | 
|  | 1460 | if ((char *)desc == isert_conn->login_req_buf) | 
|  | 1461 | return; | 
|  | 1462 |  | 
|  | 1463 | outstanding = isert_conn->post_recv_buf_count; | 
|  | 1464 | if (outstanding + ISERT_MIN_POSTED_RX <= ISERT_QP_MAX_RECV_DTOS) { | 
|  | 1465 | int err, count = min(ISERT_QP_MAX_RECV_DTOS - outstanding, | 
|  | 1466 | ISERT_MIN_POSTED_RX); | 
|  | 1467 | err = isert_post_recv(isert_conn, count); | 
|  | 1468 | if (err) { | 
|  | 1469 | pr_err("isert_post_recv() count: %d failed, %d\n", | 
|  | 1470 | count, err); | 
|  | 1471 | } | 
|  | 1472 | } | 
|  | 1473 | } | 
|  | 1474 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 1475 | static int | 
|  | 1476 | isert_map_data_buf(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | 
|  | 1477 | struct scatterlist *sg, u32 nents, u32 length, u32 offset, | 
|  | 1478 | enum iser_ib_op_code op, struct isert_data_buf *data) | 
|  | 1479 | { | 
|  | 1480 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 1481 |  | 
|  | 1482 | data->dma_dir = op == ISER_IB_RDMA_WRITE ? | 
|  | 1483 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | 
|  | 1484 |  | 
|  | 1485 | data->len = length - offset; | 
|  | 1486 | data->offset = offset; | 
|  | 1487 | data->sg_off = data->offset / PAGE_SIZE; | 
|  | 1488 |  | 
|  | 1489 | data->sg = &sg[data->sg_off]; | 
|  | 1490 | data->nents = min_t(unsigned int, nents - data->sg_off, | 
|  | 1491 | ISCSI_ISER_SG_TABLESIZE); | 
|  | 1492 | data->len = min_t(unsigned int, data->len, ISCSI_ISER_SG_TABLESIZE * | 
|  | 1493 | PAGE_SIZE); | 
|  | 1494 |  | 
|  | 1495 | data->dma_nents = ib_dma_map_sg(ib_dev, data->sg, data->nents, | 
|  | 1496 | data->dma_dir); | 
|  | 1497 | if (unlikely(!data->dma_nents)) { | 
|  | 1498 | pr_err("Cmd: unable to dma map SGs %p\n", sg); | 
|  | 1499 | return -EINVAL; | 
|  | 1500 | } | 
|  | 1501 |  | 
|  | 1502 | pr_debug("Mapped cmd: %p count: %u sg: %p sg_nents: %u rdma_len %d\n", | 
|  | 1503 | isert_cmd, data->dma_nents, data->sg, data->nents, data->len); | 
|  | 1504 |  | 
|  | 1505 | return 0; | 
|  | 1506 | } | 
|  | 1507 |  | 
|  | 1508 | static void | 
|  | 1509 | isert_unmap_data_buf(struct isert_conn *isert_conn, struct isert_data_buf *data) | 
|  | 1510 | { | 
|  | 1511 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 1512 |  | 
|  | 1513 | ib_dma_unmap_sg(ib_dev, data->sg, data->nents, data->dma_dir); | 
|  | 1514 | memset(data, 0, sizeof(*data)); | 
|  | 1515 | } | 
|  | 1516 |  | 
|  | 1517 |  | 
|  | 1518 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1519 | static void | 
|  | 1520 | isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn) | 
|  | 1521 | { | 
|  | 1522 | struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1523 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 1524 | pr_debug("isert_unmap_cmd: %p\n", isert_cmd); | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 1525 |  | 
|  | 1526 | if (wr->data.sg) { | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 1527 | pr_debug("isert_unmap_cmd: %p unmap_sg op\n", isert_cmd); | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 1528 | isert_unmap_data_buf(isert_conn, &wr->data); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1529 | } | 
|  | 1530 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 1531 | if (wr->send_wr) { | 
|  | 1532 | pr_debug("isert_unmap_cmd: %p free send_wr\n", isert_cmd); | 
|  | 1533 | kfree(wr->send_wr); | 
|  | 1534 | wr->send_wr = NULL; | 
|  | 1535 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1536 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 1537 | if (wr->ib_sge) { | 
|  | 1538 | pr_debug("isert_unmap_cmd: %p free ib_sge\n", isert_cmd); | 
|  | 1539 | kfree(wr->ib_sge); | 
|  | 1540 | wr->ib_sge = NULL; | 
|  | 1541 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1542 | } | 
|  | 1543 |  | 
|  | 1544 | static void | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 1545 | isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn) | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 1546 | { | 
|  | 1547 | struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 1548 | LIST_HEAD(unmap_list); | 
|  | 1549 |  | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 1550 | pr_debug("unreg_fastreg_cmd: %p\n", isert_cmd); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 1551 |  | 
|  | 1552 | if (wr->fr_desc) { | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 1553 | pr_debug("unreg_fastreg_cmd: %p free fr_desc %p\n", | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 1554 | isert_cmd, wr->fr_desc); | 
|  | 1555 | spin_lock_bh(&isert_conn->conn_lock); | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 1556 | list_add_tail(&wr->fr_desc->list, &isert_conn->conn_fr_pool); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 1557 | spin_unlock_bh(&isert_conn->conn_lock); | 
|  | 1558 | wr->fr_desc = NULL; | 
|  | 1559 | } | 
|  | 1560 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 1561 | if (wr->data.sg) { | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 1562 | pr_debug("unreg_fastreg_cmd: %p unmap_sg op\n", isert_cmd); | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 1563 | isert_unmap_data_buf(isert_conn, &wr->data); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 1564 | } | 
|  | 1565 |  | 
|  | 1566 | wr->ib_sge = NULL; | 
|  | 1567 | wr->send_wr = NULL; | 
|  | 1568 | } | 
|  | 1569 |  | 
|  | 1570 | static void | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1571 | isert_put_cmd(struct isert_cmd *isert_cmd) | 
|  | 1572 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1573 | struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1574 | struct isert_conn *isert_conn = isert_cmd->conn; | 
| Nicholas Bellinger | 186a964 | 2013-07-03 03:11:48 -0700 | [diff] [blame] | 1575 | struct iscsi_conn *conn = isert_conn->conn; | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 1576 | struct isert_device *device = isert_conn->conn_device; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1577 |  | 
|  | 1578 | pr_debug("Entering isert_put_cmd: %p\n", isert_cmd); | 
|  | 1579 |  | 
|  | 1580 | switch (cmd->iscsi_opcode) { | 
|  | 1581 | case ISCSI_OP_SCSI_CMD: | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1582 | spin_lock_bh(&conn->cmd_lock); | 
|  | 1583 | if (!list_empty(&cmd->i_conn_node)) | 
| Nicholas Bellinger | 5159d76 | 2014-02-03 12:53:51 -0800 | [diff] [blame] | 1584 | list_del_init(&cmd->i_conn_node); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1585 | spin_unlock_bh(&conn->cmd_lock); | 
|  | 1586 |  | 
|  | 1587 | if (cmd->data_direction == DMA_TO_DEVICE) | 
|  | 1588 | iscsit_stop_dataout_timer(cmd); | 
|  | 1589 |  | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 1590 | device->unreg_rdma_mem(isert_cmd, isert_conn); | 
| Nicholas Bellinger | 186a964 | 2013-07-03 03:11:48 -0700 | [diff] [blame] | 1591 | transport_generic_free_cmd(&cmd->se_cmd, 0); | 
|  | 1592 | break; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1593 | case ISCSI_OP_SCSI_TMFUNC: | 
| Nicholas Bellinger | 186a964 | 2013-07-03 03:11:48 -0700 | [diff] [blame] | 1594 | spin_lock_bh(&conn->cmd_lock); | 
|  | 1595 | if (!list_empty(&cmd->i_conn_node)) | 
| Nicholas Bellinger | 5159d76 | 2014-02-03 12:53:51 -0800 | [diff] [blame] | 1596 | list_del_init(&cmd->i_conn_node); | 
| Nicholas Bellinger | 186a964 | 2013-07-03 03:11:48 -0700 | [diff] [blame] | 1597 | spin_unlock_bh(&conn->cmd_lock); | 
|  | 1598 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1599 | transport_generic_free_cmd(&cmd->se_cmd, 0); | 
|  | 1600 | break; | 
|  | 1601 | case ISCSI_OP_REJECT: | 
|  | 1602 | case ISCSI_OP_NOOP_OUT: | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1603 | case ISCSI_OP_TEXT: | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1604 | spin_lock_bh(&conn->cmd_lock); | 
|  | 1605 | if (!list_empty(&cmd->i_conn_node)) | 
| Nicholas Bellinger | 5159d76 | 2014-02-03 12:53:51 -0800 | [diff] [blame] | 1606 | list_del_init(&cmd->i_conn_node); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1607 | spin_unlock_bh(&conn->cmd_lock); | 
|  | 1608 |  | 
|  | 1609 | /* | 
|  | 1610 | * Handle special case for REJECT when iscsi_add_reject*() has | 
|  | 1611 | * overwritten the original iscsi_opcode assignment, and the | 
|  | 1612 | * associated cmd->se_cmd needs to be released. | 
|  | 1613 | */ | 
|  | 1614 | if (cmd->se_cmd.se_tfo != NULL) { | 
| Nicholas Bellinger | 3df8f68 | 2013-06-26 02:31:42 -0700 | [diff] [blame] | 1615 | pr_debug("Calling transport_generic_free_cmd from" | 
|  | 1616 | " isert_put_cmd for 0x%02x\n", | 
|  | 1617 | cmd->iscsi_opcode); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1618 | transport_generic_free_cmd(&cmd->se_cmd, 0); | 
|  | 1619 | break; | 
|  | 1620 | } | 
|  | 1621 | /* | 
|  | 1622 | * Fall-through | 
|  | 1623 | */ | 
|  | 1624 | default: | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1625 | iscsit_release_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1626 | break; | 
|  | 1627 | } | 
|  | 1628 | } | 
|  | 1629 |  | 
|  | 1630 | static void | 
|  | 1631 | isert_unmap_tx_desc(struct iser_tx_desc *tx_desc, struct ib_device *ib_dev) | 
|  | 1632 | { | 
|  | 1633 | if (tx_desc->dma_addr != 0) { | 
|  | 1634 | pr_debug("Calling ib_dma_unmap_single for tx_desc->dma_addr\n"); | 
|  | 1635 | ib_dma_unmap_single(ib_dev, tx_desc->dma_addr, | 
|  | 1636 | ISER_HEADERS_LEN, DMA_TO_DEVICE); | 
|  | 1637 | tx_desc->dma_addr = 0; | 
|  | 1638 | } | 
|  | 1639 | } | 
|  | 1640 |  | 
|  | 1641 | static void | 
|  | 1642 | isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, | 
|  | 1643 | struct ib_device *ib_dev) | 
|  | 1644 | { | 
| Nicholas Bellinger | dbbc5d1 | 2013-07-03 19:39:37 -0700 | [diff] [blame] | 1645 | if (isert_cmd->pdu_buf_dma != 0) { | 
|  | 1646 | pr_debug("Calling ib_dma_unmap_single for isert_cmd->pdu_buf_dma\n"); | 
|  | 1647 | ib_dma_unmap_single(ib_dev, isert_cmd->pdu_buf_dma, | 
|  | 1648 | isert_cmd->pdu_buf_len, DMA_TO_DEVICE); | 
|  | 1649 | isert_cmd->pdu_buf_dma = 0; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1650 | } | 
|  | 1651 |  | 
|  | 1652 | isert_unmap_tx_desc(tx_desc, ib_dev); | 
|  | 1653 | isert_put_cmd(isert_cmd); | 
|  | 1654 | } | 
|  | 1655 |  | 
|  | 1656 | static void | 
| Sagi Grimberg | f93f3a7 | 2014-02-19 17:50:24 +0200 | [diff] [blame^] | 1657 | isert_completion_rdma_write(struct iser_tx_desc *tx_desc, | 
|  | 1658 | struct isert_cmd *isert_cmd) | 
|  | 1659 | { | 
|  | 1660 | struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; | 
|  | 1661 | struct isert_conn *isert_conn = isert_cmd->conn; | 
|  | 1662 | struct isert_device *device = isert_conn->conn_device; | 
|  | 1663 |  | 
|  | 1664 | device->unreg_rdma_mem(isert_cmd, isert_conn); | 
|  | 1665 | isert_put_response(isert_conn->conn, cmd); | 
|  | 1666 | } | 
|  | 1667 |  | 
|  | 1668 | static void | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1669 | isert_completion_rdma_read(struct iser_tx_desc *tx_desc, | 
|  | 1670 | struct isert_cmd *isert_cmd) | 
|  | 1671 | { | 
|  | 1672 | struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1673 | struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1674 | struct se_cmd *se_cmd = &cmd->se_cmd; | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 1675 | struct isert_conn *isert_conn = isert_cmd->conn; | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 1676 | struct isert_device *device = isert_conn->conn_device; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1677 |  | 
|  | 1678 | iscsit_stop_dataout_timer(cmd); | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 1679 | device->unreg_rdma_mem(isert_cmd, isert_conn); | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 1680 | cmd->write_data_done = wr->data.len; | 
| Nicholas Bellinger | b6b87a1 | 2014-02-27 09:05:03 -0800 | [diff] [blame] | 1681 | wr->send_wr_num = 0; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1682 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 1683 | pr_debug("Cmd: %p RDMA_READ comp calling execute_cmd\n", isert_cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1684 | spin_lock_bh(&cmd->istate_lock); | 
|  | 1685 | cmd->cmd_flags |= ICF_GOT_LAST_DATAOUT; | 
|  | 1686 | cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT; | 
|  | 1687 | spin_unlock_bh(&cmd->istate_lock); | 
|  | 1688 |  | 
|  | 1689 | target_execute_cmd(se_cmd); | 
|  | 1690 | } | 
|  | 1691 |  | 
|  | 1692 | static void | 
|  | 1693 | isert_do_control_comp(struct work_struct *work) | 
|  | 1694 | { | 
|  | 1695 | struct isert_cmd *isert_cmd = container_of(work, | 
|  | 1696 | struct isert_cmd, comp_work); | 
|  | 1697 | struct isert_conn *isert_conn = isert_cmd->conn; | 
|  | 1698 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1699 | struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1700 |  | 
|  | 1701 | switch (cmd->i_state) { | 
|  | 1702 | case ISTATE_SEND_TASKMGTRSP: | 
|  | 1703 | pr_debug("Calling iscsit_tmr_post_handler >>>>>>>>>>>>>>>>>\n"); | 
|  | 1704 |  | 
|  | 1705 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 1706 | iscsit_tmr_post_handler(cmd, cmd->conn); | 
|  | 1707 |  | 
|  | 1708 | cmd->i_state = ISTATE_SENT_STATUS; | 
|  | 1709 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); | 
|  | 1710 | break; | 
|  | 1711 | case ISTATE_SEND_REJECT: | 
|  | 1712 | pr_debug("Got isert_do_control_comp ISTATE_SEND_REJECT: >>>\n"); | 
|  | 1713 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 1714 |  | 
|  | 1715 | cmd->i_state = ISTATE_SENT_STATUS; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1716 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); | 
| Nicholas Bellinger | 3df8f68 | 2013-06-26 02:31:42 -0700 | [diff] [blame] | 1717 | break; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1718 | case ISTATE_SEND_LOGOUTRSP: | 
|  | 1719 | pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); | 
|  | 1720 | /* | 
|  | 1721 | * Call atomic_dec(&isert_conn->post_send_buf_count) | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1722 | * from isert_wait_conn() | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1723 | */ | 
|  | 1724 | isert_conn->logout_posted = true; | 
|  | 1725 | iscsit_logout_post_handler(cmd, cmd->conn); | 
|  | 1726 | break; | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1727 | case ISTATE_SEND_TEXTRSP: | 
|  | 1728 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 1729 | cmd->i_state = ISTATE_SENT_STATUS; | 
|  | 1730 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); | 
|  | 1731 | break; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1732 | default: | 
|  | 1733 | pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state); | 
|  | 1734 | dump_stack(); | 
|  | 1735 | break; | 
|  | 1736 | } | 
|  | 1737 | } | 
|  | 1738 |  | 
|  | 1739 | static void | 
|  | 1740 | isert_response_completion(struct iser_tx_desc *tx_desc, | 
|  | 1741 | struct isert_cmd *isert_cmd, | 
|  | 1742 | struct isert_conn *isert_conn, | 
|  | 1743 | struct ib_device *ib_dev) | 
|  | 1744 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 1745 | struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; | 
| Nicholas Bellinger | b6b87a1 | 2014-02-27 09:05:03 -0800 | [diff] [blame] | 1746 | struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1747 |  | 
|  | 1748 | if (cmd->i_state == ISTATE_SEND_TASKMGTRSP || | 
| Nicholas Bellinger | 3df8f68 | 2013-06-26 02:31:42 -0700 | [diff] [blame] | 1749 | cmd->i_state == ISTATE_SEND_LOGOUTRSP || | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 1750 | cmd->i_state == ISTATE_SEND_REJECT || | 
|  | 1751 | cmd->i_state == ISTATE_SEND_TEXTRSP) { | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1752 | isert_unmap_tx_desc(tx_desc, ib_dev); | 
|  | 1753 |  | 
|  | 1754 | INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp); | 
|  | 1755 | queue_work(isert_comp_wq, &isert_cmd->comp_work); | 
|  | 1756 | return; | 
|  | 1757 | } | 
| Nicholas Bellinger | b6b87a1 | 2014-02-27 09:05:03 -0800 | [diff] [blame] | 1758 | atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1759 |  | 
|  | 1760 | cmd->i_state = ISTATE_SENT_STATUS; | 
|  | 1761 | isert_completion_put(tx_desc, isert_cmd, ib_dev); | 
|  | 1762 | } | 
|  | 1763 |  | 
|  | 1764 | static void | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 1765 | __isert_send_completion(struct iser_tx_desc *tx_desc, | 
|  | 1766 | struct isert_conn *isert_conn) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1767 | { | 
|  | 1768 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 1769 | struct isert_cmd *isert_cmd = tx_desc->isert_cmd; | 
|  | 1770 | struct isert_rdma_wr *wr; | 
|  | 1771 |  | 
|  | 1772 | if (!isert_cmd) { | 
|  | 1773 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 1774 | isert_unmap_tx_desc(tx_desc, ib_dev); | 
|  | 1775 | return; | 
|  | 1776 | } | 
|  | 1777 | wr = &isert_cmd->rdma_wr; | 
|  | 1778 |  | 
|  | 1779 | switch (wr->iser_ib_op) { | 
|  | 1780 | case ISER_IB_RECV: | 
|  | 1781 | pr_err("isert_send_completion: Got ISER_IB_RECV\n"); | 
|  | 1782 | dump_stack(); | 
|  | 1783 | break; | 
|  | 1784 | case ISER_IB_SEND: | 
|  | 1785 | pr_debug("isert_send_completion: Got ISER_IB_SEND\n"); | 
|  | 1786 | isert_response_completion(tx_desc, isert_cmd, | 
|  | 1787 | isert_conn, ib_dev); | 
|  | 1788 | break; | 
|  | 1789 | case ISER_IB_RDMA_WRITE: | 
| Sagi Grimberg | f93f3a7 | 2014-02-19 17:50:24 +0200 | [diff] [blame^] | 1790 | pr_debug("isert_send_completion: Got ISER_IB_RDMA_WRITE\n"); | 
|  | 1791 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 1792 | isert_completion_rdma_write(tx_desc, isert_cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1793 | break; | 
|  | 1794 | case ISER_IB_RDMA_READ: | 
|  | 1795 | pr_debug("isert_send_completion: Got ISER_IB_RDMA_READ:\n"); | 
|  | 1796 |  | 
| Nicholas Bellinger | b6b87a1 | 2014-02-27 09:05:03 -0800 | [diff] [blame] | 1797 | atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1798 | isert_completion_rdma_read(tx_desc, isert_cmd); | 
|  | 1799 | break; | 
|  | 1800 | default: | 
|  | 1801 | pr_err("Unknown wr->iser_ib_op: 0x%02x\n", wr->iser_ib_op); | 
|  | 1802 | dump_stack(); | 
|  | 1803 | break; | 
|  | 1804 | } | 
|  | 1805 | } | 
|  | 1806 |  | 
|  | 1807 | static void | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 1808 | isert_send_completion(struct iser_tx_desc *tx_desc, | 
|  | 1809 | struct isert_conn *isert_conn) | 
|  | 1810 | { | 
|  | 1811 | struct llist_node *llnode = tx_desc->comp_llnode_batch; | 
|  | 1812 | struct iser_tx_desc *t; | 
|  | 1813 | /* | 
|  | 1814 | * Drain coalesced completion llist starting from comp_llnode_batch | 
|  | 1815 | * setup in isert_init_send_wr(), and then complete trailing tx_desc. | 
|  | 1816 | */ | 
|  | 1817 | while (llnode) { | 
|  | 1818 | t = llist_entry(llnode, struct iser_tx_desc, comp_llnode); | 
|  | 1819 | llnode = llist_next(llnode); | 
|  | 1820 | __isert_send_completion(t, isert_conn); | 
|  | 1821 | } | 
|  | 1822 | __isert_send_completion(tx_desc, isert_conn); | 
|  | 1823 | } | 
|  | 1824 |  | 
|  | 1825 | static void | 
| Nicholas Bellinger | ebbe442 | 2014-03-02 14:51:12 -0800 | [diff] [blame] | 1826 | isert_cq_drain_comp_llist(struct isert_conn *isert_conn, struct ib_device *ib_dev) | 
|  | 1827 | { | 
|  | 1828 | struct llist_node *llnode; | 
|  | 1829 | struct isert_rdma_wr *wr; | 
|  | 1830 | struct iser_tx_desc *t; | 
|  | 1831 |  | 
|  | 1832 | mutex_lock(&isert_conn->conn_mutex); | 
|  | 1833 | llnode = llist_del_all(&isert_conn->conn_comp_llist); | 
|  | 1834 | isert_conn->conn_comp_batch = 0; | 
|  | 1835 | mutex_unlock(&isert_conn->conn_mutex); | 
|  | 1836 |  | 
|  | 1837 | while (llnode) { | 
|  | 1838 | t = llist_entry(llnode, struct iser_tx_desc, comp_llnode); | 
|  | 1839 | llnode = llist_next(llnode); | 
|  | 1840 | wr = &t->isert_cmd->rdma_wr; | 
|  | 1841 |  | 
|  | 1842 | atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); | 
|  | 1843 | isert_completion_put(t, t->isert_cmd, ib_dev); | 
|  | 1844 | } | 
|  | 1845 | } | 
|  | 1846 |  | 
|  | 1847 | static void | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1848 | isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1849 | { | 
|  | 1850 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1851 | struct isert_cmd *isert_cmd = tx_desc->isert_cmd; | 
| Nicholas Bellinger | ebbe442 | 2014-03-02 14:51:12 -0800 | [diff] [blame] | 1852 | struct llist_node *llnode = tx_desc->comp_llnode_batch; | 
|  | 1853 | struct isert_rdma_wr *wr; | 
|  | 1854 | struct iser_tx_desc *t; | 
|  | 1855 |  | 
|  | 1856 | while (llnode) { | 
|  | 1857 | t = llist_entry(llnode, struct iser_tx_desc, comp_llnode); | 
|  | 1858 | llnode = llist_next(llnode); | 
|  | 1859 | wr = &t->isert_cmd->rdma_wr; | 
|  | 1860 |  | 
|  | 1861 | atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); | 
|  | 1862 | isert_completion_put(t, t->isert_cmd, ib_dev); | 
|  | 1863 | } | 
|  | 1864 | tx_desc->comp_llnode_batch = NULL; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1865 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1866 | if (!isert_cmd) | 
|  | 1867 | isert_unmap_tx_desc(tx_desc, ib_dev); | 
|  | 1868 | else | 
|  | 1869 | isert_completion_put(tx_desc, isert_cmd, ib_dev); | 
|  | 1870 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1871 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1872 | static void | 
|  | 1873 | isert_cq_rx_comp_err(struct isert_conn *isert_conn) | 
|  | 1874 | { | 
|  | 1875 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 1876 | struct iscsi_conn *conn = isert_conn->conn; | 
|  | 1877 |  | 
|  | 1878 | if (isert_conn->post_recv_buf_count) | 
|  | 1879 | return; | 
|  | 1880 |  | 
| Nicholas Bellinger | ebbe442 | 2014-03-02 14:51:12 -0800 | [diff] [blame] | 1881 | isert_cq_drain_comp_llist(isert_conn, ib_dev); | 
|  | 1882 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1883 | if (conn->sess) { | 
|  | 1884 | target_sess_cmd_list_set_waiting(conn->sess->se_sess); | 
|  | 1885 | target_wait_for_sess_cmds(conn->sess->se_sess); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1886 | } | 
|  | 1887 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1888 | while (atomic_read(&isert_conn->post_send_buf_count)) | 
|  | 1889 | msleep(3000); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1890 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1891 | mutex_lock(&isert_conn->conn_mutex); | 
|  | 1892 | isert_conn->state = ISER_CONN_DOWN; | 
|  | 1893 | mutex_unlock(&isert_conn->conn_mutex); | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 1894 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1895 | complete(&isert_conn->conn_wait_comp_err); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1896 | } | 
|  | 1897 |  | 
|  | 1898 | static void | 
|  | 1899 | isert_cq_tx_work(struct work_struct *work) | 
|  | 1900 | { | 
|  | 1901 | struct isert_cq_desc *cq_desc = container_of(work, | 
|  | 1902 | struct isert_cq_desc, cq_tx_work); | 
|  | 1903 | struct isert_device *device = cq_desc->device; | 
|  | 1904 | int cq_index = cq_desc->cq_index; | 
|  | 1905 | struct ib_cq *tx_cq = device->dev_tx_cq[cq_index]; | 
|  | 1906 | struct isert_conn *isert_conn; | 
|  | 1907 | struct iser_tx_desc *tx_desc; | 
|  | 1908 | struct ib_wc wc; | 
|  | 1909 |  | 
|  | 1910 | while (ib_poll_cq(tx_cq, 1, &wc) == 1) { | 
|  | 1911 | tx_desc = (struct iser_tx_desc *)(unsigned long)wc.wr_id; | 
|  | 1912 | isert_conn = wc.qp->qp_context; | 
|  | 1913 |  | 
|  | 1914 | if (wc.status == IB_WC_SUCCESS) { | 
|  | 1915 | isert_send_completion(tx_desc, isert_conn); | 
|  | 1916 | } else { | 
|  | 1917 | pr_debug("TX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); | 
|  | 1918 | pr_debug("TX wc.status: 0x%08x\n", wc.status); | 
| Nicholas Bellinger | c5a2adb | 2013-07-01 15:11:21 -0700 | [diff] [blame] | 1919 | pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err); | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1920 |  | 
| Nicholas Bellinger | 9bb4ca6 | 2014-02-27 07:02:48 -0800 | [diff] [blame] | 1921 | if (wc.wr_id != ISER_FASTREG_LI_WRID) { | 
| Nicholas Bellinger | ebbe442 | 2014-03-02 14:51:12 -0800 | [diff] [blame] | 1922 | if (tx_desc->llnode_active) | 
|  | 1923 | continue; | 
|  | 1924 |  | 
| Nicholas Bellinger | 9bb4ca6 | 2014-02-27 07:02:48 -0800 | [diff] [blame] | 1925 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 1926 | isert_cq_tx_comp_err(tx_desc, isert_conn); | 
|  | 1927 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1928 | } | 
|  | 1929 | } | 
|  | 1930 |  | 
|  | 1931 | ib_req_notify_cq(tx_cq, IB_CQ_NEXT_COMP); | 
|  | 1932 | } | 
|  | 1933 |  | 
|  | 1934 | static void | 
|  | 1935 | isert_cq_tx_callback(struct ib_cq *cq, void *context) | 
|  | 1936 | { | 
|  | 1937 | struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context; | 
|  | 1938 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1939 | queue_work(isert_comp_wq, &cq_desc->cq_tx_work); | 
|  | 1940 | } | 
|  | 1941 |  | 
|  | 1942 | static void | 
|  | 1943 | isert_cq_rx_work(struct work_struct *work) | 
|  | 1944 | { | 
|  | 1945 | struct isert_cq_desc *cq_desc = container_of(work, | 
|  | 1946 | struct isert_cq_desc, cq_rx_work); | 
|  | 1947 | struct isert_device *device = cq_desc->device; | 
|  | 1948 | int cq_index = cq_desc->cq_index; | 
|  | 1949 | struct ib_cq *rx_cq = device->dev_rx_cq[cq_index]; | 
|  | 1950 | struct isert_conn *isert_conn; | 
|  | 1951 | struct iser_rx_desc *rx_desc; | 
|  | 1952 | struct ib_wc wc; | 
|  | 1953 | unsigned long xfer_len; | 
|  | 1954 |  | 
|  | 1955 | while (ib_poll_cq(rx_cq, 1, &wc) == 1) { | 
|  | 1956 | rx_desc = (struct iser_rx_desc *)(unsigned long)wc.wr_id; | 
|  | 1957 | isert_conn = wc.qp->qp_context; | 
|  | 1958 |  | 
|  | 1959 | if (wc.status == IB_WC_SUCCESS) { | 
|  | 1960 | xfer_len = (unsigned long)wc.byte_len; | 
|  | 1961 | isert_rx_completion(rx_desc, isert_conn, xfer_len); | 
|  | 1962 | } else { | 
|  | 1963 | pr_debug("RX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); | 
| Nicholas Bellinger | c5a2adb | 2013-07-01 15:11:21 -0700 | [diff] [blame] | 1964 | if (wc.status != IB_WC_WR_FLUSH_ERR) { | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1965 | pr_debug("RX wc.status: 0x%08x\n", wc.status); | 
| Nicholas Bellinger | c5a2adb | 2013-07-01 15:11:21 -0700 | [diff] [blame] | 1966 | pr_debug("RX wc.vendor_err: 0x%08x\n", | 
|  | 1967 | wc.vendor_err); | 
|  | 1968 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1969 | isert_conn->post_recv_buf_count--; | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 1970 | isert_cq_rx_comp_err(isert_conn); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1971 | } | 
|  | 1972 | } | 
|  | 1973 |  | 
|  | 1974 | ib_req_notify_cq(rx_cq, IB_CQ_NEXT_COMP); | 
|  | 1975 | } | 
|  | 1976 |  | 
|  | 1977 | static void | 
|  | 1978 | isert_cq_rx_callback(struct ib_cq *cq, void *context) | 
|  | 1979 | { | 
|  | 1980 | struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context; | 
|  | 1981 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 1982 | queue_work(isert_rx_wq, &cq_desc->cq_rx_work); | 
|  | 1983 | } | 
|  | 1984 |  | 
|  | 1985 | static int | 
|  | 1986 | isert_post_response(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd) | 
|  | 1987 | { | 
|  | 1988 | struct ib_send_wr *wr_failed; | 
|  | 1989 | int ret; | 
|  | 1990 |  | 
|  | 1991 | atomic_inc(&isert_conn->post_send_buf_count); | 
|  | 1992 |  | 
|  | 1993 | ret = ib_post_send(isert_conn->conn_qp, &isert_cmd->tx_desc.send_wr, | 
|  | 1994 | &wr_failed); | 
|  | 1995 | if (ret) { | 
|  | 1996 | pr_err("ib_post_send failed with %d\n", ret); | 
|  | 1997 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 1998 | return ret; | 
|  | 1999 | } | 
|  | 2000 | return ret; | 
|  | 2001 | } | 
|  | 2002 |  | 
|  | 2003 | static int | 
|  | 2004 | isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd) | 
|  | 2005 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2006 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2007 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
|  | 2008 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | 
|  | 2009 | struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *) | 
|  | 2010 | &isert_cmd->tx_desc.iscsi_header; | 
|  | 2011 |  | 
|  | 2012 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | 
|  | 2013 | iscsit_build_rsp_pdu(cmd, conn, true, hdr); | 
|  | 2014 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | 
|  | 2015 | /* | 
|  | 2016 | * Attach SENSE DATA payload to iSCSI Response PDU | 
|  | 2017 | */ | 
|  | 2018 | if (cmd->se_cmd.sense_buffer && | 
|  | 2019 | ((cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) || | 
|  | 2020 | (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) { | 
|  | 2021 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 2022 | struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; | 
| Nicholas Bellinger | dbbc5d1 | 2013-07-03 19:39:37 -0700 | [diff] [blame] | 2023 | u32 padding, pdu_len; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2024 |  | 
|  | 2025 | put_unaligned_be16(cmd->se_cmd.scsi_sense_length, | 
|  | 2026 | cmd->sense_buffer); | 
|  | 2027 | cmd->se_cmd.scsi_sense_length += sizeof(__be16); | 
|  | 2028 |  | 
|  | 2029 | padding = -(cmd->se_cmd.scsi_sense_length) & 3; | 
|  | 2030 | hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length); | 
| Nicholas Bellinger | dbbc5d1 | 2013-07-03 19:39:37 -0700 | [diff] [blame] | 2031 | pdu_len = cmd->se_cmd.scsi_sense_length + padding; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2032 |  | 
| Nicholas Bellinger | dbbc5d1 | 2013-07-03 19:39:37 -0700 | [diff] [blame] | 2033 | isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, | 
|  | 2034 | (void *)cmd->sense_buffer, pdu_len, | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2035 | DMA_TO_DEVICE); | 
|  | 2036 |  | 
| Nicholas Bellinger | dbbc5d1 | 2013-07-03 19:39:37 -0700 | [diff] [blame] | 2037 | isert_cmd->pdu_buf_len = pdu_len; | 
|  | 2038 | tx_dsg->addr	= isert_cmd->pdu_buf_dma; | 
|  | 2039 | tx_dsg->length	= pdu_len; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2040 | tx_dsg->lkey	= isert_conn->conn_mr->lkey; | 
|  | 2041 | isert_cmd->tx_desc.num_sge = 2; | 
|  | 2042 | } | 
|  | 2043 |  | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 2044 | isert_init_send_wr(isert_conn, isert_cmd, send_wr, true); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2045 |  | 
|  | 2046 | pr_debug("Posting SCSI Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | 
|  | 2047 |  | 
|  | 2048 | return isert_post_response(isert_conn, isert_cmd); | 
|  | 2049 | } | 
|  | 2050 |  | 
|  | 2051 | static int | 
|  | 2052 | isert_put_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn, | 
|  | 2053 | bool nopout_response) | 
|  | 2054 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2055 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2056 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
|  | 2057 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | 
|  | 2058 |  | 
|  | 2059 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | 
|  | 2060 | iscsit_build_nopin_rsp(cmd, conn, (struct iscsi_nopin *) | 
|  | 2061 | &isert_cmd->tx_desc.iscsi_header, | 
|  | 2062 | nopout_response); | 
|  | 2063 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 2064 | isert_init_send_wr(isert_conn, isert_cmd, send_wr, false); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2065 |  | 
| Masanari Iida | 8b513d0 | 2013-05-21 23:13:12 +0900 | [diff] [blame] | 2066 | pr_debug("Posting NOPIN Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2067 |  | 
|  | 2068 | return isert_post_response(isert_conn, isert_cmd); | 
|  | 2069 | } | 
|  | 2070 |  | 
|  | 2071 | static int | 
|  | 2072 | isert_put_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | 
|  | 2073 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2074 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2075 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
|  | 2076 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | 
|  | 2077 |  | 
|  | 2078 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | 
|  | 2079 | iscsit_build_logout_rsp(cmd, conn, (struct iscsi_logout_rsp *) | 
|  | 2080 | &isert_cmd->tx_desc.iscsi_header); | 
|  | 2081 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 2082 | isert_init_send_wr(isert_conn, isert_cmd, send_wr, false); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2083 |  | 
|  | 2084 | pr_debug("Posting Logout Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | 
|  | 2085 |  | 
|  | 2086 | return isert_post_response(isert_conn, isert_cmd); | 
|  | 2087 | } | 
|  | 2088 |  | 
|  | 2089 | static int | 
|  | 2090 | isert_put_tm_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | 
|  | 2091 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2092 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2093 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
|  | 2094 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | 
|  | 2095 |  | 
|  | 2096 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | 
|  | 2097 | iscsit_build_task_mgt_rsp(cmd, conn, (struct iscsi_tm_rsp *) | 
|  | 2098 | &isert_cmd->tx_desc.iscsi_header); | 
|  | 2099 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 2100 | isert_init_send_wr(isert_conn, isert_cmd, send_wr, false); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2101 |  | 
|  | 2102 | pr_debug("Posting Task Management Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | 
|  | 2103 |  | 
|  | 2104 | return isert_post_response(isert_conn, isert_cmd); | 
|  | 2105 | } | 
|  | 2106 |  | 
|  | 2107 | static int | 
|  | 2108 | isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | 
|  | 2109 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2110 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2111 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
|  | 2112 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | 
| Nicholas Bellinger | 3df8f68 | 2013-06-26 02:31:42 -0700 | [diff] [blame] | 2113 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 2114 | struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; | 
|  | 2115 | struct iscsi_reject *hdr = | 
|  | 2116 | (struct iscsi_reject *)&isert_cmd->tx_desc.iscsi_header; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2117 |  | 
|  | 2118 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | 
| Nicholas Bellinger | 3df8f68 | 2013-06-26 02:31:42 -0700 | [diff] [blame] | 2119 | iscsit_build_reject(cmd, conn, hdr); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2120 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | 
| Nicholas Bellinger | 3df8f68 | 2013-06-26 02:31:42 -0700 | [diff] [blame] | 2121 |  | 
|  | 2122 | hton24(hdr->dlength, ISCSI_HDR_LEN); | 
| Nicholas Bellinger | dbbc5d1 | 2013-07-03 19:39:37 -0700 | [diff] [blame] | 2123 | isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, | 
| Nicholas Bellinger | 3df8f68 | 2013-06-26 02:31:42 -0700 | [diff] [blame] | 2124 | (void *)cmd->buf_ptr, ISCSI_HDR_LEN, | 
|  | 2125 | DMA_TO_DEVICE); | 
| Nicholas Bellinger | dbbc5d1 | 2013-07-03 19:39:37 -0700 | [diff] [blame] | 2126 | isert_cmd->pdu_buf_len = ISCSI_HDR_LEN; | 
|  | 2127 | tx_dsg->addr	= isert_cmd->pdu_buf_dma; | 
| Nicholas Bellinger | 3df8f68 | 2013-06-26 02:31:42 -0700 | [diff] [blame] | 2128 | tx_dsg->length	= ISCSI_HDR_LEN; | 
|  | 2129 | tx_dsg->lkey	= isert_conn->conn_mr->lkey; | 
|  | 2130 | isert_cmd->tx_desc.num_sge = 2; | 
|  | 2131 |  | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 2132 | isert_init_send_wr(isert_conn, isert_cmd, send_wr, false); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2133 |  | 
|  | 2134 | pr_debug("Posting Reject IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | 
|  | 2135 |  | 
|  | 2136 | return isert_post_response(isert_conn, isert_cmd); | 
|  | 2137 | } | 
|  | 2138 |  | 
|  | 2139 | static int | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 2140 | isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | 
|  | 2141 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2142 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 2143 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
|  | 2144 | struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; | 
|  | 2145 | struct iscsi_text_rsp *hdr = | 
|  | 2146 | (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header; | 
|  | 2147 | u32 txt_rsp_len; | 
|  | 2148 | int rc; | 
|  | 2149 |  | 
|  | 2150 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | 
|  | 2151 | rc = iscsit_build_text_rsp(cmd, conn, hdr); | 
|  | 2152 | if (rc < 0) | 
|  | 2153 | return rc; | 
|  | 2154 |  | 
|  | 2155 | txt_rsp_len = rc; | 
|  | 2156 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | 
|  | 2157 |  | 
|  | 2158 | if (txt_rsp_len) { | 
|  | 2159 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 2160 | struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; | 
|  | 2161 | void *txt_rsp_buf = cmd->buf_ptr; | 
|  | 2162 |  | 
|  | 2163 | isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, | 
|  | 2164 | txt_rsp_buf, txt_rsp_len, DMA_TO_DEVICE); | 
|  | 2165 |  | 
|  | 2166 | isert_cmd->pdu_buf_len = txt_rsp_len; | 
|  | 2167 | tx_dsg->addr	= isert_cmd->pdu_buf_dma; | 
|  | 2168 | tx_dsg->length	= txt_rsp_len; | 
|  | 2169 | tx_dsg->lkey	= isert_conn->conn_mr->lkey; | 
|  | 2170 | isert_cmd->tx_desc.num_sge = 2; | 
|  | 2171 | } | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 2172 | isert_init_send_wr(isert_conn, isert_cmd, send_wr, false); | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 2173 |  | 
|  | 2174 | pr_debug("Posting Text Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); | 
|  | 2175 |  | 
|  | 2176 | return isert_post_response(isert_conn, isert_cmd); | 
|  | 2177 | } | 
|  | 2178 |  | 
|  | 2179 | static int | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2180 | isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, | 
|  | 2181 | struct ib_sge *ib_sge, struct ib_send_wr *send_wr, | 
|  | 2182 | u32 data_left, u32 offset) | 
|  | 2183 | { | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2184 | struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2185 | struct scatterlist *sg_start, *tmp_sg; | 
|  | 2186 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
|  | 2187 | u32 sg_off, page_off; | 
|  | 2188 | int i = 0, sg_nents; | 
|  | 2189 |  | 
|  | 2190 | sg_off = offset / PAGE_SIZE; | 
|  | 2191 | sg_start = &cmd->se_cmd.t_data_sg[sg_off]; | 
|  | 2192 | sg_nents = min(cmd->se_cmd.t_data_nents - sg_off, isert_conn->max_sge); | 
|  | 2193 | page_off = offset % PAGE_SIZE; | 
|  | 2194 |  | 
|  | 2195 | send_wr->sg_list = ib_sge; | 
|  | 2196 | send_wr->num_sge = sg_nents; | 
|  | 2197 | send_wr->wr_id = (unsigned long)&isert_cmd->tx_desc; | 
|  | 2198 | /* | 
|  | 2199 | * Perform mapping of TCM scatterlist memory ib_sge dma_addr. | 
|  | 2200 | */ | 
|  | 2201 | for_each_sg(sg_start, tmp_sg, sg_nents, i) { | 
|  | 2202 | pr_debug("ISER RDMA from SGL dma_addr: 0x%16llx dma_len: %u, page_off: %u\n", | 
|  | 2203 | (unsigned long long)tmp_sg->dma_address, | 
|  | 2204 | tmp_sg->length, page_off); | 
|  | 2205 |  | 
|  | 2206 | ib_sge->addr = ib_sg_dma_address(ib_dev, tmp_sg) + page_off; | 
|  | 2207 | ib_sge->length = min_t(u32, data_left, | 
|  | 2208 | ib_sg_dma_len(ib_dev, tmp_sg) - page_off); | 
|  | 2209 | ib_sge->lkey = isert_conn->conn_mr->lkey; | 
|  | 2210 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2211 | pr_debug("RDMA ib_sge: addr: 0x%16llx  length: %u lkey: %08x\n", | 
|  | 2212 | ib_sge->addr, ib_sge->length, ib_sge->lkey); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2213 | page_off = 0; | 
|  | 2214 | data_left -= ib_sge->length; | 
|  | 2215 | ib_sge++; | 
|  | 2216 | pr_debug("Incrementing ib_sge pointer to %p\n", ib_sge); | 
|  | 2217 | } | 
|  | 2218 |  | 
|  | 2219 | pr_debug("Set outgoing sg_list: %p num_sg: %u from TCM SGLs\n", | 
|  | 2220 | send_wr->sg_list, send_wr->num_sge); | 
|  | 2221 |  | 
|  | 2222 | return sg_nents; | 
|  | 2223 | } | 
|  | 2224 |  | 
|  | 2225 | static int | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2226 | isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
|  | 2227 | struct isert_rdma_wr *wr) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2228 | { | 
|  | 2229 | struct se_cmd *se_cmd = &cmd->se_cmd; | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2230 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2231 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2232 | struct isert_data_buf *data = &wr->data; | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2233 | struct ib_send_wr *send_wr; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2234 | struct ib_sge *ib_sge; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2235 | u32 offset, data_len, data_left, rdma_write_max, va_offset = 0; | 
|  | 2236 | int ret = 0, i, ib_sge_cnt; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2237 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2238 | isert_cmd->tx_desc.isert_cmd = isert_cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2239 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2240 | offset = wr->iser_ib_op == ISER_IB_RDMA_READ ? cmd->write_data_done : 0; | 
|  | 2241 | ret = isert_map_data_buf(isert_conn, isert_cmd, se_cmd->t_data_sg, | 
|  | 2242 | se_cmd->t_data_nents, se_cmd->data_length, | 
|  | 2243 | offset, wr->iser_ib_op, &wr->data); | 
|  | 2244 | if (ret) | 
|  | 2245 | return ret; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2246 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2247 | data_left = data->len; | 
|  | 2248 | offset = data->offset; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2249 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2250 | ib_sge = kzalloc(sizeof(struct ib_sge) * data->nents, GFP_KERNEL); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2251 | if (!ib_sge) { | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2252 | pr_warn("Unable to allocate ib_sge\n"); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2253 | ret = -ENOMEM; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2254 | goto unmap_cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2255 | } | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2256 | wr->ib_sge = ib_sge; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2257 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2258 | wr->send_wr_num = DIV_ROUND_UP(data->nents, isert_conn->max_sge); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2259 | wr->send_wr = kzalloc(sizeof(struct ib_send_wr) * wr->send_wr_num, | 
|  | 2260 | GFP_KERNEL); | 
|  | 2261 | if (!wr->send_wr) { | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2262 | pr_debug("Unable to allocate wr->send_wr\n"); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2263 | ret = -ENOMEM; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2264 | goto unmap_cmd; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2265 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2266 |  | 
|  | 2267 | wr->isert_cmd = isert_cmd; | 
|  | 2268 | rdma_write_max = isert_conn->max_sge * PAGE_SIZE; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2269 |  | 
|  | 2270 | for (i = 0; i < wr->send_wr_num; i++) { | 
|  | 2271 | send_wr = &isert_cmd->rdma_wr.send_wr[i]; | 
|  | 2272 | data_len = min(data_left, rdma_write_max); | 
|  | 2273 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2274 | send_wr->send_flags = 0; | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2275 | if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) { | 
|  | 2276 | send_wr->opcode = IB_WR_RDMA_WRITE; | 
|  | 2277 | send_wr->wr.rdma.remote_addr = isert_cmd->read_va + offset; | 
|  | 2278 | send_wr->wr.rdma.rkey = isert_cmd->read_stag; | 
|  | 2279 | if (i + 1 == wr->send_wr_num) | 
|  | 2280 | send_wr->next = &isert_cmd->tx_desc.send_wr; | 
|  | 2281 | else | 
|  | 2282 | send_wr->next = &wr->send_wr[i + 1]; | 
|  | 2283 | } else { | 
|  | 2284 | send_wr->opcode = IB_WR_RDMA_READ; | 
|  | 2285 | send_wr->wr.rdma.remote_addr = isert_cmd->write_va + va_offset; | 
|  | 2286 | send_wr->wr.rdma.rkey = isert_cmd->write_stag; | 
|  | 2287 | if (i + 1 == wr->send_wr_num) | 
|  | 2288 | send_wr->send_flags = IB_SEND_SIGNALED; | 
|  | 2289 | else | 
|  | 2290 | send_wr->next = &wr->send_wr[i + 1]; | 
|  | 2291 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2292 |  | 
|  | 2293 | ib_sge_cnt = isert_build_rdma_wr(isert_conn, isert_cmd, ib_sge, | 
|  | 2294 | send_wr, data_len, offset); | 
|  | 2295 | ib_sge += ib_sge_cnt; | 
|  | 2296 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2297 | offset += data_len; | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2298 | va_offset += data_len; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2299 | data_left -= data_len; | 
|  | 2300 | } | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2301 |  | 
|  | 2302 | return 0; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2303 | unmap_cmd: | 
|  | 2304 | isert_unmap_data_buf(isert_conn, data); | 
|  | 2305 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2306 | return ret; | 
|  | 2307 | } | 
|  | 2308 |  | 
|  | 2309 | static int | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2310 | isert_map_fr_pagelist(struct ib_device *ib_dev, | 
|  | 2311 | struct scatterlist *sg_start, int sg_nents, u64 *fr_pl) | 
|  | 2312 | { | 
|  | 2313 | u64 start_addr, end_addr, page, chunk_start = 0; | 
|  | 2314 | struct scatterlist *tmp_sg; | 
|  | 2315 | int i = 0, new_chunk, last_ent, n_pages; | 
|  | 2316 |  | 
|  | 2317 | n_pages = 0; | 
|  | 2318 | new_chunk = 1; | 
|  | 2319 | last_ent = sg_nents - 1; | 
|  | 2320 | for_each_sg(sg_start, tmp_sg, sg_nents, i) { | 
|  | 2321 | start_addr = ib_sg_dma_address(ib_dev, tmp_sg); | 
|  | 2322 | if (new_chunk) | 
|  | 2323 | chunk_start = start_addr; | 
|  | 2324 | end_addr = start_addr + ib_sg_dma_len(ib_dev, tmp_sg); | 
|  | 2325 |  | 
|  | 2326 | pr_debug("SGL[%d] dma_addr: 0x%16llx len: %u\n", | 
|  | 2327 | i, (unsigned long long)tmp_sg->dma_address, | 
|  | 2328 | tmp_sg->length); | 
|  | 2329 |  | 
|  | 2330 | if ((end_addr & ~PAGE_MASK) && i < last_ent) { | 
|  | 2331 | new_chunk = 0; | 
|  | 2332 | continue; | 
|  | 2333 | } | 
|  | 2334 | new_chunk = 1; | 
|  | 2335 |  | 
|  | 2336 | page = chunk_start & PAGE_MASK; | 
|  | 2337 | do { | 
|  | 2338 | fr_pl[n_pages++] = page; | 
|  | 2339 | pr_debug("Mapped page_list[%d] page_addr: 0x%16llx\n", | 
|  | 2340 | n_pages - 1, page); | 
|  | 2341 | page += PAGE_SIZE; | 
|  | 2342 | } while (page < end_addr); | 
|  | 2343 | } | 
|  | 2344 |  | 
|  | 2345 | return n_pages; | 
|  | 2346 | } | 
|  | 2347 |  | 
|  | 2348 | static int | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2349 | isert_fast_reg_mr(struct isert_conn *isert_conn, | 
|  | 2350 | struct fast_reg_descriptor *fr_desc, | 
|  | 2351 | struct isert_data_buf *mem, | 
|  | 2352 | struct ib_sge *sge) | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2353 | { | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2354 | struct ib_device *ib_dev = isert_conn->conn_cm_id->device; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2355 | struct ib_send_wr fr_wr, inv_wr; | 
|  | 2356 | struct ib_send_wr *bad_wr, *wr = NULL; | 
| Sagi Grimberg | 9bd626e | 2014-01-09 18:40:54 +0200 | [diff] [blame] | 2357 | int ret, pagelist_len; | 
|  | 2358 | u32 page_off; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2359 | u8 key; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2360 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2361 | if (mem->dma_nents == 1) { | 
|  | 2362 | sge->lkey = isert_conn->conn_mr->lkey; | 
|  | 2363 | sge->addr = ib_sg_dma_address(ib_dev, &mem->sg[0]); | 
|  | 2364 | sge->length = ib_sg_dma_len(ib_dev, &mem->sg[0]); | 
|  | 2365 | return 0; | 
|  | 2366 | } | 
|  | 2367 |  | 
|  | 2368 | page_off = mem->offset % PAGE_SIZE; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2369 |  | 
| Sagi Grimberg | 9bd626e | 2014-01-09 18:40:54 +0200 | [diff] [blame] | 2370 | pr_debug("Use fr_desc %p sg_nents %d offset %u\n", | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2371 | fr_desc, mem->nents, mem->offset); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2372 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2373 | pagelist_len = isert_map_fr_pagelist(ib_dev, mem->sg, mem->nents, | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2374 | &fr_desc->data_frpl->page_list[0]); | 
|  | 2375 |  | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 2376 | if (!(fr_desc->ind & ISERT_DATA_KEY_VALID)) { | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2377 | memset(&inv_wr, 0, sizeof(inv_wr)); | 
| Nicholas Bellinger | 9bb4ca6 | 2014-02-27 07:02:48 -0800 | [diff] [blame] | 2378 | inv_wr.wr_id = ISER_FASTREG_LI_WRID; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2379 | inv_wr.opcode = IB_WR_LOCAL_INV; | 
|  | 2380 | inv_wr.ex.invalidate_rkey = fr_desc->data_mr->rkey; | 
|  | 2381 | wr = &inv_wr; | 
|  | 2382 | /* Bump the key */ | 
|  | 2383 | key = (u8)(fr_desc->data_mr->rkey & 0x000000FF); | 
|  | 2384 | ib_update_fast_reg_key(fr_desc->data_mr, ++key); | 
|  | 2385 | } | 
|  | 2386 |  | 
|  | 2387 | /* Prepare FASTREG WR */ | 
|  | 2388 | memset(&fr_wr, 0, sizeof(fr_wr)); | 
| Nicholas Bellinger | 9bb4ca6 | 2014-02-27 07:02:48 -0800 | [diff] [blame] | 2389 | fr_wr.wr_id = ISER_FASTREG_LI_WRID; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2390 | fr_wr.opcode = IB_WR_FAST_REG_MR; | 
|  | 2391 | fr_wr.wr.fast_reg.iova_start = | 
|  | 2392 | fr_desc->data_frpl->page_list[0] + page_off; | 
|  | 2393 | fr_wr.wr.fast_reg.page_list = fr_desc->data_frpl; | 
|  | 2394 | fr_wr.wr.fast_reg.page_list_len = pagelist_len; | 
|  | 2395 | fr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2396 | fr_wr.wr.fast_reg.length = mem->len; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2397 | fr_wr.wr.fast_reg.rkey = fr_desc->data_mr->rkey; | 
|  | 2398 | fr_wr.wr.fast_reg.access_flags = IB_ACCESS_LOCAL_WRITE; | 
|  | 2399 |  | 
|  | 2400 | if (!wr) | 
|  | 2401 | wr = &fr_wr; | 
|  | 2402 | else | 
|  | 2403 | wr->next = &fr_wr; | 
|  | 2404 |  | 
|  | 2405 | ret = ib_post_send(isert_conn->conn_qp, wr, &bad_wr); | 
|  | 2406 | if (ret) { | 
|  | 2407 | pr_err("fast registration failed, ret:%d\n", ret); | 
|  | 2408 | return ret; | 
|  | 2409 | } | 
| Sagi Grimberg | d3e125d | 2014-02-19 17:50:23 +0200 | [diff] [blame] | 2410 | fr_desc->ind &= ~ISERT_DATA_KEY_VALID; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2411 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2412 | sge->lkey = fr_desc->data_mr->lkey; | 
|  | 2413 | sge->addr = fr_desc->data_frpl->page_list[0] + page_off; | 
|  | 2414 | sge->length = mem->len; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2415 |  | 
|  | 2416 | pr_debug("RDMA ib_sge: addr: 0x%16llx  length: %u lkey: %08x\n", | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2417 | sge->addr, sge->length, sge->lkey); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2418 |  | 
|  | 2419 | return ret; | 
|  | 2420 | } | 
|  | 2421 |  | 
|  | 2422 | static int | 
| Sagi Grimberg | a3a5a82 | 2014-01-09 18:40:50 +0200 | [diff] [blame] | 2423 | isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 
|  | 2424 | struct isert_rdma_wr *wr) | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2425 | { | 
|  | 2426 | struct se_cmd *se_cmd = &cmd->se_cmd; | 
|  | 2427 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2428 | struct isert_conn *isert_conn = conn->context; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2429 | struct ib_send_wr *send_wr; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2430 | struct fast_reg_descriptor *fr_desc = NULL; | 
|  | 2431 | u32 offset; | 
|  | 2432 | int ret = 0; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2433 | unsigned long flags; | 
|  | 2434 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2435 | isert_cmd->tx_desc.isert_cmd = isert_cmd; | 
|  | 2436 |  | 
|  | 2437 | offset = wr->iser_ib_op == ISER_IB_RDMA_READ ? cmd->write_data_done : 0; | 
|  | 2438 | ret = isert_map_data_buf(isert_conn, isert_cmd, se_cmd->t_data_sg, | 
|  | 2439 | se_cmd->t_data_nents, se_cmd->data_length, | 
|  | 2440 | offset, wr->iser_ib_op, &wr->data); | 
|  | 2441 | if (ret) | 
|  | 2442 | return ret; | 
|  | 2443 |  | 
|  | 2444 | if (wr->data.dma_nents != 1) { | 
|  | 2445 | spin_lock_irqsave(&isert_conn->conn_lock, flags); | 
|  | 2446 | fr_desc = list_first_entry(&isert_conn->conn_fr_pool, | 
|  | 2447 | struct fast_reg_descriptor, list); | 
|  | 2448 | list_del(&fr_desc->list); | 
|  | 2449 | spin_unlock_irqrestore(&isert_conn->conn_lock, flags); | 
|  | 2450 | wr->fr_desc = fr_desc; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2451 | } | 
|  | 2452 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2453 | ret = isert_fast_reg_mr(isert_conn, fr_desc, &wr->data, &wr->s_ib_sge); | 
|  | 2454 | if (ret) | 
|  | 2455 | goto unmap_cmd; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2456 |  | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2457 | wr->ib_sge = &wr->s_ib_sge; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2458 | wr->send_wr_num = 1; | 
|  | 2459 | memset(&wr->s_send_wr, 0, sizeof(*send_wr)); | 
|  | 2460 | wr->send_wr = &wr->s_send_wr; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2461 | wr->isert_cmd = isert_cmd; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2462 |  | 
|  | 2463 | send_wr = &isert_cmd->rdma_wr.s_send_wr; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2464 | send_wr->sg_list = &wr->s_ib_sge; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2465 | send_wr->num_sge = 1; | 
|  | 2466 | send_wr->wr_id = (unsigned long)&isert_cmd->tx_desc; | 
|  | 2467 | if (wr->iser_ib_op == ISER_IB_RDMA_WRITE) { | 
|  | 2468 | send_wr->opcode = IB_WR_RDMA_WRITE; | 
|  | 2469 | send_wr->wr.rdma.remote_addr = isert_cmd->read_va; | 
|  | 2470 | send_wr->wr.rdma.rkey = isert_cmd->read_stag; | 
|  | 2471 | send_wr->send_flags = 0; | 
|  | 2472 | send_wr->next = &isert_cmd->tx_desc.send_wr; | 
|  | 2473 | } else { | 
|  | 2474 | send_wr->opcode = IB_WR_RDMA_READ; | 
|  | 2475 | send_wr->wr.rdma.remote_addr = isert_cmd->write_va; | 
|  | 2476 | send_wr->wr.rdma.rkey = isert_cmd->write_stag; | 
|  | 2477 | send_wr->send_flags = IB_SEND_SIGNALED; | 
|  | 2478 | } | 
|  | 2479 |  | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2480 | return 0; | 
| Sagi Grimberg | e3d7e4c | 2014-02-19 17:50:22 +0200 | [diff] [blame] | 2481 | unmap_cmd: | 
|  | 2482 | if (fr_desc) { | 
|  | 2483 | spin_lock_irqsave(&isert_conn->conn_lock, flags); | 
|  | 2484 | list_add_tail(&fr_desc->list, &isert_conn->conn_fr_pool); | 
|  | 2485 | spin_unlock_irqrestore(&isert_conn->conn_lock, flags); | 
|  | 2486 | } | 
|  | 2487 | isert_unmap_data_buf(isert_conn, &wr->data); | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2488 |  | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2489 | return ret; | 
|  | 2490 | } | 
|  | 2491 |  | 
|  | 2492 | static int | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2493 | isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd) | 
|  | 2494 | { | 
|  | 2495 | struct se_cmd *se_cmd = &cmd->se_cmd; | 
| Vu Pham | 59464ef | 2013-08-28 23:23:35 +0300 | [diff] [blame] | 2496 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2497 | struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; | 
|  | 2498 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 2499 | struct isert_device *device = isert_conn->conn_device; | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2500 | struct ib_send_wr *wr_failed; | 
|  | 2501 | int rc; | 
|  | 2502 |  | 
|  | 2503 | pr_debug("Cmd: %p RDMA_WRITE data_length: %u\n", | 
|  | 2504 | isert_cmd, se_cmd->data_length); | 
|  | 2505 | wr->iser_ib_op = ISER_IB_RDMA_WRITE; | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 2506 | rc = device->reg_rdma_mem(conn, cmd, wr); | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2507 | if (rc) { | 
|  | 2508 | pr_err("Cmd: %p failed to prepare RDMA res\n", isert_cmd); | 
|  | 2509 | return rc; | 
|  | 2510 | } | 
|  | 2511 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2512 | /* | 
|  | 2513 | * Build isert_conn->tx_desc for iSCSI response PDU and attach | 
|  | 2514 | */ | 
|  | 2515 | isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); | 
| Nicholas Bellinger | 04d9cd1 | 2013-11-12 18:05:07 -0800 | [diff] [blame] | 2516 | iscsit_build_rsp_pdu(cmd, conn, true, (struct iscsi_scsi_rsp *) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2517 | &isert_cmd->tx_desc.iscsi_header); | 
|  | 2518 | isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); | 
| Nicholas Bellinger | 95b60f0 | 2013-11-05 13:16:12 -0800 | [diff] [blame] | 2519 | isert_init_send_wr(isert_conn, isert_cmd, | 
|  | 2520 | &isert_cmd->tx_desc.send_wr, true); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2521 |  | 
| Nicholas Bellinger | b6b87a1 | 2014-02-27 09:05:03 -0800 | [diff] [blame] | 2522 | atomic_add(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2523 |  | 
|  | 2524 | rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed); | 
|  | 2525 | if (rc) { | 
|  | 2526 | pr_warn("ib_post_send() failed for IB_WR_RDMA_WRITE\n"); | 
| Nicholas Bellinger | b6b87a1 | 2014-02-27 09:05:03 -0800 | [diff] [blame] | 2527 | atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2528 | } | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2529 | pr_debug("Cmd: %p posted RDMA_WRITE + Response for iSER Data READ\n", | 
|  | 2530 | isert_cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2531 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2532 | return 1; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2533 | } | 
|  | 2534 |  | 
|  | 2535 | static int | 
|  | 2536 | isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery) | 
|  | 2537 | { | 
|  | 2538 | struct se_cmd *se_cmd = &cmd->se_cmd; | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2539 | struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2540 | struct isert_rdma_wr *wr = &isert_cmd->rdma_wr; | 
|  | 2541 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 2542 | struct isert_device *device = isert_conn->conn_device; | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2543 | struct ib_send_wr *wr_failed; | 
|  | 2544 | int rc; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2545 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2546 | pr_debug("Cmd: %p RDMA_READ data_length: %u write_data_done: %u\n", | 
|  | 2547 | isert_cmd, se_cmd->data_length, cmd->write_data_done); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2548 | wr->iser_ib_op = ISER_IB_RDMA_READ; | 
| Vu Pham | d40945d | 2013-08-28 23:23:34 +0300 | [diff] [blame] | 2549 | rc = device->reg_rdma_mem(conn, cmd, wr); | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2550 | if (rc) { | 
|  | 2551 | pr_err("Cmd: %p failed to prepare RDMA res\n", isert_cmd); | 
|  | 2552 | return rc; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2553 | } | 
|  | 2554 |  | 
| Nicholas Bellinger | b6b87a1 | 2014-02-27 09:05:03 -0800 | [diff] [blame] | 2555 | atomic_add(wr->send_wr_num, &isert_conn->post_send_buf_count); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2556 |  | 
|  | 2557 | rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed); | 
|  | 2558 | if (rc) { | 
|  | 2559 | pr_warn("ib_post_send() failed for IB_WR_RDMA_READ\n"); | 
| Nicholas Bellinger | b6b87a1 | 2014-02-27 09:05:03 -0800 | [diff] [blame] | 2560 | atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2561 | } | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2562 | pr_debug("Cmd: %p posted RDMA_READ memory for ISER Data WRITE\n", | 
|  | 2563 | isert_cmd); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2564 |  | 
| Vu Pham | 90ecc6e | 2013-08-28 23:23:33 +0300 | [diff] [blame] | 2565 | return 0; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2566 | } | 
|  | 2567 |  | 
|  | 2568 | static int | 
|  | 2569 | isert_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) | 
|  | 2570 | { | 
|  | 2571 | int ret; | 
|  | 2572 |  | 
|  | 2573 | switch (state) { | 
|  | 2574 | case ISTATE_SEND_NOPIN_WANT_RESPONSE: | 
|  | 2575 | ret = isert_put_nopin(cmd, conn, false); | 
|  | 2576 | break; | 
|  | 2577 | default: | 
|  | 2578 | pr_err("Unknown immediate state: 0x%02x\n", state); | 
|  | 2579 | ret = -EINVAL; | 
|  | 2580 | break; | 
|  | 2581 | } | 
|  | 2582 |  | 
|  | 2583 | return ret; | 
|  | 2584 | } | 
|  | 2585 |  | 
|  | 2586 | static int | 
|  | 2587 | isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) | 
|  | 2588 | { | 
|  | 2589 | int ret; | 
|  | 2590 |  | 
|  | 2591 | switch (state) { | 
|  | 2592 | case ISTATE_SEND_LOGOUTRSP: | 
|  | 2593 | ret = isert_put_logout_rsp(cmd, conn); | 
|  | 2594 | if (!ret) { | 
|  | 2595 | pr_debug("Returning iSER Logout -EAGAIN\n"); | 
|  | 2596 | ret = -EAGAIN; | 
|  | 2597 | } | 
|  | 2598 | break; | 
|  | 2599 | case ISTATE_SEND_NOPIN: | 
|  | 2600 | ret = isert_put_nopin(cmd, conn, true); | 
|  | 2601 | break; | 
|  | 2602 | case ISTATE_SEND_TASKMGTRSP: | 
|  | 2603 | ret = isert_put_tm_rsp(cmd, conn); | 
|  | 2604 | break; | 
|  | 2605 | case ISTATE_SEND_REJECT: | 
|  | 2606 | ret = isert_put_reject(cmd, conn); | 
|  | 2607 | break; | 
| Nicholas Bellinger | adb54c2 | 2013-06-14 16:47:15 -0700 | [diff] [blame] | 2608 | case ISTATE_SEND_TEXTRSP: | 
|  | 2609 | ret = isert_put_text_rsp(cmd, conn); | 
|  | 2610 | break; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2611 | case ISTATE_SEND_STATUS: | 
|  | 2612 | /* | 
|  | 2613 | * Special case for sending non GOOD SCSI status from TX thread | 
|  | 2614 | * context during pre se_cmd excecution failure. | 
|  | 2615 | */ | 
|  | 2616 | ret = isert_put_response(conn, cmd); | 
|  | 2617 | break; | 
|  | 2618 | default: | 
|  | 2619 | pr_err("Unknown response state: 0x%02x\n", state); | 
|  | 2620 | ret = -EINVAL; | 
|  | 2621 | break; | 
|  | 2622 | } | 
|  | 2623 |  | 
|  | 2624 | return ret; | 
|  | 2625 | } | 
|  | 2626 |  | 
|  | 2627 | static int | 
|  | 2628 | isert_setup_np(struct iscsi_np *np, | 
|  | 2629 | struct __kernel_sockaddr_storage *ksockaddr) | 
|  | 2630 | { | 
|  | 2631 | struct isert_np *isert_np; | 
|  | 2632 | struct rdma_cm_id *isert_lid; | 
|  | 2633 | struct sockaddr *sa; | 
|  | 2634 | int ret; | 
|  | 2635 |  | 
|  | 2636 | isert_np = kzalloc(sizeof(struct isert_np), GFP_KERNEL); | 
|  | 2637 | if (!isert_np) { | 
|  | 2638 | pr_err("Unable to allocate struct isert_np\n"); | 
|  | 2639 | return -ENOMEM; | 
|  | 2640 | } | 
|  | 2641 | init_waitqueue_head(&isert_np->np_accept_wq); | 
|  | 2642 | mutex_init(&isert_np->np_accept_mutex); | 
|  | 2643 | INIT_LIST_HEAD(&isert_np->np_accept_list); | 
|  | 2644 | init_completion(&isert_np->np_login_comp); | 
|  | 2645 |  | 
|  | 2646 | sa = (struct sockaddr *)ksockaddr; | 
|  | 2647 | pr_debug("ksockaddr: %p, sa: %p\n", ksockaddr, sa); | 
|  | 2648 | /* | 
|  | 2649 | * Setup the np->np_sockaddr from the passed sockaddr setup | 
|  | 2650 | * in iscsi_target_configfs.c code.. | 
|  | 2651 | */ | 
|  | 2652 | memcpy(&np->np_sockaddr, ksockaddr, | 
|  | 2653 | sizeof(struct __kernel_sockaddr_storage)); | 
|  | 2654 |  | 
|  | 2655 | isert_lid = rdma_create_id(isert_cma_handler, np, RDMA_PS_TCP, | 
|  | 2656 | IB_QPT_RC); | 
|  | 2657 | if (IS_ERR(isert_lid)) { | 
|  | 2658 | pr_err("rdma_create_id() for isert_listen_handler failed: %ld\n", | 
|  | 2659 | PTR_ERR(isert_lid)); | 
|  | 2660 | ret = PTR_ERR(isert_lid); | 
|  | 2661 | goto out; | 
|  | 2662 | } | 
|  | 2663 |  | 
|  | 2664 | ret = rdma_bind_addr(isert_lid, sa); | 
|  | 2665 | if (ret) { | 
|  | 2666 | pr_err("rdma_bind_addr() for isert_lid failed: %d\n", ret); | 
|  | 2667 | goto out_lid; | 
|  | 2668 | } | 
|  | 2669 |  | 
|  | 2670 | ret = rdma_listen(isert_lid, ISERT_RDMA_LISTEN_BACKLOG); | 
|  | 2671 | if (ret) { | 
|  | 2672 | pr_err("rdma_listen() for isert_lid failed: %d\n", ret); | 
|  | 2673 | goto out_lid; | 
|  | 2674 | } | 
|  | 2675 |  | 
|  | 2676 | isert_np->np_cm_id = isert_lid; | 
|  | 2677 | np->np_context = isert_np; | 
|  | 2678 | pr_debug("Setup isert_lid->context: %p\n", isert_lid->context); | 
|  | 2679 |  | 
|  | 2680 | return 0; | 
|  | 2681 |  | 
|  | 2682 | out_lid: | 
|  | 2683 | rdma_destroy_id(isert_lid); | 
|  | 2684 | out: | 
|  | 2685 | kfree(isert_np); | 
|  | 2686 | return ret; | 
|  | 2687 | } | 
|  | 2688 |  | 
|  | 2689 | static int | 
|  | 2690 | isert_check_accept_queue(struct isert_np *isert_np) | 
|  | 2691 | { | 
|  | 2692 | int empty; | 
|  | 2693 |  | 
|  | 2694 | mutex_lock(&isert_np->np_accept_mutex); | 
|  | 2695 | empty = list_empty(&isert_np->np_accept_list); | 
|  | 2696 | mutex_unlock(&isert_np->np_accept_mutex); | 
|  | 2697 |  | 
|  | 2698 | return empty; | 
|  | 2699 | } | 
|  | 2700 |  | 
|  | 2701 | static int | 
|  | 2702 | isert_rdma_accept(struct isert_conn *isert_conn) | 
|  | 2703 | { | 
|  | 2704 | struct rdma_cm_id *cm_id = isert_conn->conn_cm_id; | 
|  | 2705 | struct rdma_conn_param cp; | 
|  | 2706 | int ret; | 
|  | 2707 |  | 
|  | 2708 | memset(&cp, 0, sizeof(struct rdma_conn_param)); | 
|  | 2709 | cp.responder_resources = isert_conn->responder_resources; | 
|  | 2710 | cp.initiator_depth = isert_conn->initiator_depth; | 
|  | 2711 | cp.retry_count = 7; | 
|  | 2712 | cp.rnr_retry_count = 7; | 
|  | 2713 |  | 
|  | 2714 | pr_debug("Before rdma_accept >>>>>>>>>>>>>>>>>>>>.\n"); | 
|  | 2715 |  | 
|  | 2716 | ret = rdma_accept(cm_id, &cp); | 
|  | 2717 | if (ret) { | 
|  | 2718 | pr_err("rdma_accept() failed with: %d\n", ret); | 
|  | 2719 | return ret; | 
|  | 2720 | } | 
|  | 2721 |  | 
|  | 2722 | pr_debug("After rdma_accept >>>>>>>>>>>>>>>>>>>>>.\n"); | 
|  | 2723 |  | 
|  | 2724 | return 0; | 
|  | 2725 | } | 
|  | 2726 |  | 
|  | 2727 | static int | 
|  | 2728 | isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) | 
|  | 2729 | { | 
|  | 2730 | struct isert_conn *isert_conn = (struct isert_conn *)conn->context; | 
|  | 2731 | int ret; | 
|  | 2732 |  | 
|  | 2733 | pr_debug("isert_get_login_rx before conn_login_comp conn: %p\n", conn); | 
| Nicholas Bellinger | 6faaa85 | 2013-08-18 16:35:46 -0700 | [diff] [blame] | 2734 | /* | 
|  | 2735 | * For login requests after the first PDU, isert_rx_login_req() will | 
|  | 2736 | * kick schedule_delayed_work(&conn->login_work) as the packet is | 
|  | 2737 | * received, which turns this callback from iscsi_target_do_login_rx() | 
|  | 2738 | * into a NOP. | 
|  | 2739 | */ | 
|  | 2740 | if (!login->first_request) | 
|  | 2741 | return 0; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2742 |  | 
|  | 2743 | ret = wait_for_completion_interruptible(&isert_conn->conn_login_comp); | 
|  | 2744 | if (ret) | 
|  | 2745 | return ret; | 
|  | 2746 |  | 
|  | 2747 | pr_debug("isert_get_login_rx processing login->req: %p\n", login->req); | 
|  | 2748 | return 0; | 
|  | 2749 | } | 
|  | 2750 |  | 
|  | 2751 | static void | 
|  | 2752 | isert_set_conn_info(struct iscsi_np *np, struct iscsi_conn *conn, | 
|  | 2753 | struct isert_conn *isert_conn) | 
|  | 2754 | { | 
|  | 2755 | struct rdma_cm_id *cm_id = isert_conn->conn_cm_id; | 
|  | 2756 | struct rdma_route *cm_route = &cm_id->route; | 
|  | 2757 | struct sockaddr_in *sock_in; | 
|  | 2758 | struct sockaddr_in6 *sock_in6; | 
|  | 2759 |  | 
|  | 2760 | conn->login_family = np->np_sockaddr.ss_family; | 
|  | 2761 |  | 
|  | 2762 | if (np->np_sockaddr.ss_family == AF_INET6) { | 
|  | 2763 | sock_in6 = (struct sockaddr_in6 *)&cm_route->addr.dst_addr; | 
|  | 2764 | snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", | 
|  | 2765 | &sock_in6->sin6_addr.in6_u); | 
|  | 2766 | conn->login_port = ntohs(sock_in6->sin6_port); | 
|  | 2767 |  | 
|  | 2768 | sock_in6 = (struct sockaddr_in6 *)&cm_route->addr.src_addr; | 
|  | 2769 | snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c", | 
|  | 2770 | &sock_in6->sin6_addr.in6_u); | 
|  | 2771 | conn->local_port = ntohs(sock_in6->sin6_port); | 
|  | 2772 | } else { | 
|  | 2773 | sock_in = (struct sockaddr_in *)&cm_route->addr.dst_addr; | 
|  | 2774 | sprintf(conn->login_ip, "%pI4", | 
|  | 2775 | &sock_in->sin_addr.s_addr); | 
|  | 2776 | conn->login_port = ntohs(sock_in->sin_port); | 
|  | 2777 |  | 
|  | 2778 | sock_in = (struct sockaddr_in *)&cm_route->addr.src_addr; | 
|  | 2779 | sprintf(conn->local_ip, "%pI4", | 
|  | 2780 | &sock_in->sin_addr.s_addr); | 
|  | 2781 | conn->local_port = ntohs(sock_in->sin_port); | 
|  | 2782 | } | 
|  | 2783 | } | 
|  | 2784 |  | 
|  | 2785 | static int | 
|  | 2786 | isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) | 
|  | 2787 | { | 
|  | 2788 | struct isert_np *isert_np = (struct isert_np *)np->np_context; | 
|  | 2789 | struct isert_conn *isert_conn; | 
|  | 2790 | int max_accept = 0, ret; | 
|  | 2791 |  | 
|  | 2792 | accept_wait: | 
|  | 2793 | ret = wait_event_interruptible(isert_np->np_accept_wq, | 
|  | 2794 | !isert_check_accept_queue(isert_np) || | 
|  | 2795 | np->np_thread_state == ISCSI_NP_THREAD_RESET); | 
|  | 2796 | if (max_accept > 5) | 
|  | 2797 | return -ENODEV; | 
|  | 2798 |  | 
|  | 2799 | spin_lock_bh(&np->np_thread_lock); | 
|  | 2800 | if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { | 
|  | 2801 | spin_unlock_bh(&np->np_thread_lock); | 
|  | 2802 | pr_err("ISCSI_NP_THREAD_RESET for isert_accept_np\n"); | 
|  | 2803 | return -ENODEV; | 
|  | 2804 | } | 
|  | 2805 | spin_unlock_bh(&np->np_thread_lock); | 
|  | 2806 |  | 
|  | 2807 | mutex_lock(&isert_np->np_accept_mutex); | 
|  | 2808 | if (list_empty(&isert_np->np_accept_list)) { | 
|  | 2809 | mutex_unlock(&isert_np->np_accept_mutex); | 
|  | 2810 | max_accept++; | 
|  | 2811 | goto accept_wait; | 
|  | 2812 | } | 
|  | 2813 | isert_conn = list_first_entry(&isert_np->np_accept_list, | 
|  | 2814 | struct isert_conn, conn_accept_node); | 
|  | 2815 | list_del_init(&isert_conn->conn_accept_node); | 
|  | 2816 | mutex_unlock(&isert_np->np_accept_mutex); | 
|  | 2817 |  | 
|  | 2818 | conn->context = isert_conn; | 
|  | 2819 | isert_conn->conn = conn; | 
|  | 2820 | max_accept = 0; | 
|  | 2821 |  | 
|  | 2822 | ret = isert_rdma_post_recvl(isert_conn); | 
|  | 2823 | if (ret) | 
|  | 2824 | return ret; | 
|  | 2825 |  | 
|  | 2826 | ret = isert_rdma_accept(isert_conn); | 
|  | 2827 | if (ret) | 
|  | 2828 | return ret; | 
|  | 2829 |  | 
|  | 2830 | isert_set_conn_info(np, conn, isert_conn); | 
|  | 2831 |  | 
|  | 2832 | pr_debug("Processing isert_accept_np: isert_conn: %p\n", isert_conn); | 
|  | 2833 | return 0; | 
|  | 2834 | } | 
|  | 2835 |  | 
|  | 2836 | static void | 
|  | 2837 | isert_free_np(struct iscsi_np *np) | 
|  | 2838 | { | 
|  | 2839 | struct isert_np *isert_np = (struct isert_np *)np->np_context; | 
|  | 2840 |  | 
|  | 2841 | rdma_destroy_id(isert_np->np_cm_id); | 
|  | 2842 |  | 
|  | 2843 | np->np_context = NULL; | 
|  | 2844 | kfree(isert_np); | 
|  | 2845 | } | 
|  | 2846 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 2847 | static void isert_wait_conn(struct iscsi_conn *conn) | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2848 | { | 
|  | 2849 | struct isert_conn *isert_conn = conn->context; | 
|  | 2850 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 2851 | pr_debug("isert_wait_conn: Starting \n"); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2852 | /* | 
|  | 2853 | * Decrement post_send_buf_count for special case when called | 
|  | 2854 | * from isert_do_control_comp() -> iscsit_logout_post_handler() | 
|  | 2855 | */ | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 2856 | mutex_lock(&isert_conn->conn_mutex); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2857 | if (isert_conn->logout_posted) | 
|  | 2858 | atomic_dec(&isert_conn->post_send_buf_count); | 
|  | 2859 |  | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 2860 | if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) { | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 2861 | pr_debug("Calling rdma_disconnect from isert_wait_conn\n"); | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2862 | rdma_disconnect(isert_conn->conn_cm_id); | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 2863 | } | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2864 | /* | 
|  | 2865 | * Only wait for conn_wait_comp_err if the isert_conn made it | 
|  | 2866 | * into full feature phase.. | 
|  | 2867 | */ | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 2868 | if (isert_conn->state == ISER_CONN_INIT) { | 
|  | 2869 | mutex_unlock(&isert_conn->conn_mutex); | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 2870 | return; | 
|  | 2871 | } | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 2872 | if (isert_conn->state == ISER_CONN_UP) | 
|  | 2873 | isert_conn->state = ISER_CONN_TERMINATING; | 
| Nicholas Bellinger | b2cb964 | 2013-07-03 03:05:37 -0700 | [diff] [blame] | 2874 | mutex_unlock(&isert_conn->conn_mutex); | 
|  | 2875 |  | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 2876 | wait_for_completion(&isert_conn->conn_wait_comp_err); | 
|  | 2877 |  | 
|  | 2878 | wait_for_completion(&isert_conn->conn_wait); | 
|  | 2879 | } | 
|  | 2880 |  | 
|  | 2881 | static void isert_free_conn(struct iscsi_conn *conn) | 
|  | 2882 | { | 
|  | 2883 | struct isert_conn *isert_conn = conn->context; | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2884 |  | 
|  | 2885 | isert_put_conn(isert_conn); | 
|  | 2886 | } | 
|  | 2887 |  | 
|  | 2888 | static struct iscsit_transport iser_target_transport = { | 
|  | 2889 | .name			= "IB/iSER", | 
|  | 2890 | .transport_type		= ISCSI_INFINIBAND, | 
| Nicholas Bellinger | d703ce2 | 2013-08-17 14:27:56 -0700 | [diff] [blame] | 2891 | .priv_size		= sizeof(struct isert_cmd), | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2892 | .owner			= THIS_MODULE, | 
|  | 2893 | .iscsit_setup_np	= isert_setup_np, | 
|  | 2894 | .iscsit_accept_np	= isert_accept_np, | 
|  | 2895 | .iscsit_free_np		= isert_free_np, | 
| Nicholas Bellinger | defd884 | 2014-02-03 12:54:39 -0800 | [diff] [blame] | 2896 | .iscsit_wait_conn	= isert_wait_conn, | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2897 | .iscsit_free_conn	= isert_free_conn, | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2898 | .iscsit_get_login_rx	= isert_get_login_rx, | 
|  | 2899 | .iscsit_put_login_tx	= isert_put_login_tx, | 
|  | 2900 | .iscsit_immediate_queue	= isert_immediate_queue, | 
|  | 2901 | .iscsit_response_queue	= isert_response_queue, | 
|  | 2902 | .iscsit_get_dataout	= isert_get_dataout, | 
|  | 2903 | .iscsit_queue_data_in	= isert_put_datain, | 
|  | 2904 | .iscsit_queue_status	= isert_put_response, | 
|  | 2905 | }; | 
|  | 2906 |  | 
|  | 2907 | static int __init isert_init(void) | 
|  | 2908 | { | 
|  | 2909 | int ret; | 
|  | 2910 |  | 
|  | 2911 | isert_rx_wq = alloc_workqueue("isert_rx_wq", 0, 0); | 
|  | 2912 | if (!isert_rx_wq) { | 
|  | 2913 | pr_err("Unable to allocate isert_rx_wq\n"); | 
|  | 2914 | return -ENOMEM; | 
|  | 2915 | } | 
|  | 2916 |  | 
|  | 2917 | isert_comp_wq = alloc_workqueue("isert_comp_wq", 0, 0); | 
|  | 2918 | if (!isert_comp_wq) { | 
|  | 2919 | pr_err("Unable to allocate isert_comp_wq\n"); | 
|  | 2920 | ret = -ENOMEM; | 
|  | 2921 | goto destroy_rx_wq; | 
|  | 2922 | } | 
|  | 2923 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2924 | iscsit_register_transport(&iser_target_transport); | 
|  | 2925 | pr_debug("iSER_TARGET[0] - Loaded iser_target_transport\n"); | 
|  | 2926 | return 0; | 
|  | 2927 |  | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2928 | destroy_rx_wq: | 
|  | 2929 | destroy_workqueue(isert_rx_wq); | 
|  | 2930 | return ret; | 
|  | 2931 | } | 
|  | 2932 |  | 
|  | 2933 | static void __exit isert_exit(void) | 
|  | 2934 | { | 
| Nicholas Bellinger | b8d26b3 | 2013-03-07 00:56:19 -0800 | [diff] [blame] | 2935 | destroy_workqueue(isert_comp_wq); | 
|  | 2936 | destroy_workqueue(isert_rx_wq); | 
|  | 2937 | iscsit_unregister_transport(&iser_target_transport); | 
|  | 2938 | pr_debug("iSER_TARGET[0] - Released iser_target_transport\n"); | 
|  | 2939 | } | 
|  | 2940 |  | 
|  | 2941 | MODULE_DESCRIPTION("iSER-Target for mainline target infrastructure"); | 
|  | 2942 | MODULE_VERSION("0.1"); | 
|  | 2943 | MODULE_AUTHOR("nab@Linux-iSCSI.org"); | 
|  | 2944 | MODULE_LICENSE("GPL"); | 
|  | 2945 |  | 
|  | 2946 | module_init(isert_init); | 
|  | 2947 | module_exit(isert_exit); |