Skip to content

Commit 9c4a27d

Browse files
jahay1anguy11
authored andcommitted
idpf: enable WB_ON_ITR
Tell hardware to write back completed descriptors even when interrupts are disabled. Otherwise, descriptors might not be written back until the hardware can flush a full cacheline of descriptors. This can cause unnecessary delays when traffic is light (or even trigger Tx queue timeout). The example scenario to reproduce the Tx timeout if the fix is not applied: - configure at least 2 Tx queues to be assigned to the same q_vector, - generate a huge Tx traffic on the first Tx queue - try to send a few packets using the second Tx queue. In such a case Tx timeout will appear on the second Tx queue because no completion descriptors are written back for that queue while interrupts are disabled due to NAPI polling. Fixes: c2d548c ("idpf: add TX splitq napi poll support") Fixes: a5ab9ee ("idpf: add singleq start_xmit and napi poll") Signed-off-by: Joshua Hay <[email protected]> Co-developed-by: Michal Kubiak <[email protected]> Signed-off-by: Michal Kubiak <[email protected]> Reviewed-by: Przemek Kitszel <[email protected]> Signed-off-by: Alexander Lobakin <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent e4b398d commit 9c4a27d

File tree

5 files changed

+41
-3
lines changed

5 files changed

+41
-3
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ static int idpf_intr_reg_init(struct idpf_vport *vport)
9797
intr->dyn_ctl = idpf_get_reg_addr(adapter,
9898
reg_vals[vec_id].dyn_ctl_reg);
9999
intr->dyn_ctl_intena_m = PF_GLINT_DYN_CTL_INTENA_M;
100+
intr->dyn_ctl_intena_msk_m = PF_GLINT_DYN_CTL_INTENA_MSK_M;
100101
intr->dyn_ctl_itridx_s = PF_GLINT_DYN_CTL_ITR_INDX_S;
101102
intr->dyn_ctl_intrvl_s = PF_GLINT_DYN_CTL_INTERVAL_S;
103+
intr->dyn_ctl_wb_on_itr_m = PF_GLINT_DYN_CTL_WB_ON_ITR_M;
102104

103105
spacing = IDPF_ITR_IDX_SPACING(reg_vals[vec_id].itrn_index_spacing,
104106
IDPF_PF_ITR_IDX_SPACING);

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1120,8 +1120,10 @@ int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget)
11201120
&work_done);
11211121

11221122
/* If work not completed, return budget and polling will return */
1123-
if (!clean_complete)
1123+
if (!clean_complete) {
1124+
idpf_vport_intr_set_wb_on_itr(q_vector);
11241125
return budget;
1126+
}
11251127

11261128
work_done = min_t(int, work_done, budget - 1);
11271129

@@ -1130,6 +1132,8 @@ int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget)
11301132
*/
11311133
if (likely(napi_complete_done(napi, work_done)))
11321134
idpf_vport_intr_update_itr_ena_irq(q_vector);
1135+
else
1136+
idpf_vport_intr_set_wb_on_itr(q_vector);
11331137

11341138
return work_done;
11351139
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3715,6 +3715,7 @@ void idpf_vport_intr_update_itr_ena_irq(struct idpf_q_vector *q_vector)
37153715
/* net_dim() updates ITR out-of-band using a work item */
37163716
idpf_net_dim(q_vector);
37173717

3718+
q_vector->wb_on_itr = false;
37183719
intval = idpf_vport_intr_buildreg_itr(q_vector,
37193720
IDPF_NO_ITR_UPDATE_IDX, 0);
37203721

@@ -4017,8 +4018,10 @@ static int idpf_vport_splitq_napi_poll(struct napi_struct *napi, int budget)
40174018
clean_complete &= idpf_tx_splitq_clean_all(q_vector, budget, &work_done);
40184019

40194020
/* If work not completed, return budget and polling will return */
4020-
if (!clean_complete)
4021+
if (!clean_complete) {
4022+
idpf_vport_intr_set_wb_on_itr(q_vector);
40214023
return budget;
4024+
}
40224025

40234026
work_done = min_t(int, work_done, budget - 1);
40244027

@@ -4027,6 +4030,8 @@ static int idpf_vport_splitq_napi_poll(struct napi_struct *napi, int budget)
40274030
*/
40284031
if (likely(napi_complete_done(napi, work_done)))
40294032
idpf_vport_intr_update_itr_ena_irq(q_vector);
4033+
else
4034+
idpf_vport_intr_set_wb_on_itr(q_vector);
40304035

