060-pcie_abort.patch 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. --- a/arch/arm/mach-cns3xxx/pcie.c
  2. +++ b/arch/arm/mach-cns3xxx/pcie.c
  3. @@ -86,6 +86,79 @@ static void __iomem *cns3xxx_pci_map_bus
  4. return base + (where & 0xffc) + (devfn << 12);
  5. }
  6. +static inline int check_master_abort(struct pci_bus *bus, unsigned int devfn, int where)
  7. +{
  8. + struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus);
  9. +
  10. + /* check PCI-compatible status register after access */
  11. + if (cnspci->linked) {
  12. + void __iomem *host_base;
  13. + u32 sreg, ereg;
  14. +
  15. + host_base = (void __iomem *) 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. + pci_domain_nr(bus), 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. @@ -95,6 +168,11 @@ static int cns3xxx_pci_read_config(struc
  83. ret = pci_generic_config_read32(bus, devfn, where, size, val);
  84. + if (check_master_abort(bus, devfn, where)) {
  85. + 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);
  86. + return PCIBIOS_DEVICE_NOT_FOUND;
  87. + }
  88. +
  89. if (ret == PCIBIOS_SUCCESSFUL && !bus->number && !devfn &&
  90. (where & 0xffc) == PCI_CLASS_REVISION)
  91. /*
  92. @@ -257,8 +335,14 @@ static void __init cns3xxx_pcie_hw_init(
  93. static int cns3xxx_pcie_abort_handler(unsigned long addr, unsigned int fsr,
  94. struct pt_regs *regs)
  95. {
  96. +#if 0
  97. +/* R14_ABORT = PC+4 for XSCALE but not ARM11MPCORE
  98. + * ignore imprecise aborts and use PCI-compatible Status register to
  99. + * determine errors instead
  100. + */
  101. if (fsr & (1 << 10))
  102. regs->ARM_pc += 4;
  103. +#endif
  104. return 0;
  105. }