Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / scsifront / xenbus.c
1 /*
2  * Xen SCSI frontend driver
3  *
4  * Copyright (c) 2008, FUJITSU Limited
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License version 2
8  * as published by the Free Software Foundation; or, when distributed
9  * separately from the Linux kernel or incorporated into other
10  * software packages, subject to the following license:
11  * 
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this source file (the "Software"), to deal in the Software without
14  * restriction, including without limitation the rights to use, copy, modify,
15  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16  * and to permit persons to whom the Software is furnished to do so, subject to
17  * the following conditions:
18  * 
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21  * 
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28  * IN THE SOFTWARE.
29  */
30
31 /*
32 * Patched to support >2TB drives
33 * 2010, Samuel Kvasnica, IMS Nanofabrication AG
34 */
35
36 #include <linux/version.h>
37 #include <linux/slab.h>
38 #include "common.h"
39
40 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
41   #define DEFAULT_TASK_COMM_LEN 16
42 #else
43   #define DEFAULT_TASK_COMM_LEN TASK_COMM_LEN
44 #endif
45
46 extern struct scsi_host_template scsifront_sht;
47
48 static void scsifront_free(struct vscsifrnt_info *info)
49 {
50         struct Scsi_Host *host = info->host;
51
52 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
53         if (host->shost_state != SHOST_DEL) {
54 #else
55         if (!test_bit(SHOST_DEL, &host->shost_state)) {
56 #endif
57                 scsi_remove_host(info->host);
58         }
59
60         if (info->ring_ref != GRANT_INVALID_REF) {
61                 gnttab_end_foreign_access(info->ring_ref,
62                                         (unsigned long)info->ring.sring);
63                 info->ring_ref = GRANT_INVALID_REF;
64                 info->ring.sring = NULL;
65         }
66
67         if (info->irq)
68                 unbind_from_irqhandler(info->irq, info);
69         info->irq = 0;
70
71         scsi_host_put(info->host);
72 }
73
74
75 static int scsifront_alloc_ring(struct vscsifrnt_info *info)
76 {
77         struct xenbus_device *dev = info->dev;
78         struct vscsiif_sring *sring;
79         int err = -ENOMEM;
80
81
82         info->ring_ref = GRANT_INVALID_REF;
83
84         /***** Frontend to Backend ring start *****/
85         sring = (struct vscsiif_sring *) __get_free_page(GFP_KERNEL);
86         if (!sring) {
87                 xenbus_dev_fatal(dev, err, "fail to allocate shared ring (Front to Back)");
88                 return err;
89         }
90         SHARED_RING_INIT(sring);
91         FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
92
93         err = xenbus_grant_ring(dev, virt_to_mfn(sring));
94         if (err < 0) {
95                 free_page((unsigned long) sring);
96                 info->ring.sring = NULL;
97                 xenbus_dev_fatal(dev, err, "fail to grant shared ring (Front to Back)");
98                 goto free_sring;
99         }
100         info->ring_ref = err;
101
102         err = bind_listening_port_to_irqhandler(
103                         dev->otherend_id, scsifront_intr,
104                         IRQF_SAMPLE_RANDOM, "scsifront", info);
105
106         if (err <= 0) {
107                 xenbus_dev_fatal(dev, err, "bind_listening_port_to_irqhandler");
108                 goto free_sring;
109         }
110         info->irq = err;
111
112         return 0;
113
114 /* free resource */
115 free_sring:
116         scsifront_free(info);
117
118         return err;
119 }
120
121
122 static int scsifront_init_ring(struct vscsifrnt_info *info)
123 {
124         struct xenbus_device *dev = info->dev;
125         struct xenbus_transaction xbt;
126         int err;
127
128         DPRINTK("%s\n",__FUNCTION__);
129
130         err = scsifront_alloc_ring(info);
131         if (err)
132                 return err;
133         DPRINTK("%u %u\n", info->ring_ref, info->evtchn);
134
135 again:
136         err = xenbus_transaction_start(&xbt);
137         if (err) {
138                 xenbus_dev_fatal(dev, err, "starting transaction");
139         }
140
141         err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u",
142                                 info->ring_ref);
143         if (err) {
144                 xenbus_dev_fatal(dev, err, "%s", "writing ring-ref");
145                 goto fail;
146         }
147
148         err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
149                                 irq_to_evtchn_port(info->irq));
150
151         if (err) {
152                 xenbus_dev_fatal(dev, err, "%s", "writing event-channel");
153                 goto fail;
154         }
155
156         err = xenbus_transaction_end(xbt, 0);
157         if (err) {
158                 if (err == -EAGAIN)
159                         goto again;
160                 xenbus_dev_fatal(dev, err, "completing transaction");
161                 goto free_sring;
162         }
163
164         return 0;
165
166 fail:
167         xenbus_transaction_end(xbt, 1);
168 free_sring:
169         /* free resource */
170         scsifront_free(info);
171         
172         return err;
173 }
174
175
176 static int scsifront_probe(struct xenbus_device *dev,
177                                 const struct xenbus_device_id *id)
178 {
179         struct vscsifrnt_info *info;
180         struct Scsi_Host *host;
181         int i, err = -ENOMEM;
182         char name[DEFAULT_TASK_COMM_LEN];
183
184         host = scsi_host_alloc(&scsifront_sht, sizeof(*info));
185         if (!host) {
186                 xenbus_dev_fatal(dev, err, "fail to allocate scsi host");
187                 return err;
188         }
189         info = (struct vscsifrnt_info *) host->hostdata;
190         info->host = host;
191
192
193         dev_set_drvdata(&dev->dev, info);
194         info->dev  = dev;
195
196         for (i = 0; i < VSCSIIF_MAX_REQS; i++) {
197                 info->shadow[i].next_free = i + 1;
198                 init_waitqueue_head(&(info->shadow[i].wq_reset));
199                 info->shadow[i].wait_reset = 0;
200         }
201         info->shadow[VSCSIIF_MAX_REQS - 1].next_free = 0x0fff;
202
203         err = scsifront_init_ring(info);
204         if (err) {
205                 scsi_host_put(host);
206                 return err;
207         }
208
209         init_waitqueue_head(&info->wq);
210         spin_lock_init(&info->io_lock);
211         spin_lock_init(&info->shadow_lock);
212
213         snprintf(name, DEFAULT_TASK_COMM_LEN, "vscsiif.%d", info->host->host_no);
214
215         info->kthread = kthread_run(scsifront_schedule, info, name);
216         if (IS_ERR(info->kthread)) {
217                 err = PTR_ERR(info->kthread);
218                 info->kthread = NULL;
219                 pr_err("scsifront: kthread start err %d\n", err);
220                 goto free_sring;
221         }
222
223         host->max_id      = VSCSIIF_MAX_TARGET;
224         host->max_channel = 0;
225         host->max_lun     = VSCSIIF_MAX_LUN;
226         host->max_sectors = (VSCSIIF_SG_TABLESIZE - 1) * PAGE_SIZE / 512;
227         host->max_cmd_len = VSCSIIF_MAX_COMMAND_SIZE;
228
229         err = scsi_add_host(host, &dev->dev);
230         if (err) {
231                 pr_err("scsifront: fail to add scsi host %d\n", err);
232                 goto free_sring;
233         }
234
235         xenbus_switch_state(dev, XenbusStateInitialised);
236
237         return 0;
238
239 free_sring:
240         /* free resource */
241         scsifront_free(info);
242         return err;
243 }
244
245 static int scsifront_remove(struct xenbus_device *dev)
246 {
247         struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
248
249         DPRINTK("%s: %s removed\n",__FUNCTION__ ,dev->nodename);
250
251         if (info->kthread) {
252                 kthread_stop(info->kthread);
253                 info->kthread = NULL;
254         }
255
256         scsifront_free(info);
257         
258         return 0;
259 }
260
261
262 static int scsifront_disconnect(struct vscsifrnt_info *info)
263 {
264         struct xenbus_device *dev = info->dev;
265         struct Scsi_Host *host = info->host;
266
267         DPRINTK("%s: %s disconnect\n",__FUNCTION__ ,dev->nodename);
268
269         /* 
270           When this function is executed,  all devices of 
271           Frontend have been deleted. 
272           Therefore, it need not block I/O before remove_host.
273         */
274
275         scsi_remove_host(host);
276         xenbus_frontend_closed(dev);
277
278         return 0;
279 }
280
281 #define VSCSIFRONT_OP_ADD_LUN   1
282 #define VSCSIFRONT_OP_DEL_LUN   2
283
284 static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op)
285 {
286         struct xenbus_device *dev = info->dev;
287         int i, err = 0;
288         char str[64], state_str[64];
289         char **dir;
290         unsigned int dir_n = 0;
291         unsigned int device_state;
292         unsigned int hst, chn, tgt, lun;
293         struct scsi_device *sdev;
294
295         dir = xenbus_directory(XBT_NIL, dev->otherend, "vscsi-devs", &dir_n);
296         if (IS_ERR(dir))
297                 return;
298
299         for (i = 0; i < dir_n; i++) {
300                 /* read status */
301                 snprintf(str, sizeof(str), "vscsi-devs/%s/state", dir[i]);
302                 err = xenbus_scanf(XBT_NIL, dev->otherend, str, "%u",
303                         &device_state);
304                 if (XENBUS_EXIST_ERR(err))
305                         continue;
306                 
307                 /* virtual SCSI device */
308                 snprintf(str, sizeof(str), "vscsi-devs/%s/v-dev", dir[i]);
309                 err = xenbus_scanf(XBT_NIL, dev->otherend, str,
310                         "%u:%u:%u:%u", &hst, &chn, &tgt, &lun);
311                 if (XENBUS_EXIST_ERR(err))
312                         continue;
313
314                 /* front device state path */
315                 snprintf(state_str, sizeof(state_str), "vscsi-devs/%s/state", dir[i]);
316
317                 switch (op) {
318                 case VSCSIFRONT_OP_ADD_LUN:
319                         if (device_state == XenbusStateInitialised) {
320                                 sdev = scsi_device_lookup(info->host, chn, tgt, lun);
321                                 if (sdev) {
322                                         pr_err("scsifront: Device already in use.\n");
323                                         scsi_device_put(sdev);
324                                         xenbus_printf(XBT_NIL, dev->nodename,
325                                                 state_str, "%d", XenbusStateClosed);
326                                 } else {
327                                         scsi_add_device(info->host, chn, tgt, lun);
328                                         xenbus_printf(XBT_NIL, dev->nodename,
329                                                 state_str, "%d", XenbusStateConnected);
330                                 }
331                         }
332                         break;
333                 case VSCSIFRONT_OP_DEL_LUN:
334                         if (device_state == XenbusStateClosing) {
335                                 sdev = scsi_device_lookup(info->host, chn, tgt, lun);
336                                 if (sdev) {
337                                         scsi_remove_device(sdev);
338                                         scsi_device_put(sdev);
339                                         xenbus_printf(XBT_NIL, dev->nodename,
340                                                 state_str, "%d", XenbusStateClosed);
341                                 }
342                         }
343                         break;
344                 default:
345                         break;
346                 }
347         }
348         
349         kfree(dir);
350         return;
351 }
352
353
354
355
356 static void scsifront_backend_changed(struct xenbus_device *dev,
357                                 enum xenbus_state backend_state)
358 {
359         struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
360
361         DPRINTK("%p %u %u\n", dev, dev->state, backend_state);
362
363         switch (backend_state) {
364         case XenbusStateUnknown:
365         case XenbusStateInitialising:
366         case XenbusStateInitWait:
367         case XenbusStateClosed:
368                 break;
369
370         case XenbusStateInitialised:
371                 break;
372
373         case XenbusStateConnected:
374                 if (xenbus_read_driver_state(dev->nodename) ==
375                         XenbusStateInitialised) {
376                         scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
377                 }
378                 
379                 if (dev->state == XenbusStateConnected)
380                         break;
381                         
382                 xenbus_switch_state(dev, XenbusStateConnected);
383                 break;
384
385         case XenbusStateClosing:
386                 scsifront_disconnect(info);
387                 break;
388
389         case XenbusStateReconfiguring:
390                 scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_DEL_LUN);
391                 xenbus_switch_state(dev, XenbusStateReconfiguring);
392                 break;
393
394         case XenbusStateReconfigured:
395                 scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
396                 xenbus_switch_state(dev, XenbusStateConnected);
397                 break;
398         }
399 }
400
401
402 static const struct xenbus_device_id scsifront_ids[] = {
403         { "vscsi" },
404         { "" }
405 };
406 MODULE_ALIAS("xen:vscsi");
407
408 static DEFINE_XENBUS_DRIVER(scsifront, ,
409         .probe                  = scsifront_probe,
410         .remove                 = scsifront_remove,
411 /*      .resume                 = scsifront_resume, */
412         .otherend_changed       = scsifront_backend_changed,
413 );
414
415 int scsifront_xenbus_init(void)
416 {
417         return xenbus_register_frontend(&scsifront_driver);
418 }
419
420 void scsifront_xenbus_unregister(void)
421 {
422         xenbus_unregister_driver(&scsifront_driver);
423 }
424