Commit 3703b2c5d041a68095cdd22380c23ce27d449ad7

Authored by Nicholas Bellinger
Committed by James Bottomley
1 parent 5fa8b57313

[SCSI] tcm_loop: Add multi-fabric Linux/SCSI LLD fabric module

This patch adds the TCM_Loop Linux/SCSI LLD fabric module for
accessing TCM device backstores as locally accessable SCSI LUNs in
virtual SAS, FC, and iSCSI Target ports using the generic fabric
TransportID and Target Port WWN naming handlers from TCM's
target_core_fabric_lib.c The TCM_Loop module uses the generic fabric
configfs infratructure provided by target_core_fabric_configfs.c and
adds a module dependent attribute for the creation/release of the
virtual I_T Nexus connected the TCM_Loop Target and Initiator Ports.

TCM_Loop can also be used with scsi-generic and BSG drivers so that
STGT userspace fabric modules, QEMU-KVM and other hypervisor SCSI
passthrough support can access TCM device backstore and control CDB
emulation.

For more information please see:

http://linux-iscsi.org/wiki/Tcm_loop

[jejb: fixed up checkpatch stuff]
Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>

Showing 6 changed files with 1673 additions and 0 deletions Side-by-side Diff

drivers/target/Kconfig
... ... @@ -29,5 +29,7 @@
29 29 Say Y here to enable the TCM/pSCSI subsystem plugin for non-buffered
30 30 passthrough access to Linux/SCSI device
31 31  
  32 +source "drivers/target/loopback/Kconfig"
  33 +
32 34 endif
drivers/target/Makefile
... ... @@ -21,4 +21,7 @@
21 21 obj-$(CONFIG_TCM_IBLOCK) += target_core_iblock.o
22 22 obj-$(CONFIG_TCM_FILEIO) += target_core_file.o
23 23 obj-$(CONFIG_TCM_PSCSI) += target_core_pscsi.o
  24 +
  25 +# Fabric modules
  26 +obj-$(CONFIG_LOOPBACK_TARGET) += loopback/
drivers/target/loopback/Kconfig
  1 +config LOOPBACK_TARGET
  2 + tristate "TCM Virtual SAS target and Linux/SCSI LDD fabric loopback module"
  3 + help
  4 + Say Y here to enable the TCM Virtual SAS target and Linux/SCSI LLD
  5 + fabric loopback module.
  6 +
  7 +config LOOPBACK_TARGET_CDB_DEBUG
  8 + bool "TCM loopback fabric module CDB debug code"
  9 + depends on LOOPBACK_TARGET
  10 + help
  11 + Say Y here to enable the TCM loopback fabric module CDB debug code
drivers/target/loopback/Makefile
  1 +obj-$(CONFIG_LOOPBACK_TARGET) += tcm_loop.o
drivers/target/loopback/tcm_loop.c
Changes suppressed. Click to show
  1 +/*******************************************************************************
  2 + *
  3 + * This file contains the Linux/SCSI LLD virtual SCSI initiator driver
  4 + * for emulated SAS initiator ports
  5 + *
  6 + * © Copyright 2011 RisingTide Systems LLC.
  7 + *
  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>
  34 +#include <scsi/libsas.h> /* For TASK_ATTR_* */
  35 +
  36 +#include <target/target_core_base.h>
  37 +#include <target/target_core_transport.h>
  38 +#include <target/target_core_fabric_ops.h>
  39 +#include <target/target_core_fabric_configfs.h>
  40 +#include <target/target_core_fabric_lib.h>
  41 +#include <target/target_core_configfs.h>
  42 +#include <target/target_core_device.h>
  43 +#include <target/target_core_tpg.h>
  44 +#include <target/target_core_tmr.h>
  45 +
  46 +#include "tcm_loop.h"
  47 +
  48 +#define to_tcm_loop_hba(hba) container_of(hba, struct tcm_loop_hba, dev)
  49 +
  50 +/* Local pointer to allocated TCM configfs fabric module */
  51 +static struct target_fabric_configfs *tcm_loop_fabric_configfs;
  52 +
  53 +static struct kmem_cache *tcm_loop_cmd_cache;
  54 +
  55 +static int tcm_loop_hba_no_cnt;
  56 +
  57 +/*
  58 + * Allocate a tcm_loop cmd descriptor from target_core_mod code
  59 + *
  60 + * Can be called from interrupt context in tcm_loop_queuecommand() below
  61 + */
  62 +static struct se_cmd *tcm_loop_allocate_core_cmd(
  63 + struct tcm_loop_hba *tl_hba,
  64 + struct se_portal_group *se_tpg,
  65 + struct scsi_cmnd *sc)
  66 +{
  67 + struct se_cmd *se_cmd;
  68 + struct se_session *se_sess;
  69 + struct tcm_loop_nexus *tl_nexus = tl_hba->tl_nexus;
  70 + struct tcm_loop_cmd *tl_cmd;
  71 + int sam_task_attr;
  72 +
  73 + if (!tl_nexus) {
  74 + scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
  75 + " does not exist\n");
  76 + set_host_byte(sc, DID_ERROR);
  77 + return NULL;
  78 + }
  79 + se_sess = tl_nexus->se_sess;
  80 +
  81 + tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_ATOMIC);
  82 + if (!tl_cmd) {
  83 + printk(KERN_ERR "Unable to allocate struct tcm_loop_cmd\n");
  84 + set_host_byte(sc, DID_ERROR);
  85 + return NULL;
  86 + }
  87 + se_cmd = &tl_cmd->tl_se_cmd;
  88 + /*
  89 + * Save the pointer to struct scsi_cmnd *sc
  90 + */
  91 + tl_cmd->sc = sc;
  92 + /*
  93 + * Locate the SAM Task Attr from struct scsi_cmnd *
  94 + */
  95 + if (sc->device->tagged_supported) {
  96 + switch (sc->tag) {
  97 + case HEAD_OF_QUEUE_TAG:
  98 + sam_task_attr = TASK_ATTR_HOQ;
  99 + break;
  100 + case ORDERED_QUEUE_TAG:
  101 + sam_task_attr = TASK_ATTR_ORDERED;
  102 + break;
  103 + default:
  104 + sam_task_attr = TASK_ATTR_SIMPLE;
  105 + break;
  106 + }
  107 + } else
  108 + sam_task_attr = TASK_ATTR_SIMPLE;
  109 +
  110 + /*
  111 + * Initialize struct se_cmd descriptor from target_core_mod infrastructure
  112 + */
  113 + transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,
  114 + scsi_bufflen(sc), sc->sc_data_direction, sam_task_attr,
  115 + &tl_cmd->tl_sense_buf[0]);
  116 +
  117 + /*
  118 + * Signal BIDI usage with T_TASK(cmd)->t_tasks_bidi
  119 + */
  120 + if (scsi_bidi_cmnd(sc))
  121 + T_TASK(se_cmd)->t_tasks_bidi = 1;
  122 + /*
  123 + * Locate the struct se_lun pointer and attach it to struct se_cmd
  124 + */
  125 + if (transport_get_lun_for_cmd(se_cmd, NULL, tl_cmd->sc->device->lun) < 0) {
  126 + kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
  127 + set_host_byte(sc, DID_NO_CONNECT);
  128 + return NULL;
  129 + }
  130 +
  131 + transport_device_setup_cmd(se_cmd);
  132 + return se_cmd;
  133 +}
  134 +
  135 +/*
  136 + * Called by struct target_core_fabric_ops->new_cmd_map()
  137 + *
  138 + * Always called in process context. A non zero return value
  139 + * here will signal to handle an exception based on the return code.
  140 + */
  141 +static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
  142 +{
  143 + struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
  144 + struct tcm_loop_cmd, tl_se_cmd);
  145 + struct scsi_cmnd *sc = tl_cmd->sc;
  146 + void *mem_ptr, *mem_bidi_ptr = NULL;
  147 + u32 sg_no_bidi = 0;
  148 + int ret;
  149 + /*
  150 + * Allocate the necessary tasks to complete the received CDB+data
  151 + */
  152 + ret = transport_generic_allocate_tasks(se_cmd, tl_cmd->sc->cmnd);
  153 + if (ret == -1) {
  154 + /* Out of Resources */
  155 + return PYX_TRANSPORT_LU_COMM_FAILURE;
  156 + } else if (ret == -2) {
  157 + /*
  158 + * Handle case for SAM_STAT_RESERVATION_CONFLICT
  159 + */
  160 + if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
  161 + return PYX_TRANSPORT_RESERVATION_CONFLICT;
  162 + /*
  163 + * Otherwise, return SAM_STAT_CHECK_CONDITION and return
  164 + * sense data.
  165 + */
  166 + return PYX_TRANSPORT_USE_SENSE_REASON;
  167 + }
  168 + /*
  169 + * Setup the struct scatterlist memory from the received
  170 + * struct scsi_cmnd.
  171 + */
  172 + if (scsi_sg_count(sc)) {
  173 + se_cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM;
  174 + mem_ptr = (void *)scsi_sglist(sc);
  175 + /*
  176 + * For BIDI commands, pass in the extra READ buffer
  177 + * to transport_generic_map_mem_to_cmd() below..
  178 + */
  179 + if (T_TASK(se_cmd)->t_tasks_bidi) {
  180 + struct scsi_data_buffer *sdb = scsi_in(sc);
  181 +
  182 + mem_bidi_ptr = (void *)sdb->table.sgl;
  183 + sg_no_bidi = sdb->table.nents;
  184 + }
  185 + } else {
  186 + /*
  187 + * Used for DMA_NONE
  188 + */
  189 + mem_ptr = NULL;
  190 + }
  191 + /*
  192 + * Map the SG memory into struct se_mem->page linked list using the same
  193 + * physical memory at sg->page_link.
  194 + */
  195 + ret = transport_generic_map_mem_to_cmd(se_cmd, mem_ptr,
  196 + scsi_sg_count(sc), mem_bidi_ptr, sg_no_bidi);
  197 + if (ret < 0)
  198 + return PYX_TRANSPORT_LU_COMM_FAILURE;
  199 +
  200 + return 0;
  201 +}
  202 +
  203 +/*
  204 + * Called from struct target_core_fabric_ops->check_stop_free()
  205 + */
  206 +static void tcm_loop_check_stop_free(struct se_cmd *se_cmd)
  207 +{
  208 + /*
  209 + * Do not release struct se_cmd's containing a valid TMR
  210 + * pointer. These will be released directly in tcm_loop_device_reset()
  211 + * with transport_generic_free_cmd().
  212 + */
  213 + if (se_cmd->se_tmr_req)
  214 + return;
  215 + /*
  216 + * Release the struct se_cmd, which will make a callback to release
  217 + * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd()
  218 + */
  219 + transport_generic_free_cmd(se_cmd, 0, 1, 0);
  220 +}
  221 +
  222 +/*
  223 + * Called from struct target_core_fabric_ops->release_cmd_to_pool()
  224 + */
  225 +static void tcm_loop_deallocate_core_cmd(struct se_cmd *se_cmd)
  226 +{
  227 + struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
  228 + struct tcm_loop_cmd, tl_se_cmd);
  229 +
  230 + kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
  231 +}
  232 +
  233 +static int tcm_loop_proc_info(struct Scsi_Host *host, char *buffer,
  234 + char **start, off_t offset,
  235 + int length, int inout)
  236 +{
  237 + return sprintf(buffer, "tcm_loop_proc_info()\n");
  238 +}
  239 +
  240 +static int tcm_loop_driver_probe(struct device *);
  241 +static int tcm_loop_driver_remove(struct device *);
  242 +
  243 +static int pseudo_lld_bus_match(struct device *dev,
  244 + struct device_driver *dev_driver)
  245 +{
  246 + return 1;
  247 +}
  248 +
  249 +static struct bus_type tcm_loop_lld_bus = {
  250 + .name = "tcm_loop_bus",
  251 + .match = pseudo_lld_bus_match,
  252 + .probe = tcm_loop_driver_probe,
  253 + .remove = tcm_loop_driver_remove,
  254 +};
  255 +
  256 +static struct device_driver tcm_loop_driverfs = {
  257 + .name = "tcm_loop",
  258 + .bus = &tcm_loop_lld_bus,
  259 +};
  260 +/*
  261 + * Used with root_device_register() in tcm_loop_alloc_core_bus() below
  262 + */
  263 +struct device *tcm_loop_primary;
  264 +
  265 +/*
  266 + * Copied from drivers/scsi/libfc/fc_fcp.c:fc_change_queue_depth() and
  267 + * drivers/scsi/libiscsi.c:iscsi_change_queue_depth()
  268 + */
  269 +static int tcm_loop_change_queue_depth(
  270 + struct scsi_device *sdev,
  271 + int depth,
  272 + int reason)
  273 +{
  274 + switch (reason) {
  275 + case SCSI_QDEPTH_DEFAULT:
  276 + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
  277 + break;
  278 + case SCSI_QDEPTH_QFULL:
  279 + scsi_track_queue_full(sdev, depth);
  280 + break;
  281 + case SCSI_QDEPTH_RAMP_UP:
  282 + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
  283 + break;
  284 + default:
  285 + return -EOPNOTSUPP;
  286 + }
  287 + return sdev->queue_depth;
  288 +}
  289 +
  290 +/*
  291 + * Main entry point from struct scsi_host_template for incoming SCSI CDB+Data
  292 + * from Linux/SCSI subsystem for SCSI low level device drivers (LLDs)
  293 + */
  294 +static int tcm_loop_queuecommand(
  295 + struct Scsi_Host *sh,
  296 + struct scsi_cmnd *sc)
  297 +{
  298 + struct se_cmd *se_cmd;
  299 + struct se_portal_group *se_tpg;
  300 + struct tcm_loop_hba *tl_hba;
  301 + struct tcm_loop_tpg *tl_tpg;
  302 +
  303 + TL_CDB_DEBUG("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
  304 + " scsi_buf_len: %u\n", sc->device->host->host_no,
  305 + sc->device->id, sc->device->channel, sc->device->lun,
  306 + sc->cmnd[0], scsi_bufflen(sc));
  307 + /*
  308 + * Locate the tcm_loop_hba_t pointer
  309 + */
  310 + tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
  311 + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
  312 + se_tpg = &tl_tpg->tl_se_tpg;
  313 + /*
  314 + * Determine the SAM Task Attribute and allocate tl_cmd and
  315 + * tl_cmd->tl_se_cmd from TCM infrastructure
  316 + */
  317 + se_cmd = tcm_loop_allocate_core_cmd(tl_hba, se_tpg, sc);
  318 + if (!se_cmd) {
  319 + sc->scsi_done(sc);
  320 + return 0;
  321 + }
  322 + /*
  323 + * Queue up the newly allocated to be processed in TCM thread context.
  324 + */
  325 + transport_generic_handle_cdb_map(se_cmd);
  326 + return 0;
  327 +}
  328 +
  329 +/*
  330 + * Called from SCSI EH process context to issue a LUN_RESET TMR
  331 + * to struct scsi_device
  332 + */
  333 +static int tcm_loop_device_reset(struct scsi_cmnd *sc)
  334 +{
  335 + struct se_cmd *se_cmd = NULL;
  336 + struct se_portal_group *se_tpg;
  337 + struct se_session *se_sess;
  338 + struct tcm_loop_cmd *tl_cmd = NULL;
  339 + struct tcm_loop_hba *tl_hba;
  340 + struct tcm_loop_nexus *tl_nexus;
  341 + struct tcm_loop_tmr *tl_tmr = NULL;
  342 + struct tcm_loop_tpg *tl_tpg;
  343 + int ret = FAILED;
  344 + /*
  345 + * Locate the tcm_loop_hba_t pointer
  346 + */
  347 + tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
  348 + /*
  349 + * Locate the tl_nexus and se_sess pointers
  350 + */
  351 + tl_nexus = tl_hba->tl_nexus;
  352 + if (!tl_nexus) {
  353 + printk(KERN_ERR "Unable to perform device reset without"
  354 + " active I_T Nexus\n");
  355 + return FAILED;
  356 + }
  357 + se_sess = tl_nexus->se_sess;
  358 + /*
  359 + * Locate the tl_tpg and se_tpg pointers from TargetID in sc->device->id
  360 + */
  361 + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
  362 + se_tpg = &tl_tpg->tl_se_tpg;
  363 +
  364 + tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
  365 + if (!tl_cmd) {
  366 + printk(KERN_ERR "Unable to allocate memory for tl_cmd\n");
  367 + return FAILED;
  368 + }
  369 +
  370 + tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL);
  371 + if (!tl_tmr) {
  372 + printk(KERN_ERR "Unable to allocate memory for tl_tmr\n");
  373 + goto release;
  374 + }
  375 + init_waitqueue_head(&tl_tmr->tl_tmr_wait);
  376 +
  377 + se_cmd = &tl_cmd->tl_se_cmd;
  378 + /*
  379 + * Initialize struct se_cmd descriptor from target_core_mod infrastructure
  380 + */
  381 + transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0,
  382 + DMA_NONE, TASK_ATTR_SIMPLE,
  383 + &tl_cmd->tl_sense_buf[0]);
  384 + /*
  385 + * Allocate the LUN_RESET TMR
  386 + */
  387 + se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, (void *)tl_tmr,
  388 + TMR_LUN_RESET);
  389 + if (!se_cmd->se_tmr_req)
  390 + goto release;
  391 + /*
  392 + * Locate the underlying TCM struct se_lun from sc->device->lun
  393 + */
  394 + if (transport_get_lun_for_tmr(se_cmd, sc->device->lun) < 0)
  395 + goto release;
  396 + /*
  397 + * Queue the TMR to TCM Core and sleep waiting for tcm_loop_queue_tm_rsp()
  398 + * to wake us up.
  399 + */
  400 + transport_generic_handle_tmr(se_cmd);
  401 + wait_event(tl_tmr->tl_tmr_wait, atomic_read(&tl_tmr->tmr_complete));
  402 + /*
  403 + * The TMR LUN_RESET has completed, check the response status and
  404 + * then release allocations.
  405 + */
  406 + ret = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
  407 + SUCCESS : FAILED;
  408 +release:
  409 + if (se_cmd)
  410 + transport_generic_free_cmd(se_cmd, 1, 1, 0);
  411 + else
  412 + kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
  413 + kfree(tl_tmr);
  414 + return ret;
  415 +}
  416 +
  417 +static int tcm_loop_slave_alloc(struct scsi_device *sd)
  418 +{
  419 + set_bit(QUEUE_FLAG_BIDI, &sd->request_queue->queue_flags);
  420 + return 0;
  421 +}
  422 +
  423 +static int tcm_loop_slave_configure(struct scsi_device *sd)
  424 +{
  425 + return 0;
  426 +}
  427 +
  428 +static struct scsi_host_template tcm_loop_driver_template = {
  429 + .proc_info = tcm_loop_proc_info,
  430 + .proc_name = "tcm_loopback",
  431 + .name = "TCM_Loopback",
  432 + .queuecommand = tcm_loop_queuecommand,
  433 + .change_queue_depth = tcm_loop_change_queue_depth,
  434 + .eh_device_reset_handler = tcm_loop_device_reset,
  435 + .can_queue = TL_SCSI_CAN_QUEUE,
  436 + .this_id = -1,
  437 + .sg_tablesize = TL_SCSI_SG_TABLESIZE,
  438 + .cmd_per_lun = TL_SCSI_CMD_PER_LUN,
  439 + .max_sectors = TL_SCSI_MAX_SECTORS,
  440 + .use_clustering = DISABLE_CLUSTERING,
  441 + .slave_alloc = tcm_loop_slave_alloc,
  442 + .slave_configure = tcm_loop_slave_configure,
  443 + .module = THIS_MODULE,
  444 +};
  445 +
  446 +static int tcm_loop_driver_probe(struct device *dev)
  447 +{
  448 + struct tcm_loop_hba *tl_hba;
  449 + struct Scsi_Host *sh;
  450 + int error;
  451 +
  452 + tl_hba = to_tcm_loop_hba(dev);
  453 +
  454 + sh = scsi_host_alloc(&tcm_loop_driver_template,
  455 + sizeof(struct tcm_loop_hba));
  456 + if (!sh) {
  457 + printk(KERN_ERR "Unable to allocate struct scsi_host\n");
  458 + return -ENODEV;
  459 + }
  460 + tl_hba->sh = sh;
  461 +
  462 + /*
  463 + * Assign the struct tcm_loop_hba pointer to struct Scsi_Host->hostdata
  464 + */
  465 + *((struct tcm_loop_hba **)sh->hostdata) = tl_hba;
  466 + /*
  467 + * Setup single ID, Channel and LUN for now..
  468 + */
  469 + sh->max_id = 2;
  470 + sh->max_lun = 0;
  471 + sh->max_channel = 0;
  472 + sh->max_cmd_len = TL_SCSI_MAX_CMD_LEN;
  473 +
  474 + error = scsi_add_host(sh, &tl_hba->dev);
  475 + if (error) {
  476 + printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
  477 + scsi_host_put(sh);
  478 + return -ENODEV;
  479 + }
  480 + return 0;
  481 +}
  482 +
  483 +static int tcm_loop_driver_remove(struct device *dev)
  484 +{
  485 + struct tcm_loop_hba *tl_hba;
  486 + struct Scsi_Host *sh;
  487 +
  488 + tl_hba = to_tcm_loop_hba(dev);
  489 + sh = tl_hba->sh;
  490 +
  491 + scsi_remove_host(sh);
  492 + scsi_host_put(sh);
  493 + return 0;
  494 +}
  495 +
  496 +static void tcm_loop_release_adapter(struct device *dev)
  497 +{
  498 + struct tcm_loop_hba *tl_hba = to_tcm_loop_hba(dev);
  499 +
  500 + kfree(tl_hba);
  501 +}
  502 +
  503 +/*
  504 + * Called from tcm_loop_make_scsi_hba() in tcm_loop_configfs.c
  505 + */
  506 +static int tcm_loop_setup_hba_bus(struct tcm_loop_hba *tl_hba, int tcm_loop_host_id)
  507 +{
  508 + int ret;
  509 +
  510 + tl_hba->dev.bus = &tcm_loop_lld_bus;
  511 + tl_hba->dev.parent = tcm_loop_primary;
  512 + tl_hba->dev.release = &tcm_loop_release_adapter;
  513 + dev_set_name(&tl_hba->dev, "tcm_loop_adapter_%d", tcm_loop_host_id);
  514 +
  515 + ret = device_register(&tl_hba->dev);
  516 + if (ret) {
  517 + printk(KERN_ERR "device_register() failed for"
  518 + " tl_hba->dev: %d\n", ret);
  519 + return -ENODEV;
  520 + }
  521 +
  522 + return 0;
  523 +}
  524 +
  525 +/*
  526 + * Called from tcm_loop_fabric_init() in tcl_loop_fabric.c to load the emulated
  527 + * tcm_loop SCSI bus.
  528 + */
  529 +static int tcm_loop_alloc_core_bus(void)
  530 +{
  531 + int ret;
  532 +
  533 + tcm_loop_primary = root_device_register("tcm_loop_0");
  534 + if (IS_ERR(tcm_loop_primary)) {
  535 + printk(KERN_ERR "Unable to allocate tcm_loop_primary\n");
  536 + return PTR_ERR(tcm_loop_primary);
  537 + }
  538 +
  539 + ret = bus_register(&tcm_loop_lld_bus);
  540 + if (ret) {
  541 + printk(KERN_ERR "bus_register() failed for tcm_loop_lld_bus\n");
  542 + goto dev_unreg;
  543 + }
  544 +
  545 + ret = driver_register(&tcm_loop_driverfs);
  546 + if (ret) {
  547 + printk(KERN_ERR "driver_register() failed for"
  548 + "tcm_loop_driverfs\n");
  549 + goto bus_unreg;
  550 + }
  551 +
  552 + printk(KERN_INFO "Initialized TCM Loop Core Bus\n");
  553 + return ret;
  554 +
  555 +bus_unreg:
  556 + bus_unregister(&tcm_loop_lld_bus);
  557 +dev_unreg:
  558 + root_device_unregister(tcm_loop_primary);
  559 + return ret;
  560 +}
  561 +
  562 +static void tcm_loop_release_core_bus(void)
  563 +{
  564 + driver_unregister(&tcm_loop_driverfs);
  565 + bus_unregister(&tcm_loop_lld_bus);
  566 + root_device_unregister(tcm_loop_primary);
  567 +
  568 + printk(KERN_INFO "Releasing TCM Loop Core BUS\n");
  569 +}
  570 +
  571 +static char *tcm_loop_get_fabric_name(void)
  572 +{
  573 + return "loopback";
  574 +}
  575 +
  576 +static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg)
  577 +{
  578 + struct tcm_loop_tpg *tl_tpg =
  579 + (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
  580 + struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
  581 + /*
  582 + * tl_proto_id is set at tcm_loop_configfs.c:tcm_loop_make_scsi_hba()
  583 + * time based on the protocol dependent prefix of the passed configfs group.
  584 + *
  585 + * Based upon tl_proto_id, TCM_Loop emulates the requested fabric
  586 + * ProtocolID using target_core_fabric_lib.c symbols.
  587 + */
  588 + switch (tl_hba->tl_proto_id) {
  589 + case SCSI_PROTOCOL_SAS:
  590 + return sas_get_fabric_proto_ident(se_tpg);
  591 + case SCSI_PROTOCOL_FCP:
  592 + return fc_get_fabric_proto_ident(se_tpg);
  593 + case SCSI_PROTOCOL_ISCSI:
  594 + return iscsi_get_fabric_proto_ident(se_tpg);
  595 + default:
  596 + printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
  597 + " SAS emulation\n", tl_hba->tl_proto_id);
  598 + break;
  599 + }
  600 +
  601 + return sas_get_fabric_proto_ident(se_tpg);
  602 +}
  603 +
  604 +static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg)
  605 +{
  606 + struct tcm_loop_tpg *tl_tpg =
  607 + (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
  608 + /*
  609 + * Return the passed NAA identifier for the SAS Target Port
  610 + */
  611 + return &tl_tpg->tl_hba->tl_wwn_address[0];
  612 +}
  613 +
  614 +static u16 tcm_loop_get_tag(struct se_portal_group *se_tpg)
  615 +{
  616 + struct tcm_loop_tpg *tl_tpg =
  617 + (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
  618 + /*
  619 + * This Tag is used when forming SCSI Name identifier in EVPD=1 0x83
  620 + * to represent the SCSI Target Port.
  621 + */
  622 + return tl_tpg->tl_tpgt;
  623 +}
  624 +
  625 +static u32 tcm_loop_get_default_depth(struct se_portal_group *se_tpg)
  626 +{
  627 + return 1;
  628 +}
  629 +
  630 +static u32 tcm_loop_get_pr_transport_id(
  631 + struct se_portal_group *se_tpg,
  632 + struct se_node_acl *se_nacl,
  633 + struct t10_pr_registration *pr_reg,
  634 + int *format_code,
  635 + unsigned char *buf)
  636 +{
  637 + struct tcm_loop_tpg *tl_tpg =
  638 + (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
  639 + struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
  640 +
  641 + switch (tl_hba->tl_proto_id) {
  642 + case SCSI_PROTOCOL_SAS:
  643 + return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
  644 + format_code, buf);
  645 + case SCSI_PROTOCOL_FCP:
  646 + return fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
  647 + format_code, buf);
  648 + case SCSI_PROTOCOL_ISCSI:
  649 + return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
  650 + format_code, buf);
  651 + default:
  652 + printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
  653 + " SAS emulation\n", tl_hba->tl_proto_id);
  654 + break;
  655 + }
  656 +
  657 + return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
  658 + format_code, buf);
  659 +}
  660 +
  661 +static u32 tcm_loop_get_pr_transport_id_len(
  662 + struct se_portal_group *se_tpg,
  663 + struct se_node_acl *se_nacl,
  664 + struct t10_pr_registration *pr_reg,
  665 + int *format_code)
  666 +{
  667 + struct tcm_loop_tpg *tl_tpg =
  668 + (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
  669 + struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
  670 +
  671 + switch (tl_hba->tl_proto_id) {
  672 + case SCSI_PROTOCOL_SAS:
  673 + return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
  674 + format_code);
  675 + case SCSI_PROTOCOL_FCP:
  676 + return fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
  677 + format_code);
  678 + case SCSI_PROTOCOL_ISCSI:
  679 + return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
  680 + format_code);
  681 + default:
  682 + printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
  683 + " SAS emulation\n", tl_hba->tl_proto_id);
  684 + break;
  685 + }
  686 +
  687 + return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
  688 + format_code);
  689 +}
  690 +
  691 +/*
  692 + * Used for handling SCSI fabric dependent TransportIDs in SPC-3 and above
  693 + * Persistent Reservation SPEC_I_PT=1 and PROUT REGISTER_AND_MOVE operations.
  694 + */
  695 +static char *tcm_loop_parse_pr_out_transport_id(
  696 + struct se_portal_group *se_tpg,
  697 + const char *buf,
  698 + u32 *out_tid_len,
  699 + char **port_nexus_ptr)
  700 +{
  701 + struct tcm_loop_tpg *tl_tpg =
  702 + (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
  703 + struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
  704 +
  705 + switch (tl_hba->tl_proto_id) {
  706 + case SCSI_PROTOCOL_SAS:
  707 + return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
  708 + port_nexus_ptr);
  709 + case SCSI_PROTOCOL_FCP:
  710 + return fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
  711 + port_nexus_ptr);
  712 + case SCSI_PROTOCOL_ISCSI:
  713 + return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
  714 + port_nexus_ptr);
  715 + default:
  716 + printk(KERN_ERR "Unknown tl_proto_id: 0x%02x, using"
  717 + " SAS emulation\n", tl_hba->tl_proto_id);
  718 + break;
  719 + }
  720 +
  721 + return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
  722 + port_nexus_ptr);
  723 +}
  724 +
  725 +/*
  726 + * Returning (1) here allows for target_core_mod struct se_node_acl to be generated
  727 + * based upon the incoming fabric dependent SCSI Initiator Port
  728 + */
  729 +static int tcm_loop_check_demo_mode(struct se_portal_group *se_tpg)
  730 +{
  731 + return 1;
  732 +}
  733 +
  734 +static int tcm_loop_check_demo_mode_cache(struct se_portal_group *se_tpg)
  735 +{
  736 + return 0;
  737 +}
  738 +
  739 +/*
  740 + * Allow I_T Nexus full READ-WRITE access without explict Initiator Node ACLs for
  741 + * local virtual Linux/SCSI LLD passthrough into VM hypervisor guest
  742 + */
  743 +static int tcm_loop_check_demo_mode_write_protect(struct se_portal_group *se_tpg)
  744 +{
  745 + return 0;
  746 +}
  747 +
  748 +/*
  749 + * Because TCM_Loop does not use explict ACLs and MappedLUNs, this will
  750 + * never be called for TCM_Loop by target_core_fabric_configfs.c code.
  751 + * It has been added here as a nop for target_fabric_tf_ops_check()
  752 + */
  753 +static int tcm_loop_check_prod_mode_write_protect(struct se_portal_group *se_tpg)
  754 +{
  755 + return 0;
  756 +}
  757 +
  758 +static struct se_node_acl *tcm_loop_tpg_alloc_fabric_acl(
  759 + struct se_portal_group *se_tpg)
  760 +{
  761 + struct tcm_loop_nacl *tl_nacl;
  762 +
  763 + tl_nacl = kzalloc(sizeof(struct tcm_loop_nacl), GFP_KERNEL);
  764 + if (!tl_nacl) {
  765 + printk(KERN_ERR "Unable to allocate struct tcm_loop_nacl\n");
  766 + return NULL;
  767 + }
  768 +
  769 + return &tl_nacl->se_node_acl;
  770 +}
  771 +
  772 +static void tcm_loop_tpg_release_fabric_acl(
  773 + struct se_portal_group *se_tpg,
  774 + struct se_node_acl *se_nacl)
  775 +{
  776 + struct tcm_loop_nacl *tl_nacl = container_of(se_nacl,
  777 + struct tcm_loop_nacl, se_node_acl);
  778 +
  779 + kfree(tl_nacl);
  780 +}
  781 +
  782 +static u32 tcm_loop_get_inst_index(struct se_portal_group *se_tpg)
  783 +{
  784 + return 1;
  785 +}
  786 +
  787 +static void tcm_loop_new_cmd_failure(struct se_cmd *se_cmd)
  788 +{
  789 + /*
  790 + * Since TCM_loop is already passing struct scatterlist data from
  791 + * struct scsi_cmnd, no more Linux/SCSI failure dependent state need
  792 + * to be handled here.
  793 + */
  794 + return;
  795 +}
  796 +
  797 +static int tcm_loop_is_state_remove(struct se_cmd *se_cmd)
  798 +{
  799 + /*
  800 + * Assume struct scsi_cmnd is not in remove state..
  801 + */
  802 + return 0;
  803 +}
  804 +
  805 +static int tcm_loop_sess_logged_in(struct se_session *se_sess)
  806 +{
  807 + /*
  808 + * Assume that TL Nexus is always active
  809 + */
  810 + return 1;
  811 +}
  812 +
  813 +static u32 tcm_loop_sess_get_index(struct se_session *se_sess)
  814 +{
  815 + return 1;
  816 +}
  817 +
  818 +static void tcm_loop_set_default_node_attributes(struct se_node_acl *se_acl)
  819 +{
  820 + return;
  821 +}
  822 +
  823 +static u32 tcm_loop_get_task_tag(struct se_cmd *se_cmd)
  824 +{
  825 + return 1;
  826 +}
  827 +
  828 +static int tcm_loop_get_cmd_state(struct se_cmd *se_cmd)
  829 +{
  830 + struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
  831 + struct tcm_loop_cmd, tl_se_cmd);
  832 +
  833 + return tl_cmd->sc_cmd_state;
  834 +}
  835 +
  836 +static int tcm_loop_shutdown_session(struct se_session *se_sess)
  837 +{
  838 + return 0;
  839 +}
  840 +
  841 +static void tcm_loop_close_session(struct se_session *se_sess)
  842 +{
  843 + return;
  844 +};
  845 +
  846 +static void tcm_loop_stop_session(
  847 + struct se_session *se_sess,
  848 + int sess_sleep,
  849 + int conn_sleep)
  850 +{
  851 + return;
  852 +}
  853 +
  854 +static void tcm_loop_fall_back_to_erl0(struct se_session *se_sess)
  855 +{
  856 + return;
  857 +}
  858 +
  859 +static int tcm_loop_write_pending(struct se_cmd *se_cmd)
  860 +{
  861 + /*
  862 + * Since Linux/SCSI has already sent down a struct scsi_cmnd
  863 + * sc->sc_data_direction of DMA_TO_DEVICE with struct scatterlist array
  864 + * memory, and memory has already been mapped to struct se_cmd->t_mem_list
  865 + * format with transport_generic_map_mem_to_cmd().
  866 + *
  867 + * We now tell TCM to add this WRITE CDB directly into the TCM storage
  868 + * object execution queue.
  869 + */
  870 + transport_generic_process_write(se_cmd);
  871 + return 0;
  872 +}
  873 +
  874 +static int tcm_loop_write_pending_status(struct se_cmd *se_cmd)
  875 +{
  876 + return 0;
  877 +}
  878 +
  879 +static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
  880 +{
  881 + struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
  882 + struct tcm_loop_cmd, tl_se_cmd);
  883 + struct scsi_cmnd *sc = tl_cmd->sc;
  884 +
  885 + TL_CDB_DEBUG("tcm_loop_queue_data_in() called for scsi_cmnd: %p"
  886 + " cdb: 0x%02x\n", sc, sc->cmnd[0]);
  887 +
  888 + sc->result = SAM_STAT_GOOD;
  889 + set_host_byte(sc, DID_OK);
  890 + sc->scsi_done(sc);
  891 + return 0;
  892 +}
  893 +
  894 +static int tcm_loop_queue_status(struct se_cmd *se_cmd)
  895 +{
  896 + struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
  897 + struct tcm_loop_cmd, tl_se_cmd);
  898 + struct scsi_cmnd *sc = tl_cmd->sc;
  899 +
  900 + TL_CDB_DEBUG("tcm_loop_queue_status() called for scsi_cmnd: %p"
  901 + " cdb: 0x%02x\n", sc, sc->cmnd[0]);
  902 +
  903 + if (se_cmd->sense_buffer &&
  904 + ((se_cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
  905 + (se_cmd->se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
  906 +
  907 + memcpy((void *)sc->sense_buffer, (void *)se_cmd->sense_buffer,
  908 + SCSI_SENSE_BUFFERSIZE);
  909 + sc->result = SAM_STAT_CHECK_CONDITION;
  910 + set_driver_byte(sc, DRIVER_SENSE);
  911 + } else
  912 + sc->result = se_cmd->scsi_status;
  913 +
  914 + set_host_byte(sc, DID_OK);
  915 + sc->scsi_done(sc);
  916 + return 0;
  917 +}
  918 +
  919 +static int tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd)
  920 +{
  921 + struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
  922 + struct tcm_loop_tmr *tl_tmr = se_tmr->fabric_tmr_ptr;
  923 + /*
  924 + * The SCSI EH thread will be sleeping on se_tmr->tl_tmr_wait, go ahead
  925 + * and wake up the wait_queue_head_t in tcm_loop_device_reset()
  926 + */
  927 + atomic_set(&tl_tmr->tmr_complete, 1);
  928 + wake_up(&tl_tmr->tl_tmr_wait);
  929 + return 0;
  930 +}
  931 +
  932 +static u16 tcm_loop_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)
  933 +{
  934 + return 0;
  935 +}
  936 +
  937 +static u16 tcm_loop_get_fabric_sense_len(void)
  938 +{
  939 + return 0;
  940 +}
  941 +
  942 +static u64 tcm_loop_pack_lun(unsigned int lun)
  943 +{
  944 + u64 result;
  945 +
  946 + /* LSB of lun into byte 1 big-endian */
  947 + result = ((lun & 0xff) << 8);
  948 + /* use flat space addressing method */
  949 + result |= 0x40 | ((lun >> 8) & 0x3f);
  950 +
  951 + return cpu_to_le64(result);
  952 +}
  953 +
  954 +static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba)
  955 +{
  956 + switch (tl_hba->tl_proto_id) {
  957 + case SCSI_PROTOCOL_SAS:
  958 + return "SAS";
  959 + case SCSI_PROTOCOL_FCP:
  960 + return "FCP";
  961 + case SCSI_PROTOCOL_ISCSI:
  962 + return "iSCSI";
  963 + default:
  964 + break;
  965 + }
  966 +
  967 + return "Unknown";
  968 +}
  969 +
  970 +/* Start items for tcm_loop_port_cit */
  971 +
  972 +static int tcm_loop_port_link(
  973 + struct se_portal_group *se_tpg,
  974 + struct se_lun *lun)
  975 +{
  976 + struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
  977 + struct tcm_loop_tpg, tl_se_tpg);
  978 + struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
  979 +
  980 + atomic_inc(&tl_tpg->tl_tpg_port_count);
  981 + smp_mb__after_atomic_inc();
  982 + /*
  983 + * Add Linux/SCSI struct scsi_device by HCTL
  984 + */
  985 + scsi_add_device(tl_hba->sh, 0, tl_tpg->tl_tpgt, lun->unpacked_lun);
  986 +
  987 + printk(KERN_INFO "TCM_Loop_ConfigFS: Port Link Successful\n");
  988 + return 0;
  989 +}
  990 +
  991 +static void tcm_loop_port_unlink(
  992 + struct se_portal_group *se_tpg,
  993 + struct se_lun *se_lun)
  994 +{
  995 + struct scsi_device *sd;
  996 + struct tcm_loop_hba *tl_hba;
  997 + struct tcm_loop_tpg *tl_tpg;
  998 +
  999 + tl_tpg = container_of(se_tpg, struct tcm_loop_tpg, tl_se_tpg);
  1000 + tl_hba = tl_tpg->tl_hba;
  1001 +
  1002 + sd = scsi_device_lookup(tl_hba->sh, 0, tl_tpg->tl_tpgt,
  1003 + se_lun->unpacked_lun);
  1004 + if (!sd) {
  1005 + printk(KERN_ERR "Unable to locate struct scsi_device for %d:%d:"
  1006 + "%d\n", 0, tl_tpg->tl_tpgt, se_lun->unpacked_lun);
  1007 + return;
  1008 + }
  1009 + /*
  1010 + * Remove Linux/SCSI struct scsi_device by HCTL
  1011 + */
  1012 + scsi_remove_device(sd);
  1013 + scsi_device_put(sd);
  1014 +
  1015 + atomic_dec(&tl_tpg->tl_tpg_port_count);
  1016 + smp_mb__after_atomic_dec();
  1017 +
  1018 + printk(KERN_INFO "TCM_Loop_ConfigFS: Port Unlink Successful\n");
  1019 +}
  1020 +
  1021 +/* End items for tcm_loop_port_cit */
  1022 +
  1023 +/* Start items for tcm_loop_nexus_cit */
  1024 +
  1025 +static int tcm_loop_make_nexus(
  1026 + struct tcm_loop_tpg *tl_tpg,
  1027 + const char *name)
  1028 +{
  1029 + struct se_portal_group *se_tpg;
  1030 + struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
  1031 + struct tcm_loop_nexus *tl_nexus;
  1032 +
  1033 + if (tl_tpg->tl_hba->tl_nexus) {
  1034 + printk(KERN_INFO "tl_tpg->tl_hba->tl_nexus already exists\n");
  1035 + return -EEXIST;
  1036 + }
  1037 + se_tpg = &tl_tpg->tl_se_tpg;
  1038 +
  1039 + tl_nexus = kzalloc(sizeof(struct tcm_loop_nexus), GFP_KERNEL);
  1040 + if (!tl_nexus) {
  1041 + printk(KERN_ERR "Unable to allocate struct tcm_loop_nexus\n");
  1042 + return -ENOMEM;
  1043 + }
  1044 + /*
  1045 + * Initialize the struct se_session pointer
  1046 + */
  1047 + tl_nexus->se_sess = transport_init_session();
  1048 + if (!tl_nexus->se_sess)
  1049 + goto out;
  1050 + /*
  1051 + * Since we are running in 'demo mode' this call with generate a
  1052 + * struct se_node_acl for the tcm_loop struct se_portal_group with the SCSI
  1053 + * Initiator port name of the passed configfs group 'name'.
  1054 + */
  1055 + tl_nexus->se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
  1056 + se_tpg, (unsigned char *)name);
  1057 + if (!tl_nexus->se_sess->se_node_acl) {
  1058 + transport_free_session(tl_nexus->se_sess);
  1059 + goto out;
  1060 + }
  1061 + /*
  1062 + * Now, register the SAS I_T Nexus as active with the call to
  1063 + * transport_register_session()
  1064 + */
  1065 + __transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
  1066 + tl_nexus->se_sess, (void *)tl_nexus);
  1067 + tl_tpg->tl_hba->tl_nexus = tl_nexus;
  1068 + printk(KERN_INFO "TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
  1069 + " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
  1070 + name);
  1071 + return 0;
  1072 +
  1073 +out:
  1074 + kfree(tl_nexus);
  1075 + return -ENOMEM;
  1076 +}
  1077 +
  1078 +static int tcm_loop_drop_nexus(
  1079 + struct tcm_loop_tpg *tpg)
  1080 +{
  1081 + struct se_session *se_sess;
  1082 + struct tcm_loop_nexus *tl_nexus;
  1083 + struct tcm_loop_hba *tl_hba = tpg->tl_hba;
  1084 +
  1085 + tl_nexus = tpg->tl_hba->tl_nexus;
  1086 + if (!tl_nexus)
  1087 + return -ENODEV;
  1088 +
  1089 + se_sess = tl_nexus->se_sess;
  1090 + if (!se_sess)
  1091 + return -ENODEV;
  1092 +
  1093 + if (atomic_read(&tpg->tl_tpg_port_count)) {
  1094 + printk(KERN_ERR "Unable to remove TCM_Loop I_T Nexus with"
  1095 + " active TPG port count: %d\n",
  1096 + atomic_read(&tpg->tl_tpg_port_count));
  1097 + return -EPERM;
  1098 + }
  1099 +
  1100 + printk(KERN_INFO "TCM_Loop_ConfigFS: Removing I_T Nexus to emulated"
  1101 + " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
  1102 + tl_nexus->se_sess->se_node_acl->initiatorname);
  1103 + /*
  1104 + * Release the SCSI I_T Nexus to the emulated SAS Target Port
  1105 + */
  1106 + transport_deregister_session(tl_nexus->se_sess);
  1107 + tpg->tl_hba->tl_nexus = NULL;
  1108 + kfree(tl_nexus);
  1109 + return 0;
  1110 +}
  1111 +
  1112 +/* End items for tcm_loop_nexus_cit */
  1113 +
  1114 +static ssize_t tcm_loop_tpg_show_nexus(
  1115 + struct se_portal_group *se_tpg,
  1116 + char *page)
  1117 +{
  1118 + struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
  1119 + struct tcm_loop_tpg, tl_se_tpg);
  1120 + struct tcm_loop_nexus *tl_nexus;
  1121 + ssize_t ret;
  1122 +
  1123 + tl_nexus = tl_tpg->tl_hba->tl_nexus;
  1124 + if (!tl_nexus)
  1125 + return -ENODEV;
  1126 +
  1127 + ret = snprintf(page, PAGE_SIZE, "%s\n",
  1128 + tl_nexus->se_sess->se_node_acl->initiatorname);
  1129 +
  1130 + return ret;
  1131 +}
  1132 +
  1133 +static ssize_t tcm_loop_tpg_store_nexus(
  1134 + struct se_portal_group *se_tpg,
  1135 + const char *page,
  1136 + size_t count)
  1137 +{
  1138 + struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
  1139 + struct tcm_loop_tpg, tl_se_tpg);
  1140 + struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
  1141 + unsigned char i_port[TL_WWN_ADDR_LEN], *ptr, *port_ptr;
  1142 + int ret;
  1143 + /*
  1144 + * Shutdown the active I_T nexus if 'NULL' is passed..
  1145 + */
  1146 + if (!strncmp(page, "NULL", 4)) {
  1147 + ret = tcm_loop_drop_nexus(tl_tpg);
  1148 + return (!ret) ? count : ret;
  1149 + }
  1150 + /*
  1151 + * Otherwise make sure the passed virtual Initiator port WWN matches
  1152 + * the fabric protocol_id set in tcm_loop_make_scsi_hba(), and call
  1153 + * tcm_loop_make_nexus()
  1154 + */
  1155 + if (strlen(page) > TL_WWN_ADDR_LEN) {
  1156 + printk(KERN_ERR "Emulated NAA Sas Address: %s, exceeds"
  1157 + " max: %d\n", page, TL_WWN_ADDR_LEN);
  1158 + return -EINVAL;
  1159 + }
  1160 + snprintf(&i_port[0], TL_WWN_ADDR_LEN, "%s", page);
  1161 +
  1162 + ptr = strstr(i_port, "naa.");
  1163 + if (ptr) {
  1164 + if (tl_hba->tl_proto_id != SCSI_PROTOCOL_SAS) {
  1165 + printk(KERN_ERR "Passed SAS Initiator Port %s does not"
  1166 + " match target port protoid: %s\n", i_port,
  1167 + tcm_loop_dump_proto_id(tl_hba));
  1168 + return -EINVAL;
  1169 + }
  1170 + port_ptr = &i_port[0];
  1171 + goto check_newline;
  1172 + }
  1173 + ptr = strstr(i_port, "fc.");
  1174 + if (ptr) {
  1175 + if (tl_hba->tl_proto_id != SCSI_PROTOCOL_FCP) {
  1176 + printk(KERN_ERR "Passed FCP Initiator Port %s does not"
  1177 + " match target port protoid: %s\n", i_port,
  1178 + tcm_loop_dump_proto_id(tl_hba));
  1179 + return -EINVAL;
  1180 + }
  1181 + port_ptr = &i_port[3]; /* Skip over "fc." */
  1182 + goto check_newline;
  1183 + }
  1184 + ptr = strstr(i_port, "iqn.");
  1185 + if (ptr) {
  1186 + if (tl_hba->tl_proto_id != SCSI_PROTOCOL_ISCSI) {
  1187 + printk(KERN_ERR "Passed iSCSI Initiator Port %s does not"
  1188 + " match target port protoid: %s\n", i_port,
  1189 + tcm_loop_dump_proto_id(tl_hba));
  1190 + return -EINVAL;
  1191 + }
  1192 + port_ptr = &i_port[0];
  1193 + goto check_newline;
  1194 + }
  1195 + printk(KERN_ERR "Unable to locate prefix for emulated Initiator Port:"
  1196 + " %s\n", i_port);
  1197 + return -EINVAL;
  1198 + /*
  1199 + * Clear any trailing newline for the NAA WWN
  1200 + */
  1201 +check_newline:
  1202 + if (i_port[strlen(i_port)-1] == '\n')
  1203 + i_port[strlen(i_port)-1] = '\0';
  1204 +
  1205 + ret = tcm_loop_make_nexus(tl_tpg, port_ptr);
  1206 + if (ret < 0)
  1207 + return ret;
  1208 +
  1209 + return count;
  1210 +}
  1211 +
  1212 +TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR);
  1213 +
  1214 +static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
  1215 + &tcm_loop_tpg_nexus.attr,
  1216 + NULL,
  1217 +};
  1218 +
  1219 +/* Start items for tcm_loop_naa_cit */
  1220 +
  1221 +struct se_portal_group *tcm_loop_make_naa_tpg(
  1222 + struct se_wwn *wwn,
  1223 + struct config_group *group,
  1224 + const char *name)
  1225 +{
  1226 + struct tcm_loop_hba *tl_hba = container_of(wwn,
  1227 + struct tcm_loop_hba, tl_hba_wwn);
  1228 + struct tcm_loop_tpg *tl_tpg;
  1229 + char *tpgt_str, *end_ptr;
  1230 + int ret;
  1231 + unsigned short int tpgt;
  1232 +
  1233 + tpgt_str = strstr(name, "tpgt_");
  1234 + if (!tpgt_str) {
  1235 + printk(KERN_ERR "Unable to locate \"tpgt_#\" directory"
  1236 + " group\n");
  1237 + return ERR_PTR(-EINVAL);
  1238 + }
  1239 + tpgt_str += 5; /* Skip ahead of "tpgt_" */
  1240 + tpgt = (unsigned short int) simple_strtoul(tpgt_str, &end_ptr, 0);
  1241 +
  1242 + if (tpgt > TL_TPGS_PER_HBA) {
  1243 + printk(KERN_ERR "Passed tpgt: %hu exceeds TL_TPGS_PER_HBA:"
  1244 + " %u\n", tpgt, TL_TPGS_PER_HBA);
  1245 + return ERR_PTR(-EINVAL);
  1246 + }
  1247 + tl_tpg = &tl_hba->tl_hba_tpgs[tpgt];
  1248 + tl_tpg->tl_hba = tl_hba;
  1249 + tl_tpg->tl_tpgt = tpgt;
  1250 + /*
  1251 + * Register the tl_tpg as a emulated SAS TCM Target Endpoint
  1252 + */
  1253 + ret = core_tpg_register(&tcm_loop_fabric_configfs->tf_ops,
  1254 + wwn, &tl_tpg->tl_se_tpg, (void *)tl_tpg,
  1255 + TRANSPORT_TPG_TYPE_NORMAL);
  1256 + if (ret < 0)
  1257 + return ERR_PTR(-ENOMEM);
  1258 +
  1259 + printk(KERN_INFO "TCM_Loop_ConfigFS: Allocated Emulated %s"
  1260 + " Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
  1261 + config_item_name(&wwn->wwn_group.cg_item), tpgt);
  1262 +
  1263 + return &tl_tpg->tl_se_tpg;
  1264 +}
  1265 +
  1266 +void tcm_loop_drop_naa_tpg(
  1267 + struct se_portal_group *se_tpg)
  1268 +{
  1269 + struct se_wwn *wwn = se_tpg->se_tpg_wwn;
  1270 + struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
  1271 + struct tcm_loop_tpg, tl_se_tpg);
  1272 + struct tcm_loop_hba *tl_hba;
  1273 + unsigned short tpgt;
  1274 +
  1275 + tl_hba = tl_tpg->tl_hba;
  1276 + tpgt = tl_tpg->tl_tpgt;
  1277 + /*
  1278 + * Release the I_T Nexus for the Virtual SAS link if present
  1279 + */
  1280 + tcm_loop_drop_nexus(tl_tpg);
  1281 + /*
  1282 + * Deregister the tl_tpg as a emulated SAS TCM Target Endpoint
  1283 + */
  1284 + core_tpg_deregister(se_tpg);
  1285 +
  1286 + printk(KERN_INFO "TCM_Loop_ConfigFS: Deallocated Emulated %s"
  1287 + " Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
  1288 + config_item_name(&wwn->wwn_group.cg_item), tpgt);
  1289 +}
  1290 +
  1291 +/* End items for tcm_loop_naa_cit */
  1292 +
  1293 +/* Start items for tcm_loop_cit */
  1294 +
  1295 +struct se_wwn *tcm_loop_make_scsi_hba(
  1296 + struct target_fabric_configfs *tf,
  1297 + struct config_group *group,
  1298 + const char *name)
  1299 +{
  1300 + struct tcm_loop_hba *tl_hba;
  1301 + struct Scsi_Host *sh;
  1302 + char *ptr;
  1303 + int ret, off = 0;
  1304 +
  1305 + tl_hba = kzalloc(sizeof(struct tcm_loop_hba), GFP_KERNEL);
  1306 + if (!tl_hba) {
  1307 + printk(KERN_ERR "Unable to allocate struct tcm_loop_hba\n");
  1308 + return ERR_PTR(-ENOMEM);
  1309 + }
  1310 + /*
  1311 + * Determine the emulated Protocol Identifier and Target Port Name
  1312 + * based on the incoming configfs directory name.
  1313 + */
  1314 + ptr = strstr(name, "naa.");
  1315 + if (ptr) {
  1316 + tl_hba->tl_proto_id = SCSI_PROTOCOL_SAS;
  1317 + goto check_len;
  1318 + }
  1319 + ptr = strstr(name, "fc.");
  1320 + if (ptr) {
  1321 + tl_hba->tl_proto_id = SCSI_PROTOCOL_FCP;
  1322 + off = 3; /* Skip over "fc." */
  1323 + goto check_len;
  1324 + }
  1325 + ptr = strstr(name, "iqn.");
  1326 + if (ptr) {
  1327 + tl_hba->tl_proto_id = SCSI_PROTOCOL_ISCSI;
  1328 + goto check_len;
  1329 + }
  1330 +
  1331 + printk(KERN_ERR "Unable to locate prefix for emulated Target Port:"
  1332 + " %s\n", name);
  1333 + return ERR_PTR(-EINVAL);
  1334 +
  1335 +check_len:
  1336 + if (strlen(name) > TL_WWN_ADDR_LEN) {
  1337 + printk(KERN_ERR "Emulated NAA %s Address: %s, exceeds"
  1338 + " max: %d\n", name, tcm_loop_dump_proto_id(tl_hba),
  1339 + TL_WWN_ADDR_LEN);
  1340 + kfree(tl_hba);
  1341 + return ERR_PTR(-EINVAL);
  1342 + }
  1343 + snprintf(&tl_hba->tl_wwn_address[0], TL_WWN_ADDR_LEN, "%s", &name[off]);
  1344 +
  1345 + /*
  1346 + * Call device_register(tl_hba->dev) to register the emulated
  1347 + * Linux/SCSI LLD of type struct Scsi_Host at tl_hba->sh after
  1348 + * device_register() callbacks in tcm_loop_driver_probe()
  1349 + */
  1350 + ret = tcm_loop_setup_hba_bus(tl_hba, tcm_loop_hba_no_cnt);
  1351 + if (ret)
  1352 + goto out;
  1353 +
  1354 + sh = tl_hba->sh;
  1355 + tcm_loop_hba_no_cnt++;
  1356 + printk(KERN_INFO "TCM_Loop_ConfigFS: Allocated emulated Target"
  1357 + " %s Address: %s at Linux/SCSI Host ID: %d\n",
  1358 + tcm_loop_dump_proto_id(tl_hba), name, sh->host_no);
  1359 +
  1360 + return &tl_hba->tl_hba_wwn;
  1361 +out:
  1362 + kfree(tl_hba);
  1363 + return ERR_PTR(ret);
  1364 +}
  1365 +
  1366 +void tcm_loop_drop_scsi_hba(
  1367 + struct se_wwn *wwn)
  1368 +{
  1369 + struct tcm_loop_hba *tl_hba = container_of(wwn,
  1370 + struct tcm_loop_hba, tl_hba_wwn);
  1371 + int host_no = tl_hba->sh->host_no;
  1372 + /*
  1373 + * Call device_unregister() on the original tl_hba->dev.
  1374 + * tcm_loop_fabric_scsi.c:tcm_loop_release_adapter() will
  1375 + * release *tl_hba;
  1376 + */
  1377 + device_unregister(&tl_hba->dev);
  1378 +
  1379 + printk(KERN_INFO "TCM_Loop_ConfigFS: Deallocated emulated Target"
  1380 + " SAS Address: %s at Linux/SCSI Host ID: %d\n",
  1381 + config_item_name(&wwn->wwn_group.cg_item), host_no);
  1382 +}
  1383 +
  1384 +/* Start items for tcm_loop_cit */
  1385 +static ssize_t tcm_loop_wwn_show_attr_version(
  1386 + struct target_fabric_configfs *tf,
  1387 + char *page)
  1388 +{
  1389 + return sprintf(page, "TCM Loopback Fabric module %s\n", TCM_LOOP_VERSION);
  1390 +}
  1391 +
  1392 +TF_WWN_ATTR_RO(tcm_loop, version);
  1393 +
  1394 +static struct configfs_attribute *tcm_loop_wwn_attrs[] = {
  1395 + &tcm_loop_wwn_version.attr,
  1396 + NULL,
  1397 +};
  1398 +
  1399 +/* End items for tcm_loop_cit */
  1400 +
  1401 +static int tcm_loop_register_configfs(void)
  1402 +{
  1403 + struct target_fabric_configfs *fabric;
  1404 + struct config_group *tf_cg;
  1405 + int ret;
  1406 + /*
  1407 + * Set the TCM Loop HBA counter to zero
  1408 + */
  1409 + tcm_loop_hba_no_cnt = 0;
  1410 + /*
  1411 + * Register the top level struct config_item_type with TCM core
  1412 + */
  1413 + fabric = target_fabric_configfs_init(THIS_MODULE, "loopback");
  1414 + if (!fabric) {
  1415 + printk(KERN_ERR "tcm_loop_register_configfs() failed!\n");
  1416 + return -1;
  1417 + }
  1418 + /*
  1419 + * Setup the fabric API of function pointers used by target_core_mod
  1420 + */
  1421 + fabric->tf_ops.get_fabric_name = &tcm_loop_get_fabric_name;
  1422 + fabric->tf_ops.get_fabric_proto_ident = &tcm_loop_get_fabric_proto_ident;
  1423 + fabric->tf_ops.tpg_get_wwn = &tcm_loop_get_endpoint_wwn;
  1424 + fabric->tf_ops.tpg_get_tag = &tcm_loop_get_tag;
  1425 + fabric->tf_ops.tpg_get_default_depth = &tcm_loop_get_default_depth;
  1426 + fabric->tf_ops.tpg_get_pr_transport_id = &tcm_loop_get_pr_transport_id;
  1427 + fabric->tf_ops.tpg_get_pr_transport_id_len =
  1428 + &tcm_loop_get_pr_transport_id_len;
  1429 + fabric->tf_ops.tpg_parse_pr_out_transport_id =
  1430 + &tcm_loop_parse_pr_out_transport_id;
  1431 + fabric->tf_ops.tpg_check_demo_mode = &tcm_loop_check_demo_mode;
  1432 + fabric->tf_ops.tpg_check_demo_mode_cache =
  1433 + &tcm_loop_check_demo_mode_cache;
  1434 + fabric->tf_ops.tpg_check_demo_mode_write_protect =
  1435 + &tcm_loop_check_demo_mode_write_protect;
  1436 + fabric->tf_ops.tpg_check_prod_mode_write_protect =
  1437 + &tcm_loop_check_prod_mode_write_protect;
  1438 + /*
  1439 + * The TCM loopback fabric module runs in demo-mode to a local
  1440 + * virtual SCSI device, so fabric dependent initator ACLs are
  1441 + * not required.
  1442 + */
  1443 + fabric->tf_ops.tpg_alloc_fabric_acl = &tcm_loop_tpg_alloc_fabric_acl;
  1444 + fabric->tf_ops.tpg_release_fabric_acl =
  1445 + &tcm_loop_tpg_release_fabric_acl;
  1446 + fabric->tf_ops.tpg_get_inst_index = &tcm_loop_get_inst_index;
  1447 + /*
  1448 + * Since tcm_loop is mapping physical memory from Linux/SCSI
  1449 + * struct scatterlist arrays for each struct scsi_cmnd I/O,
  1450 + * we do not need TCM to allocate a iovec array for
  1451 + * virtual memory address mappings
  1452 + */
  1453 + fabric->tf_ops.alloc_cmd_iovecs = NULL;
  1454 + /*
  1455 + * Used for setting up remaining TCM resources in process context
  1456 + */
  1457 + fabric->tf_ops.new_cmd_map = &tcm_loop_new_cmd_map;
  1458 + fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free;
  1459 + fabric->tf_ops.release_cmd_to_pool = &tcm_loop_deallocate_core_cmd;
  1460 + fabric->tf_ops.release_cmd_direct = &tcm_loop_deallocate_core_cmd;
  1461 + fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session;
  1462 + fabric->tf_ops.close_session = &tcm_loop_close_session;
  1463 + fabric->tf_ops.stop_session = &tcm_loop_stop_session;
  1464 + fabric->tf_ops.fall_back_to_erl0 = &tcm_loop_fall_back_to_erl0;
  1465 + fabric->tf_ops.sess_logged_in = &tcm_loop_sess_logged_in;
  1466 + fabric->tf_ops.sess_get_index = &tcm_loop_sess_get_index;
  1467 + fabric->tf_ops.sess_get_initiator_sid = NULL;
  1468 + fabric->tf_ops.write_pending = &tcm_loop_write_pending;
  1469 + fabric->tf_ops.write_pending_status = &tcm_loop_write_pending_status;
  1470 + /*
  1471 + * Not used for TCM loopback
  1472 + */
  1473 + fabric->tf_ops.set_default_node_attributes =
  1474 + &tcm_loop_set_default_node_attributes;
  1475 + fabric->tf_ops.get_task_tag = &tcm_loop_get_task_tag;
  1476 + fabric->tf_ops.get_cmd_state = &tcm_loop_get_cmd_state;
  1477 + fabric->tf_ops.new_cmd_failure = &tcm_loop_new_cmd_failure;
  1478 + fabric->tf_ops.queue_data_in = &tcm_loop_queue_data_in;
  1479 + fabric->tf_ops.queue_status = &tcm_loop_queue_status;
  1480 + fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp;
  1481 + fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len;
  1482 + fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len;
  1483 + fabric->tf_ops.is_state_remove = &tcm_loop_is_state_remove;
  1484 + fabric->tf_ops.pack_lun = &tcm_loop_pack_lun;
  1485 +
  1486 + tf_cg = &fabric->tf_group;
  1487 + /*
  1488 + * Setup function pointers for generic logic in target_core_fabric_configfs.c
  1489 + */
  1490 + fabric->tf_ops.fabric_make_wwn = &tcm_loop_make_scsi_hba;
  1491 + fabric->tf_ops.fabric_drop_wwn = &tcm_loop_drop_scsi_hba;
  1492 + fabric->tf_ops.fabric_make_tpg = &tcm_loop_make_naa_tpg;
  1493 + fabric->tf_ops.fabric_drop_tpg = &tcm_loop_drop_naa_tpg;
  1494 + /*
  1495 + * fabric_post_link() and fabric_pre_unlink() are used for
  1496 + * registration and release of TCM Loop Virtual SCSI LUNs.
  1497 + */
  1498 + fabric->tf_ops.fabric_post_link = &tcm_loop_port_link;
  1499 + fabric->tf_ops.fabric_pre_unlink = &tcm_loop_port_unlink;
  1500 + fabric->tf_ops.fabric_make_np = NULL;
  1501 + fabric->tf_ops.fabric_drop_np = NULL;
  1502 + /*
  1503 + * Setup default attribute lists for various fabric->tf_cit_tmpl
  1504 + */
  1505 + TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = tcm_loop_wwn_attrs;
  1506 + TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = tcm_loop_tpg_attrs;
  1507 + TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL;
  1508 + TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;
  1509 + TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;
  1510 + /*
  1511 + * Once fabric->tf_ops has been setup, now register the fabric for
  1512 + * use within TCM
  1513 + */
  1514 + ret = target_fabric_configfs_register(fabric);
  1515 + if (ret < 0) {
  1516 + printk(KERN_ERR "target_fabric_configfs_register() for"
  1517 + " TCM_Loop failed!\n");
  1518 + target_fabric_configfs_free(fabric);
  1519 + return -1;
  1520 + }
  1521 + /*
  1522 + * Setup our local pointer to *fabric.
  1523 + */
  1524 + tcm_loop_fabric_configfs = fabric;
  1525 + printk(KERN_INFO "TCM_LOOP[0] - Set fabric ->"
  1526 + " tcm_loop_fabric_configfs\n");
  1527 + return 0;
  1528 +}
  1529 +
  1530 +static void tcm_loop_deregister_configfs(void)
  1531 +{
  1532 + if (!tcm_loop_fabric_configfs)
  1533 + return;
  1534 +
  1535 + target_fabric_configfs_deregister(tcm_loop_fabric_configfs);
  1536 + tcm_loop_fabric_configfs = NULL;
  1537 + printk(KERN_INFO "TCM_LOOP[0] - Cleared"
  1538 + " tcm_loop_fabric_configfs\n");
  1539 +}
  1540 +
  1541 +static int __init tcm_loop_fabric_init(void)
  1542 +{
  1543 + int ret;
  1544 +
  1545 + tcm_loop_cmd_cache = kmem_cache_create("tcm_loop_cmd_cache",
  1546 + sizeof(struct tcm_loop_cmd),
  1547 + __alignof__(struct tcm_loop_cmd),
  1548 + 0, NULL);
  1549 + if (!tcm_loop_cmd_cache) {
  1550 + printk(KERN_ERR "kmem_cache_create() for"
  1551 + " tcm_loop_cmd_cache failed\n");
  1552 + return -ENOMEM;
  1553 + }
  1554 +
  1555 + ret = tcm_loop_alloc_core_bus();
  1556 + if (ret)
  1557 + return ret;
  1558 +
  1559 + ret = tcm_loop_register_configfs();
  1560 + if (ret) {
  1561 + tcm_loop_release_core_bus();
  1562 + return ret;
  1563 + }
  1564 +
  1565 + return 0;
  1566 +}
  1567 +
  1568 +static void __exit tcm_loop_fabric_exit(void)
  1569 +{
  1570 + tcm_loop_deregister_configfs();
  1571 + tcm_loop_release_core_bus();
  1572 + kmem_cache_destroy(tcm_loop_cmd_cache);
  1573 +}
  1574 +
  1575 +MODULE_DESCRIPTION("TCM loopback virtual Linux/SCSI fabric module");
  1576 +MODULE_AUTHOR("Nicholas A. Bellinger <nab@risingtidesystems.com>");
  1577 +MODULE_LICENSE("GPL");
  1578 +module_init(tcm_loop_fabric_init);
  1579 +module_exit(tcm_loop_fabric_exit);
