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>