mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-24 11:25:43 +00:00
ice: fix software generating extra interrupts
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: b7306b42be
("ice: manage interrupts during poll exit")
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Gurucharan G <gurucharanx.g@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
parent
d16a4f45f3
commit
23be7075b3
2 changed files with 16 additions and 11 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue