diff options
author | adrian <adrian@FreeBSD.org> | 2014-10-11 22:13:24 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2014-10-11 22:13:24 +0000 |
commit | 7f559d779a9492c566771991039a750f92a94872 (patch) | |
tree | e09b30fda67ed2654cd86889fedf664f41b189d3 /sys/dev/e1000/if_igb.c | |
parent | 5995ee9a987472a09da2186b9ef8efe23d83907d (diff) | |
download | FreeBSD-src-7f559d779a9492c566771991039a750f92a94872.zip FreeBSD-src-7f559d779a9492c566771991039a750f92a94872.tar.gz |
MFC r271784 - Fix the handling of EOP in status descriptors for if_igb(4)
and don't double-free mbufs.
Like ixgbe(4) chipsets, EOP is only set on the final descriptor
in a chain of descriptors. So, to free the whole list of descriptors,
we should free the current slot _and_ the assembled list of descriptors
that make up the fragment list.
The existing code was setting discard once it saw EOP + an error status;
it then freed all the subsequent descriptors until the next EOP. That's
totally the wrong order.
Diffstat (limited to 'sys/dev/e1000/if_igb.c')
-rw-r--r-- | sys/dev/e1000/if_igb.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index b1fc572..a14cb39 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -4397,7 +4397,6 @@ skip_head: rxr->fmp = NULL; rxr->lmp = NULL; - rxr->discard = FALSE; bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -4873,15 +4872,16 @@ igb_rxeof(struct igb_queue *que, int count, int *done) hdr = le16toh(cur->wb.lower.lo_dword.hs_rss.hdr_info); eop = ((staterr & E1000_RXD_STAT_EOP) == E1000_RXD_STAT_EOP); - /* Make sure all segments of a bad packet are discarded */ - if (((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) != 0) || - (rxr->discard)) { + /* + * Free the frame (all segments) if we're at EOP and + * it's an error. + * + * The datasheet states that EOP + status is only valid for + * the final segment in a multi-segment frame. + */ + if (eop && ((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) != 0)) { adapter->dropped_pkts++; ++rxr->rx_discarded; - if (!eop) /* Catch subsequent segs */ - rxr->discard = TRUE; - else - rxr->discard = FALSE; igb_rx_discard(rxr, i); goto next_desc; } |