示例#1
0
/**
 * arch_setup_msi_irq-Setup MSI interrupt
 * @pdev: Pointer to current pci device structure
 * @desc: Pointer to MSI description structure
 *
 * @return: Error/ no-error
 *
 * @note: This function  is called when pci_enable_msi is called
 */
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
	int irq = irq_alloc_desc_from(xaxipcie_msi_irq_base, -1);
	struct msi_msg msg;

	if (irq < 0)
		return irq;

	if (irq >= (xaxipcie_msi_irq_base + XILINX_NUM_MSI_IRQS + 1)) {
		irq_free_desc(irq);
		return -ENOSPC;
	}

	irq_set_msi_desc(irq, desc);

	msg.address_hi = 0x00000000;
	msg.address_lo = xaxipcie_msg_addr;
	msg.data = irq;

	pr_debug("irq %d addr_hi %08x low %08x data %08x\n",
			irq, msg.address_hi, msg.address_lo, msg.data);

	write_msi_msg(irq, &msg);

	irq_set_chip_and_handler(irq, &xilinx_msi_chip, handle_simple_irq);

	return 0;
}
示例#2
0
/**
 * intel_lpe_audio_teardown() - destroy the bridge between HDMI LPE
 * audio driver and i915
 * @dev_priv: the i915 drm device private data
 *
 * release all the resources for LPE audio <-> i915 bridge.
 */
void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
{
	struct irq_desc *desc;

	if (!HAS_LPE_AUDIO(dev_priv))
		return;

	desc = irq_to_desc(dev_priv->lpe_audio.irq);

	lpe_audio_platdev_destroy(dev_priv);

	irq_free_desc(dev_priv->lpe_audio.irq);
}
示例#3
0
void mcp2210_irq_remove(struct mcp2210_device *dev)
{
	mcp2210_info();
	if (dev->is_irq_probed) {
		const int virq_end = dev->irq_base + dev->nr_irqs;
		int virq;

		for (virq = dev->irq_base; virq < virq_end; ++virq) {
			irq_free_desc(virq);
			dev->irq_descs[virq] = NULL;
		}
		dev->is_irq_probed = 0;
	}
}
示例#4
0
static void sunxi_gpio_irq_remove(struct sunxi_gpio_chip *sgpio)
{
	int irq;
	int base = sgpio->irq_base;

	/* irq_base < 0 on unsupported platforms */
	if (base < 0)
		return;

	for (irq = base; irq < base + EINT_NUM; irq++) {
		irq_set_handler(irq, NULL);
		irq_set_chip(irq, NULL);
		irq_set_chip_data(irq, NULL);
		irq_free_desc(irq);
	}
}
示例#5
0
static int lpe_audio_setup(struct drm_i915_private *dev_priv)
{
	int ret;

	dev_priv->lpe_audio.irq = irq_alloc_desc(0);
	if (dev_priv->lpe_audio.irq < 0) {
		DRM_ERROR("Failed to allocate IRQ desc: %d\n",
			dev_priv->lpe_audio.irq);
		ret = dev_priv->lpe_audio.irq;
		goto err;
	}

	DRM_DEBUG("irq = %d\n", dev_priv->lpe_audio.irq);

	ret = lpe_audio_irq_init(dev_priv);

	if (ret) {
		DRM_ERROR("Failed to initialize irqchip for lpe audio: %d\n",
			ret);
		goto err_free_irq;
	}

	dev_priv->lpe_audio.platdev = lpe_audio_platdev_create(dev_priv);

	if (IS_ERR(dev_priv->lpe_audio.platdev)) {
		ret = PTR_ERR(dev_priv->lpe_audio.platdev);
		DRM_ERROR("Failed to create lpe audio platform device: %d\n",
			ret);
		goto err_free_irq;
	}

	/* enable chicken bit; at least this is required for Dell Wyse 3040
	 * with DP outputs (but only sometimes by some reason!)
	 */
	I915_WRITE(VLV_AUD_CHICKEN_BIT_REG, VLV_CHICKEN_BIT_DBG_ENABLE);

	return 0;
err_free_irq:
	irq_free_desc(dev_priv->lpe_audio.irq);
err:
	dev_priv->lpe_audio.irq = -1;
	dev_priv->lpe_audio.platdev = NULL;
	return ret;
}
示例#6
0
static void mcuio_soft_hc_release(struct device *device)
{
	struct mcuio_hc_platform_data *plat = dev_get_platdata(device);
	struct mcuio_soft_hc *shc;
	int i;
	if (!plat) {
		WARN_ON(1);
		return;
	}
	shc = plat->data;
	bus_unregister_notifier(&mcuio_bus_type, &device_nb);
	/* Unregister all irq controllers */
	for (i = 0; i < MCUIO_DEVS_PER_BUS; i++)
		if (shc->irq_controllers[i])
			mcuio_device_unregister(shc->irq_controllers[i]);
	irq_set_handler(shc->irqno, NULL);
	irq_set_chip(shc->irqno, NULL);
	irq_free_desc(shc->irqno);
	kfree(shc);
	mcuio_hc_dev_default_release(device);
}
示例#7
0
/*
 * This routine finds the Nth virtqueue described in the configuration of
 * this device and sets it up.
 *
 * This is kind of an ugly duckling.  It'd be nicer to have a standard
 * representation of a virtqueue in the configuration space, but it seems that
 * everyone wants to do it differently.  The KVM coders want the Guest to
 * allocate its own pages and tell the Host where they are, but for lguest it's
 * simpler for the Host to simply tell us where the pages are.
 */
