]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: mwifiex: fix error recovery in PCIE buffer descriptor management
authorDmitry Antipov <dmantipov@yandex.ru>
Mon, 31 Jul 2023 07:43:07 +0000 (10:43 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 19 Sep 2023 10:22:33 +0000 (12:22 +0200)
[ Upstream commit 288c63d5cb4667a51a04668b3e2bb0ea499bc5f4 ]

Add missing 'kfree_skb()' in 'mwifiex_init_rxq_ring()' and never do
'kfree(card->rxbd_ring_vbase)' because this area is DMAed and should
be released with 'dma_free_coherent()'. The latter is performed in
'mwifiex_pcie_delete_rxbd_ring()', which is now called to recover
from possible errors in 'mwifiex_pcie_create_rxbd_ring()'. Likewise
for 'mwifiex_pcie_init_evt_ring()', 'kfree(card->evtbd_ring_vbase)'
'mwifiex_pcie_delete_evtbd_ring()' and 'mwifiex_pcie_create_rxbd_ring()'.

Fixes: d930faee141b ("mwifiex: add support for Marvell pcie8766 chipset")
Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
Acked-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230731074334.56463-1-dmantipov@yandex.ru
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/marvell/mwifiex/pcie.c

index 94a6bbcae2d381ce022180b77dc0f07ee17b397d..8b3f46586654a1635af710c183d47a95bc12c061 100644 (file)
@@ -201,6 +201,8 @@ static int mwifiex_pcie_probe_of(struct device *dev)
 }
 
 static void mwifiex_pcie_work(struct work_struct *work);
+static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter);
+static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter);
 
 static int
 mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
@@ -804,14 +806,15 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
                if (!skb) {
                        mwifiex_dbg(adapter, ERROR,
                                    "Unable to allocate skb for RX ring.\n");
-                       kfree(card->rxbd_ring_vbase);
                        return -ENOMEM;
                }
 
                if (mwifiex_map_pci_memory(adapter, skb,
                                           MWIFIEX_RX_DATA_BUF_SIZE,
-                                          DMA_FROM_DEVICE))
-                       return -1;
+                                          DMA_FROM_DEVICE)) {
+                       kfree_skb(skb);
+                       return -ENOMEM;
+               }
 
                buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 
@@ -861,7 +864,6 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
                if (!skb) {
                        mwifiex_dbg(adapter, ERROR,
                                    "Unable to allocate skb for EVENT buf.\n");
-                       kfree(card->evtbd_ring_vbase);
                        return -ENOMEM;
                }
                skb_put(skb, MAX_EVENT_SIZE);
@@ -869,8 +871,7 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
                if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
                                           DMA_FROM_DEVICE)) {
                        kfree_skb(skb);
-                       kfree(card->evtbd_ring_vbase);
-                       return -1;
+                       return -ENOMEM;
                }
 
                buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
@@ -1070,6 +1071,7 @@ static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
  */
 static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
 {
+       int ret;
        struct pcie_service_card *card = adapter->card;
        const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
@@ -1108,7 +1110,10 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
                    (u32)((u64)card->rxbd_ring_pbase >> 32),
                    card->rxbd_ring_size);
 
-       return mwifiex_init_rxq_ring(adapter);
+       ret = mwifiex_init_rxq_ring(adapter);
+       if (ret)
+               mwifiex_pcie_delete_rxbd_ring(adapter);
+       return ret;
 }
 
 /*
@@ -1139,6 +1144,7 @@ static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
  */
 static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
 {
+       int ret;
        struct pcie_service_card *card = adapter->card;
        const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
@@ -1173,7 +1179,10 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
                    (u32)((u64)card->evtbd_ring_pbase >> 32),
                    card->evtbd_ring_size);
 
-       return mwifiex_pcie_init_evt_ring(adapter);
+       ret = mwifiex_pcie_init_evt_ring(adapter);
+       if (ret)
+               mwifiex_pcie_delete_evtbd_ring(adapter);
+       return ret;
 }
 
 /*