drivers/target/loopback/tcm_loop.h
  1 +#define TCM_LOOP_VERSION "v2.1-rc1"
  2 +#define TL_WWN_ADDR_LEN 256
  3 +#define TL_TPGS_PER_HBA 32
  4 +/*
  5 + * Defaults for struct scsi_host_template tcm_loop_driver_template
  6 + *
  7 + * We use large can_queue and cmd_per_lun here and let TCM enforce
  8 + * the underlying se_device_t->queue_depth.
  9 + */
  10 +#define TL_SCSI_CAN_QUEUE 1024
  11 +#define TL_SCSI_CMD_PER_LUN 1024
  12 +#define TL_SCSI_MAX_SECTORS 1024
  13 +#define TL_SCSI_SG_TABLESIZE 256
  14 +/*
  15 + * Used in tcm_loop_driver_probe() for struct Scsi_Host->max_cmd_len
  16 + */
  17 +#define TL_SCSI_MAX_CMD_LEN 32
  18 +
  19 +#ifdef CONFIG_LOOPBACK_TARGET_CDB_DEBUG
  20 +# define TL_CDB_DEBUG(x...) printk(KERN_INFO x)
  21 +#else
  22 +# define TL_CDB_DEBUG(x...)
  23 +#endif
  24 +
  25 +struct tcm_loop_cmd {
  26 + /* State of Linux/SCSI CDB+Data descriptor */
  27 + u32 sc_cmd_state;
  28 + /* Pointer to the CDB+Data descriptor from Linux/SCSI subsystem */
  29 + struct scsi_cmnd *sc;
  30 + struct list_head *tl_cmd_list;
  31 + /* The TCM I/O descriptor that is accessed via container_of() */
  32 + struct se_cmd tl_se_cmd;
  33 + /* Sense buffer that will be mapped into outgoing status */
  34 + unsigned char tl_sense_buf[TRANSPORT_SENSE_BUFFER];
  35 +};
  36 +
  37 +struct tcm_loop_tmr {
  38 + atomic_t tmr_complete;
  39 + wait_queue_head_t tl_tmr_wait;
  40 +};
  41 +
  42 +struct tcm_loop_nexus {
  43 + int it_nexus_active;
  44 + /*
  45 + * Pointer to Linux/SCSI HBA from linux/include/scsi_host.h
  46 + */
  47 + struct scsi_host *sh;
  48 + /*
  49 + * Pointer to TCM session for I_T Nexus
  50 + */
  51 + struct se_session *se_sess;
  52 +};
  53 +
  54 +struct tcm_loop_nacl {
  55 + struct se_node_acl se_node_acl;
  56 +};
  57 +
  58 +struct tcm_loop_tpg {
  59 + unsigned short tl_tpgt;
  60 + atomic_t tl_tpg_port_count;
  61 + struct se_portal_group tl_se_tpg;
  62 + struct tcm_loop_hba *tl_hba;
  63 +};
  64 +
  65 +struct tcm_loop_hba {
  66 + u8 tl_proto_id;
  67 + unsigned char tl_wwn_address[TL_WWN_ADDR_LEN];
  68 + struct se_hba_s *se_hba;
  69 + struct se_lun *tl_hba_lun;
  70 + struct se_port *tl_hba_lun_sep;
  71 + struct se_device_s *se_dev_hba_ptr;
  72 + struct tcm_loop_nexus *tl_nexus;
  73 + struct device dev;
  74 + struct Scsi_Host *sh;
  75 + struct tcm_loop_tpg tl_hba_tpgs[TL_TPGS_PER_HBA];
  76 + struct se_wwn tl_hba_wwn;
  77 +};