Skip to content

Commit fe4144d

Browse files
IronShendavem330
authored andcommitted
net: hns3: sync VLAN filter entries when kill VLAN ID failed
When HW is resetting, firmware is unable to handle commands from driver. So if remove VLAN device from stack at this time, it will fail to remove the VLAN ID from HW VLAN filter, then the VLAN filter status is unsynced with stack. This patch fixes it by recording the VLAN ID delete failed, and removes them again when reset complete. Fixes: 44e626f ("net: hns3: fix VLAN offload handle for VLAN inserted by port") Signed-off-by: Jian Shen <[email protected]> Signed-off-by: Peng Li <[email protected]> Signed-off-by: Huazhong Tan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d0c31df commit fe4144d

File tree

4 files changed

+112
-16
lines changed

4 files changed

+112
-16
lines changed

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

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps);
3737
static int hclge_init_vlan_config(struct hclge_dev *hdev);
38+
static void hclge_sync_vlan_filter(struct hclge_dev *hdev);
3839
static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev);
3940
static bool hclge_get_hw_reset_stat(struct hnae3_handle *handle);
4041
static int hclge_set_umv_space(struct hclge_dev *hdev, u16 space_size,
@@ -3539,6 +3540,7 @@ static void hclge_service_task(struct work_struct *work)
35393540
hclge_update_port_info(hdev);
35403541
hclge_update_link_status(hdev);
35413542
hclge_update_vport_alive(hdev);
3543+
hclge_sync_vlan_filter(hdev);
35423544
if (hdev->fd_arfs_expire_timer >= HCLGE_FD_ARFS_EXPIRE_TIMER_INTERVAL) {
35433545
hclge_rfs_filter_expire(hdev);
35443546
hdev->fd_arfs_expire_timer = 0;
@@ -7742,28 +7744,74 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
77427744
bool writen_to_tbl = false;
77437745
int ret = 0;
77447746

7745-
/* when port based VLAN enabled, we use port based VLAN as the VLAN
7746-
* filter entry. In this case, we don't update VLAN filter table
7747-
* when user add new VLAN or remove exist VLAN, just update the vport
7748-
* VLAN list. The VLAN id in VLAN list won't be writen in VLAN filter
7749-
* table until port based VLAN disabled
7747+
/* When device is resetting, firmware is unable to handle
7748+
* mailbox. Just record the vlan id, and remove it after
7749+
* reset finished.
7750+
*/
7751+
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) && is_kill) {
7752+
set_bit(vlan_id, vport->vlan_del_fail_bmap);
7753+
return -EBUSY;
7754+
}
7755+
7756+
/* When port base vlan enabled, we use port base vlan as the vlan
7757+
* filter entry. In this case, we don't update vlan filter table
7758+
* when user add new vlan or remove exist vlan, just update the vport
7759+
* vlan list. The vlan id in vlan list will be writen in vlan filter
7760+
* table until port base vlan disabled
77507761
*/
77517762
if (handle->port_base_vlan_state == HNAE3_PORT_BASE_VLAN_DISABLE) {
77527763
ret = hclge_set_vlan_filter_hw(hdev, proto, vport->vport_id,
77537764
vlan_id, 0, is_kill);
77547765
writen_to_tbl = true;
77557766
}
77567767

7757-
if (ret)
7758-
return ret;
7768+
if (!ret) {
7769+
if (is_kill)
7770+
hclge_rm_vport_vlan_table(vport, vlan_id, false);
7771+
else
7772+
hclge_add_vport_vlan_table(vport, vlan_id,
7773+
writen_to_tbl);
7774+
} else if (is_kill) {
7775+
/* When remove hw vlan filter failed, record the vlan id,
7776+
* and try to remove it from hw later, to be consistence
7777+
* with stack
7778+
*/
7779+
set_bit(vlan_id, vport->vlan_del_fail_bmap);
7780+
}
7781+
return ret;
7782+
}
77597783

7760-
if (is_kill)
7761-
hclge_rm_vport_vlan_table(vport, vlan_id, false);
7762-
else
7763-
hclge_add_vport_vlan_table(vport, vlan_id,
7764-
writen_to_tbl);
7784+
static void hclge_sync_vlan_filter(struct hclge_dev *hdev)
7785+
{
7786+
#define HCLGE_MAX_SYNC_COUNT 60
77657787

7766-
return 0;
7788+
int i, ret, sync_cnt = 0;
7789+
u16 vlan_id;
7790+
7791+
/* start from vport 1 for PF is always alive */
7792+
for (i = 0; i < hdev->num_alloc_vport; i++) {
7793+
struct hclge_vport *vport = &hdev->vport[i];
7794+
7795+
vlan_id = find_first_bit(vport->vlan_del_fail_bmap,
7796+
VLAN_N_VID);
7797+
while (vlan_id != VLAN_N_VID) {
7798+
ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
7799+
vport->vport_id, vlan_id,
7800+
0, true);
7801+
if (ret && ret != -EINVAL)
7802+
return;
7803+
7804+
clear_bit(vlan_id, vport->vlan_del_fail_bmap);
7805+
hclge_rm_vport_vlan_table(vport, vlan_id, false);
7806+
7807+
sync_cnt++;
7808+
if (sync_cnt >= HCLGE_MAX_SYNC_COUNT)
7809+
return;
7810+
7811+
vlan_id = find_first_bit(vport->vlan_del_fail_bmap,
7812+
VLAN_N_VID);
7813+
}
7814+
}
77677815
}
77687816

