drivers/pcie: Use the generic arch-interface for allocating IRQs

PCIE now uses the new interface. And pcie_alloc_irq() is only made
available when CONFIG_PCIE_CONTROLLER is unset. So only for x86 atm.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2021-01-06 14:59:36 +01:00 committed by Carles Cufí
parent 88bac5d0b5
commit c1bc5db795
2 changed files with 14 additions and 62 deletions

View file

@ -216,87 +216,34 @@ bool pcie_probe_mbar(pcie_bdf_t bdf,
return pcie_get_mbar(bdf, reg - PCIE_CONF_BAR0, mbar);
}
/* The first bit is used to indicate whether the list of reserved interrupts
* have been initialized based on content stored in the irq_alloc linker
* section in ROM.
*/
#define IRQ_LIST_INITIALIZED 0
#ifndef CONFIG_MAX_IRQ_LINES
#warning TOFIX for non-x86
#define CONFIG_MAX_IRQ_LINES 0
#endif
static ATOMIC_DEFINE(irq_reserved, CONFIG_MAX_IRQ_LINES);
static unsigned int irq_alloc(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(irq_reserved); i++) {
unsigned int fz, irq;
while ((fz = find_lsb_set(~atomic_get(&irq_reserved[i])))) {
irq = (fz - 1) + (i * sizeof(atomic_val_t) * 8);
if (irq >= CONFIG_MAX_IRQ_LINES) {
break;
}
if (!atomic_test_and_set_bit(irq_reserved, irq)) {
return irq;
}
}
}
return PCIE_CONF_INTR_IRQ_NONE;
}
static bool irq_is_reserved(unsigned int irq)
{
return atomic_test_bit(irq_reserved, irq);
}
static void irq_init(void)
{
extern uint8_t __irq_alloc_start[];
extern uint8_t __irq_alloc_end[];
const uint8_t *irq;
for (irq = __irq_alloc_start; irq < __irq_alloc_end; irq++) {
__ASSERT_NO_MSG(*irq < CONFIG_MAX_IRQ_LINES);
atomic_set_bit(irq_reserved, *irq);
}
}
#ifndef CONFIG_PCIE_CONTROLLER
unsigned int pcie_alloc_irq(pcie_bdf_t bdf)
{
unsigned int irq;
uint32_t data;
if (!atomic_test_and_set_bit(irq_reserved, IRQ_LIST_INITIALIZED)) {
irq_init();
}
data = pcie_conf_read(bdf, PCIE_CONF_INTR);
irq = PCIE_CONF_INTR_IRQ(data);
if (irq == PCIE_CONF_INTR_IRQ_NONE || irq >= CONFIG_MAX_IRQ_LINES ||
irq_is_reserved(irq)) {
irq = irq_alloc();
if (irq == PCIE_CONF_INTR_IRQ_NONE) {
return irq;
if (irq == PCIE_CONF_INTR_IRQ_NONE ||
irq >= CONFIG_MAX_IRQ_LINES ||
arch_irq_is_used(irq)) {
irq = arch_irq_allocate();
if (irq == UINT_MAX) {
return PCIE_CONF_INTR_IRQ_NONE;
}
data &= ~0xffU;
data |= irq;
pcie_conf_write(bdf, PCIE_CONF_INTR, data);
} else {
atomic_set_bit(irq_reserved, irq);
arch_irq_set_used(irq);
}
return irq;
}
#endif /* CONFIG_PCIE_CONTROLLER */
unsigned int pcie_get_irq(pcie_bdf_t bdf)
{

View file

@ -124,17 +124,22 @@ extern bool pcie_probe_mbar(pcie_bdf_t bdf,
*/
extern void pcie_set_cmd(pcie_bdf_t bdf, uint32_t bits, bool on);
#ifndef CONFIG_PCIE_CONTROLLER
/**
* @brief Allocate an IRQ for an endpoint.
*
* This function first checks the IRQ register and if it contains a valid
* value this is returned. If the register does not contain a valid value
* allocation of a new one is attempted.
* Such function is only exposed if CONFIG_PCIE_CONTROLLER is unset.
* It is thus available where architecture tied dynamic IRQ allocation for
* PCIe device makes sense.
*
* @param bdf the PCI(e) endpoint
* @return the IRQ number, or PCIE_CONF_INTR_IRQ_NONE if allocation failed.
*/
extern unsigned int pcie_alloc_irq(pcie_bdf_t bdf);
#endif /* CONFIG_PCIE_CONTROLLER */
/**
* @brief Return the IRQ assigned by the firmware/board to an endpoint.