The fallback logic of the set channels when set_channel() fails to configure TX Sched/RSS H/W configuration or for the code which brings down/restores client before/therafter is not handled properly.
Fix and refactor the code for handling the errors properly and to improve the readibility.
Fixes: 3a5a5f06d4d2 ("net: hns3: revert to old channel when setting new channel num fail") Signed-off-by: Salil Mehta salil.mehta@huawei.com Signed-off-by: Peng Li lipeng321@huawei.com --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 77 +++++++++++-------- 1 file changed, 47 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index bf4302a5cf95..fbb0f4c9b98e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4692,24 +4692,60 @@ static int hns3_reset_notify(struct hnae3_handle *handle, static int hns3_change_channels(struct hnae3_handle *handle, u32 new_tqp_num, bool rxfh_configured) { - int ret; + const struct hnae3_ae_ops *ops = handle->ae_algo->ops; + u32 org_tqp_num = handle->kinfo.num_tqps; + struct device *dev = &handle->pdev->dev; + u32 req_tqp_num = new_tqp_num; + bool revert_old_config = false; + int ret, retval = 0; + + /* bring down the client */ + ret = hns3_reset_notify(handle, HNAE3_DOWN_CLIENT); + if (ret) { + dev_err(dev, "client down fail, this should'nt have happened!\n"); + return ret; + }
- ret = handle->ae_algo->ops->set_channels(handle, new_tqp_num, - rxfh_configured); + ret = hns3_reset_notify(handle, HNAE3_UNINIT_CLIENT); if (ret) { - dev_err(&handle->pdev->dev, - "Change tqp num(%u) fail.\n", new_tqp_num); + dev_err(dev, "client uninit fail, this should'nt have happened!\n"); return ret; }
+revert_old_tpqs_config: + /* update the TX Sched and RSS config in the H/W */ + ret = ops->set_channels(handle, req_tqp_num, rxfh_configured); + if (ret) { + dev_err(dev, "TX Sched/RSS H/W cfg fail(=%d) for %s TPQs\n", + ret, revert_old_config ? "old" : "new"); + goto err_set_channel; + } + + /* restore the client */ ret = hns3_reset_notify(handle, HNAE3_INIT_CLIENT); - if (ret) - return ret; + if (ret) { + dev_err(dev, "failed to initialize the client again\n"); + goto err_set_channel; + }
ret = hns3_reset_notify(handle, HNAE3_UP_CLIENT); - if (ret) - hns3_reset_notify(handle, HNAE3_UNINIT_CLIENT); + if (ret) { + dev_err(dev, "Client up fail, this should'nt have happened!\n"); + return ret; + } + + return retval; +err_set_channel: + if (!revert_old_config) { + dev_warn(dev, "Revert TX Sched/RSS H/W config with old TPQs\n"); + req_tqp_num = org_tqp_num; + revert_old_config = true; + retval = ret; + goto revert_old_tpqs_config; + }
+ dev_err(dev, "Bad, we could'nt revert to old TPQ H/W config\n"); + dev_warn(dev, "Device maybe insane. Reload driver/Reset required!\n"); return ret; }
@@ -4720,7 +4756,6 @@ int hns3_set_channels(struct net_device *netdev, struct hnae3_knic_private_info *kinfo = &h->kinfo; bool rxfh_configured = netif_is_rxfh_configured(netdev); u32 new_tqp_num = ch->combined_count; - u16 org_tqp_num; int ret;
if (hns3_nic_resetting(netdev)) @@ -4750,28 +4785,10 @@ int hns3_set_channels(struct net_device *netdev, "set channels: tqp_num=%u, rxfh=%d\n", new_tqp_num, rxfh_configured);
- ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT); - if (ret) - return ret; - - ret = hns3_reset_notify(h, HNAE3_UNINIT_CLIENT); - if (ret) - return ret; - - org_tqp_num = h->kinfo.num_tqps; ret = hns3_change_channels(h, new_tqp_num, rxfh_configured); if (ret) { - int ret1; - - netdev_warn(netdev, - "Change channels fail, revert to old value\n"); - ret1 = hns3_change_channels(h, org_tqp_num, rxfh_configured); - if (ret1) { - netdev_err(netdev, - "revert to old channel fail\n"); - return ret1; - } - + netdev_err(netdev, "fail(=%d) to set number of channels to %u\n", ret, + new_tqp_num); return ret; }