hinic: fix a bug of ndo_stop
[ Upstream commit5.4-rM2-2.2.x-imx-squashede8a1b0efd6
] 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:51ba902a16
("net-next/hinic: Initialize hw interface") Signed-off-by: Luo bin <luobin9@huawei.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
parent
d07987924a
commit
b2e8946250
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue