Date: Thu, 7 Sep 2006 11:35:31 -0700 (PDT) From: Doug Ambrisko <ambrisko@ambrisko.com> To: freebsd-current@freebsd.org Subject: bge IPMI patch final review Message-ID: <200609071835.k87IZVUF034745@ambrisko.com>
next in thread | raw e-mail | index | archive | help
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.
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609071835.k87IZVUF034745>
