aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/virtio/virtio_pci.c53
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. */
168static 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. */
181static 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)
173static irqreturn_t vp_interrupt(int irq, void *opaque) 204static 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 */