Tom Judge wrote:
Tom Judge wrote:
Tom Judge wrote:
David Christensen wrote:
Sorry for the top post, please try following patch:
http://people.freebsd.org/~sephe/if_bce.c.diff
This is probably the cause; I noticed it when bce(4) was ported to
DragonFly.
Thanks Sephe, I think you're on to something. I have some
debug code in the driver to simulate mbuf allocation
failures and when I enable that I start receiving the same
error messages Tom reported (along with various kernel
panics), but when I include your change the system seems
to keep humming along. I'll certainly add your code into an update
shortly.
Dave
I'm not going to have a chance to test this patch until next week but
I will let you know what the results are.
Tom
So here goes, after 2 days testing we have come up with the following
data.
The configuration
[PE[12]950] ----> [PowerConnect 5324]
The system is running 8192 byte Jumbo Frames.
sultan# ifconfig bce0
bce0: flags=8847<UP,BROADCAST,DEBUG,RUNNING,SIMPLEX,MULTICAST> mtu 8192
options=3b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU>
inet 172.31.0.28 netmask 0xffffff00 broadcast 172.31.0.255
inet 172.31.0.163 netmask 0xffffffff broadcast 172.31.0.163
ether 00:19:b9:e4:4d:cc
media: Ethernet autoselect (1000baseTX <full-duplex>)
status: active
After applying both David and Sephe's patches I have yet to get a
system in a state where it is stable with jumbo frames enabled, the
systems crash almost immediately after the switch changes the port
state (Spanning tree) from LEARNING to FORWARDING. The output from
this crash can be found attached as crash-1.txt.gz.
If the frame size is left at 1500 then the interface seems stable,
however I can't fully test this as the interface is connected to a
GigE only network with an mtu of 8192.
If BCE_DEBUG is remove from if_bcereg.h then the system just exhibits
the original problem and may or may not crash.
The next test was to try the kernel with BCE_DEBUG and with the
following extra patch (so that the driver does not jump to the
breakpoint when an unexpected mbuf is found in the rx buffer).
--- if_bce.c (revision 62)
+++ if_bce.c (revision 66)
@@ -4050,7 +4050,8 @@
DBRUNIF((!(rxbd->rx_bd_flags & RX_BD_FLAGS_END)),
BCE_PRINTF("%s(%d): Unexpected mbuf
found in rx_bd[0x%04X]!\n",
__FILE__, __LINE__, sw_chain_cons);
- bce_breakpoint(sc));
+ bce_dump_mbuf(sc, m));
+// bce_breakpoint(sc));
/*
* ToDo: If the received packet is small enough
With this patch the system boots and does not crash straight away,
however it is almost completely unusable. The output with this kernel
can be found attached as crash-2.txt.gz. Also this causes the
following new error message:
fgrep -n leak crash-2.txt
3194:bce0: /usr/src/sys/dev/bce/if_bce.c(3842): Memory leak! Lost 114
mbufs from rx chain!
Has no one else come across this problem, or are Jumbo frames not
widely used?
Tom
It would seem that the crash can be simulated just by increasing the MTU
above 1500 (tested in single user mode).
Ok so I think I have fix the problem with the rx_bd tracking. I have
ported rboyer's patch to NetBSD's bnx driver to FreeBSD (patch
attached). The patch seems to get rid of two problems:
1) Unexpected mbuf in rx_bd
2) Too many free rx_bd's
However I am still faced with the problem of frames with missing
ethernet headers:
bce0: /usr/src/sys/dev/bce/if_bce.c(4128): Unusual frame size found.
Min(60), Actual(0), Max(9022)
bce0: mbuf: vaddr = 0xFFFFFF00:7B69AC00, m_len = 9216, m_flags = ( M_EXT
M_PKTHDR ) m_data = 0xFFFFFFFF:86F76000
0x00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bce0: - m_pkthdr: flags = ( ) csum_flags = ( )
bce0: - m_ext: vaddr = 0xFFFFFFFF:86F76000, ext_size = 9216, type =
EXT_JUMBO9
bce0: discard frame w/o leading ethernet header (len 4294967292 pkt len
4294967292)
bce0: /usr/src/sys/dev/bce/if_bce.c(4128): Unusual frame size found.
Min(60), Actual(0), Max(9022)
bce0: mbuf: vaddr = 0xFFFFFF00:5EB48B00, m_len = 9216, m_flags = ( M_EXT
M_PKTHDR ) m_data = 0xFFFFFFFF:86F73000
0x00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
bce0: - m_pkthdr: flags = ( ) csum_flags = ( )
bce0: - m_ext: vaddr = 0xFFFFFFFF:86F73000, ext_size = 9216, type =
EXT_JUMBO9
bce0: discard frame w/o leading ethernet header (len 4294967292 pkt len
4294967292)
bce0: /usr/src/sys/dev/bce/if_bce.c(4128): Unusual frame size found.
Min(60), Actual(27745), Max(9022)
bce0: mbuf: vaddr = 0xFFFFFF00:5E9DDC00, m_len = 9216, m_flags = ( M_EXT
M_PKTHDR ) m_data = 0xFFFFFFFF:86EF8000
0x00: 2C 6F 75 3D 50 65 72 73 6F 6E 61 6C 2C 6F 75 3D
0x10: 47 72 6F 75 70 73 2C 6F 3D 4D 69 6E 74 65 6C 30
0x20: 28 30 11 04 02 63 6E 31 0B 04 09 63 62 75 74 74
0x30: 72 6F 73 65 30 13 04 09 67 69 64 4E 75 6D 62 65
0x40: 72 31 06 04 04 31 31 30 38 30 5E 02 01 02 64 59
0x50: 04 31 63 6E 3D 6D 63 61 68 6D 2C 6F 75 3D 4C 6F
0x60: 6E 64 6F 6E 2C 6F 75 3D 50 65 72 73 6F 6E 61 6C
0x70: 2C 6F 75 3D 47 72 6F 75 70 73 2C 6F 3D 4D 69 6E
bce0: - m_pkthl er0ror
9 67 69 64 4E 75 6D 62 65 72 31 06 04 04 31 30
0x70: 33 37 30 62 02 01 02 64 5D 04 33 63 6E 3D 72 63
bce0: - m_pkthdr: flags = ( ) csum_flags = ( )
bce0: - m_ext: vaddr = 0xFFFFFFFF:86E8C000, ext_size = 9216, type =
EXT_JUMBO9
bce0: /usr/src/sys/dev/bce/if_bce.c(4081): Unexpected mbuf found in
rx_bd[0x002A]!
bce0: /usr/src/sys/dev/bce/if_bce.c(4128): Unusual frame size found.
Min(60), Actual(28515), Max(9022)
bce0: mbuf: vaddr = 0xFFFFFF00:5AB4C800, m_len = 9216, m_flags = ( M_EXT
M_PKTHDR ) m_data = 0xFFFFFFFF:86F28000
0x00: 30 0E 04 02 63 6E 31 08 04 06 63 6F 68 61 72 61
0x10: 30 13 04 09 67 69 64 4E 75 6D 62 65 72 31 06 04
0x20: 04 31 30 37 32 30 65 02 01 02 64 60 04 35 63 6E
0x30: 3D 6A 70 69 65 6B 61 72 73 2C 6F 75 3D 43 68 69
0x40: 63 61 67 6F 2C 6F 75 3D 50 65 72 73 6F 6E 61 6C
0x50: 2C 6F 75 3D 47 72 6F 75 70 73 2C 6F 3D 4D 69 6E
0x60: 74 65 6C 30 27 30 10 04 02 63 6E 31 0A 04 08 6A
0x70: 70 69 65 6B 61 72 73 30 13 04 09 67 69 64 4E 75
bce0: - m_pkthdr: flags = ( ) csum_flags = ( )
bce0: - m_ext: vaddr = 0xFFFFFFFF:86F28000, ext_size = 9216, type =
EXT_JUMBO9
bce0: /usr/src/sys/dev/bce/if_bce.c(4081): Unexpected mbuf found in
rx_bd[0x002E]!
bce0: /usr/src/sys/dev/bce/if_bce.c(4128): Unusual frame size found.
Min(60), Actual(28460), Max(9022)
bce0: mbuf: vaddr = 0xFFFFFF00:5EB9F200, m_len = 9216, m_flags = ( M_EXT
M_PKTHDR ) m_data = 0xFFFFFFFF:86F70000
0x00: 04 32 63 6E 3D 69 6E 65 73 73 2C 6F 75 3D 43 68
0x10: 69 63 61 67 6F 2C 6F 75 3D 50 65 72 73 6F 6E 61
0x20: 6C 2C 6F 75 3D 47 72 6F 75 70 73 2C 6F 3D 4D 69
0x30: 6E 74 65 6C 30 24 30 0D 04 02 63 6E 31 07 04 05
0x40: 69 6E 65 73 73 30 13 04 09 67 69 64 4E 75 6D 62
0x50: 65 72 31 06 04 04 31 31 34 32 30 67 02 01 02 64
0x60: 62 04 36 63 6E 3D 70 6D 63 6E 61 6D 61 72 61 2C
0x70: 6F 75 3D 43 68 69 63 61 67 6F 2C 6F 75 3D 50 65
bce0: - m_pkthdr: flags = ( ) csum_flags = ( )
bce0: - m_ext: vaddr = 0xFFFFFFFF:86F70000, ext_size = 9216, type =
EXT_JUMBO9
bce0: /usr/src/sys/dev/bce/if_bce.c(4081): Unexpected mbuf found in
rx_bd[0x0032]!
bce0: /usr/src/sys/dev/bce/if_bce.c(4128): Unusual frame size found.
Min(60), Actual(28787), Max(9022)
bce0: mbuf: vaddr = 0xFFFFFF00:5AB4CA00, m_len = 9216, m_flags = ( M_EXT
M_PKTHDR ) m_data = 0xFFFFFFFF:86F6D000
0x00: 02 01 02 64 57 04 30 63 6E 3D 73 70 79 65 2C 6F
0x10: 75 3D 4C 6F 6E 64 6F 6E 2C 6F 75 3D 50 65 72 73
0x20: 6F 6E 61 6C 2C 6F 75 3D 47 72 6F 75 70 73 2C 6F
0x30: 3D 4D 69 6E 74 65 6C 30 23 30 0C 04 02 63 6E 31
0x40: 06 04 04 73 70 79 65 30 13 04 09 67 69 64 4E 75
0x50: 6D 62 65 72 31 06 04 04 31 32 30 39 30 59 02 01
0x60: 02 64 54 04 2F 63 6E 3D 71 61 2C 6F 75 3D 43 68
0x70: 69 63 61 67 6F 2C 6F 75 3D 50 65 72 73 6F 6E 61
bce0: - m_pkthdr: flags = ( ) csum_flags = ( )
bce0: - m_ext: vaddr = 0xFFFFFFFF:86F6D000, ext_size = 9216, type =
EXT_JUMBO9
bce0: /usr/src/sys/dev/bce/if_bce.c(4128): Unusual frame size found.
Min(60), Actual(12855), Max(9022)
bce0: mbuf: vaddr =0 67 02 01 02 64
0x60: 62 04 36 63 6E 3D 70 6D 63 6E 61 6D 61 72 61 2C
0x70: 6F 75 3D 43 68 69 63 61 67 6F 2C 6F 75 3D 50 65
bce0: - m_pkthdr: flags = ( ) csum_flags = ( )
bce0: - m_ext: vaddr = 0xFFFFFFFF:86F70000, ext_size = 9216, type =
EXT_JUMBO9
if_bnx.c - 1.4 -> 1.5 LOG:
RX buffers are malloced memory of 9216 bytes. This can require from 1 to
4 DMA memory segments, depending on how the buffer is in memory.
When receiving a packet, we allocate a new one to remplace the one we've
used. It can need more segments than the one it remplace, leading to
corrution of the RX descriptors, and a panic in bus_dmamap_sync()
(DIAGNOSTIC
kernels) or possibly memory corruption.
Fix:
- bce_get_buf() allocates as many buffer as possible, checking the number
of free RX descriptors. Because one receive buffer is not guaranteed to
be remplaced on receive, call bce_get_buf() from bce_tick() too.
This also improve error handling from bce_get_buf().
- use MCLGET() instead of MEXTMALLOC() if we're running with the standard
ethernet MTU. This gives us more receive buffers and waste less memory.
Seem to be moving in the right direction slowly.
Tom
Index: if_bce.c
===================================================================
--- if_bce.c (revision 67)
+++ if_bce.c (revision 74)
@@ -732,7 +732,7 @@
ifp->if_capenable = ifp->if_capabilities;
/* Assume a standard 1500 byte MTU size for mbuf allocations. */
- sc->mbuf_alloc_size = MCLBYTES;
+// sc->mbuf_alloc_size = MCLBYTES;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
@@ -3475,10 +3475,12 @@
bus_dma_segment_t segs[4];
struct mbuf *m_new = NULL;
struct rx_bd *rxbd;
- int i, nsegs, error, rc = 0;
+ int i, nsegs, rc = 0;
#ifdef BCE_DEBUG
u16 debug_chain_prod = *chain_prod;
#endif
+ u16 first_chain_prod;
+ u16 min_free_bd;
DBPRINT(sc, (BCE_VERBOSE_RESET | BCE_VERBOSE_RECV), "Entering %s()\n",
__FUNCTION__);
@@ -3491,114 +3493,146 @@
DBPRINT(sc, BCE_VERBOSE_RECV, "%s(enter): prod = 0x%04X, chain_prod =
0x%04X, "
"prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod,
*prod_bseq);
- if (m == NULL) {
+ /* try to get in as many mbufs as possible */
+ if (sc->mbuf_alloc_size == MCLBYTES)
+ min_free_bd = (MCLBYTES + PAGE_SIZE - 1) / PAGE_SIZE;
+ else
+ min_free_bd = (BCE_MAX_MTU + PAGE_SIZE - 1) / PAGE_SIZE;
+ while (sc->free_rx_bd >= min_free_bd) {
+ if (m == NULL) {
+ DBRUNIF(DB_RANDOMTRUE(bce_debug_mbuf_allocation_failure),
+ BCE_PRINTF("%s(%d): Simulating mbuf allocation failure.\n",
+ __FILE__, __LINE__);
+ sc->mbuf_alloc_failed++;
+ rc = ENOBUFS;
+ goto bce_get_buf_exit);
- DBRUNIF(DB_RANDOMTRUE(bce_debug_mbuf_allocation_failure),
- BCE_PRINTF("%s(%d): Simulating mbuf allocation
failure.\n",
- __FILE__, __LINE__);
- sc->mbuf_alloc_failed++;
- rc = ENOBUFS;
- goto bce_get_buf_exit);
+ /* This is a new mbuf allocation. */
+ MGETHDR(m_new, M_DONTWAIT, MT_DATA);
+ if (m_new == NULL) {
+ DBPRINT(sc, BCE_WARN,
+ "%s(%d): RX mbuf header allocation failed!\n",
+ __FILE__, __LINE__);
+//
+ DBRUNIF(1, sc->mbuf_alloc_failed++);
+//
- /* This is a new mbuf allocation. */
- MGETHDR(m_new, M_DONTWAIT, MT_DATA);
- if (m_new == NULL) {
+ rc = ENOBUFS;
+ goto bce_get_buf_exit;
+ }
+//
+ DBRUNIF(1, sc->rx_mbuf_alloc++);
+ if (sc->mbuf_alloc_size == MCLBYTES)
+ MCLGET(m_new, M_DONTWAIT);
+ else
+ m_cljget(m_new, M_DONTWAIT, sc->mbuf_alloc_size);
+ if (!(m_new->m_flags & M_EXT)) {
+ DBPRINT(sc, BCE_WARN,
+ "%s(%d): RX mbuf chain allocation failed!\n",
+ __FILE__, __LINE__);
- DBPRINT(sc, BCE_WARN, "%s(%d): RX mbuf header
allocation failed!\n",
- __FILE__, __LINE__);
+ m_freem(m_new);
+//
+ DBRUNIF(1, sc->rx_mbuf_alloc--);
+ DBRUNIF(1, sc->mbuf_alloc_failed++);
- DBRUNIF(1, sc->mbuf_alloc_failed++);
+ rc = ENOBUFS;
+ goto bce_get_buf_exit;
+ }
- rc = ENOBUFS;
- goto bce_get_buf_exit;
- }
+ } else {
+ m_new = m;
+ m = NULL;
+ m_new->m_data = m_new->m_ext.ext_buf;
+ }
+ m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size;
+//
- DBRUNIF(1, sc->rx_mbuf_alloc++);
- m_cljget(m_new, M_DONTWAIT, sc->mbuf_alloc_size);
- if (!(m_new->m_flags & M_EXT)) {
-
- DBPRINT(sc, BCE_WARN, "%s(%d): RX mbuf chain allocation
failed!\n",
- __FILE__, __LINE__);
-
+ /* Map the mbuf cluster into device memory. */
+ map = sc->rx_mbuf_map[*chain_prod];
+ first_chain_prod = *chain_prod;
+ if (bus_dmamap_load_mbuf_sg(sc->rx_mbuf_tag, map, m_new, segs, &nsegs,
BUS_DMA_NOWAIT)) {
+ BCE_PRINTF("%s(%d): Error mapping mbuf into RX chain!\n",
+ __FILE__, __LINE__);
+//
m_freem(m_new);
DBRUNIF(1, sc->rx_mbuf_alloc--);
- DBRUNIF(1, sc->mbuf_alloc_failed++);
rc = ENOBUFS;
goto bce_get_buf_exit;
}
- m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size;
- } else {
- m_new = m;
- m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size;
- m_new->m_data = m_new->m_ext.ext_buf;
- }
+ bus_dmamap_sync(sc->rx_mbuf_tag, map, BUS_DMASYNC_PREREAD);
+//
- /* Map the mbuf cluster into device memory. */
- map = sc->rx_mbuf_map[*chain_prod];
- error = bus_dmamap_load_mbuf_sg(sc->rx_mbuf_tag, map, m_new,
- segs, &nsegs, BUS_DMA_NOWAIT);
- if (error) {
- BCE_PRINTF("%s(%d): Error mapping mbuf into RX chain!\n",
- __FILE__, __LINE__);
+ /* Watch for overflow. */
+ DBRUNIF((sc->free_rx_bd > USABLE_RX_BD),
+ BCE_PRINTF("%s(%d): Too many free rx_bd (0x%04X > 0x%04X)!\n",
+ __FILE__, __LINE__, sc->free_rx_bd, (u16) USABLE_RX_BD));
- m_freem(m_new);
+ /* Update some debug statistic counters */
+ DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
+ sc->rx_low_watermark = sc->free_rx_bd);
+ DBRUNIF((sc->free_rx_bd == 0), sc->rx_empty_count++);
- DBRUNIF(1, sc->rx_mbuf_alloc--);
+ /*
+ * Setup the rx_bd for the first segment
+ */
+ rxbd =
&sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
- rc = ENOBUFS;
- goto bce_get_buf_exit;
- }
+ rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[0].ds_addr));
+ rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[0].ds_addr));
+ rxbd->rx_bd_len = htole32(segs[0].ds_len);
+ rxbd->rx_bd_flags = htole32(RX_BD_FLAGS_START);
+ *prod_bseq += segs[0].ds_len;
+ bus_dmamap_sync(sc->rx_mbuf_tag,
+ sc->rx_bd_chain_map[RX_PAGE(*chain_prod)],
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ for (i = 1; i < nsegs; i++) {
+ *prod = NEXT_RX_BD(*prod);
+ *chain_prod = RX_CHAIN_IDX(*prod);
- /* Watch for overflow. */
- DBRUNIF((sc->free_rx_bd > USABLE_RX_BD),
- BCE_PRINTF("%s(%d): Too many free rx_bd (0x%04X > 0x%04X)!\n",
- __FILE__, __LINE__, sc->free_rx_bd, (u16)
USABLE_RX_BD));
+ rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
+ rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr));
+ rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr));
+ rxbd->rx_bd_len = htole32(segs[i].ds_len);
+ rxbd->rx_bd_flags = 0;
+ *prod_bseq += segs[i].ds_len;
- /* Update some debug statistic counters */
- DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
- sc->rx_low_watermark = sc->free_rx_bd);
- DBRUNIF((sc->free_rx_bd == 0), sc->rx_empty_count++);
+ bus_dmamap_sync(sc->rx_mbuf_tag,
+ sc->rx_bd_chain_map[RX_PAGE(*chain_prod)],
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ }
- /* Setup the rx_bd for the first segment. */
- rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
+ rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END);
+ bus_dmamap_sync(sc->rx_mbuf_tag,
+ sc->rx_bd_chain_map[RX_PAGE(*chain_prod)],
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[0].ds_addr));
- rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[0].ds_addr));
- rxbd->rx_bd_len = htole32(segs[0].ds_len);
- rxbd->rx_bd_flags = htole32(RX_BD_FLAGS_START);
- *prod_bseq += segs[0].ds_len;
+ /*
+ * Save the mbuf, ajust the map pointer (swap map for first and
+ * last rx_bd entry to that rx_mbuf_ptr and rx_mbuf_map matches)
+ * and update counter.
+ */
+ sc->rx_mbuf_ptr[*chain_prod] = m_new;
+ sc->rx_mbuf_map[first_chain_prod] = sc->rx_mbuf_map[*chain_prod];
+ sc->rx_mbuf_map[*chain_prod] = map;
+ sc->free_rx_bd -= nsegs;
- for (i = 1; i < nsegs; i++) {
- *prod = NEXT_RX_BD(*prod);
- *chain_prod = RX_CHAIN_IDX(*prod);
+ DBRUN(BCE_VERBOSE_RECV, bce_dump_rx_mbuf_chain(sc, debug_chain_prod,
+ nsegs));
+ *prod = NEXT_RX_BD(*prod);
+ *chain_prod = RX_CHAIN_IDX(*prod);
+ }
- rxbd =
&sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
- rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr));
- rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr));
- rxbd->rx_bd_len = htole32(segs[i].ds_len);
- rxbd->rx_bd_flags = 0;
- *prod_bseq += segs[i].ds_len;
- }
-
- rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END);
-
- /* Save the mbuf and update our counter. */
- sc->rx_mbuf_ptr[*chain_prod] = m_new;
- sc->free_rx_bd -= nsegs;
-
- DBRUN(BCE_VERBOSE_RECV, bce_dump_rx_mbuf_chain(sc, debug_chain_prod,
- nsegs));
-
+bce_get_buf_exit:
DBPRINT(sc, BCE_VERBOSE_RECV, "%s(exit): prod = 0x%04X, chain_prod =
0x%04X, "
"prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod,
*prod_bseq);
-bce_get_buf_exit:
DBPRINT(sc, (BCE_VERBOSE_RESET | BCE_VERBOSE_RECV), "Exiting %s()\n",
__FUNCTION__);
@@ -3773,16 +3807,11 @@
/* Allocate mbuf clusters for the rx_bd chain. */
prod = prod_bseq = 0;
- while (prod < TOTAL_RX_BD) {
- chain_prod = RX_CHAIN_IDX(prod);
- if (bce_get_buf(sc, NULL, &prod, &chain_prod, &prod_bseq)) {
- BCE_PRINTF("%s(%d): Error filling RX chain:
rx_bd[0x%04X]!\n",
- __FILE__, __LINE__, chain_prod);
- rc = ENOBUFS;
- break;
- }
- prod = NEXT_RX_BD(prod);
- }
+ chain_prod = RX_CHAIN_IDX(prod);
+ if (bce_get_buf(sc, NULL, &prod, &chain_prod, &prod_bseq)) {
+ BCE_PRINTF(
+ "Error filling RX chain: rx_bd[0x%04X]!\n", chain_prod);
+ }
/* Save the RX chain producer index. */
sc->rx_prod = prod;
@@ -4045,13 +4074,14 @@
/* The mbuf is stored with the last rx_bd entry of a packet. */
if (sc->rx_mbuf_ptr[sw_chain_cons] != NULL) {
-
+#ifdef BCE_DEBUG
/* Validate that this is the last rx_bd. */
- DBRUNIF((!(rxbd->rx_bd_flags & RX_BD_FLAGS_END)),
+ if ((rxbd->rx_bd_flags & RX_BD_FLAGS_END) == 0) {
BCE_PRINTF("%s(%d): Unexpected mbuf found in
rx_bd[0x%04X]!\n",
__FILE__, __LINE__, sw_chain_cons);
- bce_breakpoint(sc));
-
+// bce_breakpoint(sc));
+ }
+#endif
/*
* ToDo: If the received packet is small enough
* to fit into a single, non-M_EXT mbuf,
@@ -4117,7 +4147,7 @@
}
m = NULL;
- goto bce_rx_int_next_rx;
+ continue;
}
/*
@@ -4143,7 +4173,7 @@
}
m = NULL;
- goto bce_rx_int_next_rx;
+ continue;
}
/* Skip over the l2_fhdr when passing the data up the
stack. */
@@ -4215,7 +4245,6 @@
/* Pass the mbuf off to the upper layers. */
ifp->if_ipackets++;
-bce_rx_int_next_rx:
sw_prod = NEXT_RX_BD(sw_prod);
}
@@ -4475,9 +4504,15 @@
bce_set_mac_addr(sc);
/* Calculate and program the Ethernet MTU size. */
- ether_mtu = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ifp->if_mtu +
- ETHER_CRC_LEN;
+ if (ifp->if_mtu <= ETHERMTU) {
+ ether_mtu = BCE_MAX_STD_ETHER_MTU_VLAN;
+ sc->mbuf_alloc_size = MCLBYTES;
+ } else {
+ ether_mtu = BCE_MAX_JUMBO_ETHER_MTU_VLAN;
+ sc->mbuf_alloc_size = BCE_MAX_MTU;
+ }
+
DBPRINT(sc, BCE_INFO_MISC, "%s(): setting mtu = %d\n",__FUNCTION__,
ether_mtu);
/*
@@ -4488,10 +4523,8 @@
if (ether_mtu > ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) {
REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, min(ether_mtu,
BCE_MAX_JUMBO_ETHER_MTU) |
BCE_EMAC_RX_MTU_SIZE_JUMBO_ENA);
- sc->mbuf_alloc_size = MJUM9BYTES;
} else {
REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu);
- sc->mbuf_alloc_size = MCLBYTES;
}
/* Calculate the RX Ethernet frame size for rx_bd's. */
@@ -5640,6 +5673,8 @@
struct bce_softc *sc = xsc;
struct mii_data *mii;
struct ifnet *ifp;
+ u16 prod, chain_prod;
+ u32 prod_bseq;
ifp = sc->bce_ifp;
@@ -5675,6 +5710,13 @@
}
bce_tick_locked_exit:
+ /* try to get more RX buffers, just in case */
+ prod = sc->rx_prod;
+ prod_bseq = sc->rx_prod_bseq;
+ chain_prod = RX_CHAIN_IDX(prod);
+ bce_get_buf(sc, NULL, &prod, &chain_prod, &prod_bseq);
+ sc->rx_prod = prod;
+ sc->rx_prod_bseq = prod_bseq;
return;
}
Index: if_bcereg.h
===================================================================
--- if_bcereg.h (revision 67)
+++ if_bcereg.h (revision 74)
@@ -4682,7 +4682,7 @@
#define BCE_MAX_JUMBO_ETHER_MTU 9018
#define BCE_MAX_JUMBO_ETHER_MTU_VLAN 9022
-// #define BCE_MAX_MTU ETHER_MAX_LEN_JUMBO + ETHER_VLAN_ENCAP_LEN
/* 9022 */
+#define BCE_MAX_MTU 9216
/****************************************************************************/
/* BCE Device State Data Structure */
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"