1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
3*4882a593Smuzhiyun * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.
4*4882a593Smuzhiyun * Copyright (c) 2013-2014 Mellanox Technologies. All rights reserved.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This software is available to you under a choice of one of two
7*4882a593Smuzhiyun * licenses. You may choose to be licensed under the terms of the GNU
8*4882a593Smuzhiyun * General Public License (GPL) Version 2, available from the file
9*4882a593Smuzhiyun * COPYING in the main directory of this source tree, or the
10*4882a593Smuzhiyun * OpenIB.org BSD license below:
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or
13*4882a593Smuzhiyun * without modification, are permitted provided that the following
14*4882a593Smuzhiyun * conditions are met:
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * - Redistributions of source code must retain the above
17*4882a593Smuzhiyun * copyright notice, this list of conditions and the following
18*4882a593Smuzhiyun * disclaimer.
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * - Redistributions in binary form must reproduce the above
21*4882a593Smuzhiyun * copyright notice, this list of conditions and the following
22*4882a593Smuzhiyun * disclaimer in the documentation and/or other materials
23*4882a593Smuzhiyun * provided with the distribution.
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26*4882a593Smuzhiyun * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27*4882a593Smuzhiyun * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28*4882a593Smuzhiyun * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29*4882a593Smuzhiyun * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30*4882a593Smuzhiyun * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31*4882a593Smuzhiyun * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32*4882a593Smuzhiyun * SOFTWARE.
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun #include <linux/kernel.h>
35*4882a593Smuzhiyun #include <linux/module.h>
36*4882a593Smuzhiyun #include <linux/slab.h>
37*4882a593Smuzhiyun #include <linux/delay.h>
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include "iscsi_iser.h"
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define ISCSI_ISER_MAX_CONN 8
42*4882a593Smuzhiyun #define ISER_MAX_RX_LEN (ISER_QP_MAX_RECV_DTOS * ISCSI_ISER_MAX_CONN)
43*4882a593Smuzhiyun #define ISER_MAX_TX_LEN (ISER_QP_MAX_REQ_DTOS * ISCSI_ISER_MAX_CONN)
44*4882a593Smuzhiyun #define ISER_MAX_CQ_LEN (ISER_MAX_RX_LEN + ISER_MAX_TX_LEN + \
45*4882a593Smuzhiyun ISCSI_ISER_MAX_CONN)
46*4882a593Smuzhiyun
iser_qp_event_callback(struct ib_event * cause,void * context)47*4882a593Smuzhiyun static void iser_qp_event_callback(struct ib_event *cause, void *context)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun iser_err("qp event %s (%d)\n",
50*4882a593Smuzhiyun ib_event_msg(cause->event), cause->event);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
iser_event_handler(struct ib_event_handler * handler,struct ib_event * event)53*4882a593Smuzhiyun static void iser_event_handler(struct ib_event_handler *handler,
54*4882a593Smuzhiyun struct ib_event *event)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun iser_err("async event %s (%d) on device %s port %d\n",
57*4882a593Smuzhiyun ib_event_msg(event->event), event->event,
58*4882a593Smuzhiyun dev_name(&event->device->dev), event->element.port_num);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun * iser_create_device_ib_res - creates Protection Domain (PD), Completion
63*4882a593Smuzhiyun * Queue (CQ), DMA Memory Region (DMA MR) with the device associated with
64*4882a593Smuzhiyun * the adaptor.
65*4882a593Smuzhiyun *
66*4882a593Smuzhiyun * Return: 0 on success, -1 on failure
67*4882a593Smuzhiyun */
iser_create_device_ib_res(struct iser_device * device)68*4882a593Smuzhiyun static int iser_create_device_ib_res(struct iser_device *device)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun struct ib_device *ib_dev = device->ib_device;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun if (!(ib_dev->attrs.device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS)) {
73*4882a593Smuzhiyun iser_err("IB device does not support memory registrations\n");
74*4882a593Smuzhiyun return -1;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun device->pd = ib_alloc_pd(ib_dev,
78*4882a593Smuzhiyun iser_always_reg ? 0 : IB_PD_UNSAFE_GLOBAL_RKEY);
79*4882a593Smuzhiyun if (IS_ERR(device->pd))
80*4882a593Smuzhiyun goto pd_err;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun INIT_IB_EVENT_HANDLER(&device->event_handler, ib_dev,
83*4882a593Smuzhiyun iser_event_handler);
84*4882a593Smuzhiyun ib_register_event_handler(&device->event_handler);
85*4882a593Smuzhiyun return 0;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun pd_err:
88*4882a593Smuzhiyun iser_err("failed to allocate an IB resource\n");
89*4882a593Smuzhiyun return -1;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun * iser_free_device_ib_res - destroy/dealloc/dereg the DMA MR,
94*4882a593Smuzhiyun * CQ and PD created with the device associated with the adaptor.
95*4882a593Smuzhiyun */
iser_free_device_ib_res(struct iser_device * device)96*4882a593Smuzhiyun static void iser_free_device_ib_res(struct iser_device *device)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun ib_unregister_event_handler(&device->event_handler);
99*4882a593Smuzhiyun ib_dealloc_pd(device->pd);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun device->pd = NULL;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun static struct iser_fr_desc *
iser_create_fastreg_desc(struct iser_device * device,struct ib_pd * pd,bool pi_enable,unsigned int size)105*4882a593Smuzhiyun iser_create_fastreg_desc(struct iser_device *device,
106*4882a593Smuzhiyun struct ib_pd *pd,
107*4882a593Smuzhiyun bool pi_enable,
108*4882a593Smuzhiyun unsigned int size)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun struct iser_fr_desc *desc;
111*4882a593Smuzhiyun struct ib_device *ib_dev = device->ib_device;
112*4882a593Smuzhiyun enum ib_mr_type mr_type;
113*4882a593Smuzhiyun int ret;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun desc = kzalloc(sizeof(*desc), GFP_KERNEL);
116*4882a593Smuzhiyun if (!desc)
117*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (ib_dev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)
120*4882a593Smuzhiyun mr_type = IB_MR_TYPE_SG_GAPS;
121*4882a593Smuzhiyun else
122*4882a593Smuzhiyun mr_type = IB_MR_TYPE_MEM_REG;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun desc->rsc.mr = ib_alloc_mr(pd, mr_type, size);
125*4882a593Smuzhiyun if (IS_ERR(desc->rsc.mr)) {
126*4882a593Smuzhiyun ret = PTR_ERR(desc->rsc.mr);
127*4882a593Smuzhiyun iser_err("Failed to allocate ib_fast_reg_mr err=%d\n", ret);
128*4882a593Smuzhiyun goto err_alloc_mr;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (pi_enable) {
132*4882a593Smuzhiyun desc->rsc.sig_mr = ib_alloc_mr_integrity(pd, size, size);
133*4882a593Smuzhiyun if (IS_ERR(desc->rsc.sig_mr)) {
134*4882a593Smuzhiyun ret = PTR_ERR(desc->rsc.sig_mr);
135*4882a593Smuzhiyun iser_err("Failed to allocate sig_mr err=%d\n", ret);
136*4882a593Smuzhiyun goto err_alloc_mr_integrity;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun desc->rsc.mr_valid = 0;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun return desc;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun err_alloc_mr_integrity:
144*4882a593Smuzhiyun ib_dereg_mr(desc->rsc.mr);
145*4882a593Smuzhiyun err_alloc_mr:
146*4882a593Smuzhiyun kfree(desc);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun return ERR_PTR(ret);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
iser_destroy_fastreg_desc(struct iser_fr_desc * desc)151*4882a593Smuzhiyun static void iser_destroy_fastreg_desc(struct iser_fr_desc *desc)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun struct iser_reg_resources *res = &desc->rsc;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun ib_dereg_mr(res->mr);
156*4882a593Smuzhiyun if (res->sig_mr) {
157*4882a593Smuzhiyun ib_dereg_mr(res->sig_mr);
158*4882a593Smuzhiyun res->sig_mr = NULL;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun kfree(desc);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /**
164*4882a593Smuzhiyun * iser_alloc_fastreg_pool - Creates pool of fast_reg descriptors
165*4882a593Smuzhiyun * for fast registration work requests.
166*4882a593Smuzhiyun * @ib_conn: connection RDMA resources
167*4882a593Smuzhiyun * @cmds_max: max number of SCSI commands for this connection
168*4882a593Smuzhiyun * @size: max number of pages per map request
169*4882a593Smuzhiyun *
170*4882a593Smuzhiyun * Return: 0 on success, or errno code on failure
171*4882a593Smuzhiyun */
iser_alloc_fastreg_pool(struct ib_conn * ib_conn,unsigned cmds_max,unsigned int size)172*4882a593Smuzhiyun int iser_alloc_fastreg_pool(struct ib_conn *ib_conn,
173*4882a593Smuzhiyun unsigned cmds_max,
174*4882a593Smuzhiyun unsigned int size)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun struct iser_device *device = ib_conn->device;
177*4882a593Smuzhiyun struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
178*4882a593Smuzhiyun struct iser_fr_desc *desc;
179*4882a593Smuzhiyun int i, ret;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun INIT_LIST_HEAD(&fr_pool->list);
182*4882a593Smuzhiyun INIT_LIST_HEAD(&fr_pool->all_list);
183*4882a593Smuzhiyun spin_lock_init(&fr_pool->lock);
184*4882a593Smuzhiyun fr_pool->size = 0;
185*4882a593Smuzhiyun for (i = 0; i < cmds_max; i++) {
186*4882a593Smuzhiyun desc = iser_create_fastreg_desc(device, device->pd,
187*4882a593Smuzhiyun ib_conn->pi_support, size);
188*4882a593Smuzhiyun if (IS_ERR(desc)) {
189*4882a593Smuzhiyun ret = PTR_ERR(desc);
190*4882a593Smuzhiyun goto err;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun list_add_tail(&desc->list, &fr_pool->list);
194*4882a593Smuzhiyun list_add_tail(&desc->all_list, &fr_pool->all_list);
195*4882a593Smuzhiyun fr_pool->size++;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun return 0;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun err:
201*4882a593Smuzhiyun iser_free_fastreg_pool(ib_conn);
202*4882a593Smuzhiyun return ret;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /**
206*4882a593Smuzhiyun * iser_free_fastreg_pool - releases the pool of fast_reg descriptors
207*4882a593Smuzhiyun * @ib_conn: connection RDMA resources
208*4882a593Smuzhiyun */
iser_free_fastreg_pool(struct ib_conn * ib_conn)209*4882a593Smuzhiyun void iser_free_fastreg_pool(struct ib_conn *ib_conn)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
212*4882a593Smuzhiyun struct iser_fr_desc *desc, *tmp;
213*4882a593Smuzhiyun int i = 0;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun if (list_empty(&fr_pool->all_list))
216*4882a593Smuzhiyun return;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun iser_info("freeing conn %p fr pool\n", ib_conn);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun list_for_each_entry_safe(desc, tmp, &fr_pool->all_list, all_list) {
221*4882a593Smuzhiyun list_del(&desc->all_list);
222*4882a593Smuzhiyun iser_destroy_fastreg_desc(desc);
223*4882a593Smuzhiyun ++i;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun if (i < fr_pool->size)
227*4882a593Smuzhiyun iser_warn("pool still has %d regions registered\n",
228*4882a593Smuzhiyun fr_pool->size - i);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun /*
232*4882a593Smuzhiyun * iser_create_ib_conn_res - Queue-Pair (QP)
233*4882a593Smuzhiyun *
234*4882a593Smuzhiyun * Return: 0 on success, -1 on failure
235*4882a593Smuzhiyun */
iser_create_ib_conn_res(struct ib_conn * ib_conn)236*4882a593Smuzhiyun static int iser_create_ib_conn_res(struct ib_conn *ib_conn)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun struct iser_conn *iser_conn = to_iser_conn(ib_conn);
239*4882a593Smuzhiyun struct iser_device *device;
240*4882a593Smuzhiyun struct ib_device *ib_dev;
241*4882a593Smuzhiyun struct ib_qp_init_attr init_attr;
242*4882a593Smuzhiyun int ret = -ENOMEM;
243*4882a593Smuzhiyun unsigned int max_send_wr, cq_size;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun BUG_ON(ib_conn->device == NULL);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun device = ib_conn->device;
248*4882a593Smuzhiyun ib_dev = device->ib_device;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun if (ib_conn->pi_support)
251*4882a593Smuzhiyun max_send_wr = ISER_QP_SIG_MAX_REQ_DTOS + 1;
252*4882a593Smuzhiyun else
253*4882a593Smuzhiyun max_send_wr = ISER_QP_MAX_REQ_DTOS + 1;
254*4882a593Smuzhiyun max_send_wr = min_t(unsigned int, max_send_wr,
255*4882a593Smuzhiyun (unsigned int)ib_dev->attrs.max_qp_wr);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun cq_size = max_send_wr + ISER_QP_MAX_RECV_DTOS;
258*4882a593Smuzhiyun ib_conn->cq = ib_cq_pool_get(ib_dev, cq_size, -1, IB_POLL_SOFTIRQ);
259*4882a593Smuzhiyun if (IS_ERR(ib_conn->cq)) {
260*4882a593Smuzhiyun ret = PTR_ERR(ib_conn->cq);
261*4882a593Smuzhiyun goto cq_err;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun ib_conn->cq_size = cq_size;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun memset(&init_attr, 0, sizeof(init_attr));
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun init_attr.event_handler = iser_qp_event_callback;
268*4882a593Smuzhiyun init_attr.qp_context = (void *)ib_conn;
269*4882a593Smuzhiyun init_attr.send_cq = ib_conn->cq;
270*4882a593Smuzhiyun init_attr.recv_cq = ib_conn->cq;
271*4882a593Smuzhiyun init_attr.cap.max_recv_wr = ISER_QP_MAX_RECV_DTOS;
272*4882a593Smuzhiyun init_attr.cap.max_send_sge = 2;
273*4882a593Smuzhiyun init_attr.cap.max_recv_sge = 1;
274*4882a593Smuzhiyun init_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
275*4882a593Smuzhiyun init_attr.qp_type = IB_QPT_RC;
276*4882a593Smuzhiyun init_attr.cap.max_send_wr = max_send_wr;
277*4882a593Smuzhiyun if (ib_conn->pi_support)
278*4882a593Smuzhiyun init_attr.create_flags |= IB_QP_CREATE_INTEGRITY_EN;
279*4882a593Smuzhiyun iser_conn->max_cmds = ISER_GET_MAX_XMIT_CMDS(max_send_wr - 1);
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun ret = rdma_create_qp(ib_conn->cma_id, device->pd, &init_attr);
282*4882a593Smuzhiyun if (ret)
283*4882a593Smuzhiyun goto out_err;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun ib_conn->qp = ib_conn->cma_id->qp;
286*4882a593Smuzhiyun iser_info("setting conn %p cma_id %p qp %p max_send_wr %d\n",
287*4882a593Smuzhiyun ib_conn, ib_conn->cma_id,
288*4882a593Smuzhiyun ib_conn->cma_id->qp, max_send_wr);
289*4882a593Smuzhiyun return ret;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun out_err:
292*4882a593Smuzhiyun ib_cq_pool_put(ib_conn->cq, ib_conn->cq_size);
293*4882a593Smuzhiyun cq_err:
294*4882a593Smuzhiyun iser_err("unable to alloc mem or create resource, err %d\n", ret);
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun return ret;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun /*
300*4882a593Smuzhiyun * based on the resolved device node GUID see if there already allocated
301*4882a593Smuzhiyun * device for this device. If there's no such, create one.
302*4882a593Smuzhiyun */
303*4882a593Smuzhiyun static
iser_device_find_by_ib_device(struct rdma_cm_id * cma_id)304*4882a593Smuzhiyun struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun struct iser_device *device;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun mutex_lock(&ig.device_list_mutex);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun list_for_each_entry(device, &ig.device_list, ig_list)
311*4882a593Smuzhiyun /* find if there's a match using the node GUID */
312*4882a593Smuzhiyun if (device->ib_device->node_guid == cma_id->device->node_guid)
313*4882a593Smuzhiyun goto inc_refcnt;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun device = kzalloc(sizeof *device, GFP_KERNEL);
316*4882a593Smuzhiyun if (device == NULL)
317*4882a593Smuzhiyun goto out;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun /* assign this device to the device */
320*4882a593Smuzhiyun device->ib_device = cma_id->device;
321*4882a593Smuzhiyun /* init the device and link it into ig device list */
322*4882a593Smuzhiyun if (iser_create_device_ib_res(device)) {
323*4882a593Smuzhiyun kfree(device);
324*4882a593Smuzhiyun device = NULL;
325*4882a593Smuzhiyun goto out;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun list_add(&device->ig_list, &ig.device_list);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun inc_refcnt:
330*4882a593Smuzhiyun device->refcount++;
331*4882a593Smuzhiyun out:
332*4882a593Smuzhiyun mutex_unlock(&ig.device_list_mutex);
333*4882a593Smuzhiyun return device;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /* if there's no demand for this device, release it */
iser_device_try_release(struct iser_device * device)337*4882a593Smuzhiyun static void iser_device_try_release(struct iser_device *device)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun mutex_lock(&ig.device_list_mutex);
340*4882a593Smuzhiyun device->refcount--;
341*4882a593Smuzhiyun iser_info("device %p refcount %d\n", device, device->refcount);
342*4882a593Smuzhiyun if (!device->refcount) {
343*4882a593Smuzhiyun iser_free_device_ib_res(device);
344*4882a593Smuzhiyun list_del(&device->ig_list);
345*4882a593Smuzhiyun kfree(device);
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun mutex_unlock(&ig.device_list_mutex);
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /*
351*4882a593Smuzhiyun * Called with state mutex held
352*4882a593Smuzhiyun */
iser_conn_state_comp_exch(struct iser_conn * iser_conn,enum iser_conn_state comp,enum iser_conn_state exch)353*4882a593Smuzhiyun static int iser_conn_state_comp_exch(struct iser_conn *iser_conn,
354*4882a593Smuzhiyun enum iser_conn_state comp,
355*4882a593Smuzhiyun enum iser_conn_state exch)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun int ret;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun ret = (iser_conn->state == comp);
360*4882a593Smuzhiyun if (ret)
361*4882a593Smuzhiyun iser_conn->state = exch;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun return ret;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
iser_release_work(struct work_struct * work)366*4882a593Smuzhiyun void iser_release_work(struct work_struct *work)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun struct iser_conn *iser_conn;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun iser_conn = container_of(work, struct iser_conn, release_work);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun /* Wait for conn_stop to complete */
373*4882a593Smuzhiyun wait_for_completion(&iser_conn->stop_completion);
374*4882a593Smuzhiyun /* Wait for IB resouces cleanup to complete */
375*4882a593Smuzhiyun wait_for_completion(&iser_conn->ib_completion);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun mutex_lock(&iser_conn->state_mutex);
378*4882a593Smuzhiyun iser_conn->state = ISER_CONN_DOWN;
379*4882a593Smuzhiyun mutex_unlock(&iser_conn->state_mutex);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun iser_conn_release(iser_conn);
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun /**
385*4882a593Smuzhiyun * iser_free_ib_conn_res - release IB related resources
386*4882a593Smuzhiyun * @iser_conn: iser connection struct
387*4882a593Smuzhiyun * @destroy: indicator if we need to try to release the
388*4882a593Smuzhiyun * iser device and memory regoins pool (only iscsi
389*4882a593Smuzhiyun * shutdown and DEVICE_REMOVAL will use this).
390*4882a593Smuzhiyun *
391*4882a593Smuzhiyun * This routine is called with the iser state mutex held
392*4882a593Smuzhiyun * so the cm_id removal is out of here. It is Safe to
393*4882a593Smuzhiyun * be invoked multiple times.
394*4882a593Smuzhiyun */
iser_free_ib_conn_res(struct iser_conn * iser_conn,bool destroy)395*4882a593Smuzhiyun static void iser_free_ib_conn_res(struct iser_conn *iser_conn,
396*4882a593Smuzhiyun bool destroy)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun struct ib_conn *ib_conn = &iser_conn->ib_conn;
399*4882a593Smuzhiyun struct iser_device *device = ib_conn->device;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun iser_info("freeing conn %p cma_id %p qp %p\n",
402*4882a593Smuzhiyun iser_conn, ib_conn->cma_id, ib_conn->qp);
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (ib_conn->qp != NULL) {
405*4882a593Smuzhiyun rdma_destroy_qp(ib_conn->cma_id);
406*4882a593Smuzhiyun ib_cq_pool_put(ib_conn->cq, ib_conn->cq_size);
407*4882a593Smuzhiyun ib_conn->qp = NULL;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun if (destroy) {
411*4882a593Smuzhiyun if (iser_conn->rx_descs)
412*4882a593Smuzhiyun iser_free_rx_descriptors(iser_conn);
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun if (device != NULL) {
415*4882a593Smuzhiyun iser_device_try_release(device);
416*4882a593Smuzhiyun ib_conn->device = NULL;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun /**
422*4882a593Smuzhiyun * iser_conn_release - Frees all conn objects and deallocs conn descriptor
423*4882a593Smuzhiyun * @iser_conn: iSER connection context
424*4882a593Smuzhiyun */
iser_conn_release(struct iser_conn * iser_conn)425*4882a593Smuzhiyun void iser_conn_release(struct iser_conn *iser_conn)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun struct ib_conn *ib_conn = &iser_conn->ib_conn;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun mutex_lock(&ig.connlist_mutex);
430*4882a593Smuzhiyun list_del(&iser_conn->conn_list);
431*4882a593Smuzhiyun mutex_unlock(&ig.connlist_mutex);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun mutex_lock(&iser_conn->state_mutex);
434*4882a593Smuzhiyun /* In case we endup here without ep_disconnect being invoked. */
435*4882a593Smuzhiyun if (iser_conn->state != ISER_CONN_DOWN) {
436*4882a593Smuzhiyun iser_warn("iser conn %p state %d, expected state down.\n",
437*4882a593Smuzhiyun iser_conn, iser_conn->state);
438*4882a593Smuzhiyun iscsi_destroy_endpoint(iser_conn->ep);
439*4882a593Smuzhiyun iser_conn->state = ISER_CONN_DOWN;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun /*
442*4882a593Smuzhiyun * In case we never got to bind stage, we still need to
443*4882a593Smuzhiyun * release IB resources (which is safe to call more than once).
444*4882a593Smuzhiyun */
445*4882a593Smuzhiyun iser_free_ib_conn_res(iser_conn, true);
446*4882a593Smuzhiyun mutex_unlock(&iser_conn->state_mutex);
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun if (ib_conn->cma_id != NULL) {
449*4882a593Smuzhiyun rdma_destroy_id(ib_conn->cma_id);
450*4882a593Smuzhiyun ib_conn->cma_id = NULL;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun kfree(iser_conn);
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun /**
457*4882a593Smuzhiyun * iser_conn_terminate - triggers start of the disconnect procedures and
458*4882a593Smuzhiyun * waits for them to be done
459*4882a593Smuzhiyun * @iser_conn: iSER connection context
460*4882a593Smuzhiyun *
461*4882a593Smuzhiyun * Called with state mutex held
462*4882a593Smuzhiyun */
iser_conn_terminate(struct iser_conn * iser_conn)463*4882a593Smuzhiyun int iser_conn_terminate(struct iser_conn *iser_conn)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun struct ib_conn *ib_conn = &iser_conn->ib_conn;
466*4882a593Smuzhiyun int err = 0;
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun /* terminate the iser conn only if the conn state is UP */
469*4882a593Smuzhiyun if (!iser_conn_state_comp_exch(iser_conn, ISER_CONN_UP,
470*4882a593Smuzhiyun ISER_CONN_TERMINATING))
471*4882a593Smuzhiyun return 0;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun iser_info("iser_conn %p state %d\n", iser_conn, iser_conn->state);
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun /* suspend queuing of new iscsi commands */
476*4882a593Smuzhiyun if (iser_conn->iscsi_conn)
477*4882a593Smuzhiyun iscsi_suspend_queue(iser_conn->iscsi_conn);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /*
480*4882a593Smuzhiyun * In case we didn't already clean up the cma_id (peer initiated
481*4882a593Smuzhiyun * a disconnection), we need to Cause the CMA to change the QP
482*4882a593Smuzhiyun * state to ERROR.
483*4882a593Smuzhiyun */
484*4882a593Smuzhiyun if (ib_conn->cma_id) {
485*4882a593Smuzhiyun err = rdma_disconnect(ib_conn->cma_id);
486*4882a593Smuzhiyun if (err)
487*4882a593Smuzhiyun iser_err("Failed to disconnect, conn: 0x%p err %d\n",
488*4882a593Smuzhiyun iser_conn, err);
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun /* block until all flush errors are consumed */
491*4882a593Smuzhiyun ib_drain_sq(ib_conn->qp);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun return 1;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun /*
498*4882a593Smuzhiyun * Called with state mutex held
499*4882a593Smuzhiyun */
iser_connect_error(struct rdma_cm_id * cma_id)500*4882a593Smuzhiyun static void iser_connect_error(struct rdma_cm_id *cma_id)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun struct iser_conn *iser_conn;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun iser_conn = (struct iser_conn *)cma_id->context;
505*4882a593Smuzhiyun iser_conn->state = ISER_CONN_TERMINATING;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun static void
iser_calc_scsi_params(struct iser_conn * iser_conn,unsigned int max_sectors)509*4882a593Smuzhiyun iser_calc_scsi_params(struct iser_conn *iser_conn,
510*4882a593Smuzhiyun unsigned int max_sectors)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun struct iser_device *device = iser_conn->ib_conn.device;
513*4882a593Smuzhiyun struct ib_device_attr *attr = &device->ib_device->attrs;
514*4882a593Smuzhiyun unsigned short sg_tablesize, sup_sg_tablesize;
515*4882a593Smuzhiyun unsigned short reserved_mr_pages;
516*4882a593Smuzhiyun u32 max_num_sg;
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun /*
519*4882a593Smuzhiyun * FRs without SG_GAPS can only map up to a (device) page per entry,
520*4882a593Smuzhiyun * but if the first entry is misaligned we'll end up using two entries
521*4882a593Smuzhiyun * (head and tail) for a single page worth data, so one additional
522*4882a593Smuzhiyun * entry is required.
523*4882a593Smuzhiyun */
524*4882a593Smuzhiyun if (attr->device_cap_flags & IB_DEVICE_SG_GAPS_REG)
525*4882a593Smuzhiyun reserved_mr_pages = 0;
526*4882a593Smuzhiyun else
527*4882a593Smuzhiyun reserved_mr_pages = 1;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun if (iser_conn->ib_conn.pi_support)
530*4882a593Smuzhiyun max_num_sg = attr->max_pi_fast_reg_page_list_len;
531*4882a593Smuzhiyun else
532*4882a593Smuzhiyun max_num_sg = attr->max_fast_reg_page_list_len;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun sg_tablesize = DIV_ROUND_UP(max_sectors * SECTOR_SIZE, SZ_4K);
535*4882a593Smuzhiyun sup_sg_tablesize = min_t(uint, ISCSI_ISER_MAX_SG_TABLESIZE,
536*4882a593Smuzhiyun max_num_sg - reserved_mr_pages);
537*4882a593Smuzhiyun iser_conn->scsi_sg_tablesize = min(sg_tablesize, sup_sg_tablesize);
538*4882a593Smuzhiyun iser_conn->pages_per_mr =
539*4882a593Smuzhiyun iser_conn->scsi_sg_tablesize + reserved_mr_pages;
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun /*
543*4882a593Smuzhiyun * Called with state mutex held
544*4882a593Smuzhiyun */
iser_addr_handler(struct rdma_cm_id * cma_id)545*4882a593Smuzhiyun static void iser_addr_handler(struct rdma_cm_id *cma_id)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun struct iser_device *device;
548*4882a593Smuzhiyun struct iser_conn *iser_conn;
549*4882a593Smuzhiyun struct ib_conn *ib_conn;
550*4882a593Smuzhiyun int ret;
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun iser_conn = (struct iser_conn *)cma_id->context;
553*4882a593Smuzhiyun if (iser_conn->state != ISER_CONN_PENDING)
554*4882a593Smuzhiyun /* bailout */
555*4882a593Smuzhiyun return;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun ib_conn = &iser_conn->ib_conn;
558*4882a593Smuzhiyun device = iser_device_find_by_ib_device(cma_id);
559*4882a593Smuzhiyun if (!device) {
560*4882a593Smuzhiyun iser_err("device lookup/creation failed\n");
561*4882a593Smuzhiyun iser_connect_error(cma_id);
562*4882a593Smuzhiyun return;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun ib_conn->device = device;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun /* connection T10-PI support */
568*4882a593Smuzhiyun if (iser_pi_enable) {
569*4882a593Smuzhiyun if (!(device->ib_device->attrs.device_cap_flags &
570*4882a593Smuzhiyun IB_DEVICE_INTEGRITY_HANDOVER)) {
571*4882a593Smuzhiyun iser_warn("T10-PI requested but not supported on %s, "
572*4882a593Smuzhiyun "continue without T10-PI\n",
573*4882a593Smuzhiyun dev_name(&ib_conn->device->ib_device->dev));
574*4882a593Smuzhiyun ib_conn->pi_support = false;
575*4882a593Smuzhiyun } else {
576*4882a593Smuzhiyun ib_conn->pi_support = true;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun iser_calc_scsi_params(iser_conn, iser_max_sectors);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun ret = rdma_resolve_route(cma_id, 1000);
583*4882a593Smuzhiyun if (ret) {
584*4882a593Smuzhiyun iser_err("resolve route failed: %d\n", ret);
585*4882a593Smuzhiyun iser_connect_error(cma_id);
586*4882a593Smuzhiyun return;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun /*
591*4882a593Smuzhiyun * Called with state mutex held
592*4882a593Smuzhiyun */
iser_route_handler(struct rdma_cm_id * cma_id)593*4882a593Smuzhiyun static void iser_route_handler(struct rdma_cm_id *cma_id)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun struct rdma_conn_param conn_param;
596*4882a593Smuzhiyun int ret;
597*4882a593Smuzhiyun struct iser_cm_hdr req_hdr;
598*4882a593Smuzhiyun struct iser_conn *iser_conn = (struct iser_conn *)cma_id->context;
599*4882a593Smuzhiyun struct ib_conn *ib_conn = &iser_conn->ib_conn;
600*4882a593Smuzhiyun struct ib_device *ib_dev = ib_conn->device->ib_device;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun if (iser_conn->state != ISER_CONN_PENDING)
603*4882a593Smuzhiyun /* bailout */
604*4882a593Smuzhiyun return;
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun ret = iser_create_ib_conn_res(ib_conn);
607*4882a593Smuzhiyun if (ret)
608*4882a593Smuzhiyun goto failure;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun memset(&conn_param, 0, sizeof conn_param);
611*4882a593Smuzhiyun conn_param.responder_resources = ib_dev->attrs.max_qp_rd_atom;
612*4882a593Smuzhiyun conn_param.initiator_depth = 1;
613*4882a593Smuzhiyun conn_param.retry_count = 7;
614*4882a593Smuzhiyun conn_param.rnr_retry_count = 6;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun memset(&req_hdr, 0, sizeof(req_hdr));
617*4882a593Smuzhiyun req_hdr.flags = ISER_ZBVA_NOT_SUP;
618*4882a593Smuzhiyun if (!iser_always_reg)
619*4882a593Smuzhiyun req_hdr.flags |= ISER_SEND_W_INV_NOT_SUP;
620*4882a593Smuzhiyun conn_param.private_data = (void *)&req_hdr;
621*4882a593Smuzhiyun conn_param.private_data_len = sizeof(struct iser_cm_hdr);
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun ret = rdma_connect_locked(cma_id, &conn_param);
624*4882a593Smuzhiyun if (ret) {
625*4882a593Smuzhiyun iser_err("failure connecting: %d\n", ret);
626*4882a593Smuzhiyun goto failure;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun return;
630*4882a593Smuzhiyun failure:
631*4882a593Smuzhiyun iser_connect_error(cma_id);
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun
iser_connected_handler(struct rdma_cm_id * cma_id,const void * private_data)634*4882a593Smuzhiyun static void iser_connected_handler(struct rdma_cm_id *cma_id,
635*4882a593Smuzhiyun const void *private_data)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun struct iser_conn *iser_conn;
638*4882a593Smuzhiyun struct ib_qp_attr attr;
639*4882a593Smuzhiyun struct ib_qp_init_attr init_attr;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun iser_conn = (struct iser_conn *)cma_id->context;
642*4882a593Smuzhiyun if (iser_conn->state != ISER_CONN_PENDING)
643*4882a593Smuzhiyun /* bailout */
644*4882a593Smuzhiyun return;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun (void)ib_query_qp(cma_id->qp, &attr, ~0, &init_attr);
647*4882a593Smuzhiyun iser_info("remote qpn:%x my qpn:%x\n", attr.dest_qp_num, cma_id->qp->qp_num);
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun if (private_data) {
650*4882a593Smuzhiyun u8 flags = *(u8 *)private_data;
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun iser_conn->snd_w_inv = !(flags & ISER_SEND_W_INV_NOT_SUP);
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun iser_info("conn %p: negotiated %s invalidation\n",
656*4882a593Smuzhiyun iser_conn, iser_conn->snd_w_inv ? "remote" : "local");
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun iser_conn->state = ISER_CONN_UP;
659*4882a593Smuzhiyun complete(&iser_conn->up_completion);
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
iser_disconnected_handler(struct rdma_cm_id * cma_id)662*4882a593Smuzhiyun static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun struct iser_conn *iser_conn = (struct iser_conn *)cma_id->context;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun if (iser_conn_terminate(iser_conn)) {
667*4882a593Smuzhiyun if (iser_conn->iscsi_conn)
668*4882a593Smuzhiyun iscsi_conn_failure(iser_conn->iscsi_conn,
669*4882a593Smuzhiyun ISCSI_ERR_CONN_FAILED);
670*4882a593Smuzhiyun else
671*4882a593Smuzhiyun iser_err("iscsi_iser connection isn't bound\n");
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun
iser_cleanup_handler(struct rdma_cm_id * cma_id,bool destroy)675*4882a593Smuzhiyun static void iser_cleanup_handler(struct rdma_cm_id *cma_id,
676*4882a593Smuzhiyun bool destroy)
677*4882a593Smuzhiyun {
678*4882a593Smuzhiyun struct iser_conn *iser_conn = (struct iser_conn *)cma_id->context;
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun /*
681*4882a593Smuzhiyun * We are not guaranteed that we visited disconnected_handler
682*4882a593Smuzhiyun * by now, call it here to be safe that we handle CM drep
683*4882a593Smuzhiyun * and flush errors.
684*4882a593Smuzhiyun */
685*4882a593Smuzhiyun iser_disconnected_handler(cma_id);
686*4882a593Smuzhiyun iser_free_ib_conn_res(iser_conn, destroy);
687*4882a593Smuzhiyun complete(&iser_conn->ib_completion);
688*4882a593Smuzhiyun };
689*4882a593Smuzhiyun
iser_cma_handler(struct rdma_cm_id * cma_id,struct rdma_cm_event * event)690*4882a593Smuzhiyun static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun struct iser_conn *iser_conn;
693*4882a593Smuzhiyun int ret = 0;
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun iser_conn = (struct iser_conn *)cma_id->context;
696*4882a593Smuzhiyun iser_info("%s (%d): status %d conn %p id %p\n",
697*4882a593Smuzhiyun rdma_event_msg(event->event), event->event,
698*4882a593Smuzhiyun event->status, cma_id->context, cma_id);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun mutex_lock(&iser_conn->state_mutex);
701*4882a593Smuzhiyun switch (event->event) {
702*4882a593Smuzhiyun case RDMA_CM_EVENT_ADDR_RESOLVED:
703*4882a593Smuzhiyun iser_addr_handler(cma_id);
704*4882a593Smuzhiyun break;
705*4882a593Smuzhiyun case RDMA_CM_EVENT_ROUTE_RESOLVED:
706*4882a593Smuzhiyun iser_route_handler(cma_id);
707*4882a593Smuzhiyun break;
708*4882a593Smuzhiyun case RDMA_CM_EVENT_ESTABLISHED:
709*4882a593Smuzhiyun iser_connected_handler(cma_id, event->param.conn.private_data);
710*4882a593Smuzhiyun break;
711*4882a593Smuzhiyun case RDMA_CM_EVENT_REJECTED:
712*4882a593Smuzhiyun iser_info("Connection rejected: %s\n",
713*4882a593Smuzhiyun rdma_reject_msg(cma_id, event->status));
714*4882a593Smuzhiyun fallthrough;
715*4882a593Smuzhiyun case RDMA_CM_EVENT_ADDR_ERROR:
716*4882a593Smuzhiyun case RDMA_CM_EVENT_ROUTE_ERROR:
717*4882a593Smuzhiyun case RDMA_CM_EVENT_CONNECT_ERROR:
718*4882a593Smuzhiyun case RDMA_CM_EVENT_UNREACHABLE:
719*4882a593Smuzhiyun iser_connect_error(cma_id);
720*4882a593Smuzhiyun break;
721*4882a593Smuzhiyun case RDMA_CM_EVENT_DISCONNECTED:
722*4882a593Smuzhiyun case RDMA_CM_EVENT_ADDR_CHANGE:
723*4882a593Smuzhiyun case RDMA_CM_EVENT_TIMEWAIT_EXIT:
724*4882a593Smuzhiyun iser_cleanup_handler(cma_id, false);
725*4882a593Smuzhiyun break;
726*4882a593Smuzhiyun case RDMA_CM_EVENT_DEVICE_REMOVAL:
727*4882a593Smuzhiyun /*
728*4882a593Smuzhiyun * we *must* destroy the device as we cannot rely
729*4882a593Smuzhiyun * on iscsid to be around to initiate error handling.
730*4882a593Smuzhiyun * also if we are not in state DOWN implicitly destroy
731*4882a593Smuzhiyun * the cma_id.
732*4882a593Smuzhiyun */
733*4882a593Smuzhiyun iser_cleanup_handler(cma_id, true);
734*4882a593Smuzhiyun if (iser_conn->state != ISER_CONN_DOWN) {
735*4882a593Smuzhiyun iser_conn->ib_conn.cma_id = NULL;
736*4882a593Smuzhiyun ret = 1;
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun break;
739*4882a593Smuzhiyun default:
740*4882a593Smuzhiyun iser_err("Unexpected RDMA CM event: %s (%d)\n",
741*4882a593Smuzhiyun rdma_event_msg(event->event), event->event);
742*4882a593Smuzhiyun break;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun mutex_unlock(&iser_conn->state_mutex);
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun return ret;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
iser_conn_init(struct iser_conn * iser_conn)749*4882a593Smuzhiyun void iser_conn_init(struct iser_conn *iser_conn)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun struct ib_conn *ib_conn = &iser_conn->ib_conn;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun iser_conn->state = ISER_CONN_INIT;
754*4882a593Smuzhiyun init_completion(&iser_conn->stop_completion);
755*4882a593Smuzhiyun init_completion(&iser_conn->ib_completion);
756*4882a593Smuzhiyun init_completion(&iser_conn->up_completion);
757*4882a593Smuzhiyun INIT_LIST_HEAD(&iser_conn->conn_list);
758*4882a593Smuzhiyun mutex_init(&iser_conn->state_mutex);
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun ib_conn->post_recv_buf_count = 0;
761*4882a593Smuzhiyun ib_conn->reg_cqe.done = iser_reg_comp;
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun /**
765*4882a593Smuzhiyun * starts the process of connecting to the target
766*4882a593Smuzhiyun * sleeps until the connection is established or rejected
767*4882a593Smuzhiyun */
iser_connect(struct iser_conn * iser_conn,struct sockaddr * src_addr,struct sockaddr * dst_addr,int non_blocking)768*4882a593Smuzhiyun int iser_connect(struct iser_conn *iser_conn,
769*4882a593Smuzhiyun struct sockaddr *src_addr,
770*4882a593Smuzhiyun struct sockaddr *dst_addr,
771*4882a593Smuzhiyun int non_blocking)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun struct ib_conn *ib_conn = &iser_conn->ib_conn;
774*4882a593Smuzhiyun int err = 0;
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun mutex_lock(&iser_conn->state_mutex);
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun sprintf(iser_conn->name, "%pISp", dst_addr);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun iser_info("connecting to: %s\n", iser_conn->name);
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun /* the device is known only --after-- address resolution */
783*4882a593Smuzhiyun ib_conn->device = NULL;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun iser_conn->state = ISER_CONN_PENDING;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun ib_conn->cma_id = rdma_create_id(&init_net, iser_cma_handler,
788*4882a593Smuzhiyun (void *)iser_conn,
789*4882a593Smuzhiyun RDMA_PS_TCP, IB_QPT_RC);
790*4882a593Smuzhiyun if (IS_ERR(ib_conn->cma_id)) {
791*4882a593Smuzhiyun err = PTR_ERR(ib_conn->cma_id);
792*4882a593Smuzhiyun iser_err("rdma_create_id failed: %d\n", err);
793*4882a593Smuzhiyun goto id_failure;
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun err = rdma_resolve_addr(ib_conn->cma_id, src_addr, dst_addr, 1000);
797*4882a593Smuzhiyun if (err) {
798*4882a593Smuzhiyun iser_err("rdma_resolve_addr failed: %d\n", err);
799*4882a593Smuzhiyun goto addr_failure;
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun if (!non_blocking) {
803*4882a593Smuzhiyun wait_for_completion_interruptible(&iser_conn->up_completion);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun if (iser_conn->state != ISER_CONN_UP) {
806*4882a593Smuzhiyun err = -EIO;
807*4882a593Smuzhiyun goto connect_failure;
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun mutex_unlock(&iser_conn->state_mutex);
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun mutex_lock(&ig.connlist_mutex);
813*4882a593Smuzhiyun list_add(&iser_conn->conn_list, &ig.connlist);
814*4882a593Smuzhiyun mutex_unlock(&ig.connlist_mutex);
815*4882a593Smuzhiyun return 0;
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun id_failure:
818*4882a593Smuzhiyun ib_conn->cma_id = NULL;
819*4882a593Smuzhiyun addr_failure:
820*4882a593Smuzhiyun iser_conn->state = ISER_CONN_DOWN;
821*4882a593Smuzhiyun connect_failure:
822*4882a593Smuzhiyun mutex_unlock(&iser_conn->state_mutex);
823*4882a593Smuzhiyun iser_conn_release(iser_conn);
824*4882a593Smuzhiyun return err;
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun
iser_post_recvl(struct iser_conn * iser_conn)827*4882a593Smuzhiyun int iser_post_recvl(struct iser_conn *iser_conn)
828*4882a593Smuzhiyun {
829*4882a593Smuzhiyun struct ib_conn *ib_conn = &iser_conn->ib_conn;
830*4882a593Smuzhiyun struct iser_login_desc *desc = &iser_conn->login_desc;
831*4882a593Smuzhiyun struct ib_recv_wr wr;
832*4882a593Smuzhiyun int ib_ret;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun desc->sge.addr = desc->rsp_dma;
835*4882a593Smuzhiyun desc->sge.length = ISER_RX_LOGIN_SIZE;
836*4882a593Smuzhiyun desc->sge.lkey = ib_conn->device->pd->local_dma_lkey;
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun desc->cqe.done = iser_login_rsp;
839*4882a593Smuzhiyun wr.wr_cqe = &desc->cqe;
840*4882a593Smuzhiyun wr.sg_list = &desc->sge;
841*4882a593Smuzhiyun wr.num_sge = 1;
842*4882a593Smuzhiyun wr.next = NULL;
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun ib_conn->post_recv_buf_count++;
845*4882a593Smuzhiyun ib_ret = ib_post_recv(ib_conn->qp, &wr, NULL);
846*4882a593Smuzhiyun if (ib_ret) {
847*4882a593Smuzhiyun iser_err("ib_post_recv failed ret=%d\n", ib_ret);
848*4882a593Smuzhiyun ib_conn->post_recv_buf_count--;
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun return ib_ret;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun
iser_post_recvm(struct iser_conn * iser_conn,int count)854*4882a593Smuzhiyun int iser_post_recvm(struct iser_conn *iser_conn, int count)
855*4882a593Smuzhiyun {
856*4882a593Smuzhiyun struct ib_conn *ib_conn = &iser_conn->ib_conn;
857*4882a593Smuzhiyun unsigned int my_rx_head = iser_conn->rx_desc_head;
858*4882a593Smuzhiyun struct iser_rx_desc *rx_desc;
859*4882a593Smuzhiyun struct ib_recv_wr *wr;
860*4882a593Smuzhiyun int i, ib_ret;
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun for (wr = ib_conn->rx_wr, i = 0; i < count; i++, wr++) {
863*4882a593Smuzhiyun rx_desc = &iser_conn->rx_descs[my_rx_head];
864*4882a593Smuzhiyun rx_desc->cqe.done = iser_task_rsp;
865*4882a593Smuzhiyun wr->wr_cqe = &rx_desc->cqe;
866*4882a593Smuzhiyun wr->sg_list = &rx_desc->rx_sg;
867*4882a593Smuzhiyun wr->num_sge = 1;
868*4882a593Smuzhiyun wr->next = wr + 1;
869*4882a593Smuzhiyun my_rx_head = (my_rx_head + 1) & iser_conn->qp_max_recv_dtos_mask;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun wr--;
873*4882a593Smuzhiyun wr->next = NULL; /* mark end of work requests list */
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun ib_conn->post_recv_buf_count += count;
876*4882a593Smuzhiyun ib_ret = ib_post_recv(ib_conn->qp, ib_conn->rx_wr, NULL);
877*4882a593Smuzhiyun if (unlikely(ib_ret)) {
878*4882a593Smuzhiyun iser_err("ib_post_recv failed ret=%d\n", ib_ret);
879*4882a593Smuzhiyun ib_conn->post_recv_buf_count -= count;
880*4882a593Smuzhiyun } else
881*4882a593Smuzhiyun iser_conn->rx_desc_head = my_rx_head;
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun return ib_ret;
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun /**
888*4882a593Smuzhiyun * iser_post_send - Initiate a Send DTO operation
889*4882a593Smuzhiyun * @ib_conn: connection RDMA resources
890*4882a593Smuzhiyun * @tx_desc: iSER TX descriptor
891*4882a593Smuzhiyun * @signal: true to send work request as SIGNALED
892*4882a593Smuzhiyun *
893*4882a593Smuzhiyun * Return: 0 on success, -1 on failure
894*4882a593Smuzhiyun */
iser_post_send(struct ib_conn * ib_conn,struct iser_tx_desc * tx_desc,bool signal)895*4882a593Smuzhiyun int iser_post_send(struct ib_conn *ib_conn, struct iser_tx_desc *tx_desc,
896*4882a593Smuzhiyun bool signal)
897*4882a593Smuzhiyun {
898*4882a593Smuzhiyun struct ib_send_wr *wr = &tx_desc->send_wr;
899*4882a593Smuzhiyun struct ib_send_wr *first_wr;
900*4882a593Smuzhiyun int ib_ret;
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun ib_dma_sync_single_for_device(ib_conn->device->ib_device,
903*4882a593Smuzhiyun tx_desc->dma_addr, ISER_HEADERS_LEN,
904*4882a593Smuzhiyun DMA_TO_DEVICE);
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun wr->next = NULL;
907*4882a593Smuzhiyun wr->wr_cqe = &tx_desc->cqe;
908*4882a593Smuzhiyun wr->sg_list = tx_desc->tx_sg;
909*4882a593Smuzhiyun wr->num_sge = tx_desc->num_sge;
910*4882a593Smuzhiyun wr->opcode = IB_WR_SEND;
911*4882a593Smuzhiyun wr->send_flags = signal ? IB_SEND_SIGNALED : 0;
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun if (tx_desc->inv_wr.next)
914*4882a593Smuzhiyun first_wr = &tx_desc->inv_wr;
915*4882a593Smuzhiyun else if (tx_desc->reg_wr.wr.next)
916*4882a593Smuzhiyun first_wr = &tx_desc->reg_wr.wr;
917*4882a593Smuzhiyun else
918*4882a593Smuzhiyun first_wr = wr;
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun ib_ret = ib_post_send(ib_conn->qp, first_wr, NULL);
921*4882a593Smuzhiyun if (unlikely(ib_ret))
922*4882a593Smuzhiyun iser_err("ib_post_send failed, ret:%d opcode:%d\n",
923*4882a593Smuzhiyun ib_ret, wr->opcode);
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun return ib_ret;
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
iser_check_task_pi_status(struct iscsi_iser_task * iser_task,enum iser_data_dir cmd_dir,sector_t * sector)928*4882a593Smuzhiyun u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
929*4882a593Smuzhiyun enum iser_data_dir cmd_dir, sector_t *sector)
930*4882a593Smuzhiyun {
931*4882a593Smuzhiyun struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
932*4882a593Smuzhiyun struct iser_fr_desc *desc = reg->mem_h;
933*4882a593Smuzhiyun unsigned long sector_size = iser_task->sc->device->sector_size;
934*4882a593Smuzhiyun struct ib_mr_status mr_status;
935*4882a593Smuzhiyun int ret;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun if (desc && desc->sig_protected) {
938*4882a593Smuzhiyun desc->sig_protected = false;
939*4882a593Smuzhiyun ret = ib_check_mr_status(desc->rsc.sig_mr,
940*4882a593Smuzhiyun IB_MR_CHECK_SIG_STATUS, &mr_status);
941*4882a593Smuzhiyun if (ret) {
942*4882a593Smuzhiyun iser_err("ib_check_mr_status failed, ret %d\n", ret);
943*4882a593Smuzhiyun /* Not a lot we can do, return ambiguous guard error */
944*4882a593Smuzhiyun *sector = 0;
945*4882a593Smuzhiyun return 0x1;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) {
949*4882a593Smuzhiyun sector_t sector_off = mr_status.sig_err.sig_err_offset;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun sector_div(sector_off, sector_size + 8);
952*4882a593Smuzhiyun *sector = scsi_get_lba(iser_task->sc) + sector_off;
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun iser_err("PI error found type %d at sector %llx "
955*4882a593Smuzhiyun "expected %x vs actual %x\n",
956*4882a593Smuzhiyun mr_status.sig_err.err_type,
957*4882a593Smuzhiyun (unsigned long long)*sector,
958*4882a593Smuzhiyun mr_status.sig_err.expected,
959*4882a593Smuzhiyun mr_status.sig_err.actual);
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun switch (mr_status.sig_err.err_type) {
962*4882a593Smuzhiyun case IB_SIG_BAD_GUARD:
963*4882a593Smuzhiyun return 0x1;
964*4882a593Smuzhiyun case IB_SIG_BAD_REFTAG:
965*4882a593Smuzhiyun return 0x3;
966*4882a593Smuzhiyun case IB_SIG_BAD_APPTAG:
967*4882a593Smuzhiyun return 0x2;
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun return 0;
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
iser_err_comp(struct ib_wc * wc,const char * type)975*4882a593Smuzhiyun void iser_err_comp(struct ib_wc *wc, const char *type)
976*4882a593Smuzhiyun {
977*4882a593Smuzhiyun if (wc->status != IB_WC_WR_FLUSH_ERR) {
978*4882a593Smuzhiyun struct iser_conn *iser_conn = to_iser_conn(wc->qp->qp_context);
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun iser_err("%s failure: %s (%d) vend_err %#x\n", type,
981*4882a593Smuzhiyun ib_wc_status_msg(wc->status), wc->status,
982*4882a593Smuzhiyun wc->vendor_err);
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun if (iser_conn->iscsi_conn)
985*4882a593Smuzhiyun iscsi_conn_failure(iser_conn->iscsi_conn,
986*4882a593Smuzhiyun ISCSI_ERR_CONN_FAILED);
987*4882a593Smuzhiyun } else {
988*4882a593Smuzhiyun iser_dbg("%s failure: %s (%d)\n", type,
989*4882a593Smuzhiyun ib_wc_status_msg(wc->status), wc->status);
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun }
992