40314036
/* Switch to poll mode in the tear-down path after sending disable
40324037
* queues virtchnl message, as the interrupts will be disabled after

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,11 @@ struct idpf_vec_regs {
349349
* struct idpf_intr_reg
350350
* @dyn_ctl: Dynamic control interrupt register
351351
* @dyn_ctl_intena_m: Mask for dyn_ctl interrupt enable
352+
* @dyn_ctl_intena_msk_m: Mask for dyn_ctl interrupt enable mask
352353
* @dyn_ctl_itridx_s: Register bit offset for ITR index
353354
* @dyn_ctl_itridx_m: Mask for ITR index
354355
* @dyn_ctl_intrvl_s: Register bit offset for ITR interval
356+
* @dyn_ctl_wb_on_itr_m: Mask for WB on ITR feature
355357
* @rx_itr: RX ITR register
356358
* @tx_itr: TX ITR register
357359
* @icr_ena: Interrupt cause register offset
@@ -360,9 +362,11 @@ struct idpf_vec_regs {
360362
struct idpf_intr_reg {
361363
void __iomem *dyn_ctl;
362364
u32 dyn_ctl_intena_m;
365+
u32 dyn_ctl_intena_msk_m;
363366
u32 dyn_ctl_itridx_s;
364367
u32 dyn_ctl_itridx_m;
365368
u32 dyn_ctl_intrvl_s;
369+
u32 dyn_ctl_wb_on_itr_m;
366370
void __iomem *rx_itr;
367371
void __iomem *tx_itr;
368372
void __iomem *icr_ena;
@@ -383,6 +387,7 @@ struct idpf_intr_reg {
383387
* @intr_reg: See struct idpf_intr_reg
384388
* @napi: napi handler
385389
* @total_events: Number of interrupts processed
390+
* @wb_on_itr: whether WB on ITR is enabled
386391
* @tx_dim: Data for TX net_dim algorithm
387392
* @tx_itr_value: TX interrupt throttling rate
388393
* @tx_intr_mode: Dynamic ITR or not
@@ -413,6 +418,7 @@ struct idpf_q_vector {
413418
__cacheline_group_begin_aligned(read_write);
414419
struct napi_struct napi;
415420
u16 total_events;
421+
bool wb_on_itr;
416422

417423
struct dim tx_dim;
418424
u16 tx_itr_value;
@@ -431,7 +437,7 @@ struct idpf_q_vector {
431437
cpumask_var_t affinity_mask;
432438
__cacheline_group_end_aligned(cold);
433439
};
434-
libeth_cacheline_set_assert(struct idpf_q_vector, 104,
440+
libeth_cacheline_set_assert(struct idpf_q_vector, 112,
435441
424 + 2 * sizeof(struct dim),
436442
8 + sizeof(cpumask_var_t));
437443

@@ -987,6 +993,25 @@ static inline void idpf_tx_splitq_build_desc(union idpf_tx_flex_desc *desc,
987993
idpf_tx_splitq_build_flow_desc(desc, params, td_cmd, size);
988994
}
989995

996+
/**
997+
* idpf_vport_intr_set_wb_on_itr - enable descriptor writeback on disabled interrupts
998+
* @q_vector: pointer to queue vector struct
999+
*/
1000+
static inline void idpf_vport_intr_set_wb_on_itr(struct idpf_q_vector *q_vector)
1001+
{
1002+
struct idpf_intr_reg *reg;
1003+
1004+
if (q_vector->wb_on_itr)
1005+
return;
1006+
1007+
q_vector->wb_on_itr = true;
1008+
reg = &q_vector->intr_reg;
1009+
1010+
writel(reg->dyn_ctl_wb_on_itr_m | reg->dyn_ctl_intena_msk_m |
1011+
(IDPF_NO_ITR_UPDATE_IDX << reg->dyn_ctl_itridx_s),
1012+
reg->dyn_ctl);
1013+
}
1014+
9901015
int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget);
9911016
void idpf_vport_init_num_qs(struct idpf_vport *vport,
9921017
struct virtchnl2_create_vport *vport_msg);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ static int idpf_vf_intr_reg_init(struct idpf_vport *vport)
9797
intr->dyn_ctl = idpf_get_reg_addr(adapter,
9898
reg_vals[vec_id].dyn_ctl_reg);
9999
intr->dyn_ctl_intena_m = VF_INT_DYN_CTLN_INTENA_M;
100+
intr->dyn_ctl_intena_msk_m = VF_INT_DYN_CTLN_INTENA_MSK_M;
100101
intr->dyn_ctl_itridx_s = VF_INT_DYN_CTLN_ITR_INDX_S;
102+
intr->dyn_ctl_wb_on_itr_m = VF_INT_DYN_CTLN_WB_ON_ITR_M;
101103

102104
spacing = IDPF_ITR_IDX_SPACING(reg_vals[vec_id].itrn_index_spacing,
103105
IDPF_VF_ITR_IDX_SPACING);

0 commit comments

Comments
 (0)