Skip to content

Commit 1dc8b53

Browse files
Alexander DuyckJeff Kirsher
authored andcommitted
i40e: Reorder logic for coalescing RS bits
This patch reorders the logic at the end of i40e_tx_map to address the fact that the logic was rather convoluted and much larger than it needed to be. In order to try and coalesce the code paths I have updated some of the comments and repurposed some of the variables in order to reduce unnecessary overhead. This patch does the following: 1. Quit tracking skb->xmit_more with a flag, just max out packet_stride 2. Drop tail_bump and do_rs and instead just use desc_count and td_cmd 3. Pull comments from ixgbe that make need for wmb() more explicit. Change-ID: Ic7da85ec75043c634e87fef958109789bcc6317c Signed-off-by: Alexander Duyck <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 4b81644 commit 1dc8b53

File tree

4 files changed

+108
-104
lines changed

4 files changed

+108
-104
lines changed

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

Lines changed: 54 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw)
616616
return 0;
617617
}
618618

619-
#define WB_STRIDE 0x3
619+
#define WB_STRIDE 4
620620

621621
/**
622622
* i40e_clean_tx_irq - Reclaim resources after transmit completes
@@ -732,7 +732,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
732732
unsigned int j = i40e_get_tx_pending(tx_ring, false);
733733

734734
if (budget &&
735-
((j / (WB_STRIDE + 1)) == 0) && (j != 0) &&
735+
((j / WB_STRIDE) == 0) && (j > 0) &&
736736
!test_bit(__I40E_DOWN, &vsi->state) &&
737737
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
738738
tx_ring->arm_wb = true;
@@ -2700,9 +2700,7 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
27002700
u32 td_tag = 0;
27012701
dma_addr_t dma;
27022702
u16 gso_segs;
2703-
u16 desc_count = 0;
2704-
bool tail_bump = true;
2705-
bool do_rs = false;
2703+
u16 desc_count = 1;
27062704

27072705
if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
27082706
td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -2785,75 +2783,80 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
27852783
tx_bi = &tx_ring->tx_bi[i];
27862784
}
27872785

2788-
/* set next_to_watch value indicating a packet is present */
2789-
first->next_to_watch = tx_desc;
2786+
netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
27902787

27912788
i++;
27922789
if (i == tx_ring->count)
27932790
i = 0;
27942791

27952792
tx_ring->next_to_use = i;
27962793

2797-
netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
27982794
i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
27992795

2796+
/* write last descriptor with EOP bit */
2797+
td_cmd |= I40E_TX_DESC_CMD_EOP;
2798+
2799+
/* We can OR these values together as they both are checked against
2800+
* 4 below and at this point desc_count will be used as a boolean value
2801+
* after this if/else block.
2802+
*/
2803+
desc_count |= ++tx_ring->packet_stride;
2804+
28002805
/* Algorithm to optimize tail and RS bit setting:
2801-
* if xmit_more is supported
2802-
* if xmit_more is true
2803-
* do not update tail and do not mark RS bit.
2804-
* if xmit_more is false and last xmit_more was false
2805-
* if every packet spanned less than 4 desc
2806-
* then set RS bit on 4th packet and update tail
2807-
* on every packet
2808-
* else
2809-
* update tail and set RS bit on every packet.
2810-
* if xmit_more is false and last_xmit_more was true
2811-
* update tail and set RS bit.
2806+
* if queue is stopped
2807+
* mark RS bit
2808+
* reset packet counter
2809+
* else if xmit_more is supported and is true
2810+
* advance packet counter to 4
2811+
* reset desc_count to 0
28122812
*
2813-
* Optimization: wmb to be issued only in case of tail update.
2814-
* Also optimize the Descriptor WB path for RS bit with the same
2815-
* algorithm.
2813+
* if desc_count >= 4
2814+
* mark RS bit
2815+
* reset packet counter
2816+
* if desc_count > 0
2817+
* update tail
28162818
*
2817-
* Note: If there are less than 4 packets
2819+
* Note: If there are less than 4 descriptors
28182820
* pending and interrupts were disabled the service task will
28192821
* trigger a force WB.
28202822
*/
2821-
if (skb->xmit_more &&
2822-
!netif_xmit_stopped(txring_txq(tx_ring))) {
2823-
tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
2824-
tail_bump = false;
2825-
} else if (!skb->xmit_more &&
2826-
!netif_xmit_stopped(txring_txq(tx_ring)) &&
2827-
(!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) &&
2828-
(tx_ring->packet_stride < WB_STRIDE) &&
2829-
(desc_count < WB_STRIDE)) {
2830-
tx_ring->packet_stride++;
2831-
} else {
2823+
if (netif_xmit_stopped(txring_txq(tx_ring))) {
2824+
goto do_rs;
2825+
} else if (skb->xmit_more) {
2826+
/* set stride to arm on next packet and reset desc_count */
2827+
tx_ring->packet_stride = WB_STRIDE;
2828+
desc_count = 0;
2829+
} else if (desc_count >= WB_STRIDE) {
2830+
do_rs:
2831+
/* write last descriptor with RS bit set */
2832+
td_cmd |= I40E_TX_DESC_CMD_RS;
28322833
tx_ring->packet_stride = 0;
2833-
tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
2834-
do_rs = true;
28352834
}
2836-
if (do_rs)
2837-
tx_ring->packet_stride = 0;
28382835

28392836
tx_desc->cmd_type_offset_bsz =
2840-
build_ctob(td_cmd, td_offset, size, td_tag) |
2841-
cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD :
2842-
I40E_TX_DESC_CMD_EOP) <<
2843-
I40E_TXD_QW1_CMD_SHIFT);
2837+
build_ctob(td_cmd, td_offset, size, td_tag);
2838+
2839+
/* Force memory writes to complete before letting h/w know there
2840+
* are new descriptors to fetch.
2841+
*
2842+
* We also use this memory barrier to make certain all of the
2843+
* status bits have been updated before next_to_watch is written.
2844+
*/
2845+
wmb();
2846+
2847+
/* set next_to_watch value indicating a packet is present */
2848+
first->next_to_watch = tx_desc;
28442849

28452850
/* notify HW of packet */
2846-
if (!tail_bump) {
2847-
prefetchw(tx_desc + 1);
2848-
} else {
2849-
/* Force memory writes to complete before letting h/w
2850-
* know there are new descriptors to fetch. (Only
2851-
* applicable for weak-ordered memory model archs,
2852-
* such as IA-64).
2853-
*/
2854-
wmb();
2851+
if (desc_count) {
28552852
writel(i, tx_ring->tail);
2853+
2854+
/* we need this if more than one processor can write to our tail
2855+
* at a time, it synchronizes IO on IA64/Altix systems
2856+
*/
2857+
mmiowb();
28562858
}
2859+
28572860
return;
28582861

28592862
dma_error:

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ struct i40e_ring {
313313

314314
u16 flags;
315315
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)
316-
#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
317316

318317
/* stats structs */
319318
struct i40e_queue_stats stats;

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

Lines changed: 54 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ u32 i40evf_get_tx_pending(struct i40e_ring *ring, bool in_sw)
150150
return 0;
151151
}
152152

153-
#define WB_STRIDE 0x3
153+
#define WB_STRIDE 4
154154

155155
/**
156156
* i40e_clean_tx_irq - Reclaim resources after transmit completes
@@ -266,7 +266,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
266266
unsigned int j = i40evf_get_tx_pending(tx_ring, false);
267267

268268
if (budget &&
269-
((j / (WB_STRIDE + 1)) == 0) && (j > 0) &&
269+
((j / WB_STRIDE) == 0) && (j > 0) &&
270270
!test_bit(__I40E_DOWN, &vsi->state) &&
271271
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
272272
tx_ring->arm_wb = true;
@@ -1950,9 +1950,7 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
19501950
u32 td_tag = 0;
19511951
dma_addr_t dma;
19521952
u16 gso_segs;
1953-
u16 desc_count = 0;
1954-
bool tail_bump = true;
1955-
bool do_rs = false;
1953+
u16 desc_count = 1;
19561954

19571955
if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
19581956
td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -2035,75 +2033,80 @@ static inline void i40evf_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
20352033
tx_bi = &tx_ring->tx_bi[i];
20362034
}
20372035

2038-
/* set next_to_watch value indicating a packet is present */
2039-
first->next_to_watch = tx_desc;
2036+
netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
20402037

20412038
i++;
20422039
if (i == tx_ring->count)
20432040
i = 0;
20442041

20452042
tx_ring->next_to_use = i;
20462043

2047-
netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
20482044
i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
20492045

