Commit eb79e640 authored by Lendacky, Thomas's avatar Lendacky, Thomas Committed by David S. Miller

amd-xgbe: Perform Tx coalescing on a packet basis

The current form of Tx coalescing works on a descriptor basis instead
of on a packet basis and doesn't take into account TSO packets. Update
the Tx coalescing support to work on a packet basis, taking into
account the number of packets associated with a TSO transmit. Also,
only activate the Tx timer if a timer value is set.
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 16978eb7
...@@ -1334,7 +1334,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) ...@@ -1334,7 +1334,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
struct xgbe_packet_data *packet = &ring->packet_data; struct xgbe_packet_data *packet = &ring->packet_data;
unsigned int csum, tso, vlan; unsigned int csum, tso, vlan;
unsigned int tso_context, vlan_context; unsigned int tso_context, vlan_context;
unsigned int tx_coalesce, tx_frames; unsigned int tx_set_ic;
int start_index = ring->cur; int start_index = ring->cur;
int i; int i;
...@@ -1357,10 +1357,26 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) ...@@ -1357,10 +1357,26 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
else else
vlan_context = 0; vlan_context = 0;
tx_coalesce = (pdata->tx_usecs || pdata->tx_frames) ? 1 : 0; /* Determine if an interrupt should be generated for this Tx:
tx_frames = pdata->tx_frames; * Interrupt:
if (tx_coalesce && !channel->tx_timer_active) * - Tx frame count exceeds the frame count setting
ring->coalesce_count = 0; * - Addition of Tx frame count to the frame count since the
* last interrupt was set exceeds the frame count setting
* No interrupt:
* - No frame count setting specified (ethtool -C ethX tx-frames 0)
* - Addition of Tx frame count to the frame count since the
* last interrupt was set does not exceed the frame count setting
*/
ring->coalesce_count += packet->tx_packets;
if (!pdata->tx_frames)
tx_set_ic = 0;
else if (packet->tx_packets > pdata->tx_frames)
tx_set_ic = 1;
else if ((ring->coalesce_count % pdata->tx_frames) <
packet->tx_packets)
tx_set_ic = 1;
else
tx_set_ic = 0;
rdata = XGBE_GET_DESC_DATA(ring, ring->cur); rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
rdesc = rdata->rdesc; rdesc = rdata->rdesc;
...@@ -1427,13 +1443,6 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) ...@@ -1427,13 +1443,6 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP))
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1); XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1);
/* Set IC bit based on Tx coalescing settings */
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
if (tx_coalesce && (!tx_frames ||
(++ring->coalesce_count % tx_frames)))
/* Clear IC bit */
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 0);
/* Mark it as First Descriptor */ /* Mark it as First Descriptor */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FD, 1); XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FD, 1);
...@@ -1478,13 +1487,6 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) ...@@ -1478,13 +1487,6 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L, XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L,
rdata->skb_dma_len); rdata->skb_dma_len);
/* Set IC bit based on Tx coalescing settings */
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
if (tx_coalesce && (!tx_frames ||
(++ring->coalesce_count % tx_frames)))
/* Clear IC bit */
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 0);
/* Set OWN bit */ /* Set OWN bit */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1); XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
...@@ -1500,6 +1502,10 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) ...@@ -1500,6 +1502,10 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
/* Set LAST bit for the last descriptor */ /* Set LAST bit for the last descriptor */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1); XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1);
/* Set IC bit based on Tx coalescing settings */
if (tx_set_ic)
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
/* Save the Tx info to report back during cleanup */ /* Save the Tx info to report back during cleanup */
rdata->tx.packets = packet->tx_packets; rdata->tx.packets = packet->tx_packets;
rdata->tx.bytes = packet->tx_bytes; rdata->tx.bytes = packet->tx_bytes;
...@@ -1530,7 +1536,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) ...@@ -1530,7 +1536,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
lower_32_bits(rdata->rdesc_dma)); lower_32_bits(rdata->rdesc_dma));
/* Start the Tx coalescing timer */ /* Start the Tx coalescing timer */
if (tx_coalesce && !channel->tx_timer_active) { if (pdata->tx_usecs && !channel->tx_timer_active) {
channel->tx_timer_active = 1; channel->tx_timer_active = 1;
hrtimer_start(&channel->tx_timer, hrtimer_start(&channel->tx_timer,
ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC), ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment