Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Nov 2002 21:18:51 -0500
From:      Don Bowman <don@sandvine.com>
To:        'Sam Leffler' <sam@errno.com>, Don Bowman <don@sandvine.com>, "'freebsd-stable@freebsd.org'" <freebsd-stable@FreeBSD.ORG>, "'freebsd-net@freebsd.org'" <freebsd-net@FreeBSD.ORG>
Cc:        "'mp@FreeBSD.org'" <mp@FreeBSD.ORG>, jdp@polstra.com, m.barthelow@F5.com
Subject:   RE: bge bug w/ out of bounds return receiver, staying in rxeof al l the time, patch
Message-ID:  <FE045D4D9F7AED4CBFF1B3B813C8533701022FFE@mail.sandvine.com>

next in thread | raw e-mail | index | archive | help
> From: Sam Leffler [mailto:sam@errno.com]
> > I would recommend a committer look this over and 
> > commit it. If you wish, I can make the patch *just*
> > be the change (changing the 16-bit to 32-bit writes,
> > without the VPD stuff), but the other changes seemed
> > generally useful.
> 
> Please whittle the patch down to just the bug fix; 5.0 is in 
> code freeze.
> 
>     Sam
> 

Sigh, I was afraid someone would say that. Will do.
The patch is against RELENG_4, but is fairly trivial. It is below,
just the bug fix is there (changing the writing to the 
receiver control block to be 32-bits all the time).

Patch follows:

Index: if_bge.c
===================================================================
RCS file: /cvs/src/sys/dev/bge/if_bge.c,v
retrieving revision 1.3.2.18
diff -U3 -r1.3.2.18 if_bge.c
--- if_bge.c	2 Nov 2002 18:22:23 -0000	1.3.2.18
+++ if_bge.c	22 Nov 2002 02:01:48 -0000
@@ -913,7 +913,7 @@
 {
 	int i;
 	struct bge_rcb *rcb;
-	struct bge_rcb_opaque *rcbo;
+	bge_max_len_flags len_flags;
 
 	for (i = 0; i < BGE_JUMBO_RX_RING_CNT; i++) {
 		if (bge_newbuf_jumbo(sc, i, NULL) == ENOBUFS)
@@ -923,9 +923,9 @@
 	sc->bge_jumbo = i - 1;
 
 	rcb = &sc->bge_rdata->bge_info.bge_jumbo_rx_rcb;
-	rcbo = (struct bge_rcb_opaque *)rcb;
-	rcb->bge_flags = 0;
-	CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcbo->bge_reg2);
+	len_flags.bge_len_flags = rcb->bge_len_flags.bge_len_flags;
+	len_flags.s.bge_flags = 0;
+	CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS,
len_flags.bge_len_flags);
 
 	CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
 
@@ -1133,6 +1133,7 @@
 	struct bge_rcb *rcb;
 	struct bge_rcb_opaque *rcbo;
 	int i;
+	bge_max_len_flags len_flags;
 
 	/*
 	 * Initialize the memory window pointer register so that
@@ -1202,12 +1203,13 @@
 	rcb = &sc->bge_rdata->bge_info.bge_std_rx_rcb;
 	BGE_HOSTADDR(rcb->bge_hostaddr) =
 	    vtophys(&sc->bge_rdata->bge_rx_std_ring);
-	rcb->bge_max_len = BGE_MAX_FRAMELEN;
+	len_flags.s.bge_max_len = BGE_MAX_FRAMELEN;
+	len_flags.s.bge_flags = 0;
+	rcb->bge_len_flags.bge_len_flags = len_flags.bge_len_flags;
 	if (sc->bge_extram)
 		rcb->bge_nicaddr = BGE_EXT_STD_RX_RINGS;
 	else
 		rcb->bge_nicaddr = BGE_STD_RX_RINGS;
-	rcb->bge_flags = 0;
 	rcbo = (struct bge_rcb_opaque *)rcb;
 	CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcbo->bge_reg0);
 	CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcbo->bge_reg1);
@@ -1224,12 +1226,13 @@
 	rcb = &sc->bge_rdata->bge_info.bge_jumbo_rx_rcb;
 	BGE_HOSTADDR(rcb->bge_hostaddr) =
 	    vtophys(&sc->bge_rdata->bge_rx_jumbo_ring);
-	rcb->bge_max_len = BGE_MAX_FRAMELEN;
+	len_flags.s.bge_max_len = BGE_MAX_FRAMELEN;
+	len_flags.s.bge_flags = BGE_RCB_FLAG_RING_DISABLED;
+	rcb->bge_len_flags.bge_len_flags = len_flags.bge_len_flags;
 	if (sc->bge_extram)
 		rcb->bge_nicaddr = BGE_EXT_JUMBO_RX_RINGS;
 	else
 		rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS;
-	rcb->bge_flags = BGE_RCB_FLAG_RING_DISABLED;
 
 	rcbo = (struct bge_rcb_opaque *)rcb;
 	CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, rcbo->bge_reg0);
@@ -1239,7 +1242,9 @@
 
 	/* Set up dummy disabled mini ring RCB */
 	rcb = &sc->bge_rdata->bge_info.bge_mini_rx_rcb;
-	rcb->bge_flags = BGE_RCB_FLAG_RING_DISABLED;
+	len_flags.s.bge_max_len = 0;
+	len_flags.s.bge_flags = BGE_RCB_FLAG_RING_DISABLED;
+	rcb->bge_len_flags.bge_len_flags = len_flags.bge_len_flags;
 	rcbo = (struct bge_rcb_opaque *)rcb;
 	CSR_WRITE_4(sc, BGE_RX_MINI_RCB_MAXLEN_FLAGS, rcbo->bge_reg2);
 
