diff options
author | Matan Barak <matanb@mellanox.com> | 2014-12-14 09:18:04 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-15 11:34:53 -0500 |
commit | da315679e80635021e98de1306ff4eee0759ba57 (patch) | |
tree | 35ce69487bed726b3225d9bd320dd80d50e6a328 | |
parent | 67e2c3883828b39548cee2091b36656787775d95 (diff) |
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: a0eacca948d2 ('net/mlx4_core: Refactor mlx4_load_one')
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 61 |
1 files changed, 33 insertions, 28 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index e25436b24ce7..c2ef266ad7c1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -2488,41 +2488,42 @@ static u64 mlx4_enable_sriov(struct mlx4_dev *dev, struct pci_dev *pdev, | |||
2488 | u8 total_vfs, int existing_vfs) | 2488 | u8 total_vfs, int existing_vfs) |
2489 | { | 2489 | { |
2490 | u64 dev_flags = dev->flags; | 2490 | u64 dev_flags = dev->flags; |
2491 | int err = 0; | ||
2491 | 2492 | ||
2492 | dev->dev_vfs = kzalloc( | 2493 | atomic_inc(&pf_loading); |
2493 | total_vfs * sizeof(*dev->dev_vfs), | 2494 | if (dev->flags & MLX4_FLAG_SRIOV) { |
2494 | GFP_KERNEL); | 2495 | if (existing_vfs != total_vfs) { |
2496 | mlx4_err(dev, "SR-IOV was already enabled, but with num_vfs (%d) different than requested (%d)\n", | ||
2497 | existing_vfs, total_vfs); | ||
2498 | total_vfs = existing_vfs; | ||
2499 | } | ||
2500 | } | ||
2501 | |||
2502 | dev->dev_vfs = kzalloc(total_vfs * sizeof(*dev->dev_vfs), GFP_KERNEL); | ||
2495 | if (NULL == dev->dev_vfs) { | 2503 | if (NULL == dev->dev_vfs) { |
2496 | mlx4_err(dev, "Failed to allocate memory for VFs\n"); | 2504 | mlx4_err(dev, "Failed to allocate memory for VFs\n"); |
2497 | goto disable_sriov; | 2505 | goto disable_sriov; |
2498 | } else if (!(dev->flags & MLX4_FLAG_SRIOV)) { | 2506 | } |
2499 | int err = 0; | 2507 | |
2500 | 2508 | if (!(dev->flags & MLX4_FLAG_SRIOV)) { | |
2501 | atomic_inc(&pf_loading); | 2509 | mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", total_vfs); |
2502 | if (existing_vfs) { | 2510 | err = pci_enable_sriov(pdev, total_vfs); |
2503 | if (existing_vfs != total_vfs) | 2511 | } |
2504 | mlx4_err(dev, "SR-IOV was already enabled, but with num_vfs (%d) different than requested (%d)\n", | 2512 | if (err) { |
2505 | existing_vfs, total_vfs); | 2513 | mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d)\n", |
2506 | } else { | 2514 | err); |
2507 | mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", total_vfs); | 2515 | goto disable_sriov; |
2508 | err = pci_enable_sriov(pdev, total_vfs); | 2516 | } else { |
2509 | } | 2517 | mlx4_warn(dev, "Running in master mode\n"); |
2510 | if (err) { | 2518 | dev_flags |= MLX4_FLAG_SRIOV | |
2511 | mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d)\n", | 2519 | MLX4_FLAG_MASTER; |
2512 | err); | 2520 | dev_flags &= ~MLX4_FLAG_SLAVE; |
2513 | atomic_dec(&pf_loading); | 2521 | dev->num_vfs = total_vfs; |
2514 | goto disable_sriov; | ||
2515 | } else { | ||
2516 | mlx4_warn(dev, "Running in master mode\n"); | ||
2517 | dev_flags |= MLX4_FLAG_SRIOV | | ||
2518 | MLX4_FLAG_MASTER; | ||
2519 | dev_flags &= ~MLX4_FLAG_SLAVE; | ||
2520 | dev->num_vfs = total_vfs; | ||
2521 | } | ||
2522 | } | 2522 | } |
2523 | return dev_flags; | 2523 | return dev_flags; |
2524 | 2524 | ||
2525 | disable_sriov: | 2525 | disable_sriov: |
2526 | atomic_dec(&pf_loading); | ||
2526 | dev->num_vfs = 0; | 2527 | dev->num_vfs = 0; |
2527 | kfree(dev->dev_vfs); | 2528 | kfree(dev->dev_vfs); |
2528 | return dev_flags & ~MLX4_FLAG_MASTER; | 2529 | return dev_flags & ~MLX4_FLAG_MASTER; |
@@ -2606,8 +2607,10 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, | |||
2606 | } | 2607 | } |
2607 | 2608 | ||
2608 | if (total_vfs) { | 2609 | if (total_vfs) { |
2609 | existing_vfs = pci_num_vf(pdev); | ||
2610 | dev->flags = MLX4_FLAG_MASTER; | 2610 | dev->flags = MLX4_FLAG_MASTER; |
2611 | existing_vfs = pci_num_vf(pdev); | ||
2612 | if (existing_vfs) | ||
2613 | dev->flags |= MLX4_FLAG_SRIOV; | ||
2611 | dev->num_vfs = total_vfs; | 2614 | dev->num_vfs = total_vfs; |
2612 | } | 2615 | } |
2613 | } | 2616 | } |
@@ -2643,6 +2646,7 @@ slave_start: | |||
2643 | } | 2646 | } |
2644 | 2647 | ||
2645 | if (mlx4_is_master(dev)) { | 2648 | if (mlx4_is_master(dev)) { |
2649 | /* when we hit the goto slave_start below, dev_cap already initialized */ | ||
2646 | if (!dev_cap) { | 2650 | if (!dev_cap) { |
2647 | dev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL); | 2651 | dev_cap = kzalloc(sizeof(*dev_cap), GFP_KERNEL); |
2648 | 2652 | ||
@@ -2849,6 +2853,7 @@ slave_start: | |||
2849 | if (mlx4_is_master(dev) && dev->num_vfs) | 2853 | if (mlx4_is_master(dev) && dev->num_vfs) |
2850 | atomic_dec(&pf_loading); | 2854 | atomic_dec(&pf_loading); |
2851 | 2855 | ||
2856 | kfree(dev_cap); | ||
2852 | return 0; | 2857 | return 0; |
2853 | 2858 | ||
2854 | err_port: | 2859 | err_port: |