void aq_pci_func_free_irqs(struct aq_nic_s *self) { struct pci_dev *pdev = self->pdev; unsigned int i; for (i = 32U; i--;) { if (!((1U << i) & self->msix_entry_mask)) continue; if (pdev->msix_enabled) irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL); free_irq(pci_irq_vector(pdev, i), self->aq_vec[i]); self->msix_entry_mask &= ~(1U << i); } }
static int xgbe_config_irqs(struct xgbe_prv_data *pdata) { int ret; ret = xgbe_config_multi_msi(pdata); if (!ret) goto out; ret = pci_alloc_irq_vectors(pdata->pcidev, 1, 1, PCI_IRQ_LEGACY | PCI_IRQ_MSI); if (ret < 0) { dev_info(pdata->dev, "single IRQ enablement failed\n"); return ret; } pdata->isr_as_tasklet = pdata->pcidev->msi_enabled ? 1 : 0; pdata->irq_count = 1; pdata->channel_irq_count = 1; pdata->dev_irq = pci_irq_vector(pdata->pcidev, 0); pdata->ecc_irq = pci_irq_vector(pdata->pcidev, 0); pdata->i2c_irq = pci_irq_vector(pdata->pcidev, 0); pdata->an_irq = pci_irq_vector(pdata->pcidev, 0); if (netif_msg_probe(pdata)) dev_dbg(pdata->dev, "single %s interrupt enabled\n", pdata->pcidev->msi_enabled ? "MSI" : "legacy"); out: if (netif_msg_probe(pdata)) { unsigned int i; dev_dbg(pdata->dev, " dev irq=%d\n", pdata->dev_irq); dev_dbg(pdata->dev, " ecc irq=%d\n", pdata->ecc_irq); dev_dbg(pdata->dev, " i2c irq=%d\n", pdata->i2c_irq); dev_dbg(pdata->dev, " an irq=%d\n", pdata->an_irq); for (i = 0; i < pdata->channel_irq_count; i++) dev_dbg(pdata->dev, " dma%u irq=%d\n", i, pdata->channel_irq[i]); } return 0; }
static int xgbe_config_multi_msi(struct xgbe_prv_data *pdata) { unsigned int vector_count; unsigned int i, j; int ret; vector_count = XGBE_MSI_BASE_COUNT; vector_count += max(pdata->rx_ring_count, pdata->tx_ring_count); ret = pci_alloc_irq_vectors(pdata->pcidev, XGBE_MSI_MIN_COUNT, vector_count, PCI_IRQ_MSI | PCI_IRQ_MSIX); if (ret < 0) { dev_info(pdata->dev, "multi MSI/MSI-X enablement failed\n"); return ret; } pdata->isr_as_tasklet = 1; pdata->irq_count = ret; pdata->dev_irq = pci_irq_vector(pdata->pcidev, 0); pdata->ecc_irq = pci_irq_vector(pdata->pcidev, 1); pdata->i2c_irq = pci_irq_vector(pdata->pcidev, 2); pdata->an_irq = pci_irq_vector(pdata->pcidev, 3); for (i = XGBE_MSI_BASE_COUNT, j = 0; i < ret; i++, j++) pdata->channel_irq[j] = pci_irq_vector(pdata->pcidev, i); pdata->channel_irq_count = j; pdata->per_channel_irq = 1; pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL; if (netif_msg_probe(pdata)) dev_dbg(pdata->dev, "multi %s interrupts enabled\n", pdata->pcidev->msix_enabled ? "MSI-X" : "MSI"); return 0; }
int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i, char *name, void *aq_vec, cpumask_t *affinity_mask) { struct pci_dev *pdev = self->pdev; int err; if (pdev->msix_enabled || pdev->msi_enabled) err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr, 0, name, aq_vec); else err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr_legacy, IRQF_SHARED, name, aq_vec); if (err >= 0) { self->msix_entry_mask |= (1 << i); self->aq_vec[i] = aq_vec; if (pdev->msix_enabled) irq_set_affinity_hint(pci_irq_vector(pdev, i), affinity_mask); } return err; }
/** * pci_request_irq - allocate an interrupt line for a PCI device * @dev: PCI device to operate on * @nr: device-relative interrupt vector index (0-based). * @handler: Function to be called when the IRQ occurs. * Primary handler for threaded interrupts. * If NULL and thread_fn != NULL the default primary handler is * installed. * @thread_fn: Function called from the IRQ handler thread * If NULL, no IRQ thread is created * @dev_id: Cookie passed back to the handler function * @fmt: Printf-like format string naming the handler * * This call allocates interrupt resources and enables the interrupt line and * IRQ handling. From the point this call is made @handler and @thread_fn may * be invoked. All interrupts requested using this function might be shared. * * @dev_id must not be NULL and must be globally unique. */ int pci_request_irq(struct pci_dev *dev, unsigned int nr, irq_handler_t handler, irq_handler_t thread_fn, void *dev_id, const char *fmt, ...) { va_list ap; int ret; char *devname; va_start(ap, fmt); devname = kvasprintf(GFP_KERNEL, fmt, ap); va_end(ap); ret = request_threaded_irq(pci_irq_vector(dev, nr), handler, thread_fn, IRQF_SHARED, devname, dev_id); if (ret) kfree(devname); return ret; }
static int thunder_mmc_register_interrupts(struct cvm_mmc_host *host, struct pci_dev *pdev) { int nvec, ret, i; nvec = pci_alloc_irq_vectors(pdev, 1, 9, PCI_IRQ_MSIX); if (nvec < 0) return nvec; /* register interrupts */ for (i = 0; i < nvec; i++) { ret = devm_request_irq(&pdev->dev, pci_irq_vector(pdev, i), cvm_mmc_interrupt, 0, cvm_mmc_irq_names[i], host); if (ret) return ret; } return 0; }
static int intel_th_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct intel_th_drvdata *drvdata = (void *)id->driver_data; struct resource resource[TH_MMIO_END + TH_NVEC_MAX] = { [TH_MMIO_CONFIG] = pdev->resource[TH_PCI_CONFIG_BAR], [TH_MMIO_SW] = pdev->resource[TH_PCI_STH_SW_BAR], }; int err, r = TH_MMIO_SW + 1, i; struct intel_th *th; err = pcim_enable_device(pdev); if (err) return err; err = pcim_iomap_regions_request_all(pdev, BAR_MASK, DRIVER_NAME); if (err) return err; if (pdev->resource[TH_PCI_RTIT_BAR].start) { resource[TH_MMIO_RTIT] = pdev->resource[TH_PCI_RTIT_BAR]; r++; } err = pci_alloc_irq_vectors(pdev, 1, 8, PCI_IRQ_ALL_TYPES); if (err > 0) for (i = 0; i < err; i++, r++) { resource[r].flags = IORESOURCE_IRQ; resource[r].start = pci_irq_vector(pdev, i); } th = intel_th_alloc(&pdev->dev, drvdata, resource, r); if (IS_ERR(th)) return PTR_ERR(th); th->activate = intel_th_pci_activate; th->deactivate = intel_th_pci_deactivate; pci_set_master(pdev); return 0; }
/** * pci_free_irq - free an interrupt allocated with pci_request_irq * @dev: PCI device to operate on * @nr: device-relative interrupt vector index (0-based). * @dev_id: Device identity to free * * Remove an interrupt handler. The handler is removed and if the interrupt * line is no longer in use by any driver it is disabled. The caller must * ensure the interrupt is disabled on the device before calling this function. * The function does not return until any executing interrupts for this IRQ * have completed. * * This function must not be called from interrupt context. */ void pci_free_irq(struct pci_dev *dev, unsigned int nr, void *dev_id) { kfree(free_irq(pci_irq_vector(dev, nr), dev_id)); }
static int igbuio_pci_enable_interrupts(struct rte_uio_pci_dev *udev) { int err = 0; #ifndef HAVE_ALLOC_IRQ_VECTORS struct msix_entry msix_entry; #endif switch (igbuio_intr_mode_preferred) { case RTE_INTR_MODE_MSIX: /* Only 1 msi-x vector needed */ #ifndef HAVE_ALLOC_IRQ_VECTORS msix_entry.entry = 0; if (pci_enable_msix(udev->pdev, &msix_entry, 1) == 0) { dev_dbg(&udev->pdev->dev, "using MSI-X"); udev->info.irq_flags = IRQF_NO_THREAD; udev->info.irq = msix_entry.vector; udev->mode = RTE_INTR_MODE_MSIX; break; } #else if (pci_alloc_irq_vectors(udev->pdev, 1, 1, PCI_IRQ_MSIX) == 1) { dev_dbg(&udev->pdev->dev, "using MSI-X"); udev->info.irq_flags = IRQF_NO_THREAD; udev->info.irq = pci_irq_vector(udev->pdev, 0); udev->mode = RTE_INTR_MODE_MSIX; break; } #endif /* fall back to MSI */ case RTE_INTR_MODE_MSI: #ifndef HAVE_ALLOC_IRQ_VECTORS if (pci_enable_msi(udev->pdev) == 0) { dev_dbg(&udev->pdev->dev, "using MSI"); udev->info.irq_flags = IRQF_NO_THREAD; udev->info.irq = udev->pdev->irq; udev->mode = RTE_INTR_MODE_MSI; break; } #else if (pci_alloc_irq_vectors(udev->pdev, 1, 1, PCI_IRQ_MSI) == 1) { dev_dbg(&udev->pdev->dev, "using MSI"); udev->info.irq_flags = IRQF_NO_THREAD; udev->info.irq = pci_irq_vector(udev->pdev, 0); udev->mode = RTE_INTR_MODE_MSI; break; } #endif /* fall back to INTX */ case RTE_INTR_MODE_LEGACY: if (pci_intx_mask_supported(udev->pdev)) { dev_dbg(&udev->pdev->dev, "using INTX"); udev->info.irq_flags = IRQF_SHARED | IRQF_NO_THREAD; udev->info.irq = udev->pdev->irq; udev->mode = RTE_INTR_MODE_LEGACY; break; } dev_notice(&udev->pdev->dev, "PCI INTX mask not supported\n"); /* fall back to no IRQ */ case RTE_INTR_MODE_NONE: udev->mode = RTE_INTR_MODE_NONE; udev->info.irq = UIO_IRQ_NONE; break; default: dev_err(&udev->pdev->dev, "invalid IRQ mode %u", igbuio_intr_mode_preferred); udev->info.irq = UIO_IRQ_NONE; err = -EINVAL; } if (udev->info.irq != UIO_IRQ_NONE) err = request_irq(udev->info.irq, igbuio_pci_irqhandler, udev->info.irq_flags, udev->info.name, udev); dev_info(&udev->pdev->dev, "uio device registered with irq %lx\n", udev->info.irq); return err; }