net: hns3: bugfix for buffer not free problem during resetting
authorHuazhong Tan <tanhuazhong@huawei.com>
Tue, 30 Oct 2018 13:50:44 +0000 (21:50 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 31 Oct 2018 19:42:38 +0000 (12:42 -0700)
When hns3_get_ring_config()/hns3_queue_to_ring()/
hns3_get_vector_ring_chain() failed during resetting, the allocated
memory has not been freed before these three functions return. So
this patch adds error handler in these functions to fix it.

Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC")
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c

index 0b4323b1f9303365651943f71c3db626139b7703..b767ff96b5370812a7eb4becd0b475bcd89f5e6d 100644 (file)
@@ -2727,7 +2727,7 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
                        chain = devm_kzalloc(&pdev->dev, sizeof(*chain),
                                             GFP_KERNEL);
                        if (!chain)
-                               return -ENOMEM;
+                               goto err_free_chain;
 
                        cur_chain->next = chain;
                        chain->tqp_index = tx_ring->tqp->tqp_index;
@@ -2757,7 +2757,7 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
        while (rx_ring) {
                chain = devm_kzalloc(&pdev->dev, sizeof(*chain), GFP_KERNEL);
                if (!chain)
-                       return -ENOMEM;
+                       goto err_free_chain;
 
                cur_chain->next = chain;
                chain->tqp_index = rx_ring->tqp->tqp_index;
@@ -2772,6 +2772,16 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
        }
 
        return 0;
+
+err_free_chain:
+       cur_chain = head->next;
+       while (cur_chain) {
+               chain = cur_chain->next;
+               devm_kfree(&pdev->dev, chain);
+               cur_chain = chain;
+       }
+
+       return -ENOMEM;
 }
 
 static void hns3_free_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
@@ -3037,8 +3047,10 @@ static int hns3_queue_to_ring(struct hnae3_queue *tqp,
                return ret;
 
        ret = hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_RX);
-       if (ret)
+       if (ret) {
+               devm_kfree(priv->dev, priv->ring_data[tqp->tqp_index].ring);
                return ret;
+       }
 
        return 0;
 }
@@ -3065,6 +3077,12 @@ static int hns3_get_ring_config(struct hns3_nic_priv *priv)
 
        return 0;
 err:
+       while (i--) {
+               devm_kfree(priv->dev, priv->ring_data[i].ring);
+               devm_kfree(priv->dev,
+                          priv->ring_data[i + h->kinfo.num_tqps].ring);
+       }
+
        devm_kfree(&pdev->dev, priv->ring_data);
        return ret;
 }