1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Support routines for initializing a PCI subsystem 4 * 5 * Extruded from code written by 6 * Dave Rusling (david.rusling@reo.mts.dec.com) 7 * David Mosberger (davidm@cs.arizona.edu) 8 * David Miller (davem@redhat.com) 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/pci.h> 13 #include <linux/errno.h> 14 #include <linux/ioport.h> 15 #include <linux/cache.h> 16 #include "pci.h" 17 18 void pci_assign_irq(struct pci_dev *dev) 19 { 20 u8 pin; 21 u8 slot = -1; 22 int irq = 0; 23 struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus); 24 25 if (!(hbrg->map_irq)) { 26 pci_dbg(dev, "runtime IRQ mapping not provided by arch\n"); 27 return; 28 } 29 30 /* 31 * If this device is not on the primary bus, we need to figure out 32 * which interrupt pin it will come in on. We know which slot it 33 * will come in on because that slot is where the bridge is. Each 34 * time the interrupt line passes through a PCI-PCI bridge we must 35 * apply the swizzle function. 36 */ 37 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); 38 /* Cope with illegal. */ 39 if (pin > 4) 40 pin = 1; 41 42 if (pin) { 43 /* Follow the chain of bridges, swizzling as we go. */ 44 if (hbrg->swizzle_irq) 45 slot = (*(hbrg->swizzle_irq))(dev, &pin); 46 47 /* 48 * If a swizzling function is not used, map_irq() must 49 * ignore slot. 50 */ 51 irq = (*(hbrg->map_irq))(dev, slot, pin); 52 if (irq == -1) 53 irq = 0; 54 } 55 dev->irq = irq; 56 57 pci_dbg(dev, "assign IRQ: got %d\n", dev->irq); 58 59 /* 60 * Always tell the device, so the driver knows what is the real IRQ 61 * to use; the device does not use it. 62 */ 63 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); 64 } 65