Exemplo n.º 1
0
static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
	unsigned int virq, rc;
	struct msi_desc *entry;
	struct msi_msg msg;
	struct axon_msic *msic;

	msic = find_msi_translator(dev);
	if (!msic)
		return -ENODEV;

	rc = setup_msi_msg_address(dev, &msg);
	if (rc)
		return rc;

	for_each_pci_msi_entry(entry, dev) {
		virq = irq_create_direct_mapping(msic->irq_domain);
		if (virq == NO_IRQ) {
			dev_warn(&dev->dev,
				 "axon_msi: virq allocation failed!\n");
			return -1;
		}
		dev_dbg(&dev->dev, "axon_msi: allocated virq 0x%x\n", virq);

		irq_set_msi_desc(virq, entry);
		msg.data = virq;
		pci_write_msi_msg(virq, &msg);
	}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
/**
 * xilinx_pcie_msi_setup_irq - Setup MSI request
 * @chip: MSI chip pointer
 * @pdev: PCIe device pointer
 * @desc: MSI descriptor pointer
 *
 * Return: '0' on success and error value on failure
 */
static int xilinx_pcie_msi_setup_irq(struct msi_controller *chip,
				     struct pci_dev *pdev,
				     struct msi_desc *desc)
{
	struct xilinx_pcie_port *port = pdev->bus->sysdata;
	unsigned int irq;
	int hwirq;
	struct msi_msg msg;
	phys_addr_t msg_addr;

	hwirq = xilinx_pcie_assign_msi();
	if (hwirq < 0)
		return hwirq;

	irq = irq_create_mapping(port->msi_domain, hwirq);
	if (!irq)
		return -EINVAL;

	irq_set_msi_desc(irq, desc);

	msg_addr = virt_to_phys((void *)port->msi_pages);

	msg.address_hi = 0;
	msg.address_lo = msg_addr;
	msg.data = irq;

	pci_write_msi_msg(irq, &msg);

	return 0;
}
Exemplo n.º 4
0
int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
	struct msi_msg	msg;
	unsigned long	dest_phys_id;
	int	irq, vector;
	cpumask_t mask;

	irq = create_irq();
	if (irq < 0)
		return irq;

	irq_set_msi_desc(irq, desc);
	cpumask_and(&mask, &(irq_to_domain(irq)), cpu_online_mask);
	dest_phys_id = cpu_physical_id(first_cpu(mask));
	vector = irq_to_vector(irq);

	msg.address_hi = 0;
	msg.address_lo =
		MSI_ADDR_HEADER |
		MSI_ADDR_DEST_MODE_PHYS |
		MSI_ADDR_REDIRECTION_CPU |
		MSI_ADDR_DEST_ID_CPU(dest_phys_id);

	msg.data =
		MSI_DATA_TRIGGER_EDGE |
		MSI_DATA_LEVEL_ASSERT |
		MSI_DATA_DELIVERY_FIXED |
		MSI_DATA_VECTOR(vector);

	write_msi_msg(irq, &msg);
	irq_set_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);

	return 0;
}
Exemplo n.º 5
0
static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
				       struct pci_dev *pdev,
				       struct msi_desc *desc)
{
	struct msi_msg msg;
	irq_hw_number_t hwirq;
	int virq;

	hwirq = armada_370_xp_alloc_msi();
	if (hwirq < 0)
		return hwirq;

	virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
	if (!virq) {
		armada_370_xp_free_msi(hwirq);
		return -EINVAL;
	}

	irq_set_msi_desc(virq, desc);

	msg.address_lo = msi_doorbell_addr;
	msg.address_hi = 0;
	msg.data = 0xf00 | (hwirq + 16);

	write_msi_msg(virq, &msg);
	return 0;
}
Exemplo n.º 6
0
/*
 * Allocate a MSI vector on a link
 */
static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
	struct msi_desc *desc)
{
	struct xlp_msi_data *md;
	struct msi_msg msg;
	unsigned long flags;
	int msivec, irt, lirq, xirq, ret;
	uint64_t msiaddr;

	/* Get MSI data for the link */
	lirq = PIC_PCIE_LINK_MSI_IRQ(link);
	xirq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
	md = irq_get_handler_data(xirq);
	msiaddr = MSI_LINK_ADDR(node, link);

	spin_lock_irqsave(&md->msi_lock, flags);
	if (md->msi_alloc_mask == 0) {
		xlp_config_link_msi(lnkbase, lirq, msiaddr);
		/* switch the link IRQ to MSI range */
		if (cpu_is_xlp9xx())
			irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link);
		else
			irt = PIC_IRT_PCIE_LINK_INDEX(link);
		nlm_setup_pic_irq(node, lirq, lirq, irt);
		nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq,
				 node * nlm_threads_per_node(), 1 /*en */);
	}

	/* allocate a MSI vec, and tell the bridge about it */
	msivec = fls(md->msi_alloc_mask);
	if (msivec == XLP_MSIVEC_PER_LINK) {
		spin_unlock_irqrestore(&md->msi_lock, flags);
		return -ENOMEM;
	}
	md->msi_alloc_mask |= (1u << msivec);
	spin_unlock_irqrestore(&md->msi_lock, flags);

	msg.address_hi = msiaddr >> 32;
	msg.address_lo = msiaddr & 0xffffffff;
	msg.data = 0xc00 | msivec;

	xirq = xirq + msivec;		/* msi mapped to global irq space */
	ret = irq_set_msi_desc(xirq, desc);
	if (ret < 0)
		return ret;

	write_msi_msg(xirq, &msg);
	return 0;
}
Exemplo n.º 7
0
/**
 * arch_setup_msi_irq() - Set up an MSI for Endpoint
 * @pdev: Pointer to PCI device structure of requesting EP
 * @desc: Pointer to MSI descriptor data
 *
 * Assigns an MSI to endpoint and sets up corresponding irq. Also passes the MSI
 * information to the endpont.
 */
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
	int ret, irq;
	struct msi_msg msg;

	if (msi_irq < 0) {
		printk(KERN_ERR "PCI: MSI irq pin not specified\n");
		return msi_irq;
	}

	ret = get_free_msi();
	if (ret < 0) {
		printk(KERN_ERR "PCI: Failed to get free MSI\n");
	} else {
		irq = msi_irq_base + ret;
#if defined(MSI_SUPPORT_1_DEV_1_BIT)
		msg.data = ret;
#elif defined(MSI_SUPPORT_1_DEV_32_BIT)
        msg.data = (ret&0x7)<<5;
#endif
		dynamic_irq_init(irq);
		ret = irq_set_msi_desc(irq, desc);

		if (!ret) {
			msg.address_hi = MSI_LOCAL_UPPER_ADDR;
			msg.address_lo = MSI_LOCAL_LOWER_ADDR;
#if defined(MSI_SUPPORT_1_DEV_1_BIT)
			printk(KERN_ERR "PCI:MSI %d @%x:%x, irq = %d\n",
					msg.data, msg.address_hi,
					msg.address_lo, irq);
#elif defined(MSI_SUPPORT_1_DEV_32_BIT)
			printk(KERN_ERR "PCI:MSI#%d[0-31] @%x:%x, irq = %d\n",
					(msg.data>>5)&0x7, msg.address_hi,
					msg.address_lo, irq);
#endif
			write_msi_msg(irq, &msg);
			irq_set_chip_and_handler_name(irq, &balong_msi_chip,
						handle_level_irq,NULL);
			set_irq_flags(irq, IRQF_VALID);
		}
	}
