aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2008-02-04 23:49:57 -0500
committerRusty Russell <rusty@rustcorp.com.au>2008-02-04 07:49:58 -0500
commit18445c4d501b9ab4336f66ef46b092661ddaf336 (patch)
tree9d23185f207d912942890cf047d1d3200806b401
parenta586d4f6016f7139d8c26df0e6927131168d3b5b (diff)
virtio: explicit enable_cb/disable_cb rather than callback return.
It seems that virtio_net wants to disable callbacks (interrupts) before calling netif_rx_schedule(), so we can't use the return value to do so. Rename "restart" to "cb_enable" and introduce "cb_disable" hook: callback now returns void, rather than a boolean. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/block/virtio_blk.c3
-rw-r--r--drivers/lguest/lguest_device.c2
-rw-r--r--drivers/net/virtio_net.c15
-rw-r--r--drivers/virtio/virtio_ring.c21
-rw-r--r--include/linux/virtio.h11
-rw-r--r--include/linux/virtio_config.h2
-rw-r--r--include/linux/virtio_ring.h2
-rw-r--r--net/9p/trans_virtio.c4
8 files changed, 35 insertions, 25 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 1c63d5b64c2..54a8017ad48 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -36,7 +36,7 @@ struct virtblk_req
36 struct virtio_blk_inhdr in_hdr; 36 struct virtio_blk_inhdr in_hdr;
37}; 37};
38 38
39static bool blk_done(struct virtqueue *vq) 39static void blk_done(struct virtqueue *vq)
40{ 40{
41 struct virtio_blk *vblk = vq->vdev->priv; 41 struct virtio_blk *vblk = vq->vdev->priv;
42 struct virtblk_req *vbr; 42 struct virtblk_req *vbr;
@@ -65,7 +65,6 @@ static bool blk_done(struct virtqueue *vq)
65 /* In case queue is stopped waiting for more buffers. */ 65 /* In case queue is stopped waiting for more buffers. */
66 blk_start_queue(vblk->disk->queue); 66 blk_start_queue(vblk->disk->queue);
67 spin_unlock_irqrestore(&vblk->lock, flags); 67 spin_unlock_irqrestore(&vblk->lock, flags);
68 return true;
69} 68}
70 69
71static bool do_req(struct request_queue *q, struct virtio_blk *vblk, 70static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 07f57a53658..ced5b44cebc 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -191,7 +191,7 @@ static void lg_notify(struct virtqueue *vq)
191 * So we provide devices with a "find virtqueue and set it up" function. */ 191 * So we provide devices with a "find virtqueue and set it up" function. */
192static struct virtqueue *lg_find_vq(struct virtio_device *vdev, 192static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
193 unsigned index, 193 unsigned index,
194 bool (*callback)(struct virtqueue *vq)) 194 void (*callback)(struct virtqueue *vq))
195{ 195{
196 struct lguest_device *ldev = to_lgdev(vdev); 196 struct lguest_device *ldev = to_lgdev(vdev);
197 struct lguest_vq_info *lvq; 197 struct lguest_vq_info *lvq;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 4b813831275..7b0059f0f5d 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -52,13 +52,12 @@ static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
52 sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr)); 52 sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
53} 53}
54 54
55static bool skb_xmit_done(struct virtqueue *rvq) 55static void skb_xmit_done(struct virtqueue *rvq)
56{ 56{
57 struct virtnet_info *vi = rvq->vdev->priv; 57 struct virtnet_info *vi = rvq->vdev->priv;
58 58
59 /* In case we were waiting for output buffers. */ 59 /* In case we were waiting for output buffers. */
60 netif_wake_queue(vi->dev); 60 netif_wake_queue(vi->dev);
61 return true;
62} 61}
63 62
64static void receive_skb(struct net_device *dev, struct sk_buff *skb, 63static void receive_skb(struct net_device *dev, struct sk_buff *skb,
@@ -161,12 +160,14 @@ static void try_fill_recv(struct virtnet_info *vi)
161 vi->rvq->vq_ops->kick(vi->rvq); 160 vi->rvq->vq_ops->kick(vi->rvq);
162} 161}
163 162
164static bool skb_recv_done(struct virtqueue *rvq) 163static void skb_recv_done(struct virtqueue *rvq)
165{ 164{
166 struct virtnet_info *vi = rvq->vdev->priv; 165 struct virtnet_info *vi = rvq->vdev->priv;
167 netif_rx_schedule(vi->dev, &vi->napi); 166 /* Schedule NAPI, Suppress further interrupts if successful. */
168 /* Suppress further interrupts. */ 167 if (netif_rx_schedule_prep(vi->dev, &vi->napi)) {
169 return false; 168 rvq->vq_ops->disable_cb(rvq);
169 __netif_rx_schedule(vi->dev, &vi->napi);
170 }
170} 171}
171 172
172static int virtnet_poll(struct napi_struct *napi, int budget) 173static int virtnet_poll(struct napi_struct *napi, int budget)
@@ -192,7 +193,7 @@ again:
192 /* Out of packets? */ 193 /* Out of packets? */
193 if (received < budget) { 194 if (received < budget) {
194 netif_rx_complete(vi->dev, napi); 195 netif_rx_complete(vi->dev, napi);
195 if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq)) 196 if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq))
196 && netif_rx_reschedule(vi->dev, napi)) 197 && netif_rx_reschedule(vi->dev, napi))
197 goto again; 198 goto again;
198 } 199 }
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1dc04b6684e..342bb0363fb 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -220,7 +220,17 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
220 return ret; 220 return ret;
221} 221}
222 222
223static bool vring_restart(struct virtqueue *_vq) 223static void vring_disable_cb(struct virtqueue *_vq)
224{
225 struct vring_virtqueue *vq = to_vvq(_vq);
226
227 START_USE(vq);
228 BUG_ON(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT);
229 vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
230 END_USE(vq);
231}
232
233static bool vring_enable_cb(struct virtqueue *_vq)
224{ 234{
225 struct vring_virtqueue *vq = to_vvq(_vq); 235 struct vring_virtqueue *vq = to_vvq(_vq);
226 236
@@ -254,8 +264,8 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
254 return IRQ_HANDLED; 264 return IRQ_HANDLED;
255 265
256 pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback); 266 pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback);
257 if (vq->vq.callback && !vq->vq.callback(&vq->vq)) 267 if (vq->vq.callback)
258 vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; 268 vq->vq.callback(&vq->vq);
259 269
260 return IRQ_HANDLED; 270 return IRQ_HANDLED;
261} 271}
@@ -264,7 +274,8 @@ static struct virtqueue_ops vring_vq_ops = {
264 .add_buf = vring_add_buf, 274 .add_buf = vring_add_buf,
265 .get_buf = vring_get_buf, 275 .get_buf = vring_get_buf,
266 .kick = vring_kick, 276 .kick = vring_kick,
267 .restart = vring_restart, 277 .disable_cb = vring_disable_cb,
278 .enable_cb = vring_enable_cb,
268 .shutdown = vring_shutdown, 279 .shutdown = vring_shutdown,
269}; 280};
270 281
@@ -272,7 +283,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
272 struct virtio_device *vdev, 283 struct virtio_device *vdev,
273 void *pages, 284 void *pages,
274 void (*notify)(struct virtqueue *), 285 void (*notify)(struct virtqueue *),
275 bool (*callback)(struct virtqueue *)) 286 void (*callback)(struct virtqueue *))
276{ 287{
277 struct vring_virtqueue *vq; 288 struct vring_virtqueue *vq;
278 unsigned int i; 289 unsigned int i;
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 14e1379876d..951d81747b4 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -11,15 +11,13 @@
11/** 11/**
12 * virtqueue - a queue to register buffers for sending or receiving. 12 * virtqueue - a queue to register buffers for sending or receiving.
13 * @callback: the function to call when buffers are consumed (can be NULL). 13 * @callback: the function to call when buffers are consumed (can be NULL).
14 * If this returns false, callbacks are suppressed until vq_ops->restart
15 * is called.
16 * @vdev: the virtio device this queue was created for. 14 * @vdev: the virtio device this queue was created for.
17 * @vq_ops: the operations for this virtqueue (see below). 15 * @vq_ops: the operations for this virtqueue (see below).
18 * @priv: a pointer for the virtqueue implementation to use. 16 * @priv: a pointer for the virtqueue implementation to use.
19 */ 17 */
20struct virtqueue 18struct virtqueue
21{ 19{
22 bool (*callback)(struct virtqueue *vq); 20 void (*callback)(struct virtqueue *vq);
23 struct virtio_device *vdev; 21 struct virtio_device *vdev;
24 struct virtqueue_ops *vq_ops; 22 struct virtqueue_ops *vq_ops;
25 void *priv; 23 void *priv;
@@ -41,7 +39,9 @@ struct virtqueue
41 * vq: the struct virtqueue we're talking about. 39 * vq: the struct virtqueue we're talking about.
42 * len: the length written into the buffer 40 * len: the length written into the buffer
43 * Returns NULL or the "data" token handed to add_buf. 41 * Returns NULL or the "data" token handed to add_buf.
44 * @restart: restart callbacks after callback returned false. 42 * @disable_cb: disable callbacks
43 * vq: the struct virtqueue we're talking about.
44 * @enable_cb: restart callbacks after disable_cb.
45 * vq: the struct virtqueue we're talking about. 45 * vq: the struct virtqueue we're talking about.
46 * This returns "false" (and doesn't re-enable) if there are pending 46 * This returns "false" (and doesn't re-enable) if there are pending
47 * buffers in the queue, to avoid a race. 47 * buffers in the queue, to avoid a race.
@@ -65,7 +65,8 @@ struct virtqueue_ops {
65 65
66 void *(*get_buf)(struct virtqueue *vq, unsigned int *len); 66 void *(*get_buf)(struct virtqueue *vq, unsigned int *len);
67 67
68 bool (*restart)(struct virtqueue *vq); 68 void (*disable_cb)(struct virtqueue *vq);
69 bool (*enable_cb)(struct virtqueue *vq);
69 70
70 void (*shutdown)(struct virtqueue *vq); 71 void (*shutdown)(struct virtqueue *vq);
71}; 72};
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 70bb26062d7..81f828ac8f4 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -61,7 +61,7 @@ struct virtio_config_ops
61 void (*set_status)(struct virtio_device *vdev, u8 status); 61 void (*set_status)(struct virtio_device *vdev, u8 status);
62 struct virtqueue *(*find_vq)(struct virtio_device *vdev, 62 struct virtqueue *(*find_vq)(struct virtio_device *vdev,
63 unsigned index, 63 unsigned index,
64 bool (*callback)(struct virtqueue *)); 64 void (*callback)(struct virtqueue *));
65 void (*del_vq)(struct virtqueue *vq); 65 void (*del_vq)(struct virtqueue *vq);
66}; 66};
67 67
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index 1a4ed49f647..8cde10e792c 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -114,7 +114,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
114 struct virtio_device *vdev, 114 struct virtio_device *vdev,
115 void *pages, 115 void *pages,
116 void (*notify)(struct virtqueue *vq), 116 void (*notify)(struct virtqueue *vq),
117 bool (*callback)(struct virtqueue *vq)); 117 void (*callback)(struct virtqueue *vq));
118void vring_del_virtqueue(struct virtqueue *vq); 118void vring_del_virtqueue(struct virtqueue *vq);
119 119
120irqreturn_t vring_interrupt(int irq, void *_vq); 120irqreturn_t vring_interrupt(int irq, void *_vq);
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 78d7946f81f..42eea5fe262 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -199,14 +199,12 @@ static void p9_virtio_close(struct p9_trans *trans)
199 kfree(trans); 199 kfree(trans);
200} 200}
201 201
202static bool p9_virtio_intr(struct virtqueue *q) 202static void p9_virtio_intr(struct virtqueue *q)
203{ 203{
204 struct virtio_chan *chan = q->vdev->priv; 204 struct virtio_chan *chan = q->vdev->priv;
205 205
206 P9_DPRINTK(P9_DEBUG_TRANS, "9p poll_wakeup: %p\n", &chan->wq); 206 P9_DPRINTK(P9_DEBUG_TRANS, "9p poll_wakeup: %p\n", &chan->wq);
207 wake_up_interruptible(&chan->wq); 207 wake_up_interruptible(&chan->wq);
208
209 return true;
210} 208}
211 209
212static int p9_virtio_probe(struct virtio_device *dev) 210static int p9_virtio_probe(struct virtio_device *dev)