Skip to content

Commit 622c36f

Browse files
tlendackydavem330
authored andcommitted
amd-xgbe: Fix jumbo MTU processing on newer hardware
Newer hardware does not provide a cumulative payload length when multiple descriptors are needed to handle the data. Once the MTU increases beyond the size that can be handled by a single descriptor, the SKB does not get built properly by the driver. The driver will now calculate the size of the data buffers used by the hardware. The first buffer of the first descriptor is for packet headers or packet headers and data when the headers can't be split. Subsequent descriptors in a multi-descriptor chain will not use the first buffer. The second buffer is used by all the descriptors in the chain for payload data. Based on whether the driver is processing the first, intermediate, or last descriptor it can calculate the buffer usage and build the SKB properly. Tested and verified on both old and new hardware. Signed-off-by: Tom Lendacky <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5371bbf commit 622c36f

File tree

3 files changed

+78
-50
lines changed

3 files changed

+78
-50
lines changed

drivers/net/ethernet/amd/xgbe/xgbe-common.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,8 +1148,8 @@
11481148
#define RX_PACKET_ATTRIBUTES_CSUM_DONE_WIDTH 1
11491149
#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 1
11501150
#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1
1151-
#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX 2
1152-
#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH 1
1151+
#define RX_PACKET_ATTRIBUTES_LAST_INDEX 2
1152+
#define RX_PACKET_ATTRIBUTES_LAST_WIDTH 1
11531153
#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3
11541154
#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1
11551155
#define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4
@@ -1158,6 +1158,8 @@
11581158
#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1
11591159
#define RX_PACKET_ATTRIBUTES_RSS_HASH_INDEX 6
11601160
#define RX_PACKET_ATTRIBUTES_RSS_HASH_WIDTH 1
1161+
#define RX_PACKET_ATTRIBUTES_FIRST_INDEX 7
1162+
#define RX_PACKET_ATTRIBUTES_FIRST_WIDTH 1
11611163

11621164
#define RX_NORMAL_DESC0_OVT_INDEX 0
11631165
#define RX_NORMAL_DESC0_OVT_WIDTH 16

drivers/net/ethernet/amd/xgbe/xgbe-dev.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,10 +1896,15 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
18961896

18971897
/* Get the header length */
18981898
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) {
1899+
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
1900+
FIRST, 1);
18991901
rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
19001902
RX_NORMAL_DESC2, HL);
19011903
if (rdata->rx.hdr_len)
19021904
pdata->ext_stats.rx_split_header_packets++;
1905+
} else {
1906+
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
1907+
FIRST, 0);
19031908
}
19041909

19051910
/* Get the RSS hash */
@@ -1922,19 +1927,16 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
19221927
}
19231928
}
19241929

1925-
/* Get the packet length */
1926-
rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
1927-
1928-
if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) {
1929-
/* Not all the data has been transferred for this packet */
1930-
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
1931-
INCOMPLETE, 1);
1930+
/* Not all the data has been transferred for this packet */
1931+
if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD))
19321932
return 0;
1933-
}
19341933

19351934
/* This is the last of the data for this packet */
19361935
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
1937-
INCOMPLETE, 0);
1936+
LAST, 1);
1937+
1938+
/* Get the packet length */
1939+
rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
19381940

19391941
/* Set checksum done indicator as appropriate */
19401942
if (netdev->features & NETIF_F_RXCSUM)

drivers/net/ethernet/amd/xgbe/xgbe-drv.c

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,13 +1971,12 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
19711971
{
19721972
struct sk_buff *skb;
19731973
u8 *packet;
1974-
unsigned int copy_len;
19751974

19761975
skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len);
19771976
if (!skb)
19781977
return NULL;
19791978

1980-
/* Start with the header buffer which may contain just the header
1979+
/* Pull in the header buffer which may contain just the header
19811980
* or the header plus data
19821981
*/
19831982
dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base,
@@ -1986,30 +1985,49 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
19861985

19871986
packet = page_address(rdata->rx.hdr.pa.pages) +
19881987
rdata->rx.hdr.pa.pages_offset;
1989-
copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : len;
1990-
copy_len = min(rdata->rx.hdr.dma_len, copy_len);
1991-
skb_copy_to_linear_data(skb, packet, copy_len);
1992-
skb_put(skb, copy_len);
1993-
1994-
len -= copy_len;
1995-
if (len) {
1996-
/* Add the remaining data as a frag */
1997-
dma_sync_single_range_for_cpu(pdata->dev,
1998-
rdata->rx.buf.dma_base,
1999-
rdata->rx.buf.dma_off,
2000-
rdata->rx.buf.dma_len,
2001-
DMA_FROM_DEVICE);
2002-
2003-
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
2004-
rdata->rx.buf.pa.pages,
2005-
rdata->rx.buf.pa.pages_offset,
2006-
len, rdata->rx.buf.dma_len);
2007-
rdata->rx.buf.pa.pages = NULL;
2008-
}
1988+
skb_copy_to_linear_data(skb, packet, len);
1989+
skb_put(skb, len);
20091990

20101991
return skb;
20111992
}
20121993

