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

PCI: xilinx: Unify INTx & MSI interrupt decode

The INTx & MSI interrupt decode paths duplicated a fair bit of common
functionality. They also strictly handled interrupts in order of INTx then
MSI, so if both types of interrupt were to be asserted simultaneously and
the MSI interrupt were first in the FIFO then the INTx code would read it &
ignore it before the MSI code then had to read it again, wasting the
original FIFO read.

Unify the INTx & MSI decode in order to reduce that duplication & allow a
single FIFO read to be performed for each interrupt regardless of its type.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: Bharat Kumar Gogada <bharatku@xilinx.com>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: Ravikiran Gummaluri <rgummal@xilinx.com>

authored by

Paul Burton and committed by
Bjorn Helgaas
d0b5dda6 b8550f11

+15 -33
+15 -33
drivers/pci/host/pcie-xilinx.c
··· 385 385 { 386 386 struct xilinx_pcie_port *port = (struct xilinx_pcie_port *)data; 387 387 struct device *dev = port->dev; 388 - u32 val, mask, status, msi_data; 388 + u32 val, mask, status; 389 389 390 390 /* Read interrupt decode and mask registers */ 391 391 val = pcie_read(port, XILINX_PCIE_REG_IDR); ··· 425 425 xilinx_pcie_clear_err_interrupts(port); 426 426 } 427 427 428 - if (status & XILINX_PCIE_INTR_INTX) { 429 - /* INTx interrupt received */ 428 + if (status & (XILINX_PCIE_INTR_INTX | XILINX_PCIE_INTR_MSI)) { 430 429 val = pcie_read(port, XILINX_PCIE_REG_RPIFR1); 431 430 432 431 /* Check whether interrupt valid */ ··· 434 435 goto error; 435 436 } 436 437 437 - if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) { 438 - /* Clear interrupt FIFO register 1 */ 439 - pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK, 440 - XILINX_PCIE_REG_RPIFR1); 441 - 442 - /* Handle INTx Interrupt */ 438 + /* Decode the IRQ number */ 439 + if (val & XILINX_PCIE_RPIFR1_MSI_INTR) { 440 + val = pcie_read(port, XILINX_PCIE_REG_RPIFR2) & 441 + XILINX_PCIE_RPIFR2_MSG_DATA; 442 + } else { 443 443 val = (val & XILINX_PCIE_RPIFR1_INTR_MASK) >> 444 444 XILINX_PCIE_RPIFR1_INTR_SHIFT; 445 - generic_handle_irq(irq_find_mapping(port->leg_domain, 446 - val)); 447 - } 448 - } 449 - 450 - if (status & XILINX_PCIE_INTR_MSI) { 451 - /* MSI Interrupt */ 452 - val = pcie_read(port, XILINX_PCIE_REG_RPIFR1); 453 - 454 - if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) { 455 - dev_warn(dev, "RP Intr FIFO1 read error\n"); 456 - goto error; 445 + val = irq_find_mapping(port->leg_domain, val); 457 446 } 458 447 459 - if (val & XILINX_PCIE_RPIFR1_MSI_INTR) { 460 - msi_data = pcie_read(port, XILINX_PCIE_REG_RPIFR2) & 461 - XILINX_PCIE_RPIFR2_MSG_DATA; 448 + /* Clear interrupt FIFO register 1 */ 449 + pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK, 450 + XILINX_PCIE_REG_RPIFR1); 462 451 463 - /* Clear interrupt FIFO register 1 */ 464 - pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK, 465 - XILINX_PCIE_REG_RPIFR1); 466 - 467 - if (IS_ENABLED(CONFIG_PCI_MSI)) { 468 - /* Handle MSI Interrupt */ 469 - generic_handle_irq(msi_data); 470 - } 471 - } 452 + /* Handle the interrupt */ 453 + if (IS_ENABLED(CONFIG_PCI_MSI) || 454 + !(val & XILINX_PCIE_RPIFR1_MSI_INTR)) 455 + generic_handle_irq(val); 472 456 } 473 457 474 458 if (status & XILINX_PCIE_INTR_SLV_UNSUPP)