Skip to content

Commit 04294e3

Browse files
anjalisinghai1Jeff Kirsher
authored andcommitted
i40e: FD filters flush policy changes
Since GLQF_FDCNT_0 register now has the right offset, use it to simplify our FD flush flow. If the filter add error happens to be for SB we just auto disable SB. If filter error happens to be for ATR, auto disable ATR and mark the state to FD_FLUSH_REQUESTED. Which gets cleared when flush completes. If we are entering flush too quickly (< 30 seconds) and we have quite a few SB rules, its time to disable ATR for good. Since SB + ATR rules is most likely making the FD table unstable. ATR can be re-enabled by turning ntuple off (ethtool -K ntuple off) and will remain off after turning ntuple on till it gets unstable again. Change-ID: I2154a2e0a5d44851a2f0eb8731e2f1d4a4d1acbc Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
1 parent 4205d37 commit 04294e3

File tree

3 files changed

+67
-20
lines changed

3 files changed

+67
-20
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ struct i40e_lump_tracking {
175175
#define I40E_FDIR_MAX_RAW_PACKET_SIZE 512
176176
#define I40E_FDIR_BUFFER_FULL_MARGIN 10
177177
#define I40E_FDIR_BUFFER_HEAD_ROOM 32
178+
#define I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR (I40E_FDIR_BUFFER_HEAD_ROOM * 4)
178179

179180
enum i40e_fd_stat_idx {
180181
I40E_FD_STAT_ATR,
@@ -636,9 +637,10 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
636637
int i40e_add_del_fdir(struct i40e_vsi *vsi,
637638
struct i40e_fdir_filter *input, bool add);
638639
void i40e_fdir_check_and_reenable(struct i40e_pf *pf);
639-
int i40e_get_current_fd_count(struct i40e_pf *pf);
640-
int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
641-
int i40e_get_current_atr_cnt(struct i40e_pf *pf);
640+
u32 i40e_get_current_fd_count(struct i40e_pf *pf);
641+
u32 i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
642+
u32 i40e_get_current_atr_cnt(struct i40e_pf *pf);
643+
u32 i40e_get_global_fd_count(struct i40e_pf *pf);
642644
bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
643645
void i40e_set_ethtool_ops(struct net_device *netdev);
644646
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5345,29 +5345,45 @@ static void i40e_service_event_complete(struct i40e_pf *pf)
53455345
* i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
53465346
* @pf: board private structure
53475347
**/
5348-
int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf)
5348+
u32 i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf)
53495349
{
5350-
int val, fcnt_prog;
5350+
u32 val, fcnt_prog;
53515351

53525352
val = rd32(&pf->hw, I40E_PFQF_FDSTAT);
53535353
fcnt_prog = (val & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK);
53545354
return fcnt_prog;
53555355
}
53565356

53575357
/**
5358-
* i40e_get_current_fd_count - Get the count of total FD filters programmed
5358+
* i40e_get_current_fd_count - Get total FD filters programmed for this PF
53595359
* @pf: board private structure
53605360
**/
5361-
int i40e_get_current_fd_count(struct i40e_pf *pf)
5361+
u32 i40e_get_current_fd_count(struct i40e_pf *pf)
53625362
{
5363-
int val, fcnt_prog;
5363+
u32 val, fcnt_prog;
5364+
53645365
val = rd32(&pf->hw, I40E_PFQF_FDSTAT);
53655366
fcnt_prog = (val & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) +
53665367
((val & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
53675368
I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
53685369
return fcnt_prog;
53695370
}
53705371

5372+
/**
5373+
* i40e_get_global_fd_count - Get total FD filters programmed on device
5374+
* @pf: board private structure
5375+
**/
5376+
u32 i40e_get_global_fd_count(struct i40e_pf *pf)
5377+
{
5378+
u32 val, fcnt_prog;
5379+
5380+
val = rd32(&pf->hw, I40E_GLQF_FDCNT_0);
5381+
fcnt_prog = (val & I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK) +
5382+
((val & I40E_GLQF_FDCNT_0_BESTCNT_MASK) >>
5383+
I40E_GLQF_FDCNT_0_BESTCNT_SHIFT);
5384+
return fcnt_prog;
5385+
}
5386+
53715387
/**
53725388
* i40e_fdir_check_and_reenable - Function to reenabe FD ATR or SB if disabled
53735389
* @pf: board private structure
@@ -5382,7 +5398,7 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
53825398
/* Check if, FD SB or ATR was auto disabled and if there is enough room
53835399
* to re-enable
53845400
*/
5385-
fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf);
5401+
fcnt_prog = i40e_get_global_fd_count(pf);
53865402
fcnt_avail = pf->fdir_pf_filter_count;
53875403
if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) ||
53885404
(pf->fd_add_err == 0) ||
@@ -5404,23 +5420,38 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
54045420
}
54055421

