Skip to content

Commit 7b5b1ee

Browse files
jahay1gregkh
authored andcommitted
idpf: stop Tx if there are insufficient buffer resources
[ Upstream commit 0c3f135 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent b2eb0df commit 7b5b1ee

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
@@ -2189,15 +2189,22 @@ void idpf_tx_splitq_build_flow_desc(union idpf_tx_flex_desc *desc,
21892189
desc->flow.qw1.compl_tag = cpu_to_le16(params->compl_tag);
21902190
}
21912191

2192-
/* Global conditions to tell whether the txq (and related resources)
2193-
* has room to allow the use of "size" descriptors.
2192+
/**
2193+
* idpf_tx_splitq_has_room - check if enough Tx splitq resources are available
2194+
* @tx_q: the queue to be checked
2195+
* @descs_needed: number of descriptors required for this packet
2196+
* @bufs_needed: number of Tx buffers required for this packet
2197+
*
2198+
* Return: 0 if no room available, 1 otherwise
21942199
*/
2195-
static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size)
2200+
static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 descs_needed,
2201+
u32 bufs_needed)
21962202
{
2197-
if (IDPF_DESC_UNUSED(tx_q) < size ||
2203+
if (IDPF_DESC_UNUSED(tx_q) < descs_needed ||
21982204
IDPF_TX_COMPLQ_PENDING(tx_q->txq_grp) >
21992205
IDPF_TX_COMPLQ_OVERFLOW_THRESH(tx_q->txq_grp->complq) ||
2200-
IDPF_TX_BUF_RSV_LOW(tx_q))
2206+
IDPF_TX_BUF_RSV_LOW(tx_q) ||
2207+
idpf_tx_splitq_get_free_bufs(tx_q->refillq) < bufs_needed)
22012208
return 0;
22022209
return 1;
22032210
}
@@ -2206,14 +2213,21 @@ static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size)
22062213
* idpf_tx_maybe_stop_splitq - 1st level check for Tx splitq stop conditions
22072214
* @tx_q: the queue to be checked
22082215
* @descs_needed: number of descriptors required for this packet
2216+
* @bufs_needed: number of buffers needed for this packet
22092217
*
2210-
* Returns 0 if stop is not needed
2218+
* Return: 0 if stop is not needed
22112219
*/
22122220
static int idpf_tx_maybe_stop_splitq(struct idpf_tx_queue *tx_q,
2213-
unsigned int descs_needed)
2221+
u32 descs_needed,
2222+
u32 bufs_needed)
22142223
{
2224+
/* Since we have multiple resources to check for splitq, our
2225+
* start,stop_thrs becomes a boolean check instead of a count
2226+
* threshold.
2227+
*/
22152228
if (netif_subqueue_maybe_stop(tx_q->netdev, tx_q->idx,
2216-
idpf_txq_has_room(tx_q, descs_needed),
2229+
idpf_txq_has_room(tx_q, descs_needed,
2230+
bufs_needed),
22172231
1, 1))
22182232
return 0;
22192233

@@ -2255,14 +2269,16 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val,
22552269
}
22562270

22572271
/**
2258-
* idpf_tx_desc_count_required - calculate number of Tx descriptors needed
2272+
* idpf_tx_res_count_required - get number of Tx resources needed for this pkt
22592273
* @txq: queue to send buffer on
22602274
* @skb: send buffer
2275+
* @bufs_needed: (output) number of buffers needed for this skb.
22612276
*
2262-
* Returns number of data descriptors needed for this skb.
2277+
* Return: number of data descriptors and buffers needed for this skb.
22632278
*/
2264-
unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
2265-
struct sk_buff *skb)
2279+
unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq,
2280+
struct sk_buff *skb,
2281+
u32 *bufs_needed)
22662282
{
22672283
const struct skb_shared_info *shinfo;
22682284
unsigned int count = 0, i;
@@ -2273,6 +2289,7 @@ unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
22732289
return count;
22742290

22752291
shinfo = skb_shinfo(skb);
2292+
*bufs_needed += shinfo->nr_frags;
22762293
for (i = 0; i < shinfo->nr_frags; i++) {
22772294
unsigned int size;
22782295

@@ -2875,11 +2892,11 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb,
28752892
};
28762893
union idpf_flex_tx_ctx_desc *ctx_desc;
28772894
struct idpf_tx_buf *first;
2878-
unsigned int count;
2895+
u32 count, buf_count = 1;
28792896
int tso, idx;
28802897
u32 buf_id;
28812898

2882-
count = idpf_tx_desc_count_required(tx_q, skb);
2899+
count = idpf_tx_res_count_required(tx_q, skb, &buf_count);
28832900
if (unlikely(!count))
28842901
return idpf_tx_drop_skb(tx_q, skb);
28852902

@@ -2889,7 +2906,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb,
28892906

28902907
/* Check for splitq specific TX resources */
28912908
count += (IDPF_TX_DESCS_PER_CACHE_LINE + tso);
2892-
if (idpf_tx_maybe_stop_splitq(tx_q, count)) {
2909+
if (idpf_tx_maybe_stop_splitq(tx_q, count, buf_count)) {
28932910
idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false);
28942911

28952912
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
@@ -1023,6 +1023,17 @@ static inline void idpf_vport_intr_set_wb_on_itr(struct idpf_q_vector *q_vector)
10231023
reg->dyn_ctl);
10241024
}
10251025

1026+
/**
1027+
* idpf_tx_splitq_get_free_bufs - get number of free buf_ids in refillq
1028+
* @refillq: pointer to refillq containing buf_ids
1029+
*/
1030+
static inline u32 idpf_tx_splitq_get_free_bufs(struct idpf_sw_queue *refillq)
1031+
{
1032+
return (refillq->next_to_use > refillq->next_to_clean ?
1033+
0 : refillq->desc_count) +
1034+
refillq->next_to_use - refillq->next_to_clean - 1;
1035+
}
1036+
10261037
int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget);
10271038
void idpf_vport_init_num_qs(struct idpf_vport *vport,
10281039
struct virtchnl2_create_vport *vport_msg);
@@ -1050,8 +1061,8 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val,
10501061
bool xmit_more);
10511062
unsigned int idpf_size_to_txd_count(unsigned int size);
10521063
netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb);
1053-
unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
1054-
struct sk_buff *skb);
1064+
unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq,
1065+
struct sk_buff *skb, u32 *buf_count);
10551066
void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue);
10561067
netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
10571068
struct idpf_tx_queue *tx_q);

0 commit comments

Comments
 (0)