When ixgbe_recovery_probe() is invoked and this function fails,
allocated resources in advance are not completely freed, because
ixgbe_probe() returns ixgbe_recovery_probe() directly and
ixgbe_recovery_probe() only frees partial resources, resulting in memory
leaks including:
- adapter->io_addr
- adapter->jump_tables[0]
- adapter->mac_table
- adapter->rss_key
- adapter->af_xdp_zc_qps

The leaked MMIO region can be observed in /proc/vmallocinfo, and the
remaining leaks are reported by kmemleak.

Don't return ixgbe_recovery_probe() directly, and instead let
ixgbe_probe() to clean up resources on failures.

Fixes: 29cb3b8d95c7 ("ixgbe: add E610 implementation of FW recovery mode")
Signed-off-by: Kohei Enju <[email protected]>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 20 ++++++++-----------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 4af3b3e71ff1..85023bb4e5a5 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -11468,14 +11468,12 @@ static void ixgbe_set_fw_version(struct ixgbe_adapter 
*adapter)
  */
 static int ixgbe_recovery_probe(struct ixgbe_adapter *adapter)
 {
-       struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
        struct ixgbe_hw *hw = &adapter->hw;
-       bool disable_dev;
        int err = -EIO;
 
        if (hw->mac.type != ixgbe_mac_e610)
-               goto clean_up_probe;
+               return err;
 
        ixgbe_get_hw_control(adapter);
        mutex_init(&hw->aci.lock);
@@ -11507,13 +11505,6 @@ static int ixgbe_recovery_probe(struct ixgbe_adapter 
*adapter)
 shutdown_aci:
        mutex_destroy(&adapter->hw.aci.lock);
        ixgbe_release_hw_control(adapter);
-clean_up_probe:
-       disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
-       free_netdev(netdev);
-       devlink_free(adapter->devlink);
-       pci_release_mem_regions(pdev);
-       if (disable_dev)
-               pci_disable_device(pdev);
        return err;
 }
 
@@ -11655,8 +11646,13 @@ static int ixgbe_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
        if (err)
                goto err_sw_init;
 
-       if (ixgbe_check_fw_error(adapter))
-               return ixgbe_recovery_probe(adapter);
+       if (ixgbe_check_fw_error(adapter)) {
+               err = ixgbe_recovery_probe(adapter);
+               if (err)
+                       goto err_sw_init;
+
+               return 0;
+       }
 
        if (adapter->hw.mac.type == ixgbe_mac_e610) {
                err = ixgbe_get_caps(&adapter->hw);
-- 
2.52.0

Reply via email to