1994+
static unsigned int xgbe_rx_buf1_len(struct xgbe_ring_data *rdata,
1995+
struct xgbe_packet_data *packet)
1996+
{
1997+
/* Always zero if not the first descriptor */
1998+
if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, FIRST))
1999+
return 0;
2000+
2001+
/* First descriptor with split header, return header length */
2002+
if (rdata->rx.hdr_len)
2003+
return rdata->rx.hdr_len;
2004+
2005+
/* First descriptor but not the last descriptor and no split header,
2006+
* so the full buffer was used
2007+
*/
2008+
if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST))
2009+
return rdata->rx.hdr.dma_len;
2010+
2011+
/* First descriptor and last descriptor and no split header, so
2012+
* calculate how much of the buffer was used
2013+
*/
2014+
return min_t(unsigned int, rdata->rx.hdr.dma_len, rdata->rx.len);
2015+
}
2016+
2017+
static unsigned int xgbe_rx_buf2_len(struct xgbe_ring_data *rdata,
2018+
struct xgbe_packet_data *packet,
2019+
unsigned int len)
2020+
{
2021+
/* Always the full buffer if not the last descriptor */
2022+
if (!XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, LAST))
2023+
return rdata->rx.buf.dma_len;
2024+
2025+
/* Last descriptor so calculate how much of the buffer was used
2026+
* for the last bit of data
2027+
*/
2028+
return rdata->rx.len - len;
2029+
}
2030+
20132031
static int xgbe_tx_poll(struct xgbe_channel *channel)
20142032
{
20152033
struct xgbe_prv_data *pdata = channel->pdata;
@@ -2092,8 +2110,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
20922110
struct napi_struct *napi;
20932111
struct sk_buff *skb;
20942112
struct skb_shared_hwtstamps *hwtstamps;
2095-
unsigned int incomplete, error, context_next, context;
2096-
unsigned int len, rdesc_len, max_len;
2113+
unsigned int last, error, context_next, context;
2114+
unsigned int len, buf1_len, buf2_len, max_len;
20972115
unsigned int received = 0;
20982116
int packet_count = 0;
20992117

@@ -2103,7 +2121,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
21032121
if (!ring)
21042122
return 0;
21052123

2106-
incomplete = 0;
2124+
last = 0;
21072125
context_next = 0;
21082126

21092127
napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi;
@@ -2137,9 +2155,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
21372155
received++;
21382156
ring->cur++;
21392157

2140-
incomplete = XGMAC_GET_BITS(packet->attributes,
2141-
RX_PACKET_ATTRIBUTES,
2142-
INCOMPLETE);
2158+
last = XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
2159+
LAST);
21432160
context_next = XGMAC_GET_BITS(packet->attributes,
21442161
RX_PACKET_ATTRIBUTES,
21452162
CONTEXT_NEXT);
@@ -2148,7 +2165,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
21482165
CONTEXT);
21492166

21502167
/* Earlier error, just drain the remaining data */
2151-
if ((incomplete || context_next) && error)
2168+
if ((!last || context_next) && error)
21522169
goto read_again;
21532170

21542171
if (error || packet->errors) {
@@ -2160,16 +2177,22 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
21602177
}
21612178

21622179
if (!context) {
2163-
/* Length is cumulative, get this descriptor's length */
2164-
rdesc_len = rdata->rx.len - len;
2165-
len += rdesc_len;
2180+
/* Get the data length in the descriptor buffers */
2181+
buf1_len = xgbe_rx_buf1_len(rdata, packet);
2182+
len += buf1_len;
2183+
buf2_len = xgbe_rx_buf2_len(rdata, packet, len);
2184+
len += buf2_len;
21662185

2167-
if (rdesc_len && !skb) {
2186+
if (!skb) {
21682187
skb = xgbe_create_skb(pdata, napi, rdata,
2169-
rdesc_len);
2170-
if (!skb)
2188+
buf1_len);
2189+
if (!skb) {
21712190
error = 1;
2172-
} else if (rdesc_len) {
2191+
goto skip_data;
2192+
}
2193+
}
2194+
2195+
if (buf2_len) {
21732196
dma_sync_single_range_for_cpu(pdata->dev,
21742197
rdata->rx.buf.dma_base,
21752198
rdata->rx.buf.dma_off,
@@ -2179,13 +2202,14 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
21792202
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
21802203
rdata->rx.buf.pa.pages,
21812204
rdata->rx.buf.pa.pages_offset,
2182-
rdesc_len,
2205+
buf2_len,
21832206
rdata->rx.buf.dma_len);
21842207
rdata->rx.buf.pa.pages = NULL;
21852208
}
21862209
}
21872210

2188-
if (incomplete || context_next)
2211+
skip_data:
2212+
if (!last || context_next)
21892213
goto read_again;
21902214

21912215
if (!skb)
@@ -2243,7 +2267,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
22432267
}
22442268

22452269
/* Check if we need to save state before leaving */
2246-
if (received && (incomplete || context_next)) {
2270+
if (received && (!last || context_next)) {
22472271
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
22482272
rdata->state_saved = 1;
22492273
rdata->state.skb = skb;

0 commit comments

Comments
 (0)