1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Chelsio Communications.
6 #include <rte_ethdev_driver.h>
13 * Get the reply to a mailbox command and store it in @rpl in big-endian order.
15 static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
18 for ( ; nflit; nflit--, mbox_addr += 8)
19 *rpl++ = htobe64(t4_read_reg64(adap, mbox_addr));
23 * t4vf_wr_mbox_core - send a command to FW through the mailbox
24 * @adapter: the adapter
25 * @cmd: the command to write
26 * @size: command length in bytes
27 * @rpl: where to optionally store the reply
28 * @sleep_ok: if true we may sleep while awaiting command completion
30 * Sends the given command to FW through the mailbox and waits for the
31 * FW to execute the command. If @rpl is not %NULL it is used to store
32 * the FW's reply to the command. The command and its optional reply
33 * are of the same length. FW can take up to 500 ms to respond.
34 * @sleep_ok determines whether we may sleep while awaiting the response.
35 * If sleeping is allowed we use progressive backoff otherwise we spin.
37 * The return value is 0 on success or a negative errno on failure. A
38 * failure can happen either because we are not able to execute the
39 * command or FW executes it but signals an error. In the latter case
40 * the return value is the error code indicated by FW (negated).
42 int t4vf_wr_mbox_core(struct adapter *adapter,
43 const void __attribute__((__may_alias__)) *cmd,
44 int size, void *rpl, bool sleep_ok)
47 * We delay in small increments at first in an effort to maintain
48 * responsiveness for simple, fast executing commands but then back
49 * off to larger delays to a maximum retry delay.
51 static const int delay[] = {
52 1, 1, 3, 5, 10, 10, 20, 50, 100
56 u32 mbox_ctl = T4VF_CIM_BASE_ADDR + A_CIM_VF_EXT_MAILBOX_CTRL;
57 __be64 cmd_rpl[MBOX_LEN / 8];
58 struct mbox_entry entry;
59 unsigned int delay_idx;
65 /* In T6, mailbox size is changed to 128 bytes to avoid
66 * invalidating the entire prefetch buffer.
68 if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5)
69 mbox_data = T4VF_MBDATA_BASE_ADDR;
71 mbox_data = T6VF_MBDATA_BASE_ADDR;
74 * Commands must be multiples of 16 bytes in length and may not be
75 * larger than the size of the Mailbox Data register array.
77 if ((size % 16) != 0 ||
78 size > NUM_CIM_VF_MAILBOX_DATA_INSTANCES * 4)
82 * Queue ourselves onto the mailbox access list. When our entry is at
83 * the front of the list, we have rights to access the mailbox. So we
84 * wait [for a while] till we're at the front [or bail out with an
87 t4_os_atomic_add_tail(&entry, &adapter->mbox_list, &adapter->mbox_lock);
92 for (i = 0; ; i += ms) {
94 * If we've waited too long, return a busy indication. This
95 * really ought to be based on our initial position in the
96 * mailbox access list but this is a start. We very rarely
97 * contend on access to the mailbox ...
99 if (i > (2 * FW_CMD_MAX_TIMEOUT)) {
100 t4_os_atomic_list_del(&entry, &adapter->mbox_list,
101 &adapter->mbox_lock);
107 * If we're at the head, break out and start the mailbox
110 if (t4_os_list_first_entry(&adapter->mbox_list) == &entry)
114 * Delay for a bit before checking again ...
117 ms = delay[delay_idx]; /* last element may repeat */
118 if (delay_idx < ARRAY_SIZE(delay) - 1)
127 * Loop trying to get ownership of the mailbox. Return an error
128 * if we can't gain ownership.
130 v = G_MBOWNER(t4_read_reg(adapter, mbox_ctl));
131 for (i = 0; v == X_MBOWNER_NONE && i < 3; i++)
132 v = G_MBOWNER(t4_read_reg(adapter, mbox_ctl));
134 if (v != X_MBOWNER_PL) {
135 t4_os_atomic_list_del(&entry, &adapter->mbox_list,
136 &adapter->mbox_lock);
137 ret = (v == X_MBOWNER_FW) ? -EBUSY : -ETIMEDOUT;
142 * Write the command array into the Mailbox Data register array and
143 * transfer ownership of the mailbox to the firmware.
145 for (i = 0, p = cmd; i < size; i += 8)
146 t4_write_reg64(adapter, mbox_data + i, be64_to_cpu(*p++));
148 t4_read_reg(adapter, mbox_data); /* flush write */
149 t4_write_reg(adapter, mbox_ctl,
150 F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW));
151 t4_read_reg(adapter, mbox_ctl); /* flush write */
156 * Spin waiting for firmware to acknowledge processing our command.
158 for (i = 0; i < FW_CMD_MAX_TIMEOUT; i++) {
160 ms = delay[delay_idx]; /* last element may repeat */
161 if (delay_idx < ARRAY_SIZE(delay) - 1)
169 * If we're the owner, see if this is the reply we wanted.
171 v = t4_read_reg(adapter, mbox_ctl);
172 if (G_MBOWNER(v) == X_MBOWNER_PL) {
174 * If the Message Valid bit isn't on, revoke ownership
175 * of the mailbox and continue waiting for our reply.
177 if ((v & F_MBMSGVALID) == 0) {
178 t4_write_reg(adapter, mbox_ctl,
179 V_MBOWNER(X_MBOWNER_NONE));
184 * We now have our reply. Extract the command return
185 * value, copy the reply back to our caller's buffer
186 * (if specified) and revoke ownership of the mailbox.
187 * We return the (negated) firmware command return
188 * code (this depends on FW_SUCCESS == 0). (Again we
189 * avoid clogging the log with FW_VI_STATS_CMD
194 * Retrieve the command reply and release the mailbox.
196 get_mbox_rpl(adapter, cmd_rpl, size / 8, mbox_data);
197 t4_write_reg(adapter, mbox_ctl,
198 V_MBOWNER(X_MBOWNER_NONE));
199 t4_os_atomic_list_del(&entry, &adapter->mbox_list,
200 &adapter->mbox_lock);
202 /* return value in high-order host-endian word */
203 v = be64_to_cpu(cmd_rpl[0]);
206 /* request bit in high-order BE word */
207 WARN_ON((be32_to_cpu(*(const u32 *)cmd)
208 & F_FW_CMD_REQUEST) == 0);
209 memcpy(rpl, cmd_rpl, size);
211 return -((int)G_FW_CMD_RETVAL(v));
216 * We timed out. Return the error ...
218 dev_err(adapter, "command %#x timed out\n",
220 dev_err(adapter, " Control = %#x\n", t4_read_reg(adapter, mbox_ctl));
221 t4_os_atomic_list_del(&entry, &adapter->mbox_list, &adapter->mbox_lock);