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

net: hns3: refine for set ring parameters

driver inclusion
category: bugfix
bugzilla: NA
CVE: NA

Previously, when changing the ring parameters, we free the old
ring resources firstly, and then setup the new ring resources.
In some case of an allocation fail, there will be no resources
to use. This patch refines it by setup new ring resources and
free the old ring resources in order.

Feature or Bugfix:Bugfix
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>
上级 0ccc85ed
......@@ -3663,7 +3663,7 @@ static int hns3_alloc_ring_memory(struct hns3_enet_ring *ring)
return ret;
}
static void hns3_fini_ring(struct hns3_enet_ring *ring)
void hns3_fini_ring(struct hns3_enet_ring *ring)
{
hns3_free_desc(ring);
devm_kfree(ring_to_dev(ring), ring->desc_cb);
......
......@@ -652,6 +652,7 @@ void hns3_clean_tx_ring(struct hns3_enet_ring *ring);
int hns3_init_all_ring(struct hns3_nic_priv *priv);
int hns3_uninit_all_ring(struct hns3_nic_priv *priv);
int hns3_nic_reset_all_ring(struct hnae3_handle *h);
void hns3_fini_ring(struct hns3_enet_ring *ring);
netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev);
bool hns3_is_phys_func(struct pci_dev *pdev);
int hns3_clean_rx_ring(
......
......@@ -878,20 +878,27 @@ static int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv,
return hns3_init_all_ring(priv);
}
static int hns3_set_ringparam(struct net_device *ndev,
struct ethtool_ringparam *param)
static struct hns3_enet_ring *hns3_backup_ringparam(struct hns3_nic_priv *priv)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
bool if_running = netif_running(ndev);
u32 old_tx_desc_num, new_tx_desc_num;
u32 old_rx_desc_num, new_rx_desc_num;
int queue_num = h->kinfo.num_tqps;
int ret;
struct hnae3_handle *handle = priv->ae_handle;
struct hns3_enet_ring *tmp_rings;
int i;
if (hns3_nic_resetting(ndev))
return -EBUSY;
tmp_rings = kcalloc(handle->kinfo.num_tqps * 2,
sizeof(struct hns3_enet_ring), GFP_KERNEL);
if (!tmp_rings)
return NULL;
for (i = 0; i < handle->kinfo.num_tqps * 2; i++)
memcpy(&tmp_rings[i], priv->ring_data[i].ring,
sizeof(struct hns3_enet_ring));
return tmp_rings;
}
static int hns3_check_ringparam(struct net_device *ndev,
struct ethtool_ringparam *param)
{
if (param->rx_mini_pending || param->rx_jumbo_pending)
return -EINVAL;
......@@ -904,6 +911,25 @@ static int hns3_set_ringparam(struct net_device *ndev,
return -EINVAL;
}
return 0;
}
static int hns3_set_ringparam(struct net_device *ndev,
struct ethtool_ringparam *param)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
struct hns3_enet_ring *tmp_rings = NULL;
bool if_running = netif_running(ndev);
u32 old_tx_desc_num, new_tx_desc_num;
u32 old_rx_desc_num, new_rx_desc_num;
int queue_num = h->kinfo.num_tqps;
int ret, i;
ret = hns3_check_ringparam(ndev, param);
if (ret)
return ret;
/* Hardware requires that its descriptors must be multiple of eight */
new_tx_desc_num = ALIGN(param->tx_pending, HNS3_RING_BD_MULTIPLE);
new_rx_desc_num = ALIGN(param->rx_pending, HNS3_RING_BD_MULTIPLE);
......@@ -921,24 +947,34 @@ static int hns3_set_ringparam(struct net_device *ndev,
if (if_running)
ndev->netdev_ops->ndo_stop(ndev);
ret = hns3_uninit_all_ring(priv);
if (ret)
return ret;
tmp_rings = hns3_backup_ringparam(priv);
if (!tmp_rings) {
netdev_err(ndev,
"backup ring param failed by allocating memory fail\n");
ret = -ENOMEM;
goto out;
}
ret = hns3_change_all_ring_bd_num(priv, new_tx_desc_num,
new_rx_desc_num);
hns3_change_all_ring_bd_num(priv, new_tx_desc_num, new_rx_desc_num);
ret = hns3_init_all_ring(priv);
if (ret) {
ret = hns3_change_all_ring_bd_num(priv, old_tx_desc_num,
old_rx_desc_num);
if (ret) {
netdev_err(ndev,
"Revert to old bd num fail, ret=%d.\n", ret);
return ret;
}
netdev_warn(ndev, "Change bd num fail, revert to old value\n");
hns3_change_all_ring_bd_num(priv, old_tx_desc_num,
old_rx_desc_num);
for (i = 0; i < h->kinfo.num_tqps * 2; i++)
memcpy(priv->ring_data[i].ring, &tmp_rings[i],
sizeof(struct hns3_enet_ring));
} else {
for (i = 0; i < h->kinfo.num_tqps; i++)
hns3_fini_ring(&tmp_rings[i]);
}
kfree(tmp_rings);
out:
if (if_running)
ret = ndev->netdev_ops->ndo_open(ndev);
ndev->netdev_ops->ndo_open(ndev);
return ret;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册