On Tue, Mar 28, 2006 at 12:38:42PM -0800, Doug Ambrisko wrote:
> Oleg Bulyzhin writes:
> | On Tue, Mar 28, 2006 at 11:24:06AM -0600, Stephen P. Cravey wrote:
> | > Does anyone have chip documentation on the broadcom BGE chips? I'm 
> having an ongoing issue with IPMI that I'd really like to get resolved. The 
> issue seems to be that during the driver start sequence, a flag is getting 
> set in the chip that's disabling the IPMI passthrough that I need in order 
> for data destined for a second mac address on the interface to recieve 
> packets. Or, a flag that this process needs isn't getting set. Not sure 
> which, but I could really use some help here. 
> | > 
> | > Or should I ask the frequent committers to the driver directly?
> | > 
> | > Thank you.
> | > 
> | > PR:
> | > kern/79143
> | > kern/88741
> | > _______________________________________________
> | 
> | Could you please test attached patch (RELENG_6 version)? It's slightly 
> | modified version of Doug Ambrisko
> | ([EMAIL PROTECTED]) patch (original version didnt work for me:
> | bcm5721 @ hp proliant dl145g2 server).
> 
> I don't see it attached.  I'd like to see your changes and I'd like know
> of your plans about getting it in.
> 
> Thanks,
> 
> Doug A.

Oops... my fault. Should be attached now.

-- 
Oleg.

Index: if_bgereg.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/bge/if_bgereg.h,v
retrieving revision 1.36.2.4
diff -u -r1.36.2.4 if_bgereg.h
--- if_bgereg.h 5 Feb 2006 18:07:15 -0000       1.36.2.4
+++ if_bgereg.h 28 Mar 2006 20:18:15 -0000
@@ -74,6 +74,11 @@
 #define BGE_SOFTWARE_GENCOMM           0x00000B50
 #define BGE_SOFTWARE_GENCOMM_SIG       0x00000B54
 #define BGE_SOFTWARE_GENCOMM_NICCFG    0x00000B58
+#define BGE_SOFTWARE_GENCOMM_FW                0x00000B78
+#define    BGE_FW_DRV_ALIVE            0x00000001
+#define    BGE_FW_PAUSE                        0x00000002
+#define BGE_SOFTWARE_GENNCOMM_FW_LEN   0x00000B7C
+#define BGE_SOFTWARE_GENNCOMM_FW_DATA  0x00000B80
 #define BGE_SOFTWARE_GENCOMM_END       0x00000FFF
 #define BGE_UNMAPPED                   0x00001000
 #define BGE_UNMAPPED_END               0x00001FFF
@@ -1627,6 +1632,7 @@
 #define BGE_MODE_CTL                   0x6800
 #define BGE_MISC_CFG                   0x6804
 #define BGE_MISC_LOCAL_CTL             0x6808
+#define BGE_CPU_EVENT                  0x6810
 #define BGE_EE_ADDR                    0x6838
 #define BGE_EE_DATA                    0x683C
 #define BGE_EE_CTL                     0x6840
@@ -2009,6 +2015,7 @@
 #define BGE_HWCFG_VOLTAGE              0x00000003
 #define BGE_HWCFG_PHYLED_MODE          0x0000000C
 #define BGE_HWCFG_MEDIA                        0x00000030
+#define BGE_HWCFG_ASF                  0x00000080
 
 #define BGE_VOLTAGE_1POINT3            0x00000000
 #define BGE_VOLTAGE_1POINT8            0x00000001
@@ -2385,6 +2392,10 @@
        int                     val;
 };
 
