Skip to content

Commit 0d58e6c

Browse files
paulburtonbjorn-helgaas
authored andcommitted
PCI: Add pci_irqd_intx_xlate()
Legacy PCI INTx interrupts are represented in the PCI_INTERRUPT_PIN register using the range 1-4, which matches our enum pci_interrupt_pin. This is however not ideal for an IRQ domain, where with 4 interrupts we would ideally have a domain of size 4 & hwirq numbers in the range 0-3. Different PCI host controller drivers have handled this in different ways. Of those under drivers/pci/ which register an INTx IRQ domain, we have: - pcie-altera uses the range 1-4 in device trees and an IRQ domain of size 5 to cover that range, with entry 0 wasted. - pcie-xilinx & pcie-xilinx-nwl use the range 1-4 in device trees but register an IRQ domain of size 4, which doesn't cover the hwirq=4/INTD case leading to that interrupt being broken. - pci-ftpci100 & pci-aardvark use the range 0-3 in both device trees & as hwirq numbering in the driver & IRQ domain. In order to introduce some level of consistency in at least the hwirq numbering used by the drivers & IRQ domains, this patch introduces a new pci_irqd_intx_xlate() helper function which drivers using the 1-4 range in device trees can assign as the xlate callback for their INTx IRQ domain. This translates the 1-4 range into a 0-3 range, allowing us to use an IRQ domain of size 4 & avoid a wasted entry. Further patches will make use of this in drivers to allow them to use an IRQ domain of size 4 for legacy INTx interrupts without breaking INTD. Signed-off-by: Paul Burton <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]>
1 parent b352baf commit 0d58e6c

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

include/linux/pci.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,38 @@ pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
14161416
NULL);
14171417
}
14181418

1419+
/**
1420+
* pci_irqd_intx_xlate() - Translate PCI INTx value to an IRQ domain hwirq
1421+
* @d: the INTx IRQ domain
1422+
* @node: the DT node for the device whose interrupt we're translating
1423+
* @intspec: the interrupt specifier data from the DT
1424+
* @intsize: the number of entries in @intspec
1425+
* @out_hwirq: pointer at which to write the hwirq number
1426+
* @out_type: pointer at which to write the interrupt type
1427+
*
1428+
* Translate a PCI INTx interrupt number from device tree in the range 1-4, as
1429+
* stored in the standard PCI_INTERRUPT_PIN register, to a value in the range
1430+
* 0-3 suitable for use in a 4 entry IRQ domain. That is, subtract one from the
1431+
* INTx value to obtain the hwirq number.
1432+
*
1433+
* Returns 0 on success, or -EINVAL if the interrupt specifier is out of range.
1434+
*/
1435+
static inline int pci_irqd_intx_xlate(struct irq_domain *d,
1436+
struct device_node *node,
1437+
const u32 *intspec,
1438+
unsigned int intsize,
1439+
unsigned long *out_hwirq,
1440+
unsigned int *out_type)
1441+
{
1442+
const u32 intx = intspec[0];
1443+
1444+
if (intx < PCI_INTERRUPT_INTA || intx > PCI_INTERRUPT_INTD)
1445+
return -EINVAL;
1446+
1447+
*out_hwirq = intx - PCI_INTERRUPT_INTA;
1448+
return 0;
1449+
}
1450+
14191451
#ifdef CONFIG_PCIEPORTBUS
14201452
extern bool pcie_ports_disabled;
14211453
extern bool pcie_ports_auto;

0 commit comments

Comments
 (0)