Beispiel #1
0
/* Notify all virtqueues on an interrupt. */
static irqreturn_t vm_interrupt(int irq, void *opaque)
{
	struct virtio_mmio_device *vm_dev = opaque;
	struct virtio_mmio_vq_info *info;
	struct virtio_driver *vdrv = container_of(vm_dev->vdev.dev.driver,
			struct virtio_driver, driver);
	unsigned long status;
	unsigned long flags;
	irqreturn_t ret = IRQ_NONE;

	/* Read and acknowledge interrupts */
	status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS);
	writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK);

	if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)
			&& vdrv && vdrv->config_changed) {
		vdrv->config_changed(&vm_dev->vdev);
		ret = IRQ_HANDLED;
	}

	if (likely(status & VIRTIO_MMIO_INT_VRING)) {
		spin_lock_irqsave(&vm_dev->lock, flags);
		list_for_each_entry(info, &vm_dev->virtqueues, node)
			ret |= vring_interrupt(irq, info->vq);
		spin_unlock_irqrestore(&vm_dev->lock, flags);
	}

	return ret;
}
Beispiel #2
0
static irqreturn_t
mic_virtio_intr_handler(int irq, void *data)
{
	struct mic_vdev *mvdev = data;
	struct virtqueue *vq;

	mic_ack_interrupt(mvdev->mdev);
	list_for_each_entry(vq, &mvdev->vdev.vqs, list)
		vring_interrupt(0, vq);

	return IRQ_HANDLED;
}
Beispiel #3
0
static irqreturn_t vop_virtio_intr_handler(int irq, void *data)
{
    struct _vop_vdev *vdev = data;
    struct vop_device *vpdev = vdev->vpdev;
    struct virtqueue *vq;

    vpdev->hw_ops->ack_interrupt(vpdev, vdev->h2c_vdev_db);
    list_for_each_entry(vq, &vdev->vdev.vqs, list)
    vring_interrupt(0, vq);

    return IRQ_HANDLED;
}
Beispiel #4
0
static void handle_event(struct work_struct *work)
{
	struct virtqueue *vq;

	flush_cache_all();

	outer_flush_range(zynq_rpmsg_p->mem_start, zynq_rpmsg_p->mem_end);

	vq = zynq_rpmsg_p->vrings[0].vq;

	if (vring_interrupt(0, vq) == IRQ_NONE)
		dev_dbg(&zynq_rpmsg_platform->dev, "no message found in vqid 0\n");
}
Beispiel #5
0
/*
 * we emulate the request_irq behaviour on top of s390 extints
 */
static void kvm_extint_handler(struct ext_code ext_code,
			       unsigned int param32, unsigned long param64)
{
	struct virtqueue *vq;
	u32 param;

	if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64)
		return;
	kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;

	/* The LSB might be overloaded, we have to mask it */
	vq = (struct virtqueue *)(param64 & ~1UL);

	/* We use ext_params to decide what this interrupt means */
	param = param32 & VIRTIO_PARAM_MASK;

	switch (param) {
	case VIRTIO_PARAM_CONFIG_CHANGED:
	{
		struct virtio_driver *drv;
		drv = container_of(vq->vdev->dev.driver,
				   struct virtio_driver, driver);
		if (drv->config_changed)
			drv->config_changed(vq->vdev);

		break;
	}
	case VIRTIO_PARAM_DEV_ADD:
		schedule_work(&hotplug_work);
		break;
	case VIRTIO_PARAM_VRING_INTERRUPT:
	default:
		vring_interrupt(0, vq);
		break;
	}
}