Skip to content

Commit

Permalink
ice: fix software generating extra interrupts
Browse files Browse the repository at this point in the history
The driver tried to work around missing completion events that occurred
while interrupts are disabled, by triggering a software interrupt
whenever we exit polling (but we had to have polled at least once).

This was causing a *lot* of extra interrupts for some workloads like
NVMe over TCP, which resulted in regressions in performance. It was also
visible when polling didn't prevent interrupts when busy_poll was
enabled.

Fix the extra interrupts by utilizing our previously unused 3rd ITR
(interrupt throttle) index and set it to 20K interrupts per second, and
then trigger a software interrupt within that rate limit.

While here, slightly refactor the code to avoid an overwrite of a local
variable in the case of wb_en = true.

Fixes: b7306b4 ("ice: manage interrupts during poll exit")
Signed-off-by: Jesse Brandeburg <[email protected]>
Tested-by: Gurucharan G <[email protected]>
Signed-off-by: Tony Nguyen <[email protected]>
  • Loading branch information
jbrandeb authored and anguy11 committed Oct 19, 2021
1 parent d16a4f4 commit 23be707
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 11 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/ice/ice_hw_autogen.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@
#define GLINT_DYN_CTL_INTERVAL_S 5
#define GLINT_DYN_CTL_INTERVAL_M ICE_M(0xFFF, 5)
#define GLINT_DYN_CTL_SW_ITR_INDX_ENA_M BIT(24)
#define GLINT_DYN_CTL_SW_ITR_INDX_S 25
#define GLINT_DYN_CTL_SW_ITR_INDX_M ICE_M(0x3, 25)
#define GLINT_DYN_CTL_WB_ON_ITR_M BIT(30)
#define GLINT_DYN_CTL_INTENA_MSK_M BIT(31)
Expand Down
26 changes: 15 additions & 11 deletions drivers/net/ethernet/intel/ice/ice_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1361,21 +1361,25 @@ static void ice_enable_interrupt(struct ice_q_vector *q_vector)
if (test_bit(ICE_DOWN, vsi->state))
return;

/* When exiting WB_ON_ITR, let ITR resume its normal
* interrupts-enabled path.
/* trigger an ITR delayed software interrupt when exiting busy poll, to
* make sure to catch any pending cleanups that might have been missed
* due to interrupt state transition. If busy poll or poll isn't
* enabled, then don't update ITR, and just enable the interrupt.
*/
if (wb_en)
if (!wb_en) {
itr_val = ice_buildreg_itr(ICE_ITR_NONE, 0);
} else {
q_vector->wb_on_itr = false;

itr_val = ice_buildreg_itr(ICE_ITR_NONE, 0);
/* trigger an immediate software interrupt when exiting
* busy poll, to make sure to catch any pending cleanups
* that might have been missed due to interrupt state
* transition.
*/
if (wb_en) {
/* do two things here with a single write. Set up the third ITR
* index to be used for software interrupt moderation, and then
* trigger a software interrupt with a rate limit of 20K on
* software interrupts, this will help avoid high interrupt
* loads due to frequently polling and exiting polling.
*/
itr_val = ice_buildreg_itr(ICE_IDX_ITR2, ICE_ITR_20K);
itr_val |= GLINT_DYN_CTL_SWINT_TRIG_M |
GLINT_DYN_CTL_SW_ITR_INDX_M |
ICE_IDX_ITR2 << GLINT_DYN_CTL_SW_ITR_INDX_S |
GLINT_DYN_CTL_SW_ITR_INDX_ENA_M;
}
wr32(&vsi->back->hw, GLINT_DYN_CTL(q_vector->reg_idx), itr_val);
Expand Down

0 comments on commit 23be707

Please sign in to comment.