Author: jhibbits
Date: Sun Jan  3 15:24:57 2016
New Revision: 293106
URL: https://svnweb.freebsd.org/changeset/base/293106

Log:
  Add error interrupt handler for Freescale PCI errors
  
  This eliminates a 'interrupt storm' warning spam with the P5020.
  
  Obtained from:        Semihalf

Modified:
  head/sys/powerpc/mpc85xx/pci_mpc85xx.c

Modified: head/sys/powerpc/mpc85xx/pci_mpc85xx.c
==============================================================================
--- head/sys/powerpc/mpc85xx/pci_mpc85xx.c      Sun Jan  3 14:46:19 2016        
(r293105)
+++ head/sys/powerpc/mpc85xx/pci_mpc85xx.c      Sun Jan  3 15:24:57 2016        
(r293106)
@@ -94,6 +94,29 @@ __FBSDID("$FreeBSD$");
 #define        REG_PEX_ERR_DR  0x0e00
 #define        REG_PEX_ERR_EN  0x0e08
 
+#define        REG_PEX_ERR_DR          0x0e00
+#define        REG_PEX_ERR_DR_ME       0x80000000
+#define        REG_PEX_ERR_DR_PCT      0x800000
+#define        REG_PEX_ERR_DR_PAT      0x400000
+#define        REG_PEX_ERR_DR_PCAC     0x200000
+#define        REG_PEX_ERR_DR_PNM      0x100000
+#define        REG_PEX_ERR_DR_CDNSC    0x80000
+#define        REG_PEX_ERR_DR_CRSNC    0x40000
+#define        REG_PEX_ERR_DR_ICCA     0x20000
+#define        REG_PEX_ERR_DR_IACA     0x10000
+#define        REG_PEX_ERR_DR_CRST     0x8000
+#define        REG_PEX_ERR_DR_MIS      0x4000
+#define        REG_PEX_ERR_DR_IOIS     0x2000
+#define        REG_PEX_ERR_DR_CIS      0x1000
+#define        REG_PEX_ERR_DR_CIEP     0x800
+#define        REG_PEX_ERR_DR_IOIEP    0x400
+#define        REG_PEX_ERR_DR_OAC      0x200
+#define        REG_PEX_ERR_DR_IOIA     0x100
+#define        REG_PEX_ERR_DR_IMBA     0x80
+#define        REG_PEX_ERR_DR_IIOBA    0x40
+#define        REG_PEX_ERR_DR_LDDE     0x20
+#define        REG_PEX_ERR_EN          0x0e08
+
 #define PCIR_LTSSM     0x404
 #define LTSSM_STAT_L0  0x16
 
@@ -113,6 +136,9 @@ struct fsl_pcib_softc {
        bus_space_tag_t sc_bst;
        int             sc_rid;
 
+       struct resource *sc_irq_res;
+       void            *sc_ih;
+
        int             sc_busnr;
        int             sc_pcie;
        uint8_t         sc_pcie_capreg;         /* PCI-E Capability Reg Set */
@@ -122,6 +148,34 @@ struct fsl_pcib_softc {
        int             sc_devfn_via_ide;
 };
 
+struct fsl_pcib_err_dr {
+       const char      *msg;
+       uint32_t        err_dr_mask;
+};
+
+static const struct fsl_pcib_err_dr pci_err[] = {
+       {"ME",          REG_PEX_ERR_DR_ME},
+       {"PCT",         REG_PEX_ERR_DR_PCT},
+       {"PAT",         REG_PEX_ERR_DR_PAT},
+       {"PCAC",        REG_PEX_ERR_DR_PCAC},
+       {"PNM",         REG_PEX_ERR_DR_PNM},
+       {"CDNSC",       REG_PEX_ERR_DR_CDNSC},
+       {"CRSNC",       REG_PEX_ERR_DR_CRSNC},
+       {"ICCA",        REG_PEX_ERR_DR_ICCA},
+       {"IACA",        REG_PEX_ERR_DR_IACA},
+       {"CRST",        REG_PEX_ERR_DR_CRST},
+       {"MIS",         REG_PEX_ERR_DR_MIS},
+       {"IOIS",        REG_PEX_ERR_DR_IOIS},
+       {"CIS",         REG_PEX_ERR_DR_CIS},
+       {"CIEP",        REG_PEX_ERR_DR_CIEP},
+       {"IOIEP",       REG_PEX_ERR_DR_IOIEP},
+       {"OAC",         REG_PEX_ERR_DR_OAC},
+       {"IOIA",        REG_PEX_ERR_DR_IOIA},
+       {"IMBA",        REG_PEX_ERR_DR_IMBA},
+       {"IIOBA",       REG_PEX_ERR_DR_IIOBA},
+       {"LDDE",        REG_PEX_ERR_DR_LDDE}
+};
+
 /* Local forward declerations. */
 static uint32_t fsl_pcib_cfgread(struct fsl_pcib_softc *, u_int, u_int, u_int,
     u_int, int);
@@ -173,6 +227,35 @@ DEFINE_CLASS_1(pcib, fsl_pcib_driver, fs
 DRIVER_MODULE(pcib, ofwbus, fsl_pcib_driver, fsl_pcib_devclass, 0, 0);
 
 static int
+fsl_pcib_err_intr(void *v)
+{
+       struct fsl_pcib_softc *sc;
+       device_t dev;
+       uint32_t err_reg, clear_reg;
+       uint8_t i;
+
+       dev = (device_t)v;
+       sc = device_get_softc(dev);
+
+       clear_reg = 0;
+       err_reg = bus_space_read_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR);
+
+       /* Check which one error occurred */
+       for (i = 0; i < sizeof(pci_err)/sizeof(struct fsl_pcib_err_dr); i++) {
+               if (err_reg & pci_err[i].err_dr_mask) {
+                       device_printf(dev, "PCI %d: report %s error\n",
+                           device_get_unit(dev), pci_err[i].msg);
+                       clear_reg |= pci_err[i].err_dr_mask;
+               }
+       }
+
+       /* Clear pending errors */
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR, clear_reg);
+
+       return (0);
+}
+
+static int
 fsl_pcib_probe(device_t dev)
 {
 
@@ -198,7 +281,7 @@ fsl_pcib_attach(device_t dev)
        struct fsl_pcib_softc *sc;
        phandle_t node;
        uint32_t cfgreg;
-       int maxslot, error;
+       int error, maxslot, rid;
        uint8_t ltssm, capptr;
 
        sc = device_get_softc(dev);
@@ -279,6 +362,34 @@ fsl_pcib_attach(device_t dev)
                }
        }
 
+       /* Allocate irq */
+       sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+           RF_ACTIVE | RF_SHAREABLE);
+       if (sc->sc_irq_res == NULL) {
+               error = fsl_pcib_detach(dev);
+               if (error != 0) {
+                       device_printf(dev,
+                           "Detach of the driver failed with error %d\n",
+                           error);
+               }
+               return (ENXIO);
+       }
+
+       /* Setup interrupt handler */
+       error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | 
INTR_MPSAFE,
+           NULL, (driver_intr_t *)fsl_pcib_err_intr, dev, &sc->sc_ih);
+       if (error != 0) {
+               device_printf(dev, "Could not setup irq, %d\n", error);
+               sc->sc_ih = NULL;
+               error = fsl_pcib_detach(dev);
+               if (error != 0) {
+                       device_printf(dev,
+                           "Detach of the driver failed with error %d\n",
+                           error);
+               }
+               return (ENXIO);
+       }
+
        fsl_pcib_err_init(dev);
 
        return (ofw_pci_attach(dev));
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to