Skip to content

Commit 0c3f135

Browse files
jahay1anguy11
authored andcommitted
idpf: stop Tx if there are insufficient buffer resources
The Tx refillq logic will cause packets to be silently dropped if there are not enough buffer resources available to send a packet in flow scheduling mode. Instead, determine how many buffers are needed along with number of descriptors. Make sure there are enough of both resources to send the packet, and stop the queue if not. Fixes: 7292af0 ("idpf: fix a race in txq wakeup") Signed-off-by: Joshua Hay <joshua.a.hay@intel.com> Reviewed-by: Madhu Chittim <madhu.chittim@intel.com> Tested-by: Samuel Salin <Samuel.salin@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent 5f417d5 commit 0c3f135

File tree

3 files changed

+47
-19
lines changed

3 files changed

+47
-19
lines changed

drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,11 @@ netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
415415
{
416416
struct idpf_tx_offload_params offload = { };
417417
struct idpf_tx_buf *first;
418+
u32 count, buf_count = 1;
418419
int csum, tso, needed;
419-
unsigned int count;
420420
__be16 protocol;
421421

422-
count = idpf_tx_desc_count_required(tx_q, skb);
422+
count = idpf_tx_res_count_required(tx_q, skb, &buf_count);
423423
if (unlikely(!count))
424424
return idpf_tx_drop_skb(tx_q, skb);
425425

drivers/net/ethernet/intel/idpf/idpf_txrx.c

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,15 +2191,22 @@ void idpf_tx_splitq_build_flow_desc(union idpf_tx_flex_desc *desc,
21912191
desc->flow.qw1.compl_tag = cpu_to_le16(params->compl_tag);
21922192
}
21932193

2194-
/* Global conditions to tell whether the txq (and related resources)
2195-
* has room to allow the use of "size" descriptors.
2194+
/**
2195+
* idpf_tx_splitq_has_room - check if enough Tx splitq resources are available
2196+
* @tx_q: the queue to be checked
2197+
* @descs_needed: number of descriptors required for this packet
2198+
* @bufs_needed: number of Tx buffers required for this packet
2199+
*
2200+
* Return: 0 if no room available, 1 otherwise
21962201
*/
2197-
static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size)
2202+
static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 descs_needed,
2203+
u32 bufs_needed)
21982204
{
2199-
if (IDPF_DESC_UNUSED(tx_q) < size ||
2205+
if (IDPF_DESC_UNUSED(tx_q) < descs_needed ||
22002206
IDPF_TX_COMPLQ_PENDING(tx_q->txq_grp) >
22012207
IDPF_TX_COMPLQ_OVERFLOW_THRESH(tx_q->txq_grp->complq) ||
2202-
IDPF_TX_BUF_RSV_LOW(tx_q))
2208+
IDPF_TX_BUF_RSV_LOW(tx_q) ||
2209+
idpf_tx_splitq_get_free_bufs(tx_q->refillq) < bufs_needed)
22032210
return 0;
22042211
return 1;
22052212
}
@@ -2208,14 +2215,21 @@ static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size)
22082215
* idpf_tx_maybe_stop_splitq - 1st level check for Tx splitq stop conditions
22092216
* @tx_q: the queue to be checked
22102217
* @descs_needed: number of descriptors required for this packet
2218+
* @bufs_needed: number of buffers needed for this packet
22112219
*
2212-
* Returns 0 if stop is not needed
2220+
* Return: 0 if stop is not needed
22132221
*/
22142222
static int idpf_tx_maybe_stop_splitq(struct idpf_tx_queue *tx_q,
2215-
unsigned int descs_needed)
2223+
u32 descs_needed,
2224+
u32 bufs_needed)
22162225
{
2226+
/* Since we have multiple resources to check for splitq, our
2227+
* start,stop_thrs becomes a boolean check instead of a count
2228+
* threshold.
2229+
*/
22172230
if (netif_subqueue_maybe_stop(tx_q->netdev, tx_q->idx,
2218-
idpf_txq_has_room(tx_q, descs_needed),
2231+
idpf_txq_has_room(tx_q, descs_needed,
2232+
bufs_needed),
22192233
1, 1))
22202234
return 0;
22212235

@@ -2257,14 +2271,16 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val,
22572271
}
22582272