Exemplo n.º 8
0
static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
	int int_no = -ENOMEM;
	unsigned int virq;
	struct msi_msg msg;
	struct msi_desc *entry;
	struct ppc4xx_msi *msi_data = &ppc4xx_msi;

	dev_dbg(&dev->dev, "PCIE-MSI:%s called. vec %x type %d\n",
		__func__, nvec, type);
	if (type == PCI_CAP_ID_MSIX)
		pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n");

	msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), GFP_KERNEL);
	if (!msi_data->msi_virqs)
		return -ENOMEM;

	for_each_pci_msi_entry(entry, dev) {
		int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
		if (int_no >= 0)
			break;
		if (int_no < 0) {
			pr_debug("%s: fail allocating msi interrupt\n",
					__func__);
		}
		virq = irq_of_parse_and_map(msi_data->msi_dev, int_no);
		if (virq == NO_IRQ) {
			dev_err(&dev->dev, "%s: fail mapping irq\n", __func__);
			msi_bitmap_free_hwirqs(&msi_data->bitmap, int_no, 1);
			return -ENOSPC;
		}
		dev_dbg(&dev->dev, "%s: virq = %d\n", __func__, virq);

		/* Setup msi address space */
		msg.address_hi = msi_data->msi_addr_hi;
		msg.address_lo = msi_data->msi_addr_lo;

		irq_set_msi_desc(virq, entry);
		msg.data = int_no;
		pci_write_msi_msg(virq, &msg);
	}
