net/mlx4: fix handling of probing failure
authorMichael Baum <michaelba@nvidia.com>
Wed, 20 Jan 2021 08:14:51 +0000 (08:14 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 29 Jan 2021 17:16:07 +0000 (18:16 +0100)
In mlx4 PCI probing, there are some validations for the Ethernet device
configuration.
From each PCI device the function creates one or two Ethernet devices.

When one of validations fails during the creation of the second device,
the first device is not freed what caused a memory leak.

Free it.

Fixes: 7fae69eeff13 ("mlx4: new poll mode driver")
Cc: stable@dpdk.org
Signed-off-by: Michael Baum <michaelba@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Tested-by: David Marchand <david.marchand@redhat.com>
drivers/net/mlx4/mlx4.c

index f520d32..284dcb9 100644 (file)
@@ -766,6 +766,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
        struct ibv_context *attr_ctx = NULL;
        struct ibv_device_attr device_attr;
        struct ibv_device_attr_ex device_attr_ex;
+       struct rte_eth_dev *prev_dev = NULL;
        struct mlx4_conf conf = {
                .ports.present = 0,
                .mr_ext_memseg_en = 1,
@@ -880,7 +881,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                                ERROR("can not attach rte ethdev");
                                rte_errno = ENOMEM;
                                err = rte_errno;
-                               goto error;
+                               goto err_secondary;
                        }
                        priv = eth_dev->data->dev_private;
                        if (!priv->verbs_alloc_ctx.enabled) {
@@ -889,24 +890,24 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                                      " from Verbs");
                                rte_errno = ENOTSUP;
                                err = rte_errno;
-                               goto error;
+                               goto err_secondary;
                        }
                        eth_dev->device = &pci_dev->device;
                        eth_dev->dev_ops = &mlx4_dev_sec_ops;
                        err = mlx4_proc_priv_init(eth_dev);
                        if (err)
-                               goto error;
+                               goto err_secondary;
                        /* Receive command fd from primary process. */
                        err = mlx4_mp_req_verbs_cmd_fd(eth_dev);
                        if (err < 0) {
                                err = rte_errno;
-                               goto error;
+                               goto err_secondary;
                        }
                        /* Remap UAR for Tx queues. */
                        err = mlx4_tx_uar_init_secondary(eth_dev, err);
                        if (err) {
                                err = rte_errno;
-                               goto error;
+                               goto err_secondary;
                        }
                        /*
                         * Ethdev pointer is still required as input since
@@ -918,7 +919,14 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                        claim_zero(mlx4_glue->close_device(ctx));
                        rte_eth_copy_pci_info(eth_dev, pci_dev);
                        rte_eth_dev_probing_finish(eth_dev);
+                       prev_dev = eth_dev;
                        continue;
+err_secondary:
+                       claim_zero(mlx4_glue->close_device(ctx));
+                       rte_eth_dev_release_port(eth_dev);
+                       if (prev_dev)
+                               rte_eth_dev_release_port(prev_dev);
+                       break;
                }
                /* Check port status. */
                err = mlx4_glue->query_port(ctx, port, &port_attr);
@@ -1093,6 +1101,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
                                 priv, mem_event_cb);
                rte_rwlock_write_unlock(&mlx4_shared_data->mem_event_rwlock);
                rte_eth_dev_probing_finish(eth_dev);
+               prev_dev = eth_dev;
                continue;
 port_error:
                rte_free(priv);
@@ -1107,14 +1116,10 @@ port_error:
                        eth_dev->data->mac_addrs = NULL;
                        rte_eth_dev_release_port(eth_dev);
                }
+               if (prev_dev)
+                       mlx4_dev_close(prev_dev);
                break;
        }
-       /*
-        * XXX if something went wrong in the loop above, there is a resource
-        * leak (ctx, pd, priv, dpdk ethdev) but we can do nothing about it as
-        * long as the dpdk does not provide a way to deallocate a ethdev and a
-        * way to enumerate the registered ethdevs to free the previous ones.
-        */
 error:
        if (attr_ctx)
                claim_zero(mlx4_glue->close_device(attr_ctx));