Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / drivers / net / ethernet / mellanox / mlx4 / cmd.c
index b16e1b9..5c93d14 100644 (file)
@@ -990,11 +990,11 @@ static struct mlx4_cmd_info cmd_info[] = {
        {
                .opcode = MLX4_CMD_CONFIG_DEV,
                .has_inbox = false,
-               .has_outbox = false,
+               .has_outbox = true,
                .out_is_imm = false,
                .encode_slave_id = false,
                .verify = NULL,
-               .wrapper = mlx4_CMD_EPERM_wrapper
+               .wrapper = mlx4_CONFIG_DEV_wrapper
        },
        {
                .opcode = MLX4_CMD_ALLOC_RES,
@@ -1338,6 +1338,15 @@ static struct mlx4_cmd_info cmd_info[] = {
                .verify = NULL,
                .wrapper = mlx4_QUERY_IF_STAT_wrapper
        },
+       {
+               .opcode = MLX4_CMD_ACCESS_REG,
+               .has_inbox = true,
+               .has_outbox = true,
+               .out_is_imm = false,
+               .encode_slave_id = false,
+               .verify = NULL,
+               .wrapper = mlx4_ACCESS_REG_wrapper,
+       },
        /* Native multicast commands are not available for guests */
        {
                .opcode = MLX4_CMD_QP_ATTACH,
@@ -2108,50 +2117,52 @@ err_vhcr:
 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;
+       }
 
-       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.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;
        }
 
-       priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev,
-                                        MLX4_MAILBOX_SIZE,
-                                        MLX4_MAILBOX_SIZE, 0);
-       if (!priv->cmd.pool)
-               goto err_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;
 
-       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;
 }
 
@@ -2175,18 +2186,28 @@ 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);
 
-       pci_pool_destroy(priv->cmd.pool);
+       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;
+               priv->mfunc.vhcr = NULL;
+       }
+       if (priv->cmd.initialized && (cleanup_mask & MLX4_CMD_CLEANUP_STRUCT))
+               priv->cmd.initialized = 0;
 }
 
 /*