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(a)huawei.com>
Signed-off-by: Peng Li <lipeng321(a)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;
}
--
2.17.1