mt76: mt7663u: fix memory leaks in mt7663u_probe
authorLorenzo Bianconi <lorenzo@kernel.org>
Sun, 21 Jun 2020 16:03:38 +0000 (18:03 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 23 Jun 2020 08:43:16 +0000 (11:43 +0300)
Fix the two following memory leaks in mt7663u_probe:
1- if device power-own times out, remove ieee80211 hw device.
2- if mt76u queues allocation fails, remove pending urbs.

Fixes: eb99cc95c3b65 ("mt76: mt7615: introduce mt7663u support")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/e4098f0c8a9ac51997de07f38c2bcdf7042d6db1.1592755166.git.lorenzo@kernel.org
drivers/net/wireless/mediatek/mt76/mt7615/usb.c
drivers/net/wireless/mediatek/mt76/usb.c

index f5dc1b8..5be6704 100644 (file)
@@ -329,25 +329,26 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
        if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
                            FW_STATE_PWR_ON << 1, 500)) {
                dev_err(dev->mt76.dev, "Timeout for power on\n");
-               return -EIO;
+               ret = -EIO;
+               goto error;
        }
 
 alloc_queues:
        ret = mt76u_alloc_mcu_queue(&dev->mt76);
        if (ret)
-               goto error;
+               goto error_free_q;
 
        ret = mt76u_alloc_queues(&dev->mt76);
        if (ret)
-               goto error;
+               goto error_free_q;
 
        ret = mt7663u_register_device(dev);
        if (ret)
-               goto error_freeq;
+               goto error_free_q;
 
        return 0;
 
-error_freeq:
+error_free_q:
        mt76u_queues_deinit(&dev->mt76);
 error:
        mt76u_deinit(&dev->mt76);
index 27abcdb..87382b2 100644 (file)
@@ -1067,11 +1067,16 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
 
 static void mt76u_free_tx(struct mt76_dev *dev)
 {
-       struct mt76_queue *q;
-       int i, j;
+       int i;
 
        for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+               struct mt76_queue *q;
+               int j;
+
                q = dev->q_tx[i].q;
+               if (!q)
+                       continue;
+
                for (j = 0; j < q->ndesc; j++)
                        usb_free_urb(q->entry[j].urb);
        }
@@ -1079,17 +1084,22 @@ static void mt76u_free_tx(struct mt76_dev *dev)
 
 void mt76u_stop_tx(struct mt76_dev *dev)
 {
-       struct mt76_queue_entry entry;
-       struct mt76_queue *q;
-       int i, j, ret;
+       int ret;
 
        ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(&dev->phy),
                                 HZ / 5);
        if (!ret) {
+               struct mt76_queue_entry entry;
+               struct mt76_queue *q;
+               int i, j;
+
                dev_err(dev->dev, "timed out waiting for pending tx\n");
 
                for (i = 0; i < IEEE80211_NUM_ACS; i++) {
                        q = dev->q_tx[i].q;
+                       if (!q)
+                               continue;
+
                        for (j = 0; j < q->ndesc; j++)
                                usb_kill_urb(q->entry[j].urb);
                }
@@ -1101,6 +1111,8 @@ void mt76u_stop_tx(struct mt76_dev *dev)
                 */
                for (i = 0; i < IEEE80211_NUM_ACS; i++) {
                        q = dev->q_tx[i].q;
+                       if (!q)
+                               continue;
 
                        /* Assure we are in sync with killed tasklet. */
                        spin_lock_bh(&q->lock);