trans_virtio.c revision 68da9ba4eeadae86ad42e52b80822fbd56971267
1b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/*
2fea511a644fb0fb938309c6ab286725ac31b87e2Eric Van Hensbergen * The Virtio 9p transport driver
3b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
4e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen * This is a block based transport driver based on the lguest block driver
5e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen * code.
6b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
7fea511a644fb0fb938309c6ab286725ac31b87e2Eric Van Hensbergen *  Copyright (C) 2007, 2008 Eric Van Hensbergen, IBM Corporation
8b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
9b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Based on virtio console driver
10b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation
11b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
12b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  This program is free software; you can redistribute it and/or modify
13b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  it under the terms of the GNU General Public License version 2
14b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  as published by the Free Software Foundation.
15b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
16b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  This program is distributed in the hope that it will be useful,
17b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  GNU General Public License for more details.
20b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
21b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  You should have received a copy of the GNU General Public License
22b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  along with this program; if not, write to:
23b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Free Software Foundation
24b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  51 Franklin Street, Fifth Floor
25b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Boston, MA  02111-1301  USA
26b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
27b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen */
28b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
29b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/in.h>
30b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/module.h>
31b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/net.h>
32b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/ipv6.h>
33b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/errno.h>
34b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/kernel.h>
35b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/un.h>
36b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/uaccess.h>
37b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/inet.h>
38b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/idr.h>
39b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/file.h>
405a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
41b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <net/9p/9p.h>
42b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/parser.h>
438b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen#include <net/9p/client.h>
44b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <net/9p/transport.h>
45b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/scatterlist.h>
4668da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)#include <linux/swap.h>
47b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/virtio.h>
48b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/virtio_9p.h>
494038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)#include "trans_common.h"
50b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
51e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen#define VIRTQUEUE_NUM	128
52e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
53b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* a single mutex to manage channel initialization and attachment */
54c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipekstatic DEFINE_MUTEX(virtio_9p_lock);
5568da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)static DECLARE_WAIT_QUEUE_HEAD(vp_wq);
5668da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)static atomic_t vp_pinned = ATOMIC_INIT(0);
57b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
58ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
59ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * struct virtio_chan - per-instance transport information
60ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @initialized: whether the channel is initialized
61ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @inuse: whether the channel is in use
62ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @lock: protects multiple elements within this structure
630e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @client: client instance
64ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio dev associated with this channel
65ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vq: virtio queue associated with this channel
66ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @sg: scatter gather list which is used to pack a request (protected?)
67ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
68ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * We keep all per-channel information in a structure.
69b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * This structure is allocated within the devices dev->mem space.
70b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * A pointer to the structure will get put in the transport private.
71ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
72b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen */
73ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
7437c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.Vstruct virtio_chan {
75ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen	bool inuse;
76b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
77e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spinlock_t lock;
78e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
79fea511a644fb0fb938309c6ab286725ac31b87e2Eric Van Hensbergen	struct p9_client *client;
80b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	struct virtio_device *vdev;
81e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct virtqueue *vq;
8252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	int ring_bufs_avail;
8352f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	wait_queue_head_t *vc_wq;
8468da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)	/* This is global limit. Since we don't have a global structure,
8568da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)	 * will be placing it in each channel.
8668da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)	 */
8768da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)	int p9_max_pages;
88e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	/* Scatterlist: can be too big for stack. */
89e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct scatterlist sg[VIRTQUEUE_NUM];
9037c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V
9197ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	int tag_len;
9297ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	/*
9397ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	 * tag name to identify a mount Non-null terminated
9497ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	 */
9597ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	char *tag;
9697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V
9737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	struct list_head chan_list;
9837c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V};
9937c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V
10037c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.Vstatic struct list_head virtio_chan_list;
101b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
102b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* How many bytes left in this page. */
103b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic unsigned int rest_of_page(void *data)
104b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
105b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);
106b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
107b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
108ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
109ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_close - reclaim resources of a channel
1100e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @client: client instance
111ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
112ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This reclaims a channel by freeing its resources and
113ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * reseting its inuse flag.
114ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
115ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
116ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
1178b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergenstatic void p9_virtio_close(struct p9_client *client)
118e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen{
1198b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen	struct virtio_chan *chan = client->trans;
120b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
121c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipek	mutex_lock(&virtio_9p_lock);
122fb786100f7c75e154e63d0f5a2982e6d46dfb602Aneesh Kumar K.V	if (chan)
123fb786100f7c75e154e63d0f5a2982e6d46dfb602Aneesh Kumar K.V		chan->inuse = false;
124c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipek	mutex_unlock(&virtio_9p_lock);
125b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
126b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
127ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
128ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * req_done - callback which signals activity from the server
129ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vq: virtio queue activity was received on
130ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
131ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This notifies us that the server has triggered some activity
132ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * on the virtio channel - most likely a response to request we
133ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * sent.  Figure out which requests now have responses and wake up
134ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * those threads.
135ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
136ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * Bugs: could do with some additional sanity checking, but appears to work.
137ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
138ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
139ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
140e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic void req_done(struct virtqueue *vq)
141b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
142e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct virtio_chan *chan = vq->vdev->priv;
143e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct p9_fcall *rc;
144e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	unsigned int len;
145e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct p9_req_t *req;
146419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)	unsigned long flags;
147e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
14891b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n");
14991b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen
150a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)	while (1) {
151419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)		spin_lock_irqsave(&chan->lock, flags);
152419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)		rc = virtqueue_get_buf(chan->vq, &len);
153419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)
154a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		if (rc == NULL) {
15552f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			spin_unlock_irqrestore(&chan->lock, flags);
156a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)			break;
157a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		}
158a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)
159a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		chan->ring_bufs_avail = 1;
160a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		spin_unlock_irqrestore(&chan->lock, flags);
161a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		/* Wakeup if anyone waiting for VirtIO ring space. */
162a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		wake_up(chan->vc_wq);
163a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
164a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag);
165a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		req = p9_tag_lookup(chan->client, rc->tag);
166a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		if (req->tc->private) {
167a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)			struct trans_rpage_info *rp = req->tc->private;
16868da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)			int p = rp->rp_nr_pages;
169a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)			/*Release pages */
170a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)			p9_release_req_pages(rp);
17168da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)			atomic_sub(p, &vp_pinned);
17268da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)			wake_up(&vp_wq);
173a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)			if (rp->rp_alloc)
174a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)				kfree(rp);
175a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)			req->tc->private = NULL;
176419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)		}
177a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		req->status = REQ_STATUS_RCVD;
178a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)		p9_client_cb(chan->client, req);
179a01a984035ea799b14aa5e874dcaeb122f09c4b4Venkateswararao Jujjuri (JV)	}
180e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen}
181b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
182ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
183ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * pack_sg_list - pack a scatter gather list from a linear buffer
184ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @sg: scatter/gather list to pack into
185ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @start: which segment of the sg_list to start at
186ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @limit: maximum segment to pack data to
187ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @data: data to pack into scatter/gather list
188ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @count: amount of data to pack into the scatter/gather list
189ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
190ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * sg_lists have multiple segments of various sizes.  This will pack
191ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * arbitrary data into an existing scatter gather list, segmenting the
192ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * data as necessary within constraints.
193ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
194ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
195ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
196e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int
197e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenpack_sg_list(struct scatterlist *sg, int start, int limit, char *data,
198e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen								int count)
199e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen{
200e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int s;
201e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int index = start;
202e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
203e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	while (count) {
204e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		s = rest_of_page(data);
205e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		if (s > count)
206e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			s = count;
207e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		sg_set_buf(&sg[index++], data, s);
208e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		count -= s;
209e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		data += s;
210d6584f3a08055688b2344eb26379fb2f3147ce91Julia Lawall		BUG_ON(index > limit);
211e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
212b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
213e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	return index-start;
214b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
215b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
21691b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen/* We don't currently allow canceling of virtio requests */
21791b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergenstatic int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
21891b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen{
21991b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	return 1;
22091b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen}
22191b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen
222ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
2234038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer,
2244038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * this takes a list of pages.
2254038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @sg: scatter/gather list to pack into
2264038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @start: which segment of the sg_list to start at
2274038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @pdata_off: Offset into the first page
2284038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @**pdata: a list of pages to add into sg.
2294038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) * @count: amount of data to pack into the scatter/gather list
2304038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV) */
2314038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)static int
2324038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)pack_sg_list_p(struct scatterlist *sg, int start, int limit, size_t pdata_off,
2334038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		struct page **pdata, int count)
2344038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV){
2354038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	int s;
2364038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	int i = 0;
2374038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	int index = start;
2384038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
2394038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	if (pdata_off) {
2404038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		s = min((int)(PAGE_SIZE - pdata_off), count);
2414038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		sg_set_page(&sg[index++], pdata[i++], s, pdata_off);
2424038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		count -= s;
2434038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	}
2444038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
2454038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	while (count) {
2464038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		BUG_ON(index > limit);
2474038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		s = min((int)PAGE_SIZE, count);
2484038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		sg_set_page(&sg[index++], pdata[i++], s, 0);
2494038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		count -= s;
2504038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	}
2514038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	return index-start;
2524038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)}
2534038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
2544038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)/**
25591b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen * p9_virtio_request - issue a request
2560e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @client: client instance issuing the request
2570e15597ebfe00e28857185f46aba00f400480ffeAbhishek Kulkarni * @req: request to be issued
258ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
259ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
260ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
261e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int
26291b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergenp9_virtio_request(struct p9_client *client, struct p9_req_t *req)
263b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
2644038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	int in, out, inp, outp;
26591b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	struct virtio_chan *chan = client->trans;
26691b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	char *rdata = (char *)req->rc+sizeof(struct p9_fcall);
267419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)	unsigned long flags;
2684038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	size_t pdata_off = 0;
2694038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	struct trans_rpage_info *rpinfo = NULL;
2704038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	int err, pdata_len = 0;
271b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
27291b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n");
273b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
274419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)	req->status = REQ_STATUS_SENT;
275419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)
2764038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	if (req->tc->pbuf_size && (req->tc->pubuf && P9_IS_USER_CONTEXT)) {
2774038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		int nr_pages = p9_nr_pages(req);
2784038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		int rpinfo_size = sizeof(struct trans_rpage_info) +
2794038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			sizeof(struct page *) * nr_pages;
2804038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
28168da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)		if (atomic_read(&vp_pinned) >= chan->p9_max_pages) {
28268da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)			err = wait_event_interruptible(vp_wq,
28368da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)				atomic_read(&vp_pinned) < chan->p9_max_pages);
28468da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)			if (err  == -ERESTARTSYS)
28568da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)				return err;
28668da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)			P9_DPRINTK(P9_DEBUG_TRANS, "9p: May gup pages now.\n");
28768da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)		}
28868da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)
2894038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		if (rpinfo_size <= (req->tc->capacity - req->tc->size)) {
2904038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			/* We can use sdata */
2914038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			req->tc->private = req->tc->sdata + req->tc->size;
2924038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			rpinfo = (struct trans_rpage_info *)req->tc->private;
2934038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			rpinfo->rp_alloc = 0;
2944038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		} else {
2954038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			req->tc->private = kmalloc(rpinfo_size, GFP_NOFS);
2964038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			if (!req->tc->private) {
2974038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)				P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: "
2984038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)					"private kmalloc returned NULL");
2994038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)				return -ENOMEM;
3004038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			}
3014038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			rpinfo = (struct trans_rpage_info *)req->tc->private;
3024038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			rpinfo->rp_alloc = 1;
3034038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		}
3044038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
3054038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		err = p9_payload_gup(req, &pdata_off, &pdata_len, nr_pages,
3064038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)				req->tc->id == P9_TREAD ? 1 : 0);
3074038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		if (err < 0) {
3084038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			if (rpinfo->rp_alloc)
3094038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)				kfree(rpinfo);
3104038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			return err;
31168da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)		} else {
31268da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)			atomic_add(rpinfo->rp_nr_pages, &vp_pinned);
3134038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		}
3144038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	}
3154038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
316316ad5501c2098cb2a2a25ed77a0421f1671411cVenkateswararao Jujjuri (JV)req_retry_pinned:
317419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)	spin_lock_irqsave(&chan->lock, flags);
3184038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
3194038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	/* Handle out VirtIO ring buffers */
32091b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata,
3214038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			req->tc->size);
3224038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
3234038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	if (req->tc->pbuf_size && (req->tc->id == P9_TWRITE)) {
3244038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		/* We have additional write payload buffer to take care */
3254038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		if (req->tc->pubuf && P9_IS_USER_CONTEXT) {
3264038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			outp = pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM,
3274038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)					pdata_off, rpinfo->rp_data, pdata_len);
3284038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		} else {
3294038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			char *pbuf = req->tc->pubuf ? req->tc->pubuf :
3304038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)								req->tc->pkbuf;
3314038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			outp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, pbuf,
3324038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)					req->tc->pbuf_size);
3334038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		}
3344038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		out += outp;
3354038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	}
3364038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)
3374038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	/* Handle in VirtIO ring buffers */
3384038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	if (req->tc->pbuf_size &&
3394038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		((req->tc->id == P9_TREAD) || (req->tc->id == P9_TREADDIR))) {
3404038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		/*
3414038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		 * Take care of additional Read payload.
3424038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		 * 11 is the read/write header = PDU Header(7) + IO Size (4).
3434038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		 * Arrange in such a way that server places header in the
3444038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		 * alloced memory and payload onto the user buffer.
3454038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		 */
3464038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		inp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata, 11);
3474038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		/*
3484038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		 * Running executables in the filesystem may result in
3494038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		 * a read request with kernel buffer as opposed to user buffer.
3504038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		 */
3514038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		if (req->tc->pubuf && P9_IS_USER_CONTEXT) {
3524038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			in = pack_sg_list_p(chan->sg, out+inp, VIRTQUEUE_NUM,
3534038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)					pdata_off, rpinfo->rp_data, pdata_len);
3544038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		} else {
3554038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			char *pbuf = req->tc->pubuf ? req->tc->pubuf :
3564038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)								req->tc->pkbuf;
3574038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			in = pack_sg_list(chan->sg, out+inp, VIRTQUEUE_NUM,
3584038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)					pbuf, req->tc->pbuf_size);
3594038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		}
3604038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		in += inp;
3614038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	} else {
3624038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)		in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata,
3634038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)				client->msize);
3644038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)	}
365b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
366419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)	err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
367419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)	if (err < 0) {
36852f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)		if (err == -ENOSPC) {
36952f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			chan->ring_bufs_avail = 0;
37052f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			spin_unlock_irqrestore(&chan->lock, flags);
37152f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			err = wait_event_interruptible(*chan->vc_wq,
37252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)							chan->ring_bufs_avail);
37352f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			if (err  == -ERESTARTSYS)
37452f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)				return err;
37552f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)
37652f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n");
377316ad5501c2098cb2a2a25ed77a0421f1671411cVenkateswararao Jujjuri (JV)			goto req_retry_pinned;
37852f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)		} else {
37952f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			spin_unlock_irqrestore(&chan->lock, flags);
38052f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			P9_DPRINTK(P9_DEBUG_TRANS,
38152f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)					"9p debug: "
38252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)					"virtio rpc add_buf returned failure");
3834038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)			if (rpinfo && rpinfo->rp_alloc)
3844038866dab4e461e0ef144458bad9d70ce0c98c1Venkateswararao Jujjuri (JV)				kfree(rpinfo);
38552f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)			return -EIO;
38652f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)		}
387e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
388b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
389dc3f5e68f846eec38fb31d78f0b6e83633ad375eMichael S. Tsirkin	virtqueue_kick(chan->vq);
390419b39561e698d73a42f8010655d22e0134486daVenkateswararao Jujjuri (JV)	spin_unlock_irqrestore(&chan->lock, flags);
391b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
39291b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n");
393e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	return 0;
394b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
395b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
39686c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.Vstatic ssize_t p9_mount_tag_show(struct device *dev,
39786c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V				struct device_attribute *attr, char *buf)
39886c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V{
39986c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	struct virtio_chan *chan;
40086c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	struct virtio_device *vdev;
40186c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V
40286c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	vdev = dev_to_virtio(dev);
40386c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	chan = vdev->priv;
40486c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V
40586c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	return snprintf(buf, chan->tag_len + 1, "%s", chan->tag);
40686c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V}
40786c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V
40886c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.Vstatic DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL);
40986c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V
410ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
411ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_probe - probe for existence of 9P virtio channels
412ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio device to probe
413ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
41437c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V * This probes for existing virtio channels.
415ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
416ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
417ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
418e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int p9_virtio_probe(struct virtio_device *vdev)
419b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
42097ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	__u16 tag_len;
42197ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	char *tag;
422b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	int err;
423b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	struct virtio_chan *chan;
424b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
42537c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL);
42637c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	if (!chan) {
42737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V		printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n");
428b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		err = -ENOMEM;
429b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		goto fail;
430b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
431b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
432e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->vdev = vdev;
433b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
434e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	/* We expect one virtqueue, for requests. */
435d2a7ddda9ffb1c8961abff6714b0f1eb925c120fMichael S. Tsirkin	chan->vq = virtio_find_single_vq(vdev, req_done, "requests");
436e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if (IS_ERR(chan->vq)) {
437e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		err = PTR_ERR(chan->vq);
438e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		goto out_free_vq;
439b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
440e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->vq->vdev->priv = chan;
441e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spin_lock_init(&chan->lock);
442b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
443e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	sg_init_table(chan->sg, VIRTQUEUE_NUM);
444b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
445b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	chan->inuse = false;
44697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) {
44797ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V		vdev->config->get(vdev,
44897ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V				offsetof(struct virtio_9p_config, tag_len),
44997ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V				&tag_len, sizeof(tag_len));
45097ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	} else {
45197ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V		err = -EINVAL;
45297ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V		goto out_free_vq;
45397ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	}
45497ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	tag = kmalloc(tag_len, GFP_KERNEL);
45597ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	if (!tag) {
45697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V		err = -ENOMEM;
45797ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V		goto out_free_vq;
45897ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	}
45997ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag),
46097ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V			tag, tag_len);
46197ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	chan->tag = tag;
46297ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	chan->tag_len = tag_len;
46386c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
46486c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	if (err) {
46552f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)		goto out_free_tag;
46686c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	}
46752f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
46852f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	if (!chan->vc_wq) {
46952f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)		err = -ENOMEM;
47052f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)		goto out_free_tag;
47152f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	}
47252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	init_waitqueue_head(chan->vc_wq);
47352f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	chan->ring_bufs_avail = 1;
47468da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)	/* Ceiling limit to avoid denial of service attacks */
47568da9ba4eeadae86ad42e52b80822fbd56971267Venkateswararao Jujjuri (JV)	chan->p9_max_pages = nr_free_buffer_pages()/4;
47652f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)
47737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	mutex_lock(&virtio_9p_lock);
47837c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	list_add_tail(&chan->chan_list, &virtio_chan_list);
47937c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	mutex_unlock(&virtio_9p_lock);
480b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return 0;
481b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
48252f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)out_free_tag:
48352f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	kfree(tag);
484e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenout_free_vq:
485d2a7ddda9ffb1c8961abff6714b0f1eb925c120fMichael S. Tsirkin	vdev->config->del_vqs(vdev);
48637c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	kfree(chan);
487b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenfail:
488b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return err;
489b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
490b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
491ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
492ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
493ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_create - allocate a new virtio channel
4948b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen * @client: client instance invoking this transport
495ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @devname: string identifying the channel to connect to (unused)
496ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @args: args passed from sys_mount() for per-transport options (unused)
497ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
498ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This sets up a transport channel for 9p communication.  Right now
499b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * we only match the first available channel, but eventually we couldlook up
500b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * alternate channels by matching devname versus a virtio_config entry.
501b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * We use a simple reference count mechanism to ensure that only a single
502ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * mount has a channel open at a time.
503ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
504ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
505ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
5068b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergenstatic int
5078b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergenp9_virtio_create(struct p9_client *client, const char *devname, char *args)
508b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
50937c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	struct virtio_chan *chan;
510c1a7c2262035e83a8f70ebe1328b3451702cf51bAneesh Kumar K.V	int ret = -ENOENT;
51137c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	int found = 0;
512b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
513c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipek	mutex_lock(&virtio_9p_lock);
51437c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	list_for_each_entry(chan, &virtio_chan_list, chan_list) {
5150b20406cda621c2495d10baab1e87127ceb43337Sven Eckelmann		if (!strncmp(devname, chan->tag, chan->tag_len) &&
5160b20406cda621c2495d10baab1e87127ceb43337Sven Eckelmann		    strlen(devname) == chan->tag_len) {
517f75580c4afb72c156746b3fc1ec977b1a85d3deeAneesh Kumar K.V			if (!chan->inuse) {
518f75580c4afb72c156746b3fc1ec977b1a85d3deeAneesh Kumar K.V				chan->inuse = true;
51937c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V				found = 1;
520f75580c4afb72c156746b3fc1ec977b1a85d3deeAneesh Kumar K.V				break;
521f75580c4afb72c156746b3fc1ec977b1a85d3deeAneesh Kumar K.V			}
522c1a7c2262035e83a8f70ebe1328b3451702cf51bAneesh Kumar K.V			ret = -EBUSY;
523b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		}
524b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
525c1549497e903a1ffa1c5808337a987180e480e7aJosef 'Jeff' Sipek	mutex_unlock(&virtio_9p_lock);
526b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
52737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	if (!found) {
528e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		printk(KERN_ERR "9p: no channels available\n");
529c1a7c2262035e83a8f70ebe1328b3451702cf51bAneesh Kumar K.V		return ret;
530e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
531e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
5328b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen	client->trans = (void *)chan;
533562ada612058133a5483c68a73605f3c5f42fffeEric Van Hensbergen	client->status = Connected;
534fea511a644fb0fb938309c6ab286725ac31b87e2Eric Van Hensbergen	chan->client = client;
535b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
5368b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen	return 0;
537b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
538b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
539ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
540ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_remove - clean up resources associated with a virtio device
541ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio device to remove
542ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
543ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
544ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
545f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenstatic void p9_virtio_remove(struct virtio_device *vdev)
546f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen{
547f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	struct virtio_chan *chan = vdev->priv;
548f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen
549f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	BUG_ON(chan->inuse);
55037c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	vdev->config->del_vqs(vdev);
55137c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V
55237c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	mutex_lock(&virtio_9p_lock);
55337c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	list_del(&chan->chan_list);
55437c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	mutex_unlock(&virtio_9p_lock);
55586c8437383acd85c05ec7c9a004f59fe7ac9821aAneesh Kumar K.V	sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
55697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	kfree(chan->tag);
55752f44e0d08ff1a065bf06615483c608163575cb1Venkateswararao Jujjuri (JV)	kfree(chan->vc_wq);
55837c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	kfree(chan);
559f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen
560f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen}
561f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen
562b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct virtio_device_id id_table[] = {
563b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	{ VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID },
564b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	{ 0 },
565b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen};
566b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
56797ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.Vstatic unsigned int features[] = {
56897ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	VIRTIO_9P_MOUNT_TAG,
56997ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V};
57097ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V
571b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* The standard "struct lguest_driver": */
572b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct virtio_driver p9_virtio_drv = {
57397ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	.feature_table  = features,
57497ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	.feature_table_size = ARRAY_SIZE(features),
57597ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	.driver.name    = KBUILD_MODNAME,
57697ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	.driver.owner	= THIS_MODULE,
57797ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	.id_table	= id_table,
57897ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	.probe		= p9_virtio_probe,
57997ee9b0257402f4731b55dfea42f24d26d793ddfAneesh Kumar K.V	.remove		= p9_virtio_remove,
580b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen};
581b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
582b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct p9_trans_module p9_virtio_trans = {
583b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.name = "virtio",
584b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.create = p9_virtio_create,
5858b81ef589ad1483dd977ef47fe00d4ce4d91a0abEric Van Hensbergen	.close = p9_virtio_close,
58691b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	.request = p9_virtio_request,
58791b8534fa8f5e01f249b1bf8df0a2540053549adEric Van Hensbergen	.cancel = p9_virtio_cancel,
588e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	.maxsize = PAGE_SIZE*16,
5896f69c395cefb26ebba2c9bb725296a3a4a9200ecVenkateswararao Jujjuri (JV)	.pref = P9_TRANS_PREF_PAYLOAD_SEP,
590b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.def = 0,
59172029fe85d8d060b3f966f2dbc36b3c75b5a6532Tejun Heo	.owner = THIS_MODULE,
592b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen};
593b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
594b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* The standard init function */
595b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic int __init p9_virtio_init(void)
596b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
59737c1209d413242d9560e343c040777049a8dd869Aneesh Kumar K.V	INIT_LIST_HEAD(&virtio_chan_list);
598b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
599b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	v9fs_register_trans(&p9_virtio_trans);
600b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return register_virtio_driver(&p9_virtio_drv);
601b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
602b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
603f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenstatic void __exit p9_virtio_cleanup(void)
604f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen{
605f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	unregister_virtio_driver(&p9_virtio_drv);
60672029fe85d8d060b3f966f2dbc36b3c75b5a6532Tejun Heo	v9fs_unregister_trans(&p9_virtio_trans);
607f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen}
608f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen
609b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenmodule_init(p9_virtio_init);
610f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenmodule_exit(p9_virtio_cleanup);
611b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
612b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_DEVICE_TABLE(virtio, id_table);
613b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
614b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_DESCRIPTION("Virtio 9p Transport");
615b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_LICENSE("GPL");
616