diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2008-03-02 17:37:48 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-03-17 07:58:13 -0400 |
commit | 27ebe308af7c14aed0711e25817c6a1235bd16ff (patch) | |
tree | dafd3caaa1591a60a7b79f7027c00bcae30f4a6e | |
parent | a978b30af3bab0dd9af9350eeda25e76123fa28e (diff) |
virtio: Use spin_lock_irqsave/restore for virtio-pci
virtio-pci acquires its spin lock in an interrupt context so it's necessary
to use spin_lock_irqsave/restore variants. This patch fixes guest SMP when
using virtio devices in KVM.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | drivers/virtio/virtio_pci.c | 15 |
1 files changed, 9 insertions, 6 deletions
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 | ||