Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / drivers / net / ethernet / mellanox / mlx4 / cmd.c
index 3c05e58..5c93d14 100644 (file)
@@ -2117,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;
 }
 
@@ -2184,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;
 }
 
 /*