|
@@ -139,6 +139,7 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
|
|
|
u32 mbox_ctl = T4VF_CIM_BASE_ADDR + CIM_VF_EXT_MAILBOX_CTRL;
|
|
|
u32 cmd_op = FW_CMD_OP_G(be32_to_cpu(((struct fw_cmd_hdr *)cmd)->hi));
|
|
|
__be64 cmd_rpl[MBOX_LEN / 8];
|
|
|
+ struct mbox_list entry;
|
|
|
|
|
|
/* In T6, mailbox size is changed to 128 bytes to avoid
|
|
|
* invalidating the entire prefetch buffer.
|
|
@@ -156,6 +157,51 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
|
|
|
size > NUM_CIM_VF_MAILBOX_DATA_INSTANCES * 4)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ /* Queue ourselves onto the mailbox access list. When our entry is at
|
|
|
+ * the front of the list, we have rights to access the mailbox. So we
|
|
|
+ * wait [for a while] till we're at the front [or bail out with an
|
|
|
+ * EBUSY] ...
|
|
|
+ */
|
|
|
+ spin_lock(&adapter->mbox_lock);
|
|
|
+ list_add_tail(&entry.list, &adapter->mlist.list);
|
|
|
+ spin_unlock(&adapter->mbox_lock);
|
|
|
+
|
|
|
+ delay_idx = 0;
|
|
|
+ ms = delay[0];
|
|
|
+
|
|
|
+ for (i = 0; ; i += ms) {
|
|
|
+ /* If we've waited too long, return a busy indication. This
|
|
|
+ * really ought to be based on our initial position in the
|
|
|
+ * mailbox access list but this is a start. We very rearely
|
|
|
+ * contend on access to the mailbox ...
|
|
|
+ */
|
|
|
+ if (i > FW_CMD_MAX_TIMEOUT) {
|
|
|
+ spin_lock(&adapter->mbox_lock);
|
|
|
+ list_del(&entry.list);
|
|
|
+ spin_unlock(&adapter->mbox_lock);
|
|
|
+ ret = -EBUSY;
|
|
|
+ t4vf_record_mbox(adapter, cmd, size, access, ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* If we're at the head, break out and start the mailbox
|
|
|
+ * protocol.
|
|
|
+ */
|
|
|
+ if (list_first_entry(&adapter->mlist.list, struct mbox_list,
|
|
|
+ list) == &entry)
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* Delay for a bit before checking again ... */
|
|
|
+ if (sleep_ok) {
|
|
|
+ ms = delay[delay_idx]; /* last element may repeat */
|
|
|
+ if (delay_idx < ARRAY_SIZE(delay) - 1)
|
|
|
+ delay_idx++;
|
|
|
+ msleep(ms);
|
|
|
+ } else {
|
|
|
+ mdelay(ms);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Loop trying to get ownership of the mailbox. Return an error
|
|
|
* if we can't gain ownership.
|
|
@@ -164,6 +210,9 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
|
|
|
for (i = 0; v == MBOX_OWNER_NONE && i < 3; i++)
|
|
|
v = MBOWNER_G(t4_read_reg(adapter, mbox_ctl));
|
|
|
if (v != MBOX_OWNER_DRV) {
|
|
|
+ spin_lock(&adapter->mbox_lock);
|
|
|
+ list_del(&entry.list);
|
|
|
+ spin_unlock(&adapter->mbox_lock);
|
|
|
ret = (v == MBOX_OWNER_FW) ? -EBUSY : -ETIMEDOUT;
|
|
|
t4vf_record_mbox(adapter, cmd, size, access, ret);
|
|
|
return ret;
|
|
@@ -248,6 +297,9 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
|
|
|
if (cmd_op != FW_VI_STATS_CMD)
|
|
|
t4vf_record_mbox(adapter, cmd_rpl, size, access,
|
|
|
execute);
|
|
|
+ spin_lock(&adapter->mbox_lock);
|
|
|
+ list_del(&entry.list);
|
|
|
+ spin_unlock(&adapter->mbox_lock);
|
|
|
return -FW_CMD_RETVAL_G(v);
|
|
|
}
|
|
|
}
|
|
@@ -255,6 +307,9 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size,
|
|
|
/* We timed out. Return the error ... */
|
|
|
ret = -ETIMEDOUT;
|
|
|
t4vf_record_mbox(adapter, cmd, size, access, ret);
|
|
|
+ spin_lock(&adapter->mbox_lock);
|
|
|
+ list_del(&entry.list);
|
|
|
+ spin_unlock(&adapter->mbox_lock);
|
|
|
return ret;
|
|
|
}
|
|
|
|