diff options
| author | Michael S. Tsirkin <mst@redhat.com> | 2009-05-14 06:55:31 -0400 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2009-06-12 08:46:37 -0400 |
| commit | 77cf524654a886e0fbbf03b16b44f048deef7b0c (patch) | |
| tree | 4b55884ceade70463c53517eae382f0412cc317c /drivers/virtio | |
| parent | d2a7ddda9ffb1c8961abff6714b0f1eb925c120f (diff) | |
virtio_pci: split up vp_interrupt
This reorganizes virtio-pci code in vp_interrupt slightly, so that
it's easier to add per-vq MSI support on top.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/virtio')
| -rw-r--r-- | drivers/virtio/virtio_pci.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 027f13fbe493..951e673e50a4 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -164,6 +164,37 @@ static void vp_notify(struct virtqueue *vq) | |||
| 164 | iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); | 164 | iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | /* Handle a configuration change: Tell driver if it wants to know. */ | ||
| 168 | static irqreturn_t vp_config_changed(int irq, void *opaque) | ||
| 169 | { | ||
| 170 | struct virtio_pci_device *vp_dev = opaque; | ||
| 171 | struct virtio_driver *drv; | ||
| 172 | drv = container_of(vp_dev->vdev.dev.driver, | ||
| 173 | struct virtio_driver, driver); | ||
| 174 | |||
| 175 | if (drv && drv->config_changed) | ||
| 176 | drv->config_changed(&vp_dev->vdev); | ||
| 177 | return IRQ_HANDLED; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* Notify all virtqueues on an interrupt. */ | ||
| 181 | static irqreturn_t vp_vring_interrupt(int irq, void *opaque) | ||
| 182 | { | ||
| 183 | struct virtio_pci_device *vp_dev = opaque; | ||
| 184 | struct virtio_pci_vq_info *info; | ||
| 185 | irqreturn_t ret = IRQ_NONE; | ||
| 186 | unsigned long flags; | ||
| 187 | |||
| 188 | spin_lock_irqsave(&vp_dev->lock, flags); | ||
| 189 | list_for_each_entry(info, &vp_dev->virtqueues, node) { | ||
| 190 | if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) | ||
| 191 | ret = IRQ_HANDLED; | ||
| 192 | } | ||
| 193 | spin_unlock_irqrestore(&vp_dev->lock, flags); | ||
| 194 | |||
| 195 | return ret; | ||
| 196 | } | ||
| 197 | |||
| 167 | /* A small wrapper to also acknowledge the interrupt when it's handled. | 198 | /* A small wrapper to also acknowledge the interrupt when it's handled. |
| 168 | * I really need an EIO hook for the vring so I can ack the interrupt once we | 199 | * I really need an EIO hook for the vring so I can ack the interrupt once we |
| 169 | * know that we'll be handling the IRQ but before we invoke the callback since | 200 | * know that we'll be handling the IRQ but before we invoke the callback since |
| @@ -173,9 +204,6 @@ static void vp_notify(struct virtqueue *vq) | |||
| 173 | static irqreturn_t vp_interrupt(int irq, void *opaque) | 204 | static irqreturn_t vp_interrupt(int irq, void *opaque) |
| 174 | { | 205 | { |
| 175 | struct virtio_pci_device *vp_dev = opaque; | 206 | struct virtio_pci_device *vp_dev = opaque; |
| 176 | struct virtio_pci_vq_info *info; | ||
| 177 | irqreturn_t ret = IRQ_NONE; | ||
| 178 | unsigned long flags; | ||
| 179 | u8 isr; | 207 | u8 isr; |
| 180 | 208 | ||
| 181 | /* reading the ISR has the effect of also clearing it so it's very | 209 | /* reading the ISR has the effect of also clearing it so it's very |
| @@ -187,23 +215,10 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) | |||
| 187 | return IRQ_NONE; | 215 | return IRQ_NONE; |
| 188 | 216 | ||
| 189 | /* Configuration change? Tell driver if it wants to know. */ | 217 | /* Configuration change? Tell driver if it wants to know. */ |
| 190 | if (isr & VIRTIO_PCI_ISR_CONFIG) { | 218 | if (isr & VIRTIO_PCI_ISR_CONFIG) |
| 191 | struct virtio_driver *drv; | 219 | vp_config_changed(irq, opaque); |
| 192 | drv = container_of(vp_dev->vdev.dev.driver, | ||
| 193 | struct virtio_driver, driver); | ||
| 194 | |||
| 195 | if (drv && drv->config_changed) | ||
| 196 | drv->config_changed(&vp_dev->vdev); | ||
| 197 | } | ||
| 198 | 220 | ||
| 199 | spin_lock_irqsave(&vp_dev->lock, flags); | 221 | return vp_vring_interrupt(irq, opaque); |
| 200 | list_for_each_entry(info, &vp_dev->virtqueues, node) { | ||
| 201 | if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) | ||
| 202 | ret = IRQ_HANDLED; | ||
| 203 | } | ||
| 204 | spin_unlock_irqrestore(&vp_dev->lock, flags); | ||
| 205 | |||
| 206 | return ret; | ||
| 207 | } | 222 | } |
| 208 | 223 | ||
| 209 | /* the config->find_vq() implementation */ | 224 | /* the config->find_vq() implementation */ |