54065422
#define I40E_MIN_FD_FLUSH_INTERVAL 10
5423+
#define I40E_MIN_FD_FLUSH_SB_ATR_UNSTABLE 30
54075424
/**
54085425
* i40e_fdir_flush_and_replay - Function to flush all FD filters and replay SB
54095426
* @pf: board private structure
54105427
**/
54115428
static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
54125429
{
5430+
unsigned long min_flush_time;
54135431
int flush_wait_retry = 50;
5432+
bool disable_atr = false;
5433+
int fd_room;
54145434
int reg;
54155435

54165436
if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED)))
54175437
return;
54185438

54195439
if (time_after(jiffies, pf->fd_flush_timestamp +
54205440
(I40E_MIN_FD_FLUSH_INTERVAL * HZ))) {
5421-
set_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
5441+
/* If the flush is happening too quick and we have mostly
5442+
* SB rules we should not re-enable ATR for some time.
5443+
*/
5444+
min_flush_time = pf->fd_flush_timestamp
5445+
+ (I40E_MIN_FD_FLUSH_SB_ATR_UNSTABLE * HZ);
5446+
fd_room = pf->fdir_pf_filter_count - pf->fdir_pf_active_filters;
5447+
5448+
if (!(time_after(jiffies, min_flush_time)) &&
5449+
(fd_room < I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) {
5450+
dev_info(&pf->pdev->dev, "ATR disabled, not enough FD filter space.\n");
5451+
disable_atr = true;
5452+
}
5453+
54225454
pf->fd_flush_timestamp = jiffies;
5423-
pf->auto_disable_flags |= I40E_FLAG_FD_SB_ENABLED;
54245455
pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
54255456
/* flush all filters */
54265457
wr32(&pf->hw, I40E_PFQF_CTL_1,
@@ -5440,10 +5471,8 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
54405471
} else {
54415472
/* replay sideband filters */
54425473
i40e_fdir_filter_restore(pf->vsi[pf->lan_vsi]);
5443-
5444-
pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
5445-
pf->auto_disable_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
5446-
pf->auto_disable_flags &= ~I40E_FLAG_FD_SB_ENABLED;
5474+
if (!disable_atr)
5475+
pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
54475476
clear_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
54485477
dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n");
54495478
}
@@ -5454,7 +5483,7 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
54545483
* i40e_get_current_atr_count - Get the count of total FD ATR filters programmed
54555484
* @pf: board private structure
54565485
**/
5457-
int i40e_get_current_atr_cnt(struct i40e_pf *pf)
5486+
u32 i40e_get_current_atr_cnt(struct i40e_pf *pf)
54585487
{
54595488
return i40e_get_current_fd_count(pf) - pf->fdir_pf_active_filters;
54605489
}
@@ -5480,9 +5509,7 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)
54805509
if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED)))
54815510
return;
54825511

5483-
if ((pf->fd_add_err >= I40E_MAX_FD_PROGRAM_ERROR) &&
5484-
(i40e_get_current_atr_cnt(pf) >= pf->fd_atr_cnt) &&
5485-
(i40e_get_current_atr_cnt(pf) > pf->fdir_pf_filter_count))
5512+
if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
54865513
i40e_fdir_flush_and_replay(pf);
54875514

54885515
i40e_fdir_check_and_reenable(pf);

drivers/net/ethernet/intel/i40e/i40e_txrx.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,12 +471,27 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
471471
dev_warn(&pdev->dev, "ntuple filter loc = %d, could not be added\n",
472472
rx_desc->wb.qword0.hi_dword.fd_id);
473473

474+
/* Check if the programming error is for ATR.
475+
* If so, auto disable ATR and set a state for
476+
* flush in progress. Next time we come here if flush is in
477+
* progress do nothing, once flush is complete the state will
478+
* be cleared.
479+
*/
480+
if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state))
481+
return;
482+
474483
pf->fd_add_err++;
475484
/* store the current atr filter count */
476485
pf->fd_atr_cnt = i40e_get_current_atr_cnt(pf);
477486

487+
if ((rx_desc->wb.qword0.hi_dword.fd_id == 0) &&
488+
(pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)) {
489+
pf->auto_disable_flags |= I40E_FLAG_FD_ATR_ENABLED;
490+
set_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state);
491+
}
492+
478493
/* filter programming failed most likely due to table full */
479-
fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf);
494+
fcnt_prog = i40e_get_global_fd_count(pf);
480495
fcnt_avail = pf->fdir_pf_filter_count;
481496
/* If ATR is running fcnt_prog can quickly change,
482497
* if we are very close to full, it makes sense to disable
@@ -1926,6 +1941,9 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
19261941
if (!(pf->flags & I40E_FLAG_FD_ATR_ENABLED))
19271942
return;
19281943

1944+
if ((pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED))
1945+
return;
1946+
19291947
/* if sampling is disabled do nothing */
19301948
if (!tx_ring->atr_sample_rate)
19311949
return;

0 commit comments

Comments
 (0)