Commit da315679 authored by Matan Barak's avatar Matan Barak Committed by David S. Miller

net/mlx4_core: Fixed memory leak and incorrect refcount in mlx4_load_one

The current mlx4_load_one has a memory leak as it always allocates
dev_cap, but frees it only on error.

In addition, even if VFs exist when mlx4_load_one is called,
we still need to notify probed VFs that we're loading (by
incrementing pf_loading).

Fixes: a0eacca9 ('net/mlx4_core: Refactor mlx4_load_one')
Signed-off-by: default avatarMatan Barak <matanb@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 67e2c388
...@@ -2488,41 +2488,42 @@ static u64 mlx4_enable_sriov(struct mlx4_dev *dev, struct pci_dev *pdev, ...@@ -2488,41 +2488,42 @@ static u64 mlx4_enable_sriov(struct mlx4_dev *dev, struct pci_dev *pdev,
u8 total_vfs, int existing_vfs) u8 total_vfs, int existing_vfs)
{ {
u64 dev_flags = dev->flags; u64 dev_flags = dev->flags;
int err = 0;
dev->dev_vfs = kzalloc( atomic_inc(&pf_loading);
total_vfs * sizeof(*dev->dev_vfs), if (dev->flags & MLX4_FLAG_SRIOV) {
GFP_KERNEL); if (existing_vfs != total_vfs) {
mlx4_err(dev, "SR-IOV was already enabled, but with num_vfs (%d) different than requested (%d)\n",
existing_vfs, total_vfs);
total_vfs = existing_vfs;
}
}
dev->dev_vfs = kzalloc(total_vfs * sizeof(*dev->dev_vfs), GFP_KERNEL);
if (NULL == dev->dev_vfs) { if (NULL == dev->dev_vfs) {
mlx4_err(dev, "Failed to allocate memory for VFs\n"); mlx4_err(dev, "Failed to allocate memory for VFs\n");
goto disable_sriov; goto disable_sriov;
} else if (!(dev->flags & MLX4_FLAG_SRIOV)) { }
int err = 0;
if (!(dev->flags & MLX4_FLAG_SRIOV)) {
atomic_inc(&pf_loading); mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", total_vfs);
if (existing_vfs) { err = pci_enable_sriov(pdev, total_vfs);
if (existing_vfs != total_vfs) }
mlx4_err(dev, "SR-IOV was already enabled, but with num_vfs (%d) different than requested (%d)\n", if (err) {
existing_vfs, total_vfs); mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d)\n",
} else { err);
mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", total_vfs); goto disable_sriov;
err = pci_enable_sriov(pdev, total_vfs); } else {
} mlx4_warn(dev, "Running in master mode\n");
if (err) { dev_flags |= MLX4_FLAG_SRIOV |
mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d)\n", MLX4_FLAG_MASTER;
err); dev_flags &= ~MLX4_FLAG_SLAVE;
atomic_dec(&pf_loading); dev->num_vfs = total_vfs;
goto disable_sriov;
} else {
mlx4_warn(dev, "Running in master mode\n");
dev_flags |= MLX4_FLAG_SRIOV |
MLX4_FLAG_MASTER;
dev_flags &= ~MLX4_FLAG_SLAVE;
dev->num_vfs = total_vfs;
}
} }
return dev_flags; return dev_flags;
disable_sriov: disable_sriov:
atomic_dec(&pf_loading);
dev->num_vfs = 0; dev->num_vfs = 0;
kfree(dev->dev_vfs); kfree(dev->dev_vfs);
return dev_flags & ~MLX4_FLAG_MASTER; return dev_flags & ~MLX4_FLAG_MASTER;
...@@ -2606,8 +2607,10 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, ...@@ -2606,8 +2607,10 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,
} }
if (total_vfs) { if (total_vfs) {
existing_vfs = pci_num_vf(pdev);
dev->flags = MLX4_FLAG_MASTER; dev->flags = MLX4_FLAG_MASTER;
existing_vfs = pci_num_vf(pdev);
if (existing_vfs)
dev->flags |= MLX4_FLAG_SRIOV;
dev->num_vfs = total_vfs; dev->num_vfs = total_vfs;
} }
} }
...@@ -2643,6 +2646,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, ...@@ -2643,6 +2646,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,
} }
if (mlx4_is_master(dev)) { if (mlx4_is_master(dev)) {
/* when we hit the goto slave_start below, dev_cap already initialized */
if (!dev_cap) { if (!dev_cap) {
dev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL); dev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL);
...@@ -2849,6 +2853,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, ...@@ -2849,6 +2853,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,
if (mlx4_is_master(dev) && dev->num_vfs) if (mlx4_is_master(dev) && dev->num_vfs)
atomic_dec(&pf_loading); atomic_dec(&pf_loading);
kfree(dev_cap);
return 0; return 0;
err_port: err_port:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment