Update mailbox writes to work with VF devices.

- Use alternate register locations for the data and control registers for
  VFs.
- Do a dummy read to force the writes to the  mailbox data registers to
  post before the write to the control register on VFs.
- Do not check the PCI-e firmware register for errors on VFs.

Reviewed by:	np
Sponsored by:	Chelsio Communications
Differential Revision:	https://reviews.freebsd.org/D7483
This commit is contained in:
jhb 2016-08-15 17:41:34 +00:00
parent d1c7b4cb81
commit ac1147637e

View File

@ -289,6 +289,14 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
if ((size & 15) || size > MBOX_LEN)
return -EINVAL;
if (adap->flags & IS_VF) {
if (is_t6(adap))
data_reg = FW_T6VF_MBDATA_BASE_ADDR;
else
data_reg = FW_T4VF_MBDATA_BASE_ADDR;
ctl_reg = VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL);
}
/*
* If we have a negative timeout, that implies that we can't sleep.
*/
@ -343,6 +351,22 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
for (i = 0; i < size; i += 8, p++)
t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p));
if (adap->flags & IS_VF) {
/*
* For the VFs, the Mailbox Data "registers" are
* actually backed by T4's "MA" interface rather than
* PL Registers (as is the case for the PFs). Because
* these are in different coherency domains, the write
* to the VF's PL-register-backed Mailbox Control can
* race in front of the writes to the MA-backed VF
* Mailbox Data "registers". So we need to do a
* read-back on at least one byte of the VF Mailbox
* Data registers before doing the write to the VF
* Mailbox Control register.
*/
t4_read_reg(adap, data_reg);
}
CH_DUMP_MBOX(adap, mbox, data_reg);
t4_write_reg(adap, ctl_reg, F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW));
@ -355,10 +379,13 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
* Loop waiting for the reply; bail out if we time out or the firmware
* reports an error.
*/
for (i = 0;
!((pcie_fw = t4_read_reg(adap, A_PCIE_FW)) & F_PCIE_FW_ERR) &&
i < timeout;
i += ms) {
pcie_fw = 0;
for (i = 0; i < timeout; i += ms) {
if (!(adap->flags & IS_VF)) {
pcie_fw = t4_read_reg(adap, A_PCIE_FW);
if (pcie_fw & F_PCIE_FW_ERR)
break;
}
if (sleep_ok) {
ms = delay[delay_idx]; /* last element may repeat */
if (delay_idx < ARRAY_SIZE(delay) - 1)