[cns3xxx]: clean up PCI bus topology
[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