static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
				    unsigned index,
				    void (*callback)(struct virtqueue *vq),
				    const char *name)
{
	struct lguest_device *ldev = to_lgdev(vdev);
	struct lguest_vq_info *lvq;
	struct virtqueue *vq;
	int err;

	if (!name)
		return NULL;

	/* We must have this many virtqueues. */
	if (index >= ldev->desc->num_vq)
		return ERR_PTR(-ENOENT);

	lvq = kmalloc(sizeof(*lvq), GFP_KERNEL);
	if (!lvq)
		return ERR_PTR(-ENOMEM);

	/*
	 * Make a copy of the "struct lguest_vqconfig" entry, which sits after
	 * the descriptor.  We need a copy because the config space might not
	 * be aligned correctly.
	 */
	memcpy(&lvq->config, lg_vq(ldev->desc)+index, sizeof(lvq->config));

	printk("Mapping virtqueue %i addr %lx\n", index,
	       (unsigned long)lvq->config.pfn << PAGE_SHIFT);
	/* Figure out how many pages the ring will take, and map that memory */
	lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT,
				DIV_ROUND_UP(vring_size(lvq->config.num,
							LGUEST_VRING_ALIGN),
					     PAGE_SIZE));
	if (!lvq->pages) {
		err = -ENOMEM;
		goto free_lvq;
	}

	/*
	 * OK, tell virtio_ring.c to set up a virtqueue now we know its size
	 * and we've got a pointer to its pages.  Note that we set weak_barriers
	 * to 'true': the host just a(nother) SMP CPU, so we only need inter-cpu
	 * barriers.
	 */
	vq = vring_new_virtqueue(index, lvq->config.num, LGUEST_VRING_ALIGN, vdev,
				 true, lvq->pages, lg_notify, callback, name);
	if (!vq) {
		err = -ENOMEM;
		goto unmap;
	}

	/* Make sure the interrupt is allocated. */
	err = lguest_setup_irq(lvq->config.irq);
	if (err)
		goto destroy_vring;

	/*
	 * Tell the interrupt for this virtqueue to go to the virtio_ring
	 * interrupt handler.
	 *
	 * FIXME: We used to have a flag for the Host to tell us we could use
	 * the interrupt as a source of randomness: it'd be nice to have that
	 * back.
	 */
	err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
			  dev_name(&vdev->dev), vq);
	if (err)
		goto free_desc;

	/*
	 * Last of all we hook up our 'struct lguest_vq_info" to the
	 * virtqueue's priv pointer.
	 */
	vq->priv = lvq;
	return vq;

free_desc:
	irq_free_desc(lvq->config.irq);
destroy_vring:
	vring_del_virtqueue(vq);
unmap:
	lguest_unmap(lvq->pages);
free_lvq:
	kfree(lvq);
	return ERR_PTR(err);
}
示例#8
0
void destroy_irq(unsigned int irq)
{
	irq_free_desc(irq);
}
示例#9
0
/**
 * arch_teardown_msi_irq-Teardown the Interrupt
 * @irq: Interrupt number to teardown
 *
 * @return: None
 *
 * @note: This function  is called when pci_disable_msi is called
 */
void arch_teardown_msi_irq(unsigned int irq)
{
	irq_free_desc(irq);
}