281 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * PCI IRQ handling code4 *5 * Copyright (c) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>6 * Copyright (C) 2017 Christoph Hellwig.7 */8 9#include <linux/device.h>10#include <linux/kernel.h>11#include <linux/errno.h>12#include <linux/export.h>13#include <linux/interrupt.h>14#include <linux/pci.h>15 16#include "pci.h"17 18/**19 * pci_request_irq - allocate an interrupt line for a PCI device20 * @dev: PCI device to operate on21 * @nr: device-relative interrupt vector index (0-based).22 * @handler: Function to be called when the IRQ occurs.23 * Primary handler for threaded interrupts.24 * If NULL and thread_fn != NULL the default primary handler is25 * installed.26 * @thread_fn: Function called from the IRQ handler thread27 * If NULL, no IRQ thread is created28 * @dev_id: Cookie passed back to the handler function29 * @fmt: Printf-like format string naming the handler30 *31 * This call allocates interrupt resources and enables the interrupt line and32 * IRQ handling. From the point this call is made @handler and @thread_fn may33 * be invoked. All interrupts requested using this function might be shared.34 *35 * @dev_id must not be NULL and must be globally unique.36 */37int pci_request_irq(struct pci_dev *dev, unsigned int nr, irq_handler_t handler,38 irq_handler_t thread_fn, void *dev_id, const char *fmt, ...)39{40 va_list ap;41 int ret;42 char *devname;43 unsigned long irqflags = IRQF_SHARED;44 45 if (!handler)46 irqflags |= IRQF_ONESHOT;47 48 va_start(ap, fmt);49 devname = kvasprintf(GFP_KERNEL, fmt, ap);50 va_end(ap);51 if (!devname)52 return -ENOMEM;53 54 ret = request_threaded_irq(pci_irq_vector(dev, nr), handler, thread_fn,55 irqflags, devname, dev_id);56 if (ret)57 kfree(devname);58 return ret;59}60EXPORT_SYMBOL(pci_request_irq);61 62/**63 * pci_free_irq - free an interrupt allocated with pci_request_irq64 * @dev: PCI device to operate on65 * @nr: device-relative interrupt vector index (0-based).66 * @dev_id: Device identity to free67 *68 * Remove an interrupt handler. The handler is removed and if the interrupt69 * line is no longer in use by any driver it is disabled. The caller must70 * ensure the interrupt is disabled on the device before calling this function.71 * The function does not return until any executing interrupts for this IRQ72 * have completed.73 *74 * This function must not be called from interrupt context.75 */76void pci_free_irq(struct pci_dev *dev, unsigned int nr, void *dev_id)77{78 kfree(free_irq(pci_irq_vector(dev, nr), dev_id));79}80EXPORT_SYMBOL(pci_free_irq);81 82/**83 * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge84 * @dev: the PCI device85 * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD)86 *87 * Perform INTx swizzling for a device behind one level of bridge. This is88 * required by section 9.1 of the PCI-to-PCI bridge specification for devices89 * behind bridges on add-in cards. For devices with ARI enabled, the slot90 * number is always 0 (see the Implementation Note in section 2.2.8.1 of91 * the PCI Express Base Specification, Revision 2.1)92 */93u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin)94{95 int slot;96 97 if (pci_ari_enabled(dev->bus))98 slot = 0;99 else100 slot = PCI_SLOT(dev->devfn);101 102 return (((pin - 1) + slot) % 4) + 1;103}104 105int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)106{107 u8 pin;108 109 pin = dev->pin;110 if (!pin)111 return -1;112 113 while (!pci_is_root_bus(dev->bus)) {114 pin = pci_swizzle_interrupt_pin(dev, pin);115 dev = dev->bus->self;116 }117 *bridge = dev;118 return pin;119}120 121/**122 * pci_common_swizzle - swizzle INTx all the way to root bridge123 * @dev: the PCI device124 * @pinp: pointer to the INTx pin value (1=INTA, 2=INTB, 3=INTD, 4=INTD)125 *126 * Perform INTx swizzling for a device. This traverses through all PCI-to-PCI127 * bridges all the way up to a PCI root bus.128 */129u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)130{131 u8 pin = *pinp;132 133 while (!pci_is_root_bus(dev->bus)) {134 pin = pci_swizzle_interrupt_pin(dev, pin);135 dev = dev->bus->self;136 }137 *pinp = pin;138 return PCI_SLOT(dev->devfn);139}140EXPORT_SYMBOL_GPL(pci_common_swizzle);141 142void pci_assign_irq(struct pci_dev *dev)143{144 u8 pin;145 u8 slot = -1;146 int irq = 0;147 struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);148 149 if (!(hbrg->map_irq)) {150 pci_dbg(dev, "runtime IRQ mapping not provided by arch\n");151 return;152 }153 154 /*155 * If this device is not on the primary bus, we need to figure out156 * which interrupt pin it will come in on. We know which slot it157 * will come in on because that slot is where the bridge is. Each158 * time the interrupt line passes through a PCI-PCI bridge we must159 * apply the swizzle function.160 */161 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);162 /* Cope with illegal. */163 if (pin > 4)164 pin = 1;165 166 if (pin) {167 /* Follow the chain of bridges, swizzling as we go. */168 if (hbrg->swizzle_irq)169 slot = (*(hbrg->swizzle_irq))(dev, &pin);170 171 /*172 * If a swizzling function is not used, map_irq() must173 * ignore slot.174 */175 irq = (*(hbrg->map_irq))(dev, slot, pin);176 if (irq == -1)177 irq = 0;178 }179 dev->irq = irq;180 181 pci_dbg(dev, "assign IRQ: got %d\n", dev->irq);182 183 /*184 * Always tell the device, so the driver knows what is the real IRQ185 * to use; the device does not use it.186 */187 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);188}189 190static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)191{192 struct pci_bus *bus = dev->bus;193 bool mask_updated = true;194 u32 cmd_status_dword;195 u16 origcmd, newcmd;196 unsigned long flags;197 bool irq_pending;198 199 /*200 * We do a single dword read to retrieve both command and status.201 * Document assumptions that make this possible.202 */203 BUILD_BUG_ON(PCI_COMMAND % 4);204 BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);205 206 raw_spin_lock_irqsave(&pci_lock, flags);207 208 bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword);209 210 irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT;211 212 /*213 * Check interrupt status register to see whether our device214 * triggered the interrupt (when masking) or the next IRQ is215 * already pending (when unmasking).216 */217 if (mask != irq_pending) {218 mask_updated = false;219 goto done;220 }221 222 origcmd = cmd_status_dword;223 newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE;224 if (mask)225 newcmd |= PCI_COMMAND_INTX_DISABLE;226 if (newcmd != origcmd)227 bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd);228 229done:230 raw_spin_unlock_irqrestore(&pci_lock, flags);231 232 return mask_updated;233}234 235/**236 * pci_check_and_mask_intx - mask INTx on pending interrupt237 * @dev: the PCI device to operate on238 *239 * Check if the device dev has its INTx line asserted, mask it and return240 * true in that case. False is returned if no interrupt was pending.241 */242bool pci_check_and_mask_intx(struct pci_dev *dev)243{244 return pci_check_and_set_intx_mask(dev, true);245}246EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);247 248/**249 * pci_check_and_unmask_intx - unmask INTx if no interrupt is pending250 * @dev: the PCI device to operate on251 *252 * Check if the device dev has its INTx line asserted, unmask it if not and253 * return true. False is returned and the mask remains active if there was254 * still an interrupt pending.255 */256bool pci_check_and_unmask_intx(struct pci_dev *dev)257{258 return pci_check_and_set_intx_mask(dev, false);259}260EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);261 262/**263 * pcibios_penalize_isa_irq - penalize an ISA IRQ264 * @irq: ISA IRQ to penalize265 * @active: IRQ active or not266 *267 * Permits the platform to provide architecture-specific functionality when268 * penalizing ISA IRQs. This is the default implementation. Architecture269 * implementations can override this.270 */271void __weak pcibios_penalize_isa_irq(int irq, int active) {}272 273int __weak pcibios_alloc_irq(struct pci_dev *dev)274{275 return 0;276}277 278void __weak pcibios_free_irq(struct pci_dev *dev)279{280}281