提交 42815023 编写于 作者: S shenjian 提交者: Xie XiuQi

net: hns3: fix vlan filter mismatch issue

driver inclusion
category: bugfix
bugzilla: NA
CVE: NA

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 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 remove them again when reset complete.
Signed-off-by: Nshenjian (K) <shenjian15@huawei.com>
Reviewed-by: Nlipeng <lipeng321@huawei.com>
Reviewed-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 58925c13
......@@ -7223,12 +7223,13 @@ static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid,
if (!req0->resp_code)
return 0;
if (req0->resp_code == HCLGE_VF_VLAN_DEL_NO_FOUND) {
dev_warn(&hdev->pdev->dev,
"vlan %d filter is not in vf vlan table\n",
vlan);
/* vf vlan filter is disabled when vf vlan table is full,
* then new vlan id will not be added into vf vlan table.
* Just return 0 without warning, avoid massive verbose
* print logs when unload.
*/
if (req0->resp_code == HCLGE_VF_VLAN_DEL_NO_FOUND)
return 0;
}
dev_err(&hdev->pdev->dev,
"Kill vf vlan filter fail, ret =%d.\n",
......@@ -7323,11 +7324,20 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
bool writen_to_tbl = false;
int ret = 0;
/* When device is resetting, firmware is unable to handle
* mailbox. Just record the vlan id, and remove it after
* reset finished.
*/
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) && is_kill) {
set_bit(vlan_id, vport->vlan_del_fail_bmap);
return -EBUSY;
}
/* when port base vlan enabled, we use port base vlan as the vlan
* filter condition. In this case, we don't update vlan filter table
* when user add new vlan or remove exist vlan, just update the vport
* vlan list. The vlan id in vlan list will be writen in vlan filter
* table until port base vlan disabled
* table until port base vlan disabled.
*/
if (handle->port_base_vlan_state == HNAE3_PORT_BASE_VLAN_DISABLE) {
ret = hclge_set_vlan_filter_hw(hdev, proto, vport->vport_id,
......@@ -7344,9 +7354,8 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
} else if (is_kill) {
/* when remove hw vlan filter failed, record the vlan id,
* and try to remove it from hw later, to be consistence
* with stack
* with stack.
*/
hclge_rm_vport_vlan_table(vport, vlan_id, false);
set_bit(vlan_id, vport->vlan_del_fail_bmap);
}
return ret;
......@@ -7883,8 +7892,11 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev)
ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
vport->vport_id, vlan_id,
0, true);
if (!ret || ret == -EINVAL)
if (!ret || ret == -EINVAL) {
clear_bit(vlan_id, vport->vlan_del_fail_bmap);
hclge_rm_vport_vlan_table(vport, vlan_id,
false);
}
sync_cnt++;
if (sync_cnt >= HCLGE_MAX_SYNC_COUNT)
......
......@@ -1209,6 +1209,7 @@ static int hclgevf_set_vlan_filter(struct hnae3_handle *handle,
#define HCLGEVF_VLAN_MBX_MSG_LEN 5
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
u8 msg_data[HCLGEVF_VLAN_MBX_MSG_LEN];
int ret;
if (vlan_id > MAX_VLAN_ID)
return -EINVAL;
......@@ -1216,12 +1217,52 @@ static int hclgevf_set_vlan_filter(struct hnae3_handle *handle,
if (proto != htons(ETH_P_8021Q))
return -EPROTONOSUPPORT;
/* When device is resetting, firmware is unable to handle
* mailbox. Just record the vlan id, and remove it after
* reset finished.
*/
if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) && is_kill) {
set_bit(vlan_id, hdev->vlan_del_fail_bmap);
return -EBUSY;
}
msg_data[0] = is_kill;
memcpy(&msg_data[1], &vlan_id, sizeof(vlan_id));
memcpy(&msg_data[3], &proto, sizeof(proto));
return hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
HCLGE_MBX_VLAN_FILTER, msg_data,
HCLGEVF_VLAN_MBX_MSG_LEN, false, NULL, 0);
/* when remove hw vlan filter failed, record the vlan id,
* and try to remove it from hw later, to be consistence
* with stack.
*/
if (is_kill && ret)
set_bit(vlan_id, hdev->vlan_del_fail_bmap);
return ret;
}
static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev)
{
#define HCLGEVF_MAX_SYNC_COUNT 60
struct hnae3_handle *handle = &hdev->nic;
int ret, sync_cnt = 0;
u16 vlan_id;
vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
while (vlan_id != VLAN_N_VID) {
ret = hclgevf_set_vlan_filter(handle, htons(ETH_P_8021Q),
vlan_id, true);
if (!ret)
clear_bit(vlan_id, hdev->vlan_del_fail_bmap);
sync_cnt++;
if (sync_cnt >= HCLGEVF_MAX_SYNC_COUNT)
return;
vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
}
}
static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
......@@ -1801,6 +1842,8 @@ static void hclgevf_service_task(struct work_struct *work)
hclgevf_update_link_mode(hdev);
hclgevf_sync_vlan_filter(hdev);
hclgevf_deferred_task_schedule(hdev);
clear_bit(HCLGEVF_STATE_SERVICE_SCHED, &hdev->state);
......
......@@ -4,6 +4,7 @@
#ifndef __HCLGEVF_MAIN_H
#define __HCLGEVF_MAIN_H
#include <linux/fs.h>
#include <linux/if_vlan.h>
#include <linux/types.h>
#include "hclge_mbx.h"
#include "hclgevf_cmd.h"
......@@ -221,6 +222,8 @@ struct hclgevf_dev {
u16 *vector_status;
int *vector_irq;
unsigned long vlan_del_fail_bmap[BITS_TO_LONGS(VLAN_N_VID)];
bool mbx_event_pending;
struct hclgevf_mbx_resp_status mbx_resp; /* mailbox response */
struct hclgevf_mbx_arq_ring arq; /* mailbox async rx queue */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册