77697817
static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,7 @@ struct hclge_vport {
929929
u32 bw_limit; /* VSI BW Limit (0 = disabled) */
930930
u8 dwrr;
931931

932+
unsigned long vlan_del_fail_bmap[BITS_TO_LONGS(VLAN_N_VID)];
932933
struct hclge_port_base_vlan_config port_base_vlan_cfg;
933934
struct hclge_tx_vtag_cfg txvlan_cfg;
934935
struct hclge_rx_vtag_cfg rxvlan_cfg;

drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,19 +1244,61 @@ static int hclgevf_set_vlan_filter(struct hnae3_handle *handle,
12441244
#define HCLGEVF_VLAN_MBX_MSG_LEN 5
12451245
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
12461246
u8 msg_data[HCLGEVF_VLAN_MBX_MSG_LEN];
1247+
int ret;
12471248

12481249
if (vlan_id > HCLGEVF_MAX_VLAN_ID)
12491250
return -EINVAL;
12501251

12511252
if (proto != htons(ETH_P_8021Q))
12521253
return -EPROTONOSUPPORT;
12531254

1255+
/* When device is resetting, firmware is unable to handle
1256+
* mailbox. Just record the vlan id, and remove it after
1257+
* reset finished.
1258+
*/
1259+
if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) && is_kill) {
1260+
set_bit(vlan_id, hdev->vlan_del_fail_bmap);
1261+
return -EBUSY;
1262+
}
1263+
12541264
msg_data[0] = is_kill;
12551265
memcpy(&msg_data[1], &vlan_id, sizeof(vlan_id));
12561266
memcpy(&msg_data[3], &proto, sizeof(proto));
1257-
return hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
1258-
HCLGE_MBX_VLAN_FILTER, msg_data,
1259-
HCLGEVF_VLAN_MBX_MSG_LEN, false, NULL, 0);
1267+
ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
1268+
HCLGE_MBX_VLAN_FILTER, msg_data,
1269+
HCLGEVF_VLAN_MBX_MSG_LEN, false, NULL, 0);
1270+
1271+
/* When remove hw vlan filter failed, record the vlan id,
1272+
* and try to remove it from hw later, to be consistence
1273+
* with stack.
1274+
*/
1275+
if (is_kill && ret)
1276+
set_bit(vlan_id, hdev->vlan_del_fail_bmap);
1277+
1278+
return ret;
1279+
}
1280+
1281+
static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev)
1282+
{
1283+
#define HCLGEVF_MAX_SYNC_COUNT 60
1284+
struct hnae3_handle *handle = &hdev->nic;
1285+
int ret, sync_cnt = 0;
1286+
u16 vlan_id;
1287+
1288+
vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
1289+
while (vlan_id != VLAN_N_VID) {
1290+
ret = hclgevf_set_vlan_filter(handle, htons(ETH_P_8021Q),
1291+
vlan_id, true);
1292+
if (ret)
1293+
return;
1294+
1295+
clear_bit(vlan_id, hdev->vlan_del_fail_bmap);
1296+
sync_cnt++;
1297+
if (sync_cnt >= HCLGEVF_MAX_SYNC_COUNT)
1298+
return;
1299+
1300+
vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
1301+
}
12601302
}
12611303

12621304
static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
@@ -1797,6 +1839,8 @@ static void hclgevf_service_task(struct work_struct *work)
17971839

17981840
hclgevf_update_link_mode(hdev);
17991841

1842+
hclgevf_sync_vlan_filter(hdev);
1843+
18001844
hclgevf_deferred_task_schedule(hdev);
18011845

18021846
clear_bit(HCLGEVF_STATE_SERVICE_SCHED, &hdev->state);

drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifndef __HCLGEVF_MAIN_H
55
#define __HCLGEVF_MAIN_H
66
#include <linux/fs.h>
7+
#include <linux/if_vlan.h>
78
#include <linux/types.h>
89
#include "hclge_mbx.h"
910
#include "hclgevf_cmd.h"
@@ -270,6 +271,8 @@ struct hclgevf_dev {
270271
u16 *vector_status;
271272
int *vector_irq;
272273

274+
unsigned long vlan_del_fail_bmap[BITS_TO_LONGS(VLAN_N_VID)];
275+
273276
bool mbx_event_pending;
274277
struct hclgevf_mbx_resp_status mbx_resp; /* mailbox response */
275278
struct hclgevf_mbx_arq_ring arq; /* mailbox async rx queue */

0 commit comments

Comments
 (0)