blob: 1b41e6776152a446b5fda48a1db3fd4594083b99 [file] [log] [blame]
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001/*******************************************************************************
2 *
3 * This file contains the Linux/SCSI LLD virtual SCSI initiator driver
4 * for emulated SAS initiator ports
5 *
Nicholas Bellinger4c762512013-09-05 15:29:12 -07006 * © Copyright 2011-2013 Datera, Inc.
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07007 *
8 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
9 *
10 * Author: Nicholas A. Bellinger <nab@risingtidesystems.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 ****************************************************************************/
22
23#include <linux/module.h>
24#include <linux/moduleparam.h>
25#include <linux/init.h>
26#include <linux/slab.h>
27#include <linux/types.h>
28#include <linux/configfs.h>
29#include <scsi/scsi.h>
30#include <scsi/scsi_tcq.h>
31#include <scsi/scsi_host.h>
32#include <scsi/scsi_device.h>
33#include <scsi/scsi_cmnd.h>
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070034
35#include <target/target_core_base.h>
Christoph Hellwigc4795fb2011-11-16 09:46:48 -050036#include <target/target_core_fabric.h>
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070037#include <target/target_core_fabric_configfs.h>
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070038#include <target/target_core_configfs.h>
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070039
40#include "tcm_loop.h"
41
42#define to_tcm_loop_hba(hba) container_of(hba, struct tcm_loop_hba, dev)
43
44/* Local pointer to allocated TCM configfs fabric module */
45static struct target_fabric_configfs *tcm_loop_fabric_configfs;
46
Christoph Hellwigafe2cb72012-02-02 17:04:41 -050047static struct workqueue_struct *tcm_loop_workqueue;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070048static struct kmem_cache *tcm_loop_cmd_cache;
49
50static int tcm_loop_hba_no_cnt;
51
Christoph Hellwig16786452012-02-02 17:04:42 -050052static int tcm_loop_queue_status(struct se_cmd *se_cmd);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070053
54/*
55 * Called from struct target_core_fabric_ops->check_stop_free()
56 */
Nicholas Bellinger88dd9e22011-11-02 03:33:16 -070057static int tcm_loop_check_stop_free(struct se_cmd *se_cmd)
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070058{
59 /*
60 * Do not release struct se_cmd's containing a valid TMR
61 * pointer. These will be released directly in tcm_loop_device_reset()
62 * with transport_generic_free_cmd().
63 */
Andy Groverc8e31f22012-01-19 13:39:17 -080064 if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
Nicholas Bellinger88dd9e22011-11-02 03:33:16 -070065 return 0;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070066 /*
67 * Release the struct se_cmd, which will make a callback to release
68 * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd()
69 */
Christoph Hellwig82f1c8a2011-09-13 23:09:01 +020070 transport_generic_free_cmd(se_cmd, 0);
Nicholas Bellinger88dd9e22011-11-02 03:33:16 -070071 return 1;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070072}
73
Christoph Hellwig35462972011-05-31 23:56:57 -040074static void tcm_loop_release_cmd(struct se_cmd *se_cmd)
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070075{
76 struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
77 struct tcm_loop_cmd, tl_se_cmd);
78
79 kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
80}
81
Al Viro8946b072013-03-31 02:01:55 -040082static int tcm_loop_show_info(struct seq_file *m, struct Scsi_Host *host)
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070083{
Al Viro8946b072013-03-31 02:01:55 -040084 seq_printf(m, "tcm_loop_proc_info()\n");
85 return 0;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -070086}
87
88static int tcm_loop_driver_probe(struct device *);
89static int tcm_loop_driver_remove(struct device *);
90
91static int pseudo_lld_bus_match(struct device *dev,
92 struct device_driver *dev_driver)
93{
94 return 1;
95}
96
97static struct bus_type tcm_loop_lld_bus = {
98 .name = "tcm_loop_bus",
99 .match = pseudo_lld_bus_match,
100 .probe = tcm_loop_driver_probe,
101 .remove = tcm_loop_driver_remove,
102};
103
104static struct device_driver tcm_loop_driverfs = {
105 .name = "tcm_loop",
106 .bus = &tcm_loop_lld_bus,
107};
108/*
109 * Used with root_device_register() in tcm_loop_alloc_core_bus() below
110 */
111struct device *tcm_loop_primary;
112
113/*
114 * Copied from drivers/scsi/libfc/fc_fcp.c:fc_change_queue_depth() and
115 * drivers/scsi/libiscsi.c:iscsi_change_queue_depth()
116 */
117static int tcm_loop_change_queue_depth(
118 struct scsi_device *sdev,
119 int depth,
120 int reason)
121{
122 switch (reason) {
123 case SCSI_QDEPTH_DEFAULT:
124 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
125 break;
126 case SCSI_QDEPTH_QFULL:
127 scsi_track_queue_full(sdev, depth);
128 break;
129 case SCSI_QDEPTH_RAMP_UP:
130 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
131 break;
132 default:
133 return -EOPNOTSUPP;
134 }
135 return sdev->queue_depth;
136}
137
Hannes Reinecke969871c2013-10-16 09:12:55 +0200138static int tcm_loop_change_queue_type(struct scsi_device *sdev, int tag)
139{
140 if (sdev->tagged_supported) {
141 scsi_set_tag_type(sdev, tag);
142
143 if (tag)
144 scsi_activate_tcq(sdev, sdev->queue_depth);
145 else
146 scsi_deactivate_tcq(sdev, sdev->queue_depth);
147 } else
148 tag = 0;
149
150 return tag;
151}
152
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700153/*
Christoph Hellwigf872c9f2012-02-02 17:04:40 -0500154 * Locate the SAM Task Attr from struct scsi_cmnd *
155 */
156static int tcm_loop_sam_attr(struct scsi_cmnd *sc)
157{
158 if (sc->device->tagged_supported) {
159 switch (sc->tag) {
160 case HEAD_OF_QUEUE_TAG:
161 return MSG_HEAD_TAG;
162 case ORDERED_QUEUE_TAG:
163 return MSG_ORDERED_TAG;
164 default:
165 break;
166 }
167 }
168
169 return MSG_SIMPLE_TAG;
170}
171
Christoph Hellwigafe2cb72012-02-02 17:04:41 -0500172static void tcm_loop_submission_work(struct work_struct *work)
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700173{
Christoph Hellwigafe2cb72012-02-02 17:04:41 -0500174 struct tcm_loop_cmd *tl_cmd =
175 container_of(work, struct tcm_loop_cmd, work);
176 struct se_cmd *se_cmd = &tl_cmd->tl_se_cmd;
177 struct scsi_cmnd *sc = tl_cmd->sc;
178 struct tcm_loop_nexus *tl_nexus;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700179 struct tcm_loop_hba *tl_hba;
180 struct tcm_loop_tpg *tl_tpg;
Christoph Hellwig16786452012-02-02 17:04:42 -0500181 struct scatterlist *sgl_bidi = NULL;
182 u32 sgl_bidi_count = 0;
Nicholas Bellinger8f9f44f2012-10-01 23:29:49 -0700183 int rc;
Christoph Hellwigf872c9f2012-02-02 17:04:40 -0500184
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700185 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
186 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
Christoph Hellwigafe2cb72012-02-02 17:04:41 -0500187
Nicholas Bellinger0a020432011-10-10 19:44:05 -0700188 /*
189 * Ensure that this tl_tpg reference from the incoming sc->device->id
190 * has already been configured via tcm_loop_make_naa_tpg().
191 */
192 if (!tl_tpg->tl_hba) {
193 set_host_byte(sc, DID_NO_CONNECT);
Christoph Hellwigf872c9f2012-02-02 17:04:40 -0500194 goto out_done;
Nicholas Bellinger0a020432011-10-10 19:44:05 -0700195 }
Hannes Reineckefb2b2842013-10-16 09:12:53 +0200196 if (tl_tpg->tl_transport_status == TCM_TRANSPORT_OFFLINE) {
197 set_host_byte(sc, DID_TRANSPORT_DISRUPTED);
198 goto out_done;
199 }
Christoph Hellwigf872c9f2012-02-02 17:04:40 -0500200 tl_nexus = tl_hba->tl_nexus;
201 if (!tl_nexus) {
202 scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
203 " does not exist\n");
204 set_host_byte(sc, DID_ERROR);
205 goto out_done;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700206 }
Christoph Hellwig16786452012-02-02 17:04:42 -0500207 if (scsi_bidi_cmnd(sc)) {
208 struct scsi_data_buffer *sdb = scsi_in(sc);
209
210 sgl_bidi = sdb->table.sgl;
211 sgl_bidi_count = sdb->table.nents;
Christoph Hellwigf872c9f2012-02-02 17:04:40 -0500212 se_cmd->se_cmd_flags |= SCF_BIDI;
213
Christoph Hellwig16786452012-02-02 17:04:42 -0500214 }
Nicholas Bellinger8f9f44f2012-10-01 23:29:49 -0700215 rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
216 &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
217 scsi_bufflen(sc), tcm_loop_sam_attr(sc),
218 sc->sc_data_direction, 0,
219 scsi_sglist(sc), scsi_sg_count(sc),
220 sgl_bidi, sgl_bidi_count);
221 if (rc < 0) {
Christoph Hellwigf872c9f2012-02-02 17:04:40 -0500222 set_host_byte(sc, DID_NO_CONNECT);
223 goto out_done;
224 }
Christoph Hellwigafe2cb72012-02-02 17:04:41 -0500225 return;
Christoph Hellwigf872c9f2012-02-02 17:04:40 -0500226
227out_done:
228 sc->scsi_done(sc);
Christoph Hellwigafe2cb72012-02-02 17:04:41 -0500229 return;
230}
231
232/*
233 * ->queuecommand can be and usually is called from interrupt context, so
234 * defer the actual submission to a workqueue.
235 */
236static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
237{
238 struct tcm_loop_cmd *tl_cmd;
239
240 pr_debug("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
241 " scsi_buf_len: %u\n", sc->device->host->host_no,
242 sc->device->id, sc->device->channel, sc->device->lun,
243 sc->cmnd[0], scsi_bufflen(sc));
244
245 tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_ATOMIC);
246 if (!tl_cmd) {
247 pr_err("Unable to allocate struct tcm_loop_cmd\n");
248 set_host_byte(sc, DID_ERROR);
249 sc->scsi_done(sc);
250 return 0;
251 }
252
253 tl_cmd->sc = sc;
Hannes Reinecke969871c2013-10-16 09:12:55 +0200254 tl_cmd->sc_cmd_tag = sc->tag;
Christoph Hellwigafe2cb72012-02-02 17:04:41 -0500255 INIT_WORK(&tl_cmd->work, tcm_loop_submission_work);
256 queue_work(tcm_loop_workqueue, &tl_cmd->work);
Christoph Hellwigf872c9f2012-02-02 17:04:40 -0500257 return 0;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700258}
259
260/*
261 * Called from SCSI EH process context to issue a LUN_RESET TMR
262 * to struct scsi_device
263 */
Hannes Reineckea314d702013-10-16 09:12:54 +0200264static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
265 struct tcm_loop_nexus *tl_nexus,
Hannes Reinecke969871c2013-10-16 09:12:55 +0200266 int lun, int task, enum tcm_tmreq_table tmr)
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700267{
268 struct se_cmd *se_cmd = NULL;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700269 struct se_session *se_sess;
Hannes Reineckea314d702013-10-16 09:12:54 +0200270 struct se_portal_group *se_tpg;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700271 struct tcm_loop_cmd *tl_cmd = NULL;
Hannes Reineckea314d702013-10-16 09:12:54 +0200272 struct tcm_loop_tmr *tl_tmr = NULL;
273 int ret = TMR_FUNCTION_FAILED, rc;
274
275 tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
276 if (!tl_cmd) {
277 pr_err("Unable to allocate memory for tl_cmd\n");
278 return ret;
279 }
280
281 tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL);
282 if (!tl_tmr) {
283 pr_err("Unable to allocate memory for tl_tmr\n");
284 goto release;
285 }
286 init_waitqueue_head(&tl_tmr->tl_tmr_wait);
287
288 se_cmd = &tl_cmd->tl_se_cmd;
289 se_tpg = &tl_tpg->tl_se_tpg;
290 se_sess = tl_nexus->se_sess;
291 /*
292 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
293 */
294 transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0,
295 DMA_NONE, MSG_SIMPLE_TAG,
296 &tl_cmd->tl_sense_buf[0]);
297
298 rc = core_tmr_alloc_req(se_cmd, tl_tmr, tmr, GFP_KERNEL);
299 if (rc < 0)
300 goto release;
301
Hannes Reinecke969871c2013-10-16 09:12:55 +0200302 if (tmr == TMR_ABORT_TASK)
303 se_cmd->se_tmr_req->ref_task_tag = task;
304
Hannes Reineckea314d702013-10-16 09:12:54 +0200305 /*
306 * Locate the underlying TCM struct se_lun
307 */
308 if (transport_lookup_tmr_lun(se_cmd, lun) < 0) {
309 ret = TMR_LUN_DOES_NOT_EXIST;
310 goto release;
311 }
312 /*
313 * Queue the TMR to TCM Core and sleep waiting for
314 * tcm_loop_queue_tm_rsp() to wake us up.
315 */
316 transport_generic_handle_tmr(se_cmd);
317 wait_event(tl_tmr->tl_tmr_wait, atomic_read(&tl_tmr->tmr_complete));
318 /*
319 * The TMR LUN_RESET has completed, check the response status and
320 * then release allocations.
321 */
322 ret = se_cmd->se_tmr_req->response;
323release:
324 if (se_cmd)
325 transport_generic_free_cmd(se_cmd, 1);
326 else
327 kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
328 kfree(tl_tmr);
329 return ret;
330}
331
Hannes Reinecke969871c2013-10-16 09:12:55 +0200332static int tcm_loop_abort_task(struct scsi_cmnd *sc)
333{
334 struct tcm_loop_hba *tl_hba;
335 struct tcm_loop_nexus *tl_nexus;
336 struct tcm_loop_tpg *tl_tpg;
337 int ret = FAILED;
338
339 /*
340 * Locate the tcm_loop_hba_t pointer
341 */
342 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
343 /*
344 * Locate the tl_nexus and se_sess pointers
345 */
346 tl_nexus = tl_hba->tl_nexus;
347 if (!tl_nexus) {
348 pr_err("Unable to perform device reset without"
349 " active I_T Nexus\n");
350 return FAILED;
351 }
352
353 /*
354 * Locate the tl_tpg pointer from TargetID in sc->device->id
355 */
356 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
357 ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
358 sc->tag, TMR_ABORT_TASK);
359 return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
360}
361
Hannes Reineckea314d702013-10-16 09:12:54 +0200362/*
363 * Called from SCSI EH process context to issue a LUN_RESET TMR
364 * to struct scsi_device
365 */
366static int tcm_loop_device_reset(struct scsi_cmnd *sc)
367{
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700368 struct tcm_loop_hba *tl_hba;
369 struct tcm_loop_nexus *tl_nexus;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700370 struct tcm_loop_tpg *tl_tpg;
Hannes Reineckea314d702013-10-16 09:12:54 +0200371 int ret = FAILED;
372
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700373 /*
374 * Locate the tcm_loop_hba_t pointer
375 */
376 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
377 /*
378 * Locate the tl_nexus and se_sess pointers
379 */
380 tl_nexus = tl_hba->tl_nexus;
381 if (!tl_nexus) {
Andy Grover6708bb22011-06-08 10:36:43 -0700382 pr_err("Unable to perform device reset without"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700383 " active I_T Nexus\n");
384 return FAILED;
385 }
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700386 /*
Hannes Reineckea314d702013-10-16 09:12:54 +0200387 * Locate the tl_tpg pointer from TargetID in sc->device->id
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700388 */
389 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
Hannes Reinecke969871c2013-10-16 09:12:55 +0200390 ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
391 0, TMR_LUN_RESET);
Hannes Reineckea314d702013-10-16 09:12:54 +0200392 return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700393}
394
Hannes Reinecke8f4a1fb2013-10-16 09:12:56 +0200395static int tcm_loop_target_reset(struct scsi_cmnd *sc)
396{
397 struct tcm_loop_hba *tl_hba;
398 struct tcm_loop_tpg *tl_tpg;
399
400 /*
401 * Locate the tcm_loop_hba_t pointer
402 */
403 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
404 if (!tl_hba) {
405 pr_err("Unable to perform device reset without"
406 " active I_T Nexus\n");
407 return FAILED;
408 }
409 /*
410 * Locate the tl_tpg pointer from TargetID in sc->device->id
411 */
412 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
413 if (tl_tpg) {
414 tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
415 return SUCCESS;
416 }
417 return FAILED;
418}
419
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700420static int tcm_loop_slave_alloc(struct scsi_device *sd)
421{
422 set_bit(QUEUE_FLAG_BIDI, &sd->request_queue->queue_flags);
423 return 0;
424}
425
426static int tcm_loop_slave_configure(struct scsi_device *sd)
427{
Hannes Reinecke969871c2013-10-16 09:12:55 +0200428 if (sd->tagged_supported) {
429 scsi_activate_tcq(sd, sd->queue_depth);
430 scsi_adjust_queue_depth(sd, MSG_SIMPLE_TAG,
431 sd->host->cmd_per_lun);
432 } else {
433 scsi_adjust_queue_depth(sd, 0,
434 sd->host->cmd_per_lun);
435 }
436
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700437 return 0;
438}
439
440static struct scsi_host_template tcm_loop_driver_template = {
Al Viro8946b072013-03-31 02:01:55 -0400441 .show_info = tcm_loop_show_info,
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700442 .proc_name = "tcm_loopback",
443 .name = "TCM_Loopback",
444 .queuecommand = tcm_loop_queuecommand,
445 .change_queue_depth = tcm_loop_change_queue_depth,
Hannes Reinecke969871c2013-10-16 09:12:55 +0200446 .change_queue_type = tcm_loop_change_queue_type,
447 .eh_abort_handler = tcm_loop_abort_task,
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700448 .eh_device_reset_handler = tcm_loop_device_reset,
Hannes Reinecke8f4a1fb2013-10-16 09:12:56 +0200449 .eh_target_reset_handler = tcm_loop_target_reset,
Christoph Hellwig2e88efd2011-11-29 03:20:41 -0500450 .can_queue = 1024,
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700451 .this_id = -1,
Christoph Hellwig2e88efd2011-11-29 03:20:41 -0500452 .sg_tablesize = 256,
453 .cmd_per_lun = 1024,
454 .max_sectors = 0xFFFF,
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700455 .use_clustering = DISABLE_CLUSTERING,
456 .slave_alloc = tcm_loop_slave_alloc,
457 .slave_configure = tcm_loop_slave_configure,
458 .module = THIS_MODULE,
459};
460
461static int tcm_loop_driver_probe(struct device *dev)
462{
463 struct tcm_loop_hba *tl_hba;
464 struct Scsi_Host *sh;
465 int error;
466
467 tl_hba = to_tcm_loop_hba(dev);
468
469 sh = scsi_host_alloc(&tcm_loop_driver_template,
470 sizeof(struct tcm_loop_hba));
471 if (!sh) {
Andy Grover6708bb22011-06-08 10:36:43 -0700472 pr_err("Unable to allocate struct scsi_host\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700473 return -ENODEV;
474 }
475 tl_hba->sh = sh;
476
477 /*
478 * Assign the struct tcm_loop_hba pointer to struct Scsi_Host->hostdata
479 */
480 *((struct tcm_loop_hba **)sh->hostdata) = tl_hba;
481 /*
482 * Setup single ID, Channel and LUN for now..
483 */
484 sh->max_id = 2;
485 sh->max_lun = 0;
486 sh->max_channel = 0;
487 sh->max_cmd_len = TL_SCSI_MAX_CMD_LEN;
488
489 error = scsi_add_host(sh, &tl_hba->dev);
490 if (error) {
Andy Grover6708bb22011-06-08 10:36:43 -0700491 pr_err("%s: scsi_add_host failed\n", __func__);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700492 scsi_host_put(sh);
493 return -ENODEV;
494 }
495 return 0;
496}
497
498static int tcm_loop_driver_remove(struct device *dev)
499{
500 struct tcm_loop_hba *tl_hba;
501 struct Scsi_Host *sh;
502
503 tl_hba = to_tcm_loop_hba(dev);
504 sh = tl_hba->sh;
505
506 scsi_remove_host(sh);
507 scsi_host_put(sh);
508 return 0;
509}
510
511static void tcm_loop_release_adapter(struct device *dev)
512{
513 struct tcm_loop_hba *tl_hba = to_tcm_loop_hba(dev);
514
515 kfree(tl_hba);
516}
517
518/*
519 * Called from tcm_loop_make_scsi_hba() in tcm_loop_configfs.c
520 */
521static int tcm_loop_setup_hba_bus(struct tcm_loop_hba *tl_hba, int tcm_loop_host_id)
522{
523 int ret;
524
525 tl_hba->dev.bus = &tcm_loop_lld_bus;
526 tl_hba->dev.parent = tcm_loop_primary;
527 tl_hba->dev.release = &tcm_loop_release_adapter;
528 dev_set_name(&tl_hba->dev, "tcm_loop_adapter_%d", tcm_loop_host_id);
529
530 ret = device_register(&tl_hba->dev);
531 if (ret) {
Andy Grover6708bb22011-06-08 10:36:43 -0700532 pr_err("device_register() failed for"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700533 " tl_hba->dev: %d\n", ret);
534 return -ENODEV;
535 }
536
537 return 0;
538}
539
540/*
541 * Called from tcm_loop_fabric_init() in tcl_loop_fabric.c to load the emulated
542 * tcm_loop SCSI bus.
543 */
544static int tcm_loop_alloc_core_bus(void)
545{
546 int ret;
547
548 tcm_loop_primary = root_device_register("tcm_loop_0");
549 if (IS_ERR(tcm_loop_primary)) {
Andy Grover6708bb22011-06-08 10:36:43 -0700550 pr_err("Unable to allocate tcm_loop_primary\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700551 return PTR_ERR(tcm_loop_primary);
552 }
553
554 ret = bus_register(&tcm_loop_lld_bus);
555 if (ret) {
Andy Grover6708bb22011-06-08 10:36:43 -0700556 pr_err("bus_register() failed for tcm_loop_lld_bus\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700557 goto dev_unreg;
558 }
559
560 ret = driver_register(&tcm_loop_driverfs);
561 if (ret) {
Andy Grover6708bb22011-06-08 10:36:43 -0700562 pr_err("driver_register() failed for"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700563 "tcm_loop_driverfs\n");
564 goto bus_unreg;
565 }
566
Andy Grover6708bb22011-06-08 10:36:43 -0700567 pr_debug("Initialized TCM Loop Core Bus\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700568 return ret;
569
570bus_unreg:
571 bus_unregister(&tcm_loop_lld_bus);
572dev_unreg:
573 root_device_unregister(tcm_loop_primary);
574 return ret;
575}
576
577static void tcm_loop_release_core_bus(void)
578{
579 driver_unregister(&tcm_loop_driverfs);
580 bus_unregister(&tcm_loop_lld_bus);
581 root_device_unregister(tcm_loop_primary);
582
Andy Grover6708bb22011-06-08 10:36:43 -0700583 pr_debug("Releasing TCM Loop Core BUS\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700584}
585
586static char *tcm_loop_get_fabric_name(void)
587{
588 return "loopback";
589}
590
591static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg)
592{
Jörn Engel8359cf42011-11-24 02:05:51 +0100593 struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700594 struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
595 /*
596 * tl_proto_id is set at tcm_loop_configfs.c:tcm_loop_make_scsi_hba()
597 * time based on the protocol dependent prefix of the passed configfs group.
598 *
599 * Based upon tl_proto_id, TCM_Loop emulates the requested fabric
600 * ProtocolID using target_core_fabric_lib.c symbols.
601 */
602 switch (tl_hba->tl_proto_id) {
603 case SCSI_PROTOCOL_SAS:
604 return sas_get_fabric_proto_ident(se_tpg);
605 case SCSI_PROTOCOL_FCP:
606 return fc_get_fabric_proto_ident(se_tpg);
607 case SCSI_PROTOCOL_ISCSI:
608 return iscsi_get_fabric_proto_ident(se_tpg);
609 default:
Andy Grover6708bb22011-06-08 10:36:43 -0700610 pr_err("Unknown tl_proto_id: 0x%02x, using"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700611 " SAS emulation\n", tl_hba->tl_proto_id);
612 break;
613 }
614
615 return sas_get_fabric_proto_ident(se_tpg);
616}
617
618static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg)
619{
Jörn Engel8359cf42011-11-24 02:05:51 +0100620 struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700621 /*
622 * Return the passed NAA identifier for the SAS Target Port
623 */
624 return &tl_tpg->tl_hba->tl_wwn_address[0];
625}
626
627static u16 tcm_loop_get_tag(struct se_portal_group *se_tpg)
628{
Jörn Engel8359cf42011-11-24 02:05:51 +0100629 struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700630 /*
631 * This Tag is used when forming SCSI Name identifier in EVPD=1 0x83
632 * to represent the SCSI Target Port.
633 */
634 return tl_tpg->tl_tpgt;
635}
636
637static u32 tcm_loop_get_default_depth(struct se_portal_group *se_tpg)
638{
639 return 1;
640}
641
642static u32 tcm_loop_get_pr_transport_id(
643 struct se_portal_group *se_tpg,
644 struct se_node_acl *se_nacl,
645 struct t10_pr_registration *pr_reg,
646 int *format_code,
647 unsigned char *buf)
648{
Jörn Engel8359cf42011-11-24 02:05:51 +0100649 struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700650 struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
651
652 switch (tl_hba->tl_proto_id) {
653 case SCSI_PROTOCOL_SAS:
654 return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
655 format_code, buf);
656 case SCSI_PROTOCOL_FCP:
657 return fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
658 format_code, buf);
659 case SCSI_PROTOCOL_ISCSI:
660 return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
661 format_code, buf);
662 default:
Andy Grover6708bb22011-06-08 10:36:43 -0700663 pr_err("Unknown tl_proto_id: 0x%02x, using"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700664 " SAS emulation\n", tl_hba->tl_proto_id);
665 break;
666 }
667
668 return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
669 format_code, buf);
670}
671
672static u32 tcm_loop_get_pr_transport_id_len(
673 struct se_portal_group *se_tpg,
674 struct se_node_acl *se_nacl,
675 struct t10_pr_registration *pr_reg,
676 int *format_code)
677{
Jörn Engel8359cf42011-11-24 02:05:51 +0100678 struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700679 struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
680
681 switch (tl_hba->tl_proto_id) {
682 case SCSI_PROTOCOL_SAS:
683 return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
684 format_code);
685 case SCSI_PROTOCOL_FCP:
686 return fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
687 format_code);
688 case SCSI_PROTOCOL_ISCSI:
689 return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
690 format_code);
691 default:
Andy Grover6708bb22011-06-08 10:36:43 -0700692 pr_err("Unknown tl_proto_id: 0x%02x, using"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700693 " SAS emulation\n", tl_hba->tl_proto_id);
694 break;
695 }
696
697 return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
698 format_code);
699}
700
701/*
702 * Used for handling SCSI fabric dependent TransportIDs in SPC-3 and above
703 * Persistent Reservation SPEC_I_PT=1 and PROUT REGISTER_AND_MOVE operations.
704 */
705static char *tcm_loop_parse_pr_out_transport_id(
706 struct se_portal_group *se_tpg,
707 const char *buf,
708 u32 *out_tid_len,
709 char **port_nexus_ptr)
710{
Jörn Engel8359cf42011-11-24 02:05:51 +0100711 struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700712 struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
713
714 switch (tl_hba->tl_proto_id) {
715 case SCSI_PROTOCOL_SAS:
716 return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
717 port_nexus_ptr);
718 case SCSI_PROTOCOL_FCP:
719 return fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
720 port_nexus_ptr);
721 case SCSI_PROTOCOL_ISCSI:
722 return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
723 port_nexus_ptr);
724 default:
Andy Grover6708bb22011-06-08 10:36:43 -0700725 pr_err("Unknown tl_proto_id: 0x%02x, using"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700726 " SAS emulation\n", tl_hba->tl_proto_id);
727 break;
728 }
729
730 return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
731 port_nexus_ptr);
732}
733
734/*
735 * Returning (1) here allows for target_core_mod struct se_node_acl to be generated
736 * based upon the incoming fabric dependent SCSI Initiator Port
737 */
738static int tcm_loop_check_demo_mode(struct se_portal_group *se_tpg)
739{
740 return 1;
741}
742
743static int tcm_loop_check_demo_mode_cache(struct se_portal_group *se_tpg)
744{
745 return 0;
746}
747
748/*
749 * Allow I_T Nexus full READ-WRITE access without explict Initiator Node ACLs for
750 * local virtual Linux/SCSI LLD passthrough into VM hypervisor guest
751 */
752static int tcm_loop_check_demo_mode_write_protect(struct se_portal_group *se_tpg)
753{
754 return 0;
755}
756
757/*
758 * Because TCM_Loop does not use explict ACLs and MappedLUNs, this will
759 * never be called for TCM_Loop by target_core_fabric_configfs.c code.
760 * It has been added here as a nop for target_fabric_tf_ops_check()
761 */
762static int tcm_loop_check_prod_mode_write_protect(struct se_portal_group *se_tpg)
763{
764 return 0;
765}
766
767static struct se_node_acl *tcm_loop_tpg_alloc_fabric_acl(
768 struct se_portal_group *se_tpg)
769{
770 struct tcm_loop_nacl *tl_nacl;
771
772 tl_nacl = kzalloc(sizeof(struct tcm_loop_nacl), GFP_KERNEL);
773 if (!tl_nacl) {
Andy Grover6708bb22011-06-08 10:36:43 -0700774 pr_err("Unable to allocate struct tcm_loop_nacl\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700775 return NULL;
776 }
777
778 return &tl_nacl->se_node_acl;
779}
780
781static void tcm_loop_tpg_release_fabric_acl(
782 struct se_portal_group *se_tpg,
783 struct se_node_acl *se_nacl)
784{
785 struct tcm_loop_nacl *tl_nacl = container_of(se_nacl,
786 struct tcm_loop_nacl, se_node_acl);
787
788 kfree(tl_nacl);
789}
790
791static u32 tcm_loop_get_inst_index(struct se_portal_group *se_tpg)
792{
793 return 1;
794}
795
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700796static u32 tcm_loop_sess_get_index(struct se_session *se_sess)
797{
798 return 1;
799}
800
801static void tcm_loop_set_default_node_attributes(struct se_node_acl *se_acl)
802{
803 return;
804}
805
806static u32 tcm_loop_get_task_tag(struct se_cmd *se_cmd)
807{
Hannes Reinecke969871c2013-10-16 09:12:55 +0200808 struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
809 struct tcm_loop_cmd, tl_se_cmd);
810
811 return tl_cmd->sc_cmd_tag;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700812}
813
814static int tcm_loop_get_cmd_state(struct se_cmd *se_cmd)
815{
816 struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
817 struct tcm_loop_cmd, tl_se_cmd);
818
819 return tl_cmd->sc_cmd_state;
820}
821
822static int tcm_loop_shutdown_session(struct se_session *se_sess)
823{
824 return 0;
825}
826
827static void tcm_loop_close_session(struct se_session *se_sess)
828{
829 return;
830};
831
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700832static int tcm_loop_write_pending(struct se_cmd *se_cmd)
833{
834 /*
835 * Since Linux/SCSI has already sent down a struct scsi_cmnd
836 * sc->sc_data_direction of DMA_TO_DEVICE with struct scatterlist array
837 * memory, and memory has already been mapped to struct se_cmd->t_mem_list
838 * format with transport_generic_map_mem_to_cmd().
839 *
840 * We now tell TCM to add this WRITE CDB directly into the TCM storage
841 * object execution queue.
842 */
Christoph Hellwig70baf0a2012-07-08 15:58:39 -0400843 target_execute_cmd(se_cmd);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700844 return 0;
845}
846
847static int tcm_loop_write_pending_status(struct se_cmd *se_cmd)
848{
849 return 0;
850}
851
852static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
853{
854 struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
855 struct tcm_loop_cmd, tl_se_cmd);
856 struct scsi_cmnd *sc = tl_cmd->sc;
857
Andy Grover6708bb22011-06-08 10:36:43 -0700858 pr_debug("tcm_loop_queue_data_in() called for scsi_cmnd: %p"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700859 " cdb: 0x%02x\n", sc, sc->cmnd[0]);
860
861 sc->result = SAM_STAT_GOOD;
862 set_host_byte(sc, DID_OK);
Roland Dreier6cf3fa62012-02-14 15:30:31 -0800863 if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
864 (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
865 scsi_set_resid(sc, se_cmd->residual_count);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700866 sc->scsi_done(sc);
867 return 0;
868}
869
870static int tcm_loop_queue_status(struct se_cmd *se_cmd)
871{
872 struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
873 struct tcm_loop_cmd, tl_se_cmd);
874 struct scsi_cmnd *sc = tl_cmd->sc;
875
Andy Grover6708bb22011-06-08 10:36:43 -0700876 pr_debug("tcm_loop_queue_status() called for scsi_cmnd: %p"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700877 " cdb: 0x%02x\n", sc, sc->cmnd[0]);
878
879 if (se_cmd->sense_buffer &&
880 ((se_cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
881 (se_cmd->se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
882
Andy Grover5951146d2011-07-19 10:26:37 +0000883 memcpy(sc->sense_buffer, se_cmd->sense_buffer,
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700884 SCSI_SENSE_BUFFERSIZE);
885 sc->result = SAM_STAT_CHECK_CONDITION;
886 set_driver_byte(sc, DRIVER_SENSE);
887 } else
888 sc->result = se_cmd->scsi_status;
889
890 set_host_byte(sc, DID_OK);
Roland Dreier6cf3fa62012-02-14 15:30:31 -0800891 if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
892 (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
893 scsi_set_resid(sc, se_cmd->residual_count);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700894 sc->scsi_done(sc);
895 return 0;
896}
897
Joern Engelb79fafa2013-07-03 11:22:17 -0400898static void tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd)
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700899{
900 struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
901 struct tcm_loop_tmr *tl_tmr = se_tmr->fabric_tmr_ptr;
902 /*
903 * The SCSI EH thread will be sleeping on se_tmr->tl_tmr_wait, go ahead
904 * and wake up the wait_queue_head_t in tcm_loop_device_reset()
905 */
906 atomic_set(&tl_tmr->tmr_complete, 1);
907 wake_up(&tl_tmr->tl_tmr_wait);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700908}
909
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700910static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba)
911{
912 switch (tl_hba->tl_proto_id) {
913 case SCSI_PROTOCOL_SAS:
914 return "SAS";
915 case SCSI_PROTOCOL_FCP:
916 return "FCP";
917 case SCSI_PROTOCOL_ISCSI:
918 return "iSCSI";
919 default:
920 break;
921 }
922
923 return "Unknown";
924}
925
926/* Start items for tcm_loop_port_cit */
927
928static int tcm_loop_port_link(
929 struct se_portal_group *se_tpg,
930 struct se_lun *lun)
931{
932 struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
933 struct tcm_loop_tpg, tl_se_tpg);
934 struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
935
936 atomic_inc(&tl_tpg->tl_tpg_port_count);
937 smp_mb__after_atomic_inc();
938 /*
939 * Add Linux/SCSI struct scsi_device by HCTL
940 */
941 scsi_add_device(tl_hba->sh, 0, tl_tpg->tl_tpgt, lun->unpacked_lun);
942
Andy Grover6708bb22011-06-08 10:36:43 -0700943 pr_debug("TCM_Loop_ConfigFS: Port Link Successful\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700944 return 0;
945}
946
947static void tcm_loop_port_unlink(
948 struct se_portal_group *se_tpg,
949 struct se_lun *se_lun)
950{
951 struct scsi_device *sd;
952 struct tcm_loop_hba *tl_hba;
953 struct tcm_loop_tpg *tl_tpg;
954
955 tl_tpg = container_of(se_tpg, struct tcm_loop_tpg, tl_se_tpg);
956 tl_hba = tl_tpg->tl_hba;
957
958 sd = scsi_device_lookup(tl_hba->sh, 0, tl_tpg->tl_tpgt,
959 se_lun->unpacked_lun);
960 if (!sd) {
Andy Grover6708bb22011-06-08 10:36:43 -0700961 pr_err("Unable to locate struct scsi_device for %d:%d:"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700962 "%d\n", 0, tl_tpg->tl_tpgt, se_lun->unpacked_lun);
963 return;
964 }
965 /*
966 * Remove Linux/SCSI struct scsi_device by HCTL
967 */
968 scsi_remove_device(sd);
969 scsi_device_put(sd);
970
971 atomic_dec(&tl_tpg->tl_tpg_port_count);
972 smp_mb__after_atomic_dec();
973
Andy Grover6708bb22011-06-08 10:36:43 -0700974 pr_debug("TCM_Loop_ConfigFS: Port Unlink Successful\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700975}
976
977/* End items for tcm_loop_port_cit */
978
979/* Start items for tcm_loop_nexus_cit */
980
981static int tcm_loop_make_nexus(
982 struct tcm_loop_tpg *tl_tpg,
983 const char *name)
984{
985 struct se_portal_group *se_tpg;
986 struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
987 struct tcm_loop_nexus *tl_nexus;
Dan Carpenter552523d2011-06-15 09:41:33 -0700988 int ret = -ENOMEM;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700989
990 if (tl_tpg->tl_hba->tl_nexus) {
Andy Grover6708bb22011-06-08 10:36:43 -0700991 pr_debug("tl_tpg->tl_hba->tl_nexus already exists\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700992 return -EEXIST;
993 }
994 se_tpg = &tl_tpg->tl_se_tpg;
995
996 tl_nexus = kzalloc(sizeof(struct tcm_loop_nexus), GFP_KERNEL);
997 if (!tl_nexus) {
Andy Grover6708bb22011-06-08 10:36:43 -0700998 pr_err("Unable to allocate struct tcm_loop_nexus\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -0700999 return -ENOMEM;
1000 }
1001 /*
1002 * Initialize the struct se_session pointer
1003 */
1004 tl_nexus->se_sess = transport_init_session();
Dan Carpenter552523d2011-06-15 09:41:33 -07001005 if (IS_ERR(tl_nexus->se_sess)) {
1006 ret = PTR_ERR(tl_nexus->se_sess);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001007 goto out;
Dan Carpenter552523d2011-06-15 09:41:33 -07001008 }
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001009 /*
1010 * Since we are running in 'demo mode' this call with generate a
1011 * struct se_node_acl for the tcm_loop struct se_portal_group with the SCSI
1012 * Initiator port name of the passed configfs group 'name'.
1013 */
1014 tl_nexus->se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
1015 se_tpg, (unsigned char *)name);
1016 if (!tl_nexus->se_sess->se_node_acl) {
1017 transport_free_session(tl_nexus->se_sess);
1018 goto out;
1019 }
1020 /*
1021 * Now, register the SAS I_T Nexus as active with the call to
1022 * transport_register_session()
1023 */
1024 __transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
Andy Grover5951146d2011-07-19 10:26:37 +00001025 tl_nexus->se_sess, tl_nexus);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001026 tl_tpg->tl_hba->tl_nexus = tl_nexus;
Andy Grover6708bb22011-06-08 10:36:43 -07001027 pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001028 " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
1029 name);
1030 return 0;
1031
1032out:
1033 kfree(tl_nexus);
Dan Carpenter552523d2011-06-15 09:41:33 -07001034 return ret;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001035}
1036
1037static int tcm_loop_drop_nexus(
1038 struct tcm_loop_tpg *tpg)
1039{
1040 struct se_session *se_sess;
1041 struct tcm_loop_nexus *tl_nexus;
1042 struct tcm_loop_hba *tl_hba = tpg->tl_hba;
1043
Hannes Reinecke1ec59fe2013-10-16 09:12:52 +02001044 if (!tl_hba)
1045 return -ENODEV;
1046
1047 tl_nexus = tl_hba->tl_nexus;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001048 if (!tl_nexus)
1049 return -ENODEV;
1050
1051 se_sess = tl_nexus->se_sess;
1052 if (!se_sess)
1053 return -ENODEV;
1054
1055 if (atomic_read(&tpg->tl_tpg_port_count)) {
Andy Grover6708bb22011-06-08 10:36:43 -07001056 pr_err("Unable to remove TCM_Loop I_T Nexus with"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001057 " active TPG port count: %d\n",
1058 atomic_read(&tpg->tl_tpg_port_count));
1059 return -EPERM;
1060 }
1061
Andy Grover6708bb22011-06-08 10:36:43 -07001062 pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001063 " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
1064 tl_nexus->se_sess->se_node_acl->initiatorname);
1065 /*
1066 * Release the SCSI I_T Nexus to the emulated SAS Target Port
1067 */
1068 transport_deregister_session(tl_nexus->se_sess);
1069 tpg->tl_hba->tl_nexus = NULL;
1070 kfree(tl_nexus);
1071 return 0;
1072}
1073
1074/* End items for tcm_loop_nexus_cit */
1075
1076static ssize_t tcm_loop_tpg_show_nexus(
1077 struct se_portal_group *se_tpg,
1078 char *page)
1079{
1080 struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
1081 struct tcm_loop_tpg, tl_se_tpg);
1082 struct tcm_loop_nexus *tl_nexus;
1083 ssize_t ret;
1084
1085 tl_nexus = tl_tpg->tl_hba->tl_nexus;
1086 if (!tl_nexus)
1087 return -ENODEV;
1088
1089 ret = snprintf(page, PAGE_SIZE, "%s\n",
1090 tl_nexus->se_sess->se_node_acl->initiatorname);
1091
1092 return ret;
1093}
1094
1095static ssize_t tcm_loop_tpg_store_nexus(
1096 struct se_portal_group *se_tpg,
1097 const char *page,
1098 size_t count)
1099{
1100 struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
1101 struct tcm_loop_tpg, tl_se_tpg);
1102 struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
1103 unsigned char i_port[TL_WWN_ADDR_LEN], *ptr, *port_ptr;
1104 int ret;
1105 /*
1106 * Shutdown the active I_T nexus if 'NULL' is passed..
1107 */
1108 if (!strncmp(page, "NULL", 4)) {
1109 ret = tcm_loop_drop_nexus(tl_tpg);
1110 return (!ret) ? count : ret;
1111 }
1112 /*
1113 * Otherwise make sure the passed virtual Initiator port WWN matches
1114 * the fabric protocol_id set in tcm_loop_make_scsi_hba(), and call
1115 * tcm_loop_make_nexus()
1116 */
Dan Carpenter60d645a2011-06-15 10:03:05 -07001117 if (strlen(page) >= TL_WWN_ADDR_LEN) {
Andy Grover6708bb22011-06-08 10:36:43 -07001118 pr_err("Emulated NAA Sas Address: %s, exceeds"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001119 " max: %d\n", page, TL_WWN_ADDR_LEN);
1120 return -EINVAL;
1121 }
1122 snprintf(&i_port[0], TL_WWN_ADDR_LEN, "%s", page);
1123
1124 ptr = strstr(i_port, "naa.");
1125 if (ptr) {
1126 if (tl_hba->tl_proto_id != SCSI_PROTOCOL_SAS) {
Andy Grover6708bb22011-06-08 10:36:43 -07001127 pr_err("Passed SAS Initiator Port %s does not"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001128 " match target port protoid: %s\n", i_port,
1129 tcm_loop_dump_proto_id(tl_hba));
1130 return -EINVAL;
1131 }
1132 port_ptr = &i_port[0];
1133 goto check_newline;
1134 }
1135 ptr = strstr(i_port, "fc.");
1136 if (ptr) {
1137 if (tl_hba->tl_proto_id != SCSI_PROTOCOL_FCP) {
Andy Grover6708bb22011-06-08 10:36:43 -07001138 pr_err("Passed FCP Initiator Port %s does not"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001139 " match target port protoid: %s\n", i_port,
1140 tcm_loop_dump_proto_id(tl_hba));
1141 return -EINVAL;
1142 }
1143 port_ptr = &i_port[3]; /* Skip over "fc." */
1144 goto check_newline;
1145 }
1146 ptr = strstr(i_port, "iqn.");
1147 if (ptr) {
1148 if (tl_hba->tl_proto_id != SCSI_PROTOCOL_ISCSI) {
Andy Grover6708bb22011-06-08 10:36:43 -07001149 pr_err("Passed iSCSI Initiator Port %s does not"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001150 " match target port protoid: %s\n", i_port,
1151 tcm_loop_dump_proto_id(tl_hba));
1152 return -EINVAL;
1153 }
1154 port_ptr = &i_port[0];
1155 goto check_newline;
1156 }
Andy Grover6708bb22011-06-08 10:36:43 -07001157 pr_err("Unable to locate prefix for emulated Initiator Port:"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001158 " %s\n", i_port);
1159 return -EINVAL;
1160 /*
1161 * Clear any trailing newline for the NAA WWN
1162 */
1163check_newline:
1164 if (i_port[strlen(i_port)-1] == '\n')
1165 i_port[strlen(i_port)-1] = '\0';
1166
1167 ret = tcm_loop_make_nexus(tl_tpg, port_ptr);
1168 if (ret < 0)
1169 return ret;
1170
1171 return count;
1172}
1173
1174TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR);
1175
Hannes Reineckefb2b2842013-10-16 09:12:53 +02001176static ssize_t tcm_loop_tpg_show_transport_status(
1177 struct se_portal_group *se_tpg,
1178 char *page)
1179{
1180 struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
1181 struct tcm_loop_tpg, tl_se_tpg);
1182 const char *status = NULL;
1183 ssize_t ret = -EINVAL;
1184
1185 switch (tl_tpg->tl_transport_status) {
1186 case TCM_TRANSPORT_ONLINE:
1187 status = "online";
1188 break;
1189 case TCM_TRANSPORT_OFFLINE:
1190 status = "offline";
1191 break;
1192 default:
1193 break;
1194 }
1195
1196 if (status)
1197 ret = snprintf(page, PAGE_SIZE, "%s\n", status);
1198
1199 return ret;
1200}
1201
1202static ssize_t tcm_loop_tpg_store_transport_status(
1203 struct se_portal_group *se_tpg,
1204 const char *page,
1205 size_t count)
1206{
1207 struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
1208 struct tcm_loop_tpg, tl_se_tpg);
1209
1210 if (!strncmp(page, "online", 6)) {
1211 tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
1212 return count;
1213 }
1214 if (!strncmp(page, "offline", 7)) {
1215 tl_tpg->tl_transport_status = TCM_TRANSPORT_OFFLINE;
1216 return count;
1217 }
1218 return -EINVAL;
1219}
1220
1221TF_TPG_BASE_ATTR(tcm_loop, transport_status, S_IRUGO | S_IWUSR);
1222
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001223static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
1224 &tcm_loop_tpg_nexus.attr,
Hannes Reineckefb2b2842013-10-16 09:12:53 +02001225 &tcm_loop_tpg_transport_status.attr,
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001226 NULL,
1227};
1228
1229/* Start items for tcm_loop_naa_cit */
1230
1231struct se_portal_group *tcm_loop_make_naa_tpg(
1232 struct se_wwn *wwn,
1233 struct config_group *group,
1234 const char *name)
1235{
1236 struct tcm_loop_hba *tl_hba = container_of(wwn,
1237 struct tcm_loop_hba, tl_hba_wwn);
1238 struct tcm_loop_tpg *tl_tpg;
1239 char *tpgt_str, *end_ptr;
1240 int ret;
1241 unsigned short int tpgt;
1242
1243 tpgt_str = strstr(name, "tpgt_");
1244 if (!tpgt_str) {
Andy Grover6708bb22011-06-08 10:36:43 -07001245 pr_err("Unable to locate \"tpgt_#\" directory"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001246 " group\n");
1247 return ERR_PTR(-EINVAL);
1248 }
1249 tpgt_str += 5; /* Skip ahead of "tpgt_" */
1250 tpgt = (unsigned short int) simple_strtoul(tpgt_str, &end_ptr, 0);
1251
Dan Carpenter12f09cc2011-04-02 14:32:47 -07001252 if (tpgt >= TL_TPGS_PER_HBA) {
Andy Grover6708bb22011-06-08 10:36:43 -07001253 pr_err("Passed tpgt: %hu exceeds TL_TPGS_PER_HBA:"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001254 " %u\n", tpgt, TL_TPGS_PER_HBA);
1255 return ERR_PTR(-EINVAL);
1256 }
1257 tl_tpg = &tl_hba->tl_hba_tpgs[tpgt];
1258 tl_tpg->tl_hba = tl_hba;
1259 tl_tpg->tl_tpgt = tpgt;
1260 /*
1261 * Register the tl_tpg as a emulated SAS TCM Target Endpoint
1262 */
1263 ret = core_tpg_register(&tcm_loop_fabric_configfs->tf_ops,
Andy Grover5951146d2011-07-19 10:26:37 +00001264 wwn, &tl_tpg->tl_se_tpg, tl_tpg,
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001265 TRANSPORT_TPG_TYPE_NORMAL);
1266 if (ret < 0)
1267 return ERR_PTR(-ENOMEM);
1268
Andy Grover6708bb22011-06-08 10:36:43 -07001269 pr_debug("TCM_Loop_ConfigFS: Allocated Emulated %s"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001270 " Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
1271 config_item_name(&wwn->wwn_group.cg_item), tpgt);
1272
1273 return &tl_tpg->tl_se_tpg;
1274}
1275
1276void tcm_loop_drop_naa_tpg(
1277 struct se_portal_group *se_tpg)
1278{
1279 struct se_wwn *wwn = se_tpg->se_tpg_wwn;
1280 struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
1281 struct tcm_loop_tpg, tl_se_tpg);
1282 struct tcm_loop_hba *tl_hba;
1283 unsigned short tpgt;
1284
1285 tl_hba = tl_tpg->tl_hba;
1286 tpgt = tl_tpg->tl_tpgt;
1287 /*
1288 * Release the I_T Nexus for the Virtual SAS link if present
1289 */
1290 tcm_loop_drop_nexus(tl_tpg);
1291 /*
1292 * Deregister the tl_tpg as a emulated SAS TCM Target Endpoint
1293 */
1294 core_tpg_deregister(se_tpg);
1295
Nicholas Bellinger0a020432011-10-10 19:44:05 -07001296 tl_tpg->tl_hba = NULL;
1297 tl_tpg->tl_tpgt = 0;
1298
Andy Grover6708bb22011-06-08 10:36:43 -07001299 pr_debug("TCM_Loop_ConfigFS: Deallocated Emulated %s"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001300 " Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
1301 config_item_name(&wwn->wwn_group.cg_item), tpgt);
1302}
1303
1304/* End items for tcm_loop_naa_cit */
1305
1306/* Start items for tcm_loop_cit */
1307
1308struct se_wwn *tcm_loop_make_scsi_hba(
1309 struct target_fabric_configfs *tf,
1310 struct config_group *group,
1311 const char *name)
1312{
1313 struct tcm_loop_hba *tl_hba;
1314 struct Scsi_Host *sh;
1315 char *ptr;
1316 int ret, off = 0;
1317
1318 tl_hba = kzalloc(sizeof(struct tcm_loop_hba), GFP_KERNEL);
1319 if (!tl_hba) {
Andy Grover6708bb22011-06-08 10:36:43 -07001320 pr_err("Unable to allocate struct tcm_loop_hba\n");
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001321 return ERR_PTR(-ENOMEM);
1322 }
1323 /*
1324 * Determine the emulated Protocol Identifier and Target Port Name
1325 * based on the incoming configfs directory name.
1326 */
1327 ptr = strstr(name, "naa.");
1328 if (ptr) {
1329 tl_hba->tl_proto_id = SCSI_PROTOCOL_SAS;
1330 goto check_len;
1331 }
1332 ptr = strstr(name, "fc.");
1333 if (ptr) {
1334 tl_hba->tl_proto_id = SCSI_PROTOCOL_FCP;
1335 off = 3; /* Skip over "fc." */
1336 goto check_len;
1337 }
1338 ptr = strstr(name, "iqn.");
Jesper Juhla57b5d32011-06-28 00:30:17 +02001339 if (!ptr) {
Andy Grover6708bb22011-06-08 10:36:43 -07001340 pr_err("Unable to locate prefix for emulated Target "
Jesper Juhla57b5d32011-06-28 00:30:17 +02001341 "Port: %s\n", name);
1342 ret = -EINVAL;
1343 goto out;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001344 }
Jesper Juhla57b5d32011-06-28 00:30:17 +02001345 tl_hba->tl_proto_id = SCSI_PROTOCOL_ISCSI;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001346
1347check_len:
Dan Carpenter60d645a2011-06-15 10:03:05 -07001348 if (strlen(name) >= TL_WWN_ADDR_LEN) {
Andy Grover6708bb22011-06-08 10:36:43 -07001349 pr_err("Emulated NAA %s Address: %s, exceeds"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001350 " max: %d\n", name, tcm_loop_dump_proto_id(tl_hba),
1351 TL_WWN_ADDR_LEN);
Jesper Juhla57b5d32011-06-28 00:30:17 +02001352 ret = -EINVAL;
1353 goto out;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001354 }
1355 snprintf(&tl_hba->tl_wwn_address[0], TL_WWN_ADDR_LEN, "%s", &name[off]);
1356
1357 /*
1358 * Call device_register(tl_hba->dev) to register the emulated
1359 * Linux/SCSI LLD of type struct Scsi_Host at tl_hba->sh after
1360 * device_register() callbacks in tcm_loop_driver_probe()
1361 */
1362 ret = tcm_loop_setup_hba_bus(tl_hba, tcm_loop_hba_no_cnt);
1363 if (ret)
1364 goto out;
1365
1366 sh = tl_hba->sh;
1367 tcm_loop_hba_no_cnt++;
Andy Grover6708bb22011-06-08 10:36:43 -07001368 pr_debug("TCM_Loop_ConfigFS: Allocated emulated Target"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001369 " %s Address: %s at Linux/SCSI Host ID: %d\n",
1370 tcm_loop_dump_proto_id(tl_hba), name, sh->host_no);
1371
1372 return &tl_hba->tl_hba_wwn;
1373out:
1374 kfree(tl_hba);
1375 return ERR_PTR(ret);
1376}
1377
1378void tcm_loop_drop_scsi_hba(
1379 struct se_wwn *wwn)
1380{
1381 struct tcm_loop_hba *tl_hba = container_of(wwn,
1382 struct tcm_loop_hba, tl_hba_wwn);
Nicholas Bellinger6297b072011-11-12 09:29:51 -08001383
1384 pr_debug("TCM_Loop_ConfigFS: Deallocating emulated Target"
1385 " SAS Address: %s at Linux/SCSI Host ID: %d\n",
1386 tl_hba->tl_wwn_address, tl_hba->sh->host_no);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001387 /*
1388 * Call device_unregister() on the original tl_hba->dev.
1389 * tcm_loop_fabric_scsi.c:tcm_loop_release_adapter() will
1390 * release *tl_hba;
1391 */
1392 device_unregister(&tl_hba->dev);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001393}
1394
1395/* Start items for tcm_loop_cit */
1396static ssize_t tcm_loop_wwn_show_attr_version(
1397 struct target_fabric_configfs *tf,
1398 char *page)
1399{
1400 return sprintf(page, "TCM Loopback Fabric module %s\n", TCM_LOOP_VERSION);
1401}
1402
1403TF_WWN_ATTR_RO(tcm_loop, version);
1404
1405static struct configfs_attribute *tcm_loop_wwn_attrs[] = {
1406 &tcm_loop_wwn_version.attr,
1407 NULL,
1408};
1409
1410/* End items for tcm_loop_cit */
1411
1412static int tcm_loop_register_configfs(void)
1413{
1414 struct target_fabric_configfs *fabric;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001415 int ret;
1416 /*
1417 * Set the TCM Loop HBA counter to zero
1418 */
1419 tcm_loop_hba_no_cnt = 0;
1420 /*
1421 * Register the top level struct config_item_type with TCM core
1422 */
1423 fabric = target_fabric_configfs_init(THIS_MODULE, "loopback");
Andy Grovere3d6f902011-07-19 08:55:10 +00001424 if (IS_ERR(fabric)) {
Andy Grover6708bb22011-06-08 10:36:43 -07001425 pr_err("tcm_loop_register_configfs() failed!\n");
Andy Grovere3d6f902011-07-19 08:55:10 +00001426 return PTR_ERR(fabric);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001427 }
1428 /*
1429 * Setup the fabric API of function pointers used by target_core_mod
1430 */
1431 fabric->tf_ops.get_fabric_name = &tcm_loop_get_fabric_name;
1432 fabric->tf_ops.get_fabric_proto_ident = &tcm_loop_get_fabric_proto_ident;
1433 fabric->tf_ops.tpg_get_wwn = &tcm_loop_get_endpoint_wwn;
1434 fabric->tf_ops.tpg_get_tag = &tcm_loop_get_tag;
1435 fabric->tf_ops.tpg_get_default_depth = &tcm_loop_get_default_depth;
1436 fabric->tf_ops.tpg_get_pr_transport_id = &tcm_loop_get_pr_transport_id;
1437 fabric->tf_ops.tpg_get_pr_transport_id_len =
1438 &tcm_loop_get_pr_transport_id_len;
1439 fabric->tf_ops.tpg_parse_pr_out_transport_id =
1440 &tcm_loop_parse_pr_out_transport_id;
1441 fabric->tf_ops.tpg_check_demo_mode = &tcm_loop_check_demo_mode;
1442 fabric->tf_ops.tpg_check_demo_mode_cache =
1443 &tcm_loop_check_demo_mode_cache;
1444 fabric->tf_ops.tpg_check_demo_mode_write_protect =
1445 &tcm_loop_check_demo_mode_write_protect;
1446 fabric->tf_ops.tpg_check_prod_mode_write_protect =
1447 &tcm_loop_check_prod_mode_write_protect;
1448 /*
1449 * The TCM loopback fabric module runs in demo-mode to a local
1450 * virtual SCSI device, so fabric dependent initator ACLs are
1451 * not required.
1452 */
1453 fabric->tf_ops.tpg_alloc_fabric_acl = &tcm_loop_tpg_alloc_fabric_acl;
1454 fabric->tf_ops.tpg_release_fabric_acl =
1455 &tcm_loop_tpg_release_fabric_acl;
1456 fabric->tf_ops.tpg_get_inst_index = &tcm_loop_get_inst_index;
1457 /*
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001458 * Used for setting up remaining TCM resources in process context
1459 */
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001460 fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free;
Christoph Hellwig35462972011-05-31 23:56:57 -04001461 fabric->tf_ops.release_cmd = &tcm_loop_release_cmd;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001462 fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session;
1463 fabric->tf_ops.close_session = &tcm_loop_close_session;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001464 fabric->tf_ops.sess_get_index = &tcm_loop_sess_get_index;
1465 fabric->tf_ops.sess_get_initiator_sid = NULL;
1466 fabric->tf_ops.write_pending = &tcm_loop_write_pending;
1467 fabric->tf_ops.write_pending_status = &tcm_loop_write_pending_status;
1468 /*
1469 * Not used for TCM loopback
1470 */
1471 fabric->tf_ops.set_default_node_attributes =
1472 &tcm_loop_set_default_node_attributes;
1473 fabric->tf_ops.get_task_tag = &tcm_loop_get_task_tag;
1474 fabric->tf_ops.get_cmd_state = &tcm_loop_get_cmd_state;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001475 fabric->tf_ops.queue_data_in = &tcm_loop_queue_data_in;
1476 fabric->tf_ops.queue_status = &tcm_loop_queue_status;
1477 fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001478
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001479 /*
1480 * Setup function pointers for generic logic in target_core_fabric_configfs.c
1481 */
1482 fabric->tf_ops.fabric_make_wwn = &tcm_loop_make_scsi_hba;
1483 fabric->tf_ops.fabric_drop_wwn = &tcm_loop_drop_scsi_hba;
1484 fabric->tf_ops.fabric_make_tpg = &tcm_loop_make_naa_tpg;
1485 fabric->tf_ops.fabric_drop_tpg = &tcm_loop_drop_naa_tpg;
1486 /*
1487 * fabric_post_link() and fabric_pre_unlink() are used for
1488 * registration and release of TCM Loop Virtual SCSI LUNs.
1489 */
1490 fabric->tf_ops.fabric_post_link = &tcm_loop_port_link;
1491 fabric->tf_ops.fabric_pre_unlink = &tcm_loop_port_unlink;
1492 fabric->tf_ops.fabric_make_np = NULL;
1493 fabric->tf_ops.fabric_drop_np = NULL;
1494 /*
1495 * Setup default attribute lists for various fabric->tf_cit_tmpl
1496 */
Andy Groverd80e224d2013-10-09 11:05:56 -07001497 fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_loop_wwn_attrs;
1498 fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = tcm_loop_tpg_attrs;
1499 fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
1500 fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
1501 fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001502 /*
1503 * Once fabric->tf_ops has been setup, now register the fabric for
1504 * use within TCM
1505 */
1506 ret = target_fabric_configfs_register(fabric);
1507 if (ret < 0) {
Andy Grover6708bb22011-06-08 10:36:43 -07001508 pr_err("target_fabric_configfs_register() for"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001509 " TCM_Loop failed!\n");
1510 target_fabric_configfs_free(fabric);
1511 return -1;
1512 }
1513 /*
1514 * Setup our local pointer to *fabric.
1515 */
1516 tcm_loop_fabric_configfs = fabric;
Andy Grover6708bb22011-06-08 10:36:43 -07001517 pr_debug("TCM_LOOP[0] - Set fabric ->"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001518 " tcm_loop_fabric_configfs\n");
1519 return 0;
1520}
1521
1522static void tcm_loop_deregister_configfs(void)
1523{
1524 if (!tcm_loop_fabric_configfs)
1525 return;
1526
1527 target_fabric_configfs_deregister(tcm_loop_fabric_configfs);
1528 tcm_loop_fabric_configfs = NULL;
Andy Grover6708bb22011-06-08 10:36:43 -07001529 pr_debug("TCM_LOOP[0] - Cleared"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001530 " tcm_loop_fabric_configfs\n");
1531}
1532
1533static int __init tcm_loop_fabric_init(void)
1534{
Christoph Hellwigafe2cb72012-02-02 17:04:41 -05001535 int ret = -ENOMEM;
1536
1537 tcm_loop_workqueue = alloc_workqueue("tcm_loop", 0, 0);
1538 if (!tcm_loop_workqueue)
1539 goto out;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001540
1541 tcm_loop_cmd_cache = kmem_cache_create("tcm_loop_cmd_cache",
1542 sizeof(struct tcm_loop_cmd),
1543 __alignof__(struct tcm_loop_cmd),
1544 0, NULL);
1545 if (!tcm_loop_cmd_cache) {
Andy Grover6708bb22011-06-08 10:36:43 -07001546 pr_debug("kmem_cache_create() for"
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001547 " tcm_loop_cmd_cache failed\n");
Christoph Hellwigafe2cb72012-02-02 17:04:41 -05001548 goto out_destroy_workqueue;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001549 }
1550
1551 ret = tcm_loop_alloc_core_bus();
1552 if (ret)
Christoph Hellwigafe2cb72012-02-02 17:04:41 -05001553 goto out_destroy_cache;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001554
1555 ret = tcm_loop_register_configfs();
Christoph Hellwigafe2cb72012-02-02 17:04:41 -05001556 if (ret)
1557 goto out_release_core_bus;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001558
1559 return 0;
Christoph Hellwigafe2cb72012-02-02 17:04:41 -05001560
1561out_release_core_bus:
1562 tcm_loop_release_core_bus();
1563out_destroy_cache:
1564 kmem_cache_destroy(tcm_loop_cmd_cache);
1565out_destroy_workqueue:
1566 destroy_workqueue(tcm_loop_workqueue);
1567out:
1568 return ret;
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001569}
1570
1571static void __exit tcm_loop_fabric_exit(void)
1572{
1573 tcm_loop_deregister_configfs();
1574 tcm_loop_release_core_bus();
1575 kmem_cache_destroy(tcm_loop_cmd_cache);
Christoph Hellwigafe2cb72012-02-02 17:04:41 -05001576 destroy_workqueue(tcm_loop_workqueue);
Nicholas Bellinger3703b2c2011-03-18 15:39:17 -07001577}
1578
1579MODULE_DESCRIPTION("TCM loopback virtual Linux/SCSI fabric module");
1580MODULE_AUTHOR("Nicholas A. Bellinger <nab@risingtidesystems.com>");
1581MODULE_LICENSE("GPL");
1582module_init(tcm_loop_fabric_init);
1583module_exit(tcm_loop_fabric_exit);