00ca7078e1048b2b8626e876c8c8c27445b65fd9
[mirror/scst/.git] / scst_local / scst_local.c
1 /*
2  * Copyright (C) 2008 Richard Sharpe
3  * Copyright (C) 1992 Eric Youngdale
4  * Copyright (C) 2008 - 2009 Vladislav Bolkhovitin <vst@vlnb.net>
5  *
6  * Simulate a host adapter and an SCST target adapter back to back
7  *
8  * Based on the scsi_debug.c driver originally by Eric Youngdale and
9  * others, including D Gilbert et al
10  *
11  */
12
13 #include <linux/module.h>
14
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>
21 #include <linux/fs.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>
30
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>
38
39 /* SCST includes ... */
40 #include <scst_const.h>
41 #include <scst.h>
42
43 #define LOG_PREFIX "scst_local"
44
45 #include <scst_debug.h>
46
47 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
48 #define SCSI_MAX_SG_SEGMENTS 128
49 #endif
50
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."
56 #endif
57
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)
62 #else
63 # ifdef CONFIG_SCST_TRACING
64 #define SCST_LOCAL_DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
65         TRACE_MINOR | TRACE_SPECIAL)
66 # endif
67 #endif
68
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;
72 #endif
73
74 /*
75  * Provide some local definitions that are not provided for some earlier
76  * kernels so we operate over a wider range of kernels
77  *
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.
81  */
82
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)
87 #endif
88
89 #define TRUE 1
90 #define FALSE 0
91
92 /*
93  * Some definitions needed by the scst portion
94  */
95 static void scst_local_remove_adapter(void);
96 static int scst_local_add_adapter(void);
97
98 #define SCST_LOCAL_VERSION "0.9.2"
99 static const char *scst_local_version_date = "20090614";
100
101 /*
102  * Target structures that are shared between the two pieces
103  * This will have to change if we have more than one target
104  */
105 static struct scst_tgt_template scst_local_targ_tmpl;
106
107 /*
108  * Some max values
109  */
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
114
115 /*
116  * These following defines are the SCSI Host LLD (the initiator).
117  * SCST Target Driver is below
118  */
119
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;
123
124 static int num_aborts;
125 static int num_dev_resets;
126 static int num_target_resets;
127
128 /*
129  * Each host has multiple targets, each of which has a separate session
130  * to SCST.
131  */
132
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];
138         struct device dev;
139         char init_name[20];
140 };
141
142 #define to_scst_lcl_host(d) \
143         container_of(d, struct scst_local_host_info, dev)
144
145 /*
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.
150  */
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;
156 #endif
157 };
158
159 /*
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.
162  */
163 static struct kmem_cache *tgt_specific_pool;
164
165 static LIST_HEAD(scst_local_host_list);
166 static DEFINE_SPINLOCK(scst_local_host_list_lock);
167
168 static char scst_local_proc_name[] = "scst_ini_targ_debug";
169
170 static struct bus_type scst_fake_lld_bus;
171 static struct device scst_fake_primary;
172
173 static struct device_driver scst_local_driverfs_driver = {
174         .name   = scst_local_proc_name,
175         .bus    = &scst_fake_lld_bus,
176 };
177
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);
181
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);
186
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)");
190
191 static int scst_local_target_register(void);
192
193 static int scst_local_proc_info(struct Scsi_Host *host, char *buffer,
194                                 char **start, off_t offset, int length,
195                                 int inout)
196 {
197         int len, pos, begin;
198
199         TRACE_ENTRY();
200
201         if (inout == 1)
202                 return -EACCES;
203
204         begin = 0;
205         pos = len = sprintf(buffer, "scst_local adapter driver, version "
206                             "%s [%s]\n"
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,
211                             num_target_resets);
212         if (pos < offset) {
213                 len = 0;
214                 begin = pos;
215         }
216         if (start)
217                 *start = buffer + (offset - begin);
218         len -= (offset - begin);
219         if (len > length)
220                 len = length;
221
222         TRACE_EXIT_RES(len);
223         return len;
224 }
225
226 static ssize_t scst_local_add_host_show(struct device_driver *ddp, char *buf)
227 {
228         int len = 0;
229         struct scst_local_host_info *scst_lcl_host, *tmp;
230
231         TRACE_ENTRY();
232
233         list_for_each_entry_safe(scst_lcl_host, tmp, &scst_local_host_list,
234                                  host_list) {
235                 len += scnprintf(&buf[len], PAGE_SIZE - len, " Initiator: %s\n",
236                                  scst_lcl_host->session[0]->initiator_name);
237         }
238
239         TRACE_EXIT_RES(len);
240         return len;
241 }
242
243 static ssize_t scst_local_add_host_store(struct device_driver *ddp,
244                                          const char *buf, size_t count)
245 {
246         int delta_hosts;
247
248         TRACE_ENTRY();
249
250         if (sscanf(buf, "%d", &delta_hosts) != 1)
251                 return -EINVAL;
252         if (delta_hosts > 0) {
253                 do {
254                         scst_local_add_adapter();
255                 } while (--delta_hosts);
256         } else if (delta_hosts < 0) {
257                 do {
258                         scst_local_remove_adapter();
259                 } while (++delta_hosts);
260         }
261
262         TRACE_EXIT_RES(count);
263         return count;
264 }
265
266 static DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, scst_local_add_host_show,
267             scst_local_add_host_store);
268
269 static int do_create_driverfs_files(void)
270 {
271         int ret;
272
273         TRACE_ENTRY();
274
275         ret = driver_create_file(&scst_local_driverfs_driver,
276                                  &driver_attr_add_host);
277
278         TRACE_EXIT_RES(ret);
279         return ret;
280 }
281
282 static void do_remove_driverfs_files(void)
283 {
284         driver_remove_file(&scst_local_driverfs_driver,
285                            &driver_attr_add_host);
286 }
287
288 static char scst_local_info_buf[256];
289
290 static const char *scst_local_info(struct Scsi_Host *shp)
291 {
292         TRACE_ENTRY();
293
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);
298
299         TRACE_EXIT();
300         return scst_local_info_buf;
301 }
302
303 #if 0
304 static int scst_local_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
305 {
306         TRACE_ENTRY();
307
308         if (scst_local_opt_noise & SCST_LOCAL_OPT_LLD_NOISE)
309                 printk(KERN_INFO "scst_local: ioctl: cmd=0x%x\n", cmd);
310         return -EINVAL;
311
312         TRACE_EXIT();
313 }
314 #endif
315
316 static int scst_local_abort(struct scsi_cmnd *SCpnt)
317 {
318         struct scst_local_host_info *scst_lcl_host;
319         int ret = 0;
320         DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
321
322         TRACE_ENTRY();
323
324         scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
325
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);
329
330         wait_for_completion_interruptible(&dev_reset_completion);
331
332         ++num_aborts;
333
334         TRACE_EXIT_RES(ret);
335         return ret;
336 }
337
338 /*
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
342  */
343 static int scst_local_device_reset(struct scsi_cmnd *SCpnt)
344 {
345         struct scst_local_host_info *scst_lcl_host;
346         int lun;
347         int ret = 0;
348         DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
349
350         TRACE_ENTRY();
351
352         scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
353
354         lun = SCpnt->device->lun;
355         lun = (lun & 0xFF) << 8 | ((lun & 0xFF00) >> 8); /* FIXME: LE only */
356
357         ret = scst_rx_mgmt_fn_lun(scst_lcl_host->session[SCpnt->device->id],
358                                   SCST_LUN_RESET,
359                                   (const uint8_t *)&lun,
360                                   sizeof(lun), FALSE,
361                                   &dev_reset_completion);
362
363         /*
364          * Now wait for the completion ...
365          */
366         wait_for_completion_interruptible(&dev_reset_completion);
367
368         ++num_dev_resets;
369
370         TRACE_EXIT_RES(ret);
371         return ret;
372 }
373
374 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25))
375 static int scst_local_target_reset(struct scsi_cmnd *SCpnt)
376 {
377         struct scst_local_host_info *scst_lcl_host;
378         int lun;
379         int ret = 0;
380         DECLARE_COMPLETION_ONSTACK(dev_reset_completion);
381
382         TRACE_ENTRY();
383
384         scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
385
386         lun = SCpnt->device->lun;
387         lun = (lun & 0xFF) << 8 | ((lun & 0xFF00) >> 8); /* FIXME: LE only */
388
389         ret = scst_rx_mgmt_fn_lun(scst_lcl_host->session[SCpnt->device->id],
390                                   SCST_TARGET_RESET,
391                                   (const uint8_t *)&lun,
392                                   sizeof(lun), FALSE,
393                                   &dev_reset_completion);
394
395         /*
396          * Now wait for the completion ...
397          */
398         wait_for_completion_interruptible(&dev_reset_completion);
399
400         ++num_target_resets;
401
402         TRACE_EXIT_RES(ret);
403         return ret;
404 }
405 #endif
406
407 static void copy_sense(struct scsi_cmnd *cmnd, struct scst_cmd *scst_cmnd)
408 {
409         int scst_cmnd_sense_len = scst_cmd_get_sense_buffer_len(scst_cmnd);
410
411         TRACE_ENTRY();
412
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);
417
418         TRACE_BUFFER("Sense set", cmnd->sense_buffer, scst_cmnd_sense_len);
419
420         TRACE_EXIT();
421         return;
422 }
423
424 /*
425  * Utility function to handle processing of done and allow
426  * easy insertion of error injection if desired
427  */
428 static int scst_local_send_resp(struct scsi_cmnd *cmnd,
429                                 struct scst_cmd *scst_cmnd,
430                                 void (*done)(struct scsi_cmnd *),
431                                 int scsi_result)
432 {
433         int ret = 0;
434
435         TRACE_ENTRY();
436
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);
441         }
442
443         if (cmnd)
444                 cmnd->result = scsi_result;
445         if (done)
446                 done(cmnd);
447
448         TRACE_EXIT_RES(ret);
449         return ret;
450 }
451
452 /*
453  * This does the heavy lifting ... we pass all the commands on to the
454  * target driver and have it do its magic ...
455  */
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)
460 {
461         struct scst_local_tgt_specific *tgt_specific = NULL;
462         struct scst_local_host_info *scst_lcl_host;
463         struct scatterlist *sgl = NULL;
464         int sgl_count = 0;
465         int target = SCpnt->device->id;
466         int lun;
467         struct scst_cmd *scst_cmd = NULL;
468         scst_data_direction dir;
469
470         TRACE_ENTRY();
471
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,
474               SCpnt->cmnd[0]);
475
476         scst_lcl_host = to_scst_lcl_host(scsi_get_device(SCpnt->device->host));
477
478         scsi_set_resid(SCpnt, 0);
479
480         if (target == SCpnt->device->host->hostt->this_id) {
481                 printk(KERN_ERR "%s: initiator's id used as target\n",
482                        __func__);
483                 return scst_local_send_resp(SCpnt, NULL, done,
484                                             DID_NO_CONNECT << 16);
485         }
486
487         /*
488          * Tell the target that we have a command ... but first we need
489          * to get the LUN into a format that SCST understand
490          */
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);
497         if (!scst_cmd) {
498                 printk(KERN_ERR "%s out of memory at line %d\n",
499                        __func__, __LINE__);
500                 return -ENOMEM;
501         }
502
503         scst_cmd_set_tag(scst_cmd, SCpnt->tag);
504         switch (scsi_get_tag_type(SCpnt->device)) {
505         case MSG_SIMPLE_TAG:
506                 scst_cmd->queue_type = SCST_CMD_QUEUE_SIMPLE;
507                 break;
508         case MSG_HEAD_TAG:
509                 scst_cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
510                 break;
511         case MSG_ORDERED_TAG:
512                 scst_cmd->queue_type = SCST_CMD_QUEUE_ORDERED;
513                 break;
514         case SCSI_NO_TAG:
515         default:
516                 scst_cmd->queue_type = SCST_CMD_QUEUE_UNTAGGED;
517                 break;
518         }
519
520         /*
521          * Get some memory to keep track of the cmnd and the done routine
522          */
523         tgt_specific = kmem_cache_alloc(tgt_specific_pool, GFP_ATOMIC);
524         if (!tgt_specific) {
525                 printk(KERN_ERR "%s out of memory at line %d\n",
526                        __func__, __LINE__);
527                 return -ENOMEM;
528         }
529         tgt_specific->cmnd = SCpnt;
530         tgt_specific->done = done;
531
532         /*
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
535          * version to version
536          */
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);
541         } else {
542                 /*
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.
546                  *
547                  * We use the sglist and bufflen function/macros to isolate
548                  * us from kernel version differences.
549                  */
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);
555                         sgl_count = 1;
556                 } else {
557                         sgl = NULL;
558                         sgl_count = 0;
559                 }
560         }
561 #else
562         sgl       = scsi_sglist(SCpnt);
563         sgl_count = scsi_sg_count(SCpnt);
564 #endif
565
566         dir = SCST_DATA_NONE;
567         switch (SCpnt->sc_data_direction) {
568         case DMA_TO_DEVICE:
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);
572                 break;
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);
577                 break;
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);
588                 break;
589 #endif
590         case DMA_NONE:
591         default:
592                 dir = SCST_DATA_NONE;
593                 scst_cmd_set_expected(scst_cmd, dir, 0);
594                 break;
595         }
596
597         scst_cmd_set_tgt_priv(scst_cmd, tgt_specific);
598
599 #ifdef CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING
600         {
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);
605         }
606 #else
607         /*
608          * Unfortunately, we called with IRQs disabled, so have no choice,
609          * except pass to the thread context.
610          */
611         scst_cmd_init_done(scst_cmd, SCST_CONTEXT_THREAD);
612 #endif
613
614         /*
615          * We are done here I think. Other callbacks move us forward.
616          */
617         TRACE_EXIT();
618         return 0;
619 }
620
621 static int scst_local_targ_pre_exec(struct scst_cmd *scst_cmd)
622 {
623         int res = SCST_PREPROCESS_STATUS_SUCCESS;
624
625         TRACE_ENTRY();
626
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);
630
631         TRACE_EXIT_RES(res);
632         return res;
633 }
634
635 static void scst_local_release_adapter(struct device *dev)
636 {
637         struct scst_local_host_info *scst_lcl_host;
638         int i = 0;
639
640         TRACE_ENTRY();
641         scst_lcl_host = to_scst_lcl_host(dev);
642         if (scst_lcl_host) {
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);
649         }
650
651         TRACE_EXIT();
652 }
653
654 /*
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
657  * ready for them.
658  *
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.
661  */
662 static int scst_local_add_adapter(void)
663 {
664         int error = 0, i = 0;
665         struct scst_local_host_info *scst_lcl_host;
666         char name[32];
667
668         TRACE_ENTRY();
669
670         scst_lcl_host = kzalloc(sizeof(struct scst_local_host_info),
671                                 GFP_KERNEL);
672         if (NULL == scst_lcl_host) {
673                 printk(KERN_ERR "%s out of memory at line %d\n",
674                        __func__, __LINE__);
675                 return -ENOMEM;
676         }
677
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);
681
682         /*
683          * Register a target with SCST and add a session
684          */
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");
689                 error = -1;
690                 goto cleanup;
691         }
692
693         /*
694          * Create a session for each device
695          */
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");
703                         error = -1;
704                         goto unregister_target;
705                 }
706         }
707
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);
713 #else
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;
717 #endif
718
719         error = device_register(&scst_lcl_host->dev);
720         if (error)
721                 goto unregister_session;
722
723         scst_local_add_host++; /* keep count of what we have added */
724
725         TRACE_EXIT();
726         return error;
727
728 unregister_session:
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],
732                         TRUE, NULL);
733         }
734 unregister_target:
735         scst_unregister(scst_lcl_host->target);
736 cleanup:
737         kfree(scst_lcl_host);
738         TRACE_EXIT();
739         return error;
740 }
741
742 /*
743  * Remove an adapter ...
744  */
745 static void scst_local_remove_adapter(void)
746 {
747         struct scst_local_host_info *scst_lcl_host = NULL;
748
749         TRACE_ENTRY();
750
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,
755                                            host_list);
756                 list_del(&scst_lcl_host->host_list);
757         }
758         spin_unlock(&scst_local_host_list_lock);
759
760         if (!scst_lcl_host)
761                 return;
762
763         device_unregister(&scst_lcl_host->dev);
764
765         --scst_local_add_host;
766
767         TRACE_EXIT();
768 }
769
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,
781 #endif
782         .can_queue                      = 256,
783         .this_id                        = SCST_LOCAL_MAX_TARGETS,
784         /* SCST doesn't support sg chaining */
785         .sg_tablesize                   = SCSI_MAX_SG_SEGMENTS,
786         .cmd_per_lun                    = 32,
787         .max_sectors                    = 0xffff,
788         /*
789          * There's no gain to merge requests on this level. If necessary,
790          * they will be merged at the backstorage level.
791          */
792         .use_clustering                 = DISABLE_CLUSTERING,
793         .skip_settle_delay              = 1,
794         .module                         = THIS_MODULE,
795 };
796
797 static void scst_fake_0_release(struct device *dev)
798 {
799         TRACE_ENTRY();
800
801         TRACE_EXIT();
802 }
803
804 static struct device scst_fake_primary = {
805 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
806         .bus_id         = "scst_fake_0",
807 #else
808         .init_name      = "scst_fake_0",
809 #endif
810         .release        = scst_fake_0_release,
811 };
812
813 static int __init scst_local_init(void)
814 {
815         int ret, k, adapters;
816
817         TRACE_ENTRY();
818
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 "
823                 "details.");
824         ret = -EINVAL;
825         goto out;
826 #endif
827
828         TRACE_DBG("Adapters: %d\n", scst_local_add_host);
829
830         if (scst_local_num_tgts > SCST_LOCAL_MAX_TARGETS)
831                 scst_local_num_tgts = SCST_LOCAL_MAX_TARGETS;
832
833         /*
834          * Allocate a pool of structures for tgt_specific structures
835          */
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);
840 #else
841         tgt_specific_pool = kmem_cache_create("scst_tgt_specific",
842                                       sizeof(struct scst_local_tgt_specific),
843                                       0, SCST_SLAB_FLAGS, NULL, NULL);
844 #endif
845
846         if (!tgt_specific_pool) {
847                 printk(KERN_WARNING "%s: out of memory for "
848                        "tgt_specific structs",
849                        __func__);
850                 return -ENOMEM;
851         }
852
853         ret = device_register(&scst_fake_primary);
854         if (ret < 0) {
855                 printk(KERN_WARNING "%s: device_register error: %d\n",
856                        __func__, ret);
857                 goto destroy_kmem;
858         }
859         ret = bus_register(&scst_fake_lld_bus);
860         if (ret < 0) {
861                 printk(KERN_WARNING "%s: bus_register error: %d\n",
862                        __func__, ret);
863                 goto dev_unreg;
864         }
865         ret = driver_register(&scst_local_driverfs_driver);
866         if (ret < 0) {
867                 printk(KERN_WARNING "%s: driver_register error: %d\n",
868                        __func__, ret);
869                 goto bus_unreg;
870         }
871         ret = do_create_driverfs_files();
872         if (ret < 0) {
873                 printk(KERN_WARNING "%s: create_files error: %d\n",
874                        __func__, ret);
875                 goto driver_unregister;
876         }
877
878
879         /*
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.
883          */
884
885         ret = scst_local_target_register();
886         if (ret < 0) {
887                 printk(KERN_WARNING "%s: unable to register targ griver: %d\n",
888                        __func__, ret);
889                 goto del_files;
890         }
891
892         /*
893          * Add adapters ...
894          */
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",
901                                         __func__, k);
902                         break;
903                 }
904         }
905
906 out:
907         TRACE_EXIT_RES(ret);
908         return ret;
909
910 del_files:
911         do_remove_driverfs_files();
912 driver_unregister:
913         driver_unregister(&scst_local_driverfs_driver);
914 bus_unreg:
915         bus_unregister(&scst_fake_lld_bus);
916 dev_unreg:
917         device_unregister(&scst_fake_primary);
918 destroy_kmem:
919         kmem_cache_destroy(tgt_specific_pool);
920         goto out;
921 }
922
923 static void __exit scst_local_exit(void)
924 {
925         int k = scst_local_add_host;
926
927         TRACE_ENTRY();
928
929         for (; k; k--) {
930                 printk(KERN_INFO "removing adapter in %s\n", __func__);
931                 scst_local_remove_adapter();
932         }
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);
937
938         /*
939          * Now unregister the target template
940          */
941         scst_unregister_target_template(&scst_local_targ_tmpl);
942
943         /*
944          * Free the pool we allocated
945          */
946         if (tgt_specific_pool)
947                 kmem_cache_destroy(tgt_specific_pool);
948
949         TRACE_EXIT();
950 }
951
952 device_initcall(scst_local_init);
953 module_exit(scst_local_exit);
954
955 /*
956  * Fake LLD Bus and functions
957  */
958
959 static int scst_fake_lld_driver_probe(struct device *dev)
960 {
961         int ret = 0;
962         struct scst_local_host_info *scst_lcl_host;
963         struct Scsi_Host *hpnt;
964
965         TRACE_ENTRY();
966
967         scst_lcl_host = to_scst_lcl_host(dev);
968
969         hpnt = scsi_host_alloc(&scst_lcl_ini_driver_template,
970                                sizeof(scst_lcl_host));
971         if (NULL == hpnt) {
972                 printk(KERN_ERR "%s: scsi_register failed\n", __func__);
973                 ret = -ENODEV;
974                 return ret;
975         }
976
977         scst_lcl_host->shost = hpnt;
978
979         /*
980          * We are going to have to register with SCST here I think
981          * and fill in some of these from that info?
982          */
983
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;
987         else
988                 hpnt->max_id = scst_local_num_tgts;
989         hpnt->max_lun = scst_local_max_luns - 1;
990
991         hpnt->max_cmd_len = 260;
992
993         ret = scsi_add_host(hpnt, &scst_lcl_host->dev);
994         if (ret) {
995                 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
996                 ret = -ENODEV;
997                 scsi_host_put(hpnt);
998         } else
999                 scsi_scan_host(hpnt);
1000
1001         TRACE_EXIT_RES(ret);
1002         return ret;
1003 }
1004
1005 static int scst_fake_lld_driver_remove(struct device *dev)
1006 {
1007         struct scst_local_host_info *scst_lcl_host;
1008
1009         TRACE_ENTRY();
1010
1011         scst_lcl_host = to_scst_lcl_host(dev);
1012
1013         if (!scst_lcl_host) {
1014                 printk(KERN_ERR "%s: Unable to locate host info\n",
1015                        __func__);
1016                 return -ENODEV;
1017         }
1018
1019         scsi_remove_host(scst_lcl_host->shost);
1020
1021         scsi_host_put(scst_lcl_host->shost);
1022
1023         TRACE_EXIT();
1024         return 0;
1025 }
1026
1027 static int scst_fake_lld_bus_match(struct device *dev,
1028                                    struct device_driver *dev_driver)
1029 {
1030         TRACE_ENTRY();
1031
1032         TRACE_EXIT();
1033         return 1;
1034 }
1035
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,
1041 };
1042
1043 /*
1044  * SCST Target driver from here ... there are some forward declarations
1045  * above
1046  */
1047
1048 static int scst_local_targ_detect(struct scst_tgt_template *tgt_template)
1049 {
1050         int adapter_count;
1051
1052         TRACE_ENTRY();
1053
1054         /*
1055          * Register the adapter(s)
1056          */
1057
1058         adapter_count = scst_local_add_host;
1059
1060         TRACE_EXIT_RES(adapter_count);
1061         return adapter_count;
1062 };
1063
1064 static int scst_local_targ_release(struct scst_tgt *tgt)
1065 {
1066         TRACE_ENTRY();
1067
1068         TRACE_EXIT();
1069         return 0;
1070 }
1071
1072 static int scst_local_targ_xmit_response(struct scst_cmd *scst_cmd)
1073 {
1074         struct scst_local_tgt_specific *tgt_specific;
1075
1076         TRACE_ENTRY();
1077
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;
1083         }
1084
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);
1088
1089         tgt_specific = scst_cmd_get_tgt_priv(scst_cmd);
1090
1091         /*
1092          * This might have to change to use the two status flags
1093          */
1094         if (scst_cmd_get_is_send_status(scst_cmd)) {
1095                 (void)scst_local_send_resp(tgt_specific->cmnd, scst_cmd,
1096                                            tgt_specific->done,
1097                                            scst_cmd_get_status(scst_cmd));
1098         }
1099
1100         /*
1101          * Now tell SCST that the command is done ...
1102          */
1103         scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_SAME);
1104
1105         TRACE_EXIT();
1106
1107         return SCST_TGT_RES_SUCCESS;
1108 }
1109
1110 static void scst_local_targ_on_free_cmd(struct scst_cmd *scst_cmd)
1111 {
1112         struct scst_local_tgt_specific *tgt_specific;
1113
1114         TRACE_ENTRY();
1115
1116         tgt_specific = scst_cmd_get_tgt_priv(scst_cmd);
1117         kmem_cache_free(tgt_specific_pool, tgt_specific);
1118
1119         TRACE_EXIT();
1120         return;
1121 }
1122
1123 static void scst_local_targ_task_mgmt_done(struct scst_mgmt_cmd *mgmt_cmd)
1124 {
1125         struct completion *tgt_specific;
1126
1127         TRACE_ENTRY();
1128
1129         tgt_specific = (struct completion *)
1130                          scst_mgmt_cmd_get_tgt_priv(mgmt_cmd);
1131
1132         if (tgt_specific)
1133                 complete(tgt_specific);
1134
1135         TRACE_EXIT();
1136         return;
1137 }
1138
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,
1149 };
1150
1151 /*
1152  * Register the target driver ... to get things going
1153  */
1154 static int scst_local_target_register(void)
1155 {
1156         int ret;
1157
1158         TRACE_ENTRY();
1159
1160         ret = scst_register_target_template(&scst_local_targ_tmpl);
1161         if (ret < 0) {
1162                 printk(KERN_WARNING "scst_register_target_template "
1163                        "failed: %d\n",
1164                        ret);
1165                 goto error;
1166         }
1167
1168         TRACE_EXIT();
1169         return 0;
1170
1171 error:
1172         TRACE_EXIT_RES(ret);
1173         return ret;
1174 }
1175