Skip to content

Commit 4412288

Browse files
IronShendavem330
authored andcommitted
net: hns3: refine the flow director handle
In order to be compatible with aRFS rules, this patch adds spin_lock for flow director rule adding, deleting, querying, and packages the rule configuration. Signed-off-by: Jian Shen <[email protected]> Signed-off-by: Huazhong Tan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ffab969 commit 4412288

File tree

2 files changed

+112
-32
lines changed

2 files changed

+112
-32
lines changed

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

Lines changed: 99 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,8 +1226,10 @@ static int hclge_configure(struct hclge_dev *hdev)
12261226
hdev->tm_info.hw_pfc_map = 0;
12271227
hdev->wanted_umv_size = cfg.umv_space;
12281228

1229-
if (hnae3_dev_fd_supported(hdev))
1229+
if (hnae3_dev_fd_supported(hdev)) {
12301230
hdev->fd_en = true;
1231+
hdev->fd_active_type = HCLGE_FD_RULE_NONE;
1232+
}
12311233

12321234
ret = hclge_parse_speed(cfg.default_speed, &hdev->hw.mac.speed);
12331235
if (ret) {
@@ -4906,14 +4908,18 @@ static bool hclge_fd_rule_exist(struct hclge_dev *hdev, u16 location)
49064908
struct hclge_fd_rule *rule = NULL;
49074909
struct hlist_node *node2;
49084910

4911+
spin_lock_bh(&hdev->fd_rule_lock);
49094912
hlist_for_each_entry_safe(rule, node2, &hdev->fd_rule_list, rule_node) {
49104913
if (rule->location >= location)
49114914
break;
49124915
}
49134916

4917+
spin_unlock_bh(&hdev->fd_rule_lock);
4918+
49144919
return rule && rule->location == location;
49154920
}
49164921

