Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Aug 2006 17:16:32 +0400
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        David Christensen <davidch@broadcom.com>
Cc:        brad@openbsd.org, oleg@FreeBSD.org, net@FreeBSD.org
Subject:   Re: bge(4) one packet wedge
Message-ID:  <20060824131632.GN76666@FreeBSD.org>
In-Reply-To: <20060824084149.GI76666@cell.sick.ru>
References:  <20060823161649.GE76666@cell.sick.ru> <09BFF2FA5EAB4A45B6655E151BBDD90301D43002@NT-IRVA-0750.brcm.ad.broadcom.com> <20060824084149.GI76666@cell.sick.ru>

next in thread | previous in thread | raw e-mail | index | archive | help

--Fig2xvG2VGoz8o/s
Content-Type: text/plain; charset=koi8-r
Content-Disposition: inline

  Here I have prepared a patch, that utilizes the
tag in status block on the chips that can do this.
It also moves some chip quirks startup code to a
separate function.

-- 
Totus tuus, Glebius.
GLEBIUS-RIPN GLEB-RIPE

--Fig2xvG2VGoz8o/s
Content-Type: text/plain; charset=koi8-r
Content-Disposition: attachment; filename="bge.status_tag"

Index: if_bge.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/bge/if_bge.c,v
retrieving revision 1.139
diff -u -p -r1.139 if_bge.c
--- if_bge.c	23 Aug 2006 11:32:54 -0000	1.139
+++ if_bge.c	24 Aug 2006 13:07:12 -0000
@@ -978,7 +978,7 @@ bge_chipinit(struct bge_softc *sc)
 	int i;
 
 	/* Set endian type before we access any non-PCI registers. */
-	pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, BGE_INIT, 4);
+	pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, sc->bge_misc_ctl, 4);
 
 	/*
 	 * Check the 'ROM failed' bit on the RX CPU to see if
@@ -1982,6 +1982,70 @@ bge_dma_alloc(device_t dev)
 	return (0);
 }
 
+static void
+bge_recognize(struct bge_softc *sc)
+{
+	device_t dev = sc->bge_dev;
+	uint32_t misccfg;
+
+	/* Save ASIC rev. */
+	sc->bge_chipid =
+	    pci_read_config(dev, BGE_PCI_MISC_CTL, 4) &
+	    BGE_PCIMISCCTL_ASICREV;
+	sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
+	sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
+
+	sc->bge_misc_ctl = (BGE_HIF_SWAP_OPTIONS		|
+			    BGE_PCIMISCCTL_CLEAR_INTA		|
+			    BGE_PCIMISCCTL_MASK_PCI_INTR	|
+			    BGE_PCIMISCCTL_INDIRECT_ACCESS);
+	sc->bge_hcc_mode = 0;
+
+	/*
+	 * XXX: Broadcom Linux driver.  Not in specs or eratta.
+	 * PCI-Express?
+	 */
+	if (BGE_IS_5705_OR_BEYOND(sc)) {
+		uint32_t v;
+
+		v = pci_read_config(dev, BGE_PCI_MSI_CAPID, 4);
+		if (((v >> 8) & 0xff) == BGE_PCIE_CAPID_REG) {
+			v = pci_read_config(dev, BGE_PCIE_CAPID_REG, 4);
+			if ((v & 0xff) == BGE_PCIE_CAPID)
+				sc->bge_flags |= BGE_FLAG_PCIE;
+		}
+	}
+
+	/*
+	 * PCI-X?
+	 */
+	if ((pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) &
+	    BGE_PCISTATE_PCI_BUSMODE) == 0)
+		sc->bge_flags |= BGE_FLAG_PCIX;
+
+	misccfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID_MASK;
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5705 &&
+	    (misccfg == BGE_MISCCFG_BOARD_ID_5788 ||
+	    misccfg == BGE_MISCCFG_BOARD_ID_5788M))
+		sc->bge_flags |= BGE_FLAG_5788;
+
+	if (sc->bge_chiprev != BGE_CHIPREV_5700_AX &&
+	    sc->bge_chiprev != BGE_CHIPREV_5700_BX)
+		sc->bge_hcc_mode |= BGE_STATBLKSZ_32BYTE;
+
+	/*
+	 * 5788 and 5700 does not support tagging the status block.
+	 * This is workarounded in bge_tick_locked().
+	 */
+	if (!(sc->bge_flags & BGE_FLAG_5788) &&
+	    sc->bge_asicrev != BGE_ASICREV_BCM5700) {
+		sc->bge_flags |= BGE_FLAG_STATUSTAG;
+		sc->bge_hcc_mode |= (BGE_HCCMODE_CLRTICK_RXBD |
+		    BGE_HCCMODE_CLRTICK_TXBD);
+		sc->bge_misc_ctl |= BGE_PCIMISCCTL_TAGGED_STATUS;
+	}
+}
+
 static int
 bge_attach(device_t dev)
 {
@@ -2027,35 +2091,8 @@ bge_attach(device_t dev)
 
 	BGE_LOCK_INIT(sc, device_get_nameunit(dev));
 
-	/* Save ASIC rev. */
-
-	sc->bge_chipid =
-	    pci_read_config(dev, BGE_PCI_MISC_CTL, 4) &
-	    BGE_PCIMISCCTL_ASICREV;
-	sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
-	sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
-
-	/*
-	 * XXX: Broadcom Linux driver.  Not in specs or eratta.
-	 * PCI-Express?
-	 */
-	if (BGE_IS_5705_OR_BEYOND(sc)) {
-		uint32_t v;
-
-		v = pci_read_config(dev, BGE_PCI_MSI_CAPID, 4);
-		if (((v >> 8) & 0xff) == BGE_PCIE_CAPID_REG) {
-			v = pci_read_config(dev, BGE_PCIE_CAPID_REG, 4);
-			if ((v & 0xff) == BGE_PCIE_CAPID)
-				sc->bge_flags |= BGE_FLAG_PCIE;
-		}
-	}
-
-	/*
-	 * PCI-X ?
-	 */
-	if ((pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) &
-	    BGE_PCISTATE_PCI_BUSMODE) == 0)
-		sc->bge_flags |= BGE_FLAG_PCIX;
+	/* Fill in bge_flags, recognize features/bugs.*/
+	bge_recognize(sc);
 
 	/* Try to reset the chip. */
 	bge_reset(sc);
