diff options
Diffstat (limited to 'drivers/virtio/virtio_pci.c')
| -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)  	iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);  } +/* Handle a configuration change: Tell driver if it wants to know. */ +static irqreturn_t vp_config_changed(int irq, void *opaque) +{ +	struct virtio_pci_device *vp_dev = opaque; +	struct virtio_driver *drv; +	drv = container_of(vp_dev->vdev.dev.driver, +			   struct virtio_driver, driver); + +	if (drv && drv->config_changed) +		drv->config_changed(&vp_dev->vdev); +	return IRQ_HANDLED; +} + +/* Notify all virtqueues on an interrupt. */ +static irqreturn_t vp_vring_interrupt(int irq, void *opaque) +{ +	struct virtio_pci_device *vp_dev = opaque; +	struct virtio_pci_vq_info *info; +	irqreturn_t ret = IRQ_NONE; +	unsigned long flags; + +	spin_lock_irqsave(&vp_dev->lock, flags); +	list_for_each_entry(info, &vp_dev->virtqueues, node) { +		if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) +			ret = IRQ_HANDLED; +	} +	spin_unlock_irqrestore(&vp_dev->lock, flags); + +	return ret; +} +  /* A small wrapper to also acknowledge the interrupt when it's handled.   * I really need an EIO hook for the vring so I can ack the interrupt once we   * 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)  static irqreturn_t vp_interrupt(int irq, void *opaque)  {  	struct virtio_pci_device *vp_dev = opaque; -	struct virtio_pci_vq_info *info; -	irqreturn_t ret = IRQ_NONE; -	unsigned long flags;  	u8 isr;  	/* 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)  		return IRQ_NONE;  	/* Configuration change?  Tell driver if it wants to know. */ -	if (isr & VIRTIO_PCI_ISR_CONFIG) { -		struct virtio_driver *drv; -		drv = container_of(vp_dev->vdev.dev.driver, -				   struct virtio_driver, driver); - -		if (drv && drv->config_changed) -			drv->config_changed(&vp_dev->vdev); -	} +	if (isr & VIRTIO_PCI_ISR_CONFIG) +		vp_config_changed(irq, opaque); -	spin_lock_irqsave(&vp_dev->lock, flags); -	list_for_each_entry(info, &vp_dev->virtqueues, node) { -		if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) -			ret = IRQ_HANDLED; -	} -	spin_unlock_irqrestore(&vp_dev->lock, flags); - -	return ret; +	return vp_vring_interrupt(irq, opaque);  }  /* the config->find_vq() implementation */ | 
