Skip to content

Commit 6a7fded

Browse files
anjalisinghai1Jeff Kirsher
authored andcommitted
i40e/i40evf: Fix RS bit update in Tx path and disable force WB workaround
This patch fixes the issue of forcing WB too often causing us to not benefit from NAPI. Without this patch we were forcing WB/arming interrupt too often taking away the benefits of NAPI and causing a performance impact. With this patch we disable force WB in the clean routine for X710 and XL710 adapters. X722 adapters do not enable interrupt to force a WB and benefit from WB_ON_ITR and hence force WB is left enabled for those adapters. For XL710 and X710 adapters if we have less than 4 packets pending a software Interrupt triggered from service task will force a WB. This patch also changes the conditions for setting RS bit as described in code comments. This optimizes when the HW does a tail bump amd when it does a WB. It also optimizes when we do a wmb. Change-ID: Id831e1ae7d3e2ec3f52cd0917b41ce1d22d75d9d Signed-off-by: Anjali Singhai Jain <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent acd6544 commit 6a7fded

File tree

2 files changed

+77
-43
lines changed

2 files changed

+77
-43
lines changed

drivers/net/ethernet/intel/i40evf/i40e_txrx.c

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -245,16 +245,6 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget)
245245
tx_ring->q_vector->tx.total_bytes += total_bytes;
246246
tx_ring->q_vector->tx.total_packets += total_packets;
247247

248-
/* check to see if there are any non-cache aligned descriptors
249-
* waiting to be written back, and kick the hardware to force
250-
* them to be written back in case of napi polling
251-
*/
252-
if (budget &&
253-
!((i & WB_STRIDE) == WB_STRIDE) &&
254-
!test_bit(__I40E_DOWN, &tx_ring->vsi->state) &&
255-
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
256-
tx_ring->arm_wb = true;
257-
258248
netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev,
259249
tx_ring->queue_index),
260250
total_packets, total_bytes);
@@ -1770,6 +1760,9 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
17701760
u32 td_tag = 0;
17711761
dma_addr_t dma;
17721762
u16 gso_segs;
1763+
u16 desc_count = 0;
1764+
bool tail_bump = true;
1765+
bool do_rs = false;
17731766

17741767
if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
17751768
td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -1810,6 +1803,8 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
18101803

18111804
tx_desc++;
18121805
i++;
1806+
desc_count++;
1807+
18131808
if (i == tx_ring->count) {
18141809
tx_desc = I40E_TX_DESC(tx_ring, 0);
18151810
i = 0;
@@ -1829,6 +1824,8 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
18291824

18301825
tx_desc++;
18311826
i++;
1827+
desc_count++;
1828+
18321829
if (i == tx_ring->count) {
18331830
tx_desc = I40E_TX_DESC(tx_ring, 0);
18341831
i = 0;
@@ -1843,35 +1840,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
18431840
tx_bi = &tx_ring->tx_bi[i];
18441841
}
18451842

1846-
/* Place RS bit on last descriptor of any packet that spans across the
1847-
* 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline.
1848-
*/
18491843
#define WB_STRIDE 0x3
1850-
if (((i & WB_STRIDE) != WB_STRIDE) &&
1851-
(first <= &tx_ring->tx_bi[i]) &&
1852-
(first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) {
1853-
tx_desc->cmd_type_offset_bsz =
1854-
build_ctob(td_cmd, td_offset, size, td_tag) |
1855-
cpu_to_le64((u64)I40E_TX_DESC_CMD_EOP <<
1856-
I40E_TXD_QW1_CMD_SHIFT);
1857-
} else {
1858-
tx_desc->cmd_type_offset_bsz =
1859-
build_ctob(td_cmd, td_offset, size, td_tag) |
1860-
cpu_to_le64((u64)I40E_TXD_CMD <<
1861-
I40E_TXD_QW1_CMD_SHIFT);
1862-
}
1863-
1864-
netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
1865-
tx_ring->queue_index),
1866-
first->bytecount);
1867-
1868-
/* Force memory writes to complete before letting h/w
1869-
* know there are new descriptors to fetch. (Only
1870-
* applicable for weak-ordered memory model archs,
1871-
* such as IA-64).
1872-
*/
1873-
wmb();
1874-
18751844
/* set next_to_watch value indicating a packet is present */
18761845
first->next_to_watch = tx_desc;
18771846

