So made some progress on this but I think there is a kernel issue with the TX1
The pcie interrupt handler in the TX1 kernel (3.10.96) is shown below
static irqreturn_t tegra_pcie_isr(int irq, void *arg)
{
const char *err_msg[] = {
"Unknown",
"AXI slave error",
"AXI decode error",
"Target abort",
"Master abort",
"Invalid write",
"",
"Response decoding error",
"AXI response decoding error",
"Transcation timeout",
"",
"Slot Clock request change",
"TMS Clock clamp change",
"TMS power down",
"Peer to Peer error",
};
struct tegra_pcie *pcie = arg;
u32 code, signature;
PR_FUNC_LINE;
code = afi_readl(pcie, AFI_INTR_CODE) & AFI_INTR_CODE_MASK;
signature = afi_readl(pcie, AFI_INTR_SIGNATURE);
if (code == AFI_INTR_LEGACY)
handle_sb_intr(pcie);
afi_writel(pcie, 0, AFI_INTR_CODE);
if (code >= ARRAY_SIZE(err_msg))
code = 0;
/*
* do not pollute kernel log with master abort reports since they
* happen a lot during enumeration
*/
if (code == AFI_INTR_MASTER_ABORT)
pr_debug("PCIE: %s, signature: %08x\n",
err_msg[code], signature);
else if ((code != AFI_INTR_LEGACY) && (code != AFI_INTR_PRSNT_SENSE))
dev_err(pcie->dev, "PCIE: %s, signature: %08x\n",
err_msg[code], signature);
return IRQ_HANDLED;
}
When an AFI_INTR_LEGACY interrupt is detected it calls the handle_sb_intr() method to handle sideband messages
static void handle_sb_intr(struct tegra_pcie *pcie)
{
u32 mesg;
PR_FUNC_LINE;
mesg = afi_readl(pcie, AFI_MSG_0);
printk(KERN_ERR "AFI_MSG 0x%08x\n",mesg);
if (mesg & AFI_MSG_INTX_MASK)
/* notify device isr for INTx messages from pcie devices */
dev_dbg(pcie->dev,
"Legacy INTx interrupt occurred %x\n", mesg);
else if (mesg & AFI_MSG_PM_PME_MASK) {
struct tegra_pcie_port *port, *tmp;
/* handle PME messages */
list_for_each_entry_safe(port, tmp, &pcie->ports, list)
if (port->index == (mesg & AFI_MSG_PM_PME0))
break;
mesg = rp_readl(port, NV_PCIE2_RP_RSR);
mesg |= NV_PCIE2_RP_RSR_PMESTAT;
rp_writel(port, mesg, NV_PCIE2_RP_RSR);
} else
afi_writel(pcie, mesg, AFI_MSG_0);
}
For a legacy interrupt this just outputs a dynamic debug message so it returns to the original handler.
The handler clears the interrupt but always returns IRQ_HANDLED. As far as I am aware this prevents any other registered interrupt handlers for this interrupt being actioned. As a result my handler which has to signal to the FPGA that the transfer is complete is never called thus the FPGA never deasserts the legacy interrupt and it is continually triggered causing the kernel to hang.
I notice in later versions of the Kernel e.g. 4.8 that the isr is as below:
static irqreturn_t tegra_pcie_isr(int irq, void *arg)
{
const char *err_msg[] = {
"Unknown",
"AXI slave error",
"AXI decode error",
"Target abort",
"Master abort",
"Invalid write",
"Legacy interrupt",
"Response decoding error",
"AXI response decoding error",
"Transaction timeout",
"Slot present pin change",
"Slot clock request change",
"TMS clock ramp change",
"TMS ready for power down",
"Peer2Peer error",
};
struct tegra_pcie *pcie = arg;
u32 code, signature;
code = afi_readl(pcie, AFI_INTR_CODE) & AFI_INTR_CODE_MASK;
signature = afi_readl(pcie, AFI_INTR_SIGNATURE);
afi_writel(pcie, 0, AFI_INTR_CODE);
if (code == AFI_INTR_LEGACY)
return IRQ_NONE;
if (code >= ARRAY_SIZE(err_msg))
code = 0;
/*
* do not pollute kernel log with master abort reports since they
* happen a lot during enumeration
*/
if (code == AFI_INTR_MASTER_ABORT)
dev_dbg(pcie->dev, "%s, signature: %08x\n", err_msg[code],
signature);
else
dev_err(pcie->dev, "%s, signature: %08x\n", err_msg[code],
signature);
if (code == AFI_INTR_TARGET_ABORT || code == AFI_INTR_MASTER_ABORT ||
code == AFI_INTR_FPCI_DECODE_ERROR) {
u32 fpci = afi_readl(pcie, AFI_UPPER_FPCI_ADDRESS) & 0xff;
u64 address = (u64)fpci << 32 | (signature & 0xfffffffc);
if (code == AFI_INTR_MASTER_ABORT)
dev_dbg(pcie->dev, " FPCI address: %10llx\n", address);
else
dev_err(pcie->dev, " FPCI address: %10llx\n", address);
}
return IRQ_HANDLED;
}
So for legacy interrupts IRQ_NONE is returned immediately after the status is cleared, which should allow the interrupt to propagate to my handler yes?
Any comments by you nvidia guys?
Robert