@@ -1226,8 +1226,10 @@ static int hclge_configure(struct hclge_dev *hdev)
1226
1226
hdev -> tm_info .hw_pfc_map = 0 ;
1227
1227
hdev -> wanted_umv_size = cfg .umv_space ;
1228
1228
1229
- if (hnae3_dev_fd_supported (hdev ))
1229
+ if (hnae3_dev_fd_supported (hdev )) {
1230
1230
hdev -> fd_en = true;
1231
+ hdev -> fd_active_type = HCLGE_FD_RULE_NONE ;
1232
+ }
1231
1233
1232
1234
ret = hclge_parse_speed (cfg .default_speed , & hdev -> hw .mac .speed );
1233
1235
if (ret ) {
@@ -4906,14 +4908,18 @@ static bool hclge_fd_rule_exist(struct hclge_dev *hdev, u16 location)
4906
4908
struct hclge_fd_rule * rule = NULL ;
4907
4909
struct hlist_node * node2 ;
4908
4910
4911
+ spin_lock_bh (& hdev -> fd_rule_lock );
4909
4912
hlist_for_each_entry_safe (rule , node2 , & hdev -> fd_rule_list , rule_node ) {
4910
4913
if (rule -> location >= location )
4911
4914
break ;
4912
4915
}
4913
4916
4917
+ spin_unlock_bh (& hdev -> fd_rule_lock );
4918
+
4914
4919
return rule && rule -> location == location ;
4915
4920
}
4916
4921
4922
+ /* make sure being called after lock up with fd_rule_lock */
4917
4923
static int hclge_fd_update_rule_list (struct hclge_dev * hdev ,
4918
4924
struct hclge_fd_rule * new_rule ,
4919
4925
u16 location ,
@@ -4937,9 +4943,13 @@ static int hclge_fd_update_rule_list(struct hclge_dev *hdev,
4937
4943
kfree (rule );
4938
4944
hdev -> hclge_fd_rule_num -- ;
4939
4945
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 );
4942
4950
4951
+ return 0 ;
4952
+ }
4943
4953
} else if (!is_add ) {
4944
4954
dev_err (& hdev -> pdev -> dev ,
4945
4955
"delete fail, rule %d is inexistent\n" ,
@@ -4954,7 +4964,9 @@ static int hclge_fd_update_rule_list(struct hclge_dev *hdev,
4954
4964
else
4955
4965
hlist_add_head (& new_rule -> rule_node , & hdev -> fd_rule_list );
4956
4966
4967
+ set_bit (location , hdev -> fd_bmap );
4957
4968
hdev -> hclge_fd_rule_num ++ ;
4969
+ hdev -> fd_active_type = new_rule -> rule_type ;
4958
4970
4959
4971
return 0 ;
4960
4972
}
@@ -5112,6 +5124,36 @@ static int hclge_fd_get_tuple(struct hclge_dev *hdev,
5112
5124
return 0 ;
5113
5125
}
5114
5126
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
+
5115
5157
static int hclge_add_fd_entry (struct hnae3_handle * handle ,
5116
5158
struct ethtool_rxnfc * cmd )
5117
5159
{
@@ -5174,8 +5216,10 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
5174
5216
return - ENOMEM ;
5175
5217
5176
5218
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
+ }
5179
5223
5180
5224
rule -> flow_type = fs -> flow_type ;
5181
5225
@@ -5184,23 +5228,13 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
5184
5228
rule -> vf_id = dst_vport_id ;
5185
5229
rule -> queue_id = q_index ;
5186
5230
rule -> action = action ;
5231
+ rule -> rule_type = HCLGE_FD_EP_ACTIVE ;
5187
5232
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 );
5199
5235
5200
- return ret ;
5236
+ spin_unlock_bh ( & hdev -> fd_rule_lock ) ;
5201
5237
5202
- free_rule :
5203
- kfree (rule );
5204
5238
return ret ;
5205
5239
}
5206
5240
@@ -5232,8 +5266,12 @@ static int hclge_del_fd_entry(struct hnae3_handle *handle,
5232
5266
if (ret )
5233
5267
return ret ;
5234
5268
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 ;
5237
5275
}
5238
5276
5239
5277
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,
5243
5281
struct hclge_dev * hdev = vport -> back ;
5244
5282
struct hclge_fd_rule * rule ;
5245
5283
struct hlist_node * node ;
5284
+ u16 location ;
5246
5285
5247
5286
if (!hnae3_dev_fd_supported (hdev ))
5248
5287
return ;
5249
5288
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
+
5250
5295
if (clear_list ) {
5251
5296
hlist_for_each_entry_safe (rule , node , & hdev -> fd_rule_list ,
5252
5297
rule_node ) {
5253
- hclge_fd_tcam_config (hdev , HCLGE_FD_STAGE_1 , true,
5254
- rule -> location , NULL , false);
5255
5298
hlist_del (& rule -> rule_node );
5256
5299
kfree (rule );
5257
- hdev -> hclge_fd_rule_num -- ;
5258
5300
}
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 ]);
5264
5305
}
5306
+
5307
+ spin_unlock_bh (& hdev -> fd_rule_lock );
5265
5308
}
5266
5309
5267
5310
static int hclge_restore_fd_entries (struct hnae3_handle * handle )
@@ -5283,6 +5326,7 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle)
5283
5326
if (!hdev -> fd_en )
5284
5327
return 0 ;
5285
5328
5329
+ spin_lock_bh (& hdev -> fd_rule_lock );
5286
5330
hlist_for_each_entry_safe (rule , node , & hdev -> fd_rule_list , rule_node ) {
5287
5331
ret = hclge_config_action (hdev , HCLGE_FD_STAGE_1 , rule );
5288
5332
if (!ret )
@@ -5292,11 +5336,18 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle)
5292
5336
dev_warn (& hdev -> pdev -> dev ,
5293
5337
"Restore rule %d failed, remove it\n" ,
5294
5338
rule -> location );
5339
+ clear_bit (rule -> location , hdev -> fd_bmap );
5295
5340
hlist_del (& rule -> rule_node );
5296
5341
kfree (rule );
5297
5342
hdev -> hclge_fd_rule_num -- ;
5298
5343
}
5299
5344
}
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
+
5300
5351
return 0 ;
5301
5352
}
5302
5353
@@ -5329,13 +5380,18 @@ static int hclge_get_fd_rule_info(struct hnae3_handle *handle,
5329
5380
5330
5381
fs = (struct ethtool_rx_flow_spec * )& cmd -> fs ;
5331
5382
5383
+ spin_lock_bh (& hdev -> fd_rule_lock );
5384
+
5332
5385
hlist_for_each_entry_safe (rule , node2 , & hdev -> fd_rule_list , rule_node ) {
5333
5386
if (rule -> location >= fs -> location )
5334
5387
break ;
5335
5388
}
5336
5389
5337
- if (!rule || fs -> location != rule -> location )
5390
+ if (!rule || fs -> location != rule -> location ) {
5391
+ spin_unlock_bh (& hdev -> fd_rule_lock );
5392
+
5338
5393
return - ENOENT ;
5394
+ }
5339
5395
5340
5396
fs -> flow_type = rule -> flow_type ;
5341
5397
switch (fs -> flow_type & ~(FLOW_EXT | FLOW_MAC_EXT )) {
@@ -5474,6 +5530,7 @@ static int hclge_get_fd_rule_info(struct hnae3_handle *handle,
5474
5530
5475
5531
break ;
5476
5532
default :
5533
+ spin_unlock_bh (& hdev -> fd_rule_lock );
5477
5534
return - EOPNOTSUPP ;
5478
5535
}
5479
5536
@@ -5505,6 +5562,8 @@ static int hclge_get_fd_rule_info(struct hnae3_handle *handle,
5505
5562
fs -> ring_cookie |= vf_id ;
5506
5563
}
5507
5564
5565
+ spin_unlock_bh (& hdev -> fd_rule_lock );
5566
+
5508
5567
return 0 ;
5509
5568
}
5510
5569
@@ -5522,15 +5581,20 @@ static int hclge_get_all_rules(struct hnae3_handle *handle,
5522
5581
5523
5582
cmd -> data = hdev -> fd_cfg .rule_num [HCLGE_FD_STAGE_1 ];
5524
5583
5584
+ spin_lock_bh (& hdev -> fd_rule_lock );
5525
5585
hlist_for_each_entry_safe (rule , node2 ,
5526
5586
& 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 );
5528
5589
return - EMSGSIZE ;
5590
+ }
5529
5591
5530
5592
rule_locs [cnt ] = rule -> location ;
5531
5593
cnt ++ ;
5532
5594
}
5533
5595
5596
+ spin_unlock_bh (& hdev -> fd_rule_lock );
5597
+
5534
5598
cmd -> rule_cnt = cnt ;
5535
5599
5536
5600
return 0 ;
@@ -5565,10 +5629,12 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)
5565
5629
{
5566
5630
struct hclge_vport * vport = hclge_get_vport (handle );
5567
5631
struct hclge_dev * hdev = vport -> back ;
5632
+ bool clear ;
5568
5633
5569
5634
hdev -> fd_en = enable ;
5635
+ clear = hdev -> fd_active_type == HCLGE_FD_ARFS_ACTIVE ? true : false;
5570
5636
if (!enable )
5571
- hclge_del_all_fd_entries (handle , false );
5637
+ hclge_del_all_fd_entries (handle , clear );
5572
5638
else
5573
5639
hclge_restore_fd_entries (handle );
5574
5640
}
@@ -8143,6 +8209,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
8143
8209
8144
8210
mutex_init (& hdev -> vport_lock );
8145
8211
mutex_init (& hdev -> vport_cfg_mutex );
8212
+ spin_lock_init (& hdev -> fd_rule_lock );
8146
8213
8147
8214
ret = hclge_pci_init (hdev );
8148
8215
if (ret ) {
0 commit comments