diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 23:49:57 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 07:49:58 -0500 |
commit | 18445c4d501b9ab4336f66ef46b092661ddaf336 (patch) | |
tree | 9d23185f207d912942890cf047d1d3200806b401 | |
parent | a586d4f6016f7139d8c26df0e6927131168d3b5b (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.c | 3 | ||||
-rw-r--r-- | drivers/lguest/lguest_device.c | 2 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 15 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 21 | ||||
-rw-r--r-- | include/linux/virtio.h | 11 | ||||
-rw-r--r-- | include/linux/virtio_config.h | 2 | ||||
-rw-r--r-- | include/linux/virtio_ring.h | 2 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 4 |
8 files changed, 35 insertions, 25 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 1c63d5b64c20..54a8017ad487 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 | ||
39 | static bool blk_done(struct virtqueue *vq) | 39 | static 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 | ||
71 | static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | 70 | static 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 07f57a53658b..ced5b44cebce 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. */ |
192 | static struct virtqueue *lg_find_vq(struct virtio_device *vdev, | 192 | static 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 4b8138312750..7b0059f0f5d4 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 | ||
55 | static bool skb_xmit_done(struct virtqueue *rvq) | 55 | static 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 | ||
64 | static void receive_skb(struct net_device *dev, struct sk_buff *skb, | 63 | static 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 | ||
164 | static bool skb_recv_done(struct virtqueue *rvq) | 163 | static 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 | ||
172 | static int virtnet_poll(struct napi_struct *napi, int budget) | 173 | static 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 1dc04b6684e6..342bb0363fbe 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 | ||
223 | static bool vring_restart(struct virtqueue *_vq) | 223 | static 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 | |||
233 | static 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 14e1379876d3..951d81747b42 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 | */ |
20 | struct virtqueue | 18 | struct 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 70bb26062d76..81f828ac8f47 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 1a4ed49f6478..8cde10e792c4 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)); |
118 | void vring_del_virtqueue(struct virtqueue *vq); | 118 | void vring_del_virtqueue(struct virtqueue *vq); |
119 | 119 | ||
120 | irqreturn_t vring_interrupt(int irq, void *_vq); | 120 | irqreturn_t vring_interrupt(int irq, void *_vq); |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 78d7946f81fe..42eea5fe2628 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 | ||
202 | static bool p9_virtio_intr(struct virtqueue *q) | 202 | static 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 | ||
212 | static int p9_virtio_probe(struct virtio_device *dev) | 210 | static int p9_virtio_probe(struct virtio_device *dev) |