On Sun, Nov 28, 2010 at 05:38:28PM +0100, Markus Bergkvist wrote:
> It sure helped with the panic. Now it get unresponsive for about 2
> min then I get the print-out below, all at once and then it
> unfreezes.

try this then, it tries to figure out if the device has gone
out from under us

a dmesg would be interesting to see how your interrupt lines
are mapped

Index: if_bge.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bge.c,v
retrieving revision 1.303
diff -u -p -r1.303 if_bge.c
--- if_bge.c    20 Sep 2010 07:40:38 -0000      1.303
+++ if_bge.c    28 Nov 2010 22:36:19 -0000
@@ -127,10 +127,12 @@
 const struct bge_revision * bge_lookup_rev(u_int32_t);
 int bge_probe(struct device *, void *, void *);
 void bge_attach(struct device *, struct device *, void *);
+int bge_detach(struct device *, int);
 int bge_activate(struct device *, int);
 
 struct cfattach bge_ca = {
-       sizeof(struct bge_softc), bge_probe, bge_attach, NULL, bge_activate
+       sizeof(struct bge_softc), bge_probe, bge_attach, bge_detach,
+       bge_activate
 };
 
 struct cfdriver bge_cd = {
@@ -590,6 +592,9 @@ bge_miibus_readreg(struct device *dev, i
        u_int32_t val, autopoll;
        int i;
 
+       if (sc->sc_dying)
+               return (0);
+
        /*
         * Broadcom's own driver always assumes the internal
         * PHY is at GMII address 1. On some chips, the PHY responds
@@ -649,6 +654,9 @@ bge_miibus_writereg(struct device *dev, 
        u_int32_t autopoll;
        int i;
 
+       if (sc->sc_dying)
+               return;
+
        /* Reading with autopolling on may trigger PCI errors */
        autopoll = CSR_READ_4(sc, BGE_MI_MODE);
        if (autopoll & BGE_MIMODE_AUTOPOLL) {
@@ -1797,7 +1805,6 @@ bge_attach(struct device *parent, struct
        pcireg_t                pm_ctl, memtype, subid;
        pci_intr_handle_t       ih;
        const char              *intrstr = NULL;
-       bus_size_t              size;
        bus_dma_segment_t       seg;
        int                     rseg, gotenaddr = 0;
        u_int32_t               hwcfg = 0;
@@ -1821,7 +1828,7 @@ bge_attach(struct device *parent, struct
        DPRINTFN(5, ("pci_mapreg_map\n"));
        memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BGE_PCI_BAR0);
        if (pci_mapreg_map(pa, BGE_PCI_BAR0, memtype, 0, &sc->bge_btag,
-           &sc->bge_bhandle, NULL, &size, 0)) {
+           &sc->bge_bhandle, NULL, &sc->bge_size, 0)) {
                printf(": can't find mem space\n");
                return;
        }
@@ -2215,6 +2222,7 @@ bge_attach(struct device *parent, struct
                printf("\n");
                goto fail_5;
        }
+       sc->bge_pc = pa->pa_pc;
 
        /*
         * A Broadcom chip was detected. Inform the world.
@@ -2280,7 +2288,31 @@ fail_2:
        bus_dmamem_free(sc->bge_dmatag, &seg, rseg);
 
 fail_1:
-       bus_space_unmap(sc->bge_btag, sc->bge_bhandle, size);
+       bus_space_unmap(sc->bge_btag, sc->bge_bhandle, sc->bge_size);
+}
+
+int
+bge_detach(struct device *self, int flags)
+{
+       struct bge_softc *sc = (struct bge_softc *)self;
+       struct ifnet *ifp = &sc->arpcom.ac_if;
+
+       pci_intr_disestablish(sc->bge_pc, sc->bge_intrhand);
+
+       bge_stop(sc);
+
+       /* Detach all PHYs */
+       mii_detach(&sc->bge_mii, MII_PHY_ANY, MII_OFFSET_ANY);
+ 
+       /* Delete any remaining media. */
+       ifmedia_delete_instance(&sc->bge_mii.mii_media, IFM_INST_ANY);
+
+       ether_ifdetach(ifp);
+       if_detach(ifp);
+
+       bus_space_unmap(sc->bge_btag, sc->bge_bhandle, sc->bge_size);
+
+       return (0);
 }
 
 int
@@ -2733,7 +2765,7 @@ bge_intr(void *xsc)
 {
        struct bge_softc *sc;
        struct ifnet *ifp;
-       u_int32_t statusword;
+       u_int32_t statusword, pcistate;
 
        sc = xsc;
        ifp = &sc->arpcom.ac_if;
@@ -2746,9 +2778,19 @@ bge_intr(void *xsc)
 
        /* read status word from status block */
        statusword = sc->bge_rdata->bge_status_block.bge_status;
+       pcistate = CSR_READ_4(sc, BGE_PCI_PCISTATE);
+
+       /*
+        * This bit is self clearing, if set the device has
+        * likely disappeared
+        */
+       if (pcistate & BGE_PCISTATE_FORCE_RESET) {
+               sc->sc_dying = 1;
+               return (0);
+       }
 
        if ((statusword & BGE_STATFLAG_UPDATED) ||
-           (!(CSR_READ_4(sc, BGE_PCI_PCISTATE) & 
BGE_PCISTATE_INTR_NOT_ACTIVE))) {
+           (!(pcistate & BGE_PCISTATE_INTR_NOT_ACTIVE))) {
 
                /* Ack interrupt and stop others from occurring. */
                bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
Index: if_bgereg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bgereg.h,v
retrieving revision 1.103
diff -u -p -r1.103 if_bgereg.h
--- if_bgereg.h 20 Sep 2010 07:40:38 -0000      1.103
+++ if_bgereg.h 28 Nov 2010 22:36:20 -0000
@@ -2578,7 +2578,9 @@ struct bge_softc {
        struct arpcom           arpcom;         /* interface info */
        bus_space_handle_t      bge_bhandle;
        bus_space_tag_t         bge_btag;
+       bus_size_t              bge_size;
        void                    *bge_intrhand;
+       int                     sc_dying;
        struct pci_attach_args  bge_pa;
        struct mii_data         bge_mii;
        struct ifmedia          bge_ifmedia;    /* media info */
@@ -2611,6 +2613,7 @@ struct bge_softc {
 #define BGE_5700_FAMILY                0x02000000
 
        bus_dma_tag_t           bge_dmatag;
+       pci_chipset_tag_t       bge_pc;
        u_int32_t               bge_chipid;
        struct bge_ring_data    *bge_rdata;     /* rings */
        struct bge_chain_data   bge_cdata;      /* mbufs */

Reply via email to