/branches/18.06.1/target/linux/cns3xxx/patches-4.14/060-pcie_abort.patch |
@@ -0,0 +1,109 @@ |
--- a/arch/arm/mach-cns3xxx/pcie.c |
+++ b/arch/arm/mach-cns3xxx/pcie.c |
@@ -86,6 +86,79 @@ static void __iomem *cns3xxx_pci_map_bus |
return base + where + (devfn << 12); |
} |
|
+static inline int check_master_abort(struct pci_bus *bus, unsigned int devfn, int where) |
+{ |
+ struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus); |
+ |
+ /* check PCI-compatible status register after access */ |
+ if (cnspci->linked) { |
+ void __iomem *host_base; |
+ u32 sreg, ereg; |
+ |
+ host_base = (void __iomem *) cnspci->cfg_bases[CNS3XXX_HOST_TYPE].virtual; |
+ sreg = __raw_readw(host_base + 0x6) & 0xF900; |
+ ereg = __raw_readl(host_base + 0x104); // Uncorrectable Error Status Reg |
+ |
+ if (sreg | ereg) { |
+ /* SREG: |
+ * BIT15 - Detected Parity Error |
+ * BIT14 - Signaled System Error |
+ * BIT13 - Received Master Abort |
+ * BIT12 - Received Target Abort |
+ * BIT11 - Signaled Target Abort |
+ * BIT08 - Master Data Parity Error |
+ * |
+ * EREG: |
+ * BIT20 - Unsupported Request |
+ * BIT19 - ECRC |
+ * BIT18 - Malformed TLP |
+ * BIT17 - Receiver Overflow |
+ * BIT16 - Unexpected Completion |
+ * BIT15 - Completer Abort |
+ * BIT14 - Completion Timeout |
+ * BIT13 - Flow Control Protocol Error |
+ * BIT12 - Poisoned TLP |
+ * BIT04 - Data Link Protocol Error |
+ * |
+ * TODO: see Documentation/pci-error-recovery.txt |
+ * implement error_detected handler |
+ */ |
+/* |
+ printk("pci error: %04d:%02x:%02x.%02x sreg=0x%04x ereg=0x%08x", pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), sreg, ereg); |
+ if (sreg & BIT(15)) printk(" <PERR"); |
+ if (sreg & BIT(14)) printk(" >SERR"); |
+ if (sreg & BIT(13)) printk(" <MABRT"); |
+ if (sreg & BIT(12)) printk(" <TABRT"); |
+ if (sreg & BIT(11)) printk(" >TABRT"); |
+ if (sreg & BIT( 8)) printk(" MPERR"); |
+ |
+ if (ereg & BIT(20)) printk(" Unsup"); |
+ if (ereg & BIT(19)) printk(" ECRC"); |
+ if (ereg & BIT(18)) printk(" MTLP"); |
+ if (ereg & BIT(17)) printk(" OFLOW"); |
+ if (ereg & BIT(16)) printk(" Unex"); |
+ if (ereg & BIT(15)) printk(" ABRT"); |
+ if (ereg & BIT(14)) printk(" COMPTO"); |
+ if (ereg & BIT(13)) printk(" FLOW"); |
+ if (ereg & BIT(12)) printk(" PTLP"); |
+ if (ereg & BIT( 4)) printk(" DLINK"); |
+ printk("\n"); |
+*/ |
+ pr_debug("%s failed port%d sreg=0x%04x\n", __func__, |
+ pci_domain_nr(bus), sreg); |
+ |
+ /* make sure the status bits are reset */ |
+ __raw_writew(sreg, host_base + 6); |
+ __raw_writel(ereg, host_base + 0x104); |
+ return 1; |
+ } |
+ } |
+ else |
+ return 1; |
+ |
+ return 0; |
+} |
+ |
static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn, |
int where, int size, u32 *val) |
{ |
@@ -95,6 +168,11 @@ static int cns3xxx_pci_read_config(struc |
|
ret = pci_generic_config_read(bus, devfn, where, size, val); |
|
+ if (check_master_abort(bus, devfn, where)) { |
+ printk(KERN_ERR "pci error: %04d:%02x:%02x.%02x %02x(%d)= master_abort on read\n", pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size); |
+ return PCIBIOS_DEVICE_NOT_FOUND; |
+ } |
+ |
if (ret == PCIBIOS_SUCCESSFUL && !bus->number && !devfn && |
(where & 0xffc) == PCI_CLASS_REVISION) |
/* |
@@ -257,8 +335,14 @@ static void __init cns3xxx_pcie_hw_init( |
static int cns3xxx_pcie_abort_handler(unsigned long addr, unsigned int fsr, |
struct pt_regs *regs) |
{ |
+#if 0 |
+/* R14_ABORT = PC+4 for XSCALE but not ARM11MPCORE |
+ * ignore imprecise aborts and use PCI-compatible Status register to |
+ * determine errors instead |
+ */ |
if (fsr & (1 << 10)) |
regs->ARM_pc += 4; |
+#endif |
return 0; |
} |
|