reorder, rename and refresh patches
[openwrt/openwrt.git] / target / linux / cns3xxx / patches-3.3 / 060-pcie_abort.patch
1 --- a/arch/arm/mach-cns3xxx/pcie.c
2 +++ b/arch/arm/mach-cns3xxx/pcie.c
3 @@ -92,6 +92,78 @@ static void __iomem *cns3xxx_pci_cfg_bas
4 return base + offset;
5 }
6
7 +static inline int check_master_abort(struct pci_bus *bus, unsigned int devfn, int where)
8 +{
9 + struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus);
10 +
11 + /* check PCI-compatible status register after access */
12 + if (cnspci->linked) {
13 + u32 host_base, sreg, ereg;
14 +
15 + host_base = cnspci->cfg_bases[CNS3XXX_HOST_TYPE].virtual;
16 + sreg = __raw_readw(host_base + 0x6) & 0xF900;
17 + ereg = __raw_readl(host_base + 0x104); // Uncorrectable Error Status Reg
18 +
19 + if (sreg | ereg) {
20 + /* SREG:
21 + * BIT15 - Detected Parity Error
22 + * BIT14 - Signaled System Error
23 + * BIT13 - Received Master Abort
24 + * BIT12 - Received Target Abort
25 + * BIT11 - Signaled Target Abort
26 + * BIT08 - Master Data Parity Error
27 + *
28 + * EREG:
29 + * BIT20 - Unsupported Request
30 + * BIT19 - ECRC
31 + * BIT18 - Malformed TLP
32 + * BIT17 - Receiver Overflow
33 + * BIT16 - Unexpected Completion
34 + * BIT15 - Completer Abort
35 + * BIT14 - Completion Timeout
36 + * BIT13 - Flow Control Protocol Error
37 + * BIT12 - Poisoned TLP
38 + * BIT04 - Data Link Protocol Error
39 + *
40 + * TODO: see Documentation/pci-error-recovery.txt
41 + * implement error_detected handler
42 + */
43 +/*
44 + 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);
45 + if (sreg & BIT(15)) printk(" <PERR");
46 + if (sreg & BIT(14)) printk(" >SERR");
47 + if (sreg & BIT(13)) printk(" <MABRT");
48 + if (sreg & BIT(12)) printk(" <TABRT");
49 + if (sreg & BIT(11)) printk(" >TABRT");
50 + if (sreg & BIT( 8)) printk(" MPERR");
51 +
52 + if (ereg & BIT(20)) printk(" Unsup");
53 + if (ereg & BIT(19)) printk(" ECRC");
54 + if (ereg & BIT(18)) printk(" MTLP");
55 + if (ereg & BIT(17)) printk(" OFLOW");
56 + if (ereg & BIT(16)) printk(" Unex");
57 + if (ereg & BIT(15)) printk(" ABRT");
58 + if (ereg & BIT(14)) printk(" COMPTO");
59 + if (ereg & BIT(13)) printk(" FLOW");
60 + if (ereg & BIT(12)) printk(" PTLP");
61 + if (ereg & BIT( 4)) printk(" DLINK");
62 + printk("\n");
63 +*/
64 + pr_debug("%s failed port%d sreg=0x%04x\n", __func__,
65 + cnspci->hw_pci.domain, sreg);
66 +
67 + /* make sure the status bits are reset */
68 + __raw_writew(sreg, host_base + 6);
69 + __raw_writel(ereg, host_base + 0x104);
70 + return 1;
71 + }
72 + }
73 + else
74 + return 1;
75 +
76 + return 0;
77 +}
78 +
79 static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
80 int where, int size, u32 *val)
81 {
82 @@ -108,6 +180,11 @@ static int cns3xxx_pci_read_config(struc
83
84 v = __raw_readl(base);
85
86 + if (check_master_abort(bus, devfn, where)) {
87 + 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);
88 + return PCIBIOS_DEVICE_NOT_FOUND;
89 + }
90 +
91 if (bus->number == 0 && devfn == 0 &&
92 (where & 0xffc) == PCI_CLASS_REVISION) {
93 /*
94 @@ -137,11 +214,19 @@ static int cns3xxx_pci_write_config(stru
95 return PCIBIOS_SUCCESSFUL;
96
97 v = __raw_readl(base);
98 + if (check_master_abort(bus, devfn, where)) {
99 + 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);
100 + return PCIBIOS_DEVICE_NOT_FOUND;
101 + }
102
103 v &= ~(mask << shift);
104 v |= (val & mask) << shift;
105
106 __raw_writel(v, base);
107 + if (check_master_abort(bus, devfn, where)) {
108 + 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);
109 + return PCIBIOS_DEVICE_NOT_FOUND;
110 + }
111
112 return PCIBIOS_SUCCESSFUL;
113 }
114 @@ -360,8 +445,14 @@ static void __init cns3xxx_pcie_hw_init(
115 static int cns3xxx_pcie_abort_handler(unsigned long addr, unsigned int fsr,
116 struct pt_regs *regs)
117 {
118 +#if 0
119 +/* R14_ABORT = PC+4 for XSCALE but not ARM11MPCORE
120 + * ignore imprecise aborts and use PCI-compatible Status register to
121 + * determine errors instead
122 + */
123 if (fsr & (1 << 10))
124 regs->ARM_pc += 4;
125 +#endif
126 return 0;
127 }
128