2 * Copyright (C) 2008 Richard Sharpe
3 * Copyright (C) 1992 Eric Youngdale
4 * Copyright (C) 2008 - 2009 Vladislav Bolkhovitin <vst@vlnb.net>
6 * Simulate a host adapter and an SCST target adapter back to back
8 * Based on the scsi_debug.c driver originally by Eric Youngdale and
9 * others, including D Gilbert et al
13 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/timer.h>
18 #include <linux/types.h>
19 #include <linux/string.h>
20 #include <linux/genhd.h>
22 #include <linux/init.h>
23 #include <linux/proc_fs.h>
24 #include <linux/vmalloc.h>
25 #include <linux/moduleparam.h>
26 #include <linux/scatterlist.h>
27 #include <linux/blkdev.h>
28 #include <linux/completion.h>
29 #include <linux/stat.h>
31 #include <scsi/scsi.h>
32 #include <scsi/scsi_cmnd.h>
33 #include <scsi/scsi_device.h>
34 #include <scsi/scsi_host.h>
35 #include <scsi/scsi_tcq.h>
36 #include <scsi/scsicam.h>
37 #include <scsi/scsi_eh.h>
39 /* SCST includes ... */
40 #include <scst_const.h>
43 #define LOG_PREFIX "scst_local"
45 #include <scst_debug.h>
47 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
48 #define SCSI_MAX_SG_SEGMENTS 128
51 #if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G)
52 #warning "HIGHMEM kernel configurations are not supported by this module,\
53 because nowadays it isn't worth the effort. Consider changing\
54 VMSPLIT option or use a 64-bit configuration instead. See SCST core\
55 README file for details."
58 #ifdef CONFIG_SCST_DEBUG
59 #define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_PID | \
60 TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_MINOR | \
61 TRACE_MGMT_DEBUG | TRACE_MINOR | TRACE_SPECIAL)
63 # ifdef CONFIG_SCST_TRACING
64 #define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
65 TRACE_MINOR | TRACE_SPECIAL)
69 #if defined(CONFIG_SCST_DEBUG)
70 #define trace_flag scst_local_trace_flag
71 static unsigned long scst_local_trace_flag = SCST_LOCAL_DEFAULT_LOG_FLAGS;
75 * Provide some local definitions that are not provided for some earlier
76 * kernels so we operate over a wider range of kernels
78 * Some time before 2.6.24 scsi_sg_count, scsi_sglist and scsi_bufflen were
79 * not available. Make it available for 2.6.18 which is used still on some
80 * distros, like CentOS etc.
83 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
84 #define scsi_sg_count(cmd) ((cmd)->use_sg)
85 #define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
86 #define scsi_bufflen(cmd) ((cmd)->request_bufflen)
93 * Some definitions needed by the scst portion
95 static void scst_local_remove_adapter(void);
96 static int scst_local_add_adapter(void);
98 #define SCST_LOCAL_VERSION "0.9.2"
99 static const char *scst_local_version_date = "20090614";
102 * Target structures that are shared between the two pieces
103 * This will have to change if we have more than one target
105 static struct scst_tgt_template scst_local_targ_tmpl;
110 #define DEF_NUM_HOST 1
111 #define DEF_NUM_TGTS 1
112 #define SCST_LOCAL_MAX_TARGETS 16
113 #define DEF_MAX_LUNS 256
116 * These following defines are the SCSI Host LLD (the initiator).
117 * SCST Target Driver is below
120 static int scst_local_add_host = DEF_NUM_HOST;
121 static int scst_local_num_tgts = DEF_NUM_TGTS;
122 static int scst_local_max_luns = DEF_MAX_LUNS;
124 static int num_aborts;
125 static int num_dev_resets;
126 static int num_target_resets;
129 * Each host has multiple targets, each of which has a separate session
133 struct scst_local_host_info {
134 struct list_head host_list;
135 struct Scsi_Host *shost;
136 struct scst_tgt *target;
137 struct scst_session *session[SCST_LOCAL_MAX_TARGETS];
142 #define to_scst_lcl_host(d) \
143 container_of(d, struct scst_local_host_info, dev)
146 * Maintains data that is needed during command processing ...
147 * We have a single element scatterlist in here in case the scst_cmnd
148 * we are given has a buffer, not a scatterlist, but we only need this for
149 * kernels less than 2.6.25.
151 struct scst_local_tgt_specific {
152 struct scsi_cmnd *cmnd;
153 void (*done)(struct scsi_cmnd *);
154 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
155 struct scatterlist sgl;
160 * We use a pool of objects maintaind by the kernel so that it is less
161 * likely to have to allocate them when we are in the data path.
163 static struct kmem_cache *tgt_specific_pool;
165 static LIST_HEAD(scst_local_host_list);
166 static DEFINE_SPINLOCK(scst_local_host_list_lock);
168 static char scst_local_proc_name[] = "scst_ini_targ_debug";
170 static struct bus_type scst_fake_lld_bus;
171 static struct device scst_fake_primary;
173 static struct device_driver scst_local_driverfs_driver = {
174 .name = scst_local_proc_name,
175 .bus = &scst_fake_lld_bus,
178 module_param_named(add_host, scst_local_add_host, int, S_IRUGO | S_IWUSR);
179 module_param_named(num_tgts, scst_local_num_tgts, int, S_IRUGO | S_IWUSR);
180 module_param_named(max_luns, scst_local_max_luns, int, S_IRUGO | S_IWUSR);
182 MODULE_AUTHOR("Richard Sharpe + ideas from SCSI_DEBUG");
183 MODULE_DESCRIPTION("SCSI+SCST local adapter driver");
184 MODULE_LICENSE("GPL");
185 MODULE_VERSION(SCST_LOCAL_VERSION);
187 MODULE_PARM_DESC(add_host, "0..127 hosts can be created (def=1)");
188 MODULE_PARM_DESC(num_tgts, "mumber of targets per host (def=1)");
189 MODULE_PARM_DESC(max_luns, "number of luns per target (def=1)");
191 static int scst_local_target_register(void);
193 static int scst_local_proc_info(struct Scsi_Host *host, char *buffer,
194 char **start, off_t offset, int length,
205 pos = len = sprintf(buffer, "scst_local adapter driver, version "
207 "num_tgts=%d, Aborts=%d, Device Resets=%d, "
208 "Target Resets=%d\n",
209 SCST_LOCAL_VERSION, scst_local_version_date,
210 scst_local_num_tgts, num_aborts, num_dev_resets,
217 *start = buffer + (offset - begin);
218 len -= (offset - begin);
226 static ssize_t scst_local_add_host_show(struct device_driver *ddp, char *buf)
229 struct scst_local_host_info *scst_lcl_host, *tmp;
233 list_for_each_entry_safe(scst_lcl_host, tmp, &scst_local_host_list,
235 len += scnprintf(&buf[len], PAGE_SIZE - len, " Initiator: %s\n",
236 scst_lcl_host->session[0]->initiator_name);
243 static ssize_t scst_local_add_host_store(struct device_driver *ddp,
244 const char *buf, size_t count)
250 if (sscanf(buf, "%d", &delta_hosts) != 1)
252 if (delta_hosts > 0) {
254 scst_local_add_adapter();
255 } while (--delta_hosts);
256 } else if (delta_hosts < 0) {
258 scst_local_remove_adapter();
259 } while (++delta_hosts);
262 TRACE_EXIT_RES(count);
266 static DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, scst_local_add_host_show,
267 scst_local_add_host_store);
269 static int do_create_driverfs_files(void)
275 ret = driver_create_file(&scst_local_driverfs_driver,
276 &driver_attr_add_host);
282 static void do_remove_driverfs_files(void)
284 driver_remove_file(&scst_local_driverfs_driver,
285 &driver_attr_add_host);
288 static char scst_local_info_buf[256];
290 static const char *scst_local_info(struct Scsi_Host *shp)
294 sprintf(scst_local_info_buf, "scst_local, version %s [%s], "
295 "Aborts: %d, Device Resets: %d, Target Resets: %d",
296 SCST_LOCAL_VERSION, scst_local_version_date,
297 num_aborts, num_dev_resets, num_target_resets);
300 return scst_local_info_buf;
304 static int scst_local_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
308 if (scst_local_opt_noise & SCST_LOCAL_OPT_LLD_NOISE)
309 printk(KERN_INFO "scst_local: ioctl: cmd=0x%x\n", cmd);
316 static int scst_local_abort(struct scsi_cmnd *SCpnt)
318 struct scst_local_host_info *scst_lcl_host;
320 DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
324 scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
326 ret = scst_rx_mgmt_fn_tag(scst_lcl_host->session[SCpnt->device->id],
327 SCST_ABORT_TASK, SCpnt->tag, FALSE,
328 &dev_reset_completion);
330 wait_for_completion_interruptible(&dev_reset_completion);
339 * We issue a mgmt function. We should pass a structure to the function
340 * that contains our private data, so we can retrieve the status from the
341 * done routine ... TODO
343 static int scst_local_device_reset(struct scsi_cmnd *SCpnt)
345 struct scst_local_host_info *scst_lcl_host;
348 DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
352 scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
354 lun = SCpnt->device->lun;
355 lun = (lun & 0xFF) << 8 | ((lun & 0xFF00) >> 8); /* FIXME: LE only */
357 ret = scst_rx_mgmt_fn_lun(scst_lcl_host->session[SCpnt->device->id],
359 (const uint8_t *)&lun,
361 &dev_reset_completion);
364 * Now wait for the completion ...
366 wait_for_completion_interruptible(&dev_reset_completion);
374 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25))
375 static int scst_local_target_reset(struct scsi_cmnd *SCpnt)
377 struct scst_local_host_info *scst_lcl_host;
380 DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
384 scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
386 lun = SCpnt->device->lun;
387 lun = (lun & 0xFF) << 8 | ((lun & 0xFF00) >> 8); /* FIXME: LE only */
389 ret = scst_rx_mgmt_fn_lun(scst_lcl_host->session[SCpnt->device->id],
391 (const uint8_t *)&lun,
393 &dev_reset_completion);
396 * Now wait for the completion ...
398 wait_for_completion_interruptible(&dev_reset_completion);
407 static void copy_sense(struct scsi_cmnd *cmnd, struct scst_cmd *scst_cmnd)
409 int scst_cmnd_sense_len = scst_cmd_get_sense_buffer_len(scst_cmnd);
413 scst_cmnd_sense_len = (SCSI_SENSE_BUFFERSIZE < scst_cmnd_sense_len ?
414 SCSI_SENSE_BUFFERSIZE : scst_cmnd_sense_len);
415 memcpy(cmnd->sense_buffer, scst_cmd_get_sense_buffer(scst_cmnd),
416 scst_cmnd_sense_len);
418 TRACE_BUFFER("Sense set", cmnd->sense_buffer, scst_cmnd_sense_len);
425 * Utility function to handle processing of done and allow
426 * easy insertion of error injection if desired
428 static int scst_local_send_resp(struct scsi_cmnd *cmnd,
429 struct scst_cmd *scst_cmnd,
430 void (*done)(struct scsi_cmnd *),
437 if (cmnd && scst_cmnd) {
438 /* Simulate autosense by this driver */
439 if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xFF))
440 copy_sense(cmnd, scst_cmnd);
444 cmnd->result = scsi_result;
453 * This does the heavy lifting ... we pass all the commands on to the
454 * target driver and have it do its magic ...
456 static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
457 void (*done)(struct scsi_cmnd *))
458 __acquires(&h->host_lock)
459 __releases(&h->host_lock)
461 struct scst_local_tgt_specific *tgt_specific = NULL;
462 struct scst_local_host_info *scst_lcl_host;
463 struct scatterlist *sgl = NULL;
465 int target = SCpnt->device->id;
467 struct scst_cmd *scst_cmd = NULL;
468 scst_data_direction dir;
472 TRACE_DBG("targ: %d, init id %d, lun %d, cmd: 0X%02X\n",
473 target, SCpnt->device->host->hostt->this_id, SCpnt->device->lun,
476 scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
478 scsi_set_resid(SCpnt, 0);
480 if (target == SCpnt->device->host->hostt->this_id) {
481 printk(KERN_ERR "%s: initiator's id used as target\n",
483 return scst_local_send_resp(SCpnt, NULL, done,
484 DID_NO_CONNECT << 16);
488 * Tell the target that we have a command ... but first we need
489 * to get the LUN into a format that SCST understand
491 lun = SCpnt->device->lun;
492 lun = (lun & 0xFF) << 8 | ((lun & 0xFF00) >> 8); /* FIXME: LE only */
493 scst_cmd = scst_rx_cmd(scst_lcl_host->session[SCpnt->device->id],
494 (const uint8_t *)&lun,
495 sizeof(lun), SCpnt->cmnd,
496 SCpnt->cmd_len, TRUE);
498 printk(KERN_ERR "%s out of memory at line %d\n",
503 scst_cmd_set_tag(scst_cmd, SCpnt->tag);
504 switch (scsi_get_tag_type(SCpnt->device)) {
506 scst_cmd->queue_type = SCST_CMD_QUEUE_SIMPLE;
509 scst_cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
511 case MSG_ORDERED_TAG:
512 scst_cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
516 scst_cmd->queue_type = SCST_CMD_QUEUE_UNTAGGED;
521 * Get some memory to keep track of the cmnd and the done routine
523 tgt_specific = kmem_cache_alloc(tgt_specific_pool, GFP_ATOMIC);
525 printk(KERN_ERR "%s out of memory at line %d\n",
529 tgt_specific->cmnd = SCpnt;
530 tgt_specific->done = done;
533 * If the command has a request, not a scatterlist, then convert it
534 * to one. We use scsi_sg_count to isolate us from the changes from
537 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
538 if (scsi_sg_count(SCpnt)) {
539 sgl = scsi_sglist(SCpnt);
540 sgl_count = scsi_sg_count(SCpnt);
543 * Build a one-element scatter list out of the buffer
544 * We will not even get here if the kernel version we
545 * are building on only supports scatterlists. See #if above.
547 * We use the sglist and bufflen function/macros to isolate
548 * us from kernel version differences.
550 if (scsi_sglist(SCpnt)) {
551 sg_init_one(&(tgt_specific->sgl),
552 (const void *)scsi_sglist(SCpnt),
553 scsi_bufflen(SCpnt));
554 sgl = &(tgt_specific->sgl);
562 sgl = scsi_sglist(SCpnt);
563 sgl_count = scsi_sg_count(SCpnt);
566 dir = SCST_DATA_NONE;
567 switch (SCpnt->sc_data_direction) {
569 dir = SCST_DATA_WRITE;
570 scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
571 scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count);
573 case DMA_FROM_DEVICE:
574 dir = SCST_DATA_READ;
575 scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
576 scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count);
578 case DMA_BIDIRECTIONAL:
579 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 24))
580 /* Some of these symbols are only defined after 2.6.24 */
581 dir = SCST_DATA_BIDI;
582 scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
583 scst_cmd_set_expected_in_transfer_len(scst_cmd,
584 scsi_in(SCpnt)->length);
585 scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count);
586 scst_cmd_set_tgt_in_sg(scst_cmd, scsi_in(SCpnt)->table.sgl,
587 scsi_in(SCpnt)->table.nents);
592 dir = SCST_DATA_NONE;
593 scst_cmd_set_expected(scst_cmd, dir, 0);
597 scst_cmd_set_tgt_priv(scst_cmd, tgt_specific);
599 #ifdef CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING
601 struct Scsi_Host *h = SCpnt->device->host;
602 spin_unlock_irq(h->host_lock);
603 scst_cmd_init_done(scst_cmd, scst_estimate_context_direct());
604 spin_lock_irq(h->host_lock);
608 * Unfortunately, we called with IRQs disabled, so have no choice,
609 * except pass to the thread context.
611 scst_cmd_init_done(scst_cmd, SCST_CONTEXT_THREAD);
615 * We are done here I think. Other callbacks move us forward.
621 static int scst_local_targ_pre_exec(struct scst_cmd *scst_cmd)
623 int res = SCST_PREPROCESS_STATUS_SUCCESS;
627 if (scst_cmd_get_dh_data_buff_alloced(scst_cmd) &&
628 (scst_cmd_get_data_direction(scst_cmd) & SCST_DATA_WRITE))
629 scst_copy_sg(scst_cmd, SCST_SG_COPY_FROM_TARGET);
635 static void scst_local_release_adapter(struct device *dev)
637 struct scst_local_host_info *scst_lcl_host;
641 scst_lcl_host = to_scst_lcl_host(dev);
643 for (i = 0; i < scst_local_num_tgts; i++)
644 if (scst_lcl_host->session[i])
645 scst_unregister_session(
646 scst_lcl_host->session[i], TRUE, NULL);
647 scst_unregister(scst_lcl_host->target);
648 kfree(scst_lcl_host);
655 * Add an adapter on the host side ... We add the target before we add
656 * the host (initiator) so that we don't get any requests before we are
659 * I want to convert this so we can map many hosts to a smaller number of
660 * targets to support the simulation of multiple initiators.
662 static int scst_local_add_adapter(void)
664 int error = 0, i = 0;
665 struct scst_local_host_info *scst_lcl_host;
670 scst_lcl_host = kzalloc(sizeof(struct scst_local_host_info),
672 if (NULL == scst_lcl_host) {
673 printk(KERN_ERR "%s out of memory at line %d\n",
678 spin_lock(&scst_local_host_list_lock);
679 list_add_tail(&scst_lcl_host->host_list, &scst_local_host_list);
680 spin_unlock(&scst_local_host_list_lock);
683 * Register a target with SCST and add a session
685 sprintf(name, "scstlcltgt%d", scst_local_add_host);
686 scst_lcl_host->target = scst_register(&scst_local_targ_tmpl, name);
687 if (!scst_lcl_host) {
688 printk(KERN_WARNING "scst_register_target failed:\n");
694 * Create a session for each device
696 for (i = 0; i < scst_local_num_tgts; i++) {
697 sprintf(name, "scstlclhst%d:%d", scst_local_add_host, i);
698 scst_lcl_host->session[i] = scst_register_session(
699 scst_lcl_host->target,
700 0, name, NULL, NULL);
701 if (!scst_lcl_host->session[i]) {
702 printk(KERN_WARNING "scst_register_session failed:\n");
704 goto unregister_target;
708 scst_lcl_host->dev.bus = &scst_fake_lld_bus;
709 scst_lcl_host->dev.parent = &scst_fake_primary;
710 scst_lcl_host->dev.release = &scst_local_release_adapter;
711 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
712 sprintf(scst_lcl_host->dev.bus_id, "scst_adp_%d", scst_local_add_host);
714 snprintf(scst_lcl_host->init_name, sizeof(scst_lcl_host->init_name),
715 "scst_adp_%d", scst_local_add_host);
716 scst_lcl_host->dev.init_name = scst_lcl_host->init_name;
719 error = device_register(&scst_lcl_host->dev);
721 goto unregister_session;
723 scst_local_add_host++; /* keep count of what we have added */
729 for (i = 0; i < scst_local_num_tgts; i++) {
730 if (scst_lcl_host->session[i])
731 scst_unregister_session(scst_lcl_host->session[i],
735 scst_unregister(scst_lcl_host->target);
737 kfree(scst_lcl_host);
743 * Remove an adapter ...
745 static void scst_local_remove_adapter(void)
747 struct scst_local_host_info *scst_lcl_host = NULL;
751 spin_lock(&scst_local_host_list_lock);
752 if (!list_empty(&scst_local_host_list)) {
753 scst_lcl_host = list_entry(scst_local_host_list.prev,
754 struct scst_local_host_info,
756 list_del(&scst_lcl_host->host_list);
758 spin_unlock(&scst_local_host_list_lock);
763 device_unregister(&scst_lcl_host->dev);
765 --scst_local_add_host;
770 static struct scsi_host_template scst_lcl_ini_driver_template = {
771 .proc_info = scst_local_proc_info,
772 .proc_name = scst_local_proc_name,
773 .name = SCST_LOCAL_NAME,
774 .info = scst_local_info,
775 /* .ioctl = scst_local_ioctl, */
776 .queuecommand = scst_local_queuecommand,
777 .eh_abort_handler = scst_local_abort,
778 .eh_device_reset_handler = scst_local_device_reset,
779 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25))
780 .eh_target_reset_handler = scst_local_target_reset,
783 .this_id = SCST_LOCAL_MAX_TARGETS,
784 /* SCST doesn't support sg chaining */
785 .sg_tablesize = SCSI_MAX_SG_SEGMENTS,
787 .max_sectors = 0xffff,
789 * There's no gain to merge requests on this level. If necessary,
790 * they will be merged at the backstorage level.
792 .use_clustering = DISABLE_CLUSTERING,
793 .skip_settle_delay = 1,
794 .module = THIS_MODULE,
797 static void scst_fake_0_release(struct device *dev)
804 static struct device scst_fake_primary = {
805 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
806 .bus_id = "scst_fake_0",
808 .init_name = "scst_fake_0",
810 .release = scst_fake_0_release,
813 static int __init scst_local_init(void)
815 int ret, k, adapters;
819 #if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G)
820 PRINT_ERROR("%s", "HIGHMEM kernel configurations are not supported. "
821 "Consider changing VMSPLIT option or use a 64-bit "
822 "configuration instead. See SCST core README file for "
828 TRACE_DBG("Adapters: %d\n", scst_local_add_host);
830 if (scst_local_num_tgts > SCST_LOCAL_MAX_TARGETS)
831 scst_local_num_tgts = SCST_LOCAL_MAX_TARGETS;
834 * Allocate a pool of structures for tgt_specific structures
836 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
837 tgt_specific_pool = kmem_cache_create("scst_tgt_specific",
838 sizeof(struct scst_local_tgt_specific),
839 0, SCST_SLAB_FLAGS, NULL);
841 tgt_specific_pool = kmem_cache_create("scst_tgt_specific",
842 sizeof(struct scst_local_tgt_specific),
843 0, SCST_SLAB_FLAGS, NULL, NULL);
846 if (!tgt_specific_pool) {
847 printk(KERN_WARNING "%s: out of memory for "
848 "tgt_specific structs",
853 ret = device_register(&scst_fake_primary);
855 printk(KERN_WARNING "%s: device_register error: %d\n",
859 ret = bus_register(&scst_fake_lld_bus);
861 printk(KERN_WARNING "%s: bus_register error: %d\n",
865 ret = driver_register(&scst_local_driverfs_driver);
867 printk(KERN_WARNING "%s: driver_register error: %d\n",
871 ret = do_create_driverfs_files();
873 printk(KERN_WARNING "%s: create_files error: %d\n",
875 goto driver_unregister;
880 * register the target driver and then create a host. This makes sure
881 * that we see any targets that are there. Gotta figure out how to
882 * tell the system that there are new targets when SCST creates them.
885 ret = scst_local_target_register();
887 printk(KERN_WARNING "%s: unable to register targ griver: %d\n",
895 adapters = scst_local_add_host;
896 scst_local_add_host = 0;
897 for (k = 0; k < adapters; k++) {
898 if (scst_local_add_adapter()) {
899 printk(KERN_ERR "%s: "
900 "scst_local_add_adapter failed: %d\n",
911 do_remove_driverfs_files();
913 driver_unregister(&scst_local_driverfs_driver);
915 bus_unregister(&scst_fake_lld_bus);
917 device_unregister(&scst_fake_primary);
919 kmem_cache_destroy(tgt_specific_pool);
923 static void __exit scst_local_exit(void)
925 int k = scst_local_add_host;
930 printk(KERN_INFO "removing adapter in %s\n", __func__);
931 scst_local_remove_adapter();
933 do_remove_driverfs_files();
934 driver_unregister(&scst_local_driverfs_driver);
935 bus_unregister(&scst_fake_lld_bus);
936 device_unregister(&scst_fake_primary);
939 * Now unregister the target template
941 scst_unregister_target_template(&scst_local_targ_tmpl);
944 * Free the pool we allocated
946 if (tgt_specific_pool)
947 kmem_cache_destroy(tgt_specific_pool);
952 device_initcall(scst_local_init);
953 module_exit(scst_local_exit);
956 * Fake LLD Bus and functions
959 static int scst_fake_lld_driver_probe(struct device *dev)
962 struct scst_local_host_info *scst_lcl_host;
963 struct Scsi_Host *hpnt;
967 scst_lcl_host = to_scst_lcl_host(dev);
969 hpnt = scsi_host_alloc(&scst_lcl_ini_driver_template,
970 sizeof(scst_lcl_host));
972 printk(KERN_ERR "%s: scsi_register failed\n", __func__);
977 scst_lcl_host->shost = hpnt;
980 * We are going to have to register with SCST here I think
981 * and fill in some of these from that info?
984 *((struct scst_local_host_info **)hpnt->hostdata) = scst_lcl_host;
985 if ((hpnt->this_id >= 0) && (scst_local_num_tgts > hpnt->this_id))
986 hpnt->max_id = scst_local_num_tgts + 1;
988 hpnt->max_id = scst_local_num_tgts;
989 hpnt->max_lun = scst_local_max_luns - 1;
991 hpnt->max_cmd_len = 260;
993 ret = scsi_add_host(hpnt, &scst_lcl_host->dev);
995 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
999 scsi_scan_host(hpnt);
1001 TRACE_EXIT_RES(ret);
1005 static int scst_fake_lld_driver_remove(struct device *dev)
1007 struct scst_local_host_info *scst_lcl_host;
1011 scst_lcl_host = to_scst_lcl_host(dev);
1013 if (!scst_lcl_host) {
1014 printk(KERN_ERR "%s: Unable to locate host info\n",
1019 scsi_remove_host(scst_lcl_host->shost);
1021 scsi_host_put(scst_lcl_host->shost);
1027 static int scst_fake_lld_bus_match(struct device *dev,
1028 struct device_driver *dev_driver)
1036 static struct bus_type scst_fake_lld_bus = {
1037 .name = "scst_fake_bus",
1038 .match = scst_fake_lld_bus_match,
1039 .probe = scst_fake_lld_driver_probe,
1040 .remove = scst_fake_lld_driver_remove,
1044 * SCST Target driver from here ... there are some forward declarations
1048 static int scst_local_targ_detect(struct scst_tgt_template *tgt_template)
1055 * Register the adapter(s)
1058 adapter_count = scst_local_add_host;
1060 TRACE_EXIT_RES(adapter_count);
1061 return adapter_count;
1064 static int scst_local_targ_release(struct scst_tgt *tgt)
1072 static int scst_local_targ_xmit_response(struct scst_cmd *scst_cmd)
1074 struct scst_local_tgt_specific *tgt_specific;
1078 if (unlikely(scst_cmd_aborted(scst_cmd))) {
1079 scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED);
1080 scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
1081 printk(KERN_INFO "%s aborted command handled\n", __func__);
1082 return SCST_TGT_RES_SUCCESS;
1085 if (scst_cmd_get_dh_data_buff_alloced(scst_cmd) &&
1086 (scst_cmd_get_data_direction(scst_cmd) & SCST_DATA_READ))
1087 scst_copy_sg(scst_cmd, SCST_SG_COPY_TO_TARGET);
1089 tgt_specific = scst_cmd_get_tgt_priv(scst_cmd);
1092 * This might have to change to use the two status flags
1094 if (scst_cmd_get_is_send_status(scst_cmd)) {
1095 (void)scst_local_send_resp(tgt_specific->cmnd, scst_cmd,
1097 scst_cmd_get_status(scst_cmd));
1101 * Now tell SCST that the command is done ...
1103 scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
1107 return SCST_TGT_RES_SUCCESS;
1110 static void scst_local_targ_on_free_cmd(struct scst_cmd *scst_cmd)
1112 struct scst_local_tgt_specific *tgt_specific;
1116 tgt_specific = scst_cmd_get_tgt_priv(scst_cmd);
1117 kmem_cache_free(tgt_specific_pool, tgt_specific);
1123 static void scst_local_targ_task_mgmt_done(struct scst_mgmt_cmd *mgmt_cmd)
1125 struct completion *tgt_specific;
1129 tgt_specific = (struct completion *)
1130 scst_mgmt_cmd_get_tgt_priv(mgmt_cmd);
1133 complete(tgt_specific);
1139 static struct scst_tgt_template scst_local_targ_tmpl = {
1140 .name = "scst_local_tgt",
1141 .sg_tablesize = 0xffff,
1142 .xmit_response_atomic = 1,
1143 .detect = scst_local_targ_detect,
1144 .release = scst_local_targ_release,
1145 .pre_exec = scst_local_targ_pre_exec,
1146 .xmit_response = scst_local_targ_xmit_response,
1147 .on_free_cmd = scst_local_targ_on_free_cmd,
1148 .task_mgmt_fn_done = scst_local_targ_task_mgmt_done,
1152 * Register the target driver ... to get things going
1154 static int scst_local_target_register(void)
1160 ret = scst_register_target_template(&scst_local_targ_tmpl);
1162 printk(KERN_WARNING "scst_register_target_template "
1172 TRACE_EXIT_RES(ret);