- supported.conf: Added sparse_keymap (eeepc_laptop depends on it)
[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 #include <linux/version.h>
33 #include "common.h"
34
35 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
36   #define DEFAULT_TASK_COMM_LEN 16
37 #else
38   #define DEFAULT_TASK_COMM_LEN TASK_COMM_LEN
39 #endif
40
41 extern struct scsi_host_template scsifront_sht;
42
43 static void scsifront_free(struct vscsifrnt_info *info)
44 {
45         struct Scsi_Host *host = info->host;
46
47 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
48         if (host->shost_state != SHOST_DEL) {
49 #else
50         if (!test_bit(SHOST_DEL, &host->shost_state)) {
51 #endif
52                 scsi_remove_host(info->host);
53         }
54
55         if (info->ring_ref != GRANT_INVALID_REF) {
56                 gnttab_end_foreign_access(info->ring_ref,
57                                         (unsigned long)info->ring.sring);
58                 info->ring_ref = GRANT_INVALID_REF;
59                 info->ring.sring = NULL;
60         }
61
62         if (info->irq)
63                 unbind_from_irqhandler(info->irq, info);
64         info->irq = 0;
65
66         scsi_host_put(info->host);
67 }
68
69
70 static int scsifront_alloc_ring(struct vscsifrnt_info *info)
71 {
72         struct xenbus_device *dev = info->dev;
73         struct vscsiif_sring *sring;
74         int err = -ENOMEM;
75
76
77         info->ring_ref = GRANT_INVALID_REF;
78
79         /***** Frontend to Backend ring start *****/
80         sring = (struct vscsiif_sring *) __get_free_page(GFP_KERNEL);
81         if (!sring) {
82                 xenbus_dev_fatal(dev, err, "fail to allocate shared ring (Front to Back)");
83                 return err;
84         }
85         SHARED_RING_INIT(sring);
86         FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
87
88         err = xenbus_grant_ring(dev, virt_to_mfn(sring));
89         if (err < 0) {
90                 free_page((unsigned long) sring);
91                 info->ring.sring = NULL;
92                 xenbus_dev_fatal(dev, err, "fail to grant shared ring (Front to Back)");
93                 goto free_sring;
94         }
95         info->ring_ref = err;
96
97         err = bind_listening_port_to_irqhandler(
98                         dev->otherend_id, scsifront_intr,
99                         IRQF_SAMPLE_RANDOM, "scsifront", info);
100
101         if (err <= 0) {
102                 xenbus_dev_fatal(dev, err, "bind_listening_port_to_irqhandler");
103                 goto free_sring;
104         }
105         info->irq = err;
106
107         return 0;
108
109 /* free resource */
110 free_sring:
111         scsifront_free(info);
112
113         return err;
114 }
115
116
117 static int scsifront_init_ring(struct vscsifrnt_info *info)
118 {
119         struct xenbus_device *dev = info->dev;
120         struct xenbus_transaction xbt;
121         int err;
122
123         DPRINTK("%s\n",__FUNCTION__);
124
125         err = scsifront_alloc_ring(info);
126         if (err)
127                 return err;
128         DPRINTK("%u %u\n", info->ring_ref, info->evtchn);
129
130 again:
131         err = xenbus_transaction_start(&xbt);
132         if (err) {
133                 xenbus_dev_fatal(dev, err, "starting transaction");
134         }
135
136         err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u",
137                                 info->ring_ref);
138         if (err) {
139                 xenbus_dev_fatal(dev, err, "%s", "writing ring-ref");
140                 goto fail;
141         }
142
143         err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
144                                 irq_to_evtchn_port(info->irq));
145
146         if (err) {
147                 xenbus_dev_fatal(dev, err, "%s", "writing event-channel");
148                 goto fail;
149         }
150
151         err = xenbus_transaction_end(xbt, 0);
152         if (err) {
153                 if (err == -EAGAIN)
154                         goto again;
155                 xenbus_dev_fatal(dev, err, "completing transaction");
156                 goto free_sring;
157         }
158
159         return 0;
160
161 fail:
162         xenbus_transaction_end(xbt, 1);
163 free_sring:
164         /* free resource */
165         scsifront_free(info);
166         
167         return err;
168 }
169
170
171 static int scsifront_probe(struct xenbus_device *dev,
172                                 const struct xenbus_device_id *id)
173 {
174         struct vscsifrnt_info *info;
175         struct Scsi_Host *host;
176         int i, err = -ENOMEM;
177         char name[DEFAULT_TASK_COMM_LEN];
178
179         host = scsi_host_alloc(&scsifront_sht, sizeof(*info));
180         if (!host) {
181                 xenbus_dev_fatal(dev, err, "fail to allocate scsi host");
182                 return err;
183         }
184         info = (struct vscsifrnt_info *) host->hostdata;
185         info->host = host;
186
187
188         dev_set_drvdata(&dev->dev, info);
189         info->dev  = dev;
190
191         for (i = 0; i < VSCSIIF_MAX_REQS; i++) {
192                 info->shadow[i].next_free = i + 1;
193                 init_waitqueue_head(&(info->shadow[i].wq_reset));
194                 info->shadow[i].wait_reset = 0;
195         }
196         info->shadow[VSCSIIF_MAX_REQS - 1].next_free = 0x0fff;
197
198         err = scsifront_init_ring(info);
199         if (err) {
200                 scsi_host_put(host);
201                 return err;
202         }
203
204         init_waitqueue_head(&info->wq);
205         spin_lock_init(&info->io_lock);
206         spin_lock_init(&info->shadow_lock);
207
208         snprintf(name, DEFAULT_TASK_COMM_LEN, "vscsiif.%d", info->host->host_no);
209
210         info->kthread = kthread_run(scsifront_schedule, info, name);
211         if (IS_ERR(info->kthread)) {
212                 err = PTR_ERR(info->kthread);
213                 info->kthread = NULL;
214                 printk(KERN_ERR "scsifront: kthread start err %d\n", err);
215                 goto free_sring;
216         }
217
218         host->max_id      = VSCSIIF_MAX_TARGET;
219         host->max_channel = 0;
220         host->max_lun     = VSCSIIF_MAX_LUN;
221         host->max_sectors = (VSCSIIF_SG_TABLESIZE - 1) * PAGE_SIZE / 512;
222
223         err = scsi_add_host(host, &dev->dev);
224         if (err) {
225                 printk(KERN_ERR "scsifront: fail to add scsi host %d\n", err);
226                 goto free_sring;
227         }
228
229         xenbus_switch_state(dev, XenbusStateInitialised);
230
231         return 0;
232
233 free_sring:
234         /* free resource */
235         scsifront_free(info);
236         return err;
237 }
238
239 static int scsifront_remove(struct xenbus_device *dev)
240 {
241         struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
242
243         DPRINTK("%s: %s removed\n",__FUNCTION__ ,dev->nodename);
244
245         if (info->kthread) {
246                 kthread_stop(info->kthread);
247                 info->kthread = NULL;
248         }
249
250         scsifront_free(info);
251         
252         return 0;
253 }
254
255
256 static int scsifront_disconnect(struct vscsifrnt_info *info)
257 {
258         struct xenbus_device *dev = info->dev;
259         struct Scsi_Host *host = info->host;
260
261         DPRINTK("%s: %s disconnect\n",__FUNCTION__ ,dev->nodename);
262
263         /* 
264           When this function is executed,  all devices of 
265           Frontend have been deleted. 
266           Therefore, it need not block I/O before remove_host.
267         */
268
269         scsi_remove_host(host);
270         xenbus_frontend_closed(dev);
271
272         return 0;
273 }
274
275 #define VSCSIFRONT_OP_ADD_LUN   1
276 #define VSCSIFRONT_OP_DEL_LUN   2
277
278 static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op)
279 {
280         struct xenbus_device *dev = info->dev;
281         int i, err = 0;
282         char str[64], state_str[64];
283         char **dir;
284         unsigned int dir_n = 0;
285         unsigned int device_state;
286         unsigned int hst, chn, tgt, lun;
287         struct scsi_device *sdev;
288
289         dir = xenbus_directory(XBT_NIL, dev->otherend, "vscsi-devs", &dir_n);
290         if (IS_ERR(dir))
291                 return;
292
293         for (i = 0; i < dir_n; i++) {
294                 /* read status */
295                 snprintf(str, sizeof(str), "vscsi-devs/%s/state", dir[i]);
296                 err = xenbus_scanf(XBT_NIL, dev->otherend, str, "%u",
297                         &device_state);
298                 if (XENBUS_EXIST_ERR(err))
299                         continue;
300                 
301                 /* virtual SCSI device */
302                 snprintf(str, sizeof(str), "vscsi-devs/%s/v-dev", dir[i]);
303                 err = xenbus_scanf(XBT_NIL, dev->otherend, str,
304                         "%u:%u:%u:%u", &hst, &chn, &tgt, &lun);
305                 if (XENBUS_EXIST_ERR(err))
306                         continue;
307
308                 /* front device state path */
309                 snprintf(state_str, sizeof(state_str), "vscsi-devs/%s/state", dir[i]);
310
311                 switch (op) {
312                 case VSCSIFRONT_OP_ADD_LUN:
313                         if (device_state == XenbusStateInitialised) {
314                                 sdev = scsi_device_lookup(info->host, chn, tgt, lun);
315                                 if (sdev) {
316                                         printk(KERN_ERR "scsifront: Device already in use.\n");
317                                         scsi_device_put(sdev);
318                                         xenbus_printf(XBT_NIL, dev->nodename,
319                                                 state_str, "%d", XenbusStateClosed);
320                                 } else {
321                                         scsi_add_device(info->host, chn, tgt, lun);
322                                         xenbus_printf(XBT_NIL, dev->nodename,
323                                                 state_str, "%d", XenbusStateConnected);
324                                 }
325                         }
326                         break;
327                 case VSCSIFRONT_OP_DEL_LUN:
328                         if (device_state == XenbusStateClosing) {
329                                 sdev = scsi_device_lookup(info->host, chn, tgt, lun);
330                                 if (sdev) {
331                                         scsi_remove_device(sdev);
332                                         scsi_device_put(sdev);
333                                         xenbus_printf(XBT_NIL, dev->nodename,
334                                                 state_str, "%d", XenbusStateClosed);
335                                 }
336                         }
337                         break;
338                 default:
339                         break;
340                 }
341         }
342         
343         kfree(dir);
344         return;
345 }
346
347
348
349
350 static void scsifront_backend_changed(struct xenbus_device *dev,
351                                 enum xenbus_state backend_state)
352 {
353         struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
354
355         DPRINTK("%p %u %u\n", dev, dev->state, backend_state);
356
357         switch (backend_state) {
358         case XenbusStateUnknown:
359         case XenbusStateInitialising:
360         case XenbusStateInitWait:
361         case XenbusStateClosed:
362                 break;
363
364         case XenbusStateInitialised:
365                 break;
366
367         case XenbusStateConnected:
368                 if (xenbus_read_driver_state(dev->nodename) ==
369                         XenbusStateInitialised) {
370                         scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
371                 }
372                 
373                 if (dev->state == XenbusStateConnected)
374                         break;
375                         
376                 xenbus_switch_state(dev, XenbusStateConnected);
377                 break;
378
379         case XenbusStateClosing:
380                 scsifront_disconnect(info);
381                 break;
382
383         case XenbusStateReconfiguring:
384                 scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_DEL_LUN);
385                 xenbus_switch_state(dev, XenbusStateReconfiguring);
386                 break;
387
388         case XenbusStateReconfigured:
389                 scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
390                 xenbus_switch_state(dev, XenbusStateConnected);
391                 break;
392         }
393 }
394
395
396 static struct xenbus_device_id scsifront_ids[] = {
397         { "vscsi" },
398         { "" }
399 };
400
401
402 static struct xenbus_driver scsifront_driver = {
403         .name                   = "vscsi",
404         .ids                    = scsifront_ids,
405         .probe                  = scsifront_probe,
406         .remove                 = scsifront_remove,
407 /*      .resume                 = scsifront_resume, */
408         .otherend_changed       = scsifront_backend_changed,
409 };
410
411 int scsifront_xenbus_init(void)
412 {
413         return xenbus_register_frontend(&scsifront_driver);
414 }
415
416 void scsifront_xenbus_unregister(void)
417 {
418         xenbus_unregister_driver(&scsifront_driver);
419 }
420