]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
Merge tag 'nfc-next-4.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo...
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / ethernet / chelsio / cxgb4 / t4_hw.c
index 7907d85efa4ca934189852d88257efaed96b7d95..a63addb4e72c619f16642891fb94631a17ce5d83 100644 (file)
@@ -224,18 +224,34 @@ static void fw_asrt(struct adapter *adap, u32 mbox_addr)
                  be32_to_cpu(asrt.u.assert.x), be32_to_cpu(asrt.u.assert.y));
 }
 
-static void dump_mbox(struct adapter *adap, int mbox, u32 data_reg)
+/**
+ *     t4_record_mbox - record a Firmware Mailbox Command/Reply in the log
+ *     @adapter: the adapter
+ *     @cmd: the Firmware Mailbox Command or Reply
+ *     @size: command length in bytes
+ *     @access: the time (ms) needed to access the Firmware Mailbox
+ *     @execute: the time (ms) the command spent being executed
+ */
+static void t4_record_mbox(struct adapter *adapter,
+                          const __be64 *cmd, unsigned int size,
+                          int access, int execute)
 {
-       dev_err(adap->pdev_dev,
-               "mbox %d: %llx %llx %llx %llx %llx %llx %llx %llx\n", mbox,
-               (unsigned long long)t4_read_reg64(adap, data_reg),
-               (unsigned long long)t4_read_reg64(adap, data_reg + 8),
-               (unsigned long long)t4_read_reg64(adap, data_reg + 16),
-               (unsigned long long)t4_read_reg64(adap, data_reg + 24),
-               (unsigned long long)t4_read_reg64(adap, data_reg + 32),
-               (unsigned long long)t4_read_reg64(adap, data_reg + 40),
-               (unsigned long long)t4_read_reg64(adap, data_reg + 48),
-               (unsigned long long)t4_read_reg64(adap, data_reg + 56));
+       struct mbox_cmd_log *log = adapter->mbox_log;
+       struct mbox_cmd *entry;
+       int i;
+
+       entry = mbox_cmd_log_entry(log, log->cursor++);
+       if (log->cursor == log->size)
+               log->cursor = 0;
+
+       for (i = 0; i < size / 8; i++)
+               entry->cmd[i] = be64_to_cpu(cmd[i]);
+       while (i < MBOX_LEN / 8)
+               entry->cmd[i++] = 0;
+       entry->timestamp = jiffies;
+       entry->seqno = log->seqno++;
+       entry->access = access;
+       entry->execute = execute;
 }
 
 /**
@@ -268,12 +284,16 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
                1, 1, 3, 5, 10, 10, 20, 50, 100, 200
        };
 
+       u16 access = 0;
+       u16 execute = 0;
        u32 v;
        u64 res;
-       int i, ms, delay_idx;
+       int i, ms, delay_idx, ret;
        const __be64 *p = cmd;
        u32 data_reg = PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
        u32 ctl_reg = PF_REG(mbox, CIM_PF_MAILBOX_CTRL_A);
+       __be64 cmd_rpl[MBOX_LEN / 8];
+       u32 pcie_fw;
 
        if ((size & 15) || size > MBOX_LEN)
                return -EINVAL;
@@ -285,13 +305,24 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
        if (adap->pdev->error_state != pci_channel_io_normal)
                return -EIO;
 
+       /* If we have a negative timeout, that implies that we can't sleep. */
+       if (timeout < 0) {
+               sleep_ok = false;
+               timeout = -timeout;
+       }
+
        v = MBOWNER_G(t4_read_reg(adap, ctl_reg));
        for (i = 0; v == MBOX_OWNER_NONE && i < 3; i++)
                v = MBOWNER_G(t4_read_reg(adap, ctl_reg));
 
-       if (v != MBOX_OWNER_DRV)
-               return v ? -EBUSY : -ETIMEDOUT;
+       if (v != MBOX_OWNER_DRV) {
+               ret = (v == MBOX_OWNER_FW) ? -EBUSY : -ETIMEDOUT;
+               t4_record_mbox(adap, cmd, MBOX_LEN, access, ret);
+               return ret;
+       }
 
+       /* Copy in the new mailbox command and send it on its way ... */
+       t4_record_mbox(adap, cmd, MBOX_LEN, access, 0);
        for (i = 0; i < size; i += 8)
                t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p++));
 
@@ -301,7 +332,10 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
        delay_idx = 0;
        ms = delay[0];
 
-       for (i = 0; i < timeout; i += ms) {
+       for (i = 0;
+            !((pcie_fw = t4_read_reg(adap, PCIE_FW_A)) & PCIE_FW_ERR_F) &&
+            i < timeout;
+            i += ms) {
                if (sleep_ok) {
                        ms = delay[delay_idx];  /* last element may repeat */
                        if (delay_idx < ARRAY_SIZE(delay) - 1)
@@ -317,26 +351,31 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
                                continue;
                        }
 
-                       res = t4_read_reg64(adap, data_reg);
+                       get_mbox_rpl(adap, cmd_rpl, MBOX_LEN / 8, data_reg);
+                       res = be64_to_cpu(cmd_rpl[0]);
+
                        if (FW_CMD_OP_G(res >> 32) == FW_DEBUG_CMD) {
                                fw_asrt(adap, data_reg);
                                res = FW_CMD_RETVAL_V(EIO);
                        } else if (rpl) {
-                               get_mbox_rpl(adap, rpl, size / 8, data_reg);
+                               memcpy(rpl, cmd_rpl, size);
                        }
 
-                       if (FW_CMD_RETVAL_G((int)res))
-                               dump_mbox(adap, mbox, data_reg);
                        t4_write_reg(adap, ctl_reg, 0);
+
+                       execute = i + ms;
+                       t4_record_mbox(adap, cmd_rpl,
+                                      MBOX_LEN, access, execute);
                        return -FW_CMD_RETVAL_G((int)res);
                }
        }
 
-       dump_mbox(adap, mbox, data_reg);
+       ret = (pcie_fw & PCIE_FW_ERR_F) ? -ENXIO : -ETIMEDOUT;
+       t4_record_mbox(adap, cmd, MBOX_LEN, access, ret);
        dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n",
                *(const u8 *)cmd, mbox);
        t4_report_fw_error(adap);
-       return -ETIMEDOUT;
+       return ret;
 }
 
 int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,