blob: 060e6a84f18fb375735fc1f68cb24dc7ecd3f317 [file] [log] [blame]
Roland Dreieraef9ec32005-11-02 14:07:13 -08001/*
2 * Copyright (c) 2005 Cisco Systems. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
Roland Dreieraef9ec32005-11-02 14:07:13 -080031 */
32
Roland Dreieraef9ec32005-11-02 14:07:13 -080033#include <linux/module.h>
34#include <linux/init.h>
35#include <linux/slab.h>
36#include <linux/err.h>
37#include <linux/string.h>
38#include <linux/parser.h>
39#include <linux/random.h>
Tim Schmielaude259682006-01-08 01:02:05 -080040#include <linux/jiffies.h>
Roland Dreieraef9ec32005-11-02 14:07:13 -080041
42#include <asm/atomic.h>
43
44#include <scsi/scsi.h>
45#include <scsi/scsi_device.h>
46#include <scsi/scsi_dbg.h>
47#include <scsi/srp.h>
FUJITA Tomonori32368222007-06-27 16:33:12 +090048#include <scsi/scsi_transport_srp.h>
Roland Dreieraef9ec32005-11-02 14:07:13 -080049
Roland Dreieraef9ec32005-11-02 14:07:13 -080050#include "ib_srp.h"
51
52#define DRV_NAME "ib_srp"
53#define PFX DRV_NAME ": "
54#define DRV_VERSION "0.2"
55#define DRV_RELDATE "November 1, 2005"
56
57MODULE_AUTHOR("Roland Dreier");
58MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator "
59 "v" DRV_VERSION " (" DRV_RELDATE ")");
60MODULE_LICENSE("Dual BSD/GPL");
61
Vu Pham74b0a152006-06-17 20:37:32 -070062static int srp_sg_tablesize = SRP_DEF_SG_TABLESIZE;
63static int srp_max_iu_len;
64
65module_param(srp_sg_tablesize, int, 0444);
66MODULE_PARM_DESC(srp_sg_tablesize,
David Dillow1e89a192008-04-16 21:01:12 -070067 "Max number of gather/scatter entries per I/O (default is 12, max 255)");
Vu Pham74b0a152006-06-17 20:37:32 -070068
Roland Dreieraef9ec32005-11-02 14:07:13 -080069static int topspin_workarounds = 1;
70
71module_param(topspin_workarounds, int, 0444);
72MODULE_PARM_DESC(topspin_workarounds,
73 "Enable workarounds for Topspin/Cisco SRP target bugs if != 0");
74
Roland Dreieraef9ec32005-11-02 14:07:13 -080075static void srp_add_one(struct ib_device *device);
76static void srp_remove_one(struct ib_device *device);
Bart Van Assche9c03dc92010-02-02 19:23:54 +000077static void srp_recv_completion(struct ib_cq *cq, void *target_ptr);
78static void srp_send_completion(struct ib_cq *cq, void *target_ptr);
Roland Dreieraef9ec32005-11-02 14:07:13 -080079static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
80
FUJITA Tomonori32368222007-06-27 16:33:12 +090081static struct scsi_transport_template *ib_srp_transport_template;
82
Roland Dreieraef9ec32005-11-02 14:07:13 -080083static struct ib_client srp_client = {
84 .name = "srp",
85 .add = srp_add_one,
86 .remove = srp_remove_one
87};
88
Michael S. Tsirkinc1a0b232006-08-21 16:40:12 -070089static struct ib_sa_client srp_sa_client;
90
Roland Dreieraef9ec32005-11-02 14:07:13 -080091static inline struct srp_target_port *host_to_target(struct Scsi_Host *host)
92{
93 return (struct srp_target_port *) host->hostdata;
94}
95
96static const char *srp_target_info(struct Scsi_Host *host)
97{
98 return host_to_target(host)->target_name;
99}
100
Roland Dreier5d7cbfd2007-08-03 10:45:18 -0700101static int srp_target_is_topspin(struct srp_target_port *target)
102{
103 static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
Raghava Kondapalli3d1ff482007-08-03 10:45:18 -0700104 static const u8 cisco_oui[3] = { 0x00, 0x1b, 0x0d };
Roland Dreier5d7cbfd2007-08-03 10:45:18 -0700105
106 return topspin_workarounds &&
Raghava Kondapalli3d1ff482007-08-03 10:45:18 -0700107 (!memcmp(&target->ioc_guid, topspin_oui, sizeof topspin_oui) ||
108 !memcmp(&target->ioc_guid, cisco_oui, sizeof cisco_oui));
Roland Dreier5d7cbfd2007-08-03 10:45:18 -0700109}
110
Roland Dreieraef9ec32005-11-02 14:07:13 -0800111static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
112 gfp_t gfp_mask,
113 enum dma_data_direction direction)
114{
115 struct srp_iu *iu;
116
117 iu = kmalloc(sizeof *iu, gfp_mask);
118 if (!iu)
119 goto out;
120
121 iu->buf = kzalloc(size, gfp_mask);
122 if (!iu->buf)
123 goto out_free_iu;
124
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100125 iu->dma = ib_dma_map_single(host->srp_dev->dev, iu->buf, size,
126 direction);
127 if (ib_dma_mapping_error(host->srp_dev->dev, iu->dma))
Roland Dreieraef9ec32005-11-02 14:07:13 -0800128 goto out_free_buf;
129
130 iu->size = size;
131 iu->direction = direction;
132
133 return iu;
134
135out_free_buf:
136 kfree(iu->buf);
137out_free_iu:
138 kfree(iu);
139out:
140 return NULL;
141}
142
143static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
144{
145 if (!iu)
146 return;
147
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100148 ib_dma_unmap_single(host->srp_dev->dev, iu->dma, iu->size,
149 iu->direction);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800150 kfree(iu->buf);
151 kfree(iu);
152}
153
154static void srp_qp_event(struct ib_event *event, void *context)
155{
156 printk(KERN_ERR PFX "QP event %d\n", event->event);
157}
158
159static int srp_init_qp(struct srp_target_port *target,
160 struct ib_qp *qp)
161{
162 struct ib_qp_attr *attr;
163 int ret;
164
165 attr = kmalloc(sizeof *attr, GFP_KERNEL);
166 if (!attr)
167 return -ENOMEM;
168
Roland Dreier969a60f2008-07-14 23:48:43 -0700169 ret = ib_find_pkey(target->srp_host->srp_dev->dev,
170 target->srp_host->port,
171 be16_to_cpu(target->path.pkey),
172 &attr->pkey_index);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800173 if (ret)
174 goto out;
175
176 attr->qp_state = IB_QPS_INIT;
177 attr->qp_access_flags = (IB_ACCESS_REMOTE_READ |
178 IB_ACCESS_REMOTE_WRITE);
179 attr->port_num = target->srp_host->port;
180
181 ret = ib_modify_qp(qp, attr,
182 IB_QP_STATE |
183 IB_QP_PKEY_INDEX |
184 IB_QP_ACCESS_FLAGS |
185 IB_QP_PORT);
186
187out:
188 kfree(attr);
189 return ret;
190}
191
David Dillow9fe4bcf2008-01-08 17:08:52 -0500192static int srp_new_cm_id(struct srp_target_port *target)
193{
194 struct ib_cm_id *new_cm_id;
195
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100196 new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
David Dillow9fe4bcf2008-01-08 17:08:52 -0500197 srp_cm_handler, target);
198 if (IS_ERR(new_cm_id))
199 return PTR_ERR(new_cm_id);
200
201 if (target->cm_id)
202 ib_destroy_cm_id(target->cm_id);
203 target->cm_id = new_cm_id;
204
205 return 0;
206}
207
Roland Dreieraef9ec32005-11-02 14:07:13 -0800208static int srp_create_target_ib(struct srp_target_port *target)
209{
210 struct ib_qp_init_attr *init_attr;
211 int ret;
212
213 init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
214 if (!init_attr)
215 return -ENOMEM;
216
Bart Van Assche9c03dc92010-02-02 19:23:54 +0000217 target->recv_cq = ib_create_cq(target->srp_host->srp_dev->dev,
218 srp_recv_completion, NULL, target, SRP_RQ_SIZE, 0);
219 if (IS_ERR(target->recv_cq)) {
220 ret = PTR_ERR(target->recv_cq);
Roland Dreierda9d2f02010-02-24 15:07:59 -0800221 goto err;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800222 }
223
Bart Van Assche9c03dc92010-02-02 19:23:54 +0000224 target->send_cq = ib_create_cq(target->srp_host->srp_dev->dev,
225 srp_send_completion, NULL, target, SRP_SQ_SIZE, 0);
226 if (IS_ERR(target->send_cq)) {
227 ret = PTR_ERR(target->send_cq);
Roland Dreierda9d2f02010-02-24 15:07:59 -0800228 goto err_recv_cq;
Bart Van Assche9c03dc92010-02-02 19:23:54 +0000229 }
230
231 ib_req_notify_cq(target->recv_cq, IB_CQ_NEXT_COMP);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800232
233 init_attr->event_handler = srp_qp_event;
234 init_attr->cap.max_send_wr = SRP_SQ_SIZE;
235 init_attr->cap.max_recv_wr = SRP_RQ_SIZE;
236 init_attr->cap.max_recv_sge = 1;
237 init_attr->cap.max_send_sge = 1;
238 init_attr->sq_sig_type = IB_SIGNAL_ALL_WR;
239 init_attr->qp_type = IB_QPT_RC;
Bart Van Assche9c03dc92010-02-02 19:23:54 +0000240 init_attr->send_cq = target->send_cq;
241 init_attr->recv_cq = target->recv_cq;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800242
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100243 target->qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800244 if (IS_ERR(target->qp)) {
245 ret = PTR_ERR(target->qp);
Roland Dreierda9d2f02010-02-24 15:07:59 -0800246 goto err_send_cq;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800247 }
248
249 ret = srp_init_qp(target, target->qp);
Roland Dreierda9d2f02010-02-24 15:07:59 -0800250 if (ret)
251 goto err_qp;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800252
Roland Dreierda9d2f02010-02-24 15:07:59 -0800253 kfree(init_attr);
254 return 0;
255
256err_qp:
257 ib_destroy_qp(target->qp);
258
259err_send_cq:
260 ib_destroy_cq(target->send_cq);
261
262err_recv_cq:
263 ib_destroy_cq(target->recv_cq);
264
265err:
Roland Dreieraef9ec32005-11-02 14:07:13 -0800266 kfree(init_attr);
267 return ret;
268}
269
270static void srp_free_target_ib(struct srp_target_port *target)
271{
272 int i;
273
274 ib_destroy_qp(target->qp);
Bart Van Assche9c03dc92010-02-02 19:23:54 +0000275 ib_destroy_cq(target->send_cq);
276 ib_destroy_cq(target->recv_cq);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800277
278 for (i = 0; i < SRP_RQ_SIZE; ++i)
279 srp_free_iu(target->srp_host, target->rx_ring[i]);
Bart Van Asschedd5e6e32010-08-30 19:27:20 +0000280 for (i = 0; i < SRP_SQ_SIZE; ++i)
Roland Dreieraef9ec32005-11-02 14:07:13 -0800281 srp_free_iu(target->srp_host, target->tx_ring[i]);
282}
283
284static void srp_path_rec_completion(int status,
285 struct ib_sa_path_rec *pathrec,
286 void *target_ptr)
287{
288 struct srp_target_port *target = target_ptr;
289
290 target->status = status;
291 if (status)
David Dillow7aa54bd2008-01-07 18:23:41 -0500292 shost_printk(KERN_ERR, target->scsi_host,
293 PFX "Got failed path rec status %d\n", status);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800294 else
295 target->path = *pathrec;
296 complete(&target->done);
297}
298
299static int srp_lookup_path(struct srp_target_port *target)
300{
301 target->path.numb_path = 1;
302
303 init_completion(&target->done);
304
Michael S. Tsirkinc1a0b232006-08-21 16:40:12 -0700305 target->path_query_id = ib_sa_path_rec_get(&srp_sa_client,
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100306 target->srp_host->srp_dev->dev,
Roland Dreieraef9ec32005-11-02 14:07:13 -0800307 target->srp_host->port,
308 &target->path,
Sean Hefty247e0202007-08-08 15:51:18 -0700309 IB_SA_PATH_REC_SERVICE_ID |
Roland Dreieraef9ec32005-11-02 14:07:13 -0800310 IB_SA_PATH_REC_DGID |
311 IB_SA_PATH_REC_SGID |
312 IB_SA_PATH_REC_NUMB_PATH |
313 IB_SA_PATH_REC_PKEY,
314 SRP_PATH_REC_TIMEOUT_MS,
315 GFP_KERNEL,
316 srp_path_rec_completion,
317 target, &target->path_query);
318 if (target->path_query_id < 0)
319 return target->path_query_id;
320
321 wait_for_completion(&target->done);
322
323 if (target->status < 0)
David Dillow7aa54bd2008-01-07 18:23:41 -0500324 shost_printk(KERN_WARNING, target->scsi_host,
325 PFX "Path record query failed\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -0800326
327 return target->status;
328}
329
330static int srp_send_req(struct srp_target_port *target)
331{
332 struct {
333 struct ib_cm_req_param param;
334 struct srp_login_req priv;
335 } *req = NULL;
336 int status;
337
338 req = kzalloc(sizeof *req, GFP_KERNEL);
339 if (!req)
340 return -ENOMEM;
341
342 req->param.primary_path = &target->path;
343 req->param.alternate_path = NULL;
344 req->param.service_id = target->service_id;
345 req->param.qp_num = target->qp->qp_num;
346 req->param.qp_type = target->qp->qp_type;
347 req->param.private_data = &req->priv;
348 req->param.private_data_len = sizeof req->priv;
349 req->param.flow_control = 1;
350
351 get_random_bytes(&req->param.starting_psn, 4);
352 req->param.starting_psn &= 0xffffff;
353
354 /*
355 * Pick some arbitrary defaults here; we could make these
356 * module parameters if anyone cared about setting them.
357 */
358 req->param.responder_resources = 4;
359 req->param.remote_cm_response_timeout = 20;
360 req->param.local_cm_response_timeout = 20;
361 req->param.retry_count = 7;
362 req->param.rnr_retry_count = 7;
363 req->param.max_cm_retries = 15;
364
365 req->priv.opcode = SRP_LOGIN_REQ;
366 req->priv.tag = 0;
Vu Pham74b0a152006-06-17 20:37:32 -0700367 req->priv.req_it_iu_len = cpu_to_be32(srp_max_iu_len);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800368 req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
369 SRP_BUF_FORMAT_INDIRECT);
Ramachandra K0c0450db2006-06-17 20:37:38 -0700370 /*
Roland Dreier3cd96562006-09-22 15:22:46 -0700371 * In the published SRP specification (draft rev. 16a), the
Ramachandra K0c0450db2006-06-17 20:37:38 -0700372 * port identifier format is 8 bytes of ID extension followed
373 * by 8 bytes of GUID. Older drafts put the two halves in the
374 * opposite order, so that the GUID comes first.
375 *
376 * Targets conforming to these obsolete drafts can be
377 * recognized by the I/O Class they report.
378 */
379 if (target->io_class == SRP_REV10_IB_IO_CLASS) {
380 memcpy(req->priv.initiator_port_id,
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +0200381 &target->path.sgid.global.interface_id, 8);
Ramachandra K0c0450db2006-06-17 20:37:38 -0700382 memcpy(req->priv.initiator_port_id + 8,
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +0200383 &target->initiator_ext, 8);
Ramachandra K0c0450db2006-06-17 20:37:38 -0700384 memcpy(req->priv.target_port_id, &target->ioc_guid, 8);
385 memcpy(req->priv.target_port_id + 8, &target->id_ext, 8);
386 } else {
387 memcpy(req->priv.initiator_port_id,
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +0200388 &target->initiator_ext, 8);
389 memcpy(req->priv.initiator_port_id + 8,
390 &target->path.sgid.global.interface_id, 8);
Ramachandra K0c0450db2006-06-17 20:37:38 -0700391 memcpy(req->priv.target_port_id, &target->id_ext, 8);
392 memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
393 }
394
Roland Dreieraef9ec32005-11-02 14:07:13 -0800395 /*
396 * Topspin/Cisco SRP targets will reject our login unless we
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +0200397 * zero out the first 8 bytes of our initiator port ID and set
398 * the second 8 bytes to the local node GUID.
Roland Dreieraef9ec32005-11-02 14:07:13 -0800399 */
Roland Dreier5d7cbfd2007-08-03 10:45:18 -0700400 if (srp_target_is_topspin(target)) {
David Dillow7aa54bd2008-01-07 18:23:41 -0500401 shost_printk(KERN_DEBUG, target->scsi_host,
402 PFX "Topspin/Cisco initiator port ID workaround "
403 "activated for target GUID %016llx\n",
404 (unsigned long long) be64_to_cpu(target->ioc_guid));
Roland Dreieraef9ec32005-11-02 14:07:13 -0800405 memset(req->priv.initiator_port_id, 0, 8);
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +0200406 memcpy(req->priv.initiator_port_id + 8,
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100407 &target->srp_host->srp_dev->dev->node_guid, 8);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800408 }
Roland Dreieraef9ec32005-11-02 14:07:13 -0800409
410 status = ib_send_cm_req(target->cm_id, &req->param);
411
412 kfree(req);
413
414 return status;
415}
416
417static void srp_disconnect_target(struct srp_target_port *target)
418{
419 /* XXX should send SRP_I_LOGOUT request */
420
421 init_completion(&target->done);
Roland Dreiere6581052006-05-17 09:13:21 -0700422 if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
David Dillow7aa54bd2008-01-07 18:23:41 -0500423 shost_printk(KERN_DEBUG, target->scsi_host,
424 PFX "Sending CM DREQ failed\n");
Roland Dreiere6581052006-05-17 09:13:21 -0700425 return;
426 }
Roland Dreieraef9ec32005-11-02 14:07:13 -0800427 wait_for_completion(&target->done);
428}
429
Bart Van Assche9709f0e2010-11-26 13:13:06 -0500430static bool srp_change_state(struct srp_target_port *target,
431 enum srp_target_state old,
432 enum srp_target_state new)
433{
434 bool changed = false;
435
Bart Van Asschee9684672010-11-26 15:08:38 -0500436 spin_lock_irq(&target->lock);
Bart Van Assche9709f0e2010-11-26 13:13:06 -0500437 if (target->state == old) {
438 target->state = new;
439 changed = true;
440 }
Bart Van Asschee9684672010-11-26 15:08:38 -0500441 spin_unlock_irq(&target->lock);
Bart Van Assche9709f0e2010-11-26 13:13:06 -0500442 return changed;
443}
444
David Howellsc4028952006-11-22 14:57:56 +0000445static void srp_remove_work(struct work_struct *work)
Roland Dreieraef9ec32005-11-02 14:07:13 -0800446{
David Howellsc4028952006-11-22 14:57:56 +0000447 struct srp_target_port *target =
448 container_of(work, struct srp_target_port, work);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800449
Bart Van Assche9709f0e2010-11-26 13:13:06 -0500450 if (!srp_change_state(target, SRP_TARGET_DEAD, SRP_TARGET_REMOVED))
Roland Dreieraef9ec32005-11-02 14:07:13 -0800451 return;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800452
Matthew Wilcoxb3589fd2006-06-17 20:37:30 -0700453 spin_lock(&target->srp_host->target_lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800454 list_del(&target->list);
Matthew Wilcoxb3589fd2006-06-17 20:37:30 -0700455 spin_unlock(&target->srp_host->target_lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800456
FUJITA Tomonori32368222007-06-27 16:33:12 +0900457 srp_remove_host(target->scsi_host);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800458 scsi_remove_host(target->scsi_host);
459 ib_destroy_cm_id(target->cm_id);
460 srp_free_target_ib(target);
461 scsi_host_put(target->scsi_host);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800462}
463
464static int srp_connect_target(struct srp_target_port *target)
465{
David Dillow9fe4bcf2008-01-08 17:08:52 -0500466 int retries = 3;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800467 int ret;
468
469 ret = srp_lookup_path(target);
470 if (ret)
471 return ret;
472
473 while (1) {
474 init_completion(&target->done);
475 ret = srp_send_req(target);
476 if (ret)
477 return ret;
478 wait_for_completion(&target->done);
479
480 /*
481 * The CM event handling code will set status to
482 * SRP_PORT_REDIRECT if we get a port redirect REJ
483 * back, or SRP_DLID_REDIRECT if we get a lid/qp
484 * redirect REJ back.
485 */
486 switch (target->status) {
487 case 0:
488 return 0;
489
490 case SRP_PORT_REDIRECT:
491 ret = srp_lookup_path(target);
492 if (ret)
493 return ret;
494 break;
495
496 case SRP_DLID_REDIRECT:
497 break;
498
David Dillow9fe4bcf2008-01-08 17:08:52 -0500499 case SRP_STALE_CONN:
500 /* Our current CM id was stale, and is now in timewait.
501 * Try to reconnect with a new one.
502 */
503 if (!retries-- || srp_new_cm_id(target)) {
504 shost_printk(KERN_ERR, target->scsi_host, PFX
505 "giving up on stale connection\n");
506 target->status = -ECONNRESET;
507 return target->status;
508 }
509
510 shost_printk(KERN_ERR, target->scsi_host, PFX
511 "retrying stale connection\n");
512 break;
513
Roland Dreieraef9ec32005-11-02 14:07:13 -0800514 default:
515 return target->status;
516 }
517 }
518}
519
Roland Dreierd945e1d2006-05-09 10:50:28 -0700520static void srp_unmap_data(struct scsi_cmnd *scmnd,
521 struct srp_target_port *target,
522 struct srp_request *req)
523{
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900524 if (!scsi_sglist(scmnd) ||
Roland Dreierd945e1d2006-05-09 10:50:28 -0700525 (scmnd->sc_data_direction != DMA_TO_DEVICE &&
526 scmnd->sc_data_direction != DMA_FROM_DEVICE))
527 return;
528
Roland Dreierf5358a12006-06-17 20:37:29 -0700529 if (req->fmr) {
530 ib_fmr_pool_unmap(req->fmr);
531 req->fmr = NULL;
532 }
533
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100534 ib_dma_unmap_sg(target->srp_host->srp_dev->dev, scsi_sglist(scmnd),
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900535 scsi_sg_count(scmnd), scmnd->sc_data_direction);
Roland Dreierd945e1d2006-05-09 10:50:28 -0700536}
537
Bart Van Assche94a91742010-11-26 14:50:09 -0500538static void srp_remove_req(struct srp_target_port *target,
539 struct srp_request *req, s32 req_lim_delta)
Ishai Rabinovitz526b4ca2006-06-17 20:37:38 -0700540{
Bart Van Assche94a91742010-11-26 14:50:09 -0500541 unsigned long flags;
542
Ishai Rabinovitz526b4ca2006-06-17 20:37:38 -0700543 srp_unmap_data(req->scmnd, target, req);
Bart Van Asschee9684672010-11-26 15:08:38 -0500544 spin_lock_irqsave(&target->lock, flags);
Bart Van Assche94a91742010-11-26 14:50:09 -0500545 target->req_lim += req_lim_delta;
David Dillowf8b6e312010-11-26 13:02:21 -0500546 req->scmnd = NULL;
Bart Van Assche536ae142010-11-26 13:58:27 -0500547 list_add_tail(&req->list, &target->free_reqs);
Bart Van Asschee9684672010-11-26 15:08:38 -0500548 spin_unlock_irqrestore(&target->lock, flags);
Ishai Rabinovitz526b4ca2006-06-17 20:37:38 -0700549}
550
551static void srp_reset_req(struct srp_target_port *target, struct srp_request *req)
552{
553 req->scmnd->result = DID_RESET << 16;
554 req->scmnd->scsi_done(req->scmnd);
Bart Van Assche94a91742010-11-26 14:50:09 -0500555 srp_remove_req(target, req, 0);
Ishai Rabinovitz526b4ca2006-06-17 20:37:38 -0700556}
557
Roland Dreieraef9ec32005-11-02 14:07:13 -0800558static int srp_reconnect_target(struct srp_target_port *target)
559{
Roland Dreieraef9ec32005-11-02 14:07:13 -0800560 struct ib_qp_attr qp_attr;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800561 struct ib_wc wc;
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500562 int i, ret;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800563
Bart Van Assche9709f0e2010-11-26 13:13:06 -0500564 if (!srp_change_state(target, SRP_TARGET_LIVE, SRP_TARGET_CONNECTING))
Roland Dreieraef9ec32005-11-02 14:07:13 -0800565 return -EAGAIN;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800566
567 srp_disconnect_target(target);
568 /*
569 * Now get a new local CM ID so that we avoid confusing the
570 * target in case things are really fouled up.
571 */
David Dillow9fe4bcf2008-01-08 17:08:52 -0500572 ret = srp_new_cm_id(target);
573 if (ret)
Roland Dreieraef9ec32005-11-02 14:07:13 -0800574 goto err;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800575
576 qp_attr.qp_state = IB_QPS_RESET;
577 ret = ib_modify_qp(target->qp, &qp_attr, IB_QP_STATE);
578 if (ret)
579 goto err;
580
581 ret = srp_init_qp(target, target->qp);
582 if (ret)
583 goto err;
584
Bart Van Assche9c03dc92010-02-02 19:23:54 +0000585 while (ib_poll_cq(target->recv_cq, 1, &wc) > 0)
586 ; /* nothing */
587 while (ib_poll_cq(target->send_cq, 1, &wc) > 0)
Roland Dreieraef9ec32005-11-02 14:07:13 -0800588 ; /* nothing */
589
Bart Van Assche536ae142010-11-26 13:58:27 -0500590 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
591 struct srp_request *req = &target->req_ring[i];
592 if (req->scmnd)
593 srp_reset_req(target, req);
594 }
Roland Dreieraef9ec32005-11-02 14:07:13 -0800595
Bart Van Assche536ae142010-11-26 13:58:27 -0500596 INIT_LIST_HEAD(&target->free_tx);
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500597 for (i = 0; i < SRP_SQ_SIZE; ++i)
Bart Van Assche536ae142010-11-26 13:58:27 -0500598 list_add(&target->tx_ring[i]->list, &target->free_tx);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800599
Ishai Rabinovitz1033ff62007-01-16 17:26:22 +0200600 target->qp_in_error = 0;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800601 ret = srp_connect_target(target);
602 if (ret)
603 goto err;
604
Bart Van Assche9709f0e2010-11-26 13:13:06 -0500605 if (!srp_change_state(target, SRP_TARGET_CONNECTING, SRP_TARGET_LIVE))
Roland Dreieraef9ec32005-11-02 14:07:13 -0800606 ret = -EAGAIN;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800607
608 return ret;
609
610err:
David Dillow7aa54bd2008-01-07 18:23:41 -0500611 shost_printk(KERN_ERR, target->scsi_host,
612 PFX "reconnect failed (%d), removing target port.\n", ret);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800613
614 /*
615 * We couldn't reconnect, so kill our target port off.
Bart Van Assche9709f0e2010-11-26 13:13:06 -0500616 * However, we have to defer the real removal because we
617 * are in the context of the SCSI error handler now, which
618 * will deadlock if we call scsi_remove_host().
619 *
620 * Schedule our work inside the lock to avoid a race with
621 * the flush_scheduled_work() in srp_remove_one().
Roland Dreieraef9ec32005-11-02 14:07:13 -0800622 */
Bart Van Asschee9684672010-11-26 15:08:38 -0500623 spin_lock_irq(&target->lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800624 if (target->state == SRP_TARGET_CONNECTING) {
625 target->state = SRP_TARGET_DEAD;
David Howellsc4028952006-11-22 14:57:56 +0000626 INIT_WORK(&target->work, srp_remove_work);
Tejun Heof0626712010-10-19 15:24:36 +0000627 queue_work(ib_wq, &target->work);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800628 }
Bart Van Asschee9684672010-11-26 15:08:38 -0500629 spin_unlock_irq(&target->lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800630
631 return ret;
632}
633
Ishai Rabinovitz559ce8f2006-08-03 10:35:43 -0700634static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
Roland Dreierf5358a12006-06-17 20:37:29 -0700635 int sg_cnt, struct srp_request *req,
636 struct srp_direct_buf *buf)
637{
638 u64 io_addr = 0;
639 u64 *dma_pages;
640 u32 len;
641 int page_cnt;
642 int i, j;
643 int ret;
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100644 struct srp_device *dev = target->srp_host->srp_dev;
Ralph Campbell85507bc2006-12-12 14:30:55 -0800645 struct ib_device *ibdev = dev->dev;
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900646 struct scatterlist *sg;
Roland Dreierf5358a12006-06-17 20:37:29 -0700647
648 if (!dev->fmr_pool)
649 return -ENODEV;
650
David Dillow8c4037b2011-01-14 17:02:23 -0500651 if (ib_sg_dma_address(ibdev, &scat[0]) & ~dev->fmr_page_mask)
Ishai Rabinovitz559ce8f2006-08-03 10:35:43 -0700652 return -EINVAL;
653
Roland Dreierf5358a12006-06-17 20:37:29 -0700654 len = page_cnt = 0;
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900655 scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
656 unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
Ralph Campbell85507bc2006-12-12 14:30:55 -0800657
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900658 if (ib_sg_dma_address(ibdev, sg) & ~dev->fmr_page_mask) {
Roland Dreierf5358a12006-06-17 20:37:29 -0700659 if (i > 0)
660 return -EINVAL;
661 else
662 ++page_cnt;
663 }
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900664 if ((ib_sg_dma_address(ibdev, sg) + dma_len) &
Roland Dreierf5358a12006-06-17 20:37:29 -0700665 ~dev->fmr_page_mask) {
666 if (i < sg_cnt - 1)
667 return -EINVAL;
668 else
669 ++page_cnt;
670 }
671
Ralph Campbell85507bc2006-12-12 14:30:55 -0800672 len += dma_len;
Roland Dreierf5358a12006-06-17 20:37:29 -0700673 }
674
675 page_cnt += len >> dev->fmr_page_shift;
676 if (page_cnt > SRP_FMR_SIZE)
677 return -ENOMEM;
678
679 dma_pages = kmalloc(sizeof (u64) * page_cnt, GFP_ATOMIC);
680 if (!dma_pages)
681 return -ENOMEM;
682
683 page_cnt = 0;
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900684 scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
685 unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
Ralph Campbell85507bc2006-12-12 14:30:55 -0800686
687 for (j = 0; j < dma_len; j += dev->fmr_page_size)
Roland Dreierf5358a12006-06-17 20:37:29 -0700688 dma_pages[page_cnt++] =
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900689 (ib_sg_dma_address(ibdev, sg) &
Ralph Campbell85507bc2006-12-12 14:30:55 -0800690 dev->fmr_page_mask) + j;
691 }
Roland Dreierf5358a12006-06-17 20:37:29 -0700692
693 req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool,
Michael S. Tsirkinadfaa882006-07-14 00:23:55 -0700694 dma_pages, page_cnt, io_addr);
Roland Dreierf5358a12006-06-17 20:37:29 -0700695 if (IS_ERR(req->fmr)) {
696 ret = PTR_ERR(req->fmr);
Vu Pham6583eb32006-07-14 00:23:53 -0700697 req->fmr = NULL;
Roland Dreierf5358a12006-06-17 20:37:29 -0700698 goto out;
699 }
700
Ralph Campbell85507bc2006-12-12 14:30:55 -0800701 buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, &scat[0]) &
702 ~dev->fmr_page_mask);
Roland Dreierf5358a12006-06-17 20:37:29 -0700703 buf->key = cpu_to_be32(req->fmr->fmr->rkey);
704 buf->len = cpu_to_be32(len);
705
706 ret = 0;
707
708out:
709 kfree(dma_pages);
710
711 return ret;
712}
713
Roland Dreieraef9ec32005-11-02 14:07:13 -0800714static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
715 struct srp_request *req)
716{
Roland Dreiercf368712006-03-24 15:47:26 -0800717 struct scatterlist *scat;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800718 struct srp_cmd *cmd = req->cmd->buf;
Roland Dreiercf368712006-03-24 15:47:26 -0800719 int len, nents, count;
Roland Dreierf5358a12006-06-17 20:37:29 -0700720 u8 fmt = SRP_DATA_DESC_DIRECT;
Ralph Campbell85507bc2006-12-12 14:30:55 -0800721 struct srp_device *dev;
722 struct ib_device *ibdev;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800723
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900724 if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
Roland Dreieraef9ec32005-11-02 14:07:13 -0800725 return sizeof (struct srp_cmd);
726
727 if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
728 scmnd->sc_data_direction != DMA_TO_DEVICE) {
David Dillow7aa54bd2008-01-07 18:23:41 -0500729 shost_printk(KERN_WARNING, target->scsi_host,
730 PFX "Unhandled data direction %d\n",
731 scmnd->sc_data_direction);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800732 return -EINVAL;
733 }
734
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900735 nents = scsi_sg_count(scmnd);
736 scat = scsi_sglist(scmnd);
Roland Dreiercf368712006-03-24 15:47:26 -0800737
Greg Kroah-Hartman05321932008-03-06 00:13:36 +0100738 dev = target->srp_host->srp_dev;
Ralph Campbell85507bc2006-12-12 14:30:55 -0800739 ibdev = dev->dev;
740
741 count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
Roland Dreierf5358a12006-06-17 20:37:29 -0700742
743 fmt = SRP_DATA_DESC_DIRECT;
744 len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf);
Roland Dreiercf368712006-03-24 15:47:26 -0800745
746 if (count == 1) {
Roland Dreierf5358a12006-06-17 20:37:29 -0700747 /*
748 * The midlayer only generated a single gather/scatter
749 * entry, or DMA mapping coalesced everything to a
750 * single entry. So a direct descriptor along with
751 * the DMA MR suffices.
752 */
Roland Dreieraef9ec32005-11-02 14:07:13 -0800753 struct srp_direct_buf *buf = (void *) cmd->add_data;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800754
Ralph Campbell85507bc2006-12-12 14:30:55 -0800755 buf->va = cpu_to_be64(ib_sg_dma_address(ibdev, scat));
David Dillow9af76272010-11-26 15:34:46 -0500756 buf->key = cpu_to_be32(target->rkey);
Ralph Campbell85507bc2006-12-12 14:30:55 -0800757 buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat));
Ishai Rabinovitz559ce8f2006-08-03 10:35:43 -0700758 } else if (srp_map_fmr(target, scat, count, req,
Roland Dreierf5358a12006-06-17 20:37:29 -0700759 (void *) cmd->add_data)) {
760 /*
761 * FMR mapping failed, and the scatterlist has more
762 * than one entry. Generate an indirect memory
763 * descriptor.
764 */
Roland Dreiercf368712006-03-24 15:47:26 -0800765 struct srp_indirect_buf *buf = (void *) cmd->add_data;
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900766 struct scatterlist *sg;
Roland Dreiercf368712006-03-24 15:47:26 -0800767 u32 datalen = 0;
Roland Dreierf5358a12006-06-17 20:37:29 -0700768 int i;
Roland Dreiercf368712006-03-24 15:47:26 -0800769
770 fmt = SRP_DATA_DESC_INDIRECT;
Roland Dreierf5358a12006-06-17 20:37:29 -0700771 len = sizeof (struct srp_cmd) +
772 sizeof (struct srp_indirect_buf) +
773 count * sizeof (struct srp_direct_buf);
774
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900775 scsi_for_each_sg(scmnd, sg, count, i) {
776 unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
Ralph Campbell85507bc2006-12-12 14:30:55 -0800777
Roland Dreierf5358a12006-06-17 20:37:29 -0700778 buf->desc_list[i].va =
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900779 cpu_to_be64(ib_sg_dma_address(ibdev, sg));
Roland Dreierf5358a12006-06-17 20:37:29 -0700780 buf->desc_list[i].key =
David Dillow9af76272010-11-26 15:34:46 -0500781 cpu_to_be32(target->rkey);
Ralph Campbell85507bc2006-12-12 14:30:55 -0800782 buf->desc_list[i].len = cpu_to_be32(dma_len);
783 datalen += dma_len;
Roland Dreierf5358a12006-06-17 20:37:29 -0700784 }
Roland Dreiercf368712006-03-24 15:47:26 -0800785
786 if (scmnd->sc_data_direction == DMA_TO_DEVICE)
787 cmd->data_out_desc_cnt = count;
788 else
789 cmd->data_in_desc_cnt = count;
790
Roland Dreierf5358a12006-06-17 20:37:29 -0700791 buf->table_desc.va =
792 cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf);
Roland Dreiercf368712006-03-24 15:47:26 -0800793 buf->table_desc.key =
David Dillow9af76272010-11-26 15:34:46 -0500794 cpu_to_be32(target->rkey);
Roland Dreiercf368712006-03-24 15:47:26 -0800795 buf->table_desc.len =
796 cpu_to_be32(count * sizeof (struct srp_direct_buf));
797
Roland Dreiercf368712006-03-24 15:47:26 -0800798 buf->len = cpu_to_be32(datalen);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800799 }
800
801 if (scmnd->sc_data_direction == DMA_TO_DEVICE)
802 cmd->buf_fmt = fmt << 4;
803 else
804 cmd->buf_fmt = fmt;
805
Roland Dreieraef9ec32005-11-02 14:07:13 -0800806 return len;
807}
808
David Dillow05a1d752010-10-08 14:48:14 -0400809/*
Bart Van Assche76c75b22010-11-26 14:37:47 -0500810 * Return an IU and possible credit to the free pool
811 */
812static void srp_put_tx_iu(struct srp_target_port *target, struct srp_iu *iu,
813 enum srp_iu_type iu_type)
814{
815 unsigned long flags;
816
Bart Van Asschee9684672010-11-26 15:08:38 -0500817 spin_lock_irqsave(&target->lock, flags);
Bart Van Assche76c75b22010-11-26 14:37:47 -0500818 list_add(&iu->list, &target->free_tx);
819 if (iu_type != SRP_IU_RSP)
820 ++target->req_lim;
Bart Van Asschee9684672010-11-26 15:08:38 -0500821 spin_unlock_irqrestore(&target->lock, flags);
Bart Van Assche76c75b22010-11-26 14:37:47 -0500822}
823
824/*
Bart Van Asschee9684672010-11-26 15:08:38 -0500825 * Must be called with target->lock held to protect req_lim and free_tx.
826 * If IU is not sent, it must be returned using srp_put_tx_iu().
David Dillow05a1d752010-10-08 14:48:14 -0400827 *
828 * Note:
829 * An upper limit for the number of allocated information units for each
830 * request type is:
831 * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
832 * more than Scsi_Host.can_queue requests.
833 * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
834 * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
835 * one unanswered SRP request to an initiator.
836 */
837static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
838 enum srp_iu_type iu_type)
839{
840 s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
841 struct srp_iu *iu;
842
843 srp_send_completion(target->send_cq, target);
844
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500845 if (list_empty(&target->free_tx))
David Dillow05a1d752010-10-08 14:48:14 -0400846 return NULL;
847
848 /* Initiator responses to target requests do not consume credits */
Bart Van Assche76c75b22010-11-26 14:37:47 -0500849 if (iu_type != SRP_IU_RSP) {
850 if (target->req_lim <= rsv) {
851 ++target->zero_req_lim;
852 return NULL;
853 }
854
855 --target->req_lim;
David Dillow05a1d752010-10-08 14:48:14 -0400856 }
857
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500858 iu = list_first_entry(&target->free_tx, struct srp_iu, list);
Bart Van Assche76c75b22010-11-26 14:37:47 -0500859 list_del(&iu->list);
David Dillow05a1d752010-10-08 14:48:14 -0400860 return iu;
861}
862
Bart Van Assche76c75b22010-11-26 14:37:47 -0500863static int srp_post_send(struct srp_target_port *target,
864 struct srp_iu *iu, int len)
David Dillow05a1d752010-10-08 14:48:14 -0400865{
866 struct ib_sge list;
867 struct ib_send_wr wr, *bad_wr;
David Dillow05a1d752010-10-08 14:48:14 -0400868
869 list.addr = iu->dma;
870 list.length = len;
David Dillow9af76272010-11-26 15:34:46 -0500871 list.lkey = target->lkey;
David Dillow05a1d752010-10-08 14:48:14 -0400872
873 wr.next = NULL;
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500874 wr.wr_id = (uintptr_t) iu;
David Dillow05a1d752010-10-08 14:48:14 -0400875 wr.sg_list = &list;
876 wr.num_sge = 1;
877 wr.opcode = IB_WR_SEND;
878 wr.send_flags = IB_SEND_SIGNALED;
879
Bart Van Assche76c75b22010-11-26 14:37:47 -0500880 return ib_post_send(target->qp, &wr, &bad_wr);
David Dillow05a1d752010-10-08 14:48:14 -0400881}
882
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500883static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu)
Bart Van Asschec996bb42010-07-30 10:59:05 +0000884{
Bart Van Asschec996bb42010-07-30 10:59:05 +0000885 struct ib_recv_wr wr, *bad_wr;
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500886 struct ib_sge list;
Bart Van Asschec996bb42010-07-30 10:59:05 +0000887
888 list.addr = iu->dma;
889 list.length = iu->size;
David Dillow9af76272010-11-26 15:34:46 -0500890 list.lkey = target->lkey;
Bart Van Asschec996bb42010-07-30 10:59:05 +0000891
892 wr.next = NULL;
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500893 wr.wr_id = (uintptr_t) iu;
Bart Van Asschec996bb42010-07-30 10:59:05 +0000894 wr.sg_list = &list;
895 wr.num_sge = 1;
896
Bart Van Asschedcb4cb82010-11-26 13:22:48 -0500897 return ib_post_recv(target->qp, &wr, &bad_wr);
Bart Van Asschec996bb42010-07-30 10:59:05 +0000898}
899
Roland Dreieraef9ec32005-11-02 14:07:13 -0800900static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
901{
902 struct srp_request *req;
903 struct scsi_cmnd *scmnd;
904 unsigned long flags;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800905
Roland Dreieraef9ec32005-11-02 14:07:13 -0800906 if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
Bart Van Asschee9684672010-11-26 15:08:38 -0500907 spin_lock_irqsave(&target->lock, flags);
Bart Van Assche94a91742010-11-26 14:50:09 -0500908 target->req_lim += be32_to_cpu(rsp->req_lim_delta);
Bart Van Asschee9684672010-11-26 15:08:38 -0500909 spin_unlock_irqrestore(&target->lock, flags);
Bart Van Assche94a91742010-11-26 14:50:09 -0500910
David Dillowf8b6e312010-11-26 13:02:21 -0500911 target->tsk_mgmt_status = -1;
912 if (be32_to_cpu(rsp->resp_data_len) >= 4)
913 target->tsk_mgmt_status = rsp->data[3];
914 complete(&target->tsk_mgmt_done);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800915 } else {
David Dillowf8b6e312010-11-26 13:02:21 -0500916 req = &target->req_ring[rsp->tag];
Roland Dreierd945e1d2006-05-09 10:50:28 -0700917 scmnd = req->scmnd;
Roland Dreieraef9ec32005-11-02 14:07:13 -0800918 if (!scmnd)
David Dillow7aa54bd2008-01-07 18:23:41 -0500919 shost_printk(KERN_ERR, target->scsi_host,
920 "Null scmnd for RSP w/tag %016llx\n",
921 (unsigned long long) rsp->tag);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800922 scmnd->result = rsp->status;
923
924 if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
925 memcpy(scmnd->sense_buffer, rsp->data +
926 be32_to_cpu(rsp->resp_data_len),
927 min_t(int, be32_to_cpu(rsp->sense_data_len),
928 SCSI_SENSE_BUFFERSIZE));
929 }
930
931 if (rsp->flags & (SRP_RSP_FLAG_DOOVER | SRP_RSP_FLAG_DOUNDER))
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900932 scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
Roland Dreieraef9ec32005-11-02 14:07:13 -0800933 else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
FUJITA Tomonoribb350d12007-05-26 02:28:25 +0900934 scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
Roland Dreieraef9ec32005-11-02 14:07:13 -0800935
Bart Van Assche94a91742010-11-26 14:50:09 -0500936 srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta));
David Dillowf8b6e312010-11-26 13:02:21 -0500937 scmnd->host_scribble = NULL;
938 scmnd->scsi_done(scmnd);
Roland Dreieraef9ec32005-11-02 14:07:13 -0800939 }
Roland Dreieraef9ec32005-11-02 14:07:13 -0800940}
941
David Dillowbb125882010-10-08 14:40:47 -0400942static int srp_response_common(struct srp_target_port *target, s32 req_delta,
943 void *rsp, int len)
944{
Bart Van Assche76c75b22010-11-26 14:37:47 -0500945 struct ib_device *dev = target->srp_host->srp_dev->dev;
David Dillowbb125882010-10-08 14:40:47 -0400946 unsigned long flags;
947 struct srp_iu *iu;
Bart Van Assche76c75b22010-11-26 14:37:47 -0500948 int err;
David Dillowbb125882010-10-08 14:40:47 -0400949
Bart Van Asschee9684672010-11-26 15:08:38 -0500950 spin_lock_irqsave(&target->lock, flags);
David Dillowbb125882010-10-08 14:40:47 -0400951 target->req_lim += req_delta;
David Dillowbb125882010-10-08 14:40:47 -0400952 iu = __srp_get_tx_iu(target, SRP_IU_RSP);
Bart Van Asschee9684672010-11-26 15:08:38 -0500953 spin_unlock_irqrestore(&target->lock, flags);
Bart Van Assche76c75b22010-11-26 14:37:47 -0500954
David Dillowbb125882010-10-08 14:40:47 -0400955 if (!iu) {
956 shost_printk(KERN_ERR, target->scsi_host, PFX
957 "no IU available to send response\n");
Bart Van Assche76c75b22010-11-26 14:37:47 -0500958 return 1;
David Dillowbb125882010-10-08 14:40:47 -0400959 }
960
961 ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
962 memcpy(iu->buf, rsp, len);
963 ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
964
Bart Van Assche76c75b22010-11-26 14:37:47 -0500965 err = srp_post_send(target, iu, len);
966 if (err) {
David Dillowbb125882010-10-08 14:40:47 -0400967 shost_printk(KERN_ERR, target->scsi_host, PFX
968 "unable to post response: %d\n", err);
Bart Van Assche76c75b22010-11-26 14:37:47 -0500969 srp_put_tx_iu(target, iu, SRP_IU_RSP);
970 }
David Dillowbb125882010-10-08 14:40:47 -0400971
David Dillowbb125882010-10-08 14:40:47 -0400972 return err;
973}
974
975static void srp_process_cred_req(struct srp_target_port *target,
976 struct srp_cred_req *req)
977{
978 struct srp_cred_rsp rsp = {
979 .opcode = SRP_CRED_RSP,
980 .tag = req->tag,
981 };
982 s32 delta = be32_to_cpu(req->req_lim_delta);
983
984 if (srp_response_common(target, delta, &rsp, sizeof rsp))
985 shost_printk(KERN_ERR, target->scsi_host, PFX
986 "problems processing SRP_CRED_REQ\n");
987}
988
989static void srp_process_aer_req(struct srp_target_port *target,
990 struct srp_aer_req *req)
991{
992 struct srp_aer_rsp rsp = {
993 .opcode = SRP_AER_RSP,
994 .tag = req->tag,
995 };
996 s32 delta = be32_to_cpu(req->req_lim_delta);
997
998 shost_printk(KERN_ERR, target->scsi_host, PFX
999 "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun));
1000
1001 if (srp_response_common(target, delta, &rsp, sizeof rsp))
1002 shost_printk(KERN_ERR, target->scsi_host, PFX
1003 "problems processing SRP_AER_REQ\n");
1004}
1005
Roland Dreieraef9ec32005-11-02 14:07:13 -08001006static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
1007{
Bart Van Asschedcb4cb82010-11-26 13:22:48 -05001008 struct ib_device *dev = target->srp_host->srp_dev->dev;
1009 struct srp_iu *iu = (struct srp_iu *) wc->wr_id;
Bart Van Asschec996bb42010-07-30 10:59:05 +00001010 int res;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001011 u8 opcode;
1012
Ralph Campbell85507bc2006-12-12 14:30:55 -08001013 ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
1014 DMA_FROM_DEVICE);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001015
1016 opcode = *(u8 *) iu->buf;
1017
1018 if (0) {
David Dillow7aa54bd2008-01-07 18:23:41 -05001019 shost_printk(KERN_ERR, target->scsi_host,
1020 PFX "recv completion, opcode 0x%02x\n", opcode);
Bart Van Assche7a700812010-07-29 15:56:37 +00001021 print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 8, 1,
1022 iu->buf, wc->byte_len, true);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001023 }
1024
1025 switch (opcode) {
1026 case SRP_RSP:
1027 srp_process_rsp(target, iu->buf);
1028 break;
1029
David Dillowbb125882010-10-08 14:40:47 -04001030 case SRP_CRED_REQ:
1031 srp_process_cred_req(target, iu->buf);
1032 break;
1033
1034 case SRP_AER_REQ:
1035 srp_process_aer_req(target, iu->buf);
1036 break;
1037
Roland Dreieraef9ec32005-11-02 14:07:13 -08001038 case SRP_T_LOGOUT:
1039 /* XXX Handle target logout */
David Dillow7aa54bd2008-01-07 18:23:41 -05001040 shost_printk(KERN_WARNING, target->scsi_host,
1041 PFX "Got target logout request\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001042 break;
1043
1044 default:
David Dillow7aa54bd2008-01-07 18:23:41 -05001045 shost_printk(KERN_WARNING, target->scsi_host,
1046 PFX "Unhandled SRP opcode 0x%02x\n", opcode);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001047 break;
1048 }
1049
Ralph Campbell85507bc2006-12-12 14:30:55 -08001050 ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len,
1051 DMA_FROM_DEVICE);
Bart Van Asschec996bb42010-07-30 10:59:05 +00001052
Bart Van Asschedcb4cb82010-11-26 13:22:48 -05001053 res = srp_post_recv(target, iu);
Bart Van Asschec996bb42010-07-30 10:59:05 +00001054 if (res != 0)
1055 shost_printk(KERN_ERR, target->scsi_host,
1056 PFX "Recv failed with error code %d\n", res);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001057}
1058
Bart Van Assche9c03dc92010-02-02 19:23:54 +00001059static void srp_recv_completion(struct ib_cq *cq, void *target_ptr)
Roland Dreieraef9ec32005-11-02 14:07:13 -08001060{
1061 struct srp_target_port *target = target_ptr;
1062 struct ib_wc wc;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001063
1064 ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
1065 while (ib_poll_cq(cq, 1, &wc) > 0) {
1066 if (wc.status) {
David Dillow7aa54bd2008-01-07 18:23:41 -05001067 shost_printk(KERN_ERR, target->scsi_host,
Bart Van Assche9c03dc92010-02-02 19:23:54 +00001068 PFX "failed receive status %d\n",
David Dillow7aa54bd2008-01-07 18:23:41 -05001069 wc.status);
Ishai Rabinovitz1033ff62007-01-16 17:26:22 +02001070 target->qp_in_error = 1;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001071 break;
1072 }
1073
Bart Van Assche9c03dc92010-02-02 19:23:54 +00001074 srp_handle_recv(target, &wc);
1075 }
1076}
1077
1078static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
1079{
1080 struct srp_target_port *target = target_ptr;
1081 struct ib_wc wc;
Bart Van Asschedcb4cb82010-11-26 13:22:48 -05001082 struct srp_iu *iu;
Bart Van Assche9c03dc92010-02-02 19:23:54 +00001083
1084 while (ib_poll_cq(cq, 1, &wc) > 0) {
1085 if (wc.status) {
1086 shost_printk(KERN_ERR, target->scsi_host,
1087 PFX "failed send status %d\n",
1088 wc.status);
1089 target->qp_in_error = 1;
1090 break;
1091 }
1092
Bart Van Asschedcb4cb82010-11-26 13:22:48 -05001093 iu = (struct srp_iu *) wc.wr_id;
1094 list_add(&iu->list, &target->free_tx);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001095 }
1096}
1097
Bart Van Assche76c75b22010-11-26 14:37:47 -05001098static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
Roland Dreieraef9ec32005-11-02 14:07:13 -08001099{
Bart Van Assche76c75b22010-11-26 14:37:47 -05001100 struct srp_target_port *target = host_to_target(shost);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001101 struct srp_request *req;
1102 struct srp_iu *iu;
1103 struct srp_cmd *cmd;
Ralph Campbell85507bc2006-12-12 14:30:55 -08001104 struct ib_device *dev;
Bart Van Assche76c75b22010-11-26 14:37:47 -05001105 unsigned long flags;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001106 int len;
1107
1108 if (target->state == SRP_TARGET_CONNECTING)
1109 goto err;
1110
1111 if (target->state == SRP_TARGET_DEAD ||
1112 target->state == SRP_TARGET_REMOVED) {
1113 scmnd->result = DID_BAD_TARGET << 16;
Bart Van Assche76c75b22010-11-26 14:37:47 -05001114 scmnd->scsi_done(scmnd);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001115 return 0;
1116 }
1117
Bart Van Asschee9684672010-11-26 15:08:38 -05001118 spin_lock_irqsave(&target->lock, flags);
David Dillowbb125882010-10-08 14:40:47 -04001119 iu = __srp_get_tx_iu(target, SRP_IU_CMD);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001120 if (!iu)
Bart Van Assche695b8342011-01-13 19:02:25 +00001121 goto err_unlock;
1122
1123 req = list_first_entry(&target->free_reqs, struct srp_request, list);
1124 list_del(&req->list);
1125 spin_unlock_irqrestore(&target->lock, flags);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001126
Greg Kroah-Hartman05321932008-03-06 00:13:36 +01001127 dev = target->srp_host->srp_dev->dev;
Ralph Campbell85507bc2006-12-12 14:30:55 -08001128 ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
1129 DMA_TO_DEVICE);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001130
Roland Dreieraef9ec32005-11-02 14:07:13 -08001131 scmnd->result = 0;
David Dillowf8b6e312010-11-26 13:02:21 -05001132 scmnd->host_scribble = (void *) req;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001133
1134 cmd = iu->buf;
1135 memset(cmd, 0, sizeof *cmd);
1136
1137 cmd->opcode = SRP_CMD;
1138 cmd->lun = cpu_to_be64((u64) scmnd->device->lun << 48);
Roland Dreierd945e1d2006-05-09 10:50:28 -07001139 cmd->tag = req->index;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001140 memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
1141
Roland Dreieraef9ec32005-11-02 14:07:13 -08001142 req->scmnd = scmnd;
1143 req->cmd = iu;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001144
1145 len = srp_map_data(scmnd, target, req);
1146 if (len < 0) {
David Dillow7aa54bd2008-01-07 18:23:41 -05001147 shost_printk(KERN_ERR, target->scsi_host,
1148 PFX "Failed to map data\n");
Bart Van Assche76c75b22010-11-26 14:37:47 -05001149 goto err_iu;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001150 }
1151
Ralph Campbell85507bc2006-12-12 14:30:55 -08001152 ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len,
1153 DMA_TO_DEVICE);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001154
Bart Van Assche76c75b22010-11-26 14:37:47 -05001155 if (srp_post_send(target, iu, len)) {
David Dillow7aa54bd2008-01-07 18:23:41 -05001156 shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001157 goto err_unmap;
1158 }
1159
Roland Dreieraef9ec32005-11-02 14:07:13 -08001160 return 0;
1161
1162err_unmap:
1163 srp_unmap_data(scmnd, target, req);
1164
Bart Van Assche76c75b22010-11-26 14:37:47 -05001165err_iu:
1166 srp_put_tx_iu(target, iu, SRP_IU_CMD);
1167
Bart Van Asschee9684672010-11-26 15:08:38 -05001168 spin_lock_irqsave(&target->lock, flags);
Bart Van Assche76c75b22010-11-26 14:37:47 -05001169 list_add(&req->list, &target->free_reqs);
Bart Van Assche695b8342011-01-13 19:02:25 +00001170
1171err_unlock:
Bart Van Asschee9684672010-11-26 15:08:38 -05001172 spin_unlock_irqrestore(&target->lock, flags);
Bart Van Assche76c75b22010-11-26 14:37:47 -05001173
Roland Dreieraef9ec32005-11-02 14:07:13 -08001174err:
1175 return SCSI_MLQUEUE_HOST_BUSY;
1176}
1177
1178static int srp_alloc_iu_bufs(struct srp_target_port *target)
1179{
1180 int i;
1181
1182 for (i = 0; i < SRP_RQ_SIZE; ++i) {
1183 target->rx_ring[i] = srp_alloc_iu(target->srp_host,
1184 target->max_ti_iu_len,
1185 GFP_KERNEL, DMA_FROM_DEVICE);
1186 if (!target->rx_ring[i])
1187 goto err;
1188 }
1189
Bart Van Asschedd5e6e32010-08-30 19:27:20 +00001190 for (i = 0; i < SRP_SQ_SIZE; ++i) {
Roland Dreieraef9ec32005-11-02 14:07:13 -08001191 target->tx_ring[i] = srp_alloc_iu(target->srp_host,
Vu Pham74b0a152006-06-17 20:37:32 -07001192 srp_max_iu_len,
Roland Dreieraef9ec32005-11-02 14:07:13 -08001193 GFP_KERNEL, DMA_TO_DEVICE);
1194 if (!target->tx_ring[i])
1195 goto err;
Bart Van Asschedcb4cb82010-11-26 13:22:48 -05001196
1197 list_add(&target->tx_ring[i]->list, &target->free_tx);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001198 }
1199
1200 return 0;
1201
1202err:
1203 for (i = 0; i < SRP_RQ_SIZE; ++i) {
1204 srp_free_iu(target->srp_host, target->rx_ring[i]);
1205 target->rx_ring[i] = NULL;
1206 }
1207
Bart Van Asschedd5e6e32010-08-30 19:27:20 +00001208 for (i = 0; i < SRP_SQ_SIZE; ++i) {
Roland Dreieraef9ec32005-11-02 14:07:13 -08001209 srp_free_iu(target->srp_host, target->tx_ring[i]);
1210 target->tx_ring[i] = NULL;
1211 }
1212
1213 return -ENOMEM;
1214}
1215
David Dillow961e0be2011-01-14 17:32:07 -05001216static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
1217 struct srp_login_rsp *lrsp,
1218 struct srp_target_port *target)
1219{
1220 struct ib_qp_attr *qp_attr = NULL;
1221 int attr_mask = 0;
1222 int ret;
1223 int i;
1224
1225 if (lrsp->opcode == SRP_LOGIN_RSP) {
1226 target->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
1227 target->req_lim = be32_to_cpu(lrsp->req_lim_delta);
1228
1229 /*
1230 * Reserve credits for task management so we don't
1231 * bounce requests back to the SCSI mid-layer.
1232 */
1233 target->scsi_host->can_queue
1234 = min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE,
1235 target->scsi_host->can_queue);
1236 } else {
1237 shost_printk(KERN_WARNING, target->scsi_host,
1238 PFX "Unhandled RSP opcode %#x\n", lrsp->opcode);
1239 ret = -ECONNRESET;
1240 goto error;
1241 }
1242
1243 if (!target->rx_ring[0]) {
1244 ret = srp_alloc_iu_bufs(target);
1245 if (ret)
1246 goto error;
1247 }
1248
1249 ret = -ENOMEM;
1250 qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL);
1251 if (!qp_attr)
1252 goto error;
1253
1254 qp_attr->qp_state = IB_QPS_RTR;
1255 ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
1256 if (ret)
1257 goto error_free;
1258
1259 ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
1260 if (ret)
1261 goto error_free;
1262
1263 for (i = 0; i < SRP_RQ_SIZE; i++) {
1264 struct srp_iu *iu = target->rx_ring[i];
1265 ret = srp_post_recv(target, iu);
1266 if (ret)
1267 goto error_free;
1268 }
1269
1270 qp_attr->qp_state = IB_QPS_RTS;
1271 ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
1272 if (ret)
1273 goto error_free;
1274
1275 ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
1276 if (ret)
1277 goto error_free;
1278
1279 ret = ib_send_cm_rtu(cm_id, NULL, 0);
1280
1281error_free:
1282 kfree(qp_attr);
1283
1284error:
1285 target->status = ret;
1286}
1287
Roland Dreieraef9ec32005-11-02 14:07:13 -08001288static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
1289 struct ib_cm_event *event,
1290 struct srp_target_port *target)
1291{
David Dillow7aa54bd2008-01-07 18:23:41 -05001292 struct Scsi_Host *shost = target->scsi_host;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001293 struct ib_class_port_info *cpi;
1294 int opcode;
1295
1296 switch (event->param.rej_rcvd.reason) {
1297 case IB_CM_REJ_PORT_CM_REDIRECT:
1298 cpi = event->param.rej_rcvd.ari;
1299 target->path.dlid = cpi->redirect_lid;
1300 target->path.pkey = cpi->redirect_pkey;
1301 cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
1302 memcpy(target->path.dgid.raw, cpi->redirect_gid, 16);
1303
1304 target->status = target->path.dlid ?
1305 SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
1306 break;
1307
1308 case IB_CM_REJ_PORT_REDIRECT:
Roland Dreier5d7cbfd2007-08-03 10:45:18 -07001309 if (srp_target_is_topspin(target)) {
Roland Dreieraef9ec32005-11-02 14:07:13 -08001310 /*
1311 * Topspin/Cisco SRP gateways incorrectly send
1312 * reject reason code 25 when they mean 24
1313 * (port redirect).
1314 */
1315 memcpy(target->path.dgid.raw,
1316 event->param.rej_rcvd.ari, 16);
1317
David Dillow7aa54bd2008-01-07 18:23:41 -05001318 shost_printk(KERN_DEBUG, shost,
1319 PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
1320 (unsigned long long) be64_to_cpu(target->path.dgid.global.subnet_prefix),
1321 (unsigned long long) be64_to_cpu(target->path.dgid.global.interface_id));
Roland Dreieraef9ec32005-11-02 14:07:13 -08001322
1323 target->status = SRP_PORT_REDIRECT;
1324 } else {
David Dillow7aa54bd2008-01-07 18:23:41 -05001325 shost_printk(KERN_WARNING, shost,
1326 " REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001327 target->status = -ECONNRESET;
1328 }
1329 break;
1330
1331 case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
David Dillow7aa54bd2008-01-07 18:23:41 -05001332 shost_printk(KERN_WARNING, shost,
1333 " REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001334 target->status = -ECONNRESET;
1335 break;
1336
1337 case IB_CM_REJ_CONSUMER_DEFINED:
1338 opcode = *(u8 *) event->private_data;
1339 if (opcode == SRP_LOGIN_REJ) {
1340 struct srp_login_rej *rej = event->private_data;
1341 u32 reason = be32_to_cpu(rej->reason);
1342
1343 if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
David Dillow7aa54bd2008-01-07 18:23:41 -05001344 shost_printk(KERN_WARNING, shost,
1345 PFX "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001346 else
David Dillow7aa54bd2008-01-07 18:23:41 -05001347 shost_printk(KERN_WARNING, shost,
1348 PFX "SRP LOGIN REJECTED, reason 0x%08x\n", reason);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001349 } else
David Dillow7aa54bd2008-01-07 18:23:41 -05001350 shost_printk(KERN_WARNING, shost,
1351 " REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
1352 " opcode 0x%02x\n", opcode);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001353 target->status = -ECONNRESET;
1354 break;
1355
David Dillow9fe4bcf2008-01-08 17:08:52 -05001356 case IB_CM_REJ_STALE_CONN:
1357 shost_printk(KERN_WARNING, shost, " REJ reason: stale connection\n");
1358 target->status = SRP_STALE_CONN;
1359 break;
1360
Roland Dreieraef9ec32005-11-02 14:07:13 -08001361 default:
David Dillow7aa54bd2008-01-07 18:23:41 -05001362 shost_printk(KERN_WARNING, shost, " REJ reason 0x%x\n",
1363 event->param.rej_rcvd.reason);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001364 target->status = -ECONNRESET;
1365 }
1366}
1367
1368static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
1369{
1370 struct srp_target_port *target = cm_id->context;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001371 int comp = 0;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001372
1373 switch (event->event) {
1374 case IB_CM_REQ_ERROR:
David Dillow7aa54bd2008-01-07 18:23:41 -05001375 shost_printk(KERN_DEBUG, target->scsi_host,
1376 PFX "Sending CM REQ failed\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001377 comp = 1;
1378 target->status = -ECONNRESET;
1379 break;
1380
1381 case IB_CM_REP_RECEIVED:
1382 comp = 1;
David Dillow961e0be2011-01-14 17:32:07 -05001383 srp_cm_rep_handler(cm_id, event->private_data, target);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001384 break;
1385
1386 case IB_CM_REJ_RECEIVED:
David Dillow7aa54bd2008-01-07 18:23:41 -05001387 shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001388 comp = 1;
1389
1390 srp_cm_rej_handler(cm_id, event, target);
1391 break;
1392
Ishai Rabinovitzb7ac4ab2006-06-17 20:37:32 -07001393 case IB_CM_DREQ_RECEIVED:
David Dillow7aa54bd2008-01-07 18:23:41 -05001394 shost_printk(KERN_WARNING, target->scsi_host,
1395 PFX "DREQ received - connection closed\n");
Ishai Rabinovitzb7ac4ab2006-06-17 20:37:32 -07001396 if (ib_send_cm_drep(cm_id, NULL, 0))
David Dillow7aa54bd2008-01-07 18:23:41 -05001397 shost_printk(KERN_ERR, target->scsi_host,
1398 PFX "Sending CM DREP failed\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001399 break;
1400
1401 case IB_CM_TIMEWAIT_EXIT:
David Dillow7aa54bd2008-01-07 18:23:41 -05001402 shost_printk(KERN_ERR, target->scsi_host,
1403 PFX "connection closed\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001404
1405 comp = 1;
1406 target->status = 0;
1407 break;
1408
Ishai Rabinovitzb7ac4ab2006-06-17 20:37:32 -07001409 case IB_CM_MRA_RECEIVED:
1410 case IB_CM_DREQ_ERROR:
1411 case IB_CM_DREP_RECEIVED:
1412 break;
1413
Roland Dreieraef9ec32005-11-02 14:07:13 -08001414 default:
David Dillow7aa54bd2008-01-07 18:23:41 -05001415 shost_printk(KERN_WARNING, target->scsi_host,
1416 PFX "Unhandled CM event %d\n", event->event);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001417 break;
1418 }
1419
1420 if (comp)
1421 complete(&target->done);
1422
Roland Dreieraef9ec32005-11-02 14:07:13 -08001423 return 0;
1424}
1425
Roland Dreierd945e1d2006-05-09 10:50:28 -07001426static int srp_send_tsk_mgmt(struct srp_target_port *target,
David Dillowf8b6e312010-11-26 13:02:21 -05001427 u64 req_tag, unsigned int lun, u8 func)
Roland Dreieraef9ec32005-11-02 14:07:13 -08001428{
David Dillow19081f32010-10-18 08:54:49 -04001429 struct ib_device *dev = target->srp_host->srp_dev->dev;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001430 struct srp_iu *iu;
1431 struct srp_tsk_mgmt *tsk_mgmt;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001432
Roland Dreier1285b3a2006-03-03 15:47:25 -08001433 if (target->state == SRP_TARGET_DEAD ||
David Dillowf8b6e312010-11-26 13:02:21 -05001434 target->state == SRP_TARGET_REMOVED)
Bart Van Assche76c75b22010-11-26 14:37:47 -05001435 return -1;
Roland Dreier1285b3a2006-03-03 15:47:25 -08001436
David Dillowf8b6e312010-11-26 13:02:21 -05001437 init_completion(&target->tsk_mgmt_done);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001438
Bart Van Asschee9684672010-11-26 15:08:38 -05001439 spin_lock_irq(&target->lock);
David Dillowbb125882010-10-08 14:40:47 -04001440 iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT);
Bart Van Asschee9684672010-11-26 15:08:38 -05001441 spin_unlock_irq(&target->lock);
Bart Van Assche76c75b22010-11-26 14:37:47 -05001442
Roland Dreieraef9ec32005-11-02 14:07:13 -08001443 if (!iu)
Bart Van Assche76c75b22010-11-26 14:37:47 -05001444 return -1;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001445
David Dillow19081f32010-10-18 08:54:49 -04001446 ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
1447 DMA_TO_DEVICE);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001448 tsk_mgmt = iu->buf;
1449 memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
1450
1451 tsk_mgmt->opcode = SRP_TSK_MGMT;
David Dillowf8b6e312010-11-26 13:02:21 -05001452 tsk_mgmt->lun = cpu_to_be64((u64) lun << 48);
1453 tsk_mgmt->tag = req_tag | SRP_TAG_TSK_MGMT;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001454 tsk_mgmt->tsk_mgmt_func = func;
David Dillowf8b6e312010-11-26 13:02:21 -05001455 tsk_mgmt->task_tag = req_tag;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001456
David Dillow19081f32010-10-18 08:54:49 -04001457 ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
1458 DMA_TO_DEVICE);
Bart Van Assche76c75b22010-11-26 14:37:47 -05001459 if (srp_post_send(target, iu, sizeof *tsk_mgmt)) {
1460 srp_put_tx_iu(target, iu, SRP_IU_TSK_MGMT);
1461 return -1;
1462 }
Roland Dreierd945e1d2006-05-09 10:50:28 -07001463
David Dillowf8b6e312010-11-26 13:02:21 -05001464 if (!wait_for_completion_timeout(&target->tsk_mgmt_done,
Roland Dreieraef9ec32005-11-02 14:07:13 -08001465 msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
Roland Dreierd945e1d2006-05-09 10:50:28 -07001466 return -1;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001467
Roland Dreierd945e1d2006-05-09 10:50:28 -07001468 return 0;
Roland Dreierd945e1d2006-05-09 10:50:28 -07001469}
1470
Roland Dreieraef9ec32005-11-02 14:07:13 -08001471static int srp_abort(struct scsi_cmnd *scmnd)
1472{
Roland Dreierd945e1d2006-05-09 10:50:28 -07001473 struct srp_target_port *target = host_to_target(scmnd->device->host);
David Dillowf8b6e312010-11-26 13:02:21 -05001474 struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
Roland Dreierd945e1d2006-05-09 10:50:28 -07001475 int ret = SUCCESS;
1476
David Dillow7aa54bd2008-01-07 18:23:41 -05001477 shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001478
David Dillowf8b6e312010-11-26 13:02:21 -05001479 if (!req || target->qp_in_error)
Ishai Rabinovitz1033ff62007-01-16 17:26:22 +02001480 return FAILED;
David Dillowf8b6e312010-11-26 13:02:21 -05001481 if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
1482 SRP_TSK_ABORT_TASK))
Roland Dreierd945e1d2006-05-09 10:50:28 -07001483 return FAILED;
1484
David Dillowf8b6e312010-11-26 13:02:21 -05001485 if (req->scmnd) {
1486 if (!target->tsk_mgmt_status) {
Bart Van Assche94a91742010-11-26 14:50:09 -05001487 srp_remove_req(target, req, 0);
David Dillowf8b6e312010-11-26 13:02:21 -05001488 scmnd->result = DID_ABORT << 16;
1489 } else
1490 ret = FAILED;
1491 }
Roland Dreierd945e1d2006-05-09 10:50:28 -07001492
Roland Dreierd945e1d2006-05-09 10:50:28 -07001493 return ret;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001494}
1495
1496static int srp_reset_device(struct scsi_cmnd *scmnd)
1497{
Roland Dreierd945e1d2006-05-09 10:50:28 -07001498 struct srp_target_port *target = host_to_target(scmnd->device->host);
Bart Van Assche536ae142010-11-26 13:58:27 -05001499 int i;
Roland Dreierd945e1d2006-05-09 10:50:28 -07001500
David Dillow7aa54bd2008-01-07 18:23:41 -05001501 shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001502
Ishai Rabinovitz1033ff62007-01-16 17:26:22 +02001503 if (target->qp_in_error)
1504 return FAILED;
David Dillowf8b6e312010-11-26 13:02:21 -05001505 if (srp_send_tsk_mgmt(target, SRP_TAG_NO_REQ, scmnd->device->lun,
1506 SRP_TSK_LUN_RESET))
Roland Dreierd945e1d2006-05-09 10:50:28 -07001507 return FAILED;
David Dillowf8b6e312010-11-26 13:02:21 -05001508 if (target->tsk_mgmt_status)
Roland Dreierd945e1d2006-05-09 10:50:28 -07001509 return FAILED;
1510
Bart Van Assche536ae142010-11-26 13:58:27 -05001511 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
1512 struct srp_request *req = &target->req_ring[i];
David Dillowf8b6e312010-11-26 13:02:21 -05001513 if (req->scmnd && req->scmnd->device == scmnd->device)
Ishai Rabinovitz526b4ca2006-06-17 20:37:38 -07001514 srp_reset_req(target, req);
Bart Van Assche536ae142010-11-26 13:58:27 -05001515 }
Roland Dreierd945e1d2006-05-09 10:50:28 -07001516
Roland Dreierd945e1d2006-05-09 10:50:28 -07001517 return SUCCESS;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001518}
1519
1520static int srp_reset_host(struct scsi_cmnd *scmnd)
1521{
1522 struct srp_target_port *target = host_to_target(scmnd->device->host);
1523 int ret = FAILED;
1524
David Dillow7aa54bd2008-01-07 18:23:41 -05001525 shost_printk(KERN_ERR, target->scsi_host, PFX "SRP reset_host called\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001526
1527 if (!srp_reconnect_target(target))
1528 ret = SUCCESS;
1529
1530 return ret;
1531}
1532
Tony Jonesee959b02008-02-22 00:13:36 +01001533static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
1534 char *buf)
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001535{
Tony Jonesee959b02008-02-22 00:13:36 +01001536 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001537
1538 if (target->state == SRP_TARGET_DEAD ||
1539 target->state == SRP_TARGET_REMOVED)
1540 return -ENODEV;
1541
1542 return sprintf(buf, "0x%016llx\n",
1543 (unsigned long long) be64_to_cpu(target->id_ext));
1544}
1545
Tony Jonesee959b02008-02-22 00:13:36 +01001546static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
1547 char *buf)
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001548{
Tony Jonesee959b02008-02-22 00:13:36 +01001549 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001550
1551 if (target->state == SRP_TARGET_DEAD ||
1552 target->state == SRP_TARGET_REMOVED)
1553 return -ENODEV;
1554
1555 return sprintf(buf, "0x%016llx\n",
1556 (unsigned long long) be64_to_cpu(target->ioc_guid));
1557}
1558
Tony Jonesee959b02008-02-22 00:13:36 +01001559static ssize_t show_service_id(struct device *dev,
1560 struct device_attribute *attr, char *buf)
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001561{
Tony Jonesee959b02008-02-22 00:13:36 +01001562 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001563
1564 if (target->state == SRP_TARGET_DEAD ||
1565 target->state == SRP_TARGET_REMOVED)
1566 return -ENODEV;
1567
1568 return sprintf(buf, "0x%016llx\n",
1569 (unsigned long long) be64_to_cpu(target->service_id));
1570}
1571
Tony Jonesee959b02008-02-22 00:13:36 +01001572static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
1573 char *buf)
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001574{
Tony Jonesee959b02008-02-22 00:13:36 +01001575 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001576
1577 if (target->state == SRP_TARGET_DEAD ||
1578 target->state == SRP_TARGET_REMOVED)
1579 return -ENODEV;
1580
1581 return sprintf(buf, "0x%04x\n", be16_to_cpu(target->path.pkey));
1582}
1583
Tony Jonesee959b02008-02-22 00:13:36 +01001584static ssize_t show_dgid(struct device *dev, struct device_attribute *attr,
1585 char *buf)
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001586{
Tony Jonesee959b02008-02-22 00:13:36 +01001587 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001588
1589 if (target->state == SRP_TARGET_DEAD ||
1590 target->state == SRP_TARGET_REMOVED)
1591 return -ENODEV;
1592
Harvey Harrison5b095d9892008-10-29 12:52:50 -07001593 return sprintf(buf, "%pI6\n", target->path.dgid.raw);
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001594}
1595
Tony Jonesee959b02008-02-22 00:13:36 +01001596static ssize_t show_orig_dgid(struct device *dev,
1597 struct device_attribute *attr, char *buf)
Ishai Rabinovitz3633b3d2007-05-06 21:18:11 -07001598{
Tony Jonesee959b02008-02-22 00:13:36 +01001599 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Ishai Rabinovitz3633b3d2007-05-06 21:18:11 -07001600
1601 if (target->state == SRP_TARGET_DEAD ||
1602 target->state == SRP_TARGET_REMOVED)
1603 return -ENODEV;
1604
Harvey Harrison5b095d9892008-10-29 12:52:50 -07001605 return sprintf(buf, "%pI6\n", target->orig_dgid);
Ishai Rabinovitz3633b3d2007-05-06 21:18:11 -07001606}
1607
Bart Van Assche89de7482010-08-03 14:08:45 +00001608static ssize_t show_req_lim(struct device *dev,
1609 struct device_attribute *attr, char *buf)
1610{
1611 struct srp_target_port *target = host_to_target(class_to_shost(dev));
1612
1613 if (target->state == SRP_TARGET_DEAD ||
1614 target->state == SRP_TARGET_REMOVED)
1615 return -ENODEV;
1616
1617 return sprintf(buf, "%d\n", target->req_lim);
1618}
1619
Tony Jonesee959b02008-02-22 00:13:36 +01001620static ssize_t show_zero_req_lim(struct device *dev,
1621 struct device_attribute *attr, char *buf)
Roland Dreier6bfa24f2006-06-17 20:37:33 -07001622{
Tony Jonesee959b02008-02-22 00:13:36 +01001623 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Roland Dreier6bfa24f2006-06-17 20:37:33 -07001624
1625 if (target->state == SRP_TARGET_DEAD ||
1626 target->state == SRP_TARGET_REMOVED)
1627 return -ENODEV;
1628
1629 return sprintf(buf, "%d\n", target->zero_req_lim);
1630}
1631
Tony Jonesee959b02008-02-22 00:13:36 +01001632static ssize_t show_local_ib_port(struct device *dev,
1633 struct device_attribute *attr, char *buf)
Ishai Rabinovitzded7f1a2006-08-15 17:34:52 +03001634{
Tony Jonesee959b02008-02-22 00:13:36 +01001635 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Ishai Rabinovitzded7f1a2006-08-15 17:34:52 +03001636
1637 return sprintf(buf, "%d\n", target->srp_host->port);
1638}
1639
Tony Jonesee959b02008-02-22 00:13:36 +01001640static ssize_t show_local_ib_device(struct device *dev,
1641 struct device_attribute *attr, char *buf)
Ishai Rabinovitzded7f1a2006-08-15 17:34:52 +03001642{
Tony Jonesee959b02008-02-22 00:13:36 +01001643 struct srp_target_port *target = host_to_target(class_to_shost(dev));
Ishai Rabinovitzded7f1a2006-08-15 17:34:52 +03001644
Greg Kroah-Hartman05321932008-03-06 00:13:36 +01001645 return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
Ishai Rabinovitzded7f1a2006-08-15 17:34:52 +03001646}
1647
Tony Jonesee959b02008-02-22 00:13:36 +01001648static DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL);
1649static DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL);
1650static DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL);
1651static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL);
1652static DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL);
1653static DEVICE_ATTR(orig_dgid, S_IRUGO, show_orig_dgid, NULL);
Bart Van Assche89de7482010-08-03 14:08:45 +00001654static DEVICE_ATTR(req_lim, S_IRUGO, show_req_lim, NULL);
Tony Jonesee959b02008-02-22 00:13:36 +01001655static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL);
1656static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL);
1657static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001658
Tony Jonesee959b02008-02-22 00:13:36 +01001659static struct device_attribute *srp_host_attrs[] = {
1660 &dev_attr_id_ext,
1661 &dev_attr_ioc_guid,
1662 &dev_attr_service_id,
1663 &dev_attr_pkey,
1664 &dev_attr_dgid,
1665 &dev_attr_orig_dgid,
Bart Van Assche89de7482010-08-03 14:08:45 +00001666 &dev_attr_req_lim,
Tony Jonesee959b02008-02-22 00:13:36 +01001667 &dev_attr_zero_req_lim,
1668 &dev_attr_local_ib_port,
1669 &dev_attr_local_ib_device,
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001670 NULL
1671};
1672
Roland Dreieraef9ec32005-11-02 14:07:13 -08001673static struct scsi_host_template srp_template = {
1674 .module = THIS_MODULE,
Roland Dreierb7f008f2007-05-06 21:18:11 -07001675 .name = "InfiniBand SRP initiator",
1676 .proc_name = DRV_NAME,
Roland Dreieraef9ec32005-11-02 14:07:13 -08001677 .info = srp_target_info,
1678 .queuecommand = srp_queuecommand,
1679 .eh_abort_handler = srp_abort,
1680 .eh_device_reset_handler = srp_reset_device,
1681 .eh_host_reset_handler = srp_reset_host,
Bart Van Asschedd5e6e32010-08-30 19:27:20 +00001682 .can_queue = SRP_CMD_SQ_SIZE,
Roland Dreieraef9ec32005-11-02 14:07:13 -08001683 .this_id = -1,
Bart Van Asschedd5e6e32010-08-30 19:27:20 +00001684 .cmd_per_lun = SRP_CMD_SQ_SIZE,
Roland Dreier6ecb0c82006-03-20 10:08:23 -08001685 .use_clustering = ENABLE_CLUSTERING,
1686 .shost_attrs = srp_host_attrs
Roland Dreieraef9ec32005-11-02 14:07:13 -08001687};
1688
1689static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
1690{
FUJITA Tomonori32368222007-06-27 16:33:12 +09001691 struct srp_rport_identifiers ids;
1692 struct srp_rport *rport;
1693
Roland Dreieraef9ec32005-11-02 14:07:13 -08001694 sprintf(target->target_name, "SRP.T10:%016llX",
1695 (unsigned long long) be64_to_cpu(target->id_ext));
1696
Greg Kroah-Hartman05321932008-03-06 00:13:36 +01001697 if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device))
Roland Dreieraef9ec32005-11-02 14:07:13 -08001698 return -ENODEV;
1699
FUJITA Tomonori32368222007-06-27 16:33:12 +09001700 memcpy(ids.port_id, &target->id_ext, 8);
1701 memcpy(ids.port_id + 8, &target->ioc_guid, 8);
FUJITA Tomonoriaebd5e42007-07-11 15:08:15 +09001702 ids.roles = SRP_RPORT_ROLE_TARGET;
FUJITA Tomonori32368222007-06-27 16:33:12 +09001703 rport = srp_rport_add(target->scsi_host, &ids);
1704 if (IS_ERR(rport)) {
1705 scsi_remove_host(target->scsi_host);
1706 return PTR_ERR(rport);
1707 }
1708
Matthew Wilcoxb3589fd2006-06-17 20:37:30 -07001709 spin_lock(&host->target_lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001710 list_add_tail(&target->list, &host->target_list);
Matthew Wilcoxb3589fd2006-06-17 20:37:30 -07001711 spin_unlock(&host->target_lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001712
1713 target->state = SRP_TARGET_LIVE;
1714
Roland Dreieraef9ec32005-11-02 14:07:13 -08001715 scsi_scan_target(&target->scsi_host->shost_gendev,
Matthew Wilcox1962a4a2006-06-17 20:37:30 -07001716 0, target->scsi_id, SCAN_WILD_CARD, 0);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001717
1718 return 0;
1719}
1720
Tony Jonesee959b02008-02-22 00:13:36 +01001721static void srp_release_dev(struct device *dev)
Roland Dreieraef9ec32005-11-02 14:07:13 -08001722{
1723 struct srp_host *host =
Tony Jonesee959b02008-02-22 00:13:36 +01001724 container_of(dev, struct srp_host, dev);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001725
1726 complete(&host->released);
1727}
1728
1729static struct class srp_class = {
1730 .name = "infiniband_srp",
Tony Jonesee959b02008-02-22 00:13:36 +01001731 .dev_release = srp_release_dev
Roland Dreieraef9ec32005-11-02 14:07:13 -08001732};
1733
1734/*
1735 * Target ports are added by writing
1736 *
1737 * id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,dgid=<dest GID>,
1738 * pkey=<P_Key>,service_id=<service ID>
1739 *
1740 * to the add_target sysfs attribute.
1741 */
1742enum {
1743 SRP_OPT_ERR = 0,
1744 SRP_OPT_ID_EXT = 1 << 0,
1745 SRP_OPT_IOC_GUID = 1 << 1,
1746 SRP_OPT_DGID = 1 << 2,
1747 SRP_OPT_PKEY = 1 << 3,
1748 SRP_OPT_SERVICE_ID = 1 << 4,
1749 SRP_OPT_MAX_SECT = 1 << 5,
Vu Pham52fb2b502006-06-17 20:37:31 -07001750 SRP_OPT_MAX_CMD_PER_LUN = 1 << 6,
Ramachandra K0c0450db2006-06-17 20:37:38 -07001751 SRP_OPT_IO_CLASS = 1 << 7,
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +02001752 SRP_OPT_INITIATOR_EXT = 1 << 8,
Roland Dreieraef9ec32005-11-02 14:07:13 -08001753 SRP_OPT_ALL = (SRP_OPT_ID_EXT |
1754 SRP_OPT_IOC_GUID |
1755 SRP_OPT_DGID |
1756 SRP_OPT_PKEY |
1757 SRP_OPT_SERVICE_ID),
1758};
1759
Steven Whitehousea447c092008-10-13 10:46:57 +01001760static const match_table_t srp_opt_tokens = {
Vu Pham52fb2b502006-06-17 20:37:31 -07001761 { SRP_OPT_ID_EXT, "id_ext=%s" },
1762 { SRP_OPT_IOC_GUID, "ioc_guid=%s" },
1763 { SRP_OPT_DGID, "dgid=%s" },
1764 { SRP_OPT_PKEY, "pkey=%x" },
1765 { SRP_OPT_SERVICE_ID, "service_id=%s" },
1766 { SRP_OPT_MAX_SECT, "max_sect=%d" },
1767 { SRP_OPT_MAX_CMD_PER_LUN, "max_cmd_per_lun=%d" },
Ramachandra K0c0450db2006-06-17 20:37:38 -07001768 { SRP_OPT_IO_CLASS, "io_class=%x" },
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +02001769 { SRP_OPT_INITIATOR_EXT, "initiator_ext=%s" },
Vu Pham52fb2b502006-06-17 20:37:31 -07001770 { SRP_OPT_ERR, NULL }
Roland Dreieraef9ec32005-11-02 14:07:13 -08001771};
1772
1773static int srp_parse_options(const char *buf, struct srp_target_port *target)
1774{
1775 char *options, *sep_opt;
1776 char *p;
1777 char dgid[3];
1778 substring_t args[MAX_OPT_ARGS];
1779 int opt_mask = 0;
1780 int token;
1781 int ret = -EINVAL;
1782 int i;
1783
1784 options = kstrdup(buf, GFP_KERNEL);
1785 if (!options)
1786 return -ENOMEM;
1787
1788 sep_opt = options;
1789 while ((p = strsep(&sep_opt, ",")) != NULL) {
1790 if (!*p)
1791 continue;
1792
1793 token = match_token(p, srp_opt_tokens, args);
1794 opt_mask |= token;
1795
1796 switch (token) {
1797 case SRP_OPT_ID_EXT:
1798 p = match_strdup(args);
Ishai Rabinovitza20f3a62007-01-16 17:20:25 +02001799 if (!p) {
1800 ret = -ENOMEM;
1801 goto out;
1802 }
Roland Dreieraef9ec32005-11-02 14:07:13 -08001803 target->id_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));
1804 kfree(p);
1805 break;
1806
1807 case SRP_OPT_IOC_GUID:
1808 p = match_strdup(args);
Ishai Rabinovitza20f3a62007-01-16 17:20:25 +02001809 if (!p) {
1810 ret = -ENOMEM;
1811 goto out;
1812 }
Roland Dreieraef9ec32005-11-02 14:07:13 -08001813 target->ioc_guid = cpu_to_be64(simple_strtoull(p, NULL, 16));
1814 kfree(p);
1815 break;
1816
1817 case SRP_OPT_DGID:
1818 p = match_strdup(args);
Ishai Rabinovitza20f3a62007-01-16 17:20:25 +02001819 if (!p) {
1820 ret = -ENOMEM;
1821 goto out;
1822 }
Roland Dreieraef9ec32005-11-02 14:07:13 -08001823 if (strlen(p) != 32) {
1824 printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);
Roland Dreierce1823f2006-04-03 09:31:04 -07001825 kfree(p);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001826 goto out;
1827 }
1828
1829 for (i = 0; i < 16; ++i) {
1830 strlcpy(dgid, p + i * 2, 3);
1831 target->path.dgid.raw[i] = simple_strtoul(dgid, NULL, 16);
1832 }
Roland Dreierbf17c1c2006-03-20 10:08:25 -08001833 kfree(p);
Ishai Rabinovitz3633b3d2007-05-06 21:18:11 -07001834 memcpy(target->orig_dgid, target->path.dgid.raw, 16);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001835 break;
1836
1837 case SRP_OPT_PKEY:
1838 if (match_hex(args, &token)) {
1839 printk(KERN_WARNING PFX "bad P_Key parameter '%s'\n", p);
1840 goto out;
1841 }
1842 target->path.pkey = cpu_to_be16(token);
1843 break;
1844
1845 case SRP_OPT_SERVICE_ID:
1846 p = match_strdup(args);
Ishai Rabinovitza20f3a62007-01-16 17:20:25 +02001847 if (!p) {
1848 ret = -ENOMEM;
1849 goto out;
1850 }
Roland Dreieraef9ec32005-11-02 14:07:13 -08001851 target->service_id = cpu_to_be64(simple_strtoull(p, NULL, 16));
Sean Hefty247e0202007-08-08 15:51:18 -07001852 target->path.service_id = target->service_id;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001853 kfree(p);
1854 break;
1855
1856 case SRP_OPT_MAX_SECT:
1857 if (match_int(args, &token)) {
1858 printk(KERN_WARNING PFX "bad max sect parameter '%s'\n", p);
1859 goto out;
1860 }
1861 target->scsi_host->max_sectors = token;
1862 break;
1863
Vu Pham52fb2b502006-06-17 20:37:31 -07001864 case SRP_OPT_MAX_CMD_PER_LUN:
1865 if (match_int(args, &token)) {
1866 printk(KERN_WARNING PFX "bad max cmd_per_lun parameter '%s'\n", p);
1867 goto out;
1868 }
Bart Van Asschedd5e6e32010-08-30 19:27:20 +00001869 target->scsi_host->cmd_per_lun = min(token, SRP_CMD_SQ_SIZE);
Vu Pham52fb2b502006-06-17 20:37:31 -07001870 break;
1871
Ramachandra K0c0450db2006-06-17 20:37:38 -07001872 case SRP_OPT_IO_CLASS:
1873 if (match_hex(args, &token)) {
1874 printk(KERN_WARNING PFX "bad IO class parameter '%s' \n", p);
1875 goto out;
1876 }
1877 if (token != SRP_REV10_IB_IO_CLASS &&
1878 token != SRP_REV16A_IB_IO_CLASS) {
1879 printk(KERN_WARNING PFX "unknown IO class parameter value"
1880 " %x specified (use %x or %x).\n",
1881 token, SRP_REV10_IB_IO_CLASS, SRP_REV16A_IB_IO_CLASS);
1882 goto out;
1883 }
1884 target->io_class = token;
1885 break;
1886
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +02001887 case SRP_OPT_INITIATOR_EXT:
1888 p = match_strdup(args);
Ishai Rabinovitza20f3a62007-01-16 17:20:25 +02001889 if (!p) {
1890 ret = -ENOMEM;
1891 goto out;
1892 }
Ishai Rabinovitz01cb9bc2006-10-04 15:28:56 +02001893 target->initiator_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));
1894 kfree(p);
1895 break;
1896
Roland Dreieraef9ec32005-11-02 14:07:13 -08001897 default:
1898 printk(KERN_WARNING PFX "unknown parameter or missing value "
1899 "'%s' in target creation request\n", p);
1900 goto out;
1901 }
1902 }
1903
1904 if ((opt_mask & SRP_OPT_ALL) == SRP_OPT_ALL)
1905 ret = 0;
1906 else
1907 for (i = 0; i < ARRAY_SIZE(srp_opt_tokens); ++i)
1908 if ((srp_opt_tokens[i].token & SRP_OPT_ALL) &&
1909 !(srp_opt_tokens[i].token & opt_mask))
1910 printk(KERN_WARNING PFX "target creation request is "
1911 "missing parameter '%s'\n",
1912 srp_opt_tokens[i].pattern);
1913
1914out:
1915 kfree(options);
1916 return ret;
1917}
1918
Tony Jonesee959b02008-02-22 00:13:36 +01001919static ssize_t srp_create_target(struct device *dev,
1920 struct device_attribute *attr,
Roland Dreieraef9ec32005-11-02 14:07:13 -08001921 const char *buf, size_t count)
1922{
1923 struct srp_host *host =
Tony Jonesee959b02008-02-22 00:13:36 +01001924 container_of(dev, struct srp_host, dev);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001925 struct Scsi_Host *target_host;
1926 struct srp_target_port *target;
1927 int ret;
1928 int i;
1929
1930 target_host = scsi_host_alloc(&srp_template,
1931 sizeof (struct srp_target_port));
1932 if (!target_host)
1933 return -ENOMEM;
1934
FUJITA Tomonori32368222007-06-27 16:33:12 +09001935 target_host->transportt = ib_srp_transport_template;
Arne Redlich3c8edf02006-11-15 12:43:00 +01001936 target_host->max_lun = SRP_MAX_LUN;
1937 target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
Roland Dreier5f068992005-11-11 14:06:01 -08001938
Roland Dreieraef9ec32005-11-02 14:07:13 -08001939 target = host_to_target(target_host);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001940
Ramachandra K0c0450db2006-06-17 20:37:38 -07001941 target->io_class = SRP_REV16A_IB_IO_CLASS;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001942 target->scsi_host = target_host;
1943 target->srp_host = host;
David Dillow9af76272010-11-26 15:34:46 -05001944 target->lkey = host->srp_dev->mr->lkey;
1945 target->rkey = host->srp_dev->mr->rkey;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001946
Bart Van Asschee9684672010-11-26 15:08:38 -05001947 spin_lock_init(&target->lock);
Bart Van Asschedcb4cb82010-11-26 13:22:48 -05001948 INIT_LIST_HEAD(&target->free_tx);
Roland Dreierd945e1d2006-05-09 10:50:28 -07001949 INIT_LIST_HEAD(&target->free_reqs);
Bart Van Asschedd5e6e32010-08-30 19:27:20 +00001950 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
Roland Dreierd945e1d2006-05-09 10:50:28 -07001951 target->req_ring[i].index = i;
1952 list_add_tail(&target->req_ring[i].list, &target->free_reqs);
1953 }
Roland Dreieraef9ec32005-11-02 14:07:13 -08001954
1955 ret = srp_parse_options(buf, target);
1956 if (ret)
1957 goto err;
1958
Roland Dreier969a60f2008-07-14 23:48:43 -07001959 ib_query_gid(host->srp_dev->dev, host->port, 0, &target->path.sgid);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001960
David Dillow7aa54bd2008-01-07 18:23:41 -05001961 shost_printk(KERN_DEBUG, target->scsi_host, PFX
1962 "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
Harvey Harrison5b095d9892008-10-29 12:52:50 -07001963 "service_id %016llx dgid %pI6\n",
Roland Dreieraef9ec32005-11-02 14:07:13 -08001964 (unsigned long long) be64_to_cpu(target->id_ext),
1965 (unsigned long long) be64_to_cpu(target->ioc_guid),
1966 be16_to_cpu(target->path.pkey),
1967 (unsigned long long) be64_to_cpu(target->service_id),
Harvey Harrison8867cd72008-10-28 22:36:33 -07001968 target->path.dgid.raw);
Roland Dreieraef9ec32005-11-02 14:07:13 -08001969
1970 ret = srp_create_target_ib(target);
1971 if (ret)
1972 goto err;
1973
David Dillow9fe4bcf2008-01-08 17:08:52 -05001974 ret = srp_new_cm_id(target);
1975 if (ret)
Roland Dreieraef9ec32005-11-02 14:07:13 -08001976 goto err_free;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001977
Ishai Rabinovitz1033ff62007-01-16 17:26:22 +02001978 target->qp_in_error = 0;
Roland Dreieraef9ec32005-11-02 14:07:13 -08001979 ret = srp_connect_target(target);
1980 if (ret) {
David Dillow7aa54bd2008-01-07 18:23:41 -05001981 shost_printk(KERN_ERR, target->scsi_host,
1982 PFX "Connection failed\n");
Roland Dreieraef9ec32005-11-02 14:07:13 -08001983 goto err_cm_id;
1984 }
1985
1986 ret = srp_add_target(host, target);
1987 if (ret)
1988 goto err_disconnect;
1989
1990 return count;
1991
1992err_disconnect:
1993 srp_disconnect_target(target);
1994
1995err_cm_id:
1996 ib_destroy_cm_id(target->cm_id);
1997
1998err_free:
1999 srp_free_target_ib(target);
2000
2001err:
2002 scsi_host_put(target_host);
2003
2004 return ret;
2005}
2006
Tony Jonesee959b02008-02-22 00:13:36 +01002007static DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002008
Tony Jonesee959b02008-02-22 00:13:36 +01002009static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
2010 char *buf)
Roland Dreieraef9ec32005-11-02 14:07:13 -08002011{
Tony Jonesee959b02008-02-22 00:13:36 +01002012 struct srp_host *host = container_of(dev, struct srp_host, dev);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002013
Greg Kroah-Hartman05321932008-03-06 00:13:36 +01002014 return sprintf(buf, "%s\n", host->srp_dev->dev->name);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002015}
2016
Tony Jonesee959b02008-02-22 00:13:36 +01002017static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002018
Tony Jonesee959b02008-02-22 00:13:36 +01002019static ssize_t show_port(struct device *dev, struct device_attribute *attr,
2020 char *buf)
Roland Dreieraef9ec32005-11-02 14:07:13 -08002021{
Tony Jonesee959b02008-02-22 00:13:36 +01002022 struct srp_host *host = container_of(dev, struct srp_host, dev);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002023
2024 return sprintf(buf, "%d\n", host->port);
2025}
2026
Tony Jonesee959b02008-02-22 00:13:36 +01002027static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002028
Roland Dreierf5358a12006-06-17 20:37:29 -07002029static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
Roland Dreieraef9ec32005-11-02 14:07:13 -08002030{
2031 struct srp_host *host;
2032
2033 host = kzalloc(sizeof *host, GFP_KERNEL);
2034 if (!host)
2035 return NULL;
2036
2037 INIT_LIST_HEAD(&host->target_list);
Matthew Wilcoxb3589fd2006-06-17 20:37:30 -07002038 spin_lock_init(&host->target_lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002039 init_completion(&host->released);
Greg Kroah-Hartman05321932008-03-06 00:13:36 +01002040 host->srp_dev = device;
Roland Dreieraef9ec32005-11-02 14:07:13 -08002041 host->port = port;
2042
Tony Jonesee959b02008-02-22 00:13:36 +01002043 host->dev.class = &srp_class;
2044 host->dev.parent = device->dev->dma_device;
Kay Sieversd927e382009-01-06 10:44:39 -08002045 dev_set_name(&host->dev, "srp-%s-%d", device->dev->name, port);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002046
Tony Jonesee959b02008-02-22 00:13:36 +01002047 if (device_register(&host->dev))
Roland Dreierf5358a12006-06-17 20:37:29 -07002048 goto free_host;
Tony Jonesee959b02008-02-22 00:13:36 +01002049 if (device_create_file(&host->dev, &dev_attr_add_target))
Roland Dreieraef9ec32005-11-02 14:07:13 -08002050 goto err_class;
Tony Jonesee959b02008-02-22 00:13:36 +01002051 if (device_create_file(&host->dev, &dev_attr_ibdev))
Roland Dreieraef9ec32005-11-02 14:07:13 -08002052 goto err_class;
Tony Jonesee959b02008-02-22 00:13:36 +01002053 if (device_create_file(&host->dev, &dev_attr_port))
Roland Dreieraef9ec32005-11-02 14:07:13 -08002054 goto err_class;
2055
2056 return host;
2057
2058err_class:
Tony Jonesee959b02008-02-22 00:13:36 +01002059 device_unregister(&host->dev);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002060
Roland Dreierf5358a12006-06-17 20:37:29 -07002061free_host:
Roland Dreieraef9ec32005-11-02 14:07:13 -08002062 kfree(host);
2063
2064 return NULL;
2065}
2066
2067static void srp_add_one(struct ib_device *device)
2068{
Roland Dreierf5358a12006-06-17 20:37:29 -07002069 struct srp_device *srp_dev;
2070 struct ib_device_attr *dev_attr;
2071 struct ib_fmr_pool_param fmr_param;
Roland Dreieraef9ec32005-11-02 14:07:13 -08002072 struct srp_host *host;
Roland Dreieraef9ec32005-11-02 14:07:13 -08002073 int s, e, p;
2074
Roland Dreierf5358a12006-06-17 20:37:29 -07002075 dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
2076 if (!dev_attr)
Sean Heftycf311cd2006-01-10 07:39:34 -08002077 return;
Roland Dreieraef9ec32005-11-02 14:07:13 -08002078
Roland Dreierf5358a12006-06-17 20:37:29 -07002079 if (ib_query_device(device, dev_attr)) {
2080 printk(KERN_WARNING PFX "Query device failed for %s\n",
2081 device->name);
2082 goto free_attr;
2083 }
2084
2085 srp_dev = kmalloc(sizeof *srp_dev, GFP_KERNEL);
2086 if (!srp_dev)
2087 goto free_attr;
2088
2089 /*
2090 * Use the smallest page size supported by the HCA, down to a
2091 * minimum of 512 bytes (which is the smallest sector that a
2092 * SCSI command will ever carry).
2093 */
2094 srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1);
2095 srp_dev->fmr_page_size = 1 << srp_dev->fmr_page_shift;
Roland Dreierbf628dc2006-12-15 14:01:49 -08002096 srp_dev->fmr_page_mask = ~((u64) srp_dev->fmr_page_size - 1);
Roland Dreierf5358a12006-06-17 20:37:29 -07002097
2098 INIT_LIST_HEAD(&srp_dev->dev_list);
2099
2100 srp_dev->dev = device;
2101 srp_dev->pd = ib_alloc_pd(device);
2102 if (IS_ERR(srp_dev->pd))
2103 goto free_dev;
2104
2105 srp_dev->mr = ib_get_dma_mr(srp_dev->pd,
2106 IB_ACCESS_LOCAL_WRITE |
2107 IB_ACCESS_REMOTE_READ |
2108 IB_ACCESS_REMOTE_WRITE);
2109 if (IS_ERR(srp_dev->mr))
2110 goto err_pd;
2111
2112 memset(&fmr_param, 0, sizeof fmr_param);
2113 fmr_param.pool_size = SRP_FMR_POOL_SIZE;
2114 fmr_param.dirty_watermark = SRP_FMR_DIRTY_SIZE;
2115 fmr_param.cache = 1;
2116 fmr_param.max_pages_per_fmr = SRP_FMR_SIZE;
2117 fmr_param.page_shift = srp_dev->fmr_page_shift;
2118 fmr_param.access = (IB_ACCESS_LOCAL_WRITE |
2119 IB_ACCESS_REMOTE_WRITE |
2120 IB_ACCESS_REMOTE_READ);
2121
2122 srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param);
2123 if (IS_ERR(srp_dev->fmr_pool))
2124 srp_dev->fmr_pool = NULL;
Roland Dreieraef9ec32005-11-02 14:07:13 -08002125
Tom Tucker07ebafb2006-08-03 16:02:42 -05002126 if (device->node_type == RDMA_NODE_IB_SWITCH) {
Roland Dreieraef9ec32005-11-02 14:07:13 -08002127 s = 0;
2128 e = 0;
2129 } else {
2130 s = 1;
2131 e = device->phys_port_cnt;
2132 }
2133
2134 for (p = s; p <= e; ++p) {
Roland Dreierf5358a12006-06-17 20:37:29 -07002135 host = srp_add_port(srp_dev, p);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002136 if (host)
Roland Dreierf5358a12006-06-17 20:37:29 -07002137 list_add_tail(&host->list, &srp_dev->dev_list);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002138 }
2139
Roland Dreierf5358a12006-06-17 20:37:29 -07002140 ib_set_client_data(device, &srp_client, srp_dev);
2141
2142 goto free_attr;
2143
2144err_pd:
2145 ib_dealloc_pd(srp_dev->pd);
2146
2147free_dev:
2148 kfree(srp_dev);
2149
2150free_attr:
2151 kfree(dev_attr);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002152}
2153
2154static void srp_remove_one(struct ib_device *device)
2155{
Roland Dreierf5358a12006-06-17 20:37:29 -07002156 struct srp_device *srp_dev;
Roland Dreieraef9ec32005-11-02 14:07:13 -08002157 struct srp_host *host, *tmp_host;
2158 LIST_HEAD(target_list);
2159 struct srp_target_port *target, *tmp_target;
Roland Dreieraef9ec32005-11-02 14:07:13 -08002160
Roland Dreierf5358a12006-06-17 20:37:29 -07002161 srp_dev = ib_get_client_data(device, &srp_client);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002162
Roland Dreierf5358a12006-06-17 20:37:29 -07002163 list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
Tony Jonesee959b02008-02-22 00:13:36 +01002164 device_unregister(&host->dev);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002165 /*
2166 * Wait for the sysfs entry to go away, so that no new
2167 * target ports can be created.
2168 */
2169 wait_for_completion(&host->released);
2170
2171 /*
2172 * Mark all target ports as removed, so we stop queueing
2173 * commands and don't try to reconnect.
2174 */
Matthew Wilcoxb3589fd2006-06-17 20:37:30 -07002175 spin_lock(&host->target_lock);
Matthew Wilcox549c5fc22006-06-17 20:37:30 -07002176 list_for_each_entry(target, &host->target_list, list) {
Bart Van Asschee9684672010-11-26 15:08:38 -05002177 spin_lock_irq(&target->lock);
Ishai Rabinovitz0c5b3952006-06-17 20:37:31 -07002178 target->state = SRP_TARGET_REMOVED;
Bart Van Asschee9684672010-11-26 15:08:38 -05002179 spin_unlock_irq(&target->lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002180 }
Matthew Wilcoxb3589fd2006-06-17 20:37:30 -07002181 spin_unlock(&host->target_lock);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002182
2183 /*
2184 * Wait for any reconnection tasks that may have
2185 * started before we marked our target ports as
2186 * removed, and any target port removal tasks.
2187 */
Tejun Heof0626712010-10-19 15:24:36 +00002188 flush_workqueue(ib_wq);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002189
2190 list_for_each_entry_safe(target, tmp_target,
2191 &host->target_list, list) {
David Dillowb0e47c82008-01-03 10:25:27 -08002192 srp_remove_host(target->scsi_host);
Dave Dillowad696982008-01-03 22:35:41 -05002193 scsi_remove_host(target->scsi_host);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002194 srp_disconnect_target(target);
2195 ib_destroy_cm_id(target->cm_id);
2196 srp_free_target_ib(target);
2197 scsi_host_put(target->scsi_host);
2198 }
2199
Roland Dreieraef9ec32005-11-02 14:07:13 -08002200 kfree(host);
2201 }
2202
Roland Dreierf5358a12006-06-17 20:37:29 -07002203 if (srp_dev->fmr_pool)
2204 ib_destroy_fmr_pool(srp_dev->fmr_pool);
2205 ib_dereg_mr(srp_dev->mr);
2206 ib_dealloc_pd(srp_dev->pd);
2207
2208 kfree(srp_dev);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002209}
2210
FUJITA Tomonori32368222007-06-27 16:33:12 +09002211static struct srp_function_template ib_srp_transport_functions = {
2212};
2213
Roland Dreieraef9ec32005-11-02 14:07:13 -08002214static int __init srp_init_module(void)
2215{
2216 int ret;
2217
Bart Van Asschedcb4cb82010-11-26 13:22:48 -05002218 BUILD_BUG_ON(FIELD_SIZEOF(struct ib_wc, wr_id) < sizeof(void *));
Bart Van Asschedd5e6e32010-08-30 19:27:20 +00002219
David Dillow1e89a192008-04-16 21:01:12 -07002220 if (srp_sg_tablesize > 255) {
2221 printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
2222 srp_sg_tablesize = 255;
2223 }
2224
FUJITA Tomonori32368222007-06-27 16:33:12 +09002225 ib_srp_transport_template =
2226 srp_attach_transport(&ib_srp_transport_functions);
2227 if (!ib_srp_transport_template)
2228 return -ENOMEM;
2229
Vu Pham74b0a152006-06-17 20:37:32 -07002230 srp_template.sg_tablesize = srp_sg_tablesize;
2231 srp_max_iu_len = (sizeof (struct srp_cmd) +
2232 sizeof (struct srp_indirect_buf) +
2233 srp_sg_tablesize * 16);
2234
Roland Dreieraef9ec32005-11-02 14:07:13 -08002235 ret = class_register(&srp_class);
2236 if (ret) {
2237 printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");
FUJITA Tomonori32368222007-06-27 16:33:12 +09002238 srp_release_transport(ib_srp_transport_template);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002239 return ret;
2240 }
2241
Michael S. Tsirkinc1a0b232006-08-21 16:40:12 -07002242 ib_sa_register_client(&srp_sa_client);
2243
Roland Dreieraef9ec32005-11-02 14:07:13 -08002244 ret = ib_register_client(&srp_client);
2245 if (ret) {
2246 printk(KERN_ERR PFX "couldn't register IB client\n");
FUJITA Tomonori32368222007-06-27 16:33:12 +09002247 srp_release_transport(ib_srp_transport_template);
Michael S. Tsirkinc1a0b232006-08-21 16:40:12 -07002248 ib_sa_unregister_client(&srp_sa_client);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002249 class_unregister(&srp_class);
2250 return ret;
2251 }
2252
2253 return 0;
2254}
2255
2256static void __exit srp_cleanup_module(void)
2257{
2258 ib_unregister_client(&srp_client);
Michael S. Tsirkinc1a0b232006-08-21 16:40:12 -07002259 ib_sa_unregister_client(&srp_sa_client);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002260 class_unregister(&srp_class);
FUJITA Tomonori32368222007-06-27 16:33:12 +09002261 srp_release_transport(ib_srp_transport_template);
Roland Dreieraef9ec32005-11-02 14:07:13 -08002262}
2263
2264module_init(srp_init_module);
2265module_exit(srp_cleanup_module);