Skip to content

Commit dc8131d

Browse files
Yunsheng Lindavem330
authored andcommitted
net: hns3: Fix for packet loss due wrong filter config in VLAN tbls
There are two level of vlan tables in hardware, one is port vlan which is shared by all functions, the other one is function vlan table, each function has it's own function vlan table. Currently, PF sets the port vlan table, and vf sets the function vlan table, which will cause packet lost problem. This patch fixes this problem by setting both vlan table, and use hdev->vlan_table to manage thet port vlan table. Signed-off-by: Yunsheng Lin <[email protected]> Signed-off-by: Peng Li <[email protected]> Signed-off-by: Salil Mehta <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3ff5049 commit dc8131d

File tree

3 files changed

+70
-24
lines changed

3 files changed

+70
-24
lines changed

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

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4543,8 +4543,9 @@ static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable)
45434543
hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, enable);
45444544
}
45454545

4546-
int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
4547-
bool is_kill, u16 vlan, u8 qos, __be16 proto)
4546+
static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
4547+
bool is_kill, u16 vlan, u8 qos,
4548+
__be16 proto)
45484549
{
45494550
#define HCLGE_MAX_VF_BYTES 16
45504551
struct hclge_vlan_filter_vf_cfg_cmd *req0;
@@ -4602,12 +4603,9 @@ int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
46024603
return -EIO;
46034604
}
46044605

4605-
static int hclge_set_port_vlan_filter(struct hnae3_handle *handle,
4606-
__be16 proto, u16 vlan_id,
4607-
bool is_kill)
4606+
static int hclge_set_port_vlan_filter(struct hclge_dev *hdev, __be16 proto,
4607+
u16 vlan_id, bool is_kill)
46084608
{
4609-
struct hclge_vport *vport = hclge_get_vport(handle);
4610-
struct hclge_dev *hdev = vport->back;
46114609
struct hclge_vlan_filter_pf_cfg_cmd *req;
46124610
struct hclge_desc desc;
46134611
u8 vlan_offset_byte_val;
@@ -4627,22 +4625,66 @@ static int hclge_set_port_vlan_filter(struct hnae3_handle *handle,
46274625
req->vlan_offset_bitmap[vlan_offset_byte] = vlan_offset_byte_val;
46284626

46294627
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
4628+
if (ret)
4629+
dev_err(&hdev->pdev->dev,
4630+
"port vlan command, send fail, ret =%d.\n", ret);
4631+
return ret;
4632+
}
4633+
4634+
static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
4635+
u16 vport_id, u16 vlan_id, u8 qos,
4636+
bool is_kill)
4637+
{
4638+
u16 vport_idx, vport_num = 0;
4639+
int ret;
4640+
4641+
ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id,
4642+
0, proto);
46304643
if (ret) {
46314644
dev_err(&hdev->pdev->dev,
4632-
"port vlan command, send fail, ret =%d.\n",
4633-
ret);
4645+
"Set %d vport vlan filter config fail, ret =%d.\n",
4646+
vport_id, ret);
46344647
return ret;
46354648
}
46364649

4637-
ret = hclge_set_vf_vlan_common(hdev, 0, is_kill, vlan_id, 0, proto);
4638-
if (ret) {
4650+
/* vlan 0 may be added twice when 8021q module is enabled */
4651+
if (!is_kill && !vlan_id &&
4652+
test_bit(vport_id, hdev->vlan_table[vlan_id]))
4653+
return 0;
4654+
4655+
if (!is_kill && test_and_set_bit(vport_id, hdev->vlan_table[vlan_id])) {
46394656
dev_err(&hdev->pdev->dev,
4640-
"Set pf vlan filter config fail, ret =%d.\n",
4641-
ret);
4642-
return -EIO;
4657+
"Add port vlan failed, vport %d is already in vlan %d\n",
4658+
vport_id, vlan_id);
4659+
return -EINVAL;
46434660
}
46444661

4645-
return 0;
4662+
if (is_kill &&
4663+
!test_and_clear_bit(vport_id, hdev->vlan_table[vlan_id])) {
4664+
dev_err(&hdev->pdev->dev,
4665+
"Delete port vlan failed, vport %d is not in vlan %d\n",
4666+
vport_id, vlan_id);
4667+
return -EINVAL;
4668+
}
4669+
4670+
for_each_set_bit(vport_idx, hdev->vlan_table[vlan_id], VLAN_N_VID)
4671+
vport_num++;
4672+
4673+
if ((is_kill && vport_num == 0) || (!is_kill && vport_num == 1))
4674+
ret = hclge_set_port_vlan_filter(hdev, proto, vlan_id,
4675+
is_kill);
4676+
4677+
return ret;
4678+
}
4679+
4680+
int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
4681+
u16 vlan_id, bool is_kill)
4682+
{
4683+
struct hclge_vport *vport = hclge_get_vport(handle);
4684+
struct hclge_dev *hdev = vport->back;
4685+
4686+
return hclge_set_vlan_filter_hw(hdev, proto, vport->vport_id, vlan_id,
4687+
0, is_kill);
46464688
}
46474689