Exemplo n.º 9
0
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
    int irq = create_irq();
    int msi_irq;
    struct msi_msg msg;

    if (irq < 0)
        return irq;

    msi_irq = irq - IRQ_AURORA_MSI_START;
    irq_set_msi_desc(irq, desc);

    msg.address_hi = 0x0;
    msg.address_lo = AXP_SW_TRIG_IRQ_PHYS;
    msg.data = (0x1 << AXP_SW_TRIG_IRQ_CPU_TARGET_OFFS) |
               ((msi_irq + NR_PRIVATE_MSI_GROUP) & AXP_SW_TRIG_IRQ_INITID_MASK);

    write_msi_msg(irq, &msg);
    irq_set_chip_and_handler(irq, &armada_msi_irq_chip, handle_edge_irq);

    return 0;
}
Exemplo n.º 10
0
Arquivo: msi.c Projeto: Moretti0/gg
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
	int irq = create_irq();
	struct msi_msg msg;

	if (irq < 0)
		return irq;

	irq_set_msi_desc(irq, desc);

	msg.address_hi = 0x0;
	msg.address_lo = MSI_MATCH_ADDR;
	/* 16bits msg.data: set cpu type to the upper 8bits*/
	msg.data = (mxc_cpu_type << 8) | ((irq - IRQ_IMX_MSI_0) & 0xFF);

	write_msi_msg(irq, &msg);
	irq_set_chip_and_handler(irq, &imx_msi_chip, handle_simple_irq);
	set_irq_flags(irq, IRQF_VALID);
	pr_info("IMX-PCIe: MSI 0x%04x @%#x:%#x, irq = %d\n",
			msg.data, msg.address_hi,
			msg.address_lo, irq);
	return 0;
}
Exemplo n.º 11
0
/* hookup to linux pci msi framework */
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
	int irq;
	struct msi_msg msg;

	irq = msm_pcie_create_irq();
	if (irq < 0)
		return irq;

	PCIE_DBG("irq %d allocated\n", irq);

	irq_set_msi_desc(irq, desc);

	/* write msi vector and data */
	msg.address_hi = 0;
	msg.address_lo = MSM_PCIE_MSI_PHY;
	msg.data = irq - MSM_PCIE_MSI_INT(0);
	write_msi_msg(irq, &msg);

	irq_set_chip_and_handler(irq, &pcie_msi_chip, handle_simple_irq);
	set_irq_flags(irq, IRQF_VALID);
	return 0;
}
int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
{
	struct msi_msg msg;
	int widget;
	int status;
	nasid_t nasid;
	u64 bus_addr;
	struct sn_irq_info *sn_irq_info;
	struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
	int irq;

	if (!entry->msi_attrib.is_64)
		return -EINVAL;

	if (bussoft == NULL)
		return -EINVAL;

	if (provider == NULL || provider->dma_map_consistent == NULL)
		return -EINVAL;

	irq = create_irq();
	if (irq < 0)
		return irq;

	/*
	 * Set up the vector plumbing.  Let the prom (via sn_intr_alloc)
	 * decide which cpu to direct this msi at by default.
	 */

	nasid = NASID_GET(bussoft->bs_base);
	widget = (nasid & 1) ?
			TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
			SWIN_WIDGETNUM(bussoft->bs_base);

	sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
	if (! sn_irq_info) {
		destroy_irq(irq);
		return -ENOMEM;
	}

	status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
	if (status) {
		kfree(sn_irq_info);
		destroy_irq(irq);
		return -ENOMEM;
	}

	sn_irq_info->irq_int_bit = -1;		/* mark this as an MSI irq */
	sn_irq_fixup(pdev, sn_irq_info);

	/* Prom probably should fill these in, but doesn't ... */
	sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
	sn_irq_info->irq_bridge = (void *)bussoft->bs_base;

	/*
	 * Map the xio address into bus space
	 */
	bus_addr = (*provider->dma_map_consistent)(pdev,
					sn_irq_info->irq_xtalkaddr,
					sizeof(sn_irq_info->irq_xtalkaddr),
					SN_DMA_MSI|SN_DMA_ADDR_XIO);
	if (! bus_addr) {
		sn_intr_free(nasid, widget, sn_irq_info);
		kfree(sn_irq_info);
		destroy_irq(irq);
		return -ENOMEM;
	}

	sn_msi_info[irq].sn_irq_info = sn_irq_info;
	sn_msi_info[irq].pci_addr = bus_addr;

	msg.address_hi = (u32)(bus_addr >> 32);
	msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);

	/*
	 * In the SN platform, bit 16 is a "send vector" bit which
	 * must be present in order to move the vector through the system.
	 */
	msg.data = 0x100 + irq;

	irq_set_msi_desc(irq, entry);
	pci_write_msi_msg(irq, &msg);
	irq_set_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);

	return 0;
}
Exemplo n.º 13
0
int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
{
	struct msi_msg msg;
	int widget;
	int status;
	nasid_t nasid;
	u64 bus_addr;
	struct sn_irq_info *sn_irq_info;
	struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
	int irq;

	if (!entry->msi_attrib.is_64)
		return -EINVAL;

	if (bussoft == NULL)
		return -EINVAL;

	if (provider == NULL || provider->dma_map_consistent == NULL)
		return -EINVAL;

	irq = create_irq();
	if (irq < 0)
		return irq;


	nasid = NASID_GET(bussoft->bs_base);
	widget = (nasid & 1) ?
			TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
			SWIN_WIDGETNUM(bussoft->bs_base);

	sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
	if (! sn_irq_info) {
		destroy_irq(irq);
		return -ENOMEM;
	}

	status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
	if (status) {
		kfree(sn_irq_info);
		destroy_irq(irq);
		return -ENOMEM;
	}

	sn_irq_info->irq_int_bit = -1;		
	sn_irq_fixup(pdev, sn_irq_info);

	
	sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
	sn_irq_info->irq_bridge = (void *)bussoft->bs_base;

	bus_addr = (*provider->dma_map_consistent)(pdev,
					sn_irq_info->irq_xtalkaddr,
					sizeof(sn_irq_info->irq_xtalkaddr),
					SN_DMA_MSI|SN_DMA_ADDR_XIO);
	if (! bus_addr) {
		sn_intr_free(nasid, widget, sn_irq_info);
		kfree(sn_irq_info);
		destroy_irq(irq);
		return -ENOMEM;
	}

	sn_msi_info[irq].sn_irq_info = sn_irq_info;
	sn_msi_info[irq].pci_addr = bus_addr;

	msg.address_hi = (u32)(bus_addr >> 32);
	msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);

	msg.data = 0x100 + irq;

	irq_set_msi_desc(irq, entry);
	write_msi_msg(irq, &msg);
	irq_set_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);

	return 0;
}