summaryrefslogtreecommitdiffstats
path: root/sys/dev/e1000
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2014-10-11 22:13:24 +0000
committeradrian <adrian@FreeBSD.org>2014-10-11 22:13:24 +0000
commit7f559d779a9492c566771991039a750f92a94872 (patch)
treee09b30fda67ed2654cd86889fedf664f41b189d3 /sys/dev/e1000
parent5995ee9a987472a09da2186b9ef8efe23d83907d (diff)
downloadFreeBSD-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')
-rw-r--r--sys/dev/e1000/if_igb.c16
-rw-r--r--sys/dev/e1000/if_igb.h1
2 files changed, 8 insertions, 9 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;
}
diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h
index 0c44741..f2d0926 100644
--- a/sys/dev/e1000/if_igb.h
+++ b/sys/dev/e1000/if_igb.h
@@ -336,7 +336,6 @@ struct rx_ring {
struct lro_ctrl lro;
bool lro_enabled;
bool hdr_split;
- bool discard;
struct mtx rx_mtx;
char mtx_name[16];
u32 next_to_refresh;
OpenPOWER on IntegriCloud