+#define ASF_ENABLE             1
+#define ASF_NEW_HANDSHAKE      2
+#define ASF_STACKUP            4
+
 struct bge_softc {
        struct ifnet            *bge_ifp;       /* interface info */
        device_t                bge_dev;
@@ -2403,6 +2414,8 @@
        u_int8_t                bge_asicrev;
        u_int8_t                bge_chiprev;
        u_int8_t                bge_no_3_led;
+       u_int8_t                bge_asf_mode;
+       u_int8_t                bge_asf_count;
        u_int8_t                bge_pcie;
        struct bge_ring_data    bge_ldata;      /* rings */
        struct bge_chain_data   bge_cdata;      /* mbufs */
Index: if_bge.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/bge/if_bge.c,v
retrieving revision 1.91.2.13
diff -u -r1.91.2.13 if_bge.c
--- if_bge.c    4 Mar 2006 09:34:48 -0000       1.91.2.13
+++ if_bge.c    28 Mar 2006 20:18:21 -0000
@@ -209,6 +209,7 @@
 static void bge_txeof          (struct bge_softc *);
 static void bge_rxeof          (struct bge_softc *);
 
+static void bge_asf_driver_up  (struct bge_softc *);
 static void bge_tick_locked    (struct bge_softc *);
 static void bge_tick           (void *);
 static void bge_stats_update   (struct bge_softc *);
@@ -271,7 +272,12 @@
                                    int count);
 #endif
 
-static void bge_reset          (struct bge_softc *);
+#define BGE_RESET_START 1
+#define BGE_RESET_STOP  2
+static void bge_sig_post_reset(struct bge_softc *, int);
+static void bge_sig_legacy(struct bge_softc *, int);
+static void bge_sig_pre_reset(struct bge_softc *, int);
+static int bge_reset           (struct bge_softc *);
 static void bge_link_upd       (struct bge_softc *);
 
 static device_method_t bge_methods[] = {
@@ -609,6 +615,18 @@
                DELAY(40);
        }
 
+        if (sc->bge_asf_mode & ASF_STACKUP
+           && pci_get_device(sc->bge_dev) == BCOM_DEVICEID_BCM5721) {
+               switch (reg) {
+                case MII_BMSR:
+                       val |= BMSR_100TXFDX | BMSR_100TXHDX | BMSR_10TFDX
+                               | BMSR_10THDX | BMSR_EXTSTAT
+                               | BMSR_MFPS
+                               | BMSR_ANEG | BMSR_EXTCAP;
+                       break;
+               }
+       }
+
        if (val & BGE_MICOMM_READFAIL)
                return(0);
 
@@ -660,10 +678,10 @@
 {
        struct bge_softc *sc;
        struct mii_data *mii;
-
        sc = device_get_softc(dev);
        mii = device_get_softc(sc->bge_miibus);
 
+
        BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE);
        if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
                BGE_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_GMII);
@@ -1007,6 +1025,80 @@
        return;
 }
 
+static void
+bge_sig_pre_reset(sc, type)
+       struct bge_softc *sc;
+       int type;
+{
+       bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER);
+
+       if (sc->bge_asf_mode & ASF_NEW_HANDSHAKE) {
+               switch (type) {
+               case BGE_RESET_START:
+                       bge_writemem_ind(sc, BGE_SDI_STATUS, 0x1); /* START */
+                       break;
+               case BGE_RESET_STOP:
+                       bge_writemem_ind(sc, BGE_SDI_STATUS, 0x2); /* UNLOAD */
+                       break;
+               }
+       }
+}
+
+static void
+bge_sig_post_reset(sc, type)
+       struct bge_softc *sc;
+       int type;
+{
+       if (sc->bge_asf_mode & ASF_NEW_HANDSHAKE) {
+               switch (type) {
+               case BGE_RESET_START:
+                       bge_writemem_ind(sc, BGE_SDI_STATUS, 0x80000001); 
+                       /* START DONE */
+                       break;
+               case BGE_RESET_STOP:
+                       bge_writemem_ind(sc, BGE_SDI_STATUS, 0x80000002); 
+                       break;
+               }
+       }
+}
+
+static void
+bge_sig_legacy(sc, type)
+       struct bge_softc *sc;
+       int type;
+{
+       if (sc->bge_asf_mode) {
+               switch (type) {
+               case BGE_RESET_START:
+                       bge_writemem_ind(sc, BGE_SDI_STATUS, 0x1); /* START */
+                       break;
+               case BGE_RESET_STOP:
+                       bge_writemem_ind(sc, BGE_SDI_STATUS, 0x2); /* UNLOAD */
+                       break;
+               }
+       }
+}
+
+void bge_stop_fw(struct bge_softc *);
+void
+bge_stop_fw(sc)
+       struct bge_softc *sc;
+{
+       int i;
+
+       if (sc->bge_asf_mode) {
+               bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_FW, BGE_FW_PAUSE);
+               CSR_WRITE_4(sc, BGE_CPU_EVENT,
+                           CSR_READ_4(sc, BGE_CPU_EVENT) != (1 << 14));
+
+               for (i = 0; i < 100; i++ ) {
+                       if (!(CSR_READ_4(sc, BGE_CPU_EVENT) & (1 << 14)))
+                               break;
+                       DELAY(10);
+               }
+       }
+}
+
 /*
  * Do endian, PCI and DMA initialization. Also check the on-board ROM
  * self-test results.
@@ -1018,9 +1110,10 @@
        int                     i;
        u_int32_t               dma_rw_ctl;
 
-       /* Set endian type before we access any non-PCI registers. */
+       /* Set endianness before we access any non-PCI registers. */
        pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, BGE_INIT, 4);
 
+#ifdef DJA
        /*
         * Check the 'ROM failed' bit on the RX CPU to see if
         * self-tests passed.
@@ -1029,7 +1122,7 @@
                device_printf(sc->bge_dev, "RX CPU self-diagnostics failed!\n");
                return(ENODEV);
        }
-
+#endif
        /* Clear the MAC control register */
        CSR_WRITE_4(sc, BGE_MAC_MODE, 0);
 
@@ -1101,6 +1194,9 @@
            BGE_MODECTL_MAC_ATTN_INTR|BGE_MODECTL_HOST_SEND_BDS|
            BGE_MODECTL_TX_NO_PHDR_CSUM);
 
+       if (sc->bge_asf_mode & ASF_STACKUP)
+               BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+
        /*
         * Disable memory write invalidate.  Apparently it is not supported
         * properly by these devices.
@@ -2054,6 +2150,7 @@
        u_int32_t mac_tmp = 0;
        u_char eaddr[6];
        int error = 0, rid;
+       int trys;
 
        sc = device_get_softc(dev);
        sc->bge_dev = dev;
@@ -2121,8 +2218,35 @@
                }
        }
 
+       sc->bge_asf_mode = 0;
+
        /* Try to reset the chip. */
-       bge_reset(sc);
+       bge_stop_fw(sc);
+       bge_sig_pre_reset(sc, BGE_RESET_STOP);
+       if (bge_reset(sc)) {
+               device_printf(sc->bge_dev, "chip reset failed\n");
+               bge_release_resources(sc);
+               error = ENXIO;
+               goto fail;
+       }
+
+       if (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG)
+           == BGE_MAGIC_NUMBER) {
+               if (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG)
+                   & BGE_HWCFG_ASF) {
+                       sc->bge_asf_mode |= ASF_ENABLE;
+                       if (CSR_READ_4(sc, BGE_MODE_CTL)
+                           & BGE_MODECTL_STACKUP ) {
+                               sc->bge_asf_mode |= ASF_STACKUP;
+                       }
+                       if (sc->bge_asicrev == BGE_ASICREV_BCM5750) {
+                               sc->bge_asf_mode |= ASF_NEW_HANDSHAKE;
+                       }
+               }
+       }
+
+       bge_sig_legacy(sc, BGE_RESET_STOP);
+       bge_sig_post_reset(sc, BGE_RESET_STOP);
 
        if (bge_chipinit(sc)) {
                device_printf(sc->bge_dev, "chip initialization failed\n");
@@ -2252,13 +2376,26 @@
                /*
                 * Do transceiver setup.
                 */
+               BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+again:
+               bge_asf_driver_up(sc);
+
+               trys = 0;
                if (mii_phy_probe(dev, &sc->bge_miibus,
                    bge_ifmedia_upd, bge_ifmedia_sts)) {
+                       if (trys++ < 4) {
+                               device_printf(sc->bge_dev, "Try again\n");
+                               bge_miibus_writereg(sc->bge_dev, 1, MII_BMCR, 
BMCR_RESET);
+                               goto again;
+                       }
+
                        device_printf(sc->bge_dev, "MII without any PHY!\n");
                        bge_release_resources(sc);
                        error = ENXIO;
                        goto fail;
                }
+               if (sc->bge_asf_mode & ASF_STACKUP)
+                       BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
        }
 
        /*
@@ -2372,7 +2509,7 @@
        return;
 }
 
-static void
+static int
 bge_reset(sc)
        struct bge_softc *sc;
 {
@@ -2435,11 +2572,18 @@
            sc->bge_asicrev != BGE_ASICREV_BCM5750)
                CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE);
 
+#if DJA
+       DELAY(1000000);
        /*
-        * Prevent PXE restart: write a magic number to the
-        * general communications memory at 0xB50.
+        * Check the 'ROM failed' bit on the RX CPU to see if
+        * self-tests passed.
         */
-       bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER);
+       if (CSR_READ_4(sc, BGE_RXCPU_MODE) & BGE_RXCPUMODE_ROMFAIL) {
+               device_printf(sc->bge_dev, "RX CPU self-diagnostics failed!\n");
+               return(ENODEV);
+       }
+#endif
+
        /*
         * Poll the value location we just wrote until
         * we see the 1's complement of the magic number.
@@ -2455,7 +2599,7 @@
 
        if (i == BGE_TIMEOUT) {
                device_printf(sc->bge_dev, "firmware handshake timed out\n");
-               return;
+               return(0);
        }
 
        /*
@@ -2475,6 +2619,8 @@
        /* Fix up byte swapping */
        CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_DMA_SWAP_OPTIONS|
            BGE_MODECTL_BYTESWAP_DATA);
+       if (sc->bge_asf_mode & ASF_STACKUP)
+               BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
 
        CSR_WRITE_4(sc, BGE_MAC_MODE, 0);
 
@@ -2499,7 +2645,7 @@
        }
        DELAY(10000);
 
-       return;
+       return(0);
 }
 
 /*
@@ -2680,6 +2826,7 @@
 {
        struct bge_tx_bd *cur_tx = NULL;
        struct ifnet *ifp;
+       int acked = 0;
 
        BGE_LOCK_ASSERT(sc);
 
@@ -2716,11 +2863,36 @@
                }
                sc->bge_txcnt--;
                BGE_INC(sc->bge_tx_saved_considx, BGE_TX_RING_CNT);
-               ifp->if_timer = 0;
+               ifp->if_timer = (sc->bge_txcnt == 0) ? 0 : 5;
+
+               acked = 1;
        }
 
        if (cur_tx != NULL)
                ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+       switch (sc->bge_chipid) {
+       case BGE_CHIPID_BCM5701_A0:
+       case BGE_CHIPID_BCM5701_B0:
+       case BGE_CHIPID_BCM5701_B2:
+       case BGE_CHIPID_BCM5701_B5:
+               /*
+                * Sometimes the RX engine never gets started.  We detect
+                * this by checking to see if we have sent some packets and
+                * never got a packet.  If we haven't got a packet reset.
+                * this is only triggered if we sent packets.
+                */
+ 
+               if (acked && ifp->if_opackets > 5 && !ifp->if_ipackets) {
+                       device_printf(sc->bge_dev, "reset the card packets out 
%ld in %ld\n"
+                           , ifp->if_opackets,
+                       ifp->if_ipackets);
+                       ifp->if_flags &=~ IFF_DRV_RUNNING;
+                       bge_stop(sc);
+                       bge_init(sc);
+               }
+               break;
+       }
 }
 
 #ifdef DEVICE_POLLING
@@ -2728,7 +2900,7 @@
 bge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
 {
        struct bge_softc *sc = ifp->if_softc;
-       
+
        BGE_LOCK(sc);
        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
                bge_poll_locked(ifp, cmd, count);
@@ -2834,6 +3006,26 @@
 }
 
 static void
+bge_asf_driver_up(sc)
+       struct bge_softc *sc;
+{
+       if (sc->bge_asf_mode & ASF_STACKUP) {
+               /* Send ASF heartbeat aprox. every 2s */
+               if (sc->bge_asf_count)
+                       sc->bge_asf_count --;
+               else {
+                       sc->bge_asf_count = 5;
+                       bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM_FW,
+                           BGE_FW_DRV_ALIVE);
+                       bge_writemem_ind(sc, BGE_SOFTWARE_GENNCOMM_FW_LEN, 4);
+                       bge_writemem_ind(sc, BGE_SOFTWARE_GENNCOMM_FW_DATA, 3);
+                       CSR_WRITE_4(sc, BGE_CPU_EVENT,
+                           CSR_READ_4(sc, BGE_CPU_EVENT) != (1 << 14));
+               }
+       }
+ }
+
+static void
 bge_tick_locked(sc)
        struct bge_softc *sc;
 {
@@ -2849,7 +3041,9 @@
 
        if (!sc->bge_tbi) {
                mii = device_get_softc(sc->bge_miibus);
-               mii_tick(mii);
+               /* Don't mess with the PHY in IPMI/ASF mode */
+               if (!((sc->bge_asf_mode & ASF_STACKUP) && (sc->bge_link)))
+                       mii_tick(mii);
        } else {
                /*
                 * Since in TBI mode auto-polling can't be used we should poll
@@ -2866,6 +3060,8 @@
                }
        }
 
+       bge_asf_driver_up(sc);
+
        callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc);
 }
 
@@ -3215,7 +3411,13 @@
 
        /* Cancel pending I/O and flush buffers. */
        bge_stop(sc);
+
+       bge_stop_fw(sc);
+       bge_sig_pre_reset(sc, BGE_RESET_START);
        bge_reset(sc);
+       bge_sig_legacy(sc, BGE_RESET_START);
+       bge_sig_post_reset(sc, BGE_RESET_START);
+
        bge_chipinit(sc);
 
        /*
@@ -3298,14 +3500,14 @@
                CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 1);
        } else
 #endif
-       
+
        /* Enable host interrupts. */
        {
        BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA);
        BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
        CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
        }
-       
+
        bge_ifmedia_upd(ifp);
 
        ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -3646,7 +3848,16 @@
        /*
         * Tell firmware we're shutting down.
         */
-       BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+
+       bge_stop_fw(sc);
+       bge_sig_pre_reset(sc, BGE_RESET_STOP);
+       bge_reset(sc);
+       bge_sig_legacy(sc, BGE_RESET_STOP);
+       bge_sig_post_reset(sc, BGE_RESET_STOP);
+       if (sc->bge_asf_mode & ASF_STACKUP)
+               BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
+       else
+               BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
 
        /* Free the RX lists. */
        bge_free_rx_ring_std(sc);
@@ -3670,6 +3881,7 @@
                /*
                 * If we are called from bge_detach(), mii is already NULL.
                 */
+               //if (mii != NULL && !(sc->bge_asf_mode & ASF_ENABLE)) {
                if (mii != NULL) {
                        ifm = mii->mii_media.ifm_cur;
                        mtmp = ifm->ifm_media;

Attachment: pgpQmKEVZ8bXQ.pgp
Description: PGP signature

Reply via email to