@@ -1259,8 +1264,9 @@
 	rcb = (struct bge_rcb *)(sc->bge_vhandle + BGE_MEMWIN_START +
 	    BGE_SEND_RING_RCB);
 	for (i = 0; i < BGE_TX_RINGS_EXTSSRAM_MAX; i++) {
-		rcb->bge_flags = BGE_RCB_FLAG_RING_DISABLED;
-		rcb->bge_max_len = 0;
+		len_flags.s.bge_max_len = 0;
+		len_flags.s.bge_flags = BGE_RCB_FLAG_RING_DISABLED;
+		rcb->bge_len_flags.bge_len_flags = len_flags.bge_len_flags;
 		rcb->bge_nicaddr = 0;
 		rcb++;
 	}
@@ -1272,17 +1278,20 @@
 	BGE_HOSTADDR(rcb->bge_hostaddr) =
 	    vtophys(&sc->bge_rdata->bge_tx_ring);
 	rcb->bge_nicaddr = BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT);
-	rcb->bge_max_len = BGE_TX_RING_CNT;
-	rcb->bge_flags = 0;
+	len_flags.s.bge_max_len = BGE_TX_RING_CNT;
+	len_flags.s.bge_flags = 0;
+	rcb->bge_len_flags.bge_len_flags = len_flags.bge_len_flags;
 
 	/* Disable all unused RX return rings */
 	rcb = (struct bge_rcb *)(sc->bge_vhandle + BGE_MEMWIN_START +
 	    BGE_RX_RETURN_RING_RCB);
-	for (i = 0; i < BGE_RX_RINGS_MAX; i++) {
+	rcb++;
+	for (i = 1; i < BGE_RX_RINGS_MAX; i++) {
 		rcb->bge_hostaddr.bge_addr_hi = 0;
 		rcb->bge_hostaddr.bge_addr_lo = 0;
-		rcb->bge_flags = BGE_RCB_FLAG_RING_DISABLED;
-		rcb->bge_max_len = BGE_RETURN_RING_CNT;
+		len_flags.s.bge_max_len = BGE_RETURN_RING_CNT;
+		len_flags.s.bge_flags = BGE_RCB_FLAG_RING_DISABLED;
+		rcb->bge_len_flags.bge_len_flags = len_flags.bge_len_flags;
 		rcb->bge_nicaddr = 0;
 		CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO +
 		    (i * (sizeof(u_int64_t))), 0);
@@ -1306,8 +1315,9 @@
 	BGE_HOSTADDR(rcb->bge_hostaddr) =
 	    vtophys(&sc->bge_rdata->bge_rx_return_ring);
 	rcb->bge_nicaddr = 0x00000000;
-	rcb->bge_max_len = BGE_RETURN_RING_CNT;
-	rcb->bge_flags = 0;
+	len_flags.s.bge_max_len = BGE_RETURN_RING_CNT;
+	len_flags.s.bge_flags = 0;
+	rcb->bge_len_flags.bge_len_flags = len_flags.bge_len_flags;
 
 	/* Set random backoff seed for TX */
 	CSR_WRITE_4(sc, BGE_TX_RANDOM_BACKOFF,
@@ -1363,13 +1373,11 @@
 	CSR_WRITE_4(sc, BGE_HCC_STATS_TICKS, sc->bge_stat_ticks);
 
 	/* Set up address of statistics block */
-	CSR_WRITE_4(sc, BGE_HCC_STATS_BASEADDR, BGE_STATS_BLOCK);
 	CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_HI, 0);
 	CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_LO,
 	    vtophys(&sc->bge_rdata->bge_info.bge_stats));
 
 	/* Set up address of status block */
-	CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_BASEADDR, BGE_STATUS_BLOCK);
 	CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_HI, 0);
 	CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_LO,
 	    vtophys(&sc->bge_rdata->bge_status_block));
@@ -2082,7 +2090,7 @@
 #ifdef notdef
 	/* Avoid this for now -- checking this register is expensive. */
 	/* Make sure this is really our interrupt. */
-	if (!(CSR_READ_4(sc, BGE_MISC_LOCAL_CTL) & BGE_MLC_INTR_STATE))
+	if ((CSR_READ_4(sc, BGE_MISC_LOCAL_CTL) & BGE_MLC_INTR_STATE))
 		return;
 #endif
 	/* Ack interrupt and stop others from occuring. */
Index: if_bgereg.h
===================================================================
RCS file: /cvs/src/sys/dev/bge/if_bgereg.h,v
retrieving revision 1.1.2.7
diff -U3 -r1.1.2.7 if_bgereg.h
--- if_bgereg.h	2 Nov 2002 18:17:55 -0000	1.1.2.7
+++ if_bgereg.h	22 Nov 2002 01:58:45 -0000
@@ -1678,11 +1678,23 @@
 } bge_hostaddr;
 #define BGE_HOSTADDR(x)	x.bge_addr_lo
 
+typedef union {
+    struct {
+#if BYTE_ORDER == BIG_ENDIAN
+	u_int16_t		bge_max_len;
+	u_int16_t		bge_flags;
+#else
+	u_int16_t		bge_flags;
+	u_int16_t		bge_max_len;
+#endif
+    } s;
+    u_int32_t			bge_len_flags;
+}  bge_max_len_flags;
+
 /* Ring control block structure */
 struct bge_rcb {
 	bge_hostaddr		bge_hostaddr;
-	u_int16_t		bge_flags;
-	u_int16_t		bge_max_len;
+	bge_max_len_flags	bge_len_flags;
 	u_int32_t		bge_nicaddr;
 };
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




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