commit
1f893f57a3bf9fe1f4bcb25b55aea7f7f9712fe7 upstream.
From one hand, mlx5 driver is allowing to probe PFs in parallel.
From the other hand, devcom, which is a share resource between PFs, is
registered without any lock. This might resulted in memory problems.
Hence, use the global mlx5_dev_list_lock in order to serialize devcom
registration.
Fixes: fadd59fc50d0 ("net/mlx5: Introduce inter-device communication mechanism")
Signed-off-by: Shay Drory <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
#include <linux/mlx5/vport.h>
#include "lib/devcom.h"
#include <linux/mlx5/vport.h>
#include "lib/devcom.h"
static LIST_HEAD(devcom_list);
static LIST_HEAD(devcom_list);
if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
return NULL;
if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
return NULL;
sguid0 = mlx5_query_nic_system_image_guid(dev);
list_for_each_entry(iter, &devcom_list, list) {
struct mlx5_core_dev *tmp_dev = NULL;
sguid0 = mlx5_query_nic_system_image_guid(dev);
list_for_each_entry(iter, &devcom_list, list) {
struct mlx5_core_dev *tmp_dev = NULL;
if (!priv) {
priv = mlx5_devcom_list_alloc();
if (!priv) {
priv = mlx5_devcom_list_alloc();
- if (!priv)
- return ERR_PTR(-ENOMEM);
+ if (!priv) {
+ devcom = ERR_PTR(-ENOMEM);
+ goto out;
+ }
idx = 0;
new_priv = true;
idx = 0;
new_priv = true;
if (!devcom) {
if (new_priv)
kfree(priv);
if (!devcom) {
if (new_priv)
kfree(priv);
- return ERR_PTR(-ENOMEM);
+ devcom = ERR_PTR(-ENOMEM);
+ goto out;
}
if (new_priv)
list_add(&priv->list, &devcom_list);
}
if (new_priv)
list_add(&priv->list, &devcom_list);
+out:
+ mlx5_dev_list_unlock();
if (IS_ERR_OR_NULL(devcom))
return;
if (IS_ERR_OR_NULL(devcom))
return;
priv = devcom->priv;
priv->devs[devcom->idx] = NULL;
priv = devcom->priv;
priv->devs[devcom->idx] = NULL;
break;
if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
break;
if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
list_del(&priv->list);
kfree(priv);
list_del(&priv->list);
kfree(priv);
+out:
+ mlx5_dev_list_unlock();
}
void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
}
void mlx5_devcom_register_component(struct mlx5_devcom *devcom,