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 <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
5371bbf4b2
commit
622c36f143
@@ -1896,10 +1896,15 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
|
||||
|
||||
/* Get the header length */
|
||||
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD)) {
|
||||
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
||||
FIRST, 1);
|
||||
rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
|
||||
RX_NORMAL_DESC2, HL);
|
||||
if (rdata->rx.hdr_len)
|
||||
pdata->ext_stats.rx_split_header_packets++;
|
||||
} else {
|
||||
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
||||
FIRST, 0);
|
||||
}
|
||||
|
||||
/* Get the RSS hash */
|
||||
@@ -1922,19 +1927,16 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the packet length */
|
||||
rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
|
||||
|
||||
if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) {
|
||||
/* Not all the data has been transferred for this packet */
|
||||
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
||||
INCOMPLETE, 1);
|
||||
/* Not all the data has been transferred for this packet */
|
||||
if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the last of the data for this packet */
|
||||
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
|
||||
INCOMPLETE, 0);
|
||||
LAST, 1);
|
||||
|
||||
/* Get the packet length */
|
||||
rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
|
||||
|
||||
/* Set checksum done indicator as appropriate */
|
||||
if (netdev->features & NETIF_F_RXCSUM)
|
||||
|
Reference in New Issue
Block a user