2046+
/* write last descriptor with EOP bit */
2047+
td_cmd |= I40E_TX_DESC_CMD_EOP;
2048+
2049+
/* We can OR these values together as they both are checked against
2050+
* 4 below and at this point desc_count will be used as a boolean value
2051+
* after this if/else block.
2052+
*/
2053+
desc_count |= ++tx_ring->packet_stride;
2054+
20502055
/* Algorithm to optimize tail and RS bit setting:
2051-
* if xmit_more is supported
2052-
* if xmit_more is true
2053-
* do not update tail and do not mark RS bit.
2054-
* if xmit_more is false and last xmit_more was false
2055-
* if every packet spanned less than 4 desc
2056-
* then set RS bit on 4th packet and update tail
2057-
* on every packet
2058-
* else
2059-
* update tail and set RS bit on every packet.
2060-
* if xmit_more is false and last_xmit_more was true
2061-
* update tail and set RS bit.
2056+
* if queue is stopped
2057+
* mark RS bit
2058+
* reset packet counter
2059+
* else if xmit_more is supported and is true
2060+
* advance packet counter to 4
2061+
* reset desc_count to 0
20622062
*
2063-
* Optimization: wmb to be issued only in case of tail update.
2064-
* Also optimize the Descriptor WB path for RS bit with the same
2065-
* algorithm.
2063+
* if desc_count >= 4
2064+
* mark RS bit
2065+
* reset packet counter
2066+
* if desc_count > 0
2067+
* update tail
20662068
*
2067-
* Note: If there are less than 4 packets
2069+
* Note: If there are less than 4 descriptors
20682070
* pending and interrupts were disabled the service task will
20692071
* trigger a force WB.
20702072
*/
2071-
if (skb->xmit_more &&
2072-
!netif_xmit_stopped(txring_txq(tx_ring))) {
2073-
tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
2074-
tail_bump = false;
2075-
} else if (!skb->xmit_more &&
2076-
!netif_xmit_stopped(txring_txq(tx_ring)) &&
2077-
(!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) &&
2078-
(tx_ring->packet_stride < WB_STRIDE) &&
2079-
(desc_count < WB_STRIDE)) {
2080-
tx_ring->packet_stride++;
2081-
} else {
2073+
if (netif_xmit_stopped(txring_txq(tx_ring))) {
2074+
goto do_rs;
2075+
} else if (skb->xmit_more) {
2076+
/* set stride to arm on next packet and reset desc_count */
2077+
tx_ring->packet_stride = WB_STRIDE;
2078+
desc_count = 0;
2079+
} else if (desc_count >= WB_STRIDE) {
2080+
do_rs:
2081+
/* write last descriptor with RS bit set */
2082+
td_cmd |= I40E_TX_DESC_CMD_RS;
20822083
tx_ring->packet_stride = 0;
2083-
tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
2084-
do_rs = true;
20852084
}
2086-
if (do_rs)
2087-
tx_ring->packet_stride = 0;
20882085

20892086
tx_desc->cmd_type_offset_bsz =
2090-
build_ctob(td_cmd, td_offset, size, td_tag) |
2091-
cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD :
2092-
I40E_TX_DESC_CMD_EOP) <<
2093-
I40E_TXD_QW1_CMD_SHIFT);
2087+
build_ctob(td_cmd, td_offset, size, td_tag);
2088+
2089+
/* Force memory writes to complete before letting h/w know there
2090+
* are new descriptors to fetch.
2091+
*
2092+
* We also use this memory barrier to make certain all of the
2093+
* status bits have been updated before next_to_watch is written.
2094+
*/
2095+
wmb();
2096+
2097+
/* set next_to_watch value indicating a packet is present */
2098+
first->next_to_watch = tx_desc;
20942099

20952100
/* notify HW of packet */
2096-
if (!tail_bump) {
2097-
prefetchw(tx_desc + 1);
2098-
} else {
2099-
/* Force memory writes to complete before letting h/w
2100-
* know there are new descriptors to fetch. (Only
2101-
* applicable for weak-ordered memory model archs,
2102-
* such as IA-64).
2103-
*/
2104-
wmb();
2101+
if (desc_count) {
21052102
writel(i, tx_ring->tail);
2103+
2104+
/* we need this if more than one processor can write to our tail
2105+
* at a time, it synchronizes IO on IA64/Altix systems
2106+
*/
2107+
mmiowb();
21062108
}
2109+
21072110
return;
21082111

21092112
dma_error:

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ struct i40e_ring {
309309
bool ring_active; /* is ring online or not */
310310
bool arm_wb; /* do something to arm write back */
311311
u8 packet_stride;
312-
#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
313312

314313
u16 flags;
315314
#define I40E_TXR_FLAGS_WB_ON_ITR BIT(0)

0 commit comments

Comments
 (0)