atl1c: improve performance by avoiding unnecessary pcie writes on xmit

The kernel has xmit_more facility that hints the networking driver xmit
path about whether more packets are coming soon. This information can be
used to avoid unnecessary expensive PCIe transaction per tx packet.

Max TX pps on Mikrotik 10/25G NIC in a Threadripper 3960X system
improved from 1150Kpps to 1700Kpps.

Testing L2 forwarding on AR8151 hardware did not reveal a measurable
increase in latency.

Signed-off-by: Gatis Peisenieks <gatis@mikrotik.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Gatis Peisenieks 2021-05-13 14:43:23 +03:00 committed by David S. Miller
parent f19d4997fd
commit d7ab6419bd
1 changed files with 8 additions and 4 deletions

View File

@ -2211,8 +2211,8 @@ err_dma:
return -1; return -1;
} }
static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, static void atl1c_tx_queue(struct atl1c_adapter *adapter,
struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) enum atl1c_trans_queue type)
{ {
struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
u16 reg; u16 reg;
@ -2238,6 +2238,7 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
if (atl1c_tpd_avail(adapter, type) < tpd_req) { if (atl1c_tpd_avail(adapter, type) < tpd_req) {
/* no enough descriptor, just stop queue */ /* no enough descriptor, just stop queue */
atl1c_tx_queue(adapter, type);
netif_stop_queue(netdev); netif_stop_queue(netdev);
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
@ -2246,6 +2247,7 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
/* do TSO and check sum */ /* do TSO and check sum */
if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) { if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) {
atl1c_tx_queue(adapter, type);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
@ -2270,8 +2272,10 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
atl1c_tx_rollback(adapter, tpd, type); atl1c_tx_rollback(adapter, tpd, type);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
} else { } else {
netdev_sent_queue(adapter->netdev, skb->len); bool more = netdev_xmit_more();
atl1c_tx_queue(adapter, skb, tpd, type);
if (__netdev_sent_queue(adapter->netdev, skb->len, more))
atl1c_tx_queue(adapter, type);
} }
return NETDEV_TX_OK; return NETDEV_TX_OK;