Commit e8a1b0ef authored by Luo bin's avatar Luo bin Committed by Jakub Kicinski

hinic: fix a bug of ndo_stop

if some function in ndo_stop interface returns failure because of
hardware fault, must go on excuting rest steps rather than return
failure directly, otherwise will cause memory leak.And bump the
timeout for SET_FUNC_STATE to ensure that cmd won't return failure
when hw is busy. Otherwise hw may stomp host memory if we free
memory regardless of the return value of SET_FUNC_STATE.

Fixes: 51ba902a ("net-next/hinic: Initialize hw interface")
Signed-off-by: default avatarLuo bin <luobin9@huawei.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 3047211c
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
#define MGMT_MSG_TIMEOUT 5000 #define MGMT_MSG_TIMEOUT 5000
#define SET_FUNC_PORT_MGMT_TIMEOUT 25000
#define mgmt_to_pfhwdev(pf_mgmt) \ #define mgmt_to_pfhwdev(pf_mgmt) \
container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt) container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
...@@ -238,12 +240,13 @@ static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt, ...@@ -238,12 +240,13 @@ static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
u8 *buf_in, u16 in_size, u8 *buf_in, u16 in_size,
u8 *buf_out, u16 *out_size, u8 *buf_out, u16 *out_size,
enum mgmt_direction_type direction, enum mgmt_direction_type direction,
u16 resp_msg_id) u16 resp_msg_id, u32 timeout)
{ {
struct hinic_hwif *hwif = pf_to_mgmt->hwif; struct hinic_hwif *hwif = pf_to_mgmt->hwif;
struct pci_dev *pdev = hwif->pdev; struct pci_dev *pdev = hwif->pdev;
struct hinic_recv_msg *recv_msg; struct hinic_recv_msg *recv_msg;
struct completion *recv_done; struct completion *recv_done;
unsigned long timeo;
u16 msg_id; u16 msg_id;
int err; int err;
...@@ -267,8 +270,9 @@ static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt, ...@@ -267,8 +270,9 @@ static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
goto unlock_sync_msg; goto unlock_sync_msg;
} }
if (!wait_for_completion_timeout(recv_done, timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
msecs_to_jiffies(MGMT_MSG_TIMEOUT))) {
if (!wait_for_completion_timeout(recv_done, timeo)) {
dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id); dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
err = -ETIMEDOUT; err = -ETIMEDOUT;
goto unlock_sync_msg; goto unlock_sync_msg;
...@@ -342,6 +346,7 @@ int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt, ...@@ -342,6 +346,7 @@ int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
{ {
struct hinic_hwif *hwif = pf_to_mgmt->hwif; struct hinic_hwif *hwif = pf_to_mgmt->hwif;
struct pci_dev *pdev = hwif->pdev; struct pci_dev *pdev = hwif->pdev;
u32 timeout = 0;
if (sync != HINIC_MGMT_MSG_SYNC) { if (sync != HINIC_MGMT_MSG_SYNC) {
dev_err(&pdev->dev, "Invalid MGMT msg type\n"); dev_err(&pdev->dev, "Invalid MGMT msg type\n");
...@@ -353,9 +358,12 @@ int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt, ...@@ -353,9 +358,12 @@ int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
return -EINVAL; return -EINVAL;
} }
if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size, return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
buf_out, out_size, MGMT_DIRECT_SEND, buf_out, out_size, MGMT_DIRECT_SEND,
MSG_NOT_RESP); MSG_NOT_RESP, timeout);
} }
/** /**
......
...@@ -483,7 +483,6 @@ static int hinic_close(struct net_device *netdev) ...@@ -483,7 +483,6 @@ static int hinic_close(struct net_device *netdev)
{ {
struct hinic_dev *nic_dev = netdev_priv(netdev); struct hinic_dev *nic_dev = netdev_priv(netdev);
unsigned int flags; unsigned int flags;
int err;
down(&nic_dev->mgmt_lock); down(&nic_dev->mgmt_lock);
...@@ -497,20 +496,9 @@ static int hinic_close(struct net_device *netdev) ...@@ -497,20 +496,9 @@ static int hinic_close(struct net_device *netdev)
up(&nic_dev->mgmt_lock); up(&nic_dev->mgmt_lock);
err = hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE); hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE);
if (err) {
netif_err(nic_dev, drv, netdev,
"Failed to set func port state\n");
nic_dev->flags |= (flags & HINIC_INTF_UP);
return err;
}
err = hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE); hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE);
if (err) {
netif_err(nic_dev, drv, netdev, "Failed to set port state\n");
nic_dev->flags |= (flags & HINIC_INTF_UP);
return err;
}
if (nic_dev->flags & HINIC_RSS_ENABLE) { if (nic_dev->flags & HINIC_RSS_ENABLE) {
hinic_rss_deinit(nic_dev); hinic_rss_deinit(nic_dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment