Skip to content

Commit 0c1e44c

Browse files
jahay1PlaidCat
authored andcommitted
idpf: stop Tx if there are insufficient buffer resources
jira KERNEL-168 commit-author Joshua Hay <joshua.a.hay@intel.com> commit 0c3f135 upstream-diff | adjusted conflict in idpf_tx_splitq_frame func due to missing 1a49cf8 ("idpf: add Tx timestamp flows"). 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> (cherry picked from commit 0c3f135) Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
1 parent 95f47fc commit 0c1e44c

3 files changed

Lines changed: 47 additions & 19 deletions

File tree

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

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

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

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

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

2141-
/* Global conditions to tell whether the txq (and related resources)
2142-
* has room to allow the use of "size" descriptors.
2141+
/**
2142+
* idpf_tx_splitq_has_room - check if enough Tx splitq resources are available
2143+
* @tx_q: the queue to be checked
2144+
* @descs_needed: number of descriptors required for this packet
2145+
* @bufs_needed: number of Tx buffers required for this packet
2146+
*
2147+
* Return: 0 if no room available, 1 otherwise
21432148
*/
2144-
static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size)
2149+
static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 descs_needed,
2150+
u32 bufs_needed)
21452151
{
2146-
if (IDPF_DESC_UNUSED(tx_q) < size ||
2152+
if (IDPF_DESC_UNUSED(tx_q) < descs_needed ||
21472153
IDPF_TX_COMPLQ_PENDING(tx_q->txq_grp) >
21482154
IDPF_TX_COMPLQ_OVERFLOW_THRESH(tx_q->txq_grp->complq) ||
2149-
IDPF_TX_BUF_RSV_LOW(tx_q))
2155+
IDPF_TX_BUF_RSV_LOW(tx_q) ||
2156+
idpf_tx_splitq_get_free_bufs(tx_q->refillq) < bufs_needed)
21502157
return 0;
21512158
return 1;
21522159
}
@@ -2155,14 +2162,21 @@ static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size)
21552162
* idpf_tx_maybe_stop_splitq - 1st level check for Tx splitq stop conditions
21562163
* @tx_q: the queue to be checked
21572164
* @descs_needed: number of descriptors required for this packet
2165+
* @bufs_needed: number of buffers needed for this packet
21582166
*
2159-
* Returns 0 if stop is not needed
2167+
* Return: 0 if stop is not needed
21602168
*/
21612169
static int idpf_tx_maybe_stop_splitq(struct idpf_tx_queue *tx_q,
2162-
unsigned int descs_needed)
2170+
u32 descs_needed,
2171+
u32 bufs_needed)
21632172
{
2173+
/* Since we have multiple resources to check for splitq, our
2174+
* start,stop_thrs becomes a boolean check instead of a count
2175+
* threshold.
2176+
*/
21642177
if (netif_subqueue_maybe_stop(tx_q->netdev, tx_q->idx,
2165-
idpf_txq_has_room(tx_q, descs_needed),
2178+
idpf_txq_has_room(tx_q, descs_needed,
2179+
bufs_needed),
21662180
1, 1))
21672181
return 0;
21682182

@@ -2204,14 +2218,16 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val,
22042218
}
22052219

22062220
/**
2207-
* idpf_tx_desc_count_required - calculate number of Tx descriptors needed
2221+
* idpf_tx_res_count_required - get number of Tx resources needed for this pkt
22082222
* @txq: queue to send buffer on
22092223
* @skb: send buffer
2224+
* @bufs_needed: (output) number of buffers needed for this skb.
22102225
*
2211-
* Returns number of data descriptors needed for this skb.
2226+
* Return: number of data descriptors and buffers needed for this skb.
22122227
*/
2213-
unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
2214-
struct sk_buff *skb)
2228+
unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq,
2229+
struct sk_buff *skb,
2230+
u32 *bufs_needed)
22152231
{
22162232
const struct skb_shared_info *shinfo;
22172233
unsigned int count = 0, i;
@@ -2222,6 +2238,7 @@ unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
22222238
return count;
22232239

22242240
shinfo = skb_shinfo(skb);
2241+
*bufs_needed += shinfo->nr_frags;
22252242
for (i = 0; i < shinfo->nr_frags; i++) {
22262243
unsigned int size;
22272244

@@ -2771,11 +2788,11 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb,
27712788
.prev_ntu = tx_q->next_to_use,
27722789
};
27732790
struct idpf_tx_buf *first;
2774-
unsigned int count;
2791+
u32 count, buf_count = 1;
27752792
int tso;
27762793
u32 buf_id;
27772794

2778-
count = idpf_tx_desc_count_required(tx_q, skb);
2795+
count = idpf_tx_res_count_required(tx_q, skb, &buf_count);
27792796
if (unlikely(!count))
27802797
return idpf_tx_drop_skb(tx_q, skb);
27812798

@@ -2785,7 +2802,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb,
27852802

27862803
/* Check for splitq specific TX resources */
27872804
count += (IDPF_TX_DESCS_PER_CACHE_LINE + tso);
2788-
if (idpf_tx_maybe_stop_splitq(tx_q, count)) {
2805+
if (idpf_tx_maybe_stop_splitq(tx_q, count, buf_count)) {
27892806
idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false);
27902807

27912808
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
@@ -1112,6 +1112,17 @@ static inline void idpf_vport_intr_set_wb_on_itr(struct idpf_q_vector *q_vector)
11121112
reg->dyn_ctl);
11131113
}
11141114

1115+
/**
1116+
* idpf_tx_splitq_get_free_bufs - get number of free buf_ids in refillq
1117+
* @refillq: pointer to refillq containing buf_ids
1118+
*/
1119+
static inline u32 idpf_tx_splitq_get_free_bufs(struct idpf_sw_queue *refillq)
1120+
{
1121+
return (refillq->next_to_use > refillq->next_to_clean ?
1122+
0 : refillq->desc_count) +
1123+
refillq->next_to_use - refillq->next_to_clean - 1;
1124+
}
1125+
11151126
int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget);
11161127
void idpf_vport_init_num_qs(struct idpf_vport *vport,
11171128
struct virtchnl2_create_vport *vport_msg);
@@ -1142,8 +1153,8 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, u32 val,
11421153
bool xmit_more);
11431154
unsigned int idpf_size_to_txd_count(unsigned int size);
11441155
netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb);
1145-
unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
1146-
struct sk_buff *skb);
1156+
unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq,
1157+
struct sk_buff *skb, u32 *buf_count);
11471158
void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue);
11481159
netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
11491160
struct idpf_tx_queue *tx_q);

0 commit comments

Comments
 (0)