Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ffc39f6d authored by Matan Barak's avatar Matan Barak Committed by David S. Miller
Browse files

net/mlx4_core: Refactor mlx4_cmd_init and mlx4_cmd_cleanup



Refactoring mlx4_cmd_init and mlx4_cmd_cleanup such that partial init
and cleanup are possible. After this refactoring, calling mlx4_cmd_init
several times is safe.

This is necessary in the VF init flow when mlx4_init_hca returns -EACCESS,
we need to issue cleanup and re-attempt to call it with the slave flag.

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 225c6c8c
Loading
Loading
Loading
Loading
+44 −32
Original line number Diff line number Diff line
@@ -2117,50 +2117,52 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
int mlx4_cmd_init(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	int flags = 0;

	if (!priv->cmd.initialized) {
		mutex_init(&priv->cmd.hcr_mutex);
		mutex_init(&priv->cmd.slave_cmd_mutex);
		sema_init(&priv->cmd.poll_sem, 1);
		priv->cmd.use_events = 0;
		priv->cmd.toggle     = 1;
		priv->cmd.initialized = 1;
		flags |= MLX4_CMD_CLEANUP_STRUCT;
	}

	priv->cmd.hcr = NULL;
	priv->mfunc.vhcr = NULL;

	if (!mlx4_is_slave(dev)) {
	if (!mlx4_is_slave(dev) && !priv->cmd.hcr) {
		priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) +
					MLX4_HCR_BASE, MLX4_HCR_SIZE);
		if (!priv->cmd.hcr) {
			mlx4_err(dev, "Couldn't map command register\n");
			return -ENOMEM;
			goto err;
		}
		flags |= MLX4_CMD_CLEANUP_HCR;
	}

	if (mlx4_is_mfunc(dev)) {
	if (mlx4_is_mfunc(dev) && !priv->mfunc.vhcr) {
		priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
						      &priv->mfunc.vhcr_dma,
						      GFP_KERNEL);
		if (!priv->mfunc.vhcr)
			goto err_hcr;
			goto err;

		flags |= MLX4_CMD_CLEANUP_VHCR;
	}

	if (!priv->cmd.pool) {
		priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev,
						 MLX4_MAILBOX_SIZE,
						 MLX4_MAILBOX_SIZE, 0);
		if (!priv->cmd.pool)
		goto err_vhcr;
			goto err;

	return 0;
		flags |= MLX4_CMD_CLEANUP_POOL;
	}

err_vhcr:
	if (mlx4_is_mfunc(dev))
		dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
				  priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
	priv->mfunc.vhcr = NULL;
	return 0;

err_hcr:
	if (!mlx4_is_slave(dev))
		iounmap(priv->cmd.hcr);
err:
	mlx4_cmd_cleanup(dev, flags);
	return -ENOMEM;
}

@@ -2184,19 +2186,29 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
	iounmap(priv->mfunc.comm);
}

void mlx4_cmd_cleanup(struct mlx4_dev *dev)
void mlx4_cmd_cleanup(struct mlx4_dev *dev, int cleanup_mask)
{
	struct mlx4_priv *priv = mlx4_priv(dev);

	if (priv->cmd.pool && (cleanup_mask & MLX4_CMD_CLEANUP_POOL)) {
		pci_pool_destroy(priv->cmd.pool);
		priv->cmd.pool = NULL;
	}

	if (!mlx4_is_slave(dev))
	if (!mlx4_is_slave(dev) && priv->cmd.hcr &&
	    (cleanup_mask & MLX4_CMD_CLEANUP_HCR)) {
		iounmap(priv->cmd.hcr);
	if (mlx4_is_mfunc(dev))
		priv->cmd.hcr = NULL;
	}
	if (mlx4_is_mfunc(dev) && priv->mfunc.vhcr &&
	    (cleanup_mask & MLX4_CMD_CLEANUP_VHCR)) {
		dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
				  priv->mfunc.vhcr, priv->mfunc.vhcr_dma);
		priv->mfunc.vhcr = NULL;
	}
	if (priv->cmd.initialized && (cleanup_mask & MLX4_CMD_CLEANUP_STRUCT))
		priv->cmd.initialized = 0;
}

/*
 * Switch to using events to issue FW commands (can only be called
+3 −3
Original line number Diff line number Diff line
@@ -2396,7 +2396,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,
		if (err == -EACCES) {
			/* Not primary Physical function
			 * Running in slave mode */
			mlx4_cmd_cleanup(dev);
			mlx4_cmd_cleanup(dev, MLX4_CMD_CLEANUP_ALL);
			dev->flags |= MLX4_FLAG_SLAVE;
			dev->flags &= ~MLX4_FLAG_MASTER;
			goto slave_start;
@@ -2561,7 +2561,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,
		mlx4_multi_func_cleanup(dev);

err_cmd:
	mlx4_cmd_cleanup(dev);
	mlx4_cmd_cleanup(dev, MLX4_CMD_CLEANUP_ALL);

err_sriov:
	if (dev->flags & MLX4_FLAG_SRIOV && !existing_vfs)
@@ -2805,7 +2805,7 @@ static void mlx4_unload_one(struct pci_dev *pdev)
	mlx4_close_hca(dev);
	if (mlx4_is_slave(dev))
		mlx4_multi_func_cleanup(dev);
	mlx4_cmd_cleanup(dev);
	mlx4_cmd_cleanup(dev, MLX4_CMD_CLEANUP_ALL);

	if (dev->flags & MLX4_FLAG_MSI_X)
		pci_disable_msix(pdev);
+10 −1
Original line number Diff line number Diff line
@@ -606,6 +606,7 @@ struct mlx4_cmd {
	u8			use_events;
	u8			toggle;
	u8			comm_toggle;
	u8			initialized;
};

enum {
@@ -1126,8 +1127,16 @@ int mlx4_QUERY_QP_wrapper(struct mlx4_dev *dev, int slave,

int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe);

enum {
	MLX4_CMD_CLEANUP_STRUCT = 1UL << 0,
	MLX4_CMD_CLEANUP_POOL	= 1UL << 1,
	MLX4_CMD_CLEANUP_HCR	= 1UL << 2,
	MLX4_CMD_CLEANUP_VHCR	= 1UL << 3,
	MLX4_CMD_CLEANUP_ALL	= (MLX4_CMD_CLEANUP_VHCR << 1) - 1
};

int mlx4_cmd_init(struct mlx4_dev *dev);
void mlx4_cmd_cleanup(struct mlx4_dev *dev);
void mlx4_cmd_cleanup(struct mlx4_dev *dev, int cleanup_mask);
int mlx4_multi_func_init(struct mlx4_dev *dev);
void mlx4_multi_func_cleanup(struct mlx4_dev *dev);
void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param);