summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgbe/common/t4_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/cxgbe/common/t4_hw.c')
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c148
1 files changed, 119 insertions, 29 deletions
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index 580cdc5..35dd4e2 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -286,6 +286,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.
*/
@@ -340,6 +348,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));
@@ -352,10 +376,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)
@@ -695,10 +722,14 @@ unsigned int t4_get_regs_len(struct adapter *adapter)
switch (chip_version) {
case CHELSIO_T4:
+ if (adapter->flags & IS_VF)
+ return FW_T4VF_REGMAP_SIZE;
return T4_REGMAP_SIZE;
case CHELSIO_T5:
case CHELSIO_T6:
+ if (adapter->flags & IS_VF)
+ return FW_T4VF_REGMAP_SIZE;
return T5_REGMAP_SIZE;
}
@@ -1177,6 +1208,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size)
0x27e00, 0x27e04,
};
+ static const unsigned int t4vf_reg_ranges[] = {
+ VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS),
+ VF_MPS_REG(A_MPS_VF_CTL),
+ VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H),
+ VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_WHOAMI),
+ VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL),
+ VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS),
+ FW_T4VF_MBDATA_BASE_ADDR,
+ FW_T4VF_MBDATA_BASE_ADDR +
+ ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4),
+ };
+
static const unsigned int t5_reg_ranges[] = {
0x1008, 0x10c0,
0x10cc, 0x10f8,
@@ -1952,6 +1995,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size)
0x51300, 0x51308,
};
+ static const unsigned int t5vf_reg_ranges[] = {
+ VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS),
+ VF_MPS_REG(A_MPS_VF_CTL),
+ VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H),
+ VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_REVISION),
+ VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL),
+ VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS),
+ FW_T4VF_MBDATA_BASE_ADDR,
+ FW_T4VF_MBDATA_BASE_ADDR +
+ ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4),
+ };
+
static const unsigned int t6_reg_ranges[] = {
0x1008, 0x101c,
0x1024, 0x10a8,
@@ -2529,6 +2584,18 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size)
0x51300, 0x51324,
};
+ static const unsigned int t6vf_reg_ranges[] = {
+ VF_SGE_REG(A_SGE_VF_KDOORBELL), VF_SGE_REG(A_SGE_VF_GTS),
+ VF_MPS_REG(A_MPS_VF_CTL),
+ VF_MPS_REG(A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H),
+ VF_PL_REG(A_PL_VF_WHOAMI), VF_PL_REG(A_PL_VF_REVISION),
+ VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_CTRL),
+ VF_CIM_REG(A_CIM_VF_EXT_MAILBOX_STATUS),
+ FW_T6VF_MBDATA_BASE_ADDR,
+ FW_T6VF_MBDATA_BASE_ADDR +
+ ((NUM_CIM_PF_MAILBOX_DATA_INSTANCES - 1) * 4),
+ };
+
u32 *buf_end = (u32 *)(buf + buf_size);
const unsigned int *reg_ranges;
int reg_ranges_size, range;
@@ -2540,18 +2607,33 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size)
*/
switch (chip_version) {
case CHELSIO_T4:
- reg_ranges = t4_reg_ranges;
- reg_ranges_size = ARRAY_SIZE(t4_reg_ranges);
+ if (adap->flags & IS_VF) {
+ reg_ranges = t4vf_reg_ranges;
+ reg_ranges_size = ARRAY_SIZE(t4vf_reg_ranges);
+ } else {
+ reg_ranges = t4_reg_ranges;
+ reg_ranges_size = ARRAY_SIZE(t4_reg_ranges);
+ }
break;
case CHELSIO_T5:
- reg_ranges = t5_reg_ranges;
- reg_ranges_size = ARRAY_SIZE(t5_reg_ranges);
+ if (adap->flags & IS_VF) {
+ reg_ranges = t5vf_reg_ranges;
+ reg_ranges_size = ARRAY_SIZE(t5vf_reg_ranges);
+ } else {
+ reg_ranges = t5_reg_ranges;
+ reg_ranges_size = ARRAY_SIZE(t5_reg_ranges);
+ }
break;
case CHELSIO_T6:
- reg_ranges = t6_reg_ranges;
- reg_ranges_size = ARRAY_SIZE(t6_reg_ranges);
+ if (adap->flags & IS_VF) {
+ reg_ranges = t6vf_reg_ranges;
+ reg_ranges_size = ARRAY_SIZE(t6vf_reg_ranges);
+ } else {
+ reg_ranges = t6_reg_ranges;
+ reg_ranges_size = ARRAY_SIZE(t6_reg_ranges);
+ }
break;
default:
@@ -7413,7 +7495,7 @@ static void set_pcie_completion_timeout(struct adapter *adapter,
}
}
-static const struct chip_params *get_chip_params(int chipid)
+const struct chip_params *t4_get_chip_params(int chipid)
{
static const struct chip_params chip_params[] = {
{
@@ -7492,7 +7574,7 @@ int t4_prep_adapter(struct adapter *adapter, u8 *buf)
}
}
- adapter->chip_params = get_chip_params(chip_id(adapter));
+ adapter->chip_params = t4_get_chip_params(chip_id(adapter));
if (adapter->chip_params == NULL)
return -EINVAL;
@@ -7641,6 +7723,7 @@ int t4_init_sge_params(struct adapter *adapter)
{
u32 r;
struct sge_params *sp = &adapter->params.sge;
+ unsigned i;
r = t4_read_reg(adapter, A_SGE_INGRESS_RX_THRESHOLD);
sp->counter_val[0] = G_THRESHOLD_0(r);
@@ -7683,6 +7766,7 @@ int t4_init_sge_params(struct adapter *adapter)
sp->page_shift = (r & M_HOSTPAGESIZEPF0) + 10;
r = t4_read_reg(adapter, A_SGE_CONTROL);
+ sp->sge_control = r;
sp->spg_len = r & F_EGRSTATUSPAGESIZE ? 128 : 64;
sp->fl_pktshift = G_PKTSHIFT(r);
sp->pad_boundary = 1 << (G_INGPADBOUNDARY(r) + 5);
@@ -7695,6 +7779,9 @@ int t4_init_sge_params(struct adapter *adapter)
else
sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(r) + 5);
}
+ for (i = 0; i < SGE_FLBUF_SIZES; i++)
+ sp->sge_fl_buffer_size[i] = t4_read_reg(adapter,
+ A_SGE_FL_BUFFER_SIZE0 + (4 * i));
return 0;
}
@@ -7848,15 +7935,26 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf, int port_id)
} while ((adap->params.portvec & (1 << j)) == 0);
}
- c.op_to_portid = htonl(V_FW_CMD_OP(FW_PORT_CMD) |
- F_FW_CMD_REQUEST | F_FW_CMD_READ |
- V_FW_PORT_CMD_PORTID(j));
- c.action_to_len16 = htonl(
- V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) |
- FW_LEN16(c));
- ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
- if (ret)
- return ret;
+ if (!(adap->flags & IS_VF) ||
+ adap->params.vfres.r_caps & FW_CMD_CAP_PORT) {
+ c.op_to_portid = htonl(V_FW_CMD_OP(FW_PORT_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_READ |
+ V_FW_PORT_CMD_PORTID(j));
+ c.action_to_len16 = htonl(
+ V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) |
+ FW_LEN16(c));
+ ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
+ if (ret)
+ return ret;
+
+ ret = be32_to_cpu(c.u.info.lstatus_to_modtype);
+ p->mdio_addr = (ret & F_FW_PORT_CMD_MDIOCAP) ?
+ G_FW_PORT_CMD_MDIOADDR(ret) : -1;
+ p->port_type = G_FW_PORT_CMD_PTYPE(ret);
+ p->mod_type = G_FW_PORT_CMD_MODTYPE(ret);
+
+ init_link_config(&p->link_cfg, be16_to_cpu(c.u.info.pcap));
+ }
ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size);
if (ret < 0)
@@ -7869,14 +7967,6 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf, int port_id)
p->vi[0].rss_size = rss_size;
t4_os_set_hw_addr(adap, p->port_id, addr);
- ret = be32_to_cpu(c.u.info.lstatus_to_modtype);
- p->mdio_addr = (ret & F_FW_PORT_CMD_MDIOCAP) ?
- G_FW_PORT_CMD_MDIOADDR(ret) : -1;
- p->port_type = G_FW_PORT_CMD_PTYPE(ret);
- p->mod_type = G_FW_PORT_CMD_MODTYPE(ret);
-
- init_link_config(&p->link_cfg, be16_to_cpu(c.u.info.pcap));
-
param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_RSSINFO) |
V_FW_PARAMS_PARAM_YZ(p->vi[0].viid);
OpenPOWER on IntegriCloud