IB/mlx4: Initialize SR-IOV IB support for slaves in master context
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlx4 / cmd.c
index 7e94987d030c4da44885c5aa3dd56daf1d022907..cb9bebe28276608c188d3e29c1af9a9fb1c62b86 100644 (file)
@@ -296,7 +296,12 @@ int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param,
 
 static int cmd_pending(struct mlx4_dev *dev)
 {
-       u32 status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
+       u32 status;
+
+       if (pci_channel_offline(dev->pdev))
+               return -EIO;
+
+       status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
 
        return (status & swab32(1 << HCR_GO_BIT)) ||
                (mlx4_priv(dev)->cmd.toggle ==
@@ -314,11 +319,29 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param,
 
        mutex_lock(&cmd->hcr_mutex);
 
+       if (pci_channel_offline(dev->pdev)) {
+               /*
+                * Device is going through error recovery
+                * and cannot accept commands.
+                */
+               ret = -EIO;
+               goto out;
+       }
+
        end = jiffies;
        if (event)
                end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS);
 
        while (cmd_pending(dev)) {
+               if (pci_channel_offline(dev->pdev)) {
+                       /*
+                        * Device is going through error recovery
+                        * and cannot accept commands.
+                        */
+                       ret = -EIO;
+                       goto out;
+               }
+
                if (time_after_eq(jiffies, end)) {
                        mlx4_err(dev, "%s:cmd_pending failed\n", __func__);
                        goto out;
@@ -431,14 +454,33 @@ static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
 
        down(&priv->cmd.poll_sem);
 
+       if (pci_channel_offline(dev->pdev)) {
+               /*
+                * Device is going through error recovery
+                * and cannot accept commands.
+                */
+               err = -EIO;
+               goto out;
+       }
+
        err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0,
                            in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0);
        if (err)
                goto out;
 
        end = msecs_to_jiffies(timeout) + jiffies;
-       while (cmd_pending(dev) && time_before(jiffies, end))
+       while (cmd_pending(dev) && time_before(jiffies, end)) {
+               if (pci_channel_offline(dev->pdev)) {
+                       /*
+                        * Device is going through error recovery
+                        * and cannot accept commands.
+                        */
+                       err = -EIO;
+                       goto out;
+               }
+
                cond_resched();
+       }
 
        if (cmd_pending(dev)) {
                err = -ETIMEDOUT;
@@ -532,6 +574,9 @@ int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
               int out_is_imm, u32 in_modifier, u8 op_modifier,
               u16 op, unsigned long timeout, int native)
 {
+       if (pci_channel_offline(dev->pdev))
+               return -EIO;
+
        if (!mlx4_is_mfunc(dev) || (native && mlx4_is_master(dev))) {
                if (mlx4_priv(dev)->cmd.use_events)
                        return mlx4_cmd_wait(dev, in_param, out_param,
@@ -1295,6 +1340,8 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
                if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd)
                        goto inform_slave_state;
 
+               mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN, slave);
+
                /* write the version in the event field */
                reply |= mlx4_comm_get_version();
 
@@ -1331,6 +1378,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
                        goto reset_slave;
                slave_state[slave].vhcr_dma |= param;
                slave_state[slave].active = true;
+               mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, slave);
                break;
        case MLX4_COMM_CMD_VHCR_POST:
                if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) &&