Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[pandora-kernel.git] / net / 9p / trans_virtio.c
1 /*
2  * The Virtio 9p transport driver
3  *
4  * This is a block based transport driver based on the lguest block driver
5  * code.
6  *
7  *  Copyright (C) 2007, 2008 Eric Van Hensbergen, IBM Corporation
8  *
9  *  Based on virtio console driver
10  *  Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License version 2
14  *  as published by the Free Software Foundation.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to:
23  *  Free Software Foundation
24  *  51 Franklin Street, Fifth Floor
25  *  Boston, MA  02111-1301  USA
26  *
27  */
28
29 #include <linux/in.h>
30 #include <linux/module.h>
31 #include <linux/net.h>
32 #include <linux/ipv6.h>
33 #include <linux/errno.h>
34 #include <linux/kernel.h>
35 #include <linux/un.h>
36 #include <linux/uaccess.h>
37 #include <linux/inet.h>
38 #include <linux/idr.h>
39 #include <linux/file.h>
40 #include <linux/slab.h>
41 #include <net/9p/9p.h>
42 #include <linux/parser.h>
43 #include <net/9p/client.h>
44 #include <net/9p/transport.h>
45 #include <linux/scatterlist.h>
46 #include <linux/virtio.h>
47 #include <linux/virtio_9p.h>
48
49 #define VIRTQUEUE_NUM   128
50
51 /* a single mutex to manage channel initialization and attachment */
52 static DEFINE_MUTEX(virtio_9p_lock);
53
54 /**
55  * struct virtio_chan - per-instance transport information
56  * @initialized: whether the channel is initialized
57  * @inuse: whether the channel is in use
58  * @lock: protects multiple elements within this structure
59  * @client: client instance
60  * @vdev: virtio dev associated with this channel
61  * @vq: virtio queue associated with this channel
62  * @sg: scatter gather list which is used to pack a request (protected?)
63  *
64  * We keep all per-channel information in a structure.
65  * This structure is allocated within the devices dev->mem space.
66  * A pointer to the structure will get put in the transport private.
67  *
68  */
69
70 struct virtio_chan {
71         bool inuse;
72
73         spinlock_t lock;
74
75         struct p9_client *client;
76         struct virtio_device *vdev;
77         struct virtqueue *vq;
78         int ring_bufs_avail;
79         wait_queue_head_t *vc_wq;
80
81         /* Scatterlist: can be too big for stack. */
82         struct scatterlist sg[VIRTQUEUE_NUM];
83
84         int tag_len;
85         /*
86          * tag name to identify a mount Non-null terminated
87          */
88         char *tag;
89
90         struct list_head chan_list;
91 };
92
93 static struct list_head virtio_chan_list;
94
95 /* How many bytes left in this page. */
96 static unsigned int rest_of_page(void *data)
97 {
98         return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);
99 }
100
101 /**
102  * p9_virtio_close - reclaim resources of a channel
103  * @client: client instance
104  *
105  * This reclaims a channel by freeing its resources and
106  * reseting its inuse flag.
107  *
108  */
109
110 static void p9_virtio_close(struct p9_client *client)
111 {
112         struct virtio_chan *chan = client->trans;
113
114         mutex_lock(&virtio_9p_lock);
115         if (chan)
116                 chan->inuse = false;
117         mutex_unlock(&virtio_9p_lock);
118 }
119
120 /**
121  * req_done - callback which signals activity from the server
122  * @vq: virtio queue activity was received on
123  *
124  * This notifies us that the server has triggered some activity
125  * on the virtio channel - most likely a response to request we
126  * sent.  Figure out which requests now have responses and wake up
127  * those threads.
128  *
129  * Bugs: could do with some additional sanity checking, but appears to work.
130  *
131  */
132
133 static void req_done(struct virtqueue *vq)
134 {
135         struct virtio_chan *chan = vq->vdev->priv;
136         struct p9_fcall *rc;
137         unsigned int len;
138         struct p9_req_t *req;
139         unsigned long flags;
140
141         P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n");
142
143         do {
144                 spin_lock_irqsave(&chan->lock, flags);
145                 rc = virtqueue_get_buf(chan->vq, &len);
146
147                 if (rc != NULL) {
148                         if (!chan->ring_bufs_avail) {
149                                 chan->ring_bufs_avail = 1;
150                                 wake_up(chan->vc_wq);
151                         }
152                         spin_unlock_irqrestore(&chan->lock, flags);
153                         P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
154                         P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n",
155                                         rc->tag);
156                         req = p9_tag_lookup(chan->client, rc->tag);
157                         req->status = REQ_STATUS_RCVD;
158                         p9_client_cb(chan->client, req);
159                 } else {
160                         spin_unlock_irqrestore(&chan->lock, flags);
161                 }
162         } while (rc != NULL);
163 }
164
165 /**
166  * pack_sg_list - pack a scatter gather list from a linear buffer
167  * @sg: scatter/gather list to pack into
168  * @start: which segment of the sg_list to start at
169  * @limit: maximum segment to pack data to
170  * @data: data to pack into scatter/gather list
171  * @count: amount of data to pack into the scatter/gather list
172  *
173  * sg_lists have multiple segments of various sizes.  This will pack
174  * arbitrary data into an existing scatter gather list, segmenting the
175  * data as necessary within constraints.
176  *
177  */
178
179 static int
180 pack_sg_list(struct scatterlist *sg, int start, int limit, char *data,
181                                                                 int count)
182 {
183         int s;
184         int index = start;
185
186         while (count) {
187                 s = rest_of_page(data);
188                 if (s > count)
189                         s = count;
190                 sg_set_buf(&sg[index++], data, s);
191                 count -= s;
192                 data += s;
193                 BUG_ON(index > limit);
194         }
195
196         return index-start;
197 }
198
199 /* We don't currently allow canceling of virtio requests */
200 static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
201 {
202         return 1;
203 }
204
205 /**
206  * p9_virtio_request - issue a request
207  * @client: client instance issuing the request
208  * @req: request to be issued
209  *
210  */
211
212 static int
213 p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
214 {
215         int in, out;
216         struct virtio_chan *chan = client->trans;
217         char *rdata = (char *)req->rc+sizeof(struct p9_fcall);
218         unsigned long flags;
219         int err;
220
221         P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n");
222
223 req_retry:
224         req->status = REQ_STATUS_SENT;
225
226         spin_lock_irqsave(&chan->lock, flags);
227         out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata,
228                                                                 req->tc->size);
229         in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata,
230                                                                 client->msize);
231
232         err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
233         if (err < 0) {
234                 if (err == -ENOSPC) {
235                         chan->ring_bufs_avail = 0;
236                         spin_unlock_irqrestore(&chan->lock, flags);
237                         err = wait_event_interruptible(*chan->vc_wq,
238                                                         chan->ring_bufs_avail);
239                         if (err  == -ERESTARTSYS)
240                                 return err;
241
242                         P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n");
243                         goto req_retry;
244                 } else {
245                         spin_unlock_irqrestore(&chan->lock, flags);
246                         P9_DPRINTK(P9_DEBUG_TRANS,
247                                         "9p debug: "
248                                         "virtio rpc add_buf returned failure");
249                         return -EIO;
250                 }
251         }
252
253         virtqueue_kick(chan->vq);
254         spin_unlock_irqrestore(&chan->lock, flags);
255
256         P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n");
257         return 0;
258 }
259
260 static ssize_t p9_mount_tag_show(struct device *dev,
261                                 struct device_attribute *attr, char *buf)
262 {
263         struct virtio_chan *chan;
264         struct virtio_device *vdev;
265
266         vdev = dev_to_virtio(dev);
267         chan = vdev->priv;
268
269         return snprintf(buf, chan->tag_len + 1, "%s", chan->tag);
270 }
271
272 static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL);
273
274 /**
275  * p9_virtio_probe - probe for existence of 9P virtio channels
276  * @vdev: virtio device to probe
277  *
278  * This probes for existing virtio channels.
279  *
280  */
281
282 static int p9_virtio_probe(struct virtio_device *vdev)
283 {
284         __u16 tag_len;
285         char *tag;
286         int err;
287         struct virtio_chan *chan;
288
289         chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL);
290         if (!chan) {
291                 printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n");
292                 err = -ENOMEM;
293                 goto fail;
294         }
295
296         chan->vdev = vdev;
297
298         /* We expect one virtqueue, for requests. */
299         chan->vq = virtio_find_single_vq(vdev, req_done, "requests");
300         if (IS_ERR(chan->vq)) {
301                 err = PTR_ERR(chan->vq);
302                 goto out_free_vq;
303         }
304         chan->vq->vdev->priv = chan;
305         spin_lock_init(&chan->lock);
306
307         sg_init_table(chan->sg, VIRTQUEUE_NUM);
308
309         chan->inuse = false;
310         if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) {
311                 vdev->config->get(vdev,
312                                 offsetof(struct virtio_9p_config, tag_len),
313                                 &tag_len, sizeof(tag_len));
314         } else {
315                 err = -EINVAL;
316                 goto out_free_vq;
317         }
318         tag = kmalloc(tag_len, GFP_KERNEL);
319         if (!tag) {
320                 err = -ENOMEM;
321                 goto out_free_vq;
322         }
323         vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag),
324                         tag, tag_len);
325         chan->tag = tag;
326         chan->tag_len = tag_len;
327         err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
328         if (err) {
329                 goto out_free_tag;
330         }
331         chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
332         if (!chan->vc_wq) {
333                 err = -ENOMEM;
334                 goto out_free_tag;
335         }
336         init_waitqueue_head(chan->vc_wq);
337         chan->ring_bufs_avail = 1;
338
339         mutex_lock(&virtio_9p_lock);
340         list_add_tail(&chan->chan_list, &virtio_chan_list);
341         mutex_unlock(&virtio_9p_lock);
342         return 0;
343
344 out_free_tag:
345         kfree(tag);
346 out_free_vq:
347         vdev->config->del_vqs(vdev);
348         kfree(chan);
349 fail:
350         return err;
351 }
352
353
354 /**
355  * p9_virtio_create - allocate a new virtio channel
356  * @client: client instance invoking this transport
357  * @devname: string identifying the channel to connect to (unused)
358  * @args: args passed from sys_mount() for per-transport options (unused)
359  *
360  * This sets up a transport channel for 9p communication.  Right now
361  * we only match the first available channel, but eventually we couldlook up
362  * alternate channels by matching devname versus a virtio_config entry.
363  * We use a simple reference count mechanism to ensure that only a single
364  * mount has a channel open at a time.
365  *
366  */
367
368 static int
369 p9_virtio_create(struct p9_client *client, const char *devname, char *args)
370 {
371         struct virtio_chan *chan;
372         int ret = -ENOENT;
373         int found = 0;
374
375         mutex_lock(&virtio_9p_lock);
376         list_for_each_entry(chan, &virtio_chan_list, chan_list) {
377                 if (!strncmp(devname, chan->tag, chan->tag_len) &&
378                     strlen(devname) == chan->tag_len) {
379                         if (!chan->inuse) {
380                                 chan->inuse = true;
381                                 found = 1;
382                                 break;
383                         }
384                         ret = -EBUSY;
385                 }
386         }
387         mutex_unlock(&virtio_9p_lock);
388
389         if (!found) {
390                 printk(KERN_ERR "9p: no channels available\n");
391                 return ret;
392         }
393
394         client->trans = (void *)chan;
395         client->status = Connected;
396         chan->client = client;
397
398         return 0;
399 }
400
401 /**
402  * p9_virtio_remove - clean up resources associated with a virtio device
403  * @vdev: virtio device to remove
404  *
405  */
406
407 static void p9_virtio_remove(struct virtio_device *vdev)
408 {
409         struct virtio_chan *chan = vdev->priv;
410
411         BUG_ON(chan->inuse);
412         vdev->config->del_vqs(vdev);
413
414         mutex_lock(&virtio_9p_lock);
415         list_del(&chan->chan_list);
416         mutex_unlock(&virtio_9p_lock);
417         sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
418         kfree(chan->tag);
419         kfree(chan->vc_wq);
420         kfree(chan);
421
422 }
423
424 static struct virtio_device_id id_table[] = {
425         { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID },
426         { 0 },
427 };
428
429 static unsigned int features[] = {
430         VIRTIO_9P_MOUNT_TAG,
431 };
432
433 /* The standard "struct lguest_driver": */
434 static struct virtio_driver p9_virtio_drv = {
435         .feature_table  = features,
436         .feature_table_size = ARRAY_SIZE(features),
437         .driver.name    = KBUILD_MODNAME,
438         .driver.owner   = THIS_MODULE,
439         .id_table       = id_table,
440         .probe          = p9_virtio_probe,
441         .remove         = p9_virtio_remove,
442 };
443
444 static struct p9_trans_module p9_virtio_trans = {
445         .name = "virtio",
446         .create = p9_virtio_create,
447         .close = p9_virtio_close,
448         .request = p9_virtio_request,
449         .cancel = p9_virtio_cancel,
450         .maxsize = PAGE_SIZE*16,
451         .def = 0,
452         .owner = THIS_MODULE,
453 };
454
455 /* The standard init function */
456 static int __init p9_virtio_init(void)
457 {
458         INIT_LIST_HEAD(&virtio_chan_list);
459
460         v9fs_register_trans(&p9_virtio_trans);
461         return register_virtio_driver(&p9_virtio_drv);
462 }
463
464 static void __exit p9_virtio_cleanup(void)
465 {
466         unregister_virtio_driver(&p9_virtio_drv);
467         v9fs_unregister_trans(&p9_virtio_trans);
468 }
469
470 module_init(p9_virtio_init);
471 module_exit(p9_virtio_cleanup);
472
473 MODULE_DEVICE_TABLE(virtio, id_table);
474 MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
475 MODULE_DESCRIPTION("Virtio 9p Transport");
476 MODULE_LICENSE("GPL");