22592273
/**
2260-
* idpf_tx_desc_count_required - calculate number of Tx descriptors needed
2274+
* idpf_tx_res_count_required - get number of Tx resources needed for this pkt
22612275
* @txq: queue to send buffer on
22622276
* @skb: send buffer
2277+
* @bufs_needed: (output) number of buffers needed for this skb.
22632278
*
2264-
* Returns number of data descriptors needed for this skb.
2279+
* Return: number of data descriptors and buffers needed for this skb.
22652280
*/
2266-
unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
2267-
struct sk_buff *skb)
2281+
unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq,
2282+
struct sk_buff *skb,
2283+
u32 *bufs_needed)
22682284
{
22692285
const struct skb_shared_info *shinfo;
22702286
unsigned int count = 0, i;
@@ -2275,6 +2291,7 @@ unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
22752291
return count;
22762292

22772293
shinfo = skb_shinfo(skb);
2294+
*bufs_needed += shinfo->nr_frags;
22782295
for (i = 0; i < shinfo->nr_frags; i++) {
22792296
unsigned int size;
22802297

@@ -2892,11 +2909,11 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb,
28922909
};
28932910
union idpf_flex_tx_ctx_desc *ctx_desc;
28942911
struct idpf_tx_buf *first;
2895-
unsigned int count;
2912+
u32 count, buf_count = 1;
28962913
int tso, idx;
28972914
u32 buf_id;
28982915

2899-
count = idpf_tx_desc_count_required(tx_q, skb);
2916+
count = idpf_tx_res_count_required(tx_q, skb, &buf_count);
29002917
if (unlikely(!count))
29012918
return idpf_tx_drop_skb(tx_q, skb);
29022919

@@ -2906,7 +2923,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb,
29062923

29072924
/* Check for splitq specific TX resources */
29082925
count += (IDPF_TX_DESCS_PER_CACHE_LINE + tso);
2909-
if (idpf_tx_maybe_stop_splitq(tx_q, count)) {
2926+
if (idpf_tx_maybe_stop_splitq(tx_q, count, buf_count)) {
29102927
idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false);
29112928

29122929
return NETDEV_TX_BUSY;

drivers/net/ethernet/intel/idpf/idpf_txrx.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,17 @@ static inline void idpf_vport_intr_set_wb_on_itr(struct idpf_q_vector *q_vector)
10261026
reg->dyn_ctl);
10271027
}
10281028

1029+
/**
1030+
* idpf_tx_splitq_get_free_bufs - get number of free buf_ids in refillq
1031+
* @refillq: pointer to refillq containing buf_ids
1032+
*/
1033+
static inline u32 idpf_tx_splitq_get_free_bufs(struct idpf_sw_queue *refillq)
1034+
{
1035+
return (refillq->next_to_use > refillq->next_to_clean ?
1036+
0 : refillq->desc_count) +
1037+
refillq->next_to_use - refillq->next_to_clean - 1;
1038+
}
1039+
10291040
int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget);
10301041
void idpf_vport_init_num_qs(struct idpf_vport *vport,
10311042
struct virtchnl2_create_vport *vport_msg);
@@ -1053,8 +1064,8 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val,
10531064
bool xmit_more);
10541065
unsigned int idpf_size_to_txd_count(unsigned int size);
10551066
netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb);
1056-
unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
1057-
struct sk_buff *skb);
1067+
unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq,
1068+
struct sk_buff *skb, u32 *buf_count);
10581069
void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue);
10591070
netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
10601071
struct idpf_tx_queue *tx_q);

0 commit comments

Comments
 (0)