Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI/irq: Add pci_request_irq() and pci_free_irq() helpers

These are small wrappers around request_threaded_irq() and free_irq(),
which dynamically allocate space for the device name so that drivers don't
need to keep static buffers for these around. Additionally it works with
device-relative vector numbers to make the usage easier, and force the
IRQF_SHARED flag on given that it has no runtime overhead and should be
supported by all PCI devices.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Christoph Hellwig and committed by
Bjorn Helgaas
704e8953 25ce4be7

+66 -1
+60 -1
drivers/pci/irq.c
··· 1 1 /* 2 - * PCI IRQ failure handing code 2 + * PCI IRQ handling code 3 3 * 4 4 * Copyright (c) 2008 James Bottomley <James.Bottomley@HansenPartnership.com> 5 + * Copyright (C) 2017 Christoph Hellwig. 5 6 */ 6 7 7 8 #include <linux/acpi.h> ··· 60 59 return PCI_LOST_IRQ_NO_INFORMATION; 61 60 } 62 61 EXPORT_SYMBOL(pci_lost_interrupt); 62 + 63 + /** 64 + * pci_request_irq - allocate an interrupt line for a PCI device 65 + * @dev: PCI device to operate on 66 + * @nr: device-relative interrupt vector index (0-based). 67 + * @handler: Function to be called when the IRQ occurs. 68 + * Primary handler for threaded interrupts. 69 + * If NULL and thread_fn != NULL the default primary handler is 70 + * installed. 71 + * @thread_fn: Function called from the IRQ handler thread 72 + * If NULL, no IRQ thread is created 73 + * @dev_id: Cookie passed back to the handler function 74 + * @fmt: Printf-like format string naming the handler 75 + * 76 + * This call allocates interrupt resources and enables the interrupt line and 77 + * IRQ handling. From the point this call is made @handler and @thread_fn may 78 + * be invoked. All interrupts requested using this function might be shared. 79 + * 80 + * @dev_id must not be NULL and must be globally unique. 81 + */ 82 + int pci_request_irq(struct pci_dev *dev, unsigned int nr, irq_handler_t handler, 83 + irq_handler_t thread_fn, void *dev_id, const char *fmt, ...) 84 + { 85 + va_list ap; 86 + int ret; 87 + char *devname; 88 + 89 + va_start(ap, fmt); 90 + devname = kvasprintf(GFP_KERNEL, fmt, ap); 91 + va_end(ap); 92 + 93 + ret = request_threaded_irq(pci_irq_vector(dev, nr), handler, thread_fn, 94 + IRQF_SHARED, devname, dev_id); 95 + if (ret) 96 + kfree(devname); 97 + return ret; 98 + } 99 + EXPORT_SYMBOL(pci_request_irq); 100 + 101 + /** 102 + * pci_free_irq - free an interrupt allocated with pci_request_irq 103 + * @dev: PCI device to operate on 104 + * @nr: device-relative interrupt vector index (0-based). 105 + * @dev_id: Device identity to free 106 + * 107 + * Remove an interrupt handler. The handler is removed and if the interrupt 108 + * line is no longer in use by any driver it is disabled. The caller must 109 + * ensure the interrupt is disabled on the device before calling this function. 110 + * The function does not return until any executing interrupts for this IRQ 111 + * have completed. 112 + * 113 + * This function must not be called from interrupt context. 114 + */ 115 + void pci_free_irq(struct pci_dev *dev, unsigned int nr, void *dev_id) 116 + { 117 + kfree(free_irq(pci_irq_vector(dev, nr), dev_id)); 118 + } 119 + EXPORT_SYMBOL(pci_free_irq);
+6
include/linux/pci.h
··· 28 28 #include <linux/kobject.h> 29 29 #include <linux/atomic.h> 30 30 #include <linux/device.h> 31 + #include <linux/interrupt.h> 31 32 #include <linux/io.h> 32 33 #include <linux/resource_ext.h> 33 34 #include <uapi/linux/pci.h> ··· 1072 1071 int pci_select_bars(struct pci_dev *dev, unsigned long flags); 1073 1072 bool pci_device_is_present(struct pci_dev *pdev); 1074 1073 void pci_ignore_hotplug(struct pci_dev *dev); 1074 + 1075 + int __printf(6, 7) pci_request_irq(struct pci_dev *dev, unsigned int nr, 1076 + irq_handler_t handler, irq_handler_t thread_fn, void *dev_id, 1077 + const char *fmt, ...); 1078 + void pci_free_irq(struct pci_dev *dev, unsigned int nr, void *dev_id); 1075 1079 1076 1080 /* ROM control related routines */ 1077 1081 int pci_enable_rom(struct pci_dev *pdev);