]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/net/ethernet/mellanox/mlx4/cmd.c
mlx4: Add support for EEH error recovery
[mirror_ubuntu-bionic-kernel.git] / drivers / net / ethernet / mellanox / mlx4 / cmd.c
index 7e94987d030c4da44885c5aa3dd56daf1d022907..c8fef435302155d32aa8236e0118c2406241c48c 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,