4922+
/* make sure being called after lock up with fd_rule_lock */
49174923
static int hclge_fd_update_rule_list(struct hclge_dev *hdev,
49184924
struct hclge_fd_rule *new_rule,
49194925
u16 location,
@@ -4937,9 +4943,13 @@ static int hclge_fd_update_rule_list(struct hclge_dev *hdev,
49374943
kfree(rule);
49384944
hdev->hclge_fd_rule_num--;
49394945

4940-
if (!is_add)
4941-
return 0;
4946+
if (!is_add) {
4947+
if (!hdev->hclge_fd_rule_num)
4948+
hdev->fd_active_type = HCLGE_FD_RULE_NONE;
4949+
clear_bit(location, hdev->fd_bmap);
49424950

4951+
return 0;
4952+
}
49434953
} else if (!is_add) {
49444954
dev_err(&hdev->pdev->dev,
49454955
"delete fail, rule %d is inexistent\n",
@@ -4954,7 +4964,9 @@ static int hclge_fd_update_rule_list(struct hclge_dev *hdev,
49544964
else
49554965
hlist_add_head(&new_rule->rule_node, &hdev->fd_rule_list);
49564966

4967+
set_bit(location, hdev->fd_bmap);
49574968
hdev->hclge_fd_rule_num++;
4969+
hdev->fd_active_type = new_rule->rule_type;
49584970

49594971
return 0;
49604972
}
@@ -5112,6 +5124,36 @@ static int hclge_fd_get_tuple(struct hclge_dev *hdev,
51125124
return 0;
51135125
}
51145126

5127+
/* make sure being called after lock up with fd_rule_lock */
5128+
static int hclge_fd_config_rule(struct hclge_dev *hdev,
5129+
struct hclge_fd_rule *rule)
5130+
{
5131+
int ret;
5132+
5133+
if (!rule) {
5134+
dev_err(&hdev->pdev->dev,
5135+
"The flow director rule is NULL\n");
5136+
return -EINVAL;
5137+
}
5138+
5139+
/* it will never fail here, so needn't to check return value */
5140+
hclge_fd_update_rule_list(hdev, rule, rule->location, true);
5141+
5142+
ret = hclge_config_action(hdev, HCLGE_FD_STAGE_1, rule);
5143+
if (ret)
5144+
goto clear_rule;
5145+
5146+
ret = hclge_config_key(hdev, HCLGE_FD_STAGE_1, rule);
5147+
if (ret)
5148+
goto clear_rule;
5149+
5150+
return 0;
5151+
5152+
clear_rule:
5153+
hclge_fd_update_rule_list(hdev, rule, rule->location, false);
5154+
return ret;
5155+
}
5156+
51155157
static int hclge_add_fd_entry(struct hnae3_handle *handle,
51165158
struct ethtool_rxnfc *cmd)
51175159
{
@@ -5174,8 +5216,10 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
51745216
return -ENOMEM;
51755217

51765218
ret = hclge_fd_get_tuple(hdev, fs, rule);
5177-
if (ret)
5178-
goto free_rule;
5219+
if (ret) {
5220+
kfree(rule);
5221+
return ret;
5222+
}
51795223

51805224
rule->flow_type = fs->flow_type;
51815225

@@ -5184,23 +5228,13 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
51845228
rule->vf_id = dst_vport_id;
51855229
rule->queue_id = q_index;
51865230
rule->action = action;
5231+
rule->rule_type = HCLGE_FD_EP_ACTIVE;
51875232

5188-
ret = hclge_config_action(hdev, HCLGE_FD_STAGE_1, rule);
5189-
if (ret)
5190-
goto free_rule;
5191-
5192-
ret = hclge_config_key(hdev, HCLGE_FD_STAGE_1, rule);
5193-
if (ret)
5194-
goto free_rule;
5195-
5196-
ret = hclge_fd_update_rule_list(hdev, rule, fs->location, true);
5197-
if (ret)
5198-
goto free_rule;
5233+
spin_lock_bh(&hdev->fd_rule_lock);
5234+
ret = hclge_fd_config_rule(hdev, rule);
51995235

5200-
return ret;
5236+
spin_unlock_bh(&hdev->fd_rule_lock);
52015237

5202-
free_rule:
5203-
kfree(rule);
52045238
return ret;
52055239
}
52065240

@@ -5232,8 +5266,12 @@ static int hclge_del_fd_entry(struct hnae3_handle *handle,
52325266
if (ret)
52335267
return ret;
52345268

5235-
return hclge_fd_update_rule_list(hdev, NULL, fs->location,
5236-
false);
5269+
spin_lock_bh(&hdev->fd_rule_lock);
5270+
ret = hclge_fd_update_rule_list(hdev, NULL, fs->location, false);
5271+
5272+
spin_unlock_bh(&hdev->fd_rule_lock);
5273+
5274+
return ret;
52375275
}
52385276

52395277
static void hclge_del_all_fd_entries(struct hnae3_handle *handle,
@@ -5243,25 +5281,30 @@ static void hclge_del_all_fd_entries(struct hnae3_handle *handle,
52435281
struct hclge_dev *hdev = vport->back;
52445282
struct hclge_fd_rule *rule;
52455283
struct hlist_node *node;
5284+
u16 location;
52465285

52475286
if (!hnae3_dev_fd_supported(hdev))
52485287
return;
52495288

5289+
spin_lock_bh(&hdev->fd_rule_lock);
5290+
for_each_set_bit(location, hdev->fd_bmap,
5291+
hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1])
5292+
hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, location,
5293+
NULL, false);
5294+
52505295
if (clear_list) {
52515296
hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list,
52525297
rule_node) {
5253-
hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true,
5254-
rule->location, NULL, false);
52555298
hlist_del(&rule->rule_node);
52565299
kfree(rule);
5257-
hdev->hclge_fd_rule_num--;
52585300
}
5259-
} else {
5260-
hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list,
5261-
rule_node)
5262-
hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true,
5263-
rule->location, NULL, false);
5301+
hdev->fd_active_type = HCLGE_FD_RULE_NONE;
5302+
hdev->hclge_fd_rule_num = 0;
5303+
bitmap_zero(hdev->fd_bmap,
5304+
hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]);
52645305
}
5306+
5307+
spin_unlock_bh(&hdev->fd_rule_lock);
52655308
}
52665309

52675310
static int hclge_restore_fd_entries(struct hnae3_handle *handle)
@@ -5283,6 +5326,7 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle)
52835326
if (!hdev->fd_en)
52845327
return 0;
52855328

5329+
spin_lock_bh(&hdev->fd_rule_lock);
52865330
hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list, rule_node) {
52875331
ret = hclge_config_action(hdev, HCLGE_FD_STAGE_1, rule);
52885332
if (!ret)
@@ -5292,11 +5336,18 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle)
52925336
dev_warn(&hdev->pdev->dev,
52935337
"Restore rule %d failed, remove it\n",
52945338
rule->location);
5339+
clear_bit(rule->location, hdev->fd_bmap);
52955340
hlist_del(&rule->rule_node);
52965341
kfree(rule);
52975342
hdev->hclge_fd_rule_num--;
52985343
}
52995344
}
5345+
5346+
if (hdev->hclge_fd_rule_num)
5347+
hdev->fd_active_type = HCLGE_FD_EP_ACTIVE;
5348+
5349+
spin_unlock_bh(&hdev->fd_rule_lock);
5350+
53005351
return 0;
53015352
}
53025353

@@ -5329,13 +5380,18 @@ static int hclge_get_fd_rule_info(struct hnae3_handle *handle,
53295380

53305381
fs = (struct ethtool_rx_flow_spec *)&cmd->fs;
53315382

5383+
spin_lock_bh(&hdev->fd_rule_lock);
5384+
53325385
hlist_for_each_entry_safe(rule, node2, &hdev->fd_rule_list, rule_node) {
53335386
if (rule->location >= fs->location)
53345387
break;
53355388
}
53365389

5337-
if (!rule || fs->location != rule->location)
5390+
if (!rule || fs->location != rule->location) {
5391+
spin_unlock_bh(&hdev->fd_rule_lock);
5392+
53385393
return -ENOENT;
5394+
}
53395395

53405396
fs->flow_type = rule->flow_type;
53415397
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
@@ -5474,6 +5530,7 @@ static int hclge_get_fd_rule_info(struct hnae3_handle *handle,
54745530

54755531
break;
54765532
default:
5533+
spin_unlock_bh(&hdev->fd_rule_lock);
54775534
return -EOPNOTSUPP;
54785535
}
54795536

@@ -5505,6 +5562,8 @@ static int hclge_get_fd_rule_info(struct hnae3_handle *handle,
55055562
fs->ring_cookie |= vf_id;
55065563
}
55075564

5565+
spin_unlock_bh(&hdev->fd_rule_lock);
5566+
55085567
return 0;
55095568
}
55105569

@@ -5522,15 +5581,20 @@ static int hclge_get_all_rules(struct hnae3_handle *handle,
55225581

55235582
cmd->data = hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1];
55245583

5584+
spin_lock_bh(&hdev->fd_rule_lock);
55255585
hlist_for_each_entry_safe(rule, node2,
55265586
&hdev->fd_rule_list, rule_node) {
5527-
if (cnt == cmd->rule_cnt)
5587+
if (cnt == cmd->rule_cnt) {
5588+
spin_unlock_bh(&hdev->fd_rule_lock);
55285589
return -EMSGSIZE;
5590+
}
55295591

55305592
rule_locs[cnt] = rule->location;
55315593
cnt++;
55325594
}
55335595

5596+
spin_unlock_bh(&hdev->fd_rule_lock);
5597+
55345598
cmd->rule_cnt = cnt;
55355599

55365600
return 0;
@@ -5565,10 +5629,12 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)
55655629
{
55665630
struct hclge_vport *vport = hclge_get_vport(handle);
55675631
struct hclge_dev *hdev = vport->back;
5632+
bool clear;
55685633

55695634
hdev->fd_en = enable;
5635+
clear = hdev->fd_active_type == HCLGE_FD_ARFS_ACTIVE ? true : false;
55705636
if (!enable)
5571-
hclge_del_all_fd_entries(handle, false);
5637+
hclge_del_all_fd_entries(handle, clear);
55725638
else
55735639
hclge_restore_fd_entries(handle);
55745640
}
@@ -8143,6 +8209,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
81438209

81448210
mutex_init(&hdev->vport_lock);
81458211
mutex_init(&hdev->vport_cfg_mutex);
8212+
spin_lock_init(&hdev->fd_rule_lock);
81468213

81478214
ret = hclge_pci_init(hdev);
81488215
if (ret) {

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,15 @@ static const struct key_info tuple_key_info[] = {
578578
#define MAX_KEY_BYTES (MAX_KEY_DWORDS * 4)
579579
#define MAX_META_DATA_LENGTH 32
580580

581+
/* assigned by firmware, the real filter number for each pf may be less */
582+
#define MAX_FD_FILTER_NUM 4096
583+
584+
enum HCLGE_FD_ACTIVE_RULE_TYPE {
585+
HCLGE_FD_RULE_NONE,
586+
HCLGE_FD_ARFS_ACTIVE,
587+
HCLGE_FD_EP_ACTIVE,
588+
};
589+
581590
enum HCLGE_FD_PACKET_TYPE {
582591
NIC_PACKET,
583592
ROCE_PACKET,
@@ -630,6 +639,7 @@ struct hclge_fd_rule {
630639
u16 vf_id;
631640
u16 queue_id;
632641
u16 location;
642+
enum HCLGE_FD_ACTIVE_RULE_TYPE rule_type;
633643
};
634644

635645
struct hclge_fd_ad_data {
@@ -809,7 +819,10 @@ struct hclge_dev {
809819

810820
struct hclge_fd_cfg fd_cfg;
811821
struct hlist_head fd_rule_list;
822+
spinlock_t fd_rule_lock; /* protect fd_rule_list and fd_bmap */
812823
u16 hclge_fd_rule_num;
824+
unsigned long fd_bmap[BITS_TO_LONGS(MAX_FD_FILTER_NUM)];
825+
enum HCLGE_FD_ACTIVE_RULE_TYPE fd_active_type;
813826
u8 fd_en;
814827

815828
u16 wanted_umv_size;

0 commit comments

Comments
 (0)