Added possibility to coexist if both target driver and dev handler need custom memory...
[mirror/scst/.git] / scst_local / scst_local.c
1 /*
2  * Copyright (C) 2008 Richard Sharpe
3  * Copyright (C) 1992 Eric Youngdale
4  *
5  * Simulate a host adapter and an SCST target adapter back to back
6  *
7  * Based on the scsi_debug.c driver originally by Eric Youngdale and
8  * others, including D Gilbert et al
9  *
10  */
11
12 #include <linux/module.h>
13
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/timer.h>
17 #include <linux/types.h>
18 #include <linux/string.h>
19 #include <linux/genhd.h>
20 #include <linux/fs.h>
21 #include <linux/init.h>
22 #include <linux/proc_fs.h>
23 #include <linux/vmalloc.h>
24 #include <linux/moduleparam.h>
25 #include <linux/scatterlist.h>
26 #include <linux/blkdev.h>
27 #include <linux/completion.h>
28 #include <linux/stat.h>
29
30 #include <scsi/scsi.h>
31 #include <scsi/scsi_cmnd.h>
32 #include <scsi/scsi_device.h>
33 #include <scsi/scsi_host.h>
34 #include <scsi/scsi_tcq.h>
35 #include <scsi/scsicam.h>
36 #include <scsi/scsi_eh.h>
37
38 /* SCST includes ... */
39 #include <scst_const.h>
40 #include <scst.h>
41
42 #define LOG_PREFIX "scst_local"
43
44 #include <scst_debug.h>
45
46 #ifdef CONFIG_SCST_DEBUG
47 #define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_FUNCTION | TRACE_PID | \
48         TRACE_OUT_OF_MEM | TRACE_MGMT | TRACE_MGMT_MINOR | \
49         TRACE_MGMT_DEBUG | TRACE_MINOR | TRACE_SPECIAL)
50 #else
51 # ifdef CONFIG_SCST_TRACING
52 #define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
53         TRACE_MINOR | TRACE_SPECIAL)
54 # endif
55 #endif
56
57 #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
58 #define trace_flag scst_local_trace_flag
59 unsigned long scst_local_trace_flag = SCST_LOCAL_DEFAULT_LOG_FLAGS;
60 #endif
61
62 #define TRUE 1
63 #define FALSE 0
64
65 /*
66  * Some definitions needed by the scst portion
67  */
68 static void scst_local_remove_adapter(void);
69 static int scst_local_add_adapter(void);
70
71 #define SCST_LOCAL_VERSION "0.7"
72 static const char *scst_local_version_date = "20081011";
73
74 #define SCST_LOCAL_SG_TABLESIZE 256
75
76 /*
77  * Target structures that are shared between the two pieces
78  * This will have to change if we have more than one target
79  */
80 static struct scst_tgt_template scst_local_targ_tmpl;
81
82 /*
83  * Some max values
84  */
85 #define DEF_NUM_HOST 1
86 #define DEF_NUM_TGTS 1
87 #define MAX_TARGETS 16
88 #define DEF_MAX_LUNS 256
89 #define SCST_LOCAL_CANQUEUE 1
90 /*#define SCST_LOCAL_CANQUEUE 255*/
91
92 /*
93  * These following defines are the SCSI Host LLD (the initiator).
94  * SCST Target Driver is below
95  */
96
97 static int scst_local_add_host = DEF_NUM_HOST;
98 static int scst_local_num_tgts = DEF_NUM_TGTS;
99 static int scst_local_max_luns = DEF_MAX_LUNS;
100
101 static int num_aborts;
102 static int num_dev_resets;
103 static int num_target_resets;
104
105 /*
106  * Each host has multiple targets, each of which has a separate session
107  * to SCST.
108  */
109
110 struct scst_local_host_info {
111         struct list_head host_list;
112         struct Scsi_Host *shost;
113         struct scst_tgt *target;
114         struct scst_session *session[MAX_TARGETS];
115         struct device dev;
116 };
117
118 #define to_scst_lcl_host(d) \
119         container_of(d, struct scst_local_host_info, dev)
120
121 /*
122  * Maintains data that is needed during command processing ...
123  */
124 struct scst_local_tgt_specific {
125         struct scsi_cmnd *cmnd;
126         void (*done)(struct scsi_cmnd *);
127 };
128
129 /*
130  * We use a pool of objects maintaind by the kernel so that it is less
131  * likely to have to allocate them when we are in the data path.
132  */
133 static struct kmem_cache *tgt_specific_pool;
134
135 static LIST_HEAD(scst_local_host_list);
136 static DEFINE_SPINLOCK(scst_local_host_list_lock);
137
138 static char scst_local_proc_name[] = "scst_ini_targ_debug";
139
140 static struct bus_type scst_fake_lld_bus;
141 static struct device scst_fake_primary;
142
143 static struct device_driver scst_local_driverfs_driver = {
144         .name   = scst_local_proc_name,
145         .bus    = &scst_fake_lld_bus,
146 };
147
148 module_param_named(add_host, scst_local_add_host, int, S_IRUGO | S_IWUSR);
149 module_param_named(num_tgts, scst_local_num_tgts, int, S_IRUGO | S_IWUSR);
150 module_param_named(max_luns, scst_local_max_luns, int, S_IRUGO | S_IWUSR);
151
152 MODULE_AUTHOR("Richard Sharpe + ideas from SCSI_DEBUG");
153 MODULE_DESCRIPTION("SCSI+SCST local adapter driver");
154 MODULE_LICENSE("GPL");
155 MODULE_VERSION(SCST_LOCAL_VERSION);
156
157 MODULE_PARM_DESC(add_host, "0..127 hosts can be created (def=1)");
158 MODULE_PARM_DESC(num_tgts, "mumber of targets per host (def=1)");
159 MODULE_PARM_DESC(max_luns, "number of luns per target (def=1)");
160
161 static int scst_local_target_register(void);
162
163 static int scst_local_proc_info(struct Scsi_Host *host, char *buffer,
164                                 char **start, off_t offset, int length,
165                                 int inout)
166 {
167         int len, pos, begin;
168
169         TRACE_ENTRY();
170
171         if (inout == 1)
172                 return -EACCES;
173
174         begin = 0;
175         pos = len = sprintf(buffer, "scst_local adapter driver, version "
176                             "%s [%s]\n"
177                             "num_tgts=%d, Aborts=%d, Device Resets=%d, "
178                             "Target Resets=%d\n",
179                             SCST_LOCAL_VERSION, scst_local_version_date,
180                             scst_local_num_tgts, num_aborts, num_dev_resets,
181                             num_target_resets);
182         if (pos < offset) {
183                 len = 0;
184                 begin = pos;
185         }
186         if (start)
187                 *start = buffer + (offset - begin);
188         len -= (offset - begin);
189         if (len > length)
190                 len = length;
191
192         TRACE_EXIT_RES(len);
193         return len;
194 }
195
196 static ssize_t scst_local_add_host_show(struct device_driver *ddp, char *buf)
197 {
198         int len = 0;
199         struct scst_local_host_info *scst_lcl_host, *tmp;
200
201         TRACE_ENTRY();
202
203         list_for_each_entry_safe(scst_lcl_host, tmp, &scst_local_host_list,
204                                  host_list) {
205                 len += scnprintf(&buf[len], PAGE_SIZE - len, " Initiator: %s\n",
206                                  scst_lcl_host->session[0]->initiator_name);
207         }
208
209         TRACE_EXIT_RES(len);
210         return len;
211 }
212
213 static ssize_t scst_local_add_host_store(struct device_driver *ddp,
214                                          const char *buf, size_t count)
215 {
216         int delta_hosts;
217
218         TRACE_ENTRY();
219
220         if (sscanf(buf, "%d", &delta_hosts) != 1)
221                 return -EINVAL;
222         if (delta_hosts > 0) {
223                 do {
224                         scst_local_add_adapter();
225                 } while (--delta_hosts);
226         } else if (delta_hosts < 0) {
227                 do {
228                         scst_local_remove_adapter();
229                 } while (++delta_hosts);
230         }
231
232         TRACE_EXIT_RES(count);
233         return count;
234 }
235
236 DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, scst_local_add_host_show,
237             scst_local_add_host_store);
238
239 static int do_create_driverfs_files(void)
240 {
241         int ret;
242
243         TRACE_ENTRY();
244
245         ret = driver_create_file(&scst_local_driverfs_driver,
246                                  &driver_attr_add_host);
247
248         TRACE_EXIT_RES(ret);
249         return ret;
250 }
251
252 static void do_remove_driverfs_files(void)
253 {
254         driver_remove_file(&scst_local_driverfs_driver,
255                            &driver_attr_add_host);
256 }
257
258 static char scst_local_info_buf[256];
259
260 static const char *scst_local_info(struct Scsi_Host *shp)
261 {
262         TRACE_ENTRY();
263
264         sprintf(scst_local_info_buf, "scst_local, version %s [%s], "
265                 "Aborts: %d, Device Resets: %d, Target Resets: %d",
266                 SCST_LOCAL_VERSION, scst_local_version_date,
267                 num_aborts, num_dev_resets, num_target_resets);
268
269         TRACE_EXIT();
270         return scst_local_info_buf;
271 }
272
273 /*
274 static int scst_local_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
275 {
276         TRACE_ENTRY();
277
278         if (scst_local_opt_noise & SCST_LOCAL_OPT_LLD_NOISE)
279                 printk(KERN_INFO "scst_local: ioctl: cmd=0x%x\n", cmd);
280         return -EINVAL;
281
282         TRACE_EXIT();
283 }
284 */
285
286 static int scst_local_abort(struct scsi_cmnd *SCpnt)
287 {
288         struct scst_local_host_info *scst_lcl_host;
289         int ret = 0;
290         DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
291
292         TRACE_ENTRY();
293
294         scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
295
296         ret = scst_rx_mgmt_fn_tag(scst_lcl_host->session[SCpnt->device->id],
297                                   SCST_LUN_RESET, SCpnt->tag, FALSE,
298                                   &dev_reset_completion);
299
300         wait_for_completion_interruptible(&dev_reset_completion);
301
302         ++num_aborts;
303
304         TRACE_EXIT_RES(ret);
305         return ret;
306 }
307
308 /*
309  * We issue a mgmt function. We should pass a structure to the function
310  * that contains our private data, so we can retrieve the status from the
311  * done routine ... TODO
312  */
313 static int scst_local_device_reset(struct scsi_cmnd *SCpnt)
314 {
315         struct scst_local_host_info *scst_lcl_host;
316         int lun;
317         int ret = 0;
318         DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
319
320         TRACE_ENTRY();
321
322         scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
323
324         lun = SCpnt->device->lun;
325         lun = (lun & 0xFF) << 8 | ((lun & 0xFF00) >> 8); /* FIXME: LE only */
326
327         ret = scst_rx_mgmt_fn_lun(scst_lcl_host->session[SCpnt->device->id],
328                                   SCST_LUN_RESET,
329                                   (const uint8_t *)&lun,
330                                   sizeof(lun), FALSE,
331                                   &dev_reset_completion);
332
333         /*
334          * Now wait for the completion ...
335          */
336         wait_for_completion_interruptible(&dev_reset_completion);
337
338         ++num_dev_resets;
339
340         TRACE_EXIT_RES(ret);
341         return ret;
342 }
343
344 static int scst_local_target_reset(struct scsi_cmnd *SCpnt)
345 {
346         struct scst_local_host_info *scst_lcl_host;
347         int lun;
348         int ret = 0;
349         DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
350
351         TRACE_ENTRY();
352
353         scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
354
355         lun = SCpnt->device->lun;
356         lun = (lun & 0xFF) << 8 | ((lun & 0xFF00) >> 8); /* FIXME: LE only */
357
358         ret = scst_rx_mgmt_fn_lun(scst_lcl_host->session[SCpnt->device->id],
359                                   SCST_TARGET_RESET,
360                                   (const uint8_t *)&lun,
361                                   sizeof(lun), FALSE,
362                                   &dev_reset_completion);
363
364         /*
365          * Now wait for the completion ...
366          */
367         wait_for_completion_interruptible(&dev_reset_completion);
368
369         ++num_target_resets;
370
371         TRACE_EXIT_RES(ret);
372         return ret;
373 }
374
375 static void copy_sense(struct scsi_cmnd *cmnd, struct scst_cmd *scst_cmnd)
376 {
377         int scst_cmnd_sense_len = scst_cmd_get_sense_buffer_len(scst_cmnd);
378
379         TRACE_ENTRY();
380
381         scst_cmnd_sense_len = (SCSI_SENSE_BUFFERSIZE < scst_cmnd_sense_len ?
382                                SCSI_SENSE_BUFFERSIZE : scst_cmnd_sense_len);
383         memcpy(cmnd->sense_buffer, scst_cmd_get_sense_buffer(scst_cmnd),
384                scst_cmnd_sense_len);
385
386         TRACE_BUFFER("Sense set", cmnd->sense_buffer, scst_cmnd_sense_len);
387
388         TRACE_EXIT();
389         return;
390 }
391
392 /*
393  * Utility function to handle processing of done and allow
394  * easy insertion of error injection if desired
395  */
396 static int scst_local_send_resp(struct scsi_cmnd *cmnd,
397                                 struct scst_cmd *scst_cmnd,
398                                 void (*done)(struct scsi_cmnd *), int scsi_result)
399 {
400         int ret = 0;
401
402         TRACE_ENTRY();
403
404         if (cmnd && scst_cmnd) {
405                 /* Simulate autosense by this driver */
406                 if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xFF))
407                         copy_sense(cmnd, scst_cmnd);
408         }
409
410         if (cmnd)
411                 cmnd->result = scsi_result;
412         if (done)
413                 done(cmnd);
414
415         TRACE_EXIT_RES(ret);
416         return ret;
417 }
418
419 /*
420  * This does the heavy lifting ... we pass all the commands on to the
421  * target driver and have it do its magic ...
422  */
423 static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
424                                    void (*done)(struct scsi_cmnd *))
425 {
426         struct scst_local_tgt_specific *tgt_specific = NULL;
427         struct scst_local_host_info *scst_lcl_host;
428         int target = SCpnt->device->id;
429         int lun;
430         struct scst_cmd *scst_cmd = NULL;
431         scst_data_direction dir;
432
433         TRACE_ENTRY();
434
435         TRACE_DBG("targ: %d, init id %d, lun %d, cmd: 0X%02X\n",
436               target, SCpnt->device->host->hostt->this_id, SCpnt->device->lun,
437               SCpnt->cmnd[0]);
438
439         scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
440
441         scsi_set_resid(SCpnt, 0);
442
443         if (target == SCpnt->device->host->hostt->this_id) {
444                 printk(KERN_ERR "%s: initiator's id used as target\n",
445                        __func__);
446                 return scst_local_send_resp(SCpnt, NULL, done,
447                                             DID_NO_CONNECT << 16);
448         }
449
450         tgt_specific = kmem_cache_alloc(tgt_specific_pool, GFP_ATOMIC);
451         if (!tgt_specific) {
452                 printk(KERN_ERR "%s out of memory at line %d\n",
453                        __func__, __LINE__);
454                 return -ENOMEM;
455         }
456         tgt_specific->cmnd = SCpnt;
457         tgt_specific->done = done;
458
459         /*
460          * Tell the target that we have a command ... but first we need
461          * to get the LUN into a format that SCST understand
462          */
463         lun = SCpnt->device->lun;
464         lun = (lun & 0xFF) << 8 | ((lun & 0xFF00) >> 8); /* FIXME: LE only */
465         scst_cmd = scst_rx_cmd(scst_lcl_host->session[SCpnt->device->id],
466                                (const uint8_t *)&lun,
467                                sizeof(lun), SCpnt->cmnd,
468                                SCpnt->cmd_len, TRUE);
469         if (!scst_cmd) {
470                 printk(KERN_ERR "%s out of memory at line %d\n",
471                        __func__, __LINE__);
472                 return -ENOMEM;
473         }
474
475         scst_cmd_set_tgt_priv(scst_cmd, tgt_specific);
476         scst_cmd_set_tag(scst_cmd, SCpnt->tag);
477         switch (scsi_get_tag_type(SCpnt->device)) {
478         case MSG_SIMPLE_TAG:
479                 scst_cmd->queue_type = SCST_CMD_QUEUE_SIMPLE;
480                 break;
481         case MSG_HEAD_TAG:
482                 scst_cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
483                 break;
484         case MSG_ORDERED_TAG:
485                 scst_cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
486                 break;
487         case SCSI_NO_TAG:
488         default:
489                 scst_cmd->queue_type = SCST_CMD_QUEUE_UNTAGGED;
490                 break;
491         }
492
493         dir = SCST_DATA_NONE;
494         switch (SCpnt->sc_data_direction) {
495         case DMA_TO_DEVICE:
496                 dir = SCST_DATA_WRITE;
497                 break;
498         case DMA_FROM_DEVICE:
499                 dir = SCST_DATA_READ;
500                 break;
501         case DMA_BIDIRECTIONAL:
502                 printk(KERN_ERR "%s: DMA_BIDIRECTIONAL not allowed!\n",
503                        __func__);
504                 return scst_local_send_resp(SCpnt, NULL, done,
505                                             DID_ERROR << 16);
506                 dir = SCST_DATA_UNKNOWN;
507                 break;
508         case DMA_NONE:
509         default:
510                 dir = SCST_DATA_NONE;
511                 break;
512         }
513         scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
514
515         /* Set the SGL things directly ... */
516         scst_cmd_set_tgt_sg(scst_cmd, scsi_sglist(SCpnt), scsi_sg_count(SCpnt));
517
518         /*
519          * Unfortunately, we called with IRQs disabled, so have no choice,
520          * except pass to the thread context.
521          */
522         scst_cmd_init_done(scst_cmd, SCST_CONTEXT_THREAD);
523
524         /*
525          * We are done here I think. Other callbacks move us forward.
526          */
527         TRACE_EXIT();
528         return 0;
529 }
530
531 static void scst_local_release_adapter(struct device *dev)
532 {
533         struct scst_local_host_info *scst_lcl_host;
534         int i = 0;
535
536         TRACE_ENTRY();
537         scst_lcl_host = to_scst_lcl_host(dev);
538         if (scst_lcl_host) {
539                 for (i = 0; i < scst_local_num_tgts; i++)
540                         if (scst_lcl_host->session[i])
541                                 scst_unregister_session(
542                                         scst_lcl_host->session[i], TRUE, NULL);
543                 scst_unregister(scst_lcl_host->target);
544                 kfree(scst_lcl_host);
545         }
546
547         TRACE_EXIT();
548 }
549
550 /*
551  * Add an adapter on the host side ... We add the target before we add
552  * the host (initiator) so that we don't get any requests before we are
553  * ready for them.
554  *
555  * I want to convert this so we can map many hosts to a smaller number of
556  * targets to support the simulation of multiple initiators.
557  */
558 static int scst_local_add_adapter(void)
559 {
560         int error = 0, i = 0;
561         struct scst_local_host_info *scst_lcl_host;
562         char name[32];
563
564         TRACE_ENTRY();
565
566         scst_lcl_host = kzalloc(sizeof(struct scst_local_host_info),
567                                 GFP_KERNEL);
568         if (NULL == scst_lcl_host) {
569                 printk(KERN_ERR "%s out of memory at line %d\n",
570                        __func__, __LINE__);
571                 return -ENOMEM;
572         }
573
574         spin_lock(&scst_local_host_list_lock);
575         list_add_tail(&scst_lcl_host->host_list, &scst_local_host_list);
576         spin_unlock(&scst_local_host_list_lock);
577
578         /*
579          * Register a target with SCST and add a session
580          */
581         sprintf(name, "scstlcltgt%d", scst_local_add_host);
582         scst_lcl_host->target = scst_register(&scst_local_targ_tmpl, name);
583         if (!scst_lcl_host) {
584                 printk(KERN_WARNING "scst_register_target failed:\n");
585                 error = -1;
586                 goto cleanup;
587         }
588
589         /*
590          * Create a session for each device
591          */
592         for (i = 0; i < scst_local_num_tgts; i++) {
593                 sprintf(name, "scstlclhst%d:%d", scst_local_add_host, i);
594                 scst_lcl_host->session[i] = scst_register_session(
595                                                 scst_lcl_host->target,
596                                                 TRUE, name, NULL, NULL);
597                 if (!scst_lcl_host->session[i]) {
598                         printk(KERN_WARNING "scst_register_session failed:\n");
599                         error = -1;
600                         goto unregister_target;
601                 }
602         }
603
604         scst_lcl_host->dev.bus     = &scst_fake_lld_bus;
605         scst_lcl_host->dev.parent  = &scst_fake_primary;
606         scst_lcl_host->dev.release = &scst_local_release_adapter;
607         sprintf(scst_lcl_host->dev.bus_id, "scst_adp_%d", scst_local_add_host);
608
609         error = device_register(&scst_lcl_host->dev);
610         if (error)
611                 goto unregister_session;
612
613         scst_local_add_host++; /* keep count of what we have added */
614
615         TRACE_EXIT();
616         return error;
617
618 unregister_session:
619         for (i = 0; i < scst_local_num_tgts; i++) {
620                 if (scst_lcl_host->session[i])
621                         scst_unregister_session(scst_lcl_host->session[i],
622                         TRUE, NULL);
623         }
624 unregister_target:
625         scst_unregister(scst_lcl_host->target);
626 cleanup:
627         kfree(scst_lcl_host);
628         TRACE_EXIT();
629         return error;
630 }
631
632 /*
633  * Remove an adapter ...
634  */
635 static void scst_local_remove_adapter(void)
636 {
637         struct scst_local_host_info *scst_lcl_host = NULL;
638
639         TRACE_ENTRY();
640
641         spin_lock(&scst_local_host_list_lock);
642         if (!list_empty(&scst_local_host_list)) {
643                 scst_lcl_host = list_entry(scst_local_host_list.prev,
644                                            struct scst_local_host_info,
645                                            host_list);
646                 list_del(&scst_lcl_host->host_list);
647         }
648         spin_unlock(&scst_local_host_list_lock);
649
650         if (!scst_lcl_host)
651                 return;
652
653         device_unregister(&scst_lcl_host->dev);
654
655         --scst_local_add_host;
656
657         TRACE_EXIT();
658 }
659
660 static struct scsi_host_template scst_lcl_ini_driver_template = {
661         .proc_info                      = scst_local_proc_info,
662         .proc_name                      = scst_local_proc_name,
663         .name                           = SCST_LOCAL_NAME,
664         .info                           = scst_local_info,
665 /*      .ioctl                          = scst_local_ioctl, */
666         .queuecommand                   = scst_local_queuecommand,
667         .eh_abort_handler               = scst_local_abort,
668         .eh_device_reset_handler        = scst_local_device_reset,
669         .eh_target_reset_handler        = scst_local_target_reset,
670         .can_queue                      = SCST_LOCAL_CANQUEUE,
671         .this_id                        = 7, /*???*/
672         .sg_tablesize                   = SCST_LOCAL_SG_TABLESIZE,
673         .cmd_per_lun                    = 16,
674         .max_sectors                    = 0xffff,
675         .use_clustering                 = DISABLE_CLUSTERING,
676         .module                         = THIS_MODULE,
677 };
678
679 static void scst_fake_0_release(struct device *dev)
680 {
681         TRACE_ENTRY();
682
683         TRACE_EXIT();
684 }
685
686 static struct device scst_fake_primary = {
687         .bus_id         = "scst_fake_0",
688         .release        = scst_fake_0_release,
689 };
690
691 static int __init scst_local_init(void)
692 {
693         int ret, k, adapters;
694
695         TRACE_ENTRY();
696
697         TRACE_DBG("Adapters: %d\n", scst_local_add_host);
698
699         if (scst_local_num_tgts > MAX_TARGETS)
700                 scst_local_num_tgts = MAX_TARGETS;
701
702         /*
703          * Allocate a pool of structures for tgt_specific structures
704          */
705         tgt_specific_pool = kmem_cache_create("scst_tgt_specific",
706                                       sizeof(struct scst_local_tgt_specific),
707                                       0, SCST_SLAB_FLAGS, NULL);
708
709         if (!tgt_specific_pool) {
710                 printk(KERN_WARNING "%s: out of memory for "
711                        "tgt_specific structs",
712                        __func__);
713                 return -ENOMEM;
714         }
715
716         ret = device_register(&scst_fake_primary);
717         if (ret < 0) {
718                 printk(KERN_WARNING "%s: device_register error: %d\n",
719                        __func__, ret);
720                 goto free_stuff;
721         }
722         ret = bus_register(&scst_fake_lld_bus);
723         if (ret < 0) {
724                 printk(KERN_WARNING "%s: bus_register error: %d\n",
725                        __func__, ret);
726                 goto dev_unreg;
727         }
728         ret = driver_register(&scst_local_driverfs_driver);
729         if (ret < 0) {
730                 printk(KERN_WARNING "%s: driver_register error: %d\n",
731                        __func__, ret);
732                 goto bus_unreg;
733         }
734         ret = do_create_driverfs_files();
735         if (ret < 0) {
736                 printk(KERN_WARNING "%s: create_files error: %d\n",
737                        __func__, ret);
738                 goto driver_unregister;
739         }
740
741
742         /*
743          * register the target driver and then create a host. This makes sure
744          * that we see any targets that are there. Gotta figure out how to
745          * tell the system that there are new targets when SCST creates them.
746          */
747
748         ret = scst_local_target_register();
749         if (ret < 0) {
750                 printk(KERN_WARNING "%s: unable to register targ griver: %d\n",
751                        __func__, ret);
752                 goto del_files;
753         }
754
755         /*
756          * Add adapters ...
757          */
758         adapters = scst_local_add_host;
759         scst_local_add_host = 0;
760         for (k = 0; k < adapters; k++) {
761                 if (scst_local_add_adapter()) {
762                         printk(KERN_ERR "%s: "
763                                         "scst_local_add_adapter failed: %d\n",
764                                         __func__, k);
765                         break;
766                 }
767         }
768
769         TRACE_EXIT();
770         return 0;
771
772 del_files:
773         do_remove_driverfs_files();
774 driver_unregister:
775         driver_unregister(&scst_local_driverfs_driver);
776 bus_unreg:
777         bus_unregister(&scst_fake_lld_bus);
778 dev_unreg:
779         device_unregister(&scst_fake_primary);
780 free_stuff:
781
782         TRACE_EXIT_RES(ret);
783         return ret;
784 }
785
786 static void __exit scst_local_exit(void)
787 {
788         int k = scst_local_add_host;
789
790         TRACE_ENTRY();
791
792         for (; k; k--) {
793                 printk(KERN_INFO "removing adapter in %s\n", __func__);
794                 scst_local_remove_adapter();
795         }
796         do_remove_driverfs_files();
797         driver_unregister(&scst_local_driverfs_driver);
798         bus_unregister(&scst_fake_lld_bus);
799         device_unregister(&scst_fake_primary);
800
801         /*
802          * Now unregister the target template
803          */
804         scst_unregister_target_template(&scst_local_targ_tmpl);
805
806         /*
807          * Free the pool we allocated
808          */
809         if (tgt_specific_pool)
810                 kmem_cache_destroy(tgt_specific_pool);
811
812         TRACE_EXIT();
813 }
814
815 device_initcall(scst_local_init);
816 module_exit(scst_local_exit);
817
818 /*
819  * Fake LLD Bus and functions
820  */
821
822 static int scst_fake_lld_driver_probe(struct device *dev)
823 {
824         int ret = 0;
825         struct scst_local_host_info *scst_lcl_host;
826         struct Scsi_Host *hpnt;
827
828         TRACE_ENTRY();
829
830         scst_lcl_host = to_scst_lcl_host(dev);
831
832         hpnt = scsi_host_alloc(&scst_lcl_ini_driver_template,
833                                sizeof(scst_lcl_host));
834         if (NULL == hpnt) {
835                 printk(KERN_ERR "%s: scsi_register failed\n", __func__);
836                 ret = -ENODEV;
837                 return ret;
838         }
839
840         scst_lcl_host->shost = hpnt;
841
842         /*
843          * We are going to have to register with SCST here I think
844          * and fill in some of these from that info?
845          */
846
847         *((struct scst_local_host_info **)hpnt->hostdata) = scst_lcl_host;
848         if ((hpnt->this_id >= 0) && (scst_local_num_tgts > hpnt->this_id))
849                 hpnt->max_id = scst_local_num_tgts + 1;
850         else
851                 hpnt->max_id = scst_local_num_tgts;
852         hpnt->max_lun = scst_local_max_luns - 1;
853
854         ret = scsi_add_host(hpnt, &scst_lcl_host->dev);
855         if (ret) {
856                 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
857                 ret = -ENODEV;
858                 scsi_host_put(hpnt);
859         } else
860                 scsi_scan_host(hpnt);
861
862         TRACE_EXIT_RES(ret);
863         return ret;
864 }
865
866 static int scst_fake_lld_driver_remove(struct device *dev)
867 {
868         struct scst_local_host_info *scst_lcl_host;
869
870         TRACE_ENTRY();
871
872         scst_lcl_host = to_scst_lcl_host(dev);
873
874         if (!scst_lcl_host) {
875                 printk(KERN_ERR "%s: Unable to locate host info\n",
876                        __func__);
877                 return -ENODEV;
878         }
879
880         scsi_remove_host(scst_lcl_host->shost);
881
882         scsi_host_put(scst_lcl_host->shost);
883
884         TRACE_EXIT();
885         return 0;
886 }
887
888 static int scst_fake_lld_bus_match(struct device *dev,
889                                    struct device_driver *dev_driver)
890 {
891         TRACE_ENTRY();
892
893         TRACE_EXIT();
894         return 1;
895 }
896
897 static struct bus_type scst_fake_lld_bus = {
898         .name   = "scst_fake_bus",
899         .match  = scst_fake_lld_bus_match,
900         .probe  = scst_fake_lld_driver_probe,
901         .remove = scst_fake_lld_driver_remove,
902 };
903
904 /*
905  * SCST Target driver from here ... there are some forward declarations
906  * above
907  */
908
909 static int scst_local_targ_detect(struct scst_tgt_template *tgt_template)
910 {
911         int adapter_count;
912
913         TRACE_ENTRY();
914
915         /*
916          * Register the adapter(s)
917          */
918
919         adapter_count = scst_local_add_host;
920
921         TRACE_EXIT_RES(adapter_count);
922         return adapter_count;
923 };
924
925 static int scst_local_targ_release(struct scst_tgt *tgt)
926 {
927         TRACE_ENTRY();
928
929         TRACE_EXIT();
930         return 0;
931 }
932
933 static int scst_local_targ_xmit_response(struct scst_cmd *scst_cmd)
934 {
935         struct scst_local_tgt_specific *tgt_specific;
936
937         TRACE_ENTRY();
938
939         if (unlikely(scst_cmd_aborted(scst_cmd))) {
940                 scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED);
941                 scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
942                 printk(KERN_INFO "%s aborted command handled\n", __func__);
943                 return SCST_TGT_RES_SUCCESS;
944         }
945
946         tgt_specific = scst_cmd_get_tgt_priv(scst_cmd);
947
948         /*
949          * This might have to change to use the two status flags
950          */
951         if (scst_cmd_get_is_send_status(scst_cmd)) {
952                 (void)scst_local_send_resp(tgt_specific->cmnd, scst_cmd,
953                                            tgt_specific->done,
954                                            scst_cmd_get_status(scst_cmd));
955         }
956
957         /*
958          * Now tell SCST that the command is done ...
959          */
960         scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
961
962         TRACE_EXIT();
963
964         return SCST_TGT_RES_SUCCESS;
965 }
966
967 static void scst_local_targ_on_free_cmd(struct scst_cmd *scst_cmd)
968 {
969         struct scst_local_tgt_specific *tgt_specific;
970
971         TRACE_ENTRY();
972
973         tgt_specific = scst_cmd_get_tgt_priv(scst_cmd);
974         kmem_cache_free(tgt_specific_pool, tgt_specific);
975
976         TRACE_EXIT();
977         return;
978 }
979
980 static void scst_local_targ_task_mgmt_done(struct scst_mgmt_cmd *mgmt_cmd)
981 {
982         struct completion *tgt_specific;
983
984         TRACE_ENTRY();
985
986         tgt_specific = (struct completion *)
987                          scst_mgmt_cmd_get_tgt_priv(mgmt_cmd);
988
989         if (tgt_specific)
990                 complete(tgt_specific);
991
992         TRACE_EXIT();
993         return;
994 }
995
996 static struct scst_tgt_template scst_local_targ_tmpl = {
997         .sg_tablesize           = SCST_LOCAL_SG_TABLESIZE,
998         .name                   = "scst_local_tgt",
999         .unchecked_isa_dma      = 0,
1000         .use_clustering         = 0,
1001         .xmit_response_atomic   = 1,
1002         .detect                 = scst_local_targ_detect,
1003         .release                = scst_local_targ_release,
1004         .xmit_response          = scst_local_targ_xmit_response,
1005         .on_free_cmd            = scst_local_targ_on_free_cmd,
1006         .task_mgmt_fn_done      = scst_local_targ_task_mgmt_done,
1007 };
1008
1009 /*
1010  * Register the target driver ... to get things going
1011  */
1012 static int scst_local_target_register(void)
1013 {
1014         int ret;
1015
1016         TRACE_ENTRY();
1017
1018         ret = scst_register_target_template(&scst_local_targ_tmpl);
1019         if (ret < 0) {
1020                 printk(KERN_WARNING "scst_register_target_template "
1021                        "failed: %d\n",
1022                        ret);
1023                 goto error;
1024         }
1025
1026         TRACE_EXIT();
1027         return 0;
1028
1029 error:
1030         TRACE_EXIT_RES(ret);
1031         return ret;
1032 }
1033