diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-17 12:52:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-17 12:52:19 -0400 |
commit | 84841384ec6ec57544b76e564514d3f9eb6c1901 (patch) | |
tree | 3af1373f62d3f15c2473bf1034757cd1d0122c0b | |
parent | 3d10a15d6919488204bdb264050d156ced20d9aa (diff) | |
parent | 4265f161b6bb7b31163671329b1142b9023bf4e3 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
virtio: fix race in enable_cb
virtio: Enable netpoll interface for netconsole logging
virtio: handle > 2 billion page balloon targets
virtio: Fix sysfs bits to have proper block symlink
virtio: Use spin_lock_irqsave/restore for virtio-pci
-rw-r--r-- | drivers/block/virtio_blk.c | 1 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 22 | ||||
-rw-r--r-- | drivers/virtio/virtio_balloon.c | 4 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 15 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 1 | ||||
-rw-r--r-- | include/linux/virtio.h | 5 |
6 files changed, 34 insertions, 14 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 3b1a68d6eddb..0cfbe8c594a5 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -238,6 +238,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
238 | vblk->disk->first_minor = index_to_minor(index); | 238 | vblk->disk->first_minor = index_to_minor(index); |
239 | vblk->disk->private_data = vblk; | 239 | vblk->disk->private_data = vblk; |
240 | vblk->disk->fops = &virtblk_fops; | 240 | vblk->disk->fops = &virtblk_fops; |
241 | vblk->disk->driverfs_dev = &vdev->dev; | ||
241 | index++; | 242 | index++; |
242 | 243 | ||
243 | /* If barriers are supported, tell block layer that queue is ordered */ | 244 | /* If barriers are supported, tell block layer that queue is ordered */ |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 19fd4cb0ddf8..b58472cf76f8 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -203,8 +203,11 @@ again: | |||
203 | if (received < budget) { | 203 | if (received < budget) { |
204 | netif_rx_complete(vi->dev, napi); | 204 | netif_rx_complete(vi->dev, napi); |
205 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) | 205 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) |
206 | && netif_rx_reschedule(vi->dev, napi)) | 206 | && napi_schedule_prep(napi)) { |
207 | vi->rvq->vq_ops->disable_cb(vi->rvq); | ||
208 | __netif_rx_schedule(vi->dev, napi); | ||
207 | goto again; | 209 | goto again; |
210 | } | ||
208 | } | 211 | } |
209 | 212 | ||
210 | return received; | 213 | return received; |
@@ -278,10 +281,11 @@ again: | |||
278 | pr_debug("%s: virtio not prepared to send\n", dev->name); | 281 | pr_debug("%s: virtio not prepared to send\n", dev->name); |
279 | netif_stop_queue(dev); | 282 | netif_stop_queue(dev); |
280 | 283 | ||
281 | /* Activate callback for using skbs: if this fails it | 284 | /* Activate callback for using skbs: if this returns false it |
282 | * means some were used in the meantime. */ | 285 | * means some were used in the meantime. */ |
283 | if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { | 286 | if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { |
284 | printk("Unlikely: restart svq failed\n"); | 287 | printk("Unlikely: restart svq race\n"); |
288 | vi->svq->vq_ops->disable_cb(vi->svq); | ||
285 | netif_start_queue(dev); | 289 | netif_start_queue(dev); |
286 | goto again; | 290 | goto again; |
287 | } | 291 | } |
@@ -294,6 +298,15 @@ again: | |||
294 | return 0; | 298 | return 0; |
295 | } | 299 | } |
296 | 300 | ||
301 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
302 | static void virtnet_netpoll(struct net_device *dev) | ||
303 | { | ||
304 | struct virtnet_info *vi = netdev_priv(dev); | ||
305 | |||
306 | napi_schedule(&vi->napi); | ||
307 | } | ||
308 | #endif | ||
309 | |||
297 | static int virtnet_open(struct net_device *dev) | 310 | static int virtnet_open(struct net_device *dev) |
298 | { | 311 | { |
299 | struct virtnet_info *vi = netdev_priv(dev); | 312 | struct virtnet_info *vi = netdev_priv(dev); |
@@ -336,6 +349,9 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
336 | dev->stop = virtnet_close; | 349 | dev->stop = virtnet_close; |
337 | dev->hard_start_xmit = start_xmit; | 350 | dev->hard_start_xmit = start_xmit; |
338 | dev->features = NETIF_F_HIGHDMA; | 351 | dev->features = NETIF_F_HIGHDMA; |
352 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
353 | dev->poll_controller = virtnet_netpoll; | ||
354 | #endif | ||
339 | SET_NETDEV_DEV(dev, &vdev->dev); | 355 | SET_NETDEV_DEV(dev, &vdev->dev); |
340 | 356 | ||
341 | /* Do we support "hardware" checksums? */ | 357 | /* Do we support "hardware" checksums? */ |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index c8a4332d1132..0b3efc31ee6d 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -152,7 +152,7 @@ static void virtballoon_changed(struct virtio_device *vdev) | |||
152 | wake_up(&vb->config_change); | 152 | wake_up(&vb->config_change); |
153 | } | 153 | } |
154 | 154 | ||
155 | static inline int towards_target(struct virtio_balloon *vb) | 155 | static inline s64 towards_target(struct virtio_balloon *vb) |
156 | { | 156 | { |
157 | u32 v; | 157 | u32 v; |
158 | __virtio_config_val(vb->vdev, | 158 | __virtio_config_val(vb->vdev, |
@@ -176,7 +176,7 @@ static int balloon(void *_vballoon) | |||
176 | 176 | ||
177 | set_freezable(); | 177 | set_freezable(); |
178 | while (!kthread_should_stop()) { | 178 | while (!kthread_should_stop()) { |
179 | int diff; | 179 | s64 diff; |
180 | 180 | ||
181 | try_to_freeze(); | 181 | try_to_freeze(); |
182 | wait_event_interruptible(vb->config_change, | 182 | wait_event_interruptible(vb->config_change, |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 26f787ddd5ff..59a8f73dec73 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
@@ -177,6 +177,7 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) | |||
177 | struct virtio_pci_device *vp_dev = opaque; | 177 | struct virtio_pci_device *vp_dev = opaque; |
178 | struct virtio_pci_vq_info *info; | 178 | struct virtio_pci_vq_info *info; |
179 | irqreturn_t ret = IRQ_NONE; | 179 | irqreturn_t ret = IRQ_NONE; |
180 | unsigned long flags; | ||
180 | u8 isr; | 181 | u8 isr; |
181 | 182 | ||
182 | /* reading the ISR has the effect of also clearing it so it's very | 183 | /* reading the ISR has the effect of also clearing it so it's very |
@@ -197,12 +198,12 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) | |||
197 | drv->config_changed(&vp_dev->vdev); | 198 | drv->config_changed(&vp_dev->vdev); |
198 | } | 199 | } |
199 | 200 | ||
200 | spin_lock(&vp_dev->lock); | 201 | spin_lock_irqsave(&vp_dev->lock, flags); |
201 | list_for_each_entry(info, &vp_dev->virtqueues, node) { | 202 | list_for_each_entry(info, &vp_dev->virtqueues, node) { |
202 | if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) | 203 | if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) |
203 | ret = IRQ_HANDLED; | 204 | ret = IRQ_HANDLED; |
204 | } | 205 | } |
205 | spin_unlock(&vp_dev->lock); | 206 | spin_unlock_irqrestore(&vp_dev->lock, flags); |
206 | 207 | ||
207 | return ret; | 208 | return ret; |
208 | } | 209 | } |
@@ -214,6 +215,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
214 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 215 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
215 | struct virtio_pci_vq_info *info; | 216 | struct virtio_pci_vq_info *info; |
216 | struct virtqueue *vq; | 217 | struct virtqueue *vq; |
218 | unsigned long flags; | ||
217 | u16 num; | 219 | u16 num; |
218 | int err; | 220 | int err; |
219 | 221 | ||
@@ -255,9 +257,9 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
255 | vq->priv = info; | 257 | vq->priv = info; |
256 | info->vq = vq; | 258 | info->vq = vq; |
257 | 259 | ||
258 | spin_lock(&vp_dev->lock); | 260 | spin_lock_irqsave(&vp_dev->lock, flags); |
259 | list_add(&info->node, &vp_dev->virtqueues); | 261 | list_add(&info->node, &vp_dev->virtqueues); |
260 | spin_unlock(&vp_dev->lock); | 262 | spin_unlock_irqrestore(&vp_dev->lock, flags); |
261 | 263 | ||
262 | return vq; | 264 | return vq; |
263 | 265 | ||
@@ -274,10 +276,11 @@ static void vp_del_vq(struct virtqueue *vq) | |||
274 | { | 276 | { |
275 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | 277 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); |
276 | struct virtio_pci_vq_info *info = vq->priv; | 278 | struct virtio_pci_vq_info *info = vq->priv; |
279 | unsigned long flags; | ||
277 | 280 | ||
278 | spin_lock(&vp_dev->lock); | 281 | spin_lock_irqsave(&vp_dev->lock, flags); |
279 | list_del(&info->node); | 282 | list_del(&info->node); |
280 | spin_unlock(&vp_dev->lock); | 283 | spin_unlock_irqrestore(&vp_dev->lock, flags); |
281 | 284 | ||
282 | vring_del_virtqueue(vq); | 285 | vring_del_virtqueue(vq); |
283 | 286 | ||
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 3a28c1382131..aa714028641e 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -232,7 +232,6 @@ static bool vring_enable_cb(struct virtqueue *_vq) | |||
232 | vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; | 232 | vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; |
233 | mb(); | 233 | mb(); |
234 | if (unlikely(more_used(vq))) { | 234 | if (unlikely(more_used(vq))) { |
235 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; | ||
236 | END_USE(vq); | 235 | END_USE(vq); |
237 | return false; | 236 | return false; |
238 | } | 237 | } |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 260d1fcf29a4..12c18ac1b973 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
@@ -43,8 +43,9 @@ struct virtqueue | |||
43 | * vq: the struct virtqueue we're talking about. | 43 | * vq: the struct virtqueue we're talking about. |
44 | * @enable_cb: restart callbacks after disable_cb. | 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 re-enables callbacks; it returns "false" if there are pending |
47 | * buffers in the queue, to avoid a race. | 47 | * buffers in the queue, to detect a possible race between the driver |
48 | * checking for more work, and enabling callbacks. | ||
48 | * | 49 | * |
49 | * Locking rules are straightforward: the driver is responsible for | 50 | * Locking rules are straightforward: the driver is responsible for |
50 | * locking. No two operations may be invoked simultaneously. | 51 | * locking. No two operations may be invoked simultaneously. |