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); }
/** * 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; }
/** * 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; }
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; }
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; }
/* * 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; }
/** * 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); } }
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); }
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; }
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; }
/* 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; }
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; }