@@ -1881,15 +1850,78 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
18811850

18821851
tx_ring->next_to_use = i;
18831852

1853+
netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev,
1854+
tx_ring->queue_index),
1855+
first->bytecount);
18841856
i40evf_maybe_stop_tx(tx_ring, DESC_NEEDED);
1857+
1858+
/* Algorithm to optimize tail and RS bit setting:
1859+
* if xmit_more is supported
1860+
* if xmit_more is true
1861+
* do not update tail and do not mark RS bit.
1862+
* if xmit_more is false and last xmit_more was false
1863+
* if every packet spanned less than 4 desc
1864+
* then set RS bit on 4th packet and update tail
1865+
* on every packet
1866+
* else
1867+
* update tail and set RS bit on every packet.
1868+
* if xmit_more is false and last_xmit_more was true
1869+
* update tail and set RS bit.
1870+
* else (kernel < 3.18)
1871+
* if every packet spanned less than 4 desc
1872+
* then set RS bit on 4th packet and update tail
1873+
* on every packet
1874+
* else
1875+
* set RS bit on EOP for every packet and update tail
1876+
*
1877+
* Optimization: wmb to be issued only in case of tail update.
1878+
* Also optimize the Descriptor WB path for RS bit with the same
1879+
* algorithm.
1880+
*
1881+
* Note: If there are less than 4 packets
1882+
* pending and interrupts were disabled the service task will
1883+
* trigger a force WB.
1884+
*/
1885+
if (skb->xmit_more &&
1886+
!netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
1887+
tx_ring->queue_index))) {
1888+
tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
1889+
tail_bump = false;
1890+
} else if (!skb->xmit_more &&
1891+
!netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
1892+
tx_ring->queue_index)) &&
1893+
(!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) &&
1894+
(tx_ring->packet_stride < WB_STRIDE) &&
1895+
(desc_count < WB_STRIDE)) {
1896+
tx_ring->packet_stride++;
1897+
} else {
1898+
tx_ring->packet_stride = 0;
1899+
tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
1900+
do_rs = true;
1901+
}
1902+
if (do_rs)
1903+
tx_ring->packet_stride = 0;
1904+
1905+
tx_desc->cmd_type_offset_bsz =
1906+
build_ctob(td_cmd, td_offset, size, td_tag) |
1907+
cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD :
1908+
I40E_TX_DESC_CMD_EOP) <<
1909+
I40E_TXD_QW1_CMD_SHIFT);
1910+
18851911
/* notify HW of packet */
1886-
if (!skb->xmit_more ||
1887-
netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev,
1888-
tx_ring->queue_index)))
1889-
writel(i, tx_ring->tail);
1890-
else
1912+
if (!tail_bump)
18911913
prefetchw(tx_desc + 1);
18921914

1915+
if (tail_bump) {
1916+
/* Force memory writes to complete before letting h/w
1917+
* know there are new descriptors to fetch. (Only
1918+
* applicable for weak-ordered memory model archs,
1919+
* such as IA-64).
1920+
*/
1921+
wmb();
1922+
writel(i, tx_ring->tail);
1923+
}
1924+
18931925
return;
18941926

18951927
dma_error:

drivers/net/ethernet/intel/i40evf/i40e_txrx.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ struct i40e_ring {
268268

269269
bool ring_active; /* is ring online or not */
270270
bool arm_wb; /* do something to arm write back */
271+
u8 packet_stride;
272+
#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
271273

272274
u16 flags;
273275
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)

0 commit comments

Comments
 (0)