46484690
static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
@@ -4656,7 +4698,7 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
46564698
if (proto != htons(ETH_P_8021Q))
46574699
return -EPROTONOSUPPORT;
46584700

4659-
return hclge_set_vf_vlan_common(hdev, vfid, false, vlan, qos, proto);
4701+
return hclge_set_vlan_filter_hw(hdev, proto, vfid, vlan, qos, false);
46604702
}
46614703

46624704
static int hclge_set_vlan_tx_offload_cfg(struct hclge_vport *vport)
@@ -4821,7 +4863,7 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
48214863
}
48224864

48234865
handle = &hdev->vport[0].nic;
4824-
return hclge_set_port_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
4866+
return hclge_set_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
48254867
}
48264868

48274869
static int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
@@ -5604,6 +5646,7 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
56045646
set_bit(HCLGE_STATE_DOWN, &hdev->state);
56055647

56065648
hclge_stats_clear(hdev);
5649+
memset(hdev->vlan_table, 0, sizeof(hdev->vlan_table));
56075650

56085651
ret = hclge_cmd_init(hdev);
56095652
if (ret) {
@@ -6221,7 +6264,7 @@ static const struct hnae3_ae_ops hclge_ops = {
62216264
.get_fw_version = hclge_get_fw_version,
62226265
.get_mdix_mode = hclge_get_mdix_mode,
62236266
.enable_vlan_filter = hclge_enable_vlan_filter,
6224-
.set_vlan_filter = hclge_set_port_vlan_filter,
6267+
.set_vlan_filter = hclge_set_vlan_filter,
62256268
.set_vf_vlan_filter = hclge_set_vf_vlan_filter,
62266269
.enable_hw_strip_rxvtag = hclge_en_hw_strip_rxvtag,
62276270
.reset_event = hclge_reset_event,

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <linux/fs.h>
1313
#include <linux/types.h>
1414
#include <linux/phy.h>
15+
#include <linux/if_vlan.h>
16+
1517
#include "hclge_cmd.h"
1618
#include "hnae3.h"
1719

@@ -471,6 +473,7 @@ struct hclge_vlan_type_cfg {
471473
u16 tx_in_vlan_type;
472474
};
473475

476+
#define HCLGE_VPORT_NUM 256
474477
struct hclge_dev {
475478
struct pci_dev *pdev;
476479
struct hnae3_ae_dev *ae_dev;
@@ -562,6 +565,7 @@ struct hclge_dev {
562565

563566
u64 rx_pkts_for_led;
564567
u64 tx_pkts_for_led;
568+
unsigned long vlan_table[VLAN_N_VID][BITS_TO_LONGS(HCLGE_VPORT_NUM)];
565569
};
566570

567571
/* VPort level vlan tag configuration for TX direction */
@@ -646,8 +650,8 @@ static inline int hclge_get_queue_id(struct hnae3_queue *queue)
646650
}
647651

648652
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex);
649-
int hclge_set_vf_vlan_common(struct hclge_dev *vport, int vfid,
650-
bool is_kill, u16 vlan, u8 qos, __be16 proto);
653+
int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
654+
u16 vlan_id, bool is_kill);
651655

652656
int hclge_buffer_alloc(struct hclge_dev *hdev);
653657
int hclge_rss_init_hw(struct hclge_dev *hdev);

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,19 +264,18 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
264264
struct hclge_mbx_vf_to_pf_cmd *mbx_req,
265265
bool gen_resp)
266266
{
267-
struct hclge_dev *hdev = vport->back;
268267
int status = 0;
269268

270269
if (mbx_req->msg[1] == HCLGE_MBX_VLAN_FILTER) {
270+
struct hnae3_handle *handle = &vport->nic;
271271
u16 vlan, proto;
272272
bool is_kill;
273273

274274
is_kill = !!mbx_req->msg[2];
275275
memcpy(&vlan, &mbx_req->msg[3], sizeof(vlan));
276276
memcpy(&proto, &mbx_req->msg[5], sizeof(proto));
277-
status = hclge_set_vf_vlan_common(hdev, vport->vport_id,
278-
is_kill, vlan, 0,
279-
cpu_to_be16(proto));
277+
status = hclge_set_vlan_filter(handle, cpu_to_be16(proto),
278+
vlan, is_kill);
280279
}
281280

282281
if (gen_resp)

0 commit comments

Comments
 (0)