trans_virtio.c revision ee443996a35c1e04f210cafd43d5a98d41e46085
1b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/*
2b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * The Guest 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 *
7b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen */
8b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/*
9b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Copyright (C) 2007 Eric Van Hensbergen, IBM Corporation
10b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
11b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Based on virtio console driver
12b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation
13b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
14b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  This program is free software; you can redistribute it and/or modify
15b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  it under the terms of the GNU General Public License version 2
16b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  as published by the Free Software Foundation.
17b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
18b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  This program is distributed in the hope that it will be useful,
19b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  GNU General Public License for more details.
22b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
23b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  You should have received a copy of the GNU General Public License
24b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  along with this program; if not, write to:
25b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Free Software Foundation
26b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  51 Franklin Street, Fifth Floor
27b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *  Boston, MA  02111-1301  USA
28b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen *
29b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen */
30b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
31b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/in.h>
32b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/module.h>
33b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/net.h>
34b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/ipv6.h>
35b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/errno.h>
36b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/kernel.h>
37b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/un.h>
38b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/uaccess.h>
39b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/inet.h>
40b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/idr.h>
41b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/file.h>
42b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <net/9p/9p.h>
43b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/parser.h>
44b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <net/9p/transport.h>
45b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/scatterlist.h>
46b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/virtio.h>
47b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#include <linux/virtio_9p.h>
48b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
49e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen#define VIRTQUEUE_NUM	128
50e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
51b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* a single mutex to manage channel initialization and attachment */
52b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic DECLARE_MUTEX(virtio_9p_lock);
53b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* global which tracks highest initialized channel */
54b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic int chan_index;
55b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
56e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen#define P9_INIT_MAXTAG	16
57e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
58ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
59ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
60ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * enum p9_req_status_t - virtio request status
61ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @REQ_STATUS_IDLE: request slot unused
62ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @REQ_STATUS_SENT: request sent to server
63ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @REQ_STATUS_RCVD: response received from server
64ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @REQ_STATUS_FLSH: request has been flushed
65ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
66ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * The @REQ_STATUS_IDLE state is used to mark a request slot as unused
67ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * but use is actually tracked by the idpool structure which handles tag
68ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * id allocation.
69ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
70ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
71ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
72ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergenenum p9_req_status_t {
73ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen	REQ_STATUS_IDLE,
74ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen	REQ_STATUS_SENT,
75ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen	REQ_STATUS_RCVD,
76ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen	REQ_STATUS_FLSH,
77ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen};
78ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
79ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
80ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * struct p9_req_t - virtio request slots
81ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @status: status of this request slot
82ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @wq: wait_queue for the client to block on for this request
83ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
84ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * The virtio transport uses an array to track outstanding requests
85ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * instead of a list.  While this may incurr overhead during initial
86ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * allocation or expansion, it makes request lookup much easier as the
87ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * tag id is a index into an array.  (We use tag+1 so that we can accomodate
88ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * the -1 tag for the T_VERSION request).
89ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This also has the nice effect of only having to allocate wait_queues
90ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * once, instead of constantly allocating and freeing them.  Its possible
91ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * other resources could benefit from this scheme as well.
92ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
93ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
94e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
95e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstruct p9_req_t {
96e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int status;
97e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	wait_queue_head_t *wq;
98e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen};
99e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
100ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
101ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * struct virtio_chan - per-instance transport information
102ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @initialized: whether the channel is initialized
103ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @inuse: whether the channel is in use
104ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @lock: protects multiple elements within this structure
105ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio dev associated with this channel
106ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vq: virtio queue associated with this channel
107ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @tagpool: accounting for tag ids (and request slots)
108ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @reqs: array of request slots
109ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @max_tag: current number of request_slots allocated
110ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @sg: scatter gather list which is used to pack a request (protected?)
111ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
112ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * We keep all per-channel information in a structure.
113b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * This structure is allocated within the devices dev->mem space.
114b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * A pointer to the structure will get put in the transport private.
115ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
116b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen */
117ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
118b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct virtio_chan {
119ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen	bool initialized;
120ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen	bool inuse;
121b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
122e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spinlock_t lock;
123e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
124b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	struct virtio_device *vdev;
125e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct virtqueue *vq;
126b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
127e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct p9_idpool *tagpool;
128e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct p9_req_t *reqs;
129e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int max_tag;
130b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
131e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	/* Scatterlist: can be too big for stack. */
132e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct scatterlist sg[VIRTQUEUE_NUM];
133b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen} channels[MAX_9P_CHAN];
134b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
135ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
136ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_lookup_tag - Lookup requests by tag
137ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @c: virtio channel to lookup tag within
138ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @tag: numeric id for transaction
139ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
140ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * this is a simple array lookup, but will grow the
141ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * request_slots as necessary to accomodate transaction
142ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * ids which did not previously have a slot.
143ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
144ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * Bugs: there is currently no upper limit on request slots set
145ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * here, but that should be constrained by the id accounting.
146ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
147ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
148e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic struct p9_req_t *p9_lookup_tag(struct virtio_chan *c, u16 tag)
149e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen{
150e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	/* This looks up the original request by tag so we know which
151e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	 * buffer to read the data into */
152e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	tag++;
153e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
154e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	while (tag >= c->max_tag) {
155e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		int old_max = c->max_tag;
156e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		int count;
157e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
158e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		if (c->max_tag)
159e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			c->max_tag *= 2;
160e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		else
161e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			c->max_tag = P9_INIT_MAXTAG;
162e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
163e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		c->reqs = krealloc(c->reqs, sizeof(struct p9_req_t)*c->max_tag,
164e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen								GFP_ATOMIC);
165e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		if (!c->reqs) {
166e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			printk(KERN_ERR "Couldn't grow tag array\n");
167e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			BUG();
168e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		}
169e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		for (count = old_max; count < c->max_tag; count++) {
170e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			c->reqs[count].status = REQ_STATUS_IDLE;
17115e29b8b0542f28fc0feed2d60e0377b39a45c4fAdrian Bunk			c->reqs[count].wq = kmalloc(sizeof(wait_queue_head_t),
172e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen								GFP_ATOMIC);
173e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			if (!c->reqs[count].wq) {
174e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen				printk(KERN_ERR "Couldn't grow tag array\n");
175e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen				BUG();
176e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			}
177e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			init_waitqueue_head(c->reqs[count].wq);
178e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		}
179e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
180e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
181e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	return &c->reqs[tag];
182e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen}
183e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
184e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
185b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* How many bytes left in this page. */
186b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic unsigned int rest_of_page(void *data)
187b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
188b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE);
189b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
190b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
191ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
192ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_close - reclaim resources of a channel
193ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @trans: transport state
194ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
195ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This reclaims a channel by freeing its resources and
196ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * reseting its inuse flag.
197ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
198ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
199ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
200e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic void p9_virtio_close(struct p9_trans *trans)
201e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen{
202e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct virtio_chan *chan = trans->priv;
203e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int count;
204e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	unsigned int flags;
205b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
206e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spin_lock_irqsave(&chan->lock, flags);
207e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	p9_idpool_destroy(chan->tagpool);
208e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	for (count = 0; count < chan->max_tag; count++)
209e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		kfree(chan->reqs[count].wq);
210e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	kfree(chan->reqs);
211e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->max_tag = 0;
212e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spin_unlock_irqrestore(&chan->lock, flags);
213b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
214e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	down(&virtio_9p_lock);
215e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->inuse = false;
216e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	up(&virtio_9p_lock);
217b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
218e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	kfree(trans);
219b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
220b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
221ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
222ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * req_done - callback which signals activity from the server
223ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vq: virtio queue activity was received on
224ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
225ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This notifies us that the server has triggered some activity
226ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * on the virtio channel - most likely a response to request we
227ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * sent.  Figure out which requests now have responses and wake up
228ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * those threads.
229ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
230ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * Bugs: could do with some additional sanity checking, but appears to work.
231ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
232ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
233ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
234e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic void req_done(struct virtqueue *vq)
235b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
236e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct virtio_chan *chan = vq->vdev->priv;
237e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct p9_fcall *rc;
238e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	unsigned int len;
239e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	unsigned long flags;
240e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct p9_req_t *req;
241e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
242e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spin_lock_irqsave(&chan->lock, flags);
243e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	while ((rc = chan->vq->vq_ops->get_buf(chan->vq, &len)) != NULL) {
244e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		req = p9_lookup_tag(chan, rc->tag);
245e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		req->status = REQ_STATUS_RCVD;
246e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		wake_up(req->wq);
247e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
248e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	/* In case queue is stopped waiting for more buffers. */
249e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spin_unlock_irqrestore(&chan->lock, flags);
250e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen}
251b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
252ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
253ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * pack_sg_list - pack a scatter gather list from a linear buffer
254ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @sg: scatter/gather list to pack into
255ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @start: which segment of the sg_list to start at
256ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @limit: maximum segment to pack data to
257ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @data: data to pack into scatter/gather list
258ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @count: amount of data to pack into the scatter/gather list
259ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
260ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * sg_lists have multiple segments of various sizes.  This will pack
261ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * arbitrary data into an existing scatter gather list, segmenting the
262ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * data as necessary within constraints.
263ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
264ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
265ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
266e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int
267e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenpack_sg_list(struct scatterlist *sg, int start, int limit, char *data,
268e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen								int count)
269e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen{
270e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int s;
271e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int index = start;
272e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
273e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	while (count) {
274e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		s = rest_of_page(data);
275e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		if (s > count)
276e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			s = count;
277e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		sg_set_buf(&sg[index++], data, s);
278e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		count -= s;
279e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		data += s;
280d6584f3a08055688b2344eb26379fb2f3147ce91Julia Lawall		BUG_ON(index > limit);
281e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
282b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
283e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	return index-start;
284b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
285b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
286ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
287ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_rpc - issue a request and wait for a response
288ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @t: transport state
289ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @tc: &p9_fcall request to transmit
290ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @rc: &p9_fcall to put reponse into
291ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
292ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
293ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
294e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int
2958a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergenp9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc)
296b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
297e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int in, out;
298e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int n, err, size;
299e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct virtio_chan *chan = t->priv;
300e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	char *rdata;
301e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	struct p9_req_t *req;
302e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	unsigned long flags;
303e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
304e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if (*rc == NULL) {
3058a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergen		*rc = kmalloc(sizeof(struct p9_fcall) + t->msize, GFP_KERNEL);
306e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		if (!*rc)
307e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			return -ENOMEM;
308e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
309b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
310e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	rdata = (char *)*rc+sizeof(struct p9_fcall);
311b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
312e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	n = P9_NOTAG;
313e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if (tc->id != P9_TVERSION) {
314e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		n = p9_idpool_get(chan->tagpool);
315e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		if (n < 0)
316e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			return -ENOMEM;
317b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
318b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
3197c7d90f2dda6daec5a6aaf8f97aacc10ee4deb77Eric Van Hensbergen	spin_lock_irqsave(&chan->lock, flags);
320e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	req = p9_lookup_tag(chan, n);
321e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spin_unlock_irqrestore(&chan->lock, flags);
322b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
323e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	p9_set_tag(tc, n);
324b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
325e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio rpc tag %d\n", n);
326b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
327e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, tc->sdata, tc->size);
3288a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergen	in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, t->msize);
329b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
330e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	req->status = REQ_STATUS_SENT;
331b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
332e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if (chan->vq->vq_ops->add_buf(chan->vq, chan->sg, out, in, tc)) {
333e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		P9_DPRINTK(P9_DEBUG_TRANS,
334e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			"9p debug: virtio rpc add_buf returned failure");
335e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		return -EIO;
336e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
337b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
338e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->vq->vq_ops->kick(chan->vq);
339b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
340e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	wait_event(*req->wq, req->status == REQ_STATUS_RCVD);
341b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
342e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	size = le32_to_cpu(*(__le32 *) rdata);
343b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
3448a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergen	err = p9_deserialize_fcall(rdata, size, *rc, t->extended);
345e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if (err < 0) {
346e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		P9_DPRINTK(P9_DEBUG_TRANS,
347e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen			"9p debug: virtio rpc deserialize returned %d\n", err);
348e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		return err;
349e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
350b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
351e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen#ifdef CONFIG_NET_9P_DEBUG
352e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
353e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		char buf[150];
354b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
3558a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergen		p9_printfcall(buf, sizeof(buf), *rc, t->extended);
356e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		printk(KERN_NOTICE ">>> %p %s\n", t, buf);
357e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
358e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen#endif
359b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
360e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if (n != P9_NOTAG && p9_idpool_check(n, chan->tagpool))
361e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		p9_idpool_put(n, chan->tagpool);
362b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
363e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	req->status = REQ_STATUS_IDLE;
364b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
365e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	return 0;
366b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
367b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
368ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
369ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_probe - probe for existence of 9P virtio channels
370ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio device to probe
371ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
372ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This probes for existing virtio channels.  At present only
373ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * a single channel is in use, so in the future more work may need
374ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * to be done here.
375ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
376ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
377ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
378e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenstatic int p9_virtio_probe(struct virtio_device *vdev)
379b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
380b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	int err;
381b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	struct virtio_chan *chan;
382b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	int index;
383b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
384b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	down(&virtio_9p_lock);
385b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	index = chan_index++;
386b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	chan = &channels[index];
387b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	up(&virtio_9p_lock);
388b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
389b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	if (chan_index > MAX_9P_CHAN) {
390b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n");
391b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		BUG();
392b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		err = -ENOMEM;
393b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		goto fail;
394b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
395b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
396e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->vdev = vdev;
397b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
398e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	/* We expect one virtqueue, for requests. */
399e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->vq = vdev->config->find_vq(vdev, 0, req_done);
400e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if (IS_ERR(chan->vq)) {
401e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		err = PTR_ERR(chan->vq);
402e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		goto out_free_vq;
403b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
404e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->vq->vdev->priv = chan;
405e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	spin_lock_init(&chan->lock);
406b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
407e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	sg_init_table(chan->sg, VIRTQUEUE_NUM);
408b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
409b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	chan->inuse = false;
410b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	chan->initialized = true;
411b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return 0;
412b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
413e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergenout_free_vq:
414e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	vdev->config->del_vq(chan->vq);
415b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenfail:
416b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	down(&virtio_9p_lock);
417b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	chan_index--;
418b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	up(&virtio_9p_lock);
419b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return err;
420b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
421b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
422ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
423ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
424ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_create - allocate a new virtio channel
425ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @devname: string identifying the channel to connect to (unused)
426ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @args: args passed from sys_mount() for per-transport options (unused)
427ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @msize: requested maximum packet size
428ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @extended: 9p2000.u enabled flag
429ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
430ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * This sets up a transport channel for 9p communication.  Right now
431b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * we only match the first available channel, but eventually we couldlook up
432b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * alternate channels by matching devname versus a virtio_config entry.
433b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen * We use a simple reference count mechanism to ensure that only a single
434ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * mount has a channel open at a time.
435ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
436ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * Bugs: doesn't allow identification of a specific channel
437ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * to allocate, channels are allocated sequentially. This was
438ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * a pragmatic decision to get things rolling, but ideally some
439ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * way of identifying the channel to attach to would be nice
440ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * if we are going to support multiple channels.
441ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
442ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
443ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
4448a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergenstatic struct p9_trans *
4458a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergenp9_virtio_create(const char *devname, char *args, int msize,
4468a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergen							unsigned char extended)
447b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
448b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	struct p9_trans *trans;
449b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	struct virtio_chan *chan = channels;
450e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	int index = 0;
451b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
452b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	down(&virtio_9p_lock);
453b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	while (index < MAX_9P_CHAN) {
454b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		if (chan->initialized && !chan->inuse) {
455b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen			chan->inuse = true;
456b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen			break;
457b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		} else {
458b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen			index++;
459b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen			chan = &channels[index];
460b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		}
461b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
462b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	up(&virtio_9p_lock);
463b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
464b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	if (index >= MAX_9P_CHAN) {
465e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		printk(KERN_ERR "9p: no channels available\n");
466e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		return ERR_PTR(-ENODEV);
467e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	}
468e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen
469e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->tagpool = p9_idpool_create();
470e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	if (IS_ERR(chan->tagpool)) {
471e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		printk(KERN_ERR "9p: couldn't allocate tagpool\n");
472e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen		return ERR_PTR(-ENOMEM);
473b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
474e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	p9_idpool_get(chan->tagpool); /* reserve tag 0 */
475e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->max_tag = 0;
476e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	chan->reqs = NULL;
477b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
478b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
479b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	if (!trans) {
480b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		printk(KERN_ERR "9p: couldn't allocate transport\n");
481b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		return ERR_PTR(-ENOMEM);
482b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	}
4838a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergen	trans->extended = extended;
4848a0dc95fd976a052e5e799ef33e6c8e3141b5dffEric Van Hensbergen	trans->msize = msize;
485b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	trans->close = p9_virtio_close;
486e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	trans->rpc = p9_virtio_rpc;
487b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	trans->priv = chan;
488b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
489b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return trans;
490b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
491b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
492ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen/**
493ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * p9_virtio_remove - clean up resources associated with a virtio device
494ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen * @vdev: virtio device to remove
495ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen *
496ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen */
497ee443996a35c1e04f210cafd43d5a98d41e46085Eric Van Hensbergen
498f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenstatic void p9_virtio_remove(struct virtio_device *vdev)
499f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen{
500f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	struct virtio_chan *chan = vdev->priv;
501f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen
502f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	BUG_ON(chan->inuse);
503f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen
504f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	if (chan->initialized) {
505f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen		vdev->config->del_vq(chan->vq);
506f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen		chan->initialized = false;
507f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	}
508f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen}
509f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen
510b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen#define VIRTIO_ID_9P 9
511b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
512b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct virtio_device_id id_table[] = {
513b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	{ VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID },
514b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	{ 0 },
515b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen};
516b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
517b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* The standard "struct lguest_driver": */
518b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct virtio_driver p9_virtio_drv = {
519b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.driver.name = 	KBUILD_MODNAME,
520b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.driver.owner = THIS_MODULE,
521b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.id_table =	id_table,
522b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.probe = 	p9_virtio_probe,
523f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	.remove =	p9_virtio_remove,
524b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen};
525b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
526b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic struct p9_trans_module p9_virtio_trans = {
527b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.name = "virtio",
528b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.create = p9_virtio_create,
529e2735b7720320b68590ca2b32b78ca91213931b2Eric Van Hensbergen	.maxsize = PAGE_SIZE*16,
530b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	.def = 0,
531b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen};
532b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
533b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen/* The standard init function */
534b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenstatic int __init p9_virtio_init(void)
535b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen{
536b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	int count;
537b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
538b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	for (count = 0; count < MAX_9P_CHAN; count++)
539b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen		channels[count].initialized = false;
540b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
541b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	v9fs_register_trans(&p9_virtio_trans);
542b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen	return register_virtio_driver(&p9_virtio_drv);
543b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen}
544b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
545f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenstatic void __exit p9_virtio_cleanup(void)
546f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen{
547f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen	unregister_virtio_driver(&p9_virtio_drv);
548f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen}
549f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergen
550b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergenmodule_init(p9_virtio_init);
551f39335453fe79f4e12e263e7c6387dc9fb86bfffEric Van Hensbergenmodule_exit(p9_virtio_cleanup);
552b530cc794024be227876a089e66fb17b7b512763Eric Van Hensbergen
553b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_DEVICE_TABLE(virtio, id_table);
554b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
555b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_DESCRIPTION("Virtio 9p Transport");
556b530cc794024be227876a089e66fb17b7b512763Eric Van HensbergenMODULE_LICENSE("GPL");
557