bge IPMI patch final review

From: Doug Ambrisko <ambrisko_at_ambrisko.com>
Date: Thu, 7 Sep 2006 11:35:31 -0700 (PDT)
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
_at__at_ -326,6 +326,7 _at__at_ 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 *);
_at__at_ -376,7 +377,12 _at__at_ 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[] = {
_at__at_ -646,7 +652,6 _at__at_ 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);
 
_at__at_ -968,6 +973,81 _at__at_ 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.
_at__at_ -978,7 +1058,7 _at__at_ 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);
 
 	/*
_at__at_ -1069,6 +1149,9 _at__at_ 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.
_at__at_ -1992,6 +2075,7 _at__at_ 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;
_at__at_ -2059,7 +2143,38 _at__at_ 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");
_at__at_ -2188,13 +2303,26 _at__at_ 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);
 	}
 
 	/*
_at__at_ -2295,7 +2423,7 _at__at_ bge_release_resources(struct bge_softc *
 		BGE_LOCK_DESTROY(sc);
 }
 
-static void
+static int
 bge_reset(struct bge_softc *sc)
 {
 	device_t dev;
_at__at_ -2381,7 +2509,7 _at__at_ bge_reset(struct bge_softc *sc)
 
 	if (i == BGE_TIMEOUT) {
 		device_printf(sc->bge_dev, "firmware handshake timed out\n");
-		return;
+		return(0);
 	}
 
 	/*
_at__at_ -2401,6 +2529,8 _at__at_ 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);
 
_at__at_ -2427,6 +2557,8 _at__at_ bge_reset(struct bge_softc *sc)
 		CSR_WRITE_4(sc, 0x7c00, v | (1<<25));
 	}
 	DELAY(10000);
+
+	return(0);
 }
 
 /*
_at__at_ -2740,6 +2872,25 _at__at_ 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;
_at__at_ -2753,7 +2904,9 _at__at_ 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
_at__at_ -2770,6 +2923,8 _at__at_ bge_tick_locked(struct bge_softc *sc)
 		}
 	}
 
+	bge_asf_driver_up(sc);
+
 	callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc);
 }
 
_at__at_ -3116,7 +3271,13 _at__at_ 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);
 
 	/*
_at__at_ -3199,7 +3360,7 _at__at_ 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);
_at__at_ -3551,7 +3712,16 _at__at_ 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
_at__at_ -74,6 +74,11 _at__at_
 #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
_at__at_ -1651,6 +1656,7 _at__at_
 #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
_at__at_ -2063,6 +2069,7 _at__at_ 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
_at__at_ -2433,6 +2440,10 _at__at_ 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;
_at__at_ -2452,8 +2463,10 _at__at_ 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;
Received on Thu Sep 07 2006 - 16:35:59 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:00 UTC