123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- --- a/arch/arm/mach-cns3xxx/pcie.c
- +++ b/arch/arm/mach-cns3xxx/pcie.c
- @@ -88,6 +88,79 @@ static void __iomem *cns3xxx_pci_cfg_bas
- return base + (where & 0xffc) + (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__,
- + cnspci->hw_pci.domain, 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)
- {
- @@ -104,6 +177,11 @@ static int cns3xxx_pci_read_config(struc
-
- v = __raw_readl(base);
-
- + 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 (bus->number == 0 && devfn == 0 &&
- (where & 0xffc) == PCI_CLASS_REVISION) {
- /*
- @@ -133,11 +211,19 @@ static int cns3xxx_pci_write_config(stru
- return PCIBIOS_SUCCESSFUL;
-
- v = __raw_readl(base);
- + if (check_master_abort(bus, devfn, where)) {
- + printk(KERN_ERR "pci error: %04d:%02x:%02x.%02x %02x(%d)=0x%08x master_abort on read\n", pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
- + return PCIBIOS_DEVICE_NOT_FOUND;
- + }
-
- v &= ~(mask << shift);
- v |= (val & mask) << shift;
-
- __raw_writel(v, base);
- + if (check_master_abort(bus, devfn, where)) {
- + printk(KERN_ERR "pci error: %04d:%02x:%02x.%02x %02x(%d)=0x%08x master_abort on write\n", pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
- + return PCIBIOS_DEVICE_NOT_FOUND;
- + }
-
- return PCIBIOS_SUCCESSFUL;
- }
- @@ -315,8 +401,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;
- }
-
|