@@ -2684,16 +2721,13 @@ bge_poll(struct ifnet *ifp, enum poll_cm
 static void
 bge_intr(void *xsc)
 {
-	struct bge_softc *sc;
-	struct ifnet *ifp;
+	struct bge_softc *sc = xsc;
+	struct ifnet *ifp = sc->bge_ifp;
+	struct bge_status_block *sblock = sc->bge_ldata.bge_status_block;
 	uint32_t statusword;
 
-	sc = xsc;
-
 	BGE_LOCK(sc);
 
-	ifp = sc->bge_ifp;
-
 #ifdef DEVICE_POLLING
 	if (ifp->if_capenable & IFCAP_POLLING) {
 		BGE_UNLOCK(sc);
@@ -2701,6 +2735,15 @@ bge_intr(void *xsc)
 	}
 #endif
 
+	if ((((sc->bge_flags & BGE_FLAG_STATUSTAG) &&
+	    (sc->bge_last_tag == sblock->bge_tag)) ||
+	    !(sblock->bge_status & BGE_STATUS_UPDATED)) &&
+	    (pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) &
+	    BGE_PCISTATE_INTR_STATE)) {
+		/* Not our interrupt? */
+		BGE_UNLOCK(sc);
+		return;
+	}
 	/*
 	 * Do the mandatory PCI flush as well as get the link status.
 	 */
@@ -2729,7 +2772,13 @@ bge_intr(void *xsc)
 	}
 
 	/* Re-enable interrupts. */
-	CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+	if (sc->bge_flags & BGE_FLAG_STATUSTAG) {
+		sc->bge_last_tag = sblock->bge_tag;
+		CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, (sc->bge_last_tag << 24));
+	} else {
+		sblock->bge_status &= ~BGE_STATUS_UPDATED;
+		CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+	}
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
 	    !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
@@ -2769,6 +2818,16 @@ bge_tick_locked(struct bge_softc *sc)
 		}
 	}
 
+	if (!(sc->bge_flags & BGE_FLAG_STATUSTAG)) {
+		struct bge_status_block *sblock = sc->bge_ldata.bge_status_block;
+
+		if (sblock->bge_status & BGE_STATUS_UPDATED)
+			BGE_SETBIT(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_SET);
+		else
+			CSR_WRITE_4(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE |
+			    BGE_HCCMODE_COAL_NOW);
+	}
+
 	callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc);
 }
 
Index: if_bgereg.h
===================================================================
RCS file: /home/ncvs/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	24 Aug 2006 13:06:05 -0000
@@ -205,6 +205,7 @@
 #define BGE_PCIMISCCTL_CLOCKCTL_RW	0x00000020
 #define BGE_PCIMISCCTL_REG_WORDSWAP	0x00000040
 #define BGE_PCIMISCCTL_INDIRECT_ACCESS	0x00000080
+#define BGE_PCIMISCCTL_TAGGED_STATUS	0x00000200
 #define BGE_PCIMISCCTL_ASICREV		0xFFFF0000
 
 #define BGE_HIF_SWAP_OPTIONS	(BGE_PCIMISCCTL_ENDIAN_WORDSWAP)
@@ -218,10 +219,6 @@
 	BGE_MODECTL_BYTESWAP_DATA|BGE_MODECTL_WORDSWAP_DATA
 #endif
 
-#define BGE_INIT \
-	(BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_CLEAR_INTA| \
-	 BGE_PCIMISCCTL_MASK_PCI_INTR|BGE_PCIMISCCTL_INDIRECT_ACCESS)
-
 #define BGE_CHIPID_TIGON_I		0x40000000
 #define BGE_CHIPID_TIGON_II		0x60000000
 #define BGE_CHIPID_BCM5700_A0		0x70000000
@@ -1190,6 +1187,8 @@
 #define BGE_STATBLKSZ_FULL		0x00000000
 #define BGE_STATBLKSZ_64BYTE		0x00000080
 #define BGE_STATBLKSZ_32BYTE		0x00000100
+#define BGE_HCCMODE_CLRTICK_RXBD        0x00000200
+#define BGE_HCCMODE_CLRTICK_TXBD        0x00000400
 
 /* Host coalescing status register */
 #define BGE_HCCSTAT_ERROR		0x00000004
@@ -1684,6 +1683,9 @@
 /* Misc. config register */
 #define BGE_MISCCFG_RESET_CORE_CLOCKS	0x00000001
 #define BGE_MISCCFG_TIMER_PRESCALER	0x000000FE
+#define BGE_MISCCFG_BOARD_ID_MASK	0x0001e000
+#define BGE_MISCCFG_BOARD_ID_5788	0x00010000
+#define BGE_MISCCFG_BOARD_ID_5788M	0x00018000
 
 #define BGE_32BITTIME_66MHZ		(0x41 << 1)
 
@@ -1932,7 +1934,10 @@ struct bge_sts_idx {
 
 struct bge_status_block {
 	uint32_t		bge_status;
-	uint32_t		bge_rsvd0;
+#define	BGE_STATUS_UPDATED	0x00000001
+#define	BGE_STATUS_LINKEV	0x00000002
+#define	BGE_STATUS_ERROR	0x00000004
+	uint32_t		bge_tag;
 #if BYTE_ORDER == LITTLE_ENDIAN
 	uint16_t		bge_rx_jumbo_cons_idx;
 	uint16_t		bge_rx_std_cons_idx;
@@ -2451,11 +2456,14 @@ struct bge_softc {
 #define BGE_FLAG_NO3LED		0x00000008
 #define BGE_FLAG_PCIX		0x00000010
 #define BGE_FLAG_PCIE		0x00000020
+#define	BGE_FLAG_5788		0x00000040
+#define	BGE_FLAG_STATUSTAG	0x00000080
 	uint32_t		bge_chipid;
 	uint8_t		bge_asicrev;
 	uint8_t		bge_chiprev;
 	struct bge_ring_data	bge_ldata;	/* rings */
 	struct bge_chain_data	bge_cdata;	/* mbufs */
+	uint32_t		bge_last_tag;
 	uint16_t		bge_tx_saved_considx;
 	uint16_t		bge_rx_saved_considx;
 	uint16_t		bge_ev_saved_considx;
@@ -2474,6 +2482,9 @@ struct bge_softc {
 	int			bge_link;	/* link state */
 	int			bge_link_evt;	/* pending link event */
 	struct callout		bge_stat_ch;
+	/* Masks/values for some registers. */
+	uint32_t		bge_hcc_mode;	/* BGE_HCC_MODE */
+	uint32_t		bge_misc_ctl;	/* BGE_PCI_MISC_CTL */
 	char			*bge_vpd_prodname;
 	char			*bge_vpd_readonly;
 	u_long			bge_rx_discards;

--Fig2xvG2VGoz8o/s--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060824131632.GN76666>