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