bge IPMI patch final review
Julian Elischer
julian at elischer.org
Thu Sep 7 11:46:00 PDT 2006
Doug Ambrisko wrote:
>I'd like to commit my final bge version of the IPMI patch to keep IPMI
>working when FreeBSD attaches and also when the NIC is downed.
>I also have patches for the bce to do the same that I sent to David.
>This has various reviews and testing in the wild. I want to give
>a heads up since there have been changes in the bge driver recently.
>I'd like to not hold off on this anymore.
>
>
code looks good but could you add a bunch of comments explaining the
handshake
and how this works. (be verbose please)
>Thanks,
>
>Doug A.
>
>Index: if_bge.c
>===================================================================
>RCS file: /cvs/src/sys/dev/bge/if_bge.c,v
>retrieving revision 1.140
>diff -u -p -r1.140 if_bge.c
>--- if_bge.c 24 Aug 2006 14:41:16 -0000 1.140
>+++ if_bge.c 7 Sep 2006 18:31:59 -0000
>@@ -326,6 +326,7 @@ static void bge_dma_free(struct bge_soft
> 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 *);
>@@ -376,7 +377,12 @@ static void bge_miibus_statchg(device_t)
> static void bge_poll(struct ifnet *ifp, enum poll_cmd cmd, 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[] = {
>@@ -646,7 +652,6 @@ bge_miibus_statchg(device_t dev)
> {
> struct bge_softc *sc;
> struct mii_data *mii;
>-
> sc = device_get_softc(dev);
> mii = device_get_softc(sc->bge_miibus);
>
>@@ -968,6 +973,81 @@ bge_setmulti(struct bge_softc *sc)
> CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]);
> }
>
>+static void
>+bge_sig_pre_reset(sc, type)
>+ struct bge_softc *sc;
>+ int type;
>+{
>+ if (sc->bge_asf_mode)
>+ 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.
>@@ -978,7 +1058,7 @@ bge_chipinit(struct bge_softc *sc)
> uint32_t dma_rw_ctl;
> int i;
>
>- /* 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);
>
> /*
>@@ -1069,6 +1149,9 @@ bge_chipinit(struct bge_softc *sc)
> 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.
>@@ -1992,6 +2075,7 @@ bge_attach(device_t dev)
> uint32_t mac_tmp = 0;
> u_char eaddr[6];
> int error = 0, rid;
>+ int trys;
>
> sc = device_get_softc(dev);
> sc->bge_dev = dev;
>@@ -2059,7 +2143,38 @@ bge_attach(device_t dev)
> sc->bge_flags |= BGE_FLAG_PCIX;
>
> /* Try to reset the chip. */
>- bge_reset(sc);
>+ if (bge_reset(sc)) {
>+ device_printf(sc->bge_dev, "chip reset failed\n");
>+ bge_release_resources(sc);
>+ error = ENXIO;
>+ goto fail;
>+ }
>+
>+ sc->bge_asf_mode = 0;
>+ 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;
>+ sc->bge_asf_mode |= ASF_STACKUP;
>+ if (sc->bge_asicrev == BGE_ASICREV_BCM5750) {
>+ sc->bge_asf_mode |= ASF_NEW_HANDSHAKE;
>+ }
>+ }
>+ }
>+
>+ /* Try to reset the chip again the nice way. */
>+ 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;
>+ }
>+
>+ 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");
>@@ -2188,13 +2303,26 @@ bge_attach(device_t dev)
> /*
> * 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);
> }
>
> /*
>@@ -2295,7 +2423,7 @@ bge_release_resources(struct bge_softc *
> BGE_LOCK_DESTROY(sc);
> }
>
>-static void
>+static int
> bge_reset(struct bge_softc *sc)
> {
> device_t dev;
>@@ -2381,7 +2509,7 @@ bge_reset(struct bge_softc *sc)
>
> if (i == BGE_TIMEOUT) {
> device_printf(sc->bge_dev, "firmware handshake timed out\n");
>- return;
>+ return(0);
> }
>
> /*
>@@ -2401,6 +2529,8 @@ bge_reset(struct bge_softc *sc)
> /* 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);
>
>@@ -2427,6 +2557,8 @@ bge_reset(struct bge_softc *sc)
> CSR_WRITE_4(sc, 0x7c00, v | (1<<25));
> }
> DELAY(10000);
>+
>+ return(0);
> }
>
> /*
>@@ -2740,6 +2872,25 @@ bge_intr(void *xsc)
> }
>
> static void
>+bge_asf_driver_up(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(struct bge_softc *sc)
> {
> struct mii_data *mii = NULL;
>@@ -2753,7 +2904,9 @@ bge_tick_locked(struct bge_softc *sc)
>
> if ((sc->bge_flags & BGE_FLAG_TBI) == 0) {
> 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
>@@ -2770,6 +2923,8 @@ bge_tick_locked(struct bge_softc *sc)
> }
> }
>
>+ bge_asf_driver_up(sc);
>+
> callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc);
> }
>
>@@ -3116,7 +3271,13 @@ bge_init_locked(struct bge_softc *sc)
>
> /* 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);
>
> /*
>@@ -3199,7 +3360,7 @@ bge_init_locked(struct bge_softc *sc)
> 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);
>@@ -3551,7 +3712,16 @@ bge_stop(struct bge_softc *sc)
> /*
> * 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);
>Index: if_bgereg.h
>===================================================================
>RCS file: /cvs/src/sys/dev/bge/if_bgereg.h,v
>retrieving revision 1.52
>diff -u -p -r1.52 if_bgereg.h
>--- if_bgereg.h 23 Aug 2006 11:32:54 -0000 1.52
>+++ if_bgereg.h 7 Sep 2006 18:31:59 -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
>@@ -1651,6 +1656,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
>@@ -2063,6 +2069,7 @@ struct bge_status_block {
> #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
>@@ -2433,6 +2440,10 @@ struct bge_bcom_hack {
> 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;
>@@ -2452,8 +2463,10 @@ struct bge_softc {
> #define BGE_FLAG_PCIX 0x00000010
> #define BGE_FLAG_PCIE 0x00000020
> uint32_t bge_chipid;
>- uint8_t bge_asicrev;
>- uint8_t bge_chiprev;
>+ uint8_t bge_asicrev;
>+ uint8_t bge_chiprev;
>+ uint8_t bge_asf_mode;
>+ uint8_t bge_asf_count;
> struct bge_ring_data bge_ldata; /* rings */
> struct bge_chain_data bge_cdata; /* mbufs */
> uint16_t bge_tx_saved_considx;
>_______________________________________________
>freebsd-current at freebsd.org mailing list
>http://lists.freebsd.org/mailman/listinfo/freebsd-current
>To unsubscribe, send any mail to "freebsd-current-unsubscribe at freebsd.org"
>
>
More information about the freebsd-current
mailing list