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.c6623
1 files changed, 4990 insertions, 1633 deletions
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index 31e8668..a618297 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2012 Chelsio Communications, Inc.
+ * Copyright (c) 2012, 2016 Chelsio Communications, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,8 +57,8 @@ __FBSDID("$FreeBSD$");
* at the time it indicated completion is stored there. Returns 0 if the
* operation completes and -EAGAIN otherwise.
*/
-int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
- int polarity, int attempts, int delay, u32 *valp)
+static int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
+ int polarity, int attempts, int delay, u32 *valp)
{
while (1) {
u32 val = t4_read_reg(adapter, reg);
@@ -75,6 +75,13 @@ int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
}
}
+static inline int t4_wait_op_done(struct adapter *adapter, int reg, u32 mask,
+ int polarity, int attempts, int delay)
+{
+ return t4_wait_op_done_val(adapter, reg, mask, polarity, attempts,
+ delay, NULL);
+}
+
/**
* t4_set_reg_field - set a register field to a value
* @adapter: the adapter to program
@@ -107,8 +114,8 @@ void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask,
* register pair.
*/
void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
- unsigned int data_reg, u32 *vals, unsigned int nregs,
- unsigned int start_idx)
+ unsigned int data_reg, u32 *vals,
+ unsigned int nregs, unsigned int start_idx)
{
while (nregs--) {
t4_write_reg(adap, addr_reg, start_idx);
@@ -144,26 +151,49 @@ void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
* mechanism. This guarantees that we get the real value even if we're
* operating within a Virtual Machine and the Hypervisor is trapping our
* Configuration Space accesses.
+ *
+ * N.B. This routine should only be used as a last resort: the firmware uses
+ * the backdoor registers on a regular basis and we can end up
+ * conflicting with it's uses!
*/
u32 t4_hw_pci_read_cfg4(adapter_t *adap, int reg)
{
- t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ,
- F_ENABLE | F_LOCALCFG | V_FUNCTION(adap->pf) |
- V_REGISTER(reg));
- return t4_read_reg(adap, A_PCIE_CFG_SPACE_DATA);
+ u32 req = V_FUNCTION(adap->pf) | V_REGISTER(reg);
+ u32 val;
+
+ if (chip_id(adap) <= CHELSIO_T5)
+ req |= F_ENABLE;
+ else
+ req |= F_T6_ENABLE;
+
+ if (is_t4(adap))
+ req |= F_LOCALCFG;
+
+ t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ, req);
+ val = t4_read_reg(adap, A_PCIE_CFG_SPACE_DATA);
+
+ /*
+ * Reset F_ENABLE to 0 so reads of PCIE_CFG_SPACE_DATA won't cause a
+ * Configuration Space read. (None of the other fields matter when
+ * F_ENABLE is 0 so a simple register write is easier than a
+ * read-modify-write via t4_set_reg_field().)
+ */
+ t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ, 0);
+
+ return val;
}
/*
- * t4_report_fw_error - report firmware error
- * @adap: the adapter
+ * t4_report_fw_error - report firmware error
+ * @adap: the adapter
*
- * The adapter firmware can indicate error conditions to the host.
- * This routine prints out the reason for the firmware error (as
- * reported by the firmware).
+ * The adapter firmware can indicate error conditions to the host.
+ * If the firmware has indicated an error, print out the reason for
+ * the firmware error.
*/
static void t4_report_fw_error(struct adapter *adap)
{
- static const char *reason[] = {
+ static const char *const reason[] = {
"Crash", /* PCIE_FW_EVAL_CRASH */
"During Device Preparation", /* PCIE_FW_EVAL_PREP */
"During Device Configuration", /* PCIE_FW_EVAL_CONF */
@@ -178,7 +208,7 @@ static void t4_report_fw_error(struct adapter *adap)
pcie_fw = t4_read_reg(adap, A_PCIE_FW);
if (pcie_fw & F_PCIE_FW_ERR)
CH_ERR(adap, "Firmware reports adapter error: %s\n",
- reason[G_PCIE_FW_EVAL(pcie_fw)]);
+ reason[G_PCIE_FW_EVAL(pcie_fw)]);
}
/*
@@ -194,25 +224,27 @@ static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
/*
* Handle a FW assertion reported in a mailbox.
*/
-static void fw_asrt(struct adapter *adap, u32 mbox_addr)
+static void fw_asrt(struct adapter *adap, struct fw_debug_cmd *asrt)
{
- struct fw_debug_cmd asrt;
-
- get_mbox_rpl(adap, (__be64 *)&asrt, sizeof(asrt) / 8, mbox_addr);
- CH_ALERT(adap, "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n",
- asrt.u.assert.filename_0_7, ntohl(asrt.u.assert.line),
- ntohl(asrt.u.assert.x), ntohl(asrt.u.assert.y));
+ CH_ALERT(adap,
+ "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n",
+ asrt->u.assert.filename_0_7,
+ be32_to_cpu(asrt->u.assert.line),
+ be32_to_cpu(asrt->u.assert.x),
+ be32_to_cpu(asrt->u.assert.y));
}
#define X_CIM_PF_NOACCESS 0xeeeeeeee
/**
- * t4_wr_mbox_meat - send a command to FW through the given mailbox
+ * t4_wr_mbox_meat_timeout - send a command to FW through the given mailbox
* @adap: the adapter
* @mbox: index of the mailbox to use
* @cmd: the command to write
* @size: command length in bytes
* @rpl: where to optionally store the reply
* @sleep_ok: if true we may sleep while awaiting command completion
+ * @timeout: time to wait for command to finish before timing out
+ * (negative implies @sleep_ok=false)
*
* Sends the given command to FW through the selected mailbox and waits
* for the FW to execute the command. If @rpl is not %NULL it is used to
@@ -221,14 +253,17 @@ static void fw_asrt(struct adapter *adap, u32 mbox_addr)
* INITIALIZE can take a considerable amount of time to execute.
* @sleep_ok determines whether we may sleep while awaiting the response.
* If sleeping is allowed we use progressive backoff otherwise we spin.
+ * Note that passing in a negative @timeout is an alternate mechanism
+ * for specifying @sleep_ok=false. This is useful when a higher level
+ * interface allows for specification of @timeout but not @sleep_ok ...
*
* The return value is 0 on success or a negative errno on failure. A
* failure can happen either because we are not able to execute the
* command or FW executes it but signals an error. In the latter case
* the return value is the error code indicated by FW (negated).
*/
-int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
- void *rpl, bool sleep_ok)
+int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
+ int size, void *rpl, bool sleep_ok, int timeout)
{
/*
* We delay in small increments at first in an effort to maintain
@@ -238,43 +273,97 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
static const int delay[] = {
1, 1, 3, 5, 10, 10, 20, 50, 100
};
-
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, A_CIM_PF_MAILBOX_DATA);
u32 ctl_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_CTRL);
+ u32 ctl;
+ __be64 cmd_rpl[MBOX_LEN/8];
+ u32 pcie_fw;
if ((size & 15) || size > MBOX_LEN)
return -EINVAL;
- v = G_MBOWNER(t4_read_reg(adap, ctl_reg));
- for (i = 0; v == X_MBOWNER_NONE && i < 3; i++)
- v = G_MBOWNER(t4_read_reg(adap, ctl_reg));
+ /*
+ * If we have a negative timeout, that implies that we can't sleep.
+ */
+ if (timeout < 0) {
+ sleep_ok = false;
+ timeout = -timeout;
+ }
+
+ /*
+ * Attempt to gain access to the mailbox.
+ */
+ for (i = 0; i < 4; i++) {
+ ctl = t4_read_reg(adap, ctl_reg);
+ v = G_MBOWNER(ctl);
+ if (v != X_MBOWNER_NONE)
+ break;
+ }
+
+ /*
+ * If we were unable to gain access, dequeue ourselves from the
+ * mailbox atomic access list and report the error to our caller.
+ */
+ if (v != X_MBOWNER_PL) {
+ t4_report_fw_error(adap);
+ ret = (v == X_MBOWNER_FW) ? -EBUSY : -ETIMEDOUT;
+ return ret;
+ }
- if (v != X_MBOWNER_PL)
- return v ? -EBUSY : -ETIMEDOUT;
+ /*
+ * If we gain ownership of the mailbox and there's a "valid" message
+ * in it, this is likely an asynchronous error message from the
+ * firmware. So we'll report that and then proceed on with attempting
+ * to issue our own command ... which may well fail if the error
+ * presaged the firmware crashing ...
+ */
+ if (ctl & F_MBMSGVALID) {
+ CH_ERR(adap, "found VALID command in mbox %u: "
+ "%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));
+ }
+ /*
+ * Copy in the new mailbox command and send it on its way ...
+ */
for (i = 0; i < size; i += 8, p++)
t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p));
CH_DUMP_MBOX(adap, mbox, data_reg);
t4_write_reg(adap, ctl_reg, F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW));
- t4_read_reg(adap, ctl_reg); /* flush write */
+ t4_read_reg(adap, ctl_reg); /* flush write */
delay_idx = 0;
ms = delay[0];
- for (i = 0; i < FW_CMD_MAX_TIMEOUT; i += ms) {
+ /*
+ * 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) {
if (sleep_ok) {
ms = delay[delay_idx]; /* last element may repeat */
if (delay_idx < ARRAY_SIZE(delay) - 1)
delay_idx++;
msleep(ms);
- } else
+ } else {
mdelay(ms);
+ }
v = t4_read_reg(adap, ctl_reg);
if (v == X_CIM_PF_NOACCESS)
@@ -286,15 +375,20 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
continue;
}
+ /*
+ * Retrieve the command reply and release the mailbox.
+ */
+ get_mbox_rpl(adap, cmd_rpl, size/8, data_reg);
+ t4_write_reg(adap, ctl_reg, V_MBOWNER(X_MBOWNER_NONE));
+
CH_DUMP_MBOX(adap, mbox, data_reg);
- res = t4_read_reg64(adap, data_reg);
+ res = be64_to_cpu(cmd_rpl[0]);
if (G_FW_CMD_OP(res >> 32) == FW_DEBUG_CMD) {
- fw_asrt(adap, data_reg);
+ fw_asrt(adap, (struct fw_debug_cmd *)cmd_rpl);
res = V_FW_CMD_RETVAL(EIO);
} else if (rpl)
- get_mbox_rpl(adap, rpl, size / 8, data_reg);
- t4_write_reg(adap, ctl_reg, V_MBOWNER(X_MBOWNER_NONE));
+ memcpy(rpl, cmd_rpl, size);
return -G_FW_CMD_RETVAL((int)res);
}
}
@@ -304,11 +398,58 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
* the error and also check to see if the firmware reported any
* errors ...
*/
+ ret = (pcie_fw & F_PCIE_FW_ERR) ? -ENXIO : -ETIMEDOUT;
CH_ERR(adap, "command %#x in mailbox %d timed out\n",
*(const u8 *)cmd, mbox);
- if (t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_ERR)
- t4_report_fw_error(adap);
- return -ETIMEDOUT;
+
+ t4_report_fw_error(adap);
+ t4_fatal_err(adap);
+ return ret;
+}
+
+int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
+ void *rpl, bool sleep_ok)
+{
+ return t4_wr_mbox_meat_timeout(adap, mbox, cmd, size, rpl,
+ sleep_ok, FW_CMD_MAX_TIMEOUT);
+
+}
+
+static int t4_edc_err_read(struct adapter *adap, int idx)
+{
+ u32 edc_ecc_err_addr_reg;
+ u32 edc_bist_status_rdata_reg;
+
+ if (is_t4(adap)) {
+ CH_WARN(adap, "%s: T4 NOT supported.\n", __func__);
+ return 0;
+ }
+ if (idx != 0 && idx != 1) {
+ CH_WARN(adap, "%s: idx %d NOT supported.\n", __func__, idx);
+ return 0;
+ }
+
+ edc_ecc_err_addr_reg = EDC_T5_REG(A_EDC_H_ECC_ERR_ADDR, idx);
+ edc_bist_status_rdata_reg = EDC_T5_REG(A_EDC_H_BIST_STATUS_RDATA, idx);
+
+ CH_WARN(adap,
+ "edc%d err addr 0x%x: 0x%x.\n",
+ idx, edc_ecc_err_addr_reg,
+ t4_read_reg(adap, edc_ecc_err_addr_reg));
+ CH_WARN(adap,
+ "bist: 0x%x, status %llx %llx %llx %llx %llx %llx %llx %llx %llx.\n",
+ edc_bist_status_rdata_reg,
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg),
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 8),
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 16),
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 24),
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 32),
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 40),
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 48),
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 56),
+ (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 64));
+
+ return 0;
}
/**
@@ -493,8 +634,1956 @@ int t4_mem_read(struct adapter *adap, int mtype, u32 addr, u32 len,
}
/*
+ * Return the specified PCI-E Configuration Space register from our Physical
+ * Function. We try first via a Firmware LDST Command (if fw_attach != 0)
+ * since we prefer to let the firmware own all of these registers, but if that
+ * fails we go for it directly ourselves.
+ */
+u32 t4_read_pcie_cfg4(struct adapter *adap, int reg, int drv_fw_attach)
+{
+
+ /*
+ * If fw_attach != 0, construct and send the Firmware LDST Command to
+ * retrieve the specified PCI-E Configuration Space register.
+ */
+ if (drv_fw_attach != 0) {
+ struct fw_ldst_cmd ldst_cmd;
+ int ret;
+
+ memset(&ldst_cmd, 0, sizeof(ldst_cmd));
+ ldst_cmd.op_to_addrspace =
+ cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_READ |
+ V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
+ ldst_cmd.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst_cmd));
+ ldst_cmd.u.pcie.select_naccess = V_FW_LDST_CMD_NACCESS(1);
+ ldst_cmd.u.pcie.ctrl_to_fn =
+ (F_FW_LDST_CMD_LC | V_FW_LDST_CMD_FN(adap->pf));
+ ldst_cmd.u.pcie.r = reg;
+
+ /*
+ * If the LDST Command succeeds, return the result, otherwise
+ * fall through to reading it directly ourselves ...
+ */
+ ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd, sizeof(ldst_cmd),
+ &ldst_cmd);
+ if (ret == 0)
+ return be32_to_cpu(ldst_cmd.u.pcie.data[0]);
+
+ CH_WARN(adap, "Firmware failed to return "
+ "Configuration Space register %d, err = %d\n",
+ reg, -ret);
+ }
+
+ /*
+ * Read the desired Configuration Space register via the PCI-E
+ * Backdoor mechanism.
+ */
+ return t4_hw_pci_read_cfg4(adap, reg);
+}
+
+/**
+ * t4_get_regs_len - return the size of the chips register set
+ * @adapter: the adapter
+ *
+ * Returns the size of the chip's BAR0 register space.
+ */
+unsigned int t4_get_regs_len(struct adapter *adapter)
+{
+ unsigned int chip_version = chip_id(adapter);
+
+ switch (chip_version) {
+ case CHELSIO_T4:
+ return T4_REGMAP_SIZE;
+
+ case CHELSIO_T5:
+ case CHELSIO_T6:
+ return T5_REGMAP_SIZE;
+ }
+
+ CH_ERR(adapter,
+ "Unsupported chip version %d\n", chip_version);
+ return 0;
+}
+
+/**
+ * t4_get_regs - read chip registers into provided buffer
+ * @adap: the adapter
+ * @buf: register buffer
+ * @buf_size: size (in bytes) of register buffer
+ *
+ * If the provided register buffer isn't large enough for the chip's
+ * full register range, the register dump will be truncated to the
+ * register buffer's size.
+ */
+void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size)
+{
+ static const unsigned int t4_reg_ranges[] = {
+ 0x1008, 0x1108,
+ 0x1180, 0x1184,
+ 0x1190, 0x1194,
+ 0x11a0, 0x11a4,
+ 0x11b0, 0x11b4,
+ 0x11fc, 0x123c,
+ 0x1300, 0x173c,
+ 0x1800, 0x18fc,
+ 0x3000, 0x30d8,
+ 0x30e0, 0x30e4,
+ 0x30ec, 0x5910,
+ 0x5920, 0x5924,
+ 0x5960, 0x5960,
+ 0x5968, 0x5968,
+ 0x5970, 0x5970,
+ 0x5978, 0x5978,
+ 0x5980, 0x5980,
+ 0x5988, 0x5988,
+ 0x5990, 0x5990,
+ 0x5998, 0x5998,
+ 0x59a0, 0x59d4,
+ 0x5a00, 0x5ae0,
+ 0x5ae8, 0x5ae8,
+ 0x5af0, 0x5af0,
+ 0x5af8, 0x5af8,
+ 0x6000, 0x6098,
+ 0x6100, 0x6150,
+ 0x6200, 0x6208,
+ 0x6240, 0x6248,
+ 0x6280, 0x62b0,
+ 0x62c0, 0x6338,
+ 0x6370, 0x638c,
+ 0x6400, 0x643c,
+ 0x6500, 0x6524,
+ 0x6a00, 0x6a04,
+ 0x6a14, 0x6a38,
+ 0x6a60, 0x6a70,
+ 0x6a78, 0x6a78,
+ 0x6b00, 0x6b0c,
+ 0x6b1c, 0x6b84,
+ 0x6bf0, 0x6bf8,
+ 0x6c00, 0x6c0c,
+ 0x6c1c, 0x6c84,
+ 0x6cf0, 0x6cf8,
+ 0x6d00, 0x6d0c,
+ 0x6d1c, 0x6d84,
+ 0x6df0, 0x6df8,
+ 0x6e00, 0x6e0c,
+ 0x6e1c, 0x6e84,
+ 0x6ef0, 0x6ef8,
+ 0x6f00, 0x6f0c,
+ 0x6f1c, 0x6f84,
+ 0x6ff0, 0x6ff8,
+ 0x7000, 0x700c,
+ 0x701c, 0x7084,
+ 0x70f0, 0x70f8,
+ 0x7100, 0x710c,
+ 0x711c, 0x7184,
+ 0x71f0, 0x71f8,
+ 0x7200, 0x720c,
+ 0x721c, 0x7284,
+ 0x72f0, 0x72f8,
+ 0x7300, 0x730c,
+ 0x731c, 0x7384,
+ 0x73f0, 0x73f8,
+ 0x7400, 0x7450,
+ 0x7500, 0x7530,
+ 0x7600, 0x760c,
+ 0x7614, 0x761c,
+ 0x7680, 0x76cc,
+ 0x7700, 0x7798,
+ 0x77c0, 0x77fc,
+ 0x7900, 0x79fc,
+ 0x7b00, 0x7b58,
+ 0x7b60, 0x7b84,
+ 0x7b8c, 0x7c38,
+ 0x7d00, 0x7d38,
+ 0x7d40, 0x7d80,
+ 0x7d8c, 0x7ddc,
+ 0x7de4, 0x7e04,
+ 0x7e10, 0x7e1c,
+ 0x7e24, 0x7e38,
+ 0x7e40, 0x7e44,
+ 0x7e4c, 0x7e78,
+ 0x7e80, 0x7ea4,
+ 0x7eac, 0x7edc,
+ 0x7ee8, 0x7efc,
+ 0x8dc0, 0x8e04,
+ 0x8e10, 0x8e1c,
+ 0x8e30, 0x8e78,
+ 0x8ea0, 0x8eb8,
+ 0x8ec0, 0x8f6c,
+ 0x8fc0, 0x9008,
+ 0x9010, 0x9058,
+ 0x9060, 0x9060,
+ 0x9068, 0x9074,
+ 0x90fc, 0x90fc,
+ 0x9400, 0x9408,
+ 0x9410, 0x9458,
+ 0x9600, 0x9600,
+ 0x9608, 0x9638,
+ 0x9640, 0x96bc,
+ 0x9800, 0x9808,
+ 0x9820, 0x983c,
+ 0x9850, 0x9864,
+ 0x9c00, 0x9c6c,
+ 0x9c80, 0x9cec,
+ 0x9d00, 0x9d6c,
+ 0x9d80, 0x9dec,
+ 0x9e00, 0x9e6c,
+ 0x9e80, 0x9eec,
+ 0x9f00, 0x9f6c,
+ 0x9f80, 0x9fec,
+ 0xd004, 0xd004,
+ 0xd010, 0xd03c,
+ 0xdfc0, 0xdfe0,
+ 0xe000, 0xea7c,
+ 0xf000, 0x11190,
+ 0x19040, 0x1906c,
+ 0x19078, 0x19080,
+ 0x1908c, 0x190e4,
+ 0x190f0, 0x190f8,
+ 0x19100, 0x19110,
+ 0x19120, 0x19124,
+ 0x19150, 0x19194,
+ 0x1919c, 0x191b0,
+ 0x191d0, 0x191e8,
+ 0x19238, 0x1924c,
+ 0x193f8, 0x1943c,
+ 0x1944c, 0x19474,
+ 0x19490, 0x194e0,
+ 0x194f0, 0x194f8,
+ 0x19800, 0x19c08,
+ 0x19c10, 0x19c90,
+ 0x19ca0, 0x19ce4,
+ 0x19cf0, 0x19d40,
+ 0x19d50, 0x19d94,
+ 0x19da0, 0x19de8,
+ 0x19df0, 0x19e40,
+ 0x19e50, 0x19e90,
+ 0x19ea0, 0x19f4c,
+ 0x1a000, 0x1a004,
+ 0x1a010, 0x1a06c,
+ 0x1a0b0, 0x1a0e4,
+ 0x1a0ec, 0x1a0f4,
+ 0x1a100, 0x1a108,
+ 0x1a114, 0x1a120,
+ 0x1a128, 0x1a130,
+ 0x1a138, 0x1a138,
+ 0x1a190, 0x1a1c4,
+ 0x1a1fc, 0x1a1fc,
+ 0x1e040, 0x1e04c,
+ 0x1e284, 0x1e28c,
+ 0x1e2c0, 0x1e2c0,
+ 0x1e2e0, 0x1e2e0,
+ 0x1e300, 0x1e384,
+ 0x1e3c0, 0x1e3c8,
+ 0x1e440, 0x1e44c,
+ 0x1e684, 0x1e68c,
+ 0x1e6c0, 0x1e6c0,
+ 0x1e6e0, 0x1e6e0,
+ 0x1e700, 0x1e784,
+ 0x1e7c0, 0x1e7c8,
+ 0x1e840, 0x1e84c,
+ 0x1ea84, 0x1ea8c,
+ 0x1eac0, 0x1eac0,
+ 0x1eae0, 0x1eae0,
+ 0x1eb00, 0x1eb84,
+ 0x1ebc0, 0x1ebc8,
+ 0x1ec40, 0x1ec4c,
+ 0x1ee84, 0x1ee8c,
+ 0x1eec0, 0x1eec0,
+ 0x1eee0, 0x1eee0,
+ 0x1ef00, 0x1ef84,
+ 0x1efc0, 0x1efc8,
+ 0x1f040, 0x1f04c,
+ 0x1f284, 0x1f28c,
+ 0x1f2c0, 0x1f2c0,
+ 0x1f2e0, 0x1f2e0,
+ 0x1f300, 0x1f384,
+ 0x1f3c0, 0x1f3c8,
+ 0x1f440, 0x1f44c,
+ 0x1f684, 0x1f68c,
+ 0x1f6c0, 0x1f6c0,
+ 0x1f6e0, 0x1f6e0,
+ 0x1f700, 0x1f784,
+ 0x1f7c0, 0x1f7c8,
+ 0x1f840, 0x1f84c,
+ 0x1fa84, 0x1fa8c,
+ 0x1fac0, 0x1fac0,
+ 0x1fae0, 0x1fae0,
+ 0x1fb00, 0x1fb84,
+ 0x1fbc0, 0x1fbc8,
+ 0x1fc40, 0x1fc4c,
+ 0x1fe84, 0x1fe8c,
+ 0x1fec0, 0x1fec0,
+ 0x1fee0, 0x1fee0,
+ 0x1ff00, 0x1ff84,
+ 0x1ffc0, 0x1ffc8,
+ 0x20000, 0x2002c,
+ 0x20100, 0x2013c,
+ 0x20190, 0x201a0,
+ 0x201a8, 0x201b8,
+ 0x201c4, 0x201c8,
+ 0x20200, 0x20318,
+ 0x20400, 0x204b4,
+ 0x204c0, 0x20528,
+ 0x20540, 0x20614,
+ 0x21000, 0x21040,
+ 0x2104c, 0x21060,
+ 0x210c0, 0x210ec,
+ 0x21200, 0x21268,
+ 0x21270, 0x21284,
+ 0x212fc, 0x21388,
+ 0x21400, 0x21404,
+ 0x21500, 0x21500,
+ 0x21510, 0x21518,
+ 0x2152c, 0x21530,
+ 0x2153c, 0x2153c,
+ 0x21550, 0x21554,
+ 0x21600, 0x21600,
+ 0x21608, 0x2161c,
+ 0x21624, 0x21628,
+ 0x21630, 0x21634,
+ 0x2163c, 0x2163c,
+ 0x21700, 0x2171c,
+ 0x21780, 0x2178c,
+ 0x21800, 0x21818,
+ 0x21820, 0x21828,
+ 0x21830, 0x21848,
+ 0x21850, 0x21854,
+ 0x21860, 0x21868,
+ 0x21870, 0x21870,
+ 0x21878, 0x21898,
+ 0x218a0, 0x218a8,
+ 0x218b0, 0x218c8,
+ 0x218d0, 0x218d4,
+ 0x218e0, 0x218e8,
+ 0x218f0, 0x218f0,
+ 0x218f8, 0x21a18,
+ 0x21a20, 0x21a28,
+ 0x21a30, 0x21a48,
+ 0x21a50, 0x21a54,
+ 0x21a60, 0x21a68,
+ 0x21a70, 0x21a70,
+ 0x21a78, 0x21a98,
+ 0x21aa0, 0x21aa8,
+ 0x21ab0, 0x21ac8,
+ 0x21ad0, 0x21ad4,
+ 0x21ae0, 0x21ae8,
+ 0x21af0, 0x21af0,
+ 0x21af8, 0x21c18,
+ 0x21c20, 0x21c20,
+ 0x21c28, 0x21c30,
+ 0x21c38, 0x21c38,
+ 0x21c80, 0x21c98,
+ 0x21ca0, 0x21ca8,
+ 0x21cb0, 0x21cc8,
+ 0x21cd0, 0x21cd4,
+ 0x21ce0, 0x21ce8,
+ 0x21cf0, 0x21cf0,
+ 0x21cf8, 0x21d7c,
+ 0x21e00, 0x21e04,
+ 0x22000, 0x2202c,
+ 0x22100, 0x2213c,
+ 0x22190, 0x221a0,
+ 0x221a8, 0x221b8,
+ 0x221c4, 0x221c8,
+ 0x22200, 0x22318,
+ 0x22400, 0x224b4,
+ 0x224c0, 0x22528,
+ 0x22540, 0x22614,
+ 0x23000, 0x23040,
+ 0x2304c, 0x23060,
+ 0x230c0, 0x230ec,
+ 0x23200, 0x23268,
+ 0x23270, 0x23284,
+ 0x232fc, 0x23388,
+ 0x23400, 0x23404,
+ 0x23500, 0x23500,
+ 0x23510, 0x23518,
+ 0x2352c, 0x23530,
+ 0x2353c, 0x2353c,
+ 0x23550, 0x23554,
+ 0x23600, 0x23600,
+ 0x23608, 0x2361c,
+ 0x23624, 0x23628,
+ 0x23630, 0x23634,
+ 0x2363c, 0x2363c,
+ 0x23700, 0x2371c,
+ 0x23780, 0x2378c,
+ 0x23800, 0x23818,
+ 0x23820, 0x23828,
+ 0x23830, 0x23848,
+ 0x23850, 0x23854,
+ 0x23860, 0x23868,
+ 0x23870, 0x23870,
+ 0x23878, 0x23898,
+ 0x238a0, 0x238a8,
+ 0x238b0, 0x238c8,
+ 0x238d0, 0x238d4,
+ 0x238e0, 0x238e8,
+ 0x238f0, 0x238f0,
+ 0x238f8, 0x23a18,
+ 0x23a20, 0x23a28,
+ 0x23a30, 0x23a48,
+ 0x23a50, 0x23a54,
+ 0x23a60, 0x23a68,
+ 0x23a70, 0x23a70,
+ 0x23a78, 0x23a98,
+ 0x23aa0, 0x23aa8,
+ 0x23ab0, 0x23ac8,
+ 0x23ad0, 0x23ad4,
+ 0x23ae0, 0x23ae8,
+ 0x23af0, 0x23af0,
+ 0x23af8, 0x23c18,
+ 0x23c20, 0x23c20,
+ 0x23c28, 0x23c30,
+ 0x23c38, 0x23c38,
+ 0x23c80, 0x23c98,
+ 0x23ca0, 0x23ca8,
+ 0x23cb0, 0x23cc8,
+ 0x23cd0, 0x23cd4,
+ 0x23ce0, 0x23ce8,
+ 0x23cf0, 0x23cf0,
+ 0x23cf8, 0x23d7c,
+ 0x23e00, 0x23e04,
+ 0x24000, 0x2402c,
+ 0x24100, 0x2413c,
+ 0x24190, 0x241a0,
+ 0x241a8, 0x241b8,
+ 0x241c4, 0x241c8,
+ 0x24200, 0x24318,
+ 0x24400, 0x244b4,
+ 0x244c0, 0x24528,
+ 0x24540, 0x24614,
+ 0x25000, 0x25040,
+ 0x2504c, 0x25060,
+ 0x250c0, 0x250ec,
+ 0x25200, 0x25268,
+ 0x25270, 0x25284,
+ 0x252fc, 0x25388,
+ 0x25400, 0x25404,
+ 0x25500, 0x25500,
+ 0x25510, 0x25518,
+ 0x2552c, 0x25530,
+ 0x2553c, 0x2553c,
+ 0x25550, 0x25554,
+ 0x25600, 0x25600,
+ 0x25608, 0x2561c,
+ 0x25624, 0x25628,
+ 0x25630, 0x25634,
+ 0x2563c, 0x2563c,
+ 0x25700, 0x2571c,
+ 0x25780, 0x2578c,
+ 0x25800, 0x25818,
+ 0x25820, 0x25828,
+ 0x25830, 0x25848,
+ 0x25850, 0x25854,
+ 0x25860, 0x25868,
+ 0x25870, 0x25870,
+ 0x25878, 0x25898,
+ 0x258a0, 0x258a8,
+ 0x258b0, 0x258c8,
+ 0x258d0, 0x258d4,
+ 0x258e0, 0x258e8,
+ 0x258f0, 0x258f0,
+ 0x258f8, 0x25a18,
+ 0x25a20, 0x25a28,
+ 0x25a30, 0x25a48,
+ 0x25a50, 0x25a54,
+ 0x25a60, 0x25a68,
+ 0x25a70, 0x25a70,
+ 0x25a78, 0x25a98,
+ 0x25aa0, 0x25aa8,
+ 0x25ab0, 0x25ac8,
+ 0x25ad0, 0x25ad4,
+ 0x25ae0, 0x25ae8,
+ 0x25af0, 0x25af0,
+ 0x25af8, 0x25c18,
+ 0x25c20, 0x25c20,
+ 0x25c28, 0x25c30,
+ 0x25c38, 0x25c38,
+ 0x25c80, 0x25c98,
+ 0x25ca0, 0x25ca8,
+ 0x25cb0, 0x25cc8,
+ 0x25cd0, 0x25cd4,
+ 0x25ce0, 0x25ce8,
+ 0x25cf0, 0x25cf0,
+ 0x25cf8, 0x25d7c,
+ 0x25e00, 0x25e04,
+ 0x26000, 0x2602c,
+ 0x26100, 0x2613c,
+ 0x26190, 0x261a0,
+ 0x261a8, 0x261b8,
+ 0x261c4, 0x261c8,
+ 0x26200, 0x26318,
+ 0x26400, 0x264b4,
+ 0x264c0, 0x26528,
+ 0x26540, 0x26614,
+ 0x27000, 0x27040,
+ 0x2704c, 0x27060,
+ 0x270c0, 0x270ec,
+ 0x27200, 0x27268,
+ 0x27270, 0x27284,
+ 0x272fc, 0x27388,
+ 0x27400, 0x27404,
+ 0x27500, 0x27500,
+ 0x27510, 0x27518,
+ 0x2752c, 0x27530,
+ 0x2753c, 0x2753c,
+ 0x27550, 0x27554,
+ 0x27600, 0x27600,
+ 0x27608, 0x2761c,
+ 0x27624, 0x27628,
+ 0x27630, 0x27634,
+ 0x2763c, 0x2763c,
+ 0x27700, 0x2771c,
+ 0x27780, 0x2778c,
+ 0x27800, 0x27818,
+ 0x27820, 0x27828,
+ 0x27830, 0x27848,
+ 0x27850, 0x27854,
+ 0x27860, 0x27868,
+ 0x27870, 0x27870,
+ 0x27878, 0x27898,
+ 0x278a0, 0x278a8,
+ 0x278b0, 0x278c8,
+ 0x278d0, 0x278d4,
+ 0x278e0, 0x278e8,
+ 0x278f0, 0x278f0,
+ 0x278f8, 0x27a18,
+ 0x27a20, 0x27a28,
+ 0x27a30, 0x27a48,
+ 0x27a50, 0x27a54,
+ 0x27a60, 0x27a68,
+ 0x27a70, 0x27a70,
+ 0x27a78, 0x27a98,
+ 0x27aa0, 0x27aa8,
+ 0x27ab0, 0x27ac8,
+ 0x27ad0, 0x27ad4,
+ 0x27ae0, 0x27ae8,
+ 0x27af0, 0x27af0,
+ 0x27af8, 0x27c18,
+ 0x27c20, 0x27c20,
+ 0x27c28, 0x27c30,
+ 0x27c38, 0x27c38,
+ 0x27c80, 0x27c98,
+ 0x27ca0, 0x27ca8,
+ 0x27cb0, 0x27cc8,
+ 0x27cd0, 0x27cd4,
+ 0x27ce0, 0x27ce8,
+ 0x27cf0, 0x27cf0,
+ 0x27cf8, 0x27d7c,
+ 0x27e00, 0x27e04,
+ };
+
+ static const unsigned int t5_reg_ranges[] = {
+ 0x1008, 0x10c0,
+ 0x10cc, 0x10f8,
+ 0x1100, 0x1100,
+ 0x110c, 0x1148,
+ 0x1180, 0x1184,
+ 0x1190, 0x1194,
+ 0x11a0, 0x11a4,
+ 0x11b0, 0x11b4,
+ 0x11fc, 0x123c,
+ 0x1280, 0x173c,
+ 0x1800, 0x18fc,
+ 0x3000, 0x3028,
+ 0x3060, 0x30b0,
+ 0x30b8, 0x30d8,
+ 0x30e0, 0x30fc,
+ 0x3140, 0x357c,
+ 0x35a8, 0x35cc,
+ 0x35ec, 0x35ec,
+ 0x3600, 0x5624,
+ 0x56cc, 0x56ec,
+ 0x56f4, 0x5720,
+ 0x5728, 0x575c,
+ 0x580c, 0x5814,
+ 0x5890, 0x589c,
+ 0x58a4, 0x58ac,
+ 0x58b8, 0x58bc,
+ 0x5940, 0x59c8,
+ 0x59d0, 0x59dc,
+ 0x59fc, 0x5a18,
+ 0x5a60, 0x5a70,
+ 0x5a80, 0x5a9c,
+ 0x5b94, 0x5bfc,
+ 0x6000, 0x6020,
+ 0x6028, 0x6040,
+ 0x6058, 0x609c,
+ 0x60a8, 0x614c,
+ 0x7700, 0x7798,
+ 0x77c0, 0x78fc,
+ 0x7b00, 0x7b58,
+ 0x7b60, 0x7b84,
+ 0x7b8c, 0x7c54,
+ 0x7d00, 0x7d38,
+ 0x7d40, 0x7d80,
+ 0x7d8c, 0x7ddc,
+ 0x7de4, 0x7e04,
+ 0x7e10, 0x7e1c,
+ 0x7e24, 0x7e38,
+ 0x7e40, 0x7e44,
+ 0x7e4c, 0x7e78,
+ 0x7e80, 0x7edc,
+ 0x7ee8, 0x7efc,
+ 0x8dc0, 0x8de0,
+ 0x8df8, 0x8e04,
+ 0x8e10, 0x8e84,
+ 0x8ea0, 0x8f84,
+ 0x8fc0, 0x9058,
+ 0x9060, 0x9060,
+ 0x9068, 0x90f8,
+ 0x9400, 0x9408,
+ 0x9410, 0x9470,
+ 0x9600, 0x9600,
+ 0x9608, 0x9638,
+ 0x9640, 0x96f4,
+ 0x9800, 0x9808,
+ 0x9820, 0x983c,
+ 0x9850, 0x9864,
+ 0x9c00, 0x9c6c,
+ 0x9c80, 0x9cec,
+ 0x9d00, 0x9d6c,
+ 0x9d80, 0x9dec,
+ 0x9e00, 0x9e6c,
+ 0x9e80, 0x9eec,
+ 0x9f00, 0x9f6c,
+ 0x9f80, 0xa020,
+ 0xd004, 0xd004,
+ 0xd010, 0xd03c,
+ 0xdfc0, 0xdfe0,
+ 0xe000, 0x1106c,
+ 0x11074, 0x11088,
+ 0x1109c, 0x1117c,
+ 0x11190, 0x11204,
+ 0x19040, 0x1906c,
+ 0x19078, 0x19080,
+ 0x1908c, 0x190e8,
+ 0x190f0, 0x190f8,
+ 0x19100, 0x19110,
+ 0x19120, 0x19124,
+ 0x19150, 0x19194,
+ 0x1919c, 0x191b0,
+ 0x191d0, 0x191e8,
+ 0x19238, 0x19290,
+ 0x193f8, 0x19428,
+ 0x19430, 0x19444,
+ 0x1944c, 0x1946c,
+ 0x19474, 0x19474,
+ 0x19490, 0x194cc,
+ 0x194f0, 0x194f8,
+ 0x19c00, 0x19c08,
+ 0x19c10, 0x19c60,
+ 0x19c94, 0x19ce4,
+ 0x19cf0, 0x19d40,
+ 0x19d50, 0x19d94,
+ 0x19da0, 0x19de8,
+ 0x19df0, 0x19e10,
+ 0x19e50, 0x19e90,
+ 0x19ea0, 0x19f24,
+ 0x19f34, 0x19f34,
+ 0x19f40, 0x19f50,
+ 0x19f90, 0x19fb4,
+ 0x19fc4, 0x19fe4,
+ 0x1a000, 0x1a004,
+ 0x1a010, 0x1a06c,
+ 0x1a0b0, 0x1a0e4,
+ 0x1a0ec, 0x1a0f8,
+ 0x1a100, 0x1a108,
+ 0x1a114, 0x1a120,
+ 0x1a128, 0x1a130,
+ 0x1a138, 0x1a138,
+ 0x1a190, 0x1a1c4,
+ 0x1a1fc, 0x1a1fc,
+ 0x1e008, 0x1e00c,
+ 0x1e040, 0x1e044,
+ 0x1e04c, 0x1e04c,
+ 0x1e284, 0x1e290,
+ 0x1e2c0, 0x1e2c0,
+ 0x1e2e0, 0x1e2e0,
+ 0x1e300, 0x1e384,
+ 0x1e3c0, 0x1e3c8,
+ 0x1e408, 0x1e40c,
+ 0x1e440, 0x1e444,
+ 0x1e44c, 0x1e44c,
+ 0x1e684, 0x1e690,
+ 0x1e6c0, 0x1e6c0,
+ 0x1e6e0, 0x1e6e0,
+ 0x1e700, 0x1e784,
+ 0x1e7c0, 0x1e7c8,
+ 0x1e808, 0x1e80c,
+ 0x1e840, 0x1e844,
+ 0x1e84c, 0x1e84c,
+ 0x1ea84, 0x1ea90,
+ 0x1eac0, 0x1eac0,
+ 0x1eae0, 0x1eae0,
+ 0x1eb00, 0x1eb84,
+ 0x1ebc0, 0x1ebc8,
+ 0x1ec08, 0x1ec0c,
+ 0x1ec40, 0x1ec44,
+ 0x1ec4c, 0x1ec4c,
+ 0x1ee84, 0x1ee90,
+ 0x1eec0, 0x1eec0,
+ 0x1eee0, 0x1eee0,
+ 0x1ef00, 0x1ef84,
+ 0x1efc0, 0x1efc8,
+ 0x1f008, 0x1f00c,
+ 0x1f040, 0x1f044,
+ 0x1f04c, 0x1f04c,
+ 0x1f284, 0x1f290,
+ 0x1f2c0, 0x1f2c0,
+ 0x1f2e0, 0x1f2e0,
+ 0x1f300, 0x1f384,
+ 0x1f3c0, 0x1f3c8,
+ 0x1f408, 0x1f40c,
+ 0x1f440, 0x1f444,
+ 0x1f44c, 0x1f44c,
+ 0x1f684, 0x1f690,
+ 0x1f6c0, 0x1f6c0,
+ 0x1f6e0, 0x1f6e0,
+ 0x1f700, 0x1f784,
+ 0x1f7c0, 0x1f7c8,
+ 0x1f808, 0x1f80c,
+ 0x1f840, 0x1f844,
+ 0x1f84c, 0x1f84c,
+ 0x1fa84, 0x1fa90,
+ 0x1fac0, 0x1fac0,
+ 0x1fae0, 0x1fae0,
+ 0x1fb00, 0x1fb84,
+ 0x1fbc0, 0x1fbc8,
+ 0x1fc08, 0x1fc0c,
+ 0x1fc40, 0x1fc44,
+ 0x1fc4c, 0x1fc4c,
+ 0x1fe84, 0x1fe90,
+ 0x1fec0, 0x1fec0,
+ 0x1fee0, 0x1fee0,
+ 0x1ff00, 0x1ff84,
+ 0x1ffc0, 0x1ffc8,
+ 0x30000, 0x30030,
+ 0x30038, 0x30038,
+ 0x30040, 0x30040,
+ 0x30100, 0x30144,
+ 0x30190, 0x301a0,
+ 0x301a8, 0x301b8,
+ 0x301c4, 0x301c8,
+ 0x301d0, 0x301d0,
+ 0x30200, 0x30318,
+ 0x30400, 0x304b4,
+ 0x304c0, 0x3052c,
+ 0x30540, 0x3061c,
+ 0x30800, 0x30828,
+ 0x30834, 0x30834,
+ 0x308c0, 0x30908,
+ 0x30910, 0x309ac,
+ 0x30a00, 0x30a14,
+ 0x30a1c, 0x30a2c,
+ 0x30a44, 0x30a50,
+ 0x30a74, 0x30a74,
+ 0x30a7c, 0x30afc,
+ 0x30b08, 0x30c24,
+ 0x30d00, 0x30d00,
+ 0x30d08, 0x30d14,
+ 0x30d1c, 0x30d20,
+ 0x30d3c, 0x30d3c,
+ 0x30d48, 0x30d50,
+ 0x31200, 0x3120c,
+ 0x31220, 0x31220,
+ 0x31240, 0x31240,
+ 0x31600, 0x3160c,
+ 0x31a00, 0x31a1c,
+ 0x31e00, 0x31e20,
+ 0x31e38, 0x31e3c,
+ 0x31e80, 0x31e80,
+ 0x31e88, 0x31ea8,
+ 0x31eb0, 0x31eb4,
+ 0x31ec8, 0x31ed4,
+ 0x31fb8, 0x32004,
+ 0x32200, 0x32200,
+ 0x32208, 0x32240,
+ 0x32248, 0x32280,
+ 0x32288, 0x322c0,
+ 0x322c8, 0x322fc,
+ 0x32600, 0x32630,
+ 0x32a00, 0x32abc,
+ 0x32b00, 0x32b10,
+ 0x32b20, 0x32b30,
+ 0x32b40, 0x32b50,
+ 0x32b60, 0x32b70,
+ 0x33000, 0x33028,
+ 0x33030, 0x33048,
+ 0x33060, 0x33068,
+ 0x33070, 0x3309c,
+ 0x330f0, 0x33128,
+ 0x33130, 0x33148,
+ 0x33160, 0x33168,
+ 0x33170, 0x3319c,
+ 0x331f0, 0x33238,
+ 0x33240, 0x33240,
+ 0x33248, 0x33250,
+ 0x3325c, 0x33264,
+ 0x33270, 0x332b8,
+ 0x332c0, 0x332e4,
+ 0x332f8, 0x33338,
+ 0x33340, 0x33340,
+ 0x33348, 0x33350,
+ 0x3335c, 0x33364,
+ 0x33370, 0x333b8,
+ 0x333c0, 0x333e4,
+ 0x333f8, 0x33428,
+ 0x33430, 0x33448,
+ 0x33460, 0x33468,
+ 0x33470, 0x3349c,
+ 0x334f0, 0x33528,
+ 0x33530, 0x33548,
+ 0x33560, 0x33568,
+ 0x33570, 0x3359c,
+ 0x335f0, 0x33638,
+ 0x33640, 0x33640,
+ 0x33648, 0x33650,
+ 0x3365c, 0x33664,
+ 0x33670, 0x336b8,
+ 0x336c0, 0x336e4,
+ 0x336f8, 0x33738,
+ 0x33740, 0x33740,
+ 0x33748, 0x33750,
+ 0x3375c, 0x33764,
+ 0x33770, 0x337b8,
+ 0x337c0, 0x337e4,
+ 0x337f8, 0x337fc,
+ 0x33814, 0x33814,
+ 0x3382c, 0x3382c,
+ 0x33880, 0x3388c,
+ 0x338e8, 0x338ec,
+ 0x33900, 0x33928,
+ 0x33930, 0x33948,
+ 0x33960, 0x33968,
+ 0x33970, 0x3399c,
+ 0x339f0, 0x33a38,
+ 0x33a40, 0x33a40,
+ 0x33a48, 0x33a50,
+ 0x33a5c, 0x33a64,
+ 0x33a70, 0x33ab8,
+ 0x33ac0, 0x33ae4,
+ 0x33af8, 0x33b10,
+ 0x33b28, 0x33b28,
+ 0x33b3c, 0x33b50,
+ 0x33bf0, 0x33c10,
+ 0x33c28, 0x33c28,
+ 0x33c3c, 0x33c50,
+ 0x33cf0, 0x33cfc,
+ 0x34000, 0x34030,
+ 0x34038, 0x34038,
+ 0x34040, 0x34040,
+ 0x34100, 0x34144,
+ 0x34190, 0x341a0,
+ 0x341a8, 0x341b8,
+ 0x341c4, 0x341c8,
+ 0x341d0, 0x341d0,
+ 0x34200, 0x34318,
+ 0x34400, 0x344b4,
+ 0x344c0, 0x3452c,
+ 0x34540, 0x3461c,
+ 0x34800, 0x34828,
+ 0x34834, 0x34834,
+ 0x348c0, 0x34908,
+ 0x34910, 0x349ac,
+ 0x34a00, 0x34a14,
+ 0x34a1c, 0x34a2c,
+ 0x34a44, 0x34a50,
+ 0x34a74, 0x34a74,
+ 0x34a7c, 0x34afc,
+ 0x34b08, 0x34c24,
+ 0x34d00, 0x34d00,
+ 0x34d08, 0x34d14,
+ 0x34d1c, 0x34d20,
+ 0x34d3c, 0x34d3c,
+ 0x34d48, 0x34d50,
+ 0x35200, 0x3520c,
+ 0x35220, 0x35220,
+ 0x35240, 0x35240,
+ 0x35600, 0x3560c,
+ 0x35a00, 0x35a1c,
+ 0x35e00, 0x35e20,
+ 0x35e38, 0x35e3c,
+ 0x35e80, 0x35e80,
+ 0x35e88, 0x35ea8,
+ 0x35eb0, 0x35eb4,
+ 0x35ec8, 0x35ed4,
+ 0x35fb8, 0x36004,
+ 0x36200, 0x36200,
+ 0x36208, 0x36240,
+ 0x36248, 0x36280,
+ 0x36288, 0x362c0,
+ 0x362c8, 0x362fc,
+ 0x36600, 0x36630,
+ 0x36a00, 0x36abc,
+ 0x36b00, 0x36b10,
+ 0x36b20, 0x36b30,
+ 0x36b40, 0x36b50,
+ 0x36b60, 0x36b70,
+ 0x37000, 0x37028,
+ 0x37030, 0x37048,
+ 0x37060, 0x37068,
+ 0x37070, 0x3709c,
+ 0x370f0, 0x37128,
+ 0x37130, 0x37148,
+ 0x37160, 0x37168,
+ 0x37170, 0x3719c,
+ 0x371f0, 0x37238,
+ 0x37240, 0x37240,
+ 0x37248, 0x37250,
+ 0x3725c, 0x37264,
+ 0x37270, 0x372b8,
+ 0x372c0, 0x372e4,
+ 0x372f8, 0x37338,
+ 0x37340, 0x37340,
+ 0x37348, 0x37350,
+ 0x3735c, 0x37364,
+ 0x37370, 0x373b8,
+ 0x373c0, 0x373e4,
+ 0x373f8, 0x37428,
+ 0x37430, 0x37448,
+ 0x37460, 0x37468,
+ 0x37470, 0x3749c,
+ 0x374f0, 0x37528,
+ 0x37530, 0x37548,
+ 0x37560, 0x37568,
+ 0x37570, 0x3759c,
+ 0x375f0, 0x37638,
+ 0x37640, 0x37640,
+ 0x37648, 0x37650,
+ 0x3765c, 0x37664,
+ 0x37670, 0x376b8,
+ 0x376c0, 0x376e4,
+ 0x376f8, 0x37738,
+ 0x37740, 0x37740,
+ 0x37748, 0x37750,
+ 0x3775c, 0x37764,
+ 0x37770, 0x377b8,
+ 0x377c0, 0x377e4,
+ 0x377f8, 0x377fc,
+ 0x37814, 0x37814,
+ 0x3782c, 0x3782c,
+ 0x37880, 0x3788c,
+ 0x378e8, 0x378ec,
+ 0x37900, 0x37928,
+ 0x37930, 0x37948,
+ 0x37960, 0x37968,
+ 0x37970, 0x3799c,
+ 0x379f0, 0x37a38,
+ 0x37a40, 0x37a40,
+ 0x37a48, 0x37a50,
+ 0x37a5c, 0x37a64,
+ 0x37a70, 0x37ab8,
+ 0x37ac0, 0x37ae4,
+ 0x37af8, 0x37b10,
+ 0x37b28, 0x37b28,
+ 0x37b3c, 0x37b50,
+ 0x37bf0, 0x37c10,
+ 0x37c28, 0x37c28,
+ 0x37c3c, 0x37c50,
+ 0x37cf0, 0x37cfc,
+ 0x38000, 0x38030,
+ 0x38038, 0x38038,
+ 0x38040, 0x38040,
+ 0x38100, 0x38144,
+ 0x38190, 0x381a0,
+ 0x381a8, 0x381b8,
+ 0x381c4, 0x381c8,
+ 0x381d0, 0x381d0,
+ 0x38200, 0x38318,
+ 0x38400, 0x384b4,
+ 0x384c0, 0x3852c,
+ 0x38540, 0x3861c,
+ 0x38800, 0x38828,
+ 0x38834, 0x38834,
+ 0x388c0, 0x38908,
+ 0x38910, 0x389ac,
+ 0x38a00, 0x38a14,
+ 0x38a1c, 0x38a2c,
+ 0x38a44, 0x38a50,
+ 0x38a74, 0x38a74,
+ 0x38a7c, 0x38afc,
+ 0x38b08, 0x38c24,
+ 0x38d00, 0x38d00,
+ 0x38d08, 0x38d14,
+ 0x38d1c, 0x38d20,
+ 0x38d3c, 0x38d3c,
+ 0x38d48, 0x38d50,
+ 0x39200, 0x3920c,
+ 0x39220, 0x39220,
+ 0x39240, 0x39240,
+ 0x39600, 0x3960c,
+ 0x39a00, 0x39a1c,
+ 0x39e00, 0x39e20,
+ 0x39e38, 0x39e3c,
+ 0x39e80, 0x39e80,
+ 0x39e88, 0x39ea8,
+ 0x39eb0, 0x39eb4,
+ 0x39ec8, 0x39ed4,
+ 0x39fb8, 0x3a004,
+ 0x3a200, 0x3a200,
+ 0x3a208, 0x3a240,
+ 0x3a248, 0x3a280,
+ 0x3a288, 0x3a2c0,
+ 0x3a2c8, 0x3a2fc,
+ 0x3a600, 0x3a630,
+ 0x3aa00, 0x3aabc,
+ 0x3ab00, 0x3ab10,
+ 0x3ab20, 0x3ab30,
+ 0x3ab40, 0x3ab50,
+ 0x3ab60, 0x3ab70,
+ 0x3b000, 0x3b028,
+ 0x3b030, 0x3b048,
+ 0x3b060, 0x3b068,
+ 0x3b070, 0x3b09c,
+ 0x3b0f0, 0x3b128,
+ 0x3b130, 0x3b148,
+ 0x3b160, 0x3b168,
+ 0x3b170, 0x3b19c,
+ 0x3b1f0, 0x3b238,
+ 0x3b240, 0x3b240,
+ 0x3b248, 0x3b250,
+ 0x3b25c, 0x3b264,
+ 0x3b270, 0x3b2b8,
+ 0x3b2c0, 0x3b2e4,
+ 0x3b2f8, 0x3b338,
+ 0x3b340, 0x3b340,
+ 0x3b348, 0x3b350,
+ 0x3b35c, 0x3b364,
+ 0x3b370, 0x3b3b8,
+ 0x3b3c0, 0x3b3e4,
+ 0x3b3f8, 0x3b428,
+ 0x3b430, 0x3b448,
+ 0x3b460, 0x3b468,
+ 0x3b470, 0x3b49c,
+ 0x3b4f0, 0x3b528,
+ 0x3b530, 0x3b548,
+ 0x3b560, 0x3b568,
+ 0x3b570, 0x3b59c,
+ 0x3b5f0, 0x3b638,
+ 0x3b640, 0x3b640,
+ 0x3b648, 0x3b650,
+ 0x3b65c, 0x3b664,
+ 0x3b670, 0x3b6b8,
+ 0x3b6c0, 0x3b6e4,
+ 0x3b6f8, 0x3b738,
+ 0x3b740, 0x3b740,
+ 0x3b748, 0x3b750,
+ 0x3b75c, 0x3b764,
+ 0x3b770, 0x3b7b8,
+ 0x3b7c0, 0x3b7e4,
+ 0x3b7f8, 0x3b7fc,
+ 0x3b814, 0x3b814,
+ 0x3b82c, 0x3b82c,
+ 0x3b880, 0x3b88c,
+ 0x3b8e8, 0x3b8ec,
+ 0x3b900, 0x3b928,
+ 0x3b930, 0x3b948,
+ 0x3b960, 0x3b968,
+ 0x3b970, 0x3b99c,
+ 0x3b9f0, 0x3ba38,
+ 0x3ba40, 0x3ba40,
+ 0x3ba48, 0x3ba50,
+ 0x3ba5c, 0x3ba64,
+ 0x3ba70, 0x3bab8,
+ 0x3bac0, 0x3bae4,
+ 0x3baf8, 0x3bb10,
+ 0x3bb28, 0x3bb28,
+ 0x3bb3c, 0x3bb50,
+ 0x3bbf0, 0x3bc10,
+ 0x3bc28, 0x3bc28,
+ 0x3bc3c, 0x3bc50,
+ 0x3bcf0, 0x3bcfc,
+ 0x3c000, 0x3c030,
+ 0x3c038, 0x3c038,
+ 0x3c040, 0x3c040,
+ 0x3c100, 0x3c144,
+ 0x3c190, 0x3c1a0,
+ 0x3c1a8, 0x3c1b8,
+ 0x3c1c4, 0x3c1c8,
+ 0x3c1d0, 0x3c1d0,
+ 0x3c200, 0x3c318,
+ 0x3c400, 0x3c4b4,
+ 0x3c4c0, 0x3c52c,
+ 0x3c540, 0x3c61c,
+ 0x3c800, 0x3c828,
+ 0x3c834, 0x3c834,
+ 0x3c8c0, 0x3c908,
+ 0x3c910, 0x3c9ac,
+ 0x3ca00, 0x3ca14,
+ 0x3ca1c, 0x3ca2c,
+ 0x3ca44, 0x3ca50,
+ 0x3ca74, 0x3ca74,
+ 0x3ca7c, 0x3cafc,
+ 0x3cb08, 0x3cc24,
+ 0x3cd00, 0x3cd00,
+ 0x3cd08, 0x3cd14,
+ 0x3cd1c, 0x3cd20,
+ 0x3cd3c, 0x3cd3c,
+ 0x3cd48, 0x3cd50,
+ 0x3d200, 0x3d20c,
+ 0x3d220, 0x3d220,
+ 0x3d240, 0x3d240,
+ 0x3d600, 0x3d60c,
+ 0x3da00, 0x3da1c,
+ 0x3de00, 0x3de20,
+ 0x3de38, 0x3de3c,
+ 0x3de80, 0x3de80,
+ 0x3de88, 0x3dea8,
+ 0x3deb0, 0x3deb4,
+ 0x3dec8, 0x3ded4,
+ 0x3dfb8, 0x3e004,
+ 0x3e200, 0x3e200,
+ 0x3e208, 0x3e240,
+ 0x3e248, 0x3e280,
+ 0x3e288, 0x3e2c0,
+ 0x3e2c8, 0x3e2fc,
+ 0x3e600, 0x3e630,
+ 0x3ea00, 0x3eabc,
+ 0x3eb00, 0x3eb10,
+ 0x3eb20, 0x3eb30,
+ 0x3eb40, 0x3eb50,
+ 0x3eb60, 0x3eb70,
+ 0x3f000, 0x3f028,
+ 0x3f030, 0x3f048,
+ 0x3f060, 0x3f068,
+ 0x3f070, 0x3f09c,
+ 0x3f0f0, 0x3f128,
+ 0x3f130, 0x3f148,
+ 0x3f160, 0x3f168,
+ 0x3f170, 0x3f19c,
+ 0x3f1f0, 0x3f238,
+ 0x3f240, 0x3f240,
+ 0x3f248, 0x3f250,
+ 0x3f25c, 0x3f264,
+ 0x3f270, 0x3f2b8,
+ 0x3f2c0, 0x3f2e4,
+ 0x3f2f8, 0x3f338,
+ 0x3f340, 0x3f340,
+ 0x3f348, 0x3f350,
+ 0x3f35c, 0x3f364,
+ 0x3f370, 0x3f3b8,
+ 0x3f3c0, 0x3f3e4,
+ 0x3f3f8, 0x3f428,
+ 0x3f430, 0x3f448,
+ 0x3f460, 0x3f468,
+ 0x3f470, 0x3f49c,
+ 0x3f4f0, 0x3f528,
+ 0x3f530, 0x3f548,
+ 0x3f560, 0x3f568,
+ 0x3f570, 0x3f59c,
+ 0x3f5f0, 0x3f638,
+ 0x3f640, 0x3f640,
+ 0x3f648, 0x3f650,
+ 0x3f65c, 0x3f664,
+ 0x3f670, 0x3f6b8,
+ 0x3f6c0, 0x3f6e4,
+ 0x3f6f8, 0x3f738,
+ 0x3f740, 0x3f740,
+ 0x3f748, 0x3f750,
+ 0x3f75c, 0x3f764,
+ 0x3f770, 0x3f7b8,
+ 0x3f7c0, 0x3f7e4,
+ 0x3f7f8, 0x3f7fc,
+ 0x3f814, 0x3f814,
+ 0x3f82c, 0x3f82c,
+ 0x3f880, 0x3f88c,
+ 0x3f8e8, 0x3f8ec,
+ 0x3f900, 0x3f928,
+ 0x3f930, 0x3f948,
+ 0x3f960, 0x3f968,
+ 0x3f970, 0x3f99c,
+ 0x3f9f0, 0x3fa38,
+ 0x3fa40, 0x3fa40,
+ 0x3fa48, 0x3fa50,
+ 0x3fa5c, 0x3fa64,
+ 0x3fa70, 0x3fab8,
+ 0x3fac0, 0x3fae4,
+ 0x3faf8, 0x3fb10,
+ 0x3fb28, 0x3fb28,
+ 0x3fb3c, 0x3fb50,
+ 0x3fbf0, 0x3fc10,
+ 0x3fc28, 0x3fc28,
+ 0x3fc3c, 0x3fc50,
+ 0x3fcf0, 0x3fcfc,
+ 0x40000, 0x4000c,
+ 0x40040, 0x40050,
+ 0x40060, 0x40068,
+ 0x4007c, 0x4008c,
+ 0x40094, 0x400b0,
+ 0x400c0, 0x40144,
+ 0x40180, 0x4018c,
+ 0x40200, 0x40254,
+ 0x40260, 0x40264,
+ 0x40270, 0x40288,
+ 0x40290, 0x40298,
+ 0x402ac, 0x402c8,
+ 0x402d0, 0x402e0,
+ 0x402f0, 0x402f0,
+ 0x40300, 0x4033c,
+ 0x403f8, 0x403fc,
+ 0x41304, 0x413c4,
+ 0x41400, 0x4140c,
+ 0x41414, 0x4141c,
+ 0x41480, 0x414d0,
+ 0x44000, 0x44054,
+ 0x4405c, 0x44078,
+ 0x440c0, 0x44174,
+ 0x44180, 0x441ac,
+ 0x441b4, 0x441b8,
+ 0x441c0, 0x44254,
+ 0x4425c, 0x44278,
+ 0x442c0, 0x44374,
+ 0x44380, 0x443ac,
+ 0x443b4, 0x443b8,
+ 0x443c0, 0x44454,
+ 0x4445c, 0x44478,
+ 0x444c0, 0x44574,
+ 0x44580, 0x445ac,
+ 0x445b4, 0x445b8,
+ 0x445c0, 0x44654,
+ 0x4465c, 0x44678,
+ 0x446c0, 0x44774,
+ 0x44780, 0x447ac,
+ 0x447b4, 0x447b8,
+ 0x447c0, 0x44854,
+ 0x4485c, 0x44878,
+ 0x448c0, 0x44974,
+ 0x44980, 0x449ac,
+ 0x449b4, 0x449b8,
+ 0x449c0, 0x449fc,
+ 0x45000, 0x45004,
+ 0x45010, 0x45030,
+ 0x45040, 0x45060,
+ 0x45068, 0x45068,
+ 0x45080, 0x45084,
+ 0x450a0, 0x450b0,
+ 0x45200, 0x45204,
+ 0x45210, 0x45230,
+ 0x45240, 0x45260,
+ 0x45268, 0x45268,
+ 0x45280, 0x45284,
+ 0x452a0, 0x452b0,
+ 0x460c0, 0x460e4,
+ 0x47000, 0x4703c,
+ 0x47044, 0x4708c,
+ 0x47200, 0x47250,
+ 0x47400, 0x47408,
+ 0x47414, 0x47420,
+ 0x47600, 0x47618,
+ 0x47800, 0x47814,
+ 0x48000, 0x4800c,
+ 0x48040, 0x48050,
+ 0x48060, 0x48068,
+ 0x4807c, 0x4808c,
+ 0x48094, 0x480b0,
+ 0x480c0, 0x48144,
+ 0x48180, 0x4818c,
+ 0x48200, 0x48254,
+ 0x48260, 0x48264,
+ 0x48270, 0x48288,
+ 0x48290, 0x48298,
+ 0x482ac, 0x482c8,
+ 0x482d0, 0x482e0,
+ 0x482f0, 0x482f0,
+ 0x48300, 0x4833c,
+ 0x483f8, 0x483fc,
+ 0x49304, 0x493c4,
+ 0x49400, 0x4940c,
+ 0x49414, 0x4941c,
+ 0x49480, 0x494d0,
+ 0x4c000, 0x4c054,
+ 0x4c05c, 0x4c078,
+ 0x4c0c0, 0x4c174,
+ 0x4c180, 0x4c1ac,
+ 0x4c1b4, 0x4c1b8,
+ 0x4c1c0, 0x4c254,
+ 0x4c25c, 0x4c278,
+ 0x4c2c0, 0x4c374,
+ 0x4c380, 0x4c3ac,
+ 0x4c3b4, 0x4c3b8,
+ 0x4c3c0, 0x4c454,
+ 0x4c45c, 0x4c478,
+ 0x4c4c0, 0x4c574,
+ 0x4c580, 0x4c5ac,
+ 0x4c5b4, 0x4c5b8,
+ 0x4c5c0, 0x4c654,
+ 0x4c65c, 0x4c678,
+ 0x4c6c0, 0x4c774,
+ 0x4c780, 0x4c7ac,
+ 0x4c7b4, 0x4c7b8,
+ 0x4c7c0, 0x4c854,
+ 0x4c85c, 0x4c878,
+ 0x4c8c0, 0x4c974,
+ 0x4c980, 0x4c9ac,
+ 0x4c9b4, 0x4c9b8,
+ 0x4c9c0, 0x4c9fc,
+ 0x4d000, 0x4d004,
+ 0x4d010, 0x4d030,
+ 0x4d040, 0x4d060,
+ 0x4d068, 0x4d068,
+ 0x4d080, 0x4d084,
+ 0x4d0a0, 0x4d0b0,
+ 0x4d200, 0x4d204,
+ 0x4d210, 0x4d230,
+ 0x4d240, 0x4d260,
+ 0x4d268, 0x4d268,
+ 0x4d280, 0x4d284,
+ 0x4d2a0, 0x4d2b0,
+ 0x4e0c0, 0x4e0e4,
+ 0x4f000, 0x4f03c,
+ 0x4f044, 0x4f08c,
+ 0x4f200, 0x4f250,
+ 0x4f400, 0x4f408,
+ 0x4f414, 0x4f420,
+ 0x4f600, 0x4f618,
+ 0x4f800, 0x4f814,
+ 0x50000, 0x50084,
+ 0x50090, 0x500cc,
+ 0x50400, 0x50400,
+ 0x50800, 0x50884,
+ 0x50890, 0x508cc,
+ 0x50c00, 0x50c00,
+ 0x51000, 0x5101c,
+ 0x51300, 0x51308,
+ };
+
+ static const unsigned int t6_reg_ranges[] = {
+ 0x1008, 0x101c,
+ 0x1024, 0x10a8,
+ 0x10b4, 0x10f8,
+ 0x1100, 0x1114,
+ 0x111c, 0x112c,
+ 0x1138, 0x113c,
+ 0x1144, 0x114c,
+ 0x1180, 0x1184,
+ 0x1190, 0x1194,
+ 0x11a0, 0x11a4,
+ 0x11b0, 0x11b4,
+ 0x11fc, 0x1274,
+ 0x1280, 0x133c,
+ 0x1800, 0x18fc,
+ 0x3000, 0x302c,
+ 0x3060, 0x30b0,
+ 0x30b8, 0x30d8,
+ 0x30e0, 0x30fc,
+ 0x3140, 0x357c,
+ 0x35a8, 0x35cc,
+ 0x35ec, 0x35ec,
+ 0x3600, 0x5624,
+ 0x56cc, 0x56ec,
+ 0x56f4, 0x5720,
+ 0x5728, 0x575c,
+ 0x580c, 0x5814,
+ 0x5890, 0x589c,
+ 0x58a4, 0x58ac,
+ 0x58b8, 0x58bc,
+ 0x5940, 0x595c,
+ 0x5980, 0x598c,
+ 0x59b0, 0x59c8,
+ 0x59d0, 0x59dc,
+ 0x59fc, 0x5a18,
+ 0x5a60, 0x5a6c,
+ 0x5a80, 0x5a8c,
+ 0x5a94, 0x5a9c,
+ 0x5b94, 0x5bfc,
+ 0x5c10, 0x5e48,
+ 0x5e50, 0x5e94,
+ 0x5ea0, 0x5eb0,
+ 0x5ec0, 0x5ec0,
+ 0x5ec8, 0x5ed0,
+ 0x5ee0, 0x5ee0,
+ 0x5ef0, 0x5ef0,
+ 0x5f00, 0x5f00,
+ 0x6000, 0x6020,
+ 0x6028, 0x6040,
+ 0x6058, 0x609c,
+ 0x60a8, 0x619c,
+ 0x7700, 0x7798,
+ 0x77c0, 0x7880,
+ 0x78cc, 0x78fc,
+ 0x7b00, 0x7b58,
+ 0x7b60, 0x7b84,
+ 0x7b8c, 0x7c54,
+ 0x7d00, 0x7d38,
+ 0x7d40, 0x7d84,
+ 0x7d8c, 0x7ddc,
+ 0x7de4, 0x7e04,
+ 0x7e10, 0x7e1c,
+ 0x7e24, 0x7e38,
+ 0x7e40, 0x7e44,
+ 0x7e4c, 0x7e78,
+ 0x7e80, 0x7edc,
+ 0x7ee8, 0x7efc,
+ 0x8dc0, 0x8de4,
+ 0x8df8, 0x8e04,
+ 0x8e10, 0x8e84,
+ 0x8ea0, 0x8f88,
+ 0x8fb8, 0x9058,
+ 0x9060, 0x9060,
+ 0x9068, 0x90f8,
+ 0x9100, 0x9124,
+ 0x9400, 0x9470,
+ 0x9600, 0x9600,
+ 0x9608, 0x9638,
+ 0x9640, 0x9704,
+ 0x9710, 0x971c,
+ 0x9800, 0x9808,
+ 0x9820, 0x983c,
+ 0x9850, 0x9864,
+ 0x9c00, 0x9c6c,
+ 0x9c80, 0x9cec,
+ 0x9d00, 0x9d6c,
+ 0x9d80, 0x9dec,
+ 0x9e00, 0x9e6c,
+ 0x9e80, 0x9eec,
+ 0x9f00, 0x9f6c,
+ 0x9f80, 0xa020,
+ 0xd004, 0xd03c,
+ 0xd100, 0xd118,
+ 0xd200, 0xd214,
+ 0xd220, 0xd234,
+ 0xd240, 0xd254,
+ 0xd260, 0xd274,
+ 0xd280, 0xd294,
+ 0xd2a0, 0xd2b4,
+ 0xd2c0, 0xd2d4,
+ 0xd2e0, 0xd2f4,
+ 0xd300, 0xd31c,
+ 0xdfc0, 0xdfe0,
+ 0xe000, 0xf008,
+ 0xf010, 0xf018,
+ 0xf020, 0xf028,
+ 0x11000, 0x11014,
+ 0x11048, 0x1106c,
+ 0x11074, 0x11088,
+ 0x11098, 0x11120,
+ 0x1112c, 0x1117c,
+ 0x11190, 0x112e0,
+ 0x11300, 0x1130c,
+ 0x12000, 0x1206c,
+ 0x19040, 0x1906c,
+ 0x19078, 0x19080,
+ 0x1908c, 0x190e8,
+ 0x190f0, 0x190f8,
+ 0x19100, 0x19110,
+ 0x19120, 0x19124,
+ 0x19150, 0x19194,
+ 0x1919c, 0x191b0,
+ 0x191d0, 0x191e8,
+ 0x19238, 0x19290,
+ 0x192a4, 0x192b0,
+ 0x192bc, 0x192bc,
+ 0x19348, 0x1934c,
+ 0x193f8, 0x19418,
+ 0x19420, 0x19428,
+ 0x19430, 0x19444,
+ 0x1944c, 0x1946c,
+ 0x19474, 0x19474,
+ 0x19490, 0x194cc,
+ 0x194f0, 0x194f8,
+ 0x19c00, 0x19c48,
+ 0x19c50, 0x19c80,
+ 0x19c94, 0x19c98,
+ 0x19ca0, 0x19cbc,
+ 0x19ce4, 0x19ce4,
+ 0x19cf0, 0x19cf8,
+ 0x19d00, 0x19d28,
+ 0x19d50, 0x19d78,
+ 0x19d94, 0x19d98,
+ 0x19da0, 0x19dc8,
+ 0x19df0, 0x19e10,
+ 0x19e50, 0x19e6c,
+ 0x19ea0, 0x19ebc,
+ 0x19ec4, 0x19ef4,
+ 0x19f04, 0x19f2c,
+ 0x19f34, 0x19f34,
+ 0x19f40, 0x19f50,
+ 0x19f90, 0x19fac,
+ 0x19fc4, 0x19fc8,
+ 0x19fd0, 0x19fe4,
+ 0x1a000, 0x1a004,
+ 0x1a010, 0x1a06c,
+ 0x1a0b0, 0x1a0e4,
+ 0x1a0ec, 0x1a0f8,
+ 0x1a100, 0x1a108,
+ 0x1a114, 0x1a120,
+ 0x1a128, 0x1a130,
+ 0x1a138, 0x1a138,
+ 0x1a190, 0x1a1c4,
+ 0x1a1fc, 0x1a1fc,
+ 0x1e008, 0x1e00c,
+ 0x1e040, 0x1e044,
+ 0x1e04c, 0x1e04c,
+ 0x1e284, 0x1e290,
+ 0x1e2c0, 0x1e2c0,
+ 0x1e2e0, 0x1e2e0,
+ 0x1e300, 0x1e384,
+ 0x1e3c0, 0x1e3c8,
+ 0x1e408, 0x1e40c,
+ 0x1e440, 0x1e444,
+ 0x1e44c, 0x1e44c,
+ 0x1e684, 0x1e690,
+ 0x1e6c0, 0x1e6c0,
+ 0x1e6e0, 0x1e6e0,
+ 0x1e700, 0x1e784,
+ 0x1e7c0, 0x1e7c8,
+ 0x1e808, 0x1e80c,
+ 0x1e840, 0x1e844,
+ 0x1e84c, 0x1e84c,
+ 0x1ea84, 0x1ea90,
+ 0x1eac0, 0x1eac0,
+ 0x1eae0, 0x1eae0,
+ 0x1eb00, 0x1eb84,
+ 0x1ebc0, 0x1ebc8,
+ 0x1ec08, 0x1ec0c,
+ 0x1ec40, 0x1ec44,
+ 0x1ec4c, 0x1ec4c,
+ 0x1ee84, 0x1ee90,
+ 0x1eec0, 0x1eec0,
+ 0x1eee0, 0x1eee0,
+ 0x1ef00, 0x1ef84,
+ 0x1efc0, 0x1efc8,
+ 0x1f008, 0x1f00c,
+ 0x1f040, 0x1f044,
+ 0x1f04c, 0x1f04c,
+ 0x1f284, 0x1f290,
+ 0x1f2c0, 0x1f2c0,
+ 0x1f2e0, 0x1f2e0,
+ 0x1f300, 0x1f384,
+ 0x1f3c0, 0x1f3c8,
+ 0x1f408, 0x1f40c,
+ 0x1f440, 0x1f444,
+ 0x1f44c, 0x1f44c,
+ 0x1f684, 0x1f690,
+ 0x1f6c0, 0x1f6c0,
+ 0x1f6e0, 0x1f6e0,
+ 0x1f700, 0x1f784,
+ 0x1f7c0, 0x1f7c8,
+ 0x1f808, 0x1f80c,
+ 0x1f840, 0x1f844,
+ 0x1f84c, 0x1f84c,
+ 0x1fa84, 0x1fa90,
+ 0x1fac0, 0x1fac0,
+ 0x1fae0, 0x1fae0,
+ 0x1fb00, 0x1fb84,
+ 0x1fbc0, 0x1fbc8,
+ 0x1fc08, 0x1fc0c,
+ 0x1fc40, 0x1fc44,
+ 0x1fc4c, 0x1fc4c,
+ 0x1fe84, 0x1fe90,
+ 0x1fec0, 0x1fec0,
+ 0x1fee0, 0x1fee0,
+ 0x1ff00, 0x1ff84,
+ 0x1ffc0, 0x1ffc8,
+ 0x30000, 0x30030,
+ 0x30038, 0x30038,
+ 0x30040, 0x30040,
+ 0x30048, 0x30048,
+ 0x30050, 0x30050,
+ 0x3005c, 0x30060,
+ 0x30068, 0x30068,
+ 0x30070, 0x30070,
+ 0x30100, 0x30168,
+ 0x30190, 0x301a0,
+ 0x301a8, 0x301b8,
+ 0x301c4, 0x301c8,
+ 0x301d0, 0x301d0,
+ 0x30200, 0x30320,
+ 0x30400, 0x304b4,
+ 0x304c0, 0x3052c,
+ 0x30540, 0x3061c,
+ 0x30800, 0x308a0,
+ 0x308c0, 0x30908,
+ 0x30910, 0x309b8,
+ 0x30a00, 0x30a04,
+ 0x30a0c, 0x30a14,
+ 0x30a1c, 0x30a2c,
+ 0x30a44, 0x30a50,
+ 0x30a74, 0x30a74,
+ 0x30a7c, 0x30afc,
+ 0x30b08, 0x30c24,
+ 0x30d00, 0x30d14,
+ 0x30d1c, 0x30d3c,
+ 0x30d44, 0x30d4c,
+ 0x30d54, 0x30d74,
+ 0x30d7c, 0x30d7c,
+ 0x30de0, 0x30de0,
+ 0x30e00, 0x30ed4,
+ 0x30f00, 0x30fa4,
+ 0x30fc0, 0x30fc4,
+ 0x31000, 0x31004,
+ 0x31080, 0x310fc,
+ 0x31208, 0x31220,
+ 0x3123c, 0x31254,
+ 0x31300, 0x31300,
+ 0x31308, 0x3131c,
+ 0x31338, 0x3133c,
+ 0x31380, 0x31380,
+ 0x31388, 0x313a8,
+ 0x313b4, 0x313b4,
+ 0x31400, 0x31420,
+ 0x31438, 0x3143c,
+ 0x31480, 0x31480,
+ 0x314a8, 0x314a8,
+ 0x314b0, 0x314b4,
+ 0x314c8, 0x314d4,
+ 0x31a40, 0x31a4c,
+ 0x31af0, 0x31b20,
+ 0x31b38, 0x31b3c,
+ 0x31b80, 0x31b80,
+ 0x31ba8, 0x31ba8,
+ 0x31bb0, 0x31bb4,
+ 0x31bc8, 0x31bd4,
+ 0x32140, 0x3218c,
+ 0x321f0, 0x321f4,
+ 0x32200, 0x32200,
+ 0x32218, 0x32218,
+ 0x32400, 0x32400,
+ 0x32408, 0x3241c,
+ 0x32618, 0x32620,
+ 0x32664, 0x32664,
+ 0x326a8, 0x326a8,
+ 0x326ec, 0x326ec,
+ 0x32a00, 0x32abc,
+ 0x32b00, 0x32b38,
+ 0x32b40, 0x32b58,
+ 0x32b60, 0x32b78,
+ 0x32c00, 0x32c00,
+ 0x32c08, 0x32c3c,
+ 0x32e00, 0x32e2c,
+ 0x32f00, 0x32f2c,
+ 0x33000, 0x3302c,
+ 0x33034, 0x33050,
+ 0x33058, 0x33058,
+ 0x33060, 0x3308c,
+ 0x3309c, 0x330ac,
+ 0x330c0, 0x330c0,
+ 0x330c8, 0x330d0,
+ 0x330d8, 0x330e0,
+ 0x330ec, 0x3312c,
+ 0x33134, 0x33150,
+ 0x33158, 0x33158,
+ 0x33160, 0x3318c,
+ 0x3319c, 0x331ac,
+ 0x331c0, 0x331c0,
+ 0x331c8, 0x331d0,
+ 0x331d8, 0x331e0,
+ 0x331ec, 0x33290,
+ 0x33298, 0x332c4,
+ 0x332e4, 0x33390,
+ 0x33398, 0x333c4,
+ 0x333e4, 0x3342c,
+ 0x33434, 0x33450,
+ 0x33458, 0x33458,
+ 0x33460, 0x3348c,
+ 0x3349c, 0x334ac,
+ 0x334c0, 0x334c0,
+ 0x334c8, 0x334d0,
+ 0x334d8, 0x334e0,
+ 0x334ec, 0x3352c,
+ 0x33534, 0x33550,
+ 0x33558, 0x33558,
+ 0x33560, 0x3358c,
+ 0x3359c, 0x335ac,
+ 0x335c0, 0x335c0,
+ 0x335c8, 0x335d0,
+ 0x335d8, 0x335e0,
+ 0x335ec, 0x33690,
+ 0x33698, 0x336c4,
+ 0x336e4, 0x33790,
+ 0x33798, 0x337c4,
+ 0x337e4, 0x337fc,
+ 0x33814, 0x33814,
+ 0x33854, 0x33868,
+ 0x33880, 0x3388c,
+ 0x338c0, 0x338d0,
+ 0x338e8, 0x338ec,
+ 0x33900, 0x3392c,
+ 0x33934, 0x33950,
+ 0x33958, 0x33958,
+ 0x33960, 0x3398c,
+ 0x3399c, 0x339ac,
+ 0x339c0, 0x339c0,
+ 0x339c8, 0x339d0,
+ 0x339d8, 0x339e0,
+ 0x339ec, 0x33a90,
+ 0x33a98, 0x33ac4,
+ 0x33ae4, 0x33b10,
+ 0x33b24, 0x33b28,
+ 0x33b38, 0x33b50,
+ 0x33bf0, 0x33c10,
+ 0x33c24, 0x33c28,
+ 0x33c38, 0x33c50,
+ 0x33cf0, 0x33cfc,
+ 0x34000, 0x34030,
+ 0x34038, 0x34038,
+ 0x34040, 0x34040,
+ 0x34048, 0x34048,
+ 0x34050, 0x34050,
+ 0x3405c, 0x34060,
+ 0x34068, 0x34068,
+ 0x34070, 0x34070,
+ 0x34100, 0x34168,
+ 0x34190, 0x341a0,
+ 0x341a8, 0x341b8,
+ 0x341c4, 0x341c8,
+ 0x341d0, 0x341d0,
+ 0x34200, 0x34320,
+ 0x34400, 0x344b4,
+ 0x344c0, 0x3452c,
+ 0x34540, 0x3461c,
+ 0x34800, 0x348a0,
+ 0x348c0, 0x34908,
+ 0x34910, 0x349b8,
+ 0x34a00, 0x34a04,
+ 0x34a0c, 0x34a14,
+ 0x34a1c, 0x34a2c,
+ 0x34a44, 0x34a50,
+ 0x34a74, 0x34a74,
+ 0x34a7c, 0x34afc,
+ 0x34b08, 0x34c24,
+ 0x34d00, 0x34d14,
+ 0x34d1c, 0x34d3c,
+ 0x34d44, 0x34d4c,
+ 0x34d54, 0x34d74,
+ 0x34d7c, 0x34d7c,
+ 0x34de0, 0x34de0,
+ 0x34e00, 0x34ed4,
+ 0x34f00, 0x34fa4,
+ 0x34fc0, 0x34fc4,
+ 0x35000, 0x35004,
+ 0x35080, 0x350fc,
+ 0x35208, 0x35220,
+ 0x3523c, 0x35254,
+ 0x35300, 0x35300,
+ 0x35308, 0x3531c,
+ 0x35338, 0x3533c,
+ 0x35380, 0x35380,
+ 0x35388, 0x353a8,
+ 0x353b4, 0x353b4,
+ 0x35400, 0x35420,
+ 0x35438, 0x3543c,
+ 0x35480, 0x35480,
+ 0x354a8, 0x354a8,
+ 0x354b0, 0x354b4,
+ 0x354c8, 0x354d4,
+ 0x35a40, 0x35a4c,
+ 0x35af0, 0x35b20,
+ 0x35b38, 0x35b3c,
+ 0x35b80, 0x35b80,
+ 0x35ba8, 0x35ba8,
+ 0x35bb0, 0x35bb4,
+ 0x35bc8, 0x35bd4,
+ 0x36140, 0x3618c,
+ 0x361f0, 0x361f4,
+ 0x36200, 0x36200,
+ 0x36218, 0x36218,
+ 0x36400, 0x36400,
+ 0x36408, 0x3641c,
+ 0x36618, 0x36620,
+ 0x36664, 0x36664,
+ 0x366a8, 0x366a8,
+ 0x366ec, 0x366ec,
+ 0x36a00, 0x36abc,
+ 0x36b00, 0x36b38,
+ 0x36b40, 0x36b58,
+ 0x36b60, 0x36b78,
+ 0x36c00, 0x36c00,
+ 0x36c08, 0x36c3c,
+ 0x36e00, 0x36e2c,
+ 0x36f00, 0x36f2c,
+ 0x37000, 0x3702c,
+ 0x37034, 0x37050,
+ 0x37058, 0x37058,
+ 0x37060, 0x3708c,
+ 0x3709c, 0x370ac,
+ 0x370c0, 0x370c0,
+ 0x370c8, 0x370d0,
+ 0x370d8, 0x370e0,
+ 0x370ec, 0x3712c,
+ 0x37134, 0x37150,
+ 0x37158, 0x37158,
+ 0x37160, 0x3718c,
+ 0x3719c, 0x371ac,
+ 0x371c0, 0x371c0,
+ 0x371c8, 0x371d0,
+ 0x371d8, 0x371e0,
+ 0x371ec, 0x37290,
+ 0x37298, 0x372c4,
+ 0x372e4, 0x37390,
+ 0x37398, 0x373c4,
+ 0x373e4, 0x3742c,
+ 0x37434, 0x37450,
+ 0x37458, 0x37458,
+ 0x37460, 0x3748c,
+ 0x3749c, 0x374ac,
+ 0x374c0, 0x374c0,
+ 0x374c8, 0x374d0,
+ 0x374d8, 0x374e0,
+ 0x374ec, 0x3752c,
+ 0x37534, 0x37550,
+ 0x37558, 0x37558,
+ 0x37560, 0x3758c,
+ 0x3759c, 0x375ac,
+ 0x375c0, 0x375c0,
+ 0x375c8, 0x375d0,
+ 0x375d8, 0x375e0,
+ 0x375ec, 0x37690,
+ 0x37698, 0x376c4,
+ 0x376e4, 0x37790,
+ 0x37798, 0x377c4,
+ 0x377e4, 0x377fc,
+ 0x37814, 0x37814,
+ 0x37854, 0x37868,
+ 0x37880, 0x3788c,
+ 0x378c0, 0x378d0,
+ 0x378e8, 0x378ec,
+ 0x37900, 0x3792c,
+ 0x37934, 0x37950,
+ 0x37958, 0x37958,
+ 0x37960, 0x3798c,
+ 0x3799c, 0x379ac,
+ 0x379c0, 0x379c0,
+ 0x379c8, 0x379d0,
+ 0x379d8, 0x379e0,
+ 0x379ec, 0x37a90,
+ 0x37a98, 0x37ac4,
+ 0x37ae4, 0x37b10,
+ 0x37b24, 0x37b28,
+ 0x37b38, 0x37b50,
+ 0x37bf0, 0x37c10,
+ 0x37c24, 0x37c28,
+ 0x37c38, 0x37c50,
+ 0x37cf0, 0x37cfc,
+ 0x40040, 0x40040,
+ 0x40080, 0x40084,
+ 0x40100, 0x40100,
+ 0x40140, 0x401bc,
+ 0x40200, 0x40214,
+ 0x40228, 0x40228,
+ 0x40240, 0x40258,
+ 0x40280, 0x40280,
+ 0x40304, 0x40304,
+ 0x40330, 0x4033c,
+ 0x41304, 0x413c8,
+ 0x413d0, 0x413dc,
+ 0x413f0, 0x413f0,
+ 0x41400, 0x4140c,
+ 0x41414, 0x4141c,
+ 0x41480, 0x414d0,
+ 0x44000, 0x4407c,
+ 0x440c0, 0x441ac,
+ 0x441b4, 0x4427c,
+ 0x442c0, 0x443ac,
+ 0x443b4, 0x4447c,
+ 0x444c0, 0x445ac,
+ 0x445b4, 0x4467c,
+ 0x446c0, 0x447ac,
+ 0x447b4, 0x4487c,
+ 0x448c0, 0x449ac,
+ 0x449b4, 0x44a7c,
+ 0x44ac0, 0x44bac,
+ 0x44bb4, 0x44c7c,
+ 0x44cc0, 0x44dac,
+ 0x44db4, 0x44e7c,
+ 0x44ec0, 0x44fac,
+ 0x44fb4, 0x4507c,
+ 0x450c0, 0x451ac,
+ 0x451b4, 0x451fc,
+ 0x45800, 0x45804,
+ 0x45810, 0x45830,
+ 0x45840, 0x45860,
+ 0x45868, 0x45868,
+ 0x45880, 0x45884,
+ 0x458a0, 0x458b0,
+ 0x45a00, 0x45a04,
+ 0x45a10, 0x45a30,
+ 0x45a40, 0x45a60,
+ 0x45a68, 0x45a68,
+ 0x45a80, 0x45a84,
+ 0x45aa0, 0x45ab0,
+ 0x460c0, 0x460e4,
+ 0x47000, 0x4703c,
+ 0x47044, 0x4708c,
+ 0x47200, 0x47250,
+ 0x47400, 0x47408,
+ 0x47414, 0x47420,
+ 0x47600, 0x47618,
+ 0x47800, 0x47814,
+ 0x47820, 0x4782c,
+ 0x50000, 0x50084,
+ 0x50090, 0x500cc,
+ 0x50300, 0x50384,
+ 0x50400, 0x50400,
+ 0x50800, 0x50884,
+ 0x50890, 0x508cc,
+ 0x50b00, 0x50b84,
+ 0x50c00, 0x50c00,
+ 0x51000, 0x51020,
+ 0x51028, 0x510b0,
+ 0x51300, 0x51324,
+ };
+
+ u32 *buf_end = (u32 *)(buf + buf_size);
+ const unsigned int *reg_ranges;
+ int reg_ranges_size, range;
+ unsigned int chip_version = chip_id(adap);
+
+ /*
+ * Select the right set of register ranges to dump depending on the
+ * adapter chip type.
+ */
+ switch (chip_version) {
+ case CHELSIO_T4:
+ 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);
+ break;
+
+ case CHELSIO_T6:
+ reg_ranges = t6_reg_ranges;
+ reg_ranges_size = ARRAY_SIZE(t6_reg_ranges);
+ break;
+
+ default:
+ CH_ERR(adap,
+ "Unsupported chip version %d\n", chip_version);
+ return;
+ }
+
+ /*
+ * Clear the register buffer and insert the appropriate register
+ * values selected by the above register ranges.
+ */
+ memset(buf, 0, buf_size);
+ for (range = 0; range < reg_ranges_size; range += 2) {
+ unsigned int reg = reg_ranges[range];
+ unsigned int last_reg = reg_ranges[range + 1];
+ u32 *bufp = (u32 *)(buf + reg);
+
+ /*
+ * Iterate across the register range filling in the register
+ * buffer but don't write past the end of the register buffer.
+ */
+ while (reg <= last_reg && bufp < buf_end) {
+ *bufp++ = t4_read_reg(adap, reg);
+ reg += sizeof(u32);
+ }
+ }
+}
+
+/*
* Partial EEPROM Vital Product Data structure. Includes only the ID and
- * VPD-R header.
+ * VPD-R sections.
*/
struct t4_vpd_hdr {
u8 id_tag;
@@ -507,14 +2596,65 @@ struct t4_vpd_hdr {
/*
* EEPROM reads take a few tens of us while writes can take a bit over 5 ms.
*/
-#define EEPROM_MAX_RD_POLL 40
-#define EEPROM_MAX_WR_POLL 6
-#define EEPROM_STAT_ADDR 0x7bfc
-#define VPD_BASE 0x400
-#define VPD_BASE_OLD 0
-#define VPD_LEN 1024
+#define EEPROM_DELAY 10 /* 10us per poll spin */
+#define EEPROM_MAX_POLL 5000 /* x 5000 == 50ms */
+
+#define EEPROM_STAT_ADDR 0x7bfc
+#define VPD_BASE 0x400
+#define VPD_BASE_OLD 0
+#define VPD_LEN 1024
#define VPD_INFO_FLD_HDR_SIZE 3
-#define CHELSIO_VPD_UNIQUE_ID 0x82
+#define CHELSIO_VPD_UNIQUE_ID 0x82
+
+/*
+ * Small utility function to wait till any outstanding VPD Access is complete.
+ * We have a per-adapter state variable "VPD Busy" to indicate when we have a
+ * VPD Access in flight. This allows us to handle the problem of having a
+ * previous VPD Access time out and prevent an attempt to inject a new VPD
+ * Request before any in-flight VPD reguest has completed.
+ */
+static int t4_seeprom_wait(struct adapter *adapter)
+{
+ unsigned int base = adapter->params.pci.vpd_cap_addr;
+ int max_poll;
+
+ /*
+ * If no VPD Access is in flight, we can just return success right
+ * away.
+ */
+ if (!adapter->vpd_busy)
+ return 0;
+
+ /*
+ * Poll the VPD Capability Address/Flag register waiting for it
+ * to indicate that the operation is complete.
+ */
+ max_poll = EEPROM_MAX_POLL;
+ do {
+ u16 val;
+
+ udelay(EEPROM_DELAY);
+ t4_os_pci_read_cfg2(adapter, base + PCI_VPD_ADDR, &val);
+
+ /*
+ * If the operation is complete, mark the VPD as no longer
+ * busy and return success.
+ */
+ if ((val & PCI_VPD_ADDR_F) == adapter->vpd_flag) {
+ adapter->vpd_busy = 0;
+ return 0;
+ }
+ } while (--max_poll);
+
+ /*
+ * Failure! Note that we leave the VPD Busy status set in order to
+ * avoid pushing a new VPD Access request into the VPD Capability till
+ * the current operation eventually succeeds. It's a bug to issue a
+ * new request when an existing request is in flight and will result
+ * in corrupt hardware state.
+ */
+ return -ETIMEDOUT;
+}
/**
* t4_seeprom_read - read a serial EEPROM location
@@ -528,23 +2668,44 @@ struct t4_vpd_hdr {
*/
int t4_seeprom_read(struct adapter *adapter, u32 addr, u32 *data)
{
- u16 val;
- int attempts = EEPROM_MAX_RD_POLL;
unsigned int base = adapter->params.pci.vpd_cap_addr;
+ int ret;
+ /*
+ * VPD Accesses must alway be 4-byte aligned!
+ */
if (addr >= EEPROMVSIZE || (addr & 3))
return -EINVAL;
- t4_os_pci_write_cfg2(adapter, base + PCI_VPD_ADDR, (u16)addr);
- do {
- udelay(10);
- t4_os_pci_read_cfg2(adapter, base + PCI_VPD_ADDR, &val);
- } while (!(val & PCI_VPD_ADDR_F) && --attempts);
+ /*
+ * Wait for any previous operation which may still be in flight to
+ * complete.
+ */
+ ret = t4_seeprom_wait(adapter);
+ if (ret) {
+ CH_ERR(adapter, "VPD still busy from previous operation\n");
+ return ret;
+ }
- if (!(val & PCI_VPD_ADDR_F)) {
- CH_ERR(adapter, "reading EEPROM address 0x%x failed\n", addr);
- return -EIO;
+ /*
+ * Issue our new VPD Read request, mark the VPD as being busy and wait
+ * for our request to complete. If it doesn't complete, note the
+ * error and return it to our caller. Note that we do not reset the
+ * VPD Busy status!
+ */
+ t4_os_pci_write_cfg2(adapter, base + PCI_VPD_ADDR, (u16)addr);
+ adapter->vpd_busy = 1;
+ adapter->vpd_flag = PCI_VPD_ADDR_F;
+ ret = t4_seeprom_wait(adapter);
+ if (ret) {
+ CH_ERR(adapter, "VPD read of address %#x failed\n", addr);
+ return ret;
}
+
+ /*
+ * Grab the returned data, swizzle it into our endianess and
+ * return success.
+ */
t4_os_pci_read_cfg4(adapter, base + PCI_VPD_DATA, data);
*data = le32_to_cpu(*data);
return 0;
@@ -562,26 +2723,59 @@ int t4_seeprom_read(struct adapter *adapter, u32 addr, u32 *data)
*/
int t4_seeprom_write(struct adapter *adapter, u32 addr, u32 data)
{
- u16 val;
- int attempts = EEPROM_MAX_WR_POLL;
unsigned int base = adapter->params.pci.vpd_cap_addr;
+ int ret;
+ u32 stats_reg;
+ int max_poll;
+ /*
+ * VPD Accesses must alway be 4-byte aligned!
+ */
if (addr >= EEPROMVSIZE || (addr & 3))
return -EINVAL;
+ /*
+ * Wait for any previous operation which may still be in flight to
+ * complete.
+ */
+ ret = t4_seeprom_wait(adapter);
+ if (ret) {
+ CH_ERR(adapter, "VPD still busy from previous operation\n");
+ return ret;
+ }
+
+ /*
+ * Issue our new VPD Read request, mark the VPD as being busy and wait
+ * for our request to complete. If it doesn't complete, note the
+ * error and return it to our caller. Note that we do not reset the
+ * VPD Busy status!
+ */
t4_os_pci_write_cfg4(adapter, base + PCI_VPD_DATA,
cpu_to_le32(data));
t4_os_pci_write_cfg2(adapter, base + PCI_VPD_ADDR,
(u16)addr | PCI_VPD_ADDR_F);
+ adapter->vpd_busy = 1;
+ adapter->vpd_flag = 0;
+ ret = t4_seeprom_wait(adapter);
+ if (ret) {
+ CH_ERR(adapter, "VPD write of address %#x failed\n", addr);
+ return ret;
+ }
+
+ /*
+ * Reset PCI_VPD_DATA register after a transaction and wait for our
+ * request to complete. If it doesn't complete, return error.
+ */
+ t4_os_pci_write_cfg4(adapter, base + PCI_VPD_DATA, 0);
+ max_poll = EEPROM_MAX_POLL;
do {
- msleep(1);
- t4_os_pci_read_cfg2(adapter, base + PCI_VPD_ADDR, &val);
- } while ((val & PCI_VPD_ADDR_F) && --attempts);
+ udelay(EEPROM_DELAY);
+ t4_seeprom_read(adapter, EEPROM_STAT_ADDR, &stats_reg);
+ } while ((stats_reg & 0x1) && --max_poll);
+ if (!max_poll)
+ return -ETIMEDOUT;
- if (val & PCI_VPD_ADDR_F) {
- CH_ERR(adapter, "write to EEPROM address 0x%x failed\n", addr);
- return -EIO;
- }
+ /* Return success! */
return 0;
}
@@ -630,33 +2824,33 @@ int t4_seeprom_wp(struct adapter *adapter, int enable)
* get_vpd_keyword_val - Locates an information field keyword in the VPD
* @v: Pointer to buffered vpd data structure
* @kw: The keyword to search for
- *
+ *
* Returns the value of the information field keyword or
* -ENOENT otherwise.
*/
static int get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
{
- int i;
- unsigned int offset , len;
- const u8 *buf = &v->id_tag;
- const u8 *vpdr_len = &v->vpdr_tag;
- offset = sizeof(struct t4_vpd_hdr);
- len = (u16)vpdr_len[1] + ((u16)vpdr_len[2] << 8);
-
- if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
- return -ENOENT;
- }
+ int i;
+ unsigned int offset , len;
+ const u8 *buf = (const u8 *)v;
+ const u8 *vpdr_len = &v->vpdr_len[0];
+ offset = sizeof(struct t4_vpd_hdr);
+ len = (u16)vpdr_len[0] + ((u16)vpdr_len[1] << 8);
+
+ if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
+ return -ENOENT;
+ }
- for (i = offset; i + VPD_INFO_FLD_HDR_SIZE <= offset + len;) {
- if(memcmp(buf + i , kw , 2) == 0){
- i += VPD_INFO_FLD_HDR_SIZE;
- return i;
- }
+ for (i = offset; i + VPD_INFO_FLD_HDR_SIZE <= offset + len;) {
+ if(memcmp(buf + i , kw , 2) == 0){
+ i += VPD_INFO_FLD_HDR_SIZE;
+ return i;
+ }
- i += VPD_INFO_FLD_HDR_SIZE + buf[i+2];
- }
+ i += VPD_INFO_FLD_HDR_SIZE + buf[i+2];
+ }
- return -ENOENT;
+ return -ENOENT;
}
@@ -664,14 +2858,16 @@ static int get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
* get_vpd_params - read VPD parameters from VPD EEPROM
* @adapter: adapter to read
* @p: where to store the parameters
+ * @vpd: caller provided temporary space to read the VPD into
*
* Reads card parameters stored in VPD EEPROM.
*/
-static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
+static int get_vpd_params(struct adapter *adapter, struct vpd_params *p,
+ u8 *vpd)
{
int i, ret, addr;
int ec, sn, pn, na;
- u8 vpd[VPD_LEN], csum;
+ u8 csum;
const struct t4_vpd_hdr *v;
/*
@@ -679,31 +2875,43 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
* it at 0.
*/
ret = t4_seeprom_read(adapter, VPD_BASE, (u32 *)(vpd));
+ if (ret)
+ return (ret);
+
+ /*
+ * The VPD shall have a unique identifier specified by the PCI SIG.
+ * For chelsio adapters, the identifier is 0x82. The first byte of a VPD
+ * shall be CHELSIO_VPD_UNIQUE_ID (0x82). The VPD programming software
+ * is expected to automatically put this entry at the
+ * beginning of the VPD.
+ */
addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD;
- for (i = 0; i < sizeof(vpd); i += 4) {
+ for (i = 0; i < VPD_LEN; i += 4) {
ret = t4_seeprom_read(adapter, addr + i, (u32 *)(vpd + i));
if (ret)
return ret;
}
v = (const struct t4_vpd_hdr *)vpd;
-
+
#define FIND_VPD_KW(var,name) do { \
var = get_vpd_keyword_val(v , name); \
if (var < 0) { \
CH_ERR(adapter, "missing VPD keyword " name "\n"); \
return -EINVAL; \
} \
-} while (0)
+} while (0)
FIND_VPD_KW(i, "RV");
for (csum = 0; i >= 0; i--)
csum += vpd[i];
if (csum) {
- CH_ERR(adapter, "corrupted VPD EEPROM, actual csum %u\n", csum);
+ CH_ERR(adapter,
+ "corrupted VPD EEPROM, actual csum %u\n", csum);
return -EINVAL;
}
+
FIND_VPD_KW(ec, "EC");
FIND_VPD_KW(sn, "SN");
FIND_VPD_KW(pn, "PN");
@@ -729,16 +2937,16 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
/* serial flash and firmware constants and flash config file constants */
enum {
- SF_ATTEMPTS = 10, /* max retries for SF operations */
+ SF_ATTEMPTS = 10, /* max retries for SF operations */
/* flash command opcodes */
- SF_PROG_PAGE = 2, /* program page */
- SF_WR_DISABLE = 4, /* disable writes */
- SF_RD_STATUS = 5, /* read status register */
- SF_WR_ENABLE = 6, /* enable writes */
- SF_RD_DATA_FAST = 0xb, /* read flash */
- SF_RD_ID = 0x9f, /* read ID */
- SF_ERASE_SECTOR = 0xd8, /* erase sector */
+ SF_PROG_PAGE = 2, /* program page */
+ SF_WR_DISABLE = 4, /* disable writes */
+ SF_RD_STATUS = 5, /* read status register */
+ SF_WR_ENABLE = 6, /* enable writes */
+ SF_RD_DATA_FAST = 0xb, /* read flash */
+ SF_RD_ID = 0x9f, /* read ID */
+ SF_ERASE_SECTOR = 0xd8, /* erase sector */
};
/**
@@ -832,7 +3040,7 @@ static int flash_wait_op(struct adapter *adapter, int attempts, int delay)
* Read the specified number of 32-bit words from the serial flash.
* If @byte_oriented is set the read data is stored as a byte array
* (i.e., big-endian), otherwise as 32-bit words in the platform's
- * natural endianess.
+ * natural endianness.
*/
int t4_read_flash(struct adapter *adapter, unsigned int addr,
unsigned int nwords, u32 *data, int byte_oriented)
@@ -855,7 +3063,7 @@ int t4_read_flash(struct adapter *adapter, unsigned int addr,
if (ret)
return ret;
if (byte_oriented)
- *data = htonl(*data);
+ *data = (__force __u32)(cpu_to_be32(*data));
}
return 0;
}
@@ -870,10 +3078,10 @@ int t4_read_flash(struct adapter *adapter, unsigned int addr,
*
* Writes up to a page of data (256 bytes) to the serial flash starting
* at the given address. All the data must be written to the same page.
- * If @byte_oriented is set the write data is stored as byte stream
+ * If @byte_oriented is set the write data is stored as byte stream
* (i.e. matches what on disk), otherwise in big-endian.
*/
-static int t4_write_flash(struct adapter *adapter, unsigned int addr,
+int t4_write_flash(struct adapter *adapter, unsigned int addr,
unsigned int n, const u8 *data, int byte_oriented)
{
int ret;
@@ -895,7 +3103,7 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
val = (val << 8) + *data++;
if (!byte_oriented)
- val = htonl(val);
+ val = cpu_to_be32(val);
ret = sf1_write(adapter, c, c != left, 1, val);
if (ret)
@@ -914,8 +3122,9 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
return ret;
if (memcmp(data - n, (u8 *)buf + offset, n)) {
- CH_ERR(adapter, "failed to correctly write the flash page "
- "at %#x\n", addr);
+ CH_ERR(adapter,
+ "failed to correctly write the flash page at %#x\n",
+ addr);
return -EIO;
}
return 0;
@@ -934,8 +3143,8 @@ unlock:
*/
int t4_get_fw_version(struct adapter *adapter, u32 *vers)
{
- return t4_read_flash(adapter,
- FLASH_FW_START + offsetof(struct fw_hdr, fw_ver), 1,
+ return t4_read_flash(adapter, FLASH_FW_START +
+ offsetof(struct fw_hdr, fw_ver), 1,
vers, 0);
}
@@ -948,63 +3157,46 @@ int t4_get_fw_version(struct adapter *adapter, u32 *vers)
*/
int t4_get_tp_version(struct adapter *adapter, u32 *vers)
{
- return t4_read_flash(adapter, FLASH_FW_START + offsetof(struct fw_hdr,
- tp_microcode_ver),
+ return t4_read_flash(adapter, FLASH_FW_START +
+ offsetof(struct fw_hdr, tp_microcode_ver),
1, vers, 0);
}
/**
- * t4_check_fw_version - check if the FW is compatible with this driver
+ * t4_get_exprom_version - return the Expansion ROM version (if any)
* @adapter: the adapter
+ * @vers: where to place the version
*
- * Checks if an adapter's FW is compatible with the driver. Returns 0
- * if there's exact match, a negative error if the version could not be
- * read or there's a major version mismatch, and a positive value if the
- * expected major version is found but there's a minor version mismatch.
+ * Reads the Expansion ROM header from FLASH and returns the version
+ * number (if present) through the @vers return value pointer. We return
+ * this in the Firmware Version Format since it's convenient. Return
+ * 0 on success, -ENOENT if no Expansion ROM is present.
*/
-int t4_check_fw_version(struct adapter *adapter)
+int t4_get_exprom_version(struct adapter *adap, u32 *vers)
{
- int ret, major, minor, micro;
- int exp_major, exp_minor, exp_micro;
+ struct exprom_header {
+ unsigned char hdr_arr[16]; /* must start with 0x55aa */
+ unsigned char hdr_ver[4]; /* Expansion ROM version */
+ } *hdr;
+ u32 exprom_header_buf[DIV_ROUND_UP(sizeof(struct exprom_header),
+ sizeof(u32))];
+ int ret;
- ret = t4_get_fw_version(adapter, &adapter->params.fw_vers);
- if (!ret)
- ret = t4_get_tp_version(adapter, &adapter->params.tp_vers);
+ ret = t4_read_flash(adap, FLASH_EXP_ROM_START,
+ ARRAY_SIZE(exprom_header_buf), exprom_header_buf,
+ 0);
if (ret)
return ret;
- major = G_FW_HDR_FW_VER_MAJOR(adapter->params.fw_vers);
- minor = G_FW_HDR_FW_VER_MINOR(adapter->params.fw_vers);
- micro = G_FW_HDR_FW_VER_MICRO(adapter->params.fw_vers);
-
- switch (chip_id(adapter)) {
- case CHELSIO_T4:
- exp_major = T4FW_VERSION_MAJOR;
- exp_minor = T4FW_VERSION_MINOR;
- exp_micro = T4FW_VERSION_MICRO;
- break;
- case CHELSIO_T5:
- exp_major = T5FW_VERSION_MAJOR;
- exp_minor = T5FW_VERSION_MINOR;
- exp_micro = T5FW_VERSION_MICRO;
- break;
- default:
- CH_ERR(adapter, "Unsupported chip type, %x\n",
- chip_id(adapter));
- return -EINVAL;
- }
-
- if (major != exp_major) { /* major mismatch - fail */
- CH_ERR(adapter, "card FW has major version %u, driver wants "
- "%u\n", major, exp_major);
- return -EINVAL;
- }
-
- if (minor == exp_minor && micro == exp_micro)
- return 0; /* perfect match */
+ hdr = (struct exprom_header *)exprom_header_buf;
+ if (hdr->hdr_arr[0] != 0x55 || hdr->hdr_arr[1] != 0xaa)
+ return -ENOENT;
- /* Minor/micro version mismatch. Report it but often it's OK. */
- return 1;
+ *vers = (V_FW_HDR_FW_VER_MAJOR(hdr->hdr_ver[0]) |
+ V_FW_HDR_FW_VER_MINOR(hdr->hdr_ver[1]) |
+ V_FW_HDR_FW_VER_MICRO(hdr->hdr_ver[2]) |
+ V_FW_HDR_FW_VER_BUILD(hdr->hdr_ver[3]));
+ return 0;
}
/**
@@ -1015,17 +3207,21 @@ int t4_check_fw_version(struct adapter *adapter)
*
* Erases the sectors in the given inclusive range.
*/
-static int t4_flash_erase_sectors(struct adapter *adapter, int start, int end)
+int t4_flash_erase_sectors(struct adapter *adapter, int start, int end)
{
int ret = 0;
+ if (end >= adapter->params.sf_nsec)
+ return -EINVAL;
+
while (start <= end) {
if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 ||
(ret = sf1_write(adapter, 4, 0, 1,
SF_ERASE_SECTOR | (start << 8))) != 0 ||
(ret = flash_wait_op(adapter, 14, 500)) != 0) {
- CH_ERR(adapter, "erase of flash sector %d failed, "
- "error %d\n", start, ret);
+ CH_ERR(adapter,
+ "erase of flash sector %d failed, error %d\n",
+ start, ret);
break;
}
start++;
@@ -1054,67 +3250,30 @@ int t4_flash_cfg_addr(struct adapter *adapter)
return FLASH_CFG_START;
}
-/**
- * t4_load_cfg - download config file
- * @adap: the adapter
- * @cfg_data: the cfg text file to write
- * @size: text file size
- *
- * Write the supplied config text file to the card's serial flash.
+/*
+ * Return TRUE if the specified firmware matches the adapter. I.e. T4
+ * firmware for T4 adapters, T5 firmware for T5 adapters, etc. We go ahead
+ * and emit an error message for mismatched firmware to save our caller the
+ * effort ...
*/
-int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
+static int t4_fw_matches_chip(struct adapter *adap,
+ const struct fw_hdr *hdr)
{
- int ret, i, n, cfg_addr;
- unsigned int addr;
- unsigned int flash_cfg_start_sec;
- unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
-
- cfg_addr = t4_flash_cfg_addr(adap);
- if (cfg_addr < 0)
- return cfg_addr;
-
- addr = cfg_addr;
- flash_cfg_start_sec = addr / SF_SEC_SIZE;
-
- if (size > FLASH_CFG_MAX_SIZE) {
- CH_ERR(adap, "cfg file too large, max is %u bytes\n",
- FLASH_CFG_MAX_SIZE);
- return -EFBIG;
- }
-
- i = DIV_ROUND_UP(FLASH_CFG_MAX_SIZE, /* # of sectors spanned */
- sf_sec_size);
- ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec,
- flash_cfg_start_sec + i - 1);
/*
- * If size == 0 then we're simply erasing the FLASH sectors associated
- * with the on-adapter Firmware Configuration File.
+ * The expression below will return FALSE for any unsupported adapter
+ * which will keep us "honest" in the future ...
*/
- if (ret || size == 0)
- goto out;
-
- /* this will write to the flash up to SF_PAGE_SIZE at a time */
- for (i = 0; i< size; i+= SF_PAGE_SIZE) {
- if ( (size - i) < SF_PAGE_SIZE)
- n = size - i;
- else
- n = SF_PAGE_SIZE;
- ret = t4_write_flash(adap, addr, n, cfg_data, 1);
- if (ret)
- goto out;
-
- addr += SF_PAGE_SIZE;
- cfg_data += SF_PAGE_SIZE;
- }
-
-out:
- if (ret)
- CH_ERR(adap, "config file %s failed %d\n",
- (size == 0 ? "clear" : "download"), ret);
- return ret;
+ if ((is_t4(adap) && hdr->chip == FW_HDR_CHIP_T4) ||
+ (is_t5(adap) && hdr->chip == FW_HDR_CHIP_T5) ||
+ (is_t6(adap) && hdr->chip == FW_HDR_CHIP_T6))
+ return 1;
+
+ CH_ERR(adap,
+ "FW image (%d) is not suitable for this adapter (%d)\n",
+ hdr->chip, chip_id(adap));
+ return 0;
}
-
/**
* t4_load_fw - download firmware
* @adap: the adapter
@@ -1145,40 +3304,39 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
fw_start = FLASH_FW_START;
fw_size = FLASH_FW_MAX_SIZE;
}
+
if (!size) {
CH_ERR(adap, "FW image has no data\n");
return -EINVAL;
}
if (size & 511) {
- CH_ERR(adap, "FW image size not multiple of 512 bytes\n");
+ CH_ERR(adap,
+ "FW image size not multiple of 512 bytes\n");
return -EINVAL;
}
- if (ntohs(hdr->len512) * 512 != size) {
- CH_ERR(adap, "FW image size differs from size in FW header\n");
+ if ((unsigned int) be16_to_cpu(hdr->len512) * 512 != size) {
+ CH_ERR(adap,
+ "FW image size differs from size in FW header\n");
return -EINVAL;
}
if (size > fw_size) {
- CH_ERR(adap, "FW image too large, max is %u bytes\n", fw_size);
+ CH_ERR(adap, "FW image too large, max is %u bytes\n",
+ fw_size);
return -EFBIG;
}
- if ((is_t4(adap) && hdr->chip != FW_HDR_CHIP_T4) ||
- (is_t5(adap) && hdr->chip != FW_HDR_CHIP_T5)) {
- CH_ERR(adap,
- "FW image (%d) is not suitable for this adapter (%d)\n",
- hdr->chip, chip_id(adap));
+ if (!t4_fw_matches_chip(adap, hdr))
return -EINVAL;
- }
for (csum = 0, i = 0; i < size / sizeof(csum); i++)
- csum += ntohl(p[i]);
+ csum += be32_to_cpu(p[i]);
if (csum != 0xffffffff) {
- CH_ERR(adap, "corrupted firmware image, checksum %#x\n",
- csum);
+ CH_ERR(adap,
+ "corrupted firmware image, checksum %#x\n", csum);
return -EINVAL;
}
- i = DIV_ROUND_UP(size, sf_sec_size); /* # of sectors spanned */
+ i = DIV_ROUND_UP(size, sf_sec_size); /* # of sectors spanned */
ret = t4_flash_erase_sectors(adap, fw_start_sec, fw_start_sec + i - 1);
if (ret)
goto out;
@@ -1189,7 +3347,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
* first page with a bad version.
*/
memcpy(first_page, fw_data, SF_PAGE_SIZE);
- ((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff);
+ ((struct fw_hdr *)first_page)->fw_ver = cpu_to_be32(0xffffffff);
ret = t4_write_flash(adap, fw_start, SF_PAGE_SIZE, first_page, 1);
if (ret)
goto out;
@@ -1208,541 +3366,33 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver, 1);
out:
if (ret)
- CH_ERR(adap, "firmware download failed, error %d\n", ret);
- return ret;
-}
-
-/* BIOS boot headers */
-typedef struct pci_expansion_rom_header {
- u8 signature[2]; /* ROM Signature. Should be 0xaa55 */
- u8 reserved[22]; /* Reserved per processor Architecture data */
- u8 pcir_offset[2]; /* Offset to PCI Data Structure */
-} pci_exp_rom_header_t; /* PCI_EXPANSION_ROM_HEADER */
-
-/* Legacy PCI Expansion ROM Header */
-typedef struct legacy_pci_expansion_rom_header {
- u8 signature[2]; /* ROM Signature. Should be 0xaa55 */
- u8 size512; /* Current Image Size in units of 512 bytes */
- u8 initentry_point[4];
- u8 cksum; /* Checksum computed on the entire Image */
- u8 reserved[16]; /* Reserved */
- u8 pcir_offset[2]; /* Offset to PCI Data Struture */
-} legacy_pci_exp_rom_header_t; /* LEGACY_PCI_EXPANSION_ROM_HEADER */
-
-/* EFI PCI Expansion ROM Header */
-typedef struct efi_pci_expansion_rom_header {
- u8 signature[2]; // ROM signature. The value 0xaa55
- u8 initialization_size[2]; /* Units 512. Includes this header */
- u8 efi_signature[4]; /* Signature from EFI image header. 0x0EF1 */
- u8 efi_subsystem[2]; /* Subsystem value for EFI image header */
- u8 efi_machine_type[2]; /* Machine type from EFI image header */
- u8 compression_type[2]; /* Compression type. */
- /*
- * Compression type definition
- * 0x0: uncompressed
- * 0x1: Compressed
- * 0x2-0xFFFF: Reserved
- */
- u8 reserved[8]; /* Reserved */
- u8 efi_image_header_offset[2]; /* Offset to EFI Image */
- u8 pcir_offset[2]; /* Offset to PCI Data Structure */
-} efi_pci_exp_rom_header_t; /* EFI PCI Expansion ROM Header */
-
-/* PCI Data Structure Format */
-typedef struct pcir_data_structure { /* PCI Data Structure */
- u8 signature[4]; /* Signature. The string "PCIR" */
- u8 vendor_id[2]; /* Vendor Identification */
- u8 device_id[2]; /* Device Identification */
- u8 vital_product[2]; /* Pointer to Vital Product Data */
- u8 length[2]; /* PCIR Data Structure Length */
- u8 revision; /* PCIR Data Structure Revision */
- u8 class_code[3]; /* Class Code */
- u8 image_length[2]; /* Image Length. Multiple of 512B */
- u8 code_revision[2]; /* Revision Level of Code/Data */
- u8 code_type; /* Code Type. */
- /*
- * PCI Expansion ROM Code Types
- * 0x00: Intel IA-32, PC-AT compatible. Legacy
- * 0x01: Open Firmware standard for PCI. FCODE
- * 0x02: Hewlett-Packard PA RISC. HP reserved
- * 0x03: EFI Image. EFI
- * 0x04-0xFF: Reserved.
- */
- u8 indicator; /* Indicator. Identifies the last image in the ROM */
- u8 reserved[2]; /* Reserved */
-} pcir_data_t; /* PCI__DATA_STRUCTURE */
-
-/* BOOT constants */
-enum {
- BOOT_FLASH_BOOT_ADDR = 0x0,/* start address of boot image in flash */
- BOOT_SIGNATURE = 0xaa55, /* signature of BIOS boot ROM */
- BOOT_SIZE_INC = 512, /* image size measured in 512B chunks */
- BOOT_MIN_SIZE = sizeof(pci_exp_rom_header_t), /* basic header */
- BOOT_MAX_SIZE = 1024*BOOT_SIZE_INC, /* 1 byte * length increment */
- VENDOR_ID = 0x1425, /* Vendor ID */
- PCIR_SIGNATURE = 0x52494350 /* PCIR signature */
-};
-
-/*
- * modify_device_id - Modifies the device ID of the Boot BIOS image
- * @adatper: the device ID to write.
- * @boot_data: the boot image to modify.
- *
- * Write the supplied device ID to the boot BIOS image.
- */
-static void modify_device_id(int device_id, u8 *boot_data)
-{
- legacy_pci_exp_rom_header_t *header;
- pcir_data_t *pcir_header;
- u32 cur_header = 0;
-
- /*
- * Loop through all chained images and change the device ID's
- */
- while (1) {
- header = (legacy_pci_exp_rom_header_t *) &boot_data[cur_header];
- pcir_header = (pcir_data_t *) &boot_data[cur_header +
- le16_to_cpu(*(u16*)header->pcir_offset)];
-
- /*
- * Only modify the Device ID if code type is Legacy or HP.
- * 0x00: Okay to modify
- * 0x01: FCODE. Do not be modify
- * 0x03: Okay to modify
- * 0x04-0xFF: Do not modify
- */
- if (pcir_header->code_type == 0x00) {
- u8 csum = 0;
- int i;
-
- /*
- * Modify Device ID to match current adatper
- */
- *(u16*) pcir_header->device_id = device_id;
-
- /*
- * Set checksum temporarily to 0.
- * We will recalculate it later.
- */
- header->cksum = 0x0;
-
- /*
- * Calculate and update checksum
- */
- for (i = 0; i < (header->size512 * 512); i++)
- csum += (u8)boot_data[cur_header + i];
-
- /*
- * Invert summed value to create the checksum
- * Writing new checksum value directly to the boot data
- */
- boot_data[cur_header + 7] = -csum;
-
- } else if (pcir_header->code_type == 0x03) {
-
- /*
- * Modify Device ID to match current adatper
- */
- *(u16*) pcir_header->device_id = device_id;
-
- }
-
-
- /*
- * Check indicator element to identify if this is the last
- * image in the ROM.
- */
- if (pcir_header->indicator & 0x80)
- break;
-
- /*
- * Move header pointer up to the next image in the ROM.
- */
- cur_header += header->size512 * 512;
- }
-}
-
-/*
- * t4_load_boot - download boot flash
- * @adapter: the adapter
- * @boot_data: the boot image to write
- * @boot_addr: offset in flash to write boot_data
- * @size: image size
- *
- * Write the supplied boot image to the card's serial flash.
- * The boot image has the following sections: a 28-byte header and the
- * boot image.
- */
-int t4_load_boot(struct adapter *adap, u8 *boot_data,
- unsigned int boot_addr, unsigned int size)
-{
- pci_exp_rom_header_t *header;
- int pcir_offset ;
- pcir_data_t *pcir_header;
- int ret, addr;
- uint16_t device_id;
- unsigned int i;
- unsigned int boot_sector = boot_addr * 1024;
- unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
-
- /*
- * Make sure the boot image does not encroach on the firmware region
- */
- if ((boot_sector + size) >> 16 > FLASH_FW_START_SEC) {
- CH_ERR(adap, "boot image encroaching on firmware region\n");
- return -EFBIG;
- }
-
- /*
- * Number of sectors spanned
- */
- i = DIV_ROUND_UP(size ? size : FLASH_BOOTCFG_MAX_SIZE,
- sf_sec_size);
- ret = t4_flash_erase_sectors(adap, boot_sector >> 16,
- (boot_sector >> 16) + i - 1);
-
- /*
- * If size == 0 then we're simply erasing the FLASH sectors associated
- * with the on-adapter option ROM file
- */
- if (ret || (size == 0))
- goto out;
-
- /* Get boot header */
- header = (pci_exp_rom_header_t *)boot_data;
- pcir_offset = le16_to_cpu(*(u16 *)header->pcir_offset);
- /* PCIR Data Structure */
- pcir_header = (pcir_data_t *) &boot_data[pcir_offset];
-
- /*
- * Perform some primitive sanity testing to avoid accidentally
- * writing garbage over the boot sectors. We ought to check for
- * more but it's not worth it for now ...
- */
- if (size < BOOT_MIN_SIZE || size > BOOT_MAX_SIZE) {
- CH_ERR(adap, "boot image too small/large\n");
- return -EFBIG;
- }
-
- /*
- * Check BOOT ROM header signature
- */
- if (le16_to_cpu(*(u16*)header->signature) != BOOT_SIGNATURE ) {
- CH_ERR(adap, "Boot image missing signature\n");
- return -EINVAL;
- }
-
- /*
- * Check PCI header signature
- */
- if (le32_to_cpu(*(u32*)pcir_header->signature) != PCIR_SIGNATURE) {
- CH_ERR(adap, "PCI header missing signature\n");
- return -EINVAL;
- }
-
- /*
- * Check Vendor ID matches Chelsio ID
- */
- if (le16_to_cpu(*(u16*)pcir_header->vendor_id) != VENDOR_ID) {
- CH_ERR(adap, "Vendor ID missing signature\n");
- return -EINVAL;
- }
-
- /*
- * Retrieve adapter's device ID
- */
- t4_os_pci_read_cfg2(adap, PCI_DEVICE_ID, &device_id);
- /* Want to deal with PF 0 so I strip off PF 4 indicator */
- device_id = (device_id & 0xff) | 0x4000;
-
- /*
- * Check PCIE Device ID
- */
- if (le16_to_cpu(*(u16*)pcir_header->device_id) != device_id) {
- /*
- * Change the device ID in the Boot BIOS image to match
- * the Device ID of the current adapter.
- */
- modify_device_id(device_id, boot_data);
- }
-
- /*
- * Skip over the first SF_PAGE_SIZE worth of data and write it after
- * we finish copying the rest of the boot image. This will ensure
- * that the BIOS boot header will only be written if the boot image
- * was written in full.
- */
- addr = boot_sector;
- for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
- addr += SF_PAGE_SIZE;
- boot_data += SF_PAGE_SIZE;
- ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, boot_data, 0);
- if (ret)
- goto out;
- }
-
- ret = t4_write_flash(adap, boot_sector, SF_PAGE_SIZE, boot_data, 0);
-
-out:
- if (ret)
- CH_ERR(adap, "boot image download failed, error %d\n", ret);
+ CH_ERR(adap, "firmware download failed, error %d\n",
+ ret);
return ret;
}
/**
- * t4_read_cimq_cfg - read CIM queue configuration
+ * t4_fwcache - firmware cache operation
* @adap: the adapter
- * @base: holds the queue base addresses in bytes
- * @size: holds the queue sizes in bytes
- * @thres: holds the queue full thresholds in bytes
- *
- * Returns the current configuration of the CIM queues, starting with
- * the IBQs, then the OBQs.
+ * @op : the operation (flush or flush and invalidate)
*/
-void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres)
+int t4_fwcache(struct adapter *adap, enum fw_params_param_dev_fwcache op)
{
- unsigned int i, v;
- int cim_num_obq = is_t4(adap) ? CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
-
- for (i = 0; i < CIM_NUM_IBQ; i++) {
- t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_IBQSELECT |
- V_QUENUMSELECT(i));
- v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
- *base++ = G_CIMQBASE(v) * 256; /* value is in 256-byte units */
- *size++ = G_CIMQSIZE(v) * 256; /* value is in 256-byte units */
- *thres++ = G_QUEFULLTHRSH(v) * 8; /* 8-byte unit */
- }
- for (i = 0; i < cim_num_obq; i++) {
- t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
- V_QUENUMSELECT(i));
- v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
- *base++ = G_CIMQBASE(v) * 256; /* value is in 256-byte units */
- *size++ = G_CIMQSIZE(v) * 256; /* value is in 256-byte units */
- }
-}
-
-/**
- * t4_read_cim_ibq - read the contents of a CIM inbound queue
- * @adap: the adapter
- * @qid: the queue index
- * @data: where to store the queue contents
- * @n: capacity of @data in 32-bit words
- *
- * Reads the contents of the selected CIM queue starting at address 0 up
- * to the capacity of @data. @n must be a multiple of 4. Returns < 0 on
- * error and the number of 32-bit words actually read on success.
- */
-int t4_read_cim_ibq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
-{
- int i, err;
- unsigned int addr;
- const unsigned int nwords = CIM_IBQ_SIZE * 4;
-
- if (qid > 5 || (n & 3))
- return -EINVAL;
-
- addr = qid * nwords;
- if (n > nwords)
- n = nwords;
-
- for (i = 0; i < n; i++, addr++) {
- t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, V_IBQDBGADDR(addr) |
- F_IBQDBGEN);
- /*
- * It might take 3-10ms before the IBQ debug read access is
- * allowed. Wait for 1 Sec with a delay of 1 usec.
- */
- err = t4_wait_op_done(adap, A_CIM_IBQ_DBG_CFG, F_IBQDBGBUSY, 0,
- 1000000, 1);
- if (err)
- return err;
- *data++ = t4_read_reg(adap, A_CIM_IBQ_DBG_DATA);
- }
- t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, 0);
- return i;
-}
-
-/**
- * t4_read_cim_obq - read the contents of a CIM outbound queue
- * @adap: the adapter
- * @qid: the queue index
- * @data: where to store the queue contents
- * @n: capacity of @data in 32-bit words
- *
- * Reads the contents of the selected CIM queue starting at address 0 up
- * to the capacity of @data. @n must be a multiple of 4. Returns < 0 on
- * error and the number of 32-bit words actually read on success.
- */
-int t4_read_cim_obq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
-{
- int i, err;
- unsigned int addr, v, nwords;
- int cim_num_obq = is_t4(adap) ? CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
-
- if (qid >= cim_num_obq || (n & 3))
- return -EINVAL;
-
- t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
- V_QUENUMSELECT(qid));
- v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
-
- addr = G_CIMQBASE(v) * 64; /* muliple of 256 -> muliple of 4 */
- nwords = G_CIMQSIZE(v) * 64; /* same */
- if (n > nwords)
- n = nwords;
-
- for (i = 0; i < n; i++, addr++) {
- t4_write_reg(adap, A_CIM_OBQ_DBG_CFG, V_OBQDBGADDR(addr) |
- F_OBQDBGEN);
- err = t4_wait_op_done(adap, A_CIM_OBQ_DBG_CFG, F_OBQDBGBUSY, 0,
- 2, 1);
- if (err)
- return err;
- *data++ = t4_read_reg(adap, A_CIM_OBQ_DBG_DATA);
- }
- t4_write_reg(adap, A_CIM_OBQ_DBG_CFG, 0);
- return i;
-}
-
-enum {
- CIM_QCTL_BASE = 0,
- CIM_CTL_BASE = 0x2000,
- CIM_PBT_ADDR_BASE = 0x2800,
- CIM_PBT_LRF_BASE = 0x3000,
- CIM_PBT_DATA_BASE = 0x3800
-};
-
-/**
- * t4_cim_read - read a block from CIM internal address space
- * @adap: the adapter
- * @addr: the start address within the CIM address space
- * @n: number of words to read
- * @valp: where to store the result
- *
- * Reads a block of 4-byte words from the CIM intenal address space.
- */
-int t4_cim_read(struct adapter *adap, unsigned int addr, unsigned int n,
- unsigned int *valp)
-{
- int ret = 0;
-
- if (t4_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY)
- return -EBUSY;
-
- for ( ; !ret && n--; addr += 4) {
- t4_write_reg(adap, A_CIM_HOST_ACC_CTRL, addr);
- ret = t4_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY,
- 0, 5, 2);
- if (!ret)
- *valp++ = t4_read_reg(adap, A_CIM_HOST_ACC_DATA);
- }
- return ret;
-}
-
-/**
- * t4_cim_write - write a block into CIM internal address space
- * @adap: the adapter
- * @addr: the start address within the CIM address space
- * @n: number of words to write
- * @valp: set of values to write
- *
- * Writes a block of 4-byte words into the CIM intenal address space.
- */
-int t4_cim_write(struct adapter *adap, unsigned int addr, unsigned int n,
- const unsigned int *valp)
-{
- int ret = 0;
-
- if (t4_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY)
- return -EBUSY;
-
- for ( ; !ret && n--; addr += 4) {
- t4_write_reg(adap, A_CIM_HOST_ACC_DATA, *valp++);
- t4_write_reg(adap, A_CIM_HOST_ACC_CTRL, addr | F_HOSTWRITE);
- ret = t4_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY,
- 0, 5, 2);
- }
- return ret;
-}
-
-static int t4_cim_write1(struct adapter *adap, unsigned int addr, unsigned int val)
-{
- return t4_cim_write(adap, addr, 1, &val);
-}
-
-/**
- * t4_cim_ctl_read - read a block from CIM control region
- * @adap: the adapter
- * @addr: the start address within the CIM control region
- * @n: number of words to read
- * @valp: where to store the result
- *
- * Reads a block of 4-byte words from the CIM control region.
- */
-int t4_cim_ctl_read(struct adapter *adap, unsigned int addr, unsigned int n,
- unsigned int *valp)
-{
- return t4_cim_read(adap, addr + CIM_CTL_BASE, n, valp);
-}
-
-/**
- * t4_cim_read_la - read CIM LA capture buffer
- * @adap: the adapter
- * @la_buf: where to store the LA data
- * @wrptr: the HW write pointer within the capture buffer
- *
- * Reads the contents of the CIM LA buffer with the most recent entry at
- * the end of the returned data and with the entry at @wrptr first.
- * We try to leave the LA in the running state we find it in.
- */
-int t4_cim_read_la(struct adapter *adap, u32 *la_buf, unsigned int *wrptr)
-{
- int i, ret;
- unsigned int cfg, val, idx;
-
- ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &cfg);
- if (ret)
- return ret;
-
- if (cfg & F_UPDBGLAEN) { /* LA is running, freeze it */
- ret = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG, 0);
- if (ret)
- return ret;
- }
-
- ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &val);
- if (ret)
- goto restart;
+ struct fw_params_cmd c;
- idx = G_UPDBGLAWRPTR(val);
- if (wrptr)
- *wrptr = idx;
+ memset(&c, 0, sizeof(c));
+ c.op_to_vfn =
+ cpu_to_be32(V_FW_CMD_OP(FW_PARAMS_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+ V_FW_PARAMS_CMD_PFN(adap->pf) |
+ V_FW_PARAMS_CMD_VFN(0));
+ c.retval_len16 = cpu_to_be32(FW_LEN16(c));
+ c.param[0].mnem =
+ cpu_to_be32(V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FWCACHE));
+ c.param[0].val = (__force __be32)op;
- for (i = 0; i < adap->params.cim_la_size; i++) {
- ret = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG,
- V_UPDBGLARDPTR(idx) | F_UPDBGLARDEN);
- if (ret)
- break;
- ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &val);
- if (ret)
- break;
- if (val & F_UPDBGLARDEN) {
- ret = -ETIMEDOUT;
- break;
- }
- ret = t4_cim_read(adap, A_UP_UP_DBG_LA_DATA, 1, &la_buf[i]);
- if (ret)
- break;
- idx = (idx + 1) & M_UPDBGLARDPTR;
- }
-restart:
- if (cfg & F_UPDBGLAEN) {
- int r = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG,
- cfg & ~F_UPDBGLARDEN);
- if (!ret)
- ret = r;
- }
- return ret;
+ return t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), NULL);
}
void t4_cim_read_pif_la(struct adapter *adap, u32 *pif_req, u32 *pif_rsp,
@@ -1800,53 +3450,6 @@ void t4_cim_read_ma_la(struct adapter *adap, u32 *ma_req, u32 *ma_rsp)
t4_write_reg(adap, A_CIM_DEBUGCFG, cfg);
}
-/**
- * t4_tp_read_la - read TP LA capture buffer
- * @adap: the adapter
- * @la_buf: where to store the LA data
- * @wrptr: the HW write pointer within the capture buffer
- *
- * Reads the contents of the TP LA buffer with the most recent entry at
- * the end of the returned data and with the entry at @wrptr first.
- * We leave the LA in the running state we find it in.
- */
-void t4_tp_read_la(struct adapter *adap, u64 *la_buf, unsigned int *wrptr)
-{
- bool last_incomplete;
- unsigned int i, cfg, val, idx;
-
- cfg = t4_read_reg(adap, A_TP_DBG_LA_CONFIG) & 0xffff;
- if (cfg & F_DBGLAENABLE) /* freeze LA */
- t4_write_reg(adap, A_TP_DBG_LA_CONFIG,
- adap->params.tp.la_mask | (cfg ^ F_DBGLAENABLE));
-
- val = t4_read_reg(adap, A_TP_DBG_LA_CONFIG);
- idx = G_DBGLAWPTR(val);
- last_incomplete = G_DBGLAMODE(val) >= 2 && (val & F_DBGLAWHLF) == 0;
- if (last_incomplete)
- idx = (idx + 1) & M_DBGLARPTR;
- if (wrptr)
- *wrptr = idx;
-
- val &= 0xffff;
- val &= ~V_DBGLARPTR(M_DBGLARPTR);
- val |= adap->params.tp.la_mask;
-
- for (i = 0; i < TPLA_SIZE; i++) {
- t4_write_reg(adap, A_TP_DBG_LA_CONFIG, V_DBGLARPTR(idx) | val);
- la_buf[i] = t4_read_reg64(adap, A_TP_DBG_LA_DATAL);
- idx = (idx + 1) & M_DBGLARPTR;
- }
-
- /* Wipe out last entry if it isn't valid */
- if (last_incomplete)
- la_buf[TPLA_SIZE - 1] = ~0ULL;
-
- if (cfg & F_DBGLAENABLE) /* restore running state */
- t4_write_reg(adap, A_TP_DBG_LA_CONFIG,
- cfg | adap->params.tp.la_mask);
-}
-
void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
{
unsigned int i, j;
@@ -1867,7 +3470,7 @@ void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
FW_PORT_CAP_SPEED_100G | FW_PORT_CAP_ANEG)
/**
- * t4_link_start - apply link configuration to MAC/PHY
+ * t4_link_l1cfg - apply link configuration to MAC/PHY
* @phy: the PHY to setup
* @mac: the MAC to setup
* @lc: the requested link configuration
@@ -1879,7 +3482,7 @@ void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
* - If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
* otherwise do it later based on the outcome of auto-negotiation.
*/
-int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port,
+int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
struct link_config *lc)
{
struct fw_port_cmd c;
@@ -1892,19 +3495,22 @@ int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port,
fc |= FW_PORT_CAP_FC_TX;
memset(&c, 0, sizeof(c));
- c.op_to_portid = htonl(V_FW_CMD_OP(FW_PORT_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_PORT_CMD_PORTID(port));
- c.action_to_len16 = htonl(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
- FW_LEN16(c));
+ c.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
+ V_FW_PORT_CMD_PORTID(port));
+ c.action_to_len16 =
+ cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
+ FW_LEN16(c));
if (!(lc->supported & FW_PORT_CAP_ANEG)) {
- c.u.l1cfg.rcap = htonl((lc->supported & ADVERT_MASK) | fc);
+ c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) |
+ fc);
lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
} else if (lc->autoneg == AUTONEG_DISABLE) {
- c.u.l1cfg.rcap = htonl(lc->requested_speed | fc | mdi);
+ c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc | mdi);
lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
} else
- c.u.l1cfg.rcap = htonl(lc->advertising | fc | mdi);
+ c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc | mdi);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -1922,19 +3528,24 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
struct fw_port_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_portid = htonl(V_FW_CMD_OP(FW_PORT_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_PORT_CMD_PORTID(port));
- c.action_to_len16 = htonl(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
- FW_LEN16(c));
- c.u.l1cfg.rcap = htonl(FW_PORT_CAP_ANEG);
+ c.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
+ V_FW_PORT_CMD_PORTID(port));
+ c.action_to_len16 =
+ cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
+ FW_LEN16(c));
+ c.u.l1cfg.rcap = cpu_to_be32(FW_PORT_CAP_ANEG);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
+typedef void (*int_handler_t)(struct adapter *adap);
+
struct intr_info {
- unsigned int mask; /* bits to check in interrupt status */
- const char *msg; /* message to print or NULL */
- short stat_idx; /* stat counter to increment or -1 */
- unsigned short fatal; /* whether the condition reported is fatal */
+ unsigned int mask; /* bits to check in interrupt status */
+ const char *msg; /* message to print or NULL */
+ short stat_idx; /* stat counter to increment or -1 */
+ unsigned short fatal; /* whether the condition reported is fatal */
+ int_handler_t int_handler; /* platform-specific int handler */
};
/**
@@ -1945,7 +3556,7 @@ struct intr_info {
*
* A table driven interrupt handler that applies a set of masks to an
* interrupt status word and performs the corresponding actions if the
- * interrupts described by the mask have occured. The actions include
+ * interrupts described by the mask have occurred. The actions include
* optionally emitting a warning or alert message. The table is terminated
* by an entry specifying mask 0. Returns the number of fatal interrupt
* conditions.
@@ -1962,15 +3573,17 @@ static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg,
continue;
if (acts->fatal) {
fatal++;
- CH_ALERT(adapter, "%s (0x%x)\n",
- acts->msg, status & acts->mask);
+ CH_ALERT(adapter, "%s (0x%x)\n", acts->msg,
+ status & acts->mask);
} else if (acts->msg)
- CH_WARN_RATELIMIT(adapter, "%s (0x%x)\n",
- acts->msg, status & acts->mask);
+ CH_WARN_RATELIMIT(adapter, "%s (0x%x)\n", acts->msg,
+ status & acts->mask);
+ if (acts->int_handler)
+ acts->int_handler(adapter);
mask |= acts->mask;
}
status &= mask;
- if (status) /* clear processed interrupts */
+ if (status) /* clear processed interrupts */
t4_write_reg(adapter, reg, status);
return fatal;
}
@@ -1980,7 +3593,7 @@ static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg,
*/
static void pcie_intr_handler(struct adapter *adapter)
{
- static struct intr_info sysbus_intr_info[] = {
+ static const struct intr_info sysbus_intr_info[] = {
{ F_RNPP, "RXNP array parity error", -1, 1 },
{ F_RPCP, "RXPC array parity error", -1, 1 },
{ F_RCIP, "RXCIF array parity error", -1, 1 },
@@ -1988,7 +3601,7 @@ static void pcie_intr_handler(struct adapter *adapter)
{ F_RFTP, "RXFT array parity error", -1, 1 },
{ 0 }
};
- static struct intr_info pcie_port_intr_info[] = {
+ static const struct intr_info pcie_port_intr_info[] = {
{ F_TPCP, "TXPC array parity error", -1, 1 },
{ F_TNPP, "TXNP array parity error", -1, 1 },
{ F_TFTP, "TXFT array parity error", -1, 1 },
@@ -2000,7 +3613,7 @@ static void pcie_intr_handler(struct adapter *adapter)
{ F_TDUE, "Tx uncorrectable data error", -1, 1 },
{ 0 }
};
- static struct intr_info pcie_intr_info[] = {
+ static const struct intr_info pcie_intr_info[] = {
{ F_MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
{ F_MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
{ F_MSIDATAPERR, "MSI data parity error", -1, 1 },
@@ -2035,7 +3648,7 @@ static void pcie_intr_handler(struct adapter *adapter)
{ 0 }
};
- static struct intr_info t5_pcie_intr_info[] = {
+ static const struct intr_info t5_pcie_intr_info[] = {
{ F_MSTGRPPERR, "Master Response Read Queue parity error",
-1, 1 },
{ F_MSTTIMEOUTPERR, "Master Timeout FIFO parity error", -1, 1 },
@@ -2080,13 +3693,13 @@ static void pcie_intr_handler(struct adapter *adapter)
if (is_t4(adapter))
fat = t4_handle_intr_status(adapter,
- A_PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
- sysbus_intr_info) +
- t4_handle_intr_status(adapter,
- A_PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
- pcie_port_intr_info) +
- t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
- pcie_intr_info);
+ A_PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+ sysbus_intr_info) +
+ t4_handle_intr_status(adapter,
+ A_PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+ pcie_port_intr_info) +
+ t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
+ pcie_intr_info);
else
fat = t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
t5_pcie_intr_info);
@@ -2099,7 +3712,7 @@ static void pcie_intr_handler(struct adapter *adapter)
*/
static void tp_intr_handler(struct adapter *adapter)
{
- static struct intr_info tp_intr_info[] = {
+ static const struct intr_info tp_intr_info[] = {
{ 0x3fffffff, "TP parity error", -1, 1 },
{ F_FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1 },
{ 0 }
@@ -2117,13 +3730,13 @@ static void sge_intr_handler(struct adapter *adapter)
u64 v;
u32 err;
- static struct intr_info sge_intr_info[] = {
+ static const struct intr_info sge_intr_info[] = {
{ F_ERR_CPL_EXCEED_IQE_SIZE,
"SGE received CPL exceeding IQE size", -1, 1 },
{ F_ERR_INVALID_CIDX_INC,
"SGE GTS CIDX increment too large", -1, 0 },
{ F_ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
- { F_ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
+ { F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full },
{ F_ERR_DATA_CPL_ON_HIGH_QID1 | F_ERR_DATA_CPL_ON_HIGH_QID0,
"SGE IQID > 1023 received CPL for FL", -1, 0 },
{ F_ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
@@ -2136,23 +3749,47 @@ static void sge_intr_handler(struct adapter *adapter)
0 },
{ F_ERR_ING_CTXT_PRIO,
"SGE too many priority ingress contexts", -1, 0 },
- { F_ERR_EGR_CTXT_PRIO,
- "SGE too many priority egress contexts", -1, 0 },
{ F_INGRESS_SIZE_ERR, "SGE illegal ingress QID", -1, 0 },
{ F_EGRESS_SIZE_ERR, "SGE illegal egress QID", -1, 0 },
{ 0 }
};
+ static const struct intr_info t4t5_sge_intr_info[] = {
+ { F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped },
+ { F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full },
+ { F_ERR_EGR_CTXT_PRIO,
+ "SGE too many priority egress contexts", -1, 0 },
+ { 0 }
+ };
+
+ /*
+ * For now, treat below interrupts as fatal so that we disable SGE and
+ * get better debug */
+ static const struct intr_info t6_sge_intr_info[] = {
+ { F_ERR_PCIE_ERROR0 | F_ERR_PCIE_ERROR1,
+ "SGE PCIe error for a DBP thread", -1, 1 },
+ { F_FATAL_WRE_LEN,
+ "SGE Actual WRE packet is less than advertized length",
+ -1, 1 },
+ { 0 }
+ };
+
v = (u64)t4_read_reg(adapter, A_SGE_INT_CAUSE1) |
- ((u64)t4_read_reg(adapter, A_SGE_INT_CAUSE2) << 32);
+ ((u64)t4_read_reg(adapter, A_SGE_INT_CAUSE2) << 32);
if (v) {
CH_ALERT(adapter, "SGE parity error (%#llx)\n",
- (unsigned long long)v);
+ (unsigned long long)v);
t4_write_reg(adapter, A_SGE_INT_CAUSE1, v);
t4_write_reg(adapter, A_SGE_INT_CAUSE2, v >> 32);
}
v |= t4_handle_intr_status(adapter, A_SGE_INT_CAUSE3, sge_intr_info);
+ if (chip_id(adapter) <= CHELSIO_T5)
+ v |= t4_handle_intr_status(adapter, A_SGE_INT_CAUSE3,
+ t4t5_sge_intr_info);
+ else
+ v |= t4_handle_intr_status(adapter, A_SGE_INT_CAUSE3,
+ t6_sge_intr_info);
err = t4_read_reg(adapter, A_SGE_ERROR_STATS);
if (err & F_ERROR_QID_VALID) {
@@ -2177,7 +3814,7 @@ static void sge_intr_handler(struct adapter *adapter)
*/
static void cim_intr_handler(struct adapter *adapter)
{
- static struct intr_info cim_intr_info[] = {
+ static const struct intr_info cim_intr_info[] = {
{ F_PREFDROPINT, "CIM control register prefetch drop", -1, 1 },
{ CIM_OBQ_INTR, "CIM OBQ parity error", -1, 1 },
{ CIM_IBQ_INTR, "CIM IBQ parity error", -1, 1 },
@@ -2187,7 +3824,7 @@ static void cim_intr_handler(struct adapter *adapter)
{ F_TIEQOUTPARERRINT, "CIM TIEQ incoming parity error", -1, 1 },
{ 0 }
};
- static struct intr_info cim_upintr_info[] = {
+ static const struct intr_info cim_upintr_info[] = {
{ F_RSVDSPACEINT, "CIM reserved space access", -1, 1 },
{ F_ILLTRANSINT, "CIM illegal transaction", -1, 1 },
{ F_ILLWRINT, "CIM illegal write", -1, 1 },
@@ -2236,7 +3873,7 @@ static void cim_intr_handler(struct adapter *adapter)
*/
static void ulprx_intr_handler(struct adapter *adapter)
{
- static struct intr_info ulprx_intr_info[] = {
+ static const struct intr_info ulprx_intr_info[] = {
{ F_CAUSE_CTX_1, "ULPRX channel 1 context error", -1, 1 },
{ F_CAUSE_CTX_0, "ULPRX channel 0 context error", -1, 1 },
{ 0x7fffff, "ULPRX parity error", -1, 1 },
@@ -2252,7 +3889,7 @@ static void ulprx_intr_handler(struct adapter *adapter)
*/
static void ulptx_intr_handler(struct adapter *adapter)
{
- static struct intr_info ulptx_intr_info[] = {
+ static const struct intr_info ulptx_intr_info[] = {
{ F_PBL_BOUND_ERR_CH3, "ULPTX channel 3 PBL out of bounds", -1,
0 },
{ F_PBL_BOUND_ERR_CH2, "ULPTX channel 2 PBL out of bounds", -1,
@@ -2274,7 +3911,7 @@ static void ulptx_intr_handler(struct adapter *adapter)
*/
static void pmtx_intr_handler(struct adapter *adapter)
{
- static struct intr_info pmtx_intr_info[] = {
+ static const struct intr_info pmtx_intr_info[] = {
{ F_PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large", -1, 1 },
{ F_PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large", -1, 1 },
{ F_PCMD_LEN_OVFL2, "PMTX channel 2 pcmd too large", -1, 1 },
@@ -2297,7 +3934,7 @@ static void pmtx_intr_handler(struct adapter *adapter)
*/
static void pmrx_intr_handler(struct adapter *adapter)
{
- static struct intr_info pmrx_intr_info[] = {
+ static const struct intr_info pmrx_intr_info[] = {
{ F_ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1 },
{ 0x3ffff0, "PMRX framing error", -1, 1 },
{ F_OCSPI_PAR_ERROR, "PMRX ocspi parity error", -1, 1 },
@@ -2317,7 +3954,7 @@ static void pmrx_intr_handler(struct adapter *adapter)
*/
static void cplsw_intr_handler(struct adapter *adapter)
{
- static struct intr_info cplsw_intr_info[] = {
+ static const struct intr_info cplsw_intr_info[] = {
{ F_CIM_OP_MAP_PERR, "CPLSW CIM op_map parity error", -1, 1 },
{ F_CIM_OVFL_ERROR, "CPLSW CIM overflow", -1, 1 },
{ F_TP_FRAMING_ERROR, "CPLSW TP framing error", -1, 1 },
@@ -2336,7 +3973,8 @@ static void cplsw_intr_handler(struct adapter *adapter)
*/
static void le_intr_handler(struct adapter *adap)
{
- static struct intr_info le_intr_info[] = {
+ unsigned int chip_ver = chip_id(adap);
+ static const struct intr_info le_intr_info[] = {
{ F_LIPMISS, "LE LIP miss", -1, 0 },
{ F_LIP0, "LE 0 LIP error", -1, 0 },
{ F_PARITYERR, "LE parity error", -1, 1 },
@@ -2345,7 +3983,18 @@ static void le_intr_handler(struct adapter *adap)
{ 0 }
};
- if (t4_handle_intr_status(adap, A_LE_DB_INT_CAUSE, le_intr_info))
+ static const struct intr_info t6_le_intr_info[] = {
+ { F_T6_LIPMISS, "LE LIP miss", -1, 0 },
+ { F_T6_LIP0, "LE 0 LIP error", -1, 0 },
+ { F_TCAMINTPERR, "LE parity error", -1, 1 },
+ { F_T6_UNKNOWNCMD, "LE unknown command", -1, 1 },
+ { F_SSRAMINTPERR, "LE request queue parity error", -1, 1 },
+ { 0 }
+ };
+
+ if (t4_handle_intr_status(adap, A_LE_DB_INT_CAUSE,
+ (chip_ver <= CHELSIO_T5) ?
+ le_intr_info : t6_le_intr_info))
t4_fatal_err(adap);
}
@@ -2354,11 +4003,11 @@ static void le_intr_handler(struct adapter *adap)
*/
static void mps_intr_handler(struct adapter *adapter)
{
- static struct intr_info mps_rx_intr_info[] = {
+ static const struct intr_info mps_rx_intr_info[] = {
{ 0xffffff, "MPS Rx parity error", -1, 1 },
{ 0 }
};
- static struct intr_info mps_tx_intr_info[] = {
+ static const struct intr_info mps_tx_intr_info[] = {
{ V_TPFIFO(M_TPFIFO), "MPS Tx TP FIFO parity error", -1, 1 },
{ F_NCSIFIFO, "MPS Tx NC-SI FIFO parity error", -1, 1 },
{ V_TXDATAFIFO(M_TXDATAFIFO), "MPS Tx data FIFO parity error",
@@ -2370,26 +4019,26 @@ static void mps_intr_handler(struct adapter *adapter)
{ F_FRMERR, "MPS Tx framing error", -1, 1 },
{ 0 }
};
- static struct intr_info mps_trc_intr_info[] = {
+ static const struct intr_info mps_trc_intr_info[] = {
{ V_FILTMEM(M_FILTMEM), "MPS TRC filter parity error", -1, 1 },
{ V_PKTFIFO(M_PKTFIFO), "MPS TRC packet FIFO parity error", -1,
1 },
{ F_MISCPERR, "MPS TRC misc parity error", -1, 1 },
{ 0 }
};
- static struct intr_info mps_stat_sram_intr_info[] = {
+ static const struct intr_info mps_stat_sram_intr_info[] = {
{ 0x1fffff, "MPS statistics SRAM parity error", -1, 1 },
{ 0 }
};
- static struct intr_info mps_stat_tx_intr_info[] = {
+ static const struct intr_info mps_stat_tx_intr_info[] = {
{ 0xfffff, "MPS statistics Tx FIFO parity error", -1, 1 },
{ 0 }
};
- static struct intr_info mps_stat_rx_intr_info[] = {
+ static const struct intr_info mps_stat_rx_intr_info[] = {
{ 0xffffff, "MPS statistics Rx FIFO parity error", -1, 1 },
{ 0 }
};
- static struct intr_info mps_cls_intr_info[] = {
+ static const struct intr_info mps_cls_intr_info[] = {
{ F_MATCHSRAM, "MPS match SRAM parity error", -1, 1 },
{ F_MATCHTCAM, "MPS match TCAM parity error", -1, 1 },
{ F_HASHSRAM, "MPS hash SRAM parity error", -1, 1 },
@@ -2414,26 +4063,27 @@ static void mps_intr_handler(struct adapter *adapter)
mps_cls_intr_info);
t4_write_reg(adapter, A_MPS_INT_CAUSE, 0);
- t4_read_reg(adapter, A_MPS_INT_CAUSE); /* flush */
+ t4_read_reg(adapter, A_MPS_INT_CAUSE); /* flush */
if (fat)
t4_fatal_err(adapter);
}
-#define MEM_INT_MASK (F_PERR_INT_CAUSE | F_ECC_CE_INT_CAUSE | F_ECC_UE_INT_CAUSE)
+#define MEM_INT_MASK (F_PERR_INT_CAUSE | F_ECC_CE_INT_CAUSE | \
+ F_ECC_UE_INT_CAUSE)
/*
* EDC/MC interrupt handler.
*/
static void mem_intr_handler(struct adapter *adapter, int idx)
{
- static const char name[3][5] = { "EDC0", "EDC1", "MC" };
+ static const char name[4][7] = { "EDC0", "EDC1", "MC/MC0", "MC1" };
unsigned int addr, cnt_addr, v;
if (idx <= MEM_EDC1) {
addr = EDC_REG(A_EDC_INT_CAUSE, idx);
cnt_addr = EDC_REG(A_EDC_ECC_STATUS, idx);
- } else {
+ } else if (idx == MEM_MC) {
if (is_t4(adapter)) {
addr = A_MC_INT_CAUSE;
cnt_addr = A_MC_ECC_STATUS;
@@ -2441,22 +4091,28 @@ static void mem_intr_handler(struct adapter *adapter, int idx)
addr = A_MC_P_INT_CAUSE;
cnt_addr = A_MC_P_ECC_STATUS;
}
+ } else {
+ addr = MC_REG(A_MC_P_INT_CAUSE, 1);
+ cnt_addr = MC_REG(A_MC_P_ECC_STATUS, 1);
}
v = t4_read_reg(adapter, addr) & MEM_INT_MASK;
if (v & F_PERR_INT_CAUSE)
- CH_ALERT(adapter, "%s FIFO parity error\n", name[idx]);
+ CH_ALERT(adapter, "%s FIFO parity error\n",
+ name[idx]);
if (v & F_ECC_CE_INT_CAUSE) {
u32 cnt = G_ECC_CECNT(t4_read_reg(adapter, cnt_addr));
+ t4_edc_err_read(adapter, idx);
+
t4_write_reg(adapter, cnt_addr, V_ECC_CECNT(M_ECC_CECNT));
CH_WARN_RATELIMIT(adapter,
"%u %s correctable ECC data error%s\n",
cnt, name[idx], cnt > 1 ? "s" : "");
}
if (v & F_ECC_UE_INT_CAUSE)
- CH_ALERT(adapter, "%s uncorrectable ECC data error\n",
- name[idx]);
+ CH_ALERT(adapter,
+ "%s uncorrectable ECC data error\n", name[idx]);
t4_write_reg(adapter, addr, v);
if (v & (F_PERR_INT_CAUSE | F_ECC_UE_INT_CAUSE))
@@ -2471,19 +4127,21 @@ static void ma_intr_handler(struct adapter *adapter)
u32 v, status = t4_read_reg(adapter, A_MA_INT_CAUSE);
if (status & F_MEM_PERR_INT_CAUSE) {
- CH_ALERT(adapter, "MA parity error, parity status %#x\n",
- t4_read_reg(adapter, A_MA_PARITY_ERROR_STATUS1));
+ CH_ALERT(adapter,
+ "MA parity error, parity status %#x\n",
+ t4_read_reg(adapter, A_MA_PARITY_ERROR_STATUS1));
if (is_t5(adapter))
CH_ALERT(adapter,
- "MA parity error, parity status %#x\n",
- t4_read_reg(adapter,
- A_MA_PARITY_ERROR_STATUS2));
+ "MA parity error, parity status %#x\n",
+ t4_read_reg(adapter,
+ A_MA_PARITY_ERROR_STATUS2));
}
if (status & F_MEM_WRAP_INT_CAUSE) {
v = t4_read_reg(adapter, A_MA_INT_WRAP_STATUS);
- CH_ALERT(adapter, "MA address wrap-around error by client %u to"
- " address %#x\n", G_MEM_WRAP_CLIENT_NUM(v),
- G_MEM_WRAP_ADDRESS(v) << 4);
+ CH_ALERT(adapter, "MA address wrap-around error by "
+ "client %u to address %#x\n",
+ G_MEM_WRAP_CLIENT_NUM(v),
+ G_MEM_WRAP_ADDRESS(v) << 4);
}
t4_write_reg(adapter, A_MA_INT_CAUSE, status);
t4_fatal_err(adapter);
@@ -2494,7 +4152,7 @@ static void ma_intr_handler(struct adapter *adapter)
*/
static void smb_intr_handler(struct adapter *adap)
{
- static struct intr_info smb_intr_info[] = {
+ static const struct intr_info smb_intr_info[] = {
{ F_MSTTXFIFOPARINT, "SMB master Tx FIFO parity error", -1, 1 },
{ F_MSTRXFIFOPARINT, "SMB master Rx FIFO parity error", -1, 1 },
{ F_SLVFIFOPARINT, "SMB slave FIFO parity error", -1, 1 },
@@ -2510,7 +4168,7 @@ static void smb_intr_handler(struct adapter *adap)
*/
static void ncsi_intr_handler(struct adapter *adap)
{
- static struct intr_info ncsi_intr_info[] = {
+ static const struct intr_info ncsi_intr_info[] = {
{ F_CIM_DM_PRTY_ERR, "NC-SI CIM parity error", -1, 1 },
{ F_MPS_DM_PRTY_ERR, "NC-SI MPS parity error", -1, 1 },
{ F_TXFIFO_PRTY_ERR, "NC-SI Tx FIFO parity error", -1, 1 },
@@ -2535,14 +4193,17 @@ static void xgmac_intr_handler(struct adapter *adap, int port)
int_cause_reg = T5_PORT_REG(port, A_MAC_PORT_INT_CAUSE);
v = t4_read_reg(adap, int_cause_reg);
+
v &= (F_TXFIFO_PRTY_ERR | F_RXFIFO_PRTY_ERR);
if (!v)
return;
if (v & F_TXFIFO_PRTY_ERR)
- CH_ALERT(adap, "XGMAC %d Tx FIFO parity error\n", port);
+ CH_ALERT(adap, "XGMAC %d Tx FIFO parity error\n",
+ port);
if (v & F_RXFIFO_PRTY_ERR)
- CH_ALERT(adap, "XGMAC %d Rx FIFO parity error\n", port);
+ CH_ALERT(adap, "XGMAC %d Rx FIFO parity error\n",
+ port);
t4_write_reg(adap, int_cause_reg, v);
t4_fatal_err(adap);
}
@@ -2552,27 +4213,24 @@ static void xgmac_intr_handler(struct adapter *adap, int port)
*/
static void pl_intr_handler(struct adapter *adap)
{
- static struct intr_info pl_intr_info[] = {
+ static const struct intr_info pl_intr_info[] = {
{ F_FATALPERR, "Fatal parity error", -1, 1 },
{ F_PERRVFID, "PL VFID_MAP parity error", -1, 1 },
{ 0 }
};
- static struct intr_info t5_pl_intr_info[] = {
- { F_PL_BUSPERR, "PL bus parity error", -1, 1 },
+ static const struct intr_info t5_pl_intr_info[] = {
{ F_FATALPERR, "Fatal parity error", -1, 1 },
{ 0 }
};
if (t4_handle_intr_status(adap, A_PL_PL_INT_CAUSE,
- is_t4(adap) ? pl_intr_info : t5_pl_intr_info))
+ is_t4(adap) ?
+ pl_intr_info : t5_pl_intr_info))
t4_fatal_err(adap);
}
#define PF_INTR_MASK (F_PFSW | F_PFCIM)
-#define GLBL_INTR_MASK (F_CIM | F_MPS | F_PL | F_PCIE | F_MC | F_EDC0 | \
- F_EDC1 | F_LE | F_TP | F_MA | F_PM_TX | F_PM_RX | F_ULP_RX | \
- F_CPL_SWITCH | F_SGE | F_ULP_TX)
/**
* t4_slow_intr_handler - control path interrupt handler
@@ -2598,18 +4256,20 @@ int t4_slow_intr_handler(struct adapter *adapter)
pl_intr_handler(adapter);
if (cause & F_SMB)
smb_intr_handler(adapter);
- if (cause & F_XGMAC0)
+ if (cause & F_MAC0)
xgmac_intr_handler(adapter, 0);
- if (cause & F_XGMAC1)
+ if (cause & F_MAC1)
xgmac_intr_handler(adapter, 1);
- if (cause & F_XGMAC_KR0)
+ if (cause & F_MAC2)
xgmac_intr_handler(adapter, 2);
- if (cause & F_XGMAC_KR1)
+ if (cause & F_MAC3)
xgmac_intr_handler(adapter, 3);
if (cause & F_PCIE)
pcie_intr_handler(adapter);
- if (cause & F_MC)
+ if (cause & F_MC0)
mem_intr_handler(adapter, MEM_MC);
+ if (is_t5(adapter) && (cause & F_MC1))
+ mem_intr_handler(adapter, MEM_MC1);
if (cause & F_EDC0)
mem_intr_handler(adapter, MEM_EDC0);
if (cause & F_EDC1)
@@ -2635,7 +4295,7 @@ int t4_slow_intr_handler(struct adapter *adapter)
/* Clear the interrupts just processed for which we are the master. */
t4_write_reg(adapter, A_PL_INT_CAUSE, cause & GLBL_INTR_MASK);
- (void) t4_read_reg(adapter, A_PL_INT_CAUSE); /* flush */
+ (void)t4_read_reg(adapter, A_PL_INT_CAUSE); /* flush */
return 1;
}
@@ -2654,16 +4314,23 @@ int t4_slow_intr_handler(struct adapter *adapter)
*/
void t4_intr_enable(struct adapter *adapter)
{
- u32 pf = G_SOURCEPF(t4_read_reg(adapter, A_PL_WHOAMI));
+ u32 val = 0;
+ u32 whoami = t4_read_reg(adapter, A_PL_WHOAMI);
+ u32 pf = (chip_id(adapter) <= CHELSIO_T5
+ ? G_SOURCEPF(whoami)
+ : G_T6_SOURCEPF(whoami));
+ if (chip_id(adapter) <= CHELSIO_T5)
+ val = F_ERR_DROPPED_DB | F_ERR_EGR_CTXT_PRIO | F_DBFIFO_HP_INT;
+ else
+ val = F_ERR_PCIE_ERROR0 | F_ERR_PCIE_ERROR1 | F_FATAL_WRE_LEN;
t4_write_reg(adapter, A_SGE_INT_ENABLE3, F_ERR_CPL_EXCEED_IQE_SIZE |
F_ERR_INVALID_CIDX_INC | F_ERR_CPL_OPCODE_0 |
- F_ERR_DROPPED_DB | F_ERR_DATA_CPL_ON_HIGH_QID1 |
+ F_ERR_DATA_CPL_ON_HIGH_QID1 | F_INGRESS_SIZE_ERR |
F_ERR_DATA_CPL_ON_HIGH_QID0 | F_ERR_BAD_DB_PIDX3 |
F_ERR_BAD_DB_PIDX2 | F_ERR_BAD_DB_PIDX1 |
F_ERR_BAD_DB_PIDX0 | F_ERR_ING_CTXT_PRIO |
- F_ERR_EGR_CTXT_PRIO | F_INGRESS_SIZE_ERR |
- F_EGRESS_SIZE_ERR);
+ F_DBFIFO_LP_INT | F_EGRESS_SIZE_ERR | val);
t4_write_reg(adapter, MYPF_REG(A_PL_PF_INT_ENABLE), PF_INTR_MASK);
t4_set_reg_field(adapter, A_PL_INT_MAP0, 0, 1 << pf);
}
@@ -2678,7 +4345,10 @@ void t4_intr_enable(struct adapter *adapter)
*/
void t4_intr_disable(struct adapter *adapter)
{
- u32 pf = G_SOURCEPF(t4_read_reg(adapter, A_PL_WHOAMI));
+ u32 whoami = t4_read_reg(adapter, A_PL_WHOAMI);
+ u32 pf = (chip_id(adapter) <= CHELSIO_T5
+ ? G_SOURCEPF(whoami)
+ : G_T6_SOURCEPF(whoami));
t4_write_reg(adapter, MYPF_REG(A_PL_PF_INT_ENABLE), 0);
t4_set_reg_field(adapter, A_PL_INT_MAP0, 1 << pf, 0);
@@ -2773,11 +4443,10 @@ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
struct fw_rss_ind_tbl_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
- cmd.op_to_viid = htonl(V_FW_CMD_OP(FW_RSS_IND_TBL_CMD) |
- F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
- V_FW_RSS_IND_TBL_CMD_VIID(viid));
- cmd.retval_len16 = htonl(FW_LEN16(cmd));
-
+ cmd.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_RSS_IND_TBL_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+ V_FW_RSS_IND_TBL_CMD_VIID(viid));
+ cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
/*
* Each firmware RSS command can accommodate up to 32 RSS Ingress
@@ -2794,8 +4463,8 @@ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
* Set up the firmware RSS command header to send the next
* "nq" Ingress Queue IDs to the firmware.
*/
- cmd.niqid = htons(nq);
- cmd.startidx = htons(start);
+ cmd.niqid = cpu_to_be16(nq);
+ cmd.startidx = cpu_to_be16(start);
/*
* "nq" more done for the start of the next loop.
@@ -2841,7 +4510,6 @@ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
if (ret)
return ret;
}
-
return 0;
}
@@ -2860,15 +4528,16 @@ int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode,
struct fw_rss_glb_config_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_write = htonl(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
- F_FW_CMD_REQUEST | F_FW_CMD_WRITE);
- c.retval_len16 = htonl(FW_LEN16(c));
+ c.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE);
+ c.retval_len16 = cpu_to_be32(FW_LEN16(c));
if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) {
- c.u.manual.mode_pkd = htonl(V_FW_RSS_GLB_CONFIG_CMD_MODE(mode));
+ c.u.manual.mode_pkd =
+ cpu_to_be32(V_FW_RSS_GLB_CONFIG_CMD_MODE(mode));
} else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) {
c.u.basicvirtual.mode_pkd =
- htonl(V_FW_RSS_GLB_CONFIG_CMD_MODE(mode));
- c.u.basicvirtual.synmapen_to_hashtoeplitz = htonl(flags);
+ cpu_to_be32(V_FW_RSS_GLB_CONFIG_CMD_MODE(mode));
+ c.u.basicvirtual.synmapen_to_hashtoeplitz = cpu_to_be32(flags);
} else
return -EINVAL;
return t4_wr_mbox(adapter, mbox, &c, sizeof(c), NULL);
@@ -2890,11 +4559,11 @@ int t4_config_vi_rss(struct adapter *adapter, int mbox, unsigned int viid,
struct fw_rss_vi_config_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_viid = htonl(V_FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) |
- F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
- V_FW_RSS_VI_CONFIG_CMD_VIID(viid));
- c.retval_len16 = htonl(FW_LEN16(c));
- c.u.basicvirtual.defaultq_to_udpen = htonl(flags |
+ c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+ V_FW_RSS_VI_CONFIG_CMD_VIID(viid));
+ c.retval_len16 = cpu_to_be32(FW_LEN16(c));
+ c.u.basicvirtual.defaultq_to_udpen = cpu_to_be32(flags |
V_FW_RSS_VI_CONFIG_CMD_DEFAULTQ(defq));
return t4_wr_mbox(adapter, mbox, &c, sizeof(c), NULL);
}
@@ -2906,7 +4575,7 @@ static int rd_rss_row(struct adapter *adap, int row, u32 *val)
return t4_wait_op_done_val(adap, A_TP_RSS_LKP_TABLE, F_LKPTBLROWVLD, 1,
5, 0, val);
}
-
+
/**
* t4_read_rss - read the contents of the RSS mapping table
* @adapter: the adapter
@@ -2930,6 +4599,42 @@ int t4_read_rss(struct adapter *adapter, u16 *map)
}
/**
+ * t4_fw_tp_pio_rw - Access TP PIO through LDST
+ * @adap: the adapter
+ * @vals: where the indirect register values are stored/written
+ * @nregs: how many indirect registers to read/write
+ * @start_idx: index of first indirect register to read/write
+ * @rw: Read (1) or Write (0)
+ *
+ * Access TP PIO registers through LDST
+ */
+void t4_fw_tp_pio_rw(struct adapter *adap, u32 *vals, unsigned int nregs,
+ unsigned int start_index, unsigned int rw)
+{
+ int ret, i;
+ int cmd = FW_LDST_ADDRSPC_TP_PIO;
+ struct fw_ldst_cmd c;
+
+ for (i = 0 ; i < nregs; i++) {
+ memset(&c, 0, sizeof(c));
+ c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST |
+ (rw ? F_FW_CMD_READ :
+ F_FW_CMD_WRITE) |
+ V_FW_LDST_CMD_ADDRSPACE(cmd));
+ c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
+
+ c.u.addrval.addr = cpu_to_be32(start_index + i);
+ c.u.addrval.val = rw ? 0 : cpu_to_be32(vals[i]);
+ ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c);
+ if (ret == 0) {
+ if (rw)
+ vals[i] = be32_to_cpu(c.u.addrval.val);
+ }
+ }
+}
+
+/**
* t4_read_rss_key - read the global RSS key
* @adap: the adapter
* @key: 10-entry array holding the 320-bit RSS key
@@ -2938,8 +4643,11 @@ int t4_read_rss(struct adapter *adapter, u16 *map)
*/
void t4_read_rss_key(struct adapter *adap, u32 *key)
{
- t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, key, 10,
- A_TP_RSS_SECRET_KEY0);
+ if (t4_use_ldst(adap))
+ t4_fw_tp_pio_rw(adap, key, 10, A_TP_RSS_SECRET_KEY0, 1);
+ else
+ t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, key, 10,
+ A_TP_RSS_SECRET_KEY0);
}
/**
@@ -2952,13 +4660,35 @@ void t4_read_rss_key(struct adapter *adap, u32 *key)
* 0..15 the corresponding entry in the RSS key table is written,
* otherwise the global RSS key is written.
*/
-void t4_write_rss_key(struct adapter *adap, const u32 *key, int idx)
+void t4_write_rss_key(struct adapter *adap, u32 *key, int idx)
{
- t4_write_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, key, 10,
- A_TP_RSS_SECRET_KEY0);
- if (idx >= 0 && idx < 16)
- t4_write_reg(adap, A_TP_RSS_CONFIG_VRT,
- V_KEYWRADDR(idx) | F_KEYWREN);
+ u8 rss_key_addr_cnt = 16;
+ u32 vrt = t4_read_reg(adap, A_TP_RSS_CONFIG_VRT);
+
+ /*
+ * T6 and later: for KeyMode 3 (per-vf and per-vf scramble),
+ * allows access to key addresses 16-63 by using KeyWrAddrX
+ * as index[5:4](upper 2) into key table
+ */
+ if ((chip_id(adap) > CHELSIO_T5) &&
+ (vrt & F_KEYEXTEND) && (G_KEYMODE(vrt) == 3))
+ rss_key_addr_cnt = 32;
+
+ if (t4_use_ldst(adap))
+ t4_fw_tp_pio_rw(adap, key, 10, A_TP_RSS_SECRET_KEY0, 0);
+ else
+ t4_write_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, key, 10,
+ A_TP_RSS_SECRET_KEY0);
+
+ if (idx >= 0 && idx < rss_key_addr_cnt) {
+ if (rss_key_addr_cnt > 16)
+ t4_write_reg(adap, A_TP_RSS_CONFIG_VRT,
+ V_KEYWRADDRX(idx >> 4) |
+ V_T6_VFWRADDR(idx) | F_KEYWREN);
+ else
+ t4_write_reg(adap, A_TP_RSS_CONFIG_VRT,
+ V_KEYWRADDR(idx) | F_KEYWREN);
+ }
}
/**
@@ -2970,10 +4700,15 @@ void t4_write_rss_key(struct adapter *adap, const u32 *key, int idx)
* Reads the PF RSS Configuration Table at the specified index and returns
* the value found there.
*/
-void t4_read_rss_pf_config(struct adapter *adapter, unsigned int index, u32 *valp)
+void t4_read_rss_pf_config(struct adapter *adapter, unsigned int index,
+ u32 *valp)
{
- t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- valp, 1, A_TP_RSS_PF0_CONFIG + index);
+ if (t4_use_ldst(adapter))
+ t4_fw_tp_pio_rw(adapter, valp, 1,
+ A_TP_RSS_PF0_CONFIG + index, 1);
+ else
+ t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ valp, 1, A_TP_RSS_PF0_CONFIG + index);
}
/**
@@ -2985,10 +4720,15 @@ void t4_read_rss_pf_config(struct adapter *adapter, unsigned int index, u32 *val
* Writes the PF RSS Configuration Table at the specified index with the
* specified value.
*/
-void t4_write_rss_pf_config(struct adapter *adapter, unsigned int index, u32 val)
+void t4_write_rss_pf_config(struct adapter *adapter, unsigned int index,
+ u32 val)
{
- t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &val, 1, A_TP_RSS_PF0_CONFIG + index);
+ if (t4_use_ldst(adapter))
+ t4_fw_tp_pio_rw(adapter, &val, 1,
+ A_TP_RSS_PF0_CONFIG + index, 0);
+ else
+ t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &val, 1, A_TP_RSS_PF0_CONFIG + index);
}
/**
@@ -3004,28 +4744,40 @@ void t4_write_rss_pf_config(struct adapter *adapter, unsigned int index, u32 val
void t4_read_rss_vf_config(struct adapter *adapter, unsigned int index,
u32 *vfl, u32 *vfh)
{
- u32 vrt;
+ u32 vrt, mask, data;
+ if (chip_id(adapter) <= CHELSIO_T5) {
+ mask = V_VFWRADDR(M_VFWRADDR);
+ data = V_VFWRADDR(index);
+ } else {
+ mask = V_T6_VFWRADDR(M_T6_VFWRADDR);
+ data = V_T6_VFWRADDR(index);
+ }
/*
* Request that the index'th VF Table values be read into VFL/VFH.
*/
vrt = t4_read_reg(adapter, A_TP_RSS_CONFIG_VRT);
- vrt &= ~(F_VFRDRG | V_VFWRADDR(M_VFWRADDR) | F_VFWREN | F_KEYWREN);
- vrt |= V_VFWRADDR(index) | F_VFRDEN;
+ vrt &= ~(F_VFRDRG | F_VFWREN | F_KEYWREN | mask);
+ vrt |= data | F_VFRDEN;
t4_write_reg(adapter, A_TP_RSS_CONFIG_VRT, vrt);
/*
* Grab the VFL/VFH values ...
*/
- t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- vfl, 1, A_TP_RSS_VFL_CONFIG);
- t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- vfh, 1, A_TP_RSS_VFH_CONFIG);
+ if (t4_use_ldst(adapter)) {
+ t4_fw_tp_pio_rw(adapter, vfl, 1, A_TP_RSS_VFL_CONFIG, 1);
+ t4_fw_tp_pio_rw(adapter, vfh, 1, A_TP_RSS_VFH_CONFIG, 1);
+ } else {
+ t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ vfl, 1, A_TP_RSS_VFL_CONFIG);
+ t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ vfh, 1, A_TP_RSS_VFH_CONFIG);
+ }
}
/**
* t4_write_rss_vf_config - write VF RSS Configuration Table
- *
+ *
* @adapter: the adapter
* @index: the entry in the VF RSS table to write
* @vfl: the VFL to store
@@ -3037,22 +4789,35 @@ void t4_read_rss_vf_config(struct adapter *adapter, unsigned int index,
void t4_write_rss_vf_config(struct adapter *adapter, unsigned int index,
u32 vfl, u32 vfh)
{
- u32 vrt;
+ u32 vrt, mask, data;
+
+ if (chip_id(adapter) <= CHELSIO_T5) {
+ mask = V_VFWRADDR(M_VFWRADDR);
+ data = V_VFWRADDR(index);
+ } else {
+ mask = V_T6_VFWRADDR(M_T6_VFWRADDR);
+ data = V_T6_VFWRADDR(index);
+ }
/*
* Load up VFL/VFH with the values to be written ...
*/
- t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &vfl, 1, A_TP_RSS_VFL_CONFIG);
- t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &vfh, 1, A_TP_RSS_VFH_CONFIG);
+ if (t4_use_ldst(adapter)) {
+ t4_fw_tp_pio_rw(adapter, &vfl, 1, A_TP_RSS_VFL_CONFIG, 0);
+ t4_fw_tp_pio_rw(adapter, &vfh, 1, A_TP_RSS_VFH_CONFIG, 0);
+ } else {
+ t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &vfl, 1, A_TP_RSS_VFL_CONFIG);
+ t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &vfh, 1, A_TP_RSS_VFH_CONFIG);
+ }
/*
* Write the VFL/VFH into the VF Table at index'th location.
*/
vrt = t4_read_reg(adapter, A_TP_RSS_CONFIG_VRT);
- vrt &= ~(F_VFRDRG | F_VFRDEN | V_VFWRADDR(M_VFWRADDR) | F_KEYWREN);
- vrt |= V_VFWRADDR(index) | F_VFWREN;
+ vrt &= ~(F_VFRDRG | F_VFWREN | F_KEYWREN | mask);
+ vrt |= data | F_VFRDEN;
t4_write_reg(adapter, A_TP_RSS_CONFIG_VRT, vrt);
}
@@ -3066,8 +4831,11 @@ u32 t4_read_rss_pf_map(struct adapter *adapter)
{
u32 pfmap;
- t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &pfmap, 1, A_TP_RSS_PF_MAP);
+ if (t4_use_ldst(adapter))
+ t4_fw_tp_pio_rw(adapter, &pfmap, 1, A_TP_RSS_PF_MAP, 1);
+ else
+ t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &pfmap, 1, A_TP_RSS_PF_MAP);
return pfmap;
}
@@ -3080,8 +4848,11 @@ u32 t4_read_rss_pf_map(struct adapter *adapter)
*/
void t4_write_rss_pf_map(struct adapter *adapter, u32 pfmap)
{
- t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &pfmap, 1, A_TP_RSS_PF_MAP);
+ if (t4_use_ldst(adapter))
+ t4_fw_tp_pio_rw(adapter, &pfmap, 1, A_TP_RSS_PF_MAP, 0);
+ else
+ t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &pfmap, 1, A_TP_RSS_PF_MAP);
}
/**
@@ -3094,8 +4865,11 @@ u32 t4_read_rss_pf_mask(struct adapter *adapter)
{
u32 pfmask;
- t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &pfmask, 1, A_TP_RSS_PF_MSK);
+ if (t4_use_ldst(adapter))
+ t4_fw_tp_pio_rw(adapter, &pfmask, 1, A_TP_RSS_PF_MSK, 1);
+ else
+ t4_read_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &pfmask, 1, A_TP_RSS_PF_MSK);
return pfmask;
}
@@ -3108,61 +4882,11 @@ u32 t4_read_rss_pf_mask(struct adapter *adapter)
*/
void t4_write_rss_pf_mask(struct adapter *adapter, u32 pfmask)
{
- t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &pfmask, 1, A_TP_RSS_PF_MSK);
-}
-
-static void refresh_vlan_pri_map(struct adapter *adap)
-{
-
- t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &adap->params.tp.vlan_pri_map, 1,
- A_TP_VLAN_PRI_MAP);
-
- /*
- * Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
- * shift positions of several elements of the Compressed Filter Tuple
- * for this adapter which we need frequently ...
- */
- adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
- adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
- adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
- adap->params.tp.protocol_shift = t4_filter_field_shift(adap, F_PROTOCOL);
-
- /*
- * If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
- * represents the presense of an Outer VLAN instead of a VNIC ID.
- */
- if ((adap->params.tp.ingress_config & F_VNIC) == 0)
- adap->params.tp.vnic_shift = -1;
-}
-
-/**
- * t4_set_filter_mode - configure the optional components of filter tuples
- * @adap: the adapter
- * @mode_map: a bitmap selcting which optional filter components to enable
- *
- * Sets the filter mode by selecting the optional components to enable
- * in filter tuples. Returns 0 on success and a negative error if the
- * requested mode needs more bits than are available for optional
- * components.
- */
-int t4_set_filter_mode(struct adapter *adap, unsigned int mode_map)
-{
- static u8 width[] = { 1, 3, 17, 17, 8, 8, 16, 9, 3, 1 };
-
- int i, nbits = 0;
-
- for (i = S_FCOE; i <= S_FRAGMENTATION; i++)
- if (mode_map & (1 << i))
- nbits += width[i];
- if (nbits > FILTER_OPT_LEN)
- return -EINVAL;
- t4_write_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, &mode_map, 1,
- A_TP_VLAN_PRI_MAP);
- refresh_vlan_pri_map(adap);
-
- return 0;
+ if (t4_use_ldst(adapter))
+ t4_fw_tp_pio_rw(adapter, &pfmask, 1, A_TP_RSS_PF_MSK, 0);
+ else
+ t4_write_indirect(adapter, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &pfmask, 1, A_TP_RSS_PF_MSK);
}
/**
@@ -3186,18 +4910,18 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
if (v4) {
t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, val,
ARRAY_SIZE(val), A_TP_MIB_TCP_OUT_RST);
- v4->tcpOutRsts = STAT(OUT_RST);
- v4->tcpInSegs = STAT64(IN_SEG);
- v4->tcpOutSegs = STAT64(OUT_SEG);
- v4->tcpRetransSegs = STAT64(RXT_SEG);
+ v4->tcp_out_rsts = STAT(OUT_RST);
+ v4->tcp_in_segs = STAT64(IN_SEG);
+ v4->tcp_out_segs = STAT64(OUT_SEG);
+ v4->tcp_retrans_segs = STAT64(RXT_SEG);
}
if (v6) {
t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, val,
ARRAY_SIZE(val), A_TP_MIB_TCP_V6OUT_RST);
- v6->tcpOutRsts = STAT(OUT_RST);
- v6->tcpInSegs = STAT64(IN_SEG);
- v6->tcpOutSegs = STAT64(OUT_SEG);
- v6->tcpRetransSegs = STAT64(RXT_SEG);
+ v6->tcp_out_rsts = STAT(OUT_RST);
+ v6->tcp_in_segs = STAT64(IN_SEG);
+ v6->tcp_out_segs = STAT64(OUT_SEG);
+ v6->tcp_retrans_segs = STAT64(RXT_SEG);
}
#undef STAT64
#undef STAT
@@ -3213,18 +4937,27 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
*/
void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st)
{
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->macInErrs,
- 12, A_TP_MIB_MAC_IN_ERR_0);
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->tnlCongDrops,
- 8, A_TP_MIB_TNL_CNG_DROP_0);
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->tnlTxDrops,
- 4, A_TP_MIB_TNL_DROP_0);
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->ofldVlanDrops,
- 4, A_TP_MIB_OFD_VLN_DROP_0);
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->tcp6InErrs,
- 4, A_TP_MIB_TCP_V6IN_ERR_0);
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, &st->ofldNoNeigh,
- 2, A_TP_MIB_OFD_ARP_DROP);
+ int nchan = adap->chip_params->nchan;
+
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ st->mac_in_errs, nchan, A_TP_MIB_MAC_IN_ERR_0);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ st->hdr_in_errs, nchan, A_TP_MIB_HDR_IN_ERR_0);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ st->tcp_in_errs, nchan, A_TP_MIB_TCP_IN_ERR_0);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ st->tnl_cong_drops, nchan, A_TP_MIB_TNL_CNG_DROP_0);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ st->ofld_chan_drops, nchan, A_TP_MIB_OFD_CHN_DROP_0);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ st->tnl_tx_drops, nchan, A_TP_MIB_TNL_DROP_0);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ st->ofld_vlan_drops, nchan, A_TP_MIB_OFD_VLN_DROP_0);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ st->tcp6_in_errs, nchan, A_TP_MIB_TCP_V6IN_ERR_0);
+
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA,
+ &st->ofld_no_neigh, 2, A_TP_MIB_OFD_ARP_DROP);
}
/**
@@ -3236,8 +4969,10 @@ void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st)
*/
void t4_tp_get_proxy_stats(struct adapter *adap, struct tp_proxy_stats *st)
{
+ int nchan = adap->chip_params->nchan;
+
t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->proxy,
- 4, A_TP_MIB_TNL_LPBK_0);
+ nchan, A_TP_MIB_TNL_LPBK_0);
}
/**
@@ -3249,8 +4984,12 @@ void t4_tp_get_proxy_stats(struct adapter *adap, struct tp_proxy_stats *st)
*/
void t4_tp_get_cpl_stats(struct adapter *adap, struct tp_cpl_stats *st)
{
+ int nchan = adap->chip_params->nchan;
+
t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->req,
- 8, A_TP_MIB_CPL_IN_REQ_0);
+ nchan, A_TP_MIB_CPL_IN_REQ_0);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, st->rsp,
+ nchan, A_TP_MIB_CPL_OUT_RSP_0);
}
/**
@@ -3262,8 +5001,8 @@ void t4_tp_get_cpl_stats(struct adapter *adap, struct tp_cpl_stats *st)
*/
void t4_tp_get_rdma_stats(struct adapter *adap, struct tp_rdma_stats *st)
{
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, &st->rqe_dfr_mod,
- 2, A_TP_MIB_RQE_DFR_MOD);
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, &st->rqe_dfr_pkt,
+ 2, A_TP_MIB_RQE_DFR_PKT);
}
/**
@@ -3279,13 +5018,13 @@ void t4_get_fcoe_stats(struct adapter *adap, unsigned int idx,
{
u32 val[2];
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, &st->framesDDP,
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, &st->frames_ddp,
1, A_TP_MIB_FCOE_DDP_0 + idx);
- t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, &st->framesDrop,
+ t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, &st->frames_drop,
1, A_TP_MIB_FCOE_DROP_0 + idx);
t4_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, val,
2, A_TP_MIB_FCOE_BYTE_0_HI + 2 * idx);
- st->octetsDDP = ((u64)val[0] << 32) | val[1];
+ st->octets_ddp = ((u64)val[0] << 32) | val[1];
}
/**
@@ -3351,24 +5090,6 @@ void t4_read_cong_tbl(struct adapter *adap, u16 incr[NMTUS][NCCTRL_WIN])
}
/**
- * t4_read_pace_tbl - read the pace table
- * @adap: the adapter
- * @pace_vals: holds the returned values
- *
- * Returns the values of TP's pace table in microseconds.
- */
-void t4_read_pace_tbl(struct adapter *adap, unsigned int pace_vals[NTX_SCHED])
-{
- unsigned int i, v;
-
- for (i = 0; i < NTX_SCHED; i++) {
- t4_write_reg(adap, A_TP_PACE_TABLE, 0xffff0000 + i);
- v = t4_read_reg(adap, A_TP_PACE_TABLE);
- pace_vals[i] = dack_ticks_to_usec(adap, v);
- }
-}
-
-/**
* t4_tp_wr_bits_indirect - set/clear bits in an indirect TP register
* @adap: the adapter
* @addr: the indirect TP register address
@@ -3392,7 +5113,7 @@ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
*
* Initialize the congestion control parameters.
*/
-static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b)
+static void init_cong_ctrl(unsigned short *a, unsigned short *b)
{
a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
a[9] = 2;
@@ -3493,7 +5214,7 @@ int t4_set_pace_tbl(struct adapter *adap, const unsigned int *pace_vals,
if (n > NTX_SCHED)
return -ERANGE;
-
+
/* convert values from us to dack ticks, rounding to closest value */
for (i = 0; i < n; i++, pace_vals++) {
vals[i] = (1000 * *pace_vals + tick_ns / 2) / tick_ns;
@@ -3580,46 +5301,6 @@ int t4_set_sched_ipg(struct adapter *adap, int sched, unsigned int ipg)
return 0;
}
-/**
- * t4_get_tx_sched - get the configuration of a Tx HW traffic scheduler
- * @adap: the adapter
- * @sched: the scheduler index
- * @kbps: the byte rate in Kbps
- * @ipg: the interpacket delay in tenths of nanoseconds
- *
- * Return the current configuration of a HW Tx scheduler.
- */
-void t4_get_tx_sched(struct adapter *adap, unsigned int sched, unsigned int *kbps,
- unsigned int *ipg)
-{
- unsigned int v, addr, bpt, cpt;
-
- if (kbps) {
- addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2;
- t4_write_reg(adap, A_TP_TM_PIO_ADDR, addr);
- v = t4_read_reg(adap, A_TP_TM_PIO_DATA);
- if (sched & 1)
- v >>= 16;
- bpt = (v >> 8) & 0xff;
- cpt = v & 0xff;
- if (!cpt)
- *kbps = 0; /* scheduler disabled */
- else {
- v = (adap->params.vpd.cclk * 1000) / cpt; /* ticks/s */
- *kbps = (v * bpt) / 125;
- }
- }
- if (ipg) {
- addr = A_TP_TX_MOD_Q1_Q0_TIMER_SEPARATOR - sched / 2;
- t4_write_reg(adap, A_TP_TM_PIO_ADDR, addr);
- v = t4_read_reg(adap, A_TP_TM_PIO_DATA);
- if (sched & 1)
- v >>= 16;
- v &= 0xffff;
- *ipg = (10000 * v) / core_ticks_per_usec(adap);
- }
-}
-
/*
* Calculates a rate in bytes/s given the number of 256-byte units per 4K core
* clocks. The formula is
@@ -3653,14 +5334,18 @@ void t4_get_chan_txrate(struct adapter *adap, u64 *nic_rate, u64 *ofld_rate)
v = t4_read_reg(adap, A_TP_TX_TRATE);
nic_rate[0] = chan_rate(adap, G_TNLRATE0(v));
nic_rate[1] = chan_rate(adap, G_TNLRATE1(v));
- nic_rate[2] = chan_rate(adap, G_TNLRATE2(v));
- nic_rate[3] = chan_rate(adap, G_TNLRATE3(v));
+ if (adap->chip_params->nchan > 2) {
+ nic_rate[2] = chan_rate(adap, G_TNLRATE2(v));
+ nic_rate[3] = chan_rate(adap, G_TNLRATE3(v));
+ }
v = t4_read_reg(adap, A_TP_TX_ORATE);
ofld_rate[0] = chan_rate(adap, G_OFDRATE0(v));
ofld_rate[1] = chan_rate(adap, G_OFDRATE1(v));
- ofld_rate[2] = chan_rate(adap, G_OFDRATE2(v));
- ofld_rate[3] = chan_rate(adap, G_OFDRATE3(v));
+ if (adap->chip_params->nchan > 2) {
+ ofld_rate[2] = chan_rate(adap, G_OFDRATE2(v));
+ ofld_rate[3] = chan_rate(adap, G_OFDRATE3(v));
+ }
}
/**
@@ -3695,10 +5380,10 @@ int t4_set_trace_filter(struct adapter *adap, const struct trace_params *tp,
* TODO - After T4 data book is updated, specify the exact
* section below.
*
- * See T4 data book - MPS section for a complete description
- * of the below if..else handling of A_MPS_TRC_CFG register
+ * See T4 data book - MPS section for a complete description
+ * of the below if..else handling of A_MPS_TRC_CFG register
* value.
- */
+ */
cfg = t4_read_reg(adap, A_MPS_TRC_CFG);
if (cfg & F_TRCMULTIFILTER) {
/*
@@ -3707,10 +5392,10 @@ int t4_set_trace_filter(struct adapter *adap, const struct trace_params *tp,
* minus 2 flits for CPL_TRACE_PKT header.
*/
if (tp->snap_len > ((10 * 1024 / 4) - (2 * 8)))
- return -EINVAL;
+ return -EINVAL;
} else {
/*
- * If multiple tracers are disabled, to avoid deadlocks
+ * If multiple tracers are disabled, to avoid deadlocks
* maximum packet capture size of 9600 bytes is recommended.
* Also in this mode, only trace0 can be enabled and running.
*/
@@ -3803,7 +5488,7 @@ void t4_pmtx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
int i;
u32 data[2];
- for (i = 0; i < PM_NSTATS; i++) {
+ for (i = 0; i < adap->chip_params->pm_stats_cnt; i++) {
t4_write_reg(adap, A_PM_TX_STAT_CONFIG, i + 1);
cnt[i] = t4_read_reg(adap, A_PM_TX_STAT_COUNT);
if (is_t4(adap))
@@ -3830,12 +5515,12 @@ void t4_pmrx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
int i;
u32 data[2];
- for (i = 0; i < PM_NSTATS; i++) {
+ for (i = 0; i < adap->chip_params->pm_stats_cnt; i++) {
t4_write_reg(adap, A_PM_RX_STAT_CONFIG, i + 1);
cnt[i] = t4_read_reg(adap, A_PM_RX_STAT_COUNT);
- if (is_t4(adap))
+ if (is_t4(adap)) {
cycles[i] = t4_read_reg64(adap, A_PM_RX_STAT_LSB);
- else {
+ } else {
t4_read_indirect(adap, A_PM_RX_DBG_CTRL,
A_PM_RX_DBG_DATA, data, 2,
A_PM_RX_DBG_STAT_MSB);
@@ -3845,7 +5530,7 @@ void t4_pmrx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
}
/**
- * get_mps_bg_map - return the buffer groups associated with a port
+ * t4_get_mps_bg_map - return the buffer groups associated with a port
* @adap: the adapter
* @idx: the port index
*
@@ -3853,20 +5538,50 @@ void t4_pmrx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
* with the given port. Bit i is set if buffer group i is used by the
* port.
*/
-static unsigned int get_mps_bg_map(struct adapter *adap, int idx)
+static unsigned int t4_get_mps_bg_map(struct adapter *adap, int idx)
{
u32 n = G_NUMPORTS(t4_read_reg(adap, A_MPS_CMN_CTL));
if (n == 0)
return idx == 0 ? 0xf : 0;
- if (n == 1)
+ if (n == 1 && chip_id(adap) <= CHELSIO_T5)
return idx < 2 ? (3 << (2 * idx)) : 0;
return 1 << idx;
}
/**
+ * t4_get_port_type_description - return Port Type string description
+ * @port_type: firmware Port Type enumeration
+ */
+const char *t4_get_port_type_description(enum fw_port_type port_type)
+{
+ static const char *const port_type_description[] = {
+ "Fiber_XFI",
+ "Fiber_XAUI",
+ "BT_SGMII",
+ "BT_XFI",
+ "BT_XAUI",
+ "KX4",
+ "CX4",
+ "KX",
+ "KR",
+ "SFP",
+ "BP_AP",
+ "BP4_AP",
+ "QSFP_10G",
+ "QSA",
+ "QSFP",
+ "BP40_BA",
+ };
+
+ if (port_type < ARRAY_SIZE(port_type_description))
+ return port_type_description[port_type];
+ return "UNKNOWN";
+}
+
+/**
* t4_get_port_stats_offset - collect port stats relative to a previous
- * snapshot
+ * snapshot
* @adap: The adapter
* @idx: The port
* @stats: Current stats to fill
@@ -3896,7 +5611,7 @@ void t4_get_port_stats_offset(struct adapter *adap, int idx,
*/
void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
{
- u32 bgmap = get_mps_bg_map(adap, idx);
+ u32 bgmap = t4_get_mps_bg_map(adap, idx);
#define GET_STAT(name) \
t4_read_reg64(adap, \
@@ -3904,57 +5619,57 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
T5_PORT_REG(idx, A_MPS_PORT_STAT_##name##_L)))
#define GET_STAT_COM(name) t4_read_reg64(adap, A_MPS_STAT_##name##_L)
- p->tx_pause = GET_STAT(TX_PORT_PAUSE);
- p->tx_octets = GET_STAT(TX_PORT_BYTES);
- p->tx_frames = GET_STAT(TX_PORT_FRAMES);
- p->tx_bcast_frames = GET_STAT(TX_PORT_BCAST);
- p->tx_mcast_frames = GET_STAT(TX_PORT_MCAST);
- p->tx_ucast_frames = GET_STAT(TX_PORT_UCAST);
- p->tx_error_frames = GET_STAT(TX_PORT_ERROR);
- p->tx_frames_64 = GET_STAT(TX_PORT_64B);
- p->tx_frames_65_127 = GET_STAT(TX_PORT_65B_127B);
- p->tx_frames_128_255 = GET_STAT(TX_PORT_128B_255B);
- p->tx_frames_256_511 = GET_STAT(TX_PORT_256B_511B);
- p->tx_frames_512_1023 = GET_STAT(TX_PORT_512B_1023B);
- p->tx_frames_1024_1518 = GET_STAT(TX_PORT_1024B_1518B);
- p->tx_frames_1519_max = GET_STAT(TX_PORT_1519B_MAX);
- p->tx_drop = GET_STAT(TX_PORT_DROP);
- p->tx_ppp0 = GET_STAT(TX_PORT_PPP0);
- p->tx_ppp1 = GET_STAT(TX_PORT_PPP1);
- p->tx_ppp2 = GET_STAT(TX_PORT_PPP2);
- p->tx_ppp3 = GET_STAT(TX_PORT_PPP3);
- p->tx_ppp4 = GET_STAT(TX_PORT_PPP4);
- p->tx_ppp5 = GET_STAT(TX_PORT_PPP5);
- p->tx_ppp6 = GET_STAT(TX_PORT_PPP6);
- p->tx_ppp7 = GET_STAT(TX_PORT_PPP7);
-
- p->rx_pause = GET_STAT(RX_PORT_PAUSE);
- p->rx_octets = GET_STAT(RX_PORT_BYTES);
- p->rx_frames = GET_STAT(RX_PORT_FRAMES);
- p->rx_bcast_frames = GET_STAT(RX_PORT_BCAST);
- p->rx_mcast_frames = GET_STAT(RX_PORT_MCAST);
- p->rx_ucast_frames = GET_STAT(RX_PORT_UCAST);
- p->rx_too_long = GET_STAT(RX_PORT_MTU_ERROR);
- p->rx_jabber = GET_STAT(RX_PORT_MTU_CRC_ERROR);
- p->rx_fcs_err = GET_STAT(RX_PORT_CRC_ERROR);
- p->rx_len_err = GET_STAT(RX_PORT_LEN_ERROR);
- p->rx_symbol_err = GET_STAT(RX_PORT_SYM_ERROR);
- p->rx_runt = GET_STAT(RX_PORT_LESS_64B);
- p->rx_frames_64 = GET_STAT(RX_PORT_64B);
- p->rx_frames_65_127 = GET_STAT(RX_PORT_65B_127B);
- p->rx_frames_128_255 = GET_STAT(RX_PORT_128B_255B);
- p->rx_frames_256_511 = GET_STAT(RX_PORT_256B_511B);
- p->rx_frames_512_1023 = GET_STAT(RX_PORT_512B_1023B);
- p->rx_frames_1024_1518 = GET_STAT(RX_PORT_1024B_1518B);
- p->rx_frames_1519_max = GET_STAT(RX_PORT_1519B_MAX);
- p->rx_ppp0 = GET_STAT(RX_PORT_PPP0);
- p->rx_ppp1 = GET_STAT(RX_PORT_PPP1);
- p->rx_ppp2 = GET_STAT(RX_PORT_PPP2);
- p->rx_ppp3 = GET_STAT(RX_PORT_PPP3);
- p->rx_ppp4 = GET_STAT(RX_PORT_PPP4);
- p->rx_ppp5 = GET_STAT(RX_PORT_PPP5);
- p->rx_ppp6 = GET_STAT(RX_PORT_PPP6);
- p->rx_ppp7 = GET_STAT(RX_PORT_PPP7);
+ p->tx_pause = GET_STAT(TX_PORT_PAUSE);
+ p->tx_octets = GET_STAT(TX_PORT_BYTES);
+ p->tx_frames = GET_STAT(TX_PORT_FRAMES);
+ p->tx_bcast_frames = GET_STAT(TX_PORT_BCAST);
+ p->tx_mcast_frames = GET_STAT(TX_PORT_MCAST);
+ p->tx_ucast_frames = GET_STAT(TX_PORT_UCAST);
+ p->tx_error_frames = GET_STAT(TX_PORT_ERROR);
+ p->tx_frames_64 = GET_STAT(TX_PORT_64B);
+ p->tx_frames_65_127 = GET_STAT(TX_PORT_65B_127B);
+ p->tx_frames_128_255 = GET_STAT(TX_PORT_128B_255B);
+ p->tx_frames_256_511 = GET_STAT(TX_PORT_256B_511B);
+ p->tx_frames_512_1023 = GET_STAT(TX_PORT_512B_1023B);
+ p->tx_frames_1024_1518 = GET_STAT(TX_PORT_1024B_1518B);
+ p->tx_frames_1519_max = GET_STAT(TX_PORT_1519B_MAX);
+ p->tx_drop = GET_STAT(TX_PORT_DROP);
+ p->tx_ppp0 = GET_STAT(TX_PORT_PPP0);
+ p->tx_ppp1 = GET_STAT(TX_PORT_PPP1);
+ p->tx_ppp2 = GET_STAT(TX_PORT_PPP2);
+ p->tx_ppp3 = GET_STAT(TX_PORT_PPP3);
+ p->tx_ppp4 = GET_STAT(TX_PORT_PPP4);
+ p->tx_ppp5 = GET_STAT(TX_PORT_PPP5);
+ p->tx_ppp6 = GET_STAT(TX_PORT_PPP6);
+ p->tx_ppp7 = GET_STAT(TX_PORT_PPP7);
+
+ p->rx_pause = GET_STAT(RX_PORT_PAUSE);
+ p->rx_octets = GET_STAT(RX_PORT_BYTES);
+ p->rx_frames = GET_STAT(RX_PORT_FRAMES);
+ p->rx_bcast_frames = GET_STAT(RX_PORT_BCAST);
+ p->rx_mcast_frames = GET_STAT(RX_PORT_MCAST);
+ p->rx_ucast_frames = GET_STAT(RX_PORT_UCAST);
+ p->rx_too_long = GET_STAT(RX_PORT_MTU_ERROR);
+ p->rx_jabber = GET_STAT(RX_PORT_MTU_CRC_ERROR);
+ p->rx_fcs_err = GET_STAT(RX_PORT_CRC_ERROR);
+ p->rx_len_err = GET_STAT(RX_PORT_LEN_ERROR);
+ p->rx_symbol_err = GET_STAT(RX_PORT_SYM_ERROR);
+ p->rx_runt = GET_STAT(RX_PORT_LESS_64B);
+ p->rx_frames_64 = GET_STAT(RX_PORT_64B);
+ p->rx_frames_65_127 = GET_STAT(RX_PORT_65B_127B);
+ p->rx_frames_128_255 = GET_STAT(RX_PORT_128B_255B);
+ p->rx_frames_256_511 = GET_STAT(RX_PORT_256B_511B);
+ p->rx_frames_512_1023 = GET_STAT(RX_PORT_512B_1023B);
+ p->rx_frames_1024_1518 = GET_STAT(RX_PORT_1024B_1518B);
+ p->rx_frames_1519_max = GET_STAT(RX_PORT_1519B_MAX);
+ p->rx_ppp0 = GET_STAT(RX_PORT_PPP0);
+ p->rx_ppp1 = GET_STAT(RX_PORT_PPP1);
+ p->rx_ppp2 = GET_STAT(RX_PORT_PPP2);
+ p->rx_ppp3 = GET_STAT(RX_PORT_PPP3);
+ p->rx_ppp4 = GET_STAT(RX_PORT_PPP4);
+ p->rx_ppp5 = GET_STAT(RX_PORT_PPP5);
+ p->rx_ppp6 = GET_STAT(RX_PORT_PPP6);
+ p->rx_ppp7 = GET_STAT(RX_PORT_PPP7);
p->rx_ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_MAC_DROP_FRAME) : 0;
p->rx_ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_MAC_DROP_FRAME) : 0;
@@ -3970,39 +5685,6 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
}
/**
- * t4_clr_port_stats - clear port statistics
- * @adap: the adapter
- * @idx: the port index
- *
- * Clear HW statistics for the given port.
- */
-void t4_clr_port_stats(struct adapter *adap, int idx)
-{
- unsigned int i;
- u32 bgmap = get_mps_bg_map(adap, idx);
- u32 port_base_addr;
-
- if (is_t4(adap))
- port_base_addr = PORT_BASE(idx);
- else
- port_base_addr = T5_PORT_BASE(idx);
-
- for (i = A_MPS_PORT_STAT_TX_PORT_BYTES_L;
- i <= A_MPS_PORT_STAT_TX_PORT_PPP7_H; i += 8)
- t4_write_reg(adap, port_base_addr + i, 0);
- for (i = A_MPS_PORT_STAT_RX_PORT_BYTES_L;
- i <= A_MPS_PORT_STAT_RX_PORT_LESS_64B_H; i += 8)
- t4_write_reg(adap, port_base_addr + i, 0);
- for (i = 0; i < 4; i++)
- if (bgmap & (1 << i)) {
- t4_write_reg(adap,
- A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + i * 8, 0);
- t4_write_reg(adap,
- A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + i * 8, 0);
- }
-}
-
-/**
* t4_get_lb_stats - collect loopback port statistics
* @adap: the adapter
* @idx: the loopback port index
@@ -4012,7 +5694,7 @@ void t4_clr_port_stats(struct adapter *adap, int idx)
*/
void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
{
- u32 bgmap = get_mps_bg_map(adap, idx);
+ u32 bgmap = t4_get_mps_bg_map(adap, idx);
#define GET_STAT(name) \
t4_read_reg64(adap, \
@@ -4021,21 +5703,21 @@ void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
T5_PORT_REG(idx, A_MPS_PORT_STAT_LB_PORT_##name##_L)))
#define GET_STAT_COM(name) t4_read_reg64(adap, A_MPS_STAT_##name##_L)
- p->octets = GET_STAT(BYTES);
- p->frames = GET_STAT(FRAMES);
- p->bcast_frames = GET_STAT(BCAST);
- p->mcast_frames = GET_STAT(MCAST);
- p->ucast_frames = GET_STAT(UCAST);
- p->error_frames = GET_STAT(ERROR);
-
- p->frames_64 = GET_STAT(64B);
- p->frames_65_127 = GET_STAT(65B_127B);
- p->frames_128_255 = GET_STAT(128B_255B);
- p->frames_256_511 = GET_STAT(256B_511B);
- p->frames_512_1023 = GET_STAT(512B_1023B);
- p->frames_1024_1518 = GET_STAT(1024B_1518B);
- p->frames_1519_max = GET_STAT(1519B_MAX);
- p->drop = GET_STAT(DROP_FRAMES);
+ p->octets = GET_STAT(BYTES);
+ p->frames = GET_STAT(FRAMES);
+ p->bcast_frames = GET_STAT(BCAST);
+ p->mcast_frames = GET_STAT(MCAST);
+ p->ucast_frames = GET_STAT(UCAST);
+ p->error_frames = GET_STAT(ERROR);
+
+ p->frames_64 = GET_STAT(64B);
+ p->frames_65_127 = GET_STAT(65B_127B);
+ p->frames_128_255 = GET_STAT(128B_255B);
+ p->frames_256_511 = GET_STAT(256B_511B);
+ p->frames_512_1023 = GET_STAT(512B_1023B);
+ p->frames_1024_1518 = GET_STAT(1024B_1518B);
+ p->frames_1519_max = GET_STAT(1519B_MAX);
+ p->drop = GET_STAT(DROP_FRAMES);
p->ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_DROP_FRAME) : 0;
p->ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_DROP_FRAME) : 0;
@@ -4149,43 +5831,49 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
return 0;
}
-/**
- * t4_mk_filtdelwr - create a delete filter WR
- * @ftid: the filter ID
- * @wr: the filter work request to populate
- * @qid: ingress queue to receive the delete notification
+/* t4_mk_filtdelwr - create a delete filter WR
+ * @ftid: the filter ID
+ * @wr: the filter work request to populate
+ * @qid: ingress queue to receive the delete notification
*
- * Creates a filter work request to delete the supplied filter. If @qid is
- * negative the delete notification is suppressed.
+ * Creates a filter work request to delete the supplied filter. If @qid is
+ * negative the delete notification is suppressed.
*/
void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid)
{
memset(wr, 0, sizeof(*wr));
- wr->op_pkd = htonl(V_FW_WR_OP(FW_FILTER_WR));
- wr->len16_pkd = htonl(V_FW_WR_LEN16(sizeof(*wr) / 16));
- wr->tid_to_iq = htonl(V_FW_FILTER_WR_TID(ftid) |
- V_FW_FILTER_WR_NOREPLY(qid < 0));
- wr->del_filter_to_l2tix = htonl(F_FW_FILTER_WR_DEL_FILTER);
+ wr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));
+ wr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*wr) / 16));
+ wr->tid_to_iq = cpu_to_be32(V_FW_FILTER_WR_TID(ftid) |
+ V_FW_FILTER_WR_NOREPLY(qid < 0));
+ wr->del_filter_to_l2tix = cpu_to_be32(F_FW_FILTER_WR_DEL_FILTER);
if (qid >= 0)
- wr->rx_chan_rx_rpl_iq = htons(V_FW_FILTER_WR_RX_RPL_IQ(qid));
+ wr->rx_chan_rx_rpl_iq =
+ cpu_to_be16(V_FW_FILTER_WR_RX_RPL_IQ(qid));
}
#define INIT_CMD(var, cmd, rd_wr) do { \
- (var).op_to_write = htonl(V_FW_CMD_OP(FW_##cmd##_CMD) | \
- F_FW_CMD_REQUEST | F_FW_CMD_##rd_wr); \
- (var).retval_len16 = htonl(FW_LEN16(var)); \
+ (var).op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_##cmd##_CMD) | \
+ F_FW_CMD_REQUEST | \
+ F_FW_CMD_##rd_wr); \
+ (var).retval_len16 = cpu_to_be32(FW_LEN16(var)); \
} while (0)
-int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, u32 addr, u32 val)
+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
+ u32 addr, u32 val)
{
+ u32 ldst_addrspace;
struct fw_ldst_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE | V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE));
- c.cycles_to_len16 = htonl(FW_LEN16(c));
- c.u.addrval.addr = htonl(addr);
- c.u.addrval.val = htonl(val);
+ ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE);
+ c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE |
+ ldst_addrspace);
+ c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
+ c.u.addrval.addr = cpu_to_be32(addr);
+ c.u.addrval.val = cpu_to_be32(val);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -4205,19 +5893,22 @@ int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
unsigned int mmd, unsigned int reg, unsigned int *valp)
{
int ret;
+ u32 ldst_addrspace;
struct fw_ldst_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_READ | V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO));
- c.cycles_to_len16 = htonl(FW_LEN16(c));
- c.u.mdio.paddr_mmd = htons(V_FW_LDST_CMD_PADDR(phy_addr) |
- V_FW_LDST_CMD_MMD(mmd));
- c.u.mdio.raddr = htons(reg);
+ ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO);
+ c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_READ |
+ ldst_addrspace);
+ c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
+ c.u.mdio.paddr_mmd = cpu_to_be16(V_FW_LDST_CMD_PADDR(phy_addr) |
+ V_FW_LDST_CMD_MMD(mmd));
+ c.u.mdio.raddr = cpu_to_be16(reg);
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
if (ret == 0)
- *valp = ntohs(c.u.mdio.rval);
+ *valp = be16_to_cpu(c.u.mdio.rval);
return ret;
}
@@ -4235,197 +5926,212 @@ int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
unsigned int mmd, unsigned int reg, unsigned int val)
{
+ u32 ldst_addrspace;
struct fw_ldst_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE | V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO));
- c.cycles_to_len16 = htonl(FW_LEN16(c));
- c.u.mdio.paddr_mmd = htons(V_FW_LDST_CMD_PADDR(phy_addr) |
- V_FW_LDST_CMD_MMD(mmd));
- c.u.mdio.raddr = htons(reg);
- c.u.mdio.rval = htons(val);
+ ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO);
+ c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+ ldst_addrspace);
+ c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
+ c.u.mdio.paddr_mmd = cpu_to_be16(V_FW_LDST_CMD_PADDR(phy_addr) |
+ V_FW_LDST_CMD_MMD(mmd));
+ c.u.mdio.raddr = cpu_to_be16(reg);
+ c.u.mdio.rval = cpu_to_be16(val);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
/**
- * t4_i2c_rd - read I2C data from adapter
- * @adap: the adapter
- * @port: Port number if per-port device; <0 if not
- * @devid: per-port device ID or absolute device ID
- * @offset: byte offset into device I2C space
- * @len: byte length of I2C space data
- * @buf: buffer in which to return I2C data
*
- * Reads the I2C data from the indicated device and location.
- */
-int t4_i2c_rd(struct adapter *adap, unsigned int mbox,
- int port, unsigned int devid,
- unsigned int offset, unsigned int len,
- u8 *buf)
-{
- struct fw_ldst_cmd ldst;
- int ret;
-
- if (port >= 4 ||
- devid >= 256 ||
- offset >= 256 ||
- len > sizeof ldst.u.i2c.data)
- return -EINVAL;
-
- memset(&ldst, 0, sizeof ldst);
- ldst.op_to_addrspace =
- cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
- F_FW_CMD_REQUEST |
- F_FW_CMD_READ |
- V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C));
- ldst.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst));
- ldst.u.i2c.pid = (port < 0 ? 0xff : port);
- ldst.u.i2c.did = devid;
- ldst.u.i2c.boffset = offset;
- ldst.u.i2c.blen = len;
- ret = t4_wr_mbox(adap, mbox, &ldst, sizeof ldst, &ldst);
- if (!ret)
- memcpy(buf, ldst.u.i2c.data, len);
- return ret;
-}
-
-/**
- * t4_i2c_wr - write I2C data to adapter
+ * t4_sge_decode_idma_state - decode the idma state
* @adap: the adapter
- * @port: Port number if per-port device; <0 if not
- * @devid: per-port device ID or absolute device ID
- * @offset: byte offset into device I2C space
- * @len: byte length of I2C space data
- * @buf: buffer containing new I2C data
- *
- * Write the I2C data to the indicated device and location.
- */
-int t4_i2c_wr(struct adapter *adap, unsigned int mbox,
- int port, unsigned int devid,
- unsigned int offset, unsigned int len,
- u8 *buf)
-{
- struct fw_ldst_cmd ldst;
+ * @state: the state idma is stuck in
+ */
+void t4_sge_decode_idma_state(struct adapter *adapter, int state)
+{
+ static const char * const t4_decode[] = {
+ "IDMA_IDLE",
+ "IDMA_PUSH_MORE_CPL_FIFO",
+ "IDMA_PUSH_CPL_MSG_HEADER_TO_FIFO",
+ "Not used",
+ "IDMA_PHYSADDR_SEND_PCIEHDR",
+ "IDMA_PHYSADDR_SEND_PAYLOAD_FIRST",
+ "IDMA_PHYSADDR_SEND_PAYLOAD",
+ "IDMA_SEND_FIFO_TO_IMSG",
+ "IDMA_FL_REQ_DATA_FL_PREP",
+ "IDMA_FL_REQ_DATA_FL",
+ "IDMA_FL_DROP",
+ "IDMA_FL_H_REQ_HEADER_FL",
+ "IDMA_FL_H_SEND_PCIEHDR",
+ "IDMA_FL_H_PUSH_CPL_FIFO",
+ "IDMA_FL_H_SEND_CPL",
+ "IDMA_FL_H_SEND_IP_HDR_FIRST",
+ "IDMA_FL_H_SEND_IP_HDR",
+ "IDMA_FL_H_REQ_NEXT_HEADER_FL",
+ "IDMA_FL_H_SEND_NEXT_PCIEHDR",
+ "IDMA_FL_H_SEND_IP_HDR_PADDING",
+ "IDMA_FL_D_SEND_PCIEHDR",
+ "IDMA_FL_D_SEND_CPL_AND_IP_HDR",
+ "IDMA_FL_D_REQ_NEXT_DATA_FL",
+ "IDMA_FL_SEND_PCIEHDR",
+ "IDMA_FL_PUSH_CPL_FIFO",
+ "IDMA_FL_SEND_CPL",
+ "IDMA_FL_SEND_PAYLOAD_FIRST",
+ "IDMA_FL_SEND_PAYLOAD",
+ "IDMA_FL_REQ_NEXT_DATA_FL",
+ "IDMA_FL_SEND_NEXT_PCIEHDR",
+ "IDMA_FL_SEND_PADDING",
+ "IDMA_FL_SEND_COMPLETION_TO_IMSG",
+ "IDMA_FL_SEND_FIFO_TO_IMSG",
+ "IDMA_FL_REQ_DATAFL_DONE",
+ "IDMA_FL_REQ_HEADERFL_DONE",
+ };
+ static const char * const t5_decode[] = {
+ "IDMA_IDLE",
+ "IDMA_ALMOST_IDLE",
+ "IDMA_PUSH_MORE_CPL_FIFO",
+ "IDMA_PUSH_CPL_MSG_HEADER_TO_FIFO",
+ "IDMA_SGEFLRFLUSH_SEND_PCIEHDR",
+ "IDMA_PHYSADDR_SEND_PCIEHDR",
+ "IDMA_PHYSADDR_SEND_PAYLOAD_FIRST",
+ "IDMA_PHYSADDR_SEND_PAYLOAD",
+ "IDMA_SEND_FIFO_TO_IMSG",
+ "IDMA_FL_REQ_DATA_FL",
+ "IDMA_FL_DROP",
+ "IDMA_FL_DROP_SEND_INC",
+ "IDMA_FL_H_REQ_HEADER_FL",
+ "IDMA_FL_H_SEND_PCIEHDR",
+ "IDMA_FL_H_PUSH_CPL_FIFO",
+ "IDMA_FL_H_SEND_CPL",
+ "IDMA_FL_H_SEND_IP_HDR_FIRST",
+ "IDMA_FL_H_SEND_IP_HDR",
+ "IDMA_FL_H_REQ_NEXT_HEADER_FL",
+ "IDMA_FL_H_SEND_NEXT_PCIEHDR",
+ "IDMA_FL_H_SEND_IP_HDR_PADDING",
+ "IDMA_FL_D_SEND_PCIEHDR",
+ "IDMA_FL_D_SEND_CPL_AND_IP_HDR",
+ "IDMA_FL_D_REQ_NEXT_DATA_FL",
+ "IDMA_FL_SEND_PCIEHDR",
+ "IDMA_FL_PUSH_CPL_FIFO",
+ "IDMA_FL_SEND_CPL",
+ "IDMA_FL_SEND_PAYLOAD_FIRST",
+ "IDMA_FL_SEND_PAYLOAD",
+ "IDMA_FL_REQ_NEXT_DATA_FL",
+ "IDMA_FL_SEND_NEXT_PCIEHDR",
+ "IDMA_FL_SEND_PADDING",
+ "IDMA_FL_SEND_COMPLETION_TO_IMSG",
+ };
+ static const char * const t6_decode[] = {
+ "IDMA_IDLE",
+ "IDMA_PUSH_MORE_CPL_FIFO",
+ "IDMA_PUSH_CPL_MSG_HEADER_TO_FIFO",
+ "IDMA_SGEFLRFLUSH_SEND_PCIEHDR",
+ "IDMA_PHYSADDR_SEND_PCIEHDR",
+ "IDMA_PHYSADDR_SEND_PAYLOAD_FIRST",
+ "IDMA_PHYSADDR_SEND_PAYLOAD",
+ "IDMA_FL_REQ_DATA_FL",
+ "IDMA_FL_DROP",
+ "IDMA_FL_DROP_SEND_INC",
+ "IDMA_FL_H_REQ_HEADER_FL",
+ "IDMA_FL_H_SEND_PCIEHDR",
+ "IDMA_FL_H_PUSH_CPL_FIFO",
+ "IDMA_FL_H_SEND_CPL",
+ "IDMA_FL_H_SEND_IP_HDR_FIRST",
+ "IDMA_FL_H_SEND_IP_HDR",
+ "IDMA_FL_H_REQ_NEXT_HEADER_FL",
+ "IDMA_FL_H_SEND_NEXT_PCIEHDR",
+ "IDMA_FL_H_SEND_IP_HDR_PADDING",
+ "IDMA_FL_D_SEND_PCIEHDR",
+ "IDMA_FL_D_SEND_CPL_AND_IP_HDR",
+ "IDMA_FL_D_REQ_NEXT_DATA_FL",
+ "IDMA_FL_SEND_PCIEHDR",
+ "IDMA_FL_PUSH_CPL_FIFO",
+ "IDMA_FL_SEND_CPL",
+ "IDMA_FL_SEND_PAYLOAD_FIRST",
+ "IDMA_FL_SEND_PAYLOAD",
+ "IDMA_FL_REQ_NEXT_DATA_FL",
+ "IDMA_FL_SEND_NEXT_PCIEHDR",
+ "IDMA_FL_SEND_PADDING",
+ "IDMA_FL_SEND_COMPLETION_TO_IMSG",
+ };
+ static const u32 sge_regs[] = {
+ A_SGE_DEBUG_DATA_LOW_INDEX_2,
+ A_SGE_DEBUG_DATA_LOW_INDEX_3,
+ A_SGE_DEBUG_DATA_HIGH_INDEX_10,
+ };
+ const char * const *sge_idma_decode;
+ int sge_idma_decode_nstates;
+ int i;
+ unsigned int chip_version = chip_id(adapter);
- if (port >= 4 ||
- devid >= 256 ||
- offset >= 256 ||
- len > sizeof ldst.u.i2c.data)
- return -EINVAL;
+ /* Select the right set of decode strings to dump depending on the
+ * adapter chip type.
+ */
+ switch (chip_version) {
+ case CHELSIO_T4:
+ sge_idma_decode = (const char * const *)t4_decode;
+ sge_idma_decode_nstates = ARRAY_SIZE(t4_decode);
+ break;
- memset(&ldst, 0, sizeof ldst);
- ldst.op_to_addrspace =
- cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
- F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE |
- V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C));
- ldst.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst));
- ldst.u.i2c.pid = (port < 0 ? 0xff : port);
- ldst.u.i2c.did = devid;
- ldst.u.i2c.boffset = offset;
- ldst.u.i2c.blen = len;
- memcpy(ldst.u.i2c.data, buf, len);
- return t4_wr_mbox(adap, mbox, &ldst, sizeof ldst, &ldst);
-}
+ case CHELSIO_T5:
+ sge_idma_decode = (const char * const *)t5_decode;
+ sge_idma_decode_nstates = ARRAY_SIZE(t5_decode);
+ break;
-/**
- * t4_sge_ctxt_flush - flush the SGE context cache
- * @adap: the adapter
- * @mbox: mailbox to use for the FW command
- *
- * Issues a FW command through the given mailbox to flush the
- * SGE context cache.
- */
-int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox)
-{
- int ret;
- struct fw_ldst_cmd c;
+ case CHELSIO_T6:
+ sge_idma_decode = (const char * const *)t6_decode;
+ sge_idma_decode_nstates = ARRAY_SIZE(t6_decode);
+ break;
- memset(&c, 0, sizeof(c));
- c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_READ |
- V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_SGE_EGRC));
- c.cycles_to_len16 = htonl(FW_LEN16(c));
- c.u.idctxt.msg_ctxtflush = htonl(F_FW_LDST_CMD_CTXTFLUSH);
+ default:
+ CH_ERR(adapter, "Unsupported chip version %d\n", chip_version);
+ return;
+ }
- ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
- return ret;
+ if (state < sge_idma_decode_nstates)
+ CH_WARN(adapter, "idma state %s\n", sge_idma_decode[state]);
+ else
+ CH_WARN(adapter, "idma state %d unknown\n", state);
+
+ for (i = 0; i < ARRAY_SIZE(sge_regs); i++)
+ CH_WARN(adapter, "SGE register %#x value %#x\n",
+ sge_regs[i], t4_read_reg(adapter, sge_regs[i]));
}
/**
- * t4_sge_ctxt_rd - read an SGE context through FW
- * @adap: the adapter
- * @mbox: mailbox to use for the FW command
- * @cid: the context id
- * @ctype: the context type
- * @data: where to store the context data
+ * t4_sge_ctxt_flush - flush the SGE context cache
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
*
- * Issues a FW command through the given mailbox to read an SGE context.
+ * Issues a FW command through the given mailbox to flush the
+ * SGE context cache.
*/
-int t4_sge_ctxt_rd(struct adapter *adap, unsigned int mbox, unsigned int cid,
- enum ctxt_type ctype, u32 *data)
+int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox)
{
int ret;
+ u32 ldst_addrspace;
struct fw_ldst_cmd c;
- if (ctype == CTXT_EGRESS)
- ret = FW_LDST_ADDRSPC_SGE_EGRC;
- else if (ctype == CTXT_INGRESS)
- ret = FW_LDST_ADDRSPC_SGE_INGC;
- else if (ctype == CTXT_FLM)
- ret = FW_LDST_ADDRSPC_SGE_FLMC;
- else
- ret = FW_LDST_ADDRSPC_SGE_CONMC;
-
memset(&c, 0, sizeof(c));
- c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_READ | V_FW_LDST_CMD_ADDRSPACE(ret));
- c.cycles_to_len16 = htonl(FW_LEN16(c));
- c.u.idctxt.physid = htonl(cid);
+ ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_SGE_EGRC);
+ c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_READ |
+ ldst_addrspace);
+ c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
+ c.u.idctxt.msg_ctxtflush = cpu_to_be32(F_FW_LDST_CMD_CTXTFLUSH);
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
- if (ret == 0) {
- data[0] = ntohl(c.u.idctxt.ctxt_data0);
- data[1] = ntohl(c.u.idctxt.ctxt_data1);
- data[2] = ntohl(c.u.idctxt.ctxt_data2);
- data[3] = ntohl(c.u.idctxt.ctxt_data3);
- data[4] = ntohl(c.u.idctxt.ctxt_data4);
- data[5] = ntohl(c.u.idctxt.ctxt_data5);
- }
- return ret;
-}
-
-/**
- * t4_sge_ctxt_rd_bd - read an SGE context bypassing FW
- * @adap: the adapter
- * @cid: the context id
- * @ctype: the context type
- * @data: where to store the context data
- *
- * Reads an SGE context directly, bypassing FW. This is only for
- * debugging when FW is unavailable.
- */
-int t4_sge_ctxt_rd_bd(struct adapter *adap, unsigned int cid, enum ctxt_type ctype,
- u32 *data)
-{
- int i, ret;
-
- t4_write_reg(adap, A_SGE_CTXT_CMD, V_CTXTQID(cid) | V_CTXTTYPE(ctype));
- ret = t4_wait_op_done(adap, A_SGE_CTXT_CMD, F_BUSY, 0, 3, 1);
- if (!ret)
- for (i = A_SGE_CTXT_DATA0; i <= A_SGE_CTXT_DATA5; i += 4)
- *data++ = t4_read_reg(adap, i);
return ret;
}
/**
- * t4_fw_hello - establish communication with FW
- * @adap: the adapter
- * @mbox: mailbox to use for the FW command
- * @evt_mbox: mailbox to receive async FW events
- * @master: specifies the caller's willingness to be the device master
+ * t4_fw_hello - establish communication with FW
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @evt_mbox: mailbox to receive async FW events
+ * @master: specifies the caller's willingness to be the device master
* @state: returns the current device state (if non-NULL)
*
* Issues a command to establish communication with FW. Returns either
@@ -4443,11 +6149,11 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
retry:
memset(&c, 0, sizeof(c));
INIT_CMD(c, HELLO, WRITE);
- c.err_to_clearinit = htonl(
+ c.err_to_clearinit = cpu_to_be32(
V_FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) |
V_FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) |
- V_FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox :
- M_FW_HELLO_CMD_MBMASTER) |
+ V_FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ?
+ mbox : M_FW_HELLO_CMD_MBMASTER) |
V_FW_HELLO_CMD_MBASYNCNOT(evt_mbox) |
V_FW_HELLO_CMD_STAGE(FW_HELLO_CMD_STAGE_OS) |
F_FW_HELLO_CMD_CLEARINIT);
@@ -4468,7 +6174,7 @@ retry:
return ret;
}
- v = ntohl(c.err_to_clearinit);
+ v = be32_to_cpu(c.err_to_clearinit);
master_mbox = G_FW_HELLO_CMD_MBMASTER(v);
if (state) {
if (v & F_FW_HELLO_CMD_ERR)
@@ -4580,7 +6286,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
memset(&c, 0, sizeof(c));
INIT_CMD(c, RESET, WRITE);
- c.val = htonl(reset);
+ c.val = cpu_to_be32(reset);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -4613,8 +6319,8 @@ int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
memset(&c, 0, sizeof(c));
INIT_CMD(c, RESET, WRITE);
- c.val = htonl(F_PIORST | F_PIORSTMODE);
- c.halt_pkd = htonl(F_FW_RESET_CMD_HALT);
+ c.val = cpu_to_be32(F_PIORST | F_PIORSTMODE);
+ c.halt_pkd = cpu_to_be32(F_FW_RESET_CMD_HALT);
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -4633,7 +6339,8 @@ int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
*/
if (ret == 0 || force) {
t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, F_UPCRST);
- t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT, F_PCIE_FW_HALT);
+ t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT,
+ F_PCIE_FW_HALT);
}
/*
@@ -4731,9 +6438,13 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
const u8 *fw_data, unsigned int size, int force)
{
const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
- unsigned int bootstrap = ntohl(fw_hdr->magic) == FW_HDR_MAGIC_BOOTSTRAP;
+ unsigned int bootstrap =
+ be32_to_cpu(fw_hdr->magic) == FW_HDR_MAGIC_BOOTSTRAP;
int reset, ret;
+ if (!t4_fw_matches_chip(adap, fw_hdr))
+ return -EINVAL;
+
if (!bootstrap) {
ret = t4_fw_halt(adap, mbox, force);
if (ret < 0 && !force)
@@ -4752,7 +6463,7 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
* the newly loaded firmware will handle this right by checking
* its header flags to see if it advertises the capability.
*/
- reset = ((ntohl(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0);
+ reset = ((be32_to_cpu(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0);
return t4_fw_restart(adap, mbox, reset);
}
@@ -4774,7 +6485,7 @@ int t4_fw_initialize(struct adapter *adap, unsigned int mbox)
}
/**
- * t4_query_params - query FW or device parameters
+ * t4_query_params_rw - query FW or device parameters
* @adap: the adapter
* @mbox: mailbox to use for the FW command
* @pf: the PF
@@ -4782,13 +6493,14 @@ int t4_fw_initialize(struct adapter *adap, unsigned int mbox)
* @nparams: the number of parameters
* @params: the parameter names
* @val: the parameter values
+ * @rw: Write and read flag
*
* Reads the value of FW or device parameters. Up to 7 parameters can be
* queried at once.
*/
-int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
- unsigned int vf, unsigned int nparams, const u32 *params,
- u32 *val)
+int t4_query_params_rw(struct adapter *adap, unsigned int mbox, unsigned int pf,
+ unsigned int vf, unsigned int nparams, const u32 *params,
+ u32 *val, int rw)
{
int i, ret;
struct fw_params_cmd c;
@@ -4798,21 +6510,73 @@ int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
return -EINVAL;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_PARAMS_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_READ | V_FW_PARAMS_CMD_PFN(pf) |
- V_FW_PARAMS_CMD_VFN(vf));
- c.retval_len16 = htonl(FW_LEN16(c));
-
- for (i = 0; i < nparams; i++, p += 2, params++)
- *p = htonl(*params);
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PARAMS_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_READ |
+ V_FW_PARAMS_CMD_PFN(pf) |
+ V_FW_PARAMS_CMD_VFN(vf));
+ c.retval_len16 = cpu_to_be32(FW_LEN16(c));
+
+ for (i = 0; i < nparams; i++) {
+ *p++ = cpu_to_be32(*params++);
+ if (rw)
+ *p = cpu_to_be32(*(val + i));
+ p++;
+ }
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
if (ret == 0)
for (i = 0, p = &c.param[0].val; i < nparams; i++, p += 2)
- *val++ = ntohl(*p);
+ *val++ = be32_to_cpu(*p);
return ret;
}
+int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
+ unsigned int vf, unsigned int nparams, const u32 *params,
+ u32 *val)
+{
+ return t4_query_params_rw(adap, mbox, pf, vf, nparams, params, val, 0);
+}
+
+/**
+ * t4_set_params_timeout - sets FW or device parameters
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @pf: the PF
+ * @vf: the VF
+ * @nparams: the number of parameters
+ * @params: the parameter names
+ * @val: the parameter values
+ * @timeout: the timeout time
+ *
+ * Sets the value of FW or device parameters. Up to 7 parameters can be
+ * specified at once.
+ */
+int t4_set_params_timeout(struct adapter *adap, unsigned int mbox,
+ unsigned int pf, unsigned int vf,
+ unsigned int nparams, const u32 *params,
+ const u32 *val, int timeout)
+{
+ struct fw_params_cmd c;
+ __be32 *p = &c.param[0].mnem;
+
+ if (nparams > 7)
+ return -EINVAL;
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PARAMS_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+ V_FW_PARAMS_CMD_PFN(pf) |
+ V_FW_PARAMS_CMD_VFN(vf));
+ c.retval_len16 = cpu_to_be32(FW_LEN16(c));
+
+ while (nparams--) {
+ *p++ = cpu_to_be32(*params++);
+ *p++ = cpu_to_be32(*val++);
+ }
+
+ return t4_wr_mbox_timeout(adap, mbox, &c, sizeof(c), NULL, timeout);
+}
+
/**
* t4_set_params - sets FW or device parameters
* @adap: the adapter
@@ -4830,26 +6594,8 @@ int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int nparams, const u32 *params,
const u32 *val)
{
- struct fw_params_cmd c;
- __be32 *p = &c.param[0].mnem;
-
- if (nparams > 7)
- return -EINVAL;
-
- memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_PARAMS_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE | V_FW_PARAMS_CMD_PFN(pf) |
- V_FW_PARAMS_CMD_VFN(vf));
- c.retval_len16 = htonl(FW_LEN16(c));
-
- while (nparams--) {
- *p++ = htonl(*params);
- params++;
- *p++ = htonl(*val);
- val++;
- }
-
- return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+ return t4_set_params_timeout(adap, mbox, pf, vf, nparams, params, val,
+ FW_CMD_MAX_TIMEOUT);
}
/**
@@ -4882,18 +6628,19 @@ int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
struct fw_pfvf_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_PFVF_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE | V_FW_PFVF_CMD_PFN(pf) |
- V_FW_PFVF_CMD_VFN(vf));
- c.retval_len16 = htonl(FW_LEN16(c));
- c.niqflint_niq = htonl(V_FW_PFVF_CMD_NIQFLINT(rxqi) |
- V_FW_PFVF_CMD_NIQ(rxq));
- c.type_to_neq = htonl(V_FW_PFVF_CMD_CMASK(cmask) |
- V_FW_PFVF_CMD_PMASK(pmask) |
- V_FW_PFVF_CMD_NEQ(txq));
- c.tc_to_nexactf = htonl(V_FW_PFVF_CMD_TC(tc) | V_FW_PFVF_CMD_NVI(vi) |
- V_FW_PFVF_CMD_NEXACTF(nexact));
- c.r_caps_to_nethctrl = htonl(V_FW_PFVF_CMD_R_CAPS(rcaps) |
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE | V_FW_PFVF_CMD_PFN(pf) |
+ V_FW_PFVF_CMD_VFN(vf));
+ c.retval_len16 = cpu_to_be32(FW_LEN16(c));
+ c.niqflint_niq = cpu_to_be32(V_FW_PFVF_CMD_NIQFLINT(rxqi) |
+ V_FW_PFVF_CMD_NIQ(rxq));
+ c.type_to_neq = cpu_to_be32(V_FW_PFVF_CMD_CMASK(cmask) |
+ V_FW_PFVF_CMD_PMASK(pmask) |
+ V_FW_PFVF_CMD_NEQ(txq));
+ c.tc_to_nexactf = cpu_to_be32(V_FW_PFVF_CMD_TC(tc) |
+ V_FW_PFVF_CMD_NVI(vi) |
+ V_FW_PFVF_CMD_NEXACTF(nexact));
+ c.r_caps_to_nethctrl = cpu_to_be32(V_FW_PFVF_CMD_R_CAPS(rcaps) |
V_FW_PFVF_CMD_WX_CAPS(wxcaps) |
V_FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl));
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
@@ -4914,6 +6661,7 @@ int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
*
* Allocates a virtual interface for the given physical port. If @mac is
* not %NULL it contains the MAC addresses of the VI as assigned by FW.
+ * If @rss_size is %NULL the VI is not assigned any RSS slice by FW.
* @mac should be large enough to hold @nmac Ethernet addresses, they are
* stored consecutively so the space needed is @nmac * 6 bytes.
* Returns a negative error number or the non-negative VI id.
@@ -4927,14 +6675,16 @@ int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
struct fw_vi_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_VI_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE | F_FW_CMD_EXEC |
- V_FW_VI_CMD_PFN(pf) | V_FW_VI_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(F_FW_VI_CMD_ALLOC | FW_LEN16(c));
- c.type_to_viid = htons(V_FW_VI_CMD_TYPE(idstype) |
- V_FW_VI_CMD_FUNC(portfunc));
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_VI_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE | F_FW_CMD_EXEC |
+ V_FW_VI_CMD_PFN(pf) | V_FW_VI_CMD_VFN(vf));
+ c.alloc_to_len16 = cpu_to_be32(F_FW_VI_CMD_ALLOC | FW_LEN16(c));
+ c.type_to_viid = cpu_to_be16(V_FW_VI_CMD_TYPE(idstype) |
+ V_FW_VI_CMD_FUNC(portfunc));
c.portid_pkd = V_FW_VI_CMD_PORTID(port);
c.nmac = nmac - 1;
+ if(!rss_size)
+ c.norss_rsssize = F_FW_VI_CMD_NORSS;
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
if (ret)
@@ -4954,20 +6704,20 @@ int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
}
}
if (rss_size)
- *rss_size = G_FW_VI_CMD_RSSSIZE(ntohs(c.norss_rsssize));
- return G_FW_VI_CMD_VIID(htons(c.type_to_viid));
+ *rss_size = G_FW_VI_CMD_RSSSIZE(be16_to_cpu(c.norss_rsssize));
+ return G_FW_VI_CMD_VIID(be16_to_cpu(c.type_to_viid));
}
/**
- * t4_alloc_vi - allocate an [Ethernet Function] virtual interface
- * @adap: the adapter
- * @mbox: mailbox to use for the FW command
- * @port: physical port associated with the VI
- * @pf: the PF owning the VI
- * @vf: the VF owning the VI
- * @nmac: number of MAC addresses needed (1 to 5)
- * @mac: the MAC addresses of the VI
- * @rss_size: size of RSS table slice associated with this VI
+ * t4_alloc_vi - allocate an [Ethernet Function] virtual interface
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @port: physical port associated with the VI
+ * @pf: the PF owning the VI
+ * @vf: the VF owning the VI
+ * @nmac: number of MAC addresses needed (1 to 5)
+ * @mac: the MAC addresses of the VI
+ * @rss_size: size of RSS table slice associated with this VI
*
* backwards compatible and convieniance routine to allocate a Virtual
* Interface with a Ethernet Port Application Function and Intrustion
@@ -4982,14 +6732,14 @@ int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
}
/**
- * t4_free_vi - free a virtual interface
- * @adap: the adapter
- * @mbox: mailbox to use for the FW command
- * @pf: the PF owning the VI
- * @vf: the VF owning the VI
- * @viid: virtual interface identifiler
+ * t4_free_vi - free a virtual interface
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @pf: the PF owning the VI
+ * @vf: the VF owning the VI
+ * @viid: virtual interface identifiler
*
- * Free a previously allocated virtual interface.
+ * Free a previously allocated virtual interface.
*/
int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int viid)
@@ -4997,13 +6747,13 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
struct fw_vi_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_VI_CMD) |
- F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC |
- V_FW_VI_CMD_PFN(pf) |
- V_FW_VI_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(F_FW_VI_CMD_FREE | FW_LEN16(c));
- c.type_to_viid = htons(V_FW_VI_CMD_VIID(viid));
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_VI_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_EXEC |
+ V_FW_VI_CMD_PFN(pf) |
+ V_FW_VI_CMD_VFN(vf));
+ c.alloc_to_len16 = cpu_to_be32(F_FW_VI_CMD_FREE | FW_LEN16(c));
+ c.type_to_viid = cpu_to_be16(V_FW_VI_CMD_VIID(viid));
return t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
}
@@ -5017,7 +6767,7 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
* @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change
* @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change
* @bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change
- * @vlanex: 1 to enable HVLAN extraction, 0 to disable it, -1 no change
+ * @vlanex: 1 to enable HW VLAN extraction, 0 to disable it, -1 no change
* @sleep_ok: if true we may sleep while awaiting command completion
*
* Sets Rx properties of a virtual interface.
@@ -5041,14 +6791,16 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
vlanex = M_FW_VI_RXMODE_CMD_VLANEXEN;
memset(&c, 0, sizeof(c));
- c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_RXMODE_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE | V_FW_VI_RXMODE_CMD_VIID(viid));
- c.retval_len16 = htonl(FW_LEN16(c));
- c.mtu_to_vlanexen = htonl(V_FW_VI_RXMODE_CMD_MTU(mtu) |
- V_FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
- V_FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
- V_FW_VI_RXMODE_CMD_BROADCASTEN(bcast) |
- V_FW_VI_RXMODE_CMD_VLANEXEN(vlanex));
+ c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_RXMODE_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+ V_FW_VI_RXMODE_CMD_VIID(viid));
+ c.retval_len16 = cpu_to_be32(FW_LEN16(c));
+ c.mtu_to_vlanexen =
+ cpu_to_be32(V_FW_VI_RXMODE_CMD_MTU(mtu) |
+ V_FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
+ V_FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
+ V_FW_VI_RXMODE_CMD_BROADCASTEN(bcast) |
+ V_FW_VI_RXMODE_CMD_VLANEXEN(vlanex));
return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
}
@@ -5081,9 +6833,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
int offset, ret = 0;
struct fw_vi_mac_cmd c;
unsigned int nfilters = 0;
- unsigned int max_naddr = is_t4(adap) ?
- NUM_MPS_CLS_SRAM_L_INSTANCES :
- NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
+ unsigned int max_naddr = adap->chip_params->mps_tcam_size;
unsigned int rem = naddr;
if (naddr > max_naddr)
@@ -5099,18 +6849,18 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
int i;
memset(&c, 0, sizeof(c));
- c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) |
- F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE |
- V_FW_CMD_EXEC(free) |
- V_FW_VI_MAC_CMD_VIID(viid));
- c.freemacs_to_len16 = htonl(V_FW_VI_MAC_CMD_FREEMACS(free) |
- V_FW_CMD_LEN16(len16));
+ c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE |
+ V_FW_CMD_EXEC(free) |
+ V_FW_VI_MAC_CMD_VIID(viid));
+ c.freemacs_to_len16 = cpu_to_be32(V_FW_VI_MAC_CMD_FREEMACS(free) |
+ V_FW_CMD_LEN16(len16));
for (i = 0, p = c.u.exact; i < fw_naddr; i++, p++) {
- p->valid_to_idx = htons(
- F_FW_VI_MAC_CMD_VALID |
- V_FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
+ p->valid_to_idx =
+ cpu_to_be16(F_FW_VI_MAC_CMD_VALID |
+ V_FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
}
@@ -5124,7 +6874,8 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
break;
for (i = 0, p = c.u.exact; i < fw_naddr; i++, p++) {
- u16 index = G_FW_VI_MAC_CMD_IDX(ntohs(p->valid_to_idx));
+ u16 index = G_FW_VI_MAC_CMD_IDX(
+ be16_to_cpu(p->valid_to_idx));
if (idx)
idx[offset+i] = (index >= max_naddr
@@ -5142,7 +6893,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
}
if (ret == 0 || ret == -FW_ENOMEM)
- ret = nfilters;
+ ret = nfilters;
return ret;
}
@@ -5174,26 +6925,25 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
int ret, mode;
struct fw_vi_mac_cmd c;
struct fw_vi_mac_exact *p = c.u.exact;
- unsigned int max_mac_addr = is_t4(adap) ?
- NUM_MPS_CLS_SRAM_L_INSTANCES :
- NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
+ unsigned int max_mac_addr = adap->chip_params->mps_tcam_size;
- if (idx < 0) /* new allocation */
+ if (idx < 0) /* new allocation */
idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC;
mode = add_smt ? FW_VI_MAC_SMT_AND_MPSTCAM : FW_VI_MAC_MPS_TCAM_ENTRY;
memset(&c, 0, sizeof(c));
- c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(viid));
- c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(1));
- p->valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID |
- V_FW_VI_MAC_CMD_SMAC_RESULT(mode) |
- V_FW_VI_MAC_CMD_IDX(idx));
+ c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+ V_FW_VI_MAC_CMD_VIID(viid));
+ c.freemacs_to_len16 = cpu_to_be32(V_FW_CMD_LEN16(1));
+ p->valid_to_idx = cpu_to_be16(F_FW_VI_MAC_CMD_VALID |
+ V_FW_VI_MAC_CMD_SMAC_RESULT(mode) |
+ V_FW_VI_MAC_CMD_IDX(idx));
memcpy(p->macaddr, addr, sizeof(p->macaddr));
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
if (ret == 0) {
- ret = G_FW_VI_MAC_CMD_IDX(ntohs(p->valid_to_idx));
+ ret = G_FW_VI_MAC_CMD_IDX(be16_to_cpu(p->valid_to_idx));
if (ret >= max_mac_addr)
ret = -ENOMEM;
}
@@ -5215,18 +6965,48 @@ int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
bool ucast, u64 vec, bool sleep_ok)
{
struct fw_vi_mac_cmd c;
+ u32 val;
memset(&c, 0, sizeof(c));
- c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_WRITE | V_FW_VI_ENABLE_CMD_VIID(viid));
- c.freemacs_to_len16 = htonl(F_FW_VI_MAC_CMD_HASHVECEN |
- V_FW_VI_MAC_CMD_HASHUNIEN(ucast) |
- V_FW_CMD_LEN16(1));
+ c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
+ V_FW_VI_ENABLE_CMD_VIID(viid));
+ val = V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_HASHVEC) |
+ V_FW_VI_MAC_CMD_HASHUNIEN(ucast) | V_FW_CMD_LEN16(1);
+ c.freemacs_to_len16 = cpu_to_be32(val);
c.u.hash.hashvec = cpu_to_be64(vec);
return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
}
/**
+ * t4_enable_vi_params - enable/disable a virtual interface
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @viid: the VI id
+ * @rx_en: 1=enable Rx, 0=disable Rx
+ * @tx_en: 1=enable Tx, 0=disable Tx
+ * @dcb_en: 1=enable delivery of Data Center Bridging messages.
+ *
+ * Enables/disables a virtual interface. Note that setting DCB Enable
+ * only makes sense when enabling a Virtual Interface ...
+ */
+int t4_enable_vi_params(struct adapter *adap, unsigned int mbox,
+ unsigned int viid, bool rx_en, bool tx_en, bool dcb_en)
+{
+ struct fw_vi_enable_cmd c;
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_ENABLE_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
+ V_FW_VI_ENABLE_CMD_VIID(viid));
+ c.ien_to_len16 = cpu_to_be32(V_FW_VI_ENABLE_CMD_IEN(rx_en) |
+ V_FW_VI_ENABLE_CMD_EEN(tx_en) |
+ V_FW_VI_ENABLE_CMD_DCB_INFO(dcb_en) |
+ FW_LEN16(c));
+ return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL);
+}
+
+/**
* t4_enable_vi - enable/disable a virtual interface
* @adap: the adapter
* @mbox: mailbox to use for the FW command
@@ -5234,19 +7014,13 @@ int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
* @rx_en: 1=enable Rx, 0=disable Rx
* @tx_en: 1=enable Tx, 0=disable Tx
*
- * Enables/disables a virtual interface.
+ * Enables/disables a virtual interface. Note that setting DCB Enable
+ * only makes sense when enabling a Virtual Interface ...
*/
int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
bool rx_en, bool tx_en)
{
- struct fw_vi_enable_cmd c;
-
- memset(&c, 0, sizeof(c));
- c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_ENABLE_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_VI_ENABLE_CMD_VIID(viid));
- c.ien_to_len16 = htonl(V_FW_VI_ENABLE_CMD_IEN(rx_en) |
- V_FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c));
- return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+ return t4_enable_vi_params(adap, mbox, viid, rx_en, tx_en, 0);
}
/**
@@ -5264,41 +7038,44 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
struct fw_vi_enable_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_ENABLE_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_VI_ENABLE_CMD_VIID(viid));
- c.ien_to_len16 = htonl(F_FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
- c.blinkdur = htons(nblinks);
+ c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_ENABLE_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
+ V_FW_VI_ENABLE_CMD_VIID(viid));
+ c.ien_to_len16 = cpu_to_be32(F_FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
+ c.blinkdur = cpu_to_be16(nblinks);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
/**
- * t4_iq_start_stop - enable/disable an ingress queue and its FLs
+ * t4_iq_stop - stop an ingress queue and its FLs
* @adap: the adapter
* @mbox: mailbox to use for the FW command
- * @start: %true to enable the queues, %false to disable them
* @pf: the PF owning the queues
* @vf: the VF owning the queues
+ * @iqtype: the ingress queue type (FW_IQ_TYPE_FL_INT_CAP, etc.)
* @iqid: ingress queue id
* @fl0id: FL0 queue id or 0xffff if no attached FL0
* @fl1id: FL1 queue id or 0xffff if no attached FL1
*
- * Starts or stops an ingress queue and its associated FLs, if any.
+ * Stops an ingress queue and its associated FLs, if any. This causes
+ * any current or future data/messages destined for these queues to be
+ * tossed.
*/
-int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start,
- unsigned int pf, unsigned int vf, unsigned int iqid,
- unsigned int fl0id, unsigned int fl1id)
+int t4_iq_stop(struct adapter *adap, unsigned int mbox, unsigned int pf,
+ unsigned int vf, unsigned int iqtype, unsigned int iqid,
+ unsigned int fl0id, unsigned int fl1id)
{
struct fw_iq_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(pf) |
- V_FW_IQ_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(V_FW_IQ_CMD_IQSTART(start) |
- V_FW_IQ_CMD_IQSTOP(!start) | FW_LEN16(c));
- c.iqid = htons(iqid);
- c.fl0id = htons(fl0id);
- c.fl1id = htons(fl1id);
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(pf) |
+ V_FW_IQ_CMD_VFN(vf));
+ c.alloc_to_len16 = cpu_to_be32(F_FW_IQ_CMD_IQSTOP | FW_LEN16(c));
+ c.type_to_iqandstindex = cpu_to_be32(V_FW_IQ_CMD_TYPE(iqtype));
+ c.iqid = cpu_to_be16(iqid);
+ c.fl0id = cpu_to_be16(fl0id);
+ c.fl1id = cpu_to_be16(fl1id);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -5322,14 +7099,14 @@ int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
struct fw_iq_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(pf) |
- V_FW_IQ_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(F_FW_IQ_CMD_FREE | FW_LEN16(c));
- c.type_to_iqandstindex = htonl(V_FW_IQ_CMD_TYPE(iqtype));
- c.iqid = htons(iqid);
- c.fl0id = htons(fl0id);
- c.fl1id = htons(fl1id);
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(pf) |
+ V_FW_IQ_CMD_VFN(vf));
+ c.alloc_to_len16 = cpu_to_be32(F_FW_IQ_CMD_FREE | FW_LEN16(c));
+ c.type_to_iqandstindex = cpu_to_be32(V_FW_IQ_CMD_TYPE(iqtype));
+ c.iqid = cpu_to_be16(iqid);
+ c.fl0id = cpu_to_be16(fl0id);
+ c.fl1id = cpu_to_be16(fl1id);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -5349,11 +7126,12 @@ int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
struct fw_eq_eth_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_EQ_ETH_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_EQ_ETH_CMD_PFN(pf) |
- V_FW_EQ_ETH_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(F_FW_EQ_ETH_CMD_FREE | FW_LEN16(c));
- c.eqid_pkd = htonl(V_FW_EQ_ETH_CMD_EQID(eqid));
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_EQ_ETH_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
+ V_FW_EQ_ETH_CMD_PFN(pf) |
+ V_FW_EQ_ETH_CMD_VFN(vf));
+ c.alloc_to_len16 = cpu_to_be32(F_FW_EQ_ETH_CMD_FREE | FW_LEN16(c));
+ c.eqid_pkd = cpu_to_be32(V_FW_EQ_ETH_CMD_EQID(eqid));
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -5373,11 +7151,12 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
struct fw_eq_ctrl_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_EQ_CTRL_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_EQ_CTRL_CMD_PFN(pf) |
- V_FW_EQ_CTRL_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(F_FW_EQ_CTRL_CMD_FREE | FW_LEN16(c));
- c.cmpliqid_eqid = htonl(V_FW_EQ_CTRL_CMD_EQID(eqid));
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_EQ_CTRL_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
+ V_FW_EQ_CTRL_CMD_PFN(pf) |
+ V_FW_EQ_CTRL_CMD_VFN(vf));
+ c.alloc_to_len16 = cpu_to_be32(F_FW_EQ_CTRL_CMD_FREE | FW_LEN16(c));
+ c.cmpliqid_eqid = cpu_to_be32(V_FW_EQ_CTRL_CMD_EQID(eqid));
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -5397,15 +7176,41 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
struct fw_eq_ofld_cmd c;
memset(&c, 0, sizeof(c));
- c.op_to_vfn = htonl(V_FW_CMD_OP(FW_EQ_OFLD_CMD) | F_FW_CMD_REQUEST |
- F_FW_CMD_EXEC | V_FW_EQ_OFLD_CMD_PFN(pf) |
- V_FW_EQ_OFLD_CMD_VFN(vf));
- c.alloc_to_len16 = htonl(F_FW_EQ_OFLD_CMD_FREE | FW_LEN16(c));
- c.eqid_pkd = htonl(V_FW_EQ_OFLD_CMD_EQID(eqid));
+ c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_EQ_OFLD_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
+ V_FW_EQ_OFLD_CMD_PFN(pf) |
+ V_FW_EQ_OFLD_CMD_VFN(vf));
+ c.alloc_to_len16 = cpu_to_be32(F_FW_EQ_OFLD_CMD_FREE | FW_LEN16(c));
+ c.eqid_pkd = cpu_to_be32(V_FW_EQ_OFLD_CMD_EQID(eqid));
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
/**
+ * t4_link_down_rc_str - return a string for a Link Down Reason Code
+ * @link_down_rc: Link Down Reason Code
+ *
+ * Returns a string representation of the Link Down Reason Code.
+ */
+const char *t4_link_down_rc_str(unsigned char link_down_rc)
+{
+ static const char *reason[] = {
+ "Link Down",
+ "Remote Fault",
+ "Auto-negotiation Failure",
+ "Reserved3",
+ "Insufficient Airflow",
+ "Unable To Determine Reason",
+ "No RX Signal Detected",
+ "Reserved7",
+ };
+
+ if (link_down_rc >= ARRAY_SIZE(reason))
+ return "Bad Reason Code";
+
+ return reason[link_down_rc];
+}
+
+/**
* t4_handle_fw_rpl - process a FW reply message
* @adap: the adapter
* @rpl: start of the FW message
@@ -5416,15 +7221,16 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
{
u8 opcode = *(const u8 *)rpl;
const struct fw_port_cmd *p = (const void *)rpl;
- unsigned int action = G_FW_PORT_CMD_ACTION(ntohl(p->action_to_len16));
+ unsigned int action =
+ G_FW_PORT_CMD_ACTION(be32_to_cpu(p->action_to_len16));
if (opcode == FW_PORT_CMD && action == FW_PORT_ACTION_GET_PORT_INFO) {
/* link/module state change message */
int speed = 0, fc = 0, i;
- int chan = G_FW_PORT_CMD_PORTID(ntohl(p->op_to_portid));
+ int chan = G_FW_PORT_CMD_PORTID(be32_to_cpu(p->op_to_portid));
struct port_info *pi = NULL;
struct link_config *lc;
- u32 stat = ntohl(p->u.info.lstatus_to_modtype);
+ u32 stat = be32_to_cpu(p->u.info.lstatus_to_modtype);
int link_ok = (stat & F_FW_PORT_CMD_LSTATUS) != 0;
u32 mod = G_FW_PORT_CMD_MODTYPE(stat);
@@ -5433,13 +7239,13 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
if (stat & F_FW_PORT_CMD_TXPAUSE)
fc |= PAUSE_TX;
if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
- speed = SPEED_100;
+ speed = 100;
else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
- speed = SPEED_1000;
+ speed = 1000;
else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
- speed = SPEED_10000;
+ speed = 10000;
else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
- speed = SPEED_40000;
+ speed = 40000;
for_each_port(adap, i) {
pi = adap2pinfo(adap, i);
@@ -5464,12 +7270,11 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
lc->link_ok = link_ok;
lc->speed = speed;
lc->fc = fc;
- lc->supported = ntohs(p->u.info.pcap);
+ lc->supported = be16_to_cpu(p->u.info.pcap);
t4_os_link_changed(adap, i, link_ok, reason);
}
} else {
- CH_WARN_RATELIMIT(adap,
- "Unknown firmware reply 0x%x (0x%x)\n", opcode, action);
+ CH_WARN_RATELIMIT(adap, "Unknown firmware reply %d\n", opcode);
return -EINVAL;
}
return 0;
@@ -5483,7 +7288,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
* Determines a card's PCI mode and associated parameters, such as speed
* and width.
*/
-static void __devinit get_pci_mode(struct adapter *adapter,
+static void get_pci_mode(struct adapter *adapter,
struct pci_params *p)
{
u16 val;
@@ -5505,8 +7310,7 @@ static void __devinit get_pci_mode(struct adapter *adapter,
* Initializes the SW state maintained for each link, including the link's
* capabilities and default speed/flow-control/autonegotiation settings.
*/
-static void __devinit init_link_config(struct link_config *lc,
- unsigned int caps)
+static void init_link_config(struct link_config *lc, unsigned int caps)
{
lc->supported = caps;
lc->requested_speed = 0;
@@ -5522,21 +7326,43 @@ static void __devinit init_link_config(struct link_config *lc,
}
}
-static int __devinit get_flash_params(struct adapter *adapter)
+struct flash_desc {
+ u32 vendor_and_model_id;
+ u32 size_mb;
+};
+
+int t4_get_flash_params(struct adapter *adapter)
{
+ /*
+ * Table for non-Numonix supported flash parts. Numonix parts are left
+ * to the preexisting well-tested code. All flash parts have 64KB
+ * sectors.
+ */
+ static struct flash_desc supported_flash[] = {
+ { 0x150201, 4 << 20 }, /* Spansion 4MB S25FL032P */
+ };
+
int ret;
u32 info = 0;
ret = sf1_write(adapter, 1, 1, 0, SF_RD_ID);
if (!ret)
ret = sf1_read(adapter, 3, 0, 1, &info);
- t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
+ t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
if (ret < 0)
return ret;
- if ((info & 0xff) != 0x20) /* not a Numonix flash */
+ for (ret = 0; ret < ARRAY_SIZE(supported_flash); ++ret)
+ if (supported_flash[ret].vendor_and_model_id == info) {
+ adapter->params.sf_size = supported_flash[ret].size_mb;
+ adapter->params.sf_nsec =
+ adapter->params.sf_size / SF_SEC_SIZE;
+ return 0;
+ }
+
+ if ((info & 0xff) != 0x20) /* not a Numonix flash */
return -EINVAL;
- info >>= 16; /* log2 of size */
+ info >>= 16; /* log2 of size */
if (info >= 0x14 && info < 0x18)
adapter->params.sf_nsec = 1 << (info - 16);
else if (info == 0x18)
@@ -5544,10 +7370,20 @@ static int __devinit get_flash_params(struct adapter *adapter)
else
return -EINVAL;
adapter->params.sf_size = 1 << info;
+
+ /*
+ * We should ~probably~ reject adapters with FLASHes which are too
+ * small but we have some legacy FPGAs with small FLASHes that we'd
+ * still like to use. So instead we emit a scary message ...
+ */
+ if (adapter->params.sf_size < FLASH_MIN_SIZE)
+ CH_WARN(adapter, "WARNING!!! FLASH size %#x < %#x!!!\n",
+ adapter->params.sf_size, FLASH_MIN_SIZE);
+
return 0;
}
-static void __devinit set_pcie_completion_timeout(struct adapter *adapter,
+static void set_pcie_completion_timeout(struct adapter *adapter,
u8 range)
{
u16 val;
@@ -5562,16 +7398,64 @@ static void __devinit set_pcie_completion_timeout(struct adapter *adapter,
}
}
+static const struct chip_params *get_chip_params(int chipid)
+{
+ static const struct chip_params chip_params[] = {
+ {
+ /* T4 */
+ .nchan = NCHAN,
+ .pm_stats_cnt = PM_NSTATS,
+ .cng_ch_bits_log = 2,
+ .nsched_cls = 15,
+ .cim_num_obq = CIM_NUM_OBQ,
+ .mps_rplc_size = 128,
+ .vfcount = 128,
+ .sge_fl_db = F_DBPRIO,
+ .mps_tcam_size = NUM_MPS_CLS_SRAM_L_INSTANCES,
+ },
+ {
+ /* T5 */
+ .nchan = NCHAN,
+ .pm_stats_cnt = PM_NSTATS,
+ .cng_ch_bits_log = 2,
+ .nsched_cls = 16,
+ .cim_num_obq = CIM_NUM_OBQ_T5,
+ .mps_rplc_size = 128,
+ .vfcount = 128,
+ .sge_fl_db = F_DBPRIO | F_DBTYPE,
+ .mps_tcam_size = NUM_MPS_T5_CLS_SRAM_L_INSTANCES,
+ },
+ {
+ /* T6 */
+ .nchan = T6_NCHAN,
+ .pm_stats_cnt = T6_PM_NSTATS,
+ .cng_ch_bits_log = 3,
+ .nsched_cls = 16,
+ .cim_num_obq = CIM_NUM_OBQ_T5,
+ .mps_rplc_size = 256,
+ .vfcount = 256,
+ .sge_fl_db = 0,
+ .mps_tcam_size = NUM_MPS_T5_CLS_SRAM_L_INSTANCES,
+ },
+ };
+
+ chipid -= CHELSIO_T4;
+ if (chipid < 0 || chipid >= ARRAY_SIZE(chip_params))
+ return NULL;
+
+ return &chip_params[chipid];
+}
+
/**
* t4_prep_adapter - prepare SW and HW for operation
* @adapter: the adapter
- * @reset: if true perform a HW reset
+ * @buf: temporary space of at least VPD_LEN size provided by the caller.
*
* Initialize adapter SW state for the various HW modules, set initial
* values for some adapter tunables, take PHYs out of reset, and
* initialize the MDIO interface.
*/
-int __devinit t4_prep_adapter(struct adapter *adapter)
+int t4_prep_adapter(struct adapter *adapter, u8 *buf)
{
int ret;
uint16_t device_id;
@@ -5592,20 +7476,25 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
return -EINVAL;
}
}
+
+ adapter->chip_params = get_chip_params(chip_id(adapter));
+ if (adapter->chip_params == NULL)
+ return -EINVAL;
+
adapter->params.pci.vpd_cap_addr =
t4_os_find_pci_capability(adapter, PCI_CAP_ID_VPD);
- ret = get_flash_params(adapter);
+ ret = t4_get_flash_params(adapter);
if (ret < 0)
return ret;
- ret = get_vpd_params(adapter, &adapter->params.vpd);
+ ret = get_vpd_params(adapter, &adapter->params.vpd, buf);
if (ret < 0)
return ret;
/* Cards with real ASICs have the chipid in the PCIe device id */
t4_os_pci_read_cfg2(adapter, PCI_DEVICE_ID, &device_id);
- if (device_id >> 12 == adapter->params.chipid)
+ if (device_id >> 12 == chip_id(adapter))
adapter->params.cim_la_size = CIMLA_SIZE;
else {
/* FPGA */
@@ -5628,40 +7517,258 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
}
/**
- * t4_init_tp_params - initialize adap->params.tp
+ * t4_shutdown_adapter - shut down adapter, host & wire
+ * @adapter: the adapter
+ *
+ * Perform an emergency shutdown of the adapter and stop it from
+ * continuing any further communication on the ports or DMA to the
+ * host. This is typically used when the adapter and/or firmware
+ * have crashed and we want to prevent any further accidental
+ * communication with the rest of the world. This will also force
+ * the port Link Status to go down -- if register writes work --
+ * which should help our peers figure out that we're down.
+ */
+int t4_shutdown_adapter(struct adapter *adapter)
+{
+ int port;
+
+ t4_intr_disable(adapter);
+ t4_write_reg(adapter, A_DBG_GPIO_EN, 0);
+ for_each_port(adapter, port) {
+ u32 a_port_cfg = PORT_REG(port,
+ is_t4(adapter)
+ ? A_XGMAC_PORT_CFG
+ : A_MAC_PORT_CFG);
+
+ t4_write_reg(adapter, a_port_cfg,
+ t4_read_reg(adapter, a_port_cfg)
+ & ~V_SIGNAL_DET(1));
+ }
+ t4_set_reg_field(adapter, A_SGE_CONTROL, F_GLOBALENABLE, 0);
+
+ return 0;
+}
+
+/**
+ * t4_init_devlog_params - initialize adapter->params.devlog
* @adap: the adapter
+ * @fw_attach: whether we can talk to the firmware
+ *
+ * Initialize various fields of the adapter's Firmware Device Log
+ * Parameters structure.
+ */
+int t4_init_devlog_params(struct adapter *adap, int fw_attach)
+{
+ struct devlog_params *dparams = &adap->params.devlog;
+ u32 pf_dparams;
+ unsigned int devlog_meminfo;
+ struct fw_devlog_cmd devlog_cmd;
+ int ret;
+
+ /* If we're dealing with newer firmware, the Device Log Paramerters
+ * are stored in a designated register which allows us to access the
+ * Device Log even if we can't talk to the firmware.
+ */
+ pf_dparams =
+ t4_read_reg(adap, PCIE_FW_REG(A_PCIE_FW_PF, PCIE_FW_PF_DEVLOG));
+ if (pf_dparams) {
+ unsigned int nentries, nentries128;
+
+ dparams->memtype = G_PCIE_FW_PF_DEVLOG_MEMTYPE(pf_dparams);
+ dparams->start = G_PCIE_FW_PF_DEVLOG_ADDR16(pf_dparams) << 4;
+
+ nentries128 = G_PCIE_FW_PF_DEVLOG_NENTRIES128(pf_dparams);
+ nentries = (nentries128 + 1) * 128;
+ dparams->size = nentries * sizeof(struct fw_devlog_e);
+
+ return 0;
+ }
+
+ /*
+ * For any failing returns ...
+ */
+ memset(dparams, 0, sizeof *dparams);
+
+ /*
+ * If we can't talk to the firmware, there's really nothing we can do
+ * at this point.
+ */
+ if (!fw_attach)
+ return -ENXIO;
+
+ /* Otherwise, ask the firmware for it's Device Log Parameters.
+ */
+ memset(&devlog_cmd, 0, sizeof devlog_cmd);
+ devlog_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_DEVLOG_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_READ);
+ devlog_cmd.retval_len16 = cpu_to_be32(FW_LEN16(devlog_cmd));
+ ret = t4_wr_mbox(adap, adap->mbox, &devlog_cmd, sizeof(devlog_cmd),
+ &devlog_cmd);
+ if (ret)
+ return ret;
+
+ devlog_meminfo =
+ be32_to_cpu(devlog_cmd.memtype_devlog_memaddr16_devlog);
+ dparams->memtype = G_FW_DEVLOG_CMD_MEMTYPE_DEVLOG(devlog_meminfo);
+ dparams->start = G_FW_DEVLOG_CMD_MEMADDR16_DEVLOG(devlog_meminfo) << 4;
+ dparams->size = be32_to_cpu(devlog_cmd.memsize_devlog);
+
+ return 0;
+}
+
+/**
+ * t4_init_sge_params - initialize adap->params.sge
+ * @adapter: the adapter
*
- * Initialize various fields of the adapter's TP Parameters structure.
+ * Initialize various fields of the adapter's SGE Parameters structure.
*/
-int __devinit t4_init_tp_params(struct adapter *adap)
+int t4_init_sge_params(struct adapter *adapter)
+{
+ u32 r;
+ struct sge_params *sp = &adapter->params.sge;
+
+ r = t4_read_reg(adapter, A_SGE_INGRESS_RX_THRESHOLD);
+ sp->counter_val[0] = G_THRESHOLD_0(r);
+ sp->counter_val[1] = G_THRESHOLD_1(r);
+ sp->counter_val[2] = G_THRESHOLD_2(r);
+ sp->counter_val[3] = G_THRESHOLD_3(r);
+
+ r = t4_read_reg(adapter, A_SGE_TIMER_VALUE_0_AND_1);
+ sp->timer_val[0] = core_ticks_to_us(adapter, G_TIMERVALUE0(r));
+ sp->timer_val[1] = core_ticks_to_us(adapter, G_TIMERVALUE1(r));
+ r = t4_read_reg(adapter, A_SGE_TIMER_VALUE_2_AND_3);
+ sp->timer_val[2] = core_ticks_to_us(adapter, G_TIMERVALUE2(r));
+ sp->timer_val[3] = core_ticks_to_us(adapter, G_TIMERVALUE3(r));
+ r = t4_read_reg(adapter, A_SGE_TIMER_VALUE_4_AND_5);
+ sp->timer_val[4] = core_ticks_to_us(adapter, G_TIMERVALUE4(r));
+ sp->timer_val[5] = core_ticks_to_us(adapter, G_TIMERVALUE5(r));
+
+ r = t4_read_reg(adapter, A_SGE_CONM_CTRL);
+ sp->fl_starve_threshold = G_EGRTHRESHOLD(r) * 2 + 1;
+ if (is_t4(adapter))
+ sp->fl_starve_threshold2 = sp->fl_starve_threshold;
+ else
+ sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(r) * 2 + 1;
+
+ /* egress queues: log2 of # of doorbells per BAR2 page */
+ r = t4_read_reg(adapter, A_SGE_EGRESS_QUEUES_PER_PAGE_PF);
+ r >>= S_QUEUESPERPAGEPF0 +
+ (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * adapter->pf;
+ sp->eq_s_qpp = r & M_QUEUESPERPAGEPF0;
+
+ /* ingress queues: log2 of # of doorbells per BAR2 page */
+ r = t4_read_reg(adapter, A_SGE_INGRESS_QUEUES_PER_PAGE_PF);
+ r >>= S_QUEUESPERPAGEPF0 +
+ (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * adapter->pf;
+ sp->iq_s_qpp = r & M_QUEUESPERPAGEPF0;
+
+ r = t4_read_reg(adapter, A_SGE_HOST_PAGE_SIZE);
+ r >>= S_HOSTPAGESIZEPF0 +
+ (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * adapter->pf;
+ sp->page_shift = (r & M_HOSTPAGESIZEPF0) + 10;
+
+ r = t4_read_reg(adapter, A_SGE_CONTROL);
+ sp->spg_len = r & F_EGRSTATUSPAGESIZE ? 128 : 64;
+ sp->fl_pktshift = G_PKTSHIFT(r);
+ sp->pad_boundary = 1 << (G_INGPADBOUNDARY(r) + 5);
+ if (is_t4(adapter))
+ sp->pack_boundary = sp->pad_boundary;
+ else {
+ r = t4_read_reg(adapter, A_SGE_CONTROL2);
+ if (G_INGPACKBOUNDARY(r) == 0)
+ sp->pack_boundary = 16;
+ else
+ sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(r) + 5);
+ }
+
+ return 0;
+}
+
+/*
+ * Read and cache the adapter's compressed filter mode and ingress config.
+ */
+static void read_filter_mode_and_ingress_config(struct adapter *adap)
+{
+ struct tp_params *tpp = &adap->params.tp;
+
+ if (t4_use_ldst(adap)) {
+ t4_fw_tp_pio_rw(adap, &tpp->vlan_pri_map, 1,
+ A_TP_VLAN_PRI_MAP, 1);
+ t4_fw_tp_pio_rw(adap, &tpp->ingress_config, 1,
+ A_TP_INGRESS_CONFIG, 1);
+ } else {
+ t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &tpp->vlan_pri_map, 1, A_TP_VLAN_PRI_MAP);
+ t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
+ &tpp->ingress_config, 1, A_TP_INGRESS_CONFIG);
+ }
+
+ /*
+ * Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
+ * shift positions of several elements of the Compressed Filter Tuple
+ * for this adapter which we need frequently ...
+ */
+ tpp->fcoe_shift = t4_filter_field_shift(adap, F_FCOE);
+ tpp->port_shift = t4_filter_field_shift(adap, F_PORT);
+ tpp->vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
+ tpp->vlan_shift = t4_filter_field_shift(adap, F_VLAN);
+ tpp->tos_shift = t4_filter_field_shift(adap, F_TOS);
+ tpp->protocol_shift = t4_filter_field_shift(adap, F_PROTOCOL);
+ tpp->ethertype_shift = t4_filter_field_shift(adap, F_ETHERTYPE);
+ tpp->macmatch_shift = t4_filter_field_shift(adap, F_MACMATCH);
+ tpp->matchtype_shift = t4_filter_field_shift(adap, F_MPSHITTYPE);
+ tpp->frag_shift = t4_filter_field_shift(adap, F_FRAGMENTATION);
+
+ /*
+ * If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
+ * represents the presense of an Outer VLAN instead of a VNIC ID.
+ */
+ if ((tpp->ingress_config & F_VNIC) == 0)
+ tpp->vnic_shift = -1;
+}
+
+/**
+ * t4_init_tp_params - initialize adap->params.tp
+ * @adap: the adapter
+ *
+ * Initialize various fields of the adapter's TP Parameters structure.
+ */
+int t4_init_tp_params(struct adapter *adap)
{
int chan;
u32 v;
+ struct tp_params *tpp = &adap->params.tp;
v = t4_read_reg(adap, A_TP_TIMER_RESOLUTION);
- adap->params.tp.tre = G_TIMERRESOLUTION(v);
- adap->params.tp.dack_re = G_DELAYEDACKRESOLUTION(v);
+ tpp->tre = G_TIMERRESOLUTION(v);
+ tpp->dack_re = G_DELAYEDACKRESOLUTION(v);
/* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
- for (chan = 0; chan < NCHAN; chan++)
- adap->params.tp.tx_modq[chan] = chan;
+ for (chan = 0; chan < MAX_NCHAN; chan++)
+ tpp->tx_modq[chan] = chan;
- t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA,
- &adap->params.tp.ingress_config, 1,
- A_TP_INGRESS_CONFIG);
- refresh_vlan_pri_map(adap);
+ read_filter_mode_and_ingress_config(adap);
+
+ /*
+ * For T6, cache the adapter's compressed error vector
+ * and passing outer header info for encapsulated packets.
+ */
+ if (chip_id(adap) > CHELSIO_T5) {
+ v = t4_read_reg(adap, A_TP_OUT_CONFIG);
+ tpp->rx_pkt_encap = (v & F_CRXPKTENC) ? 1 : 0;
+ }
return 0;
}
/**
- * t4_filter_field_shift - calculate filter field shift
- * @adap: the adapter
- * @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
+ * t4_filter_field_shift - calculate filter field shift
+ * @adap: the adapter
+ * @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
*
- * Return the shift position of a filter field within the Compressed
- * Filter Tuple. The filter field is specified via its selection bit
- * within TP_VLAN_PRI_MAL (filter mode). E.g. F_VLAN.
+ * Return the shift position of a filter field within the Compressed
+ * Filter Tuple. The filter field is specified via its selection bit
+ * within TP_VLAN_PRI_MAL (filter mode). E.g. F_VLAN.
*/
int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
{
@@ -5673,29 +7780,49 @@ int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
return -1;
for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
- switch (filter_mode & sel) {
- case F_FCOE: field_shift += W_FT_FCOE; break;
- case F_PORT: field_shift += W_FT_PORT; break;
- case F_VNIC_ID: field_shift += W_FT_VNIC_ID; break;
- case F_VLAN: field_shift += W_FT_VLAN; break;
- case F_TOS: field_shift += W_FT_TOS; break;
- case F_PROTOCOL: field_shift += W_FT_PROTOCOL; break;
- case F_ETHERTYPE: field_shift += W_FT_ETHERTYPE; break;
- case F_MACMATCH: field_shift += W_FT_MACMATCH; break;
- case F_MPSHITTYPE: field_shift += W_FT_MPSHITTYPE; break;
- case F_FRAGMENTATION: field_shift += W_FT_FRAGMENTATION; break;
- }
+ switch (filter_mode & sel) {
+ case F_FCOE:
+ field_shift += W_FT_FCOE;
+ break;
+ case F_PORT:
+ field_shift += W_FT_PORT;
+ break;
+ case F_VNIC_ID:
+ field_shift += W_FT_VNIC_ID;
+ break;
+ case F_VLAN:
+ field_shift += W_FT_VLAN;
+ break;
+ case F_TOS:
+ field_shift += W_FT_TOS;
+ break;
+ case F_PROTOCOL:
+ field_shift += W_FT_PROTOCOL;
+ break;
+ case F_ETHERTYPE:
+ field_shift += W_FT_ETHERTYPE;
+ break;
+ case F_MACMATCH:
+ field_shift += W_FT_MACMATCH;
+ break;
+ case F_MPSHITTYPE:
+ field_shift += W_FT_MPSHITTYPE;
+ break;
+ case F_FRAGMENTATION:
+ field_shift += W_FT_FRAGMENTATION;
+ break;
+ }
}
return field_shift;
}
-int __devinit t4_port_init(struct port_info *p, int mbox, int pf, int vf)
+int t4_port_init(struct adapter *adap, int mbox, int pf, int vf, int port_id)
{
u8 addr[6];
int ret, i, j;
struct fw_port_cmd c;
u16 rss_size;
- adapter_t *adap = p->adapter;
+ struct port_info *p = adap2pinfo(adap, port_id);
u32 param, val;
memset(&c, 0, sizeof(c));
@@ -5722,18 +7849,18 @@ int __devinit t4_port_init(struct port_info *p, int mbox, int pf, int vf)
p->vi[0].viid = ret;
p->tx_chan = j;
- p->rx_chan_map = get_mps_bg_map(adap, j);
+ p->rx_chan_map = t4_get_mps_bg_map(adap, j);
p->lport = j;
p->vi[0].rss_size = rss_size;
t4_os_set_hw_addr(adap, p->port_id, addr);
- ret = ntohl(c.u.info.lstatus_to_modtype);
+ 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, ntohs(c.u.info.pcap));
+ 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) |
@@ -5749,6 +7876,1161 @@ int __devinit t4_port_init(struct port_info *p, int mbox, int pf, int vf)
return 0;
}
+/**
+ * t4_read_cimq_cfg - read CIM queue configuration
+ * @adap: the adapter
+ * @base: holds the queue base addresses in bytes
+ * @size: holds the queue sizes in bytes
+ * @thres: holds the queue full thresholds in bytes
+ *
+ * Returns the current configuration of the CIM queues, starting with
+ * the IBQs, then the OBQs.
+ */
+void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres)
+{
+ unsigned int i, v;
+ int cim_num_obq = adap->chip_params->cim_num_obq;
+
+ for (i = 0; i < CIM_NUM_IBQ; i++) {
+ t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_IBQSELECT |
+ V_QUENUMSELECT(i));
+ v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
+ /* value is in 256-byte units */
+ *base++ = G_CIMQBASE(v) * 256;
+ *size++ = G_CIMQSIZE(v) * 256;
+ *thres++ = G_QUEFULLTHRSH(v) * 8; /* 8-byte unit */
+ }
+ for (i = 0; i < cim_num_obq; i++) {
+ t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
+ V_QUENUMSELECT(i));
+ v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
+ /* value is in 256-byte units */
+ *base++ = G_CIMQBASE(v) * 256;
+ *size++ = G_CIMQSIZE(v) * 256;
+ }
+}
+
+/**
+ * t4_read_cim_ibq - read the contents of a CIM inbound queue
+ * @adap: the adapter
+ * @qid: the queue index
+ * @data: where to store the queue contents
+ * @n: capacity of @data in 32-bit words
+ *
+ * Reads the contents of the selected CIM queue starting at address 0 up
+ * to the capacity of @data. @n must be a multiple of 4. Returns < 0 on
+ * error and the number of 32-bit words actually read on success.
+ */
+int t4_read_cim_ibq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
+{
+ int i, err, attempts;
+ unsigned int addr;
+ const unsigned int nwords = CIM_IBQ_SIZE * 4;
+
+ if (qid > 5 || (n & 3))
+ return -EINVAL;
+
+ addr = qid * nwords;
+ if (n > nwords)
+ n = nwords;
+
+ /* It might take 3-10ms before the IBQ debug read access is allowed.
+ * Wait for 1 Sec with a delay of 1 usec.
+ */
+ attempts = 1000000;
+
+ for (i = 0; i < n; i++, addr++) {
+ t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, V_IBQDBGADDR(addr) |
+ F_IBQDBGEN);
+ err = t4_wait_op_done(adap, A_CIM_IBQ_DBG_CFG, F_IBQDBGBUSY, 0,
+ attempts, 1);
+ if (err)
+ return err;
+ *data++ = t4_read_reg(adap, A_CIM_IBQ_DBG_DATA);
+ }
+ t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, 0);
+ return i;
+}
+
+/**
+ * t4_read_cim_obq - read the contents of a CIM outbound queue
+ * @adap: the adapter
+ * @qid: the queue index
+ * @data: where to store the queue contents
+ * @n: capacity of @data in 32-bit words
+ *
+ * Reads the contents of the selected CIM queue starting at address 0 up
+ * to the capacity of @data. @n must be a multiple of 4. Returns < 0 on
+ * error and the number of 32-bit words actually read on success.
+ */
+int t4_read_cim_obq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
+{
+ int i, err;
+ unsigned int addr, v, nwords;
+ int cim_num_obq = adap->chip_params->cim_num_obq;
+
+ if ((qid > (cim_num_obq - 1)) || (n & 3))
+ return -EINVAL;
+
+ t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
+ V_QUENUMSELECT(qid));
+ v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
+
+ addr = G_CIMQBASE(v) * 64; /* muliple of 256 -> muliple of 4 */
+ nwords = G_CIMQSIZE(v) * 64; /* same */
+ if (n > nwords)
+ n = nwords;
+
+ for (i = 0; i < n; i++, addr++) {
+ t4_write_reg(adap, A_CIM_OBQ_DBG_CFG, V_OBQDBGADDR(addr) |
+ F_OBQDBGEN);
+ err = t4_wait_op_done(adap, A_CIM_OBQ_DBG_CFG, F_OBQDBGBUSY, 0,
+ 2, 1);
+ if (err)
+ return err;
+ *data++ = t4_read_reg(adap, A_CIM_OBQ_DBG_DATA);
+ }
+ t4_write_reg(adap, A_CIM_OBQ_DBG_CFG, 0);
+ return i;
+}
+
+enum {
+ CIM_QCTL_BASE = 0,
+ CIM_CTL_BASE = 0x2000,
+ CIM_PBT_ADDR_BASE = 0x2800,
+ CIM_PBT_LRF_BASE = 0x3000,
+ CIM_PBT_DATA_BASE = 0x3800
+};
+
+/**
+ * t4_cim_read - read a block from CIM internal address space
+ * @adap: the adapter
+ * @addr: the start address within the CIM address space
+ * @n: number of words to read
+ * @valp: where to store the result
+ *
+ * Reads a block of 4-byte words from the CIM intenal address space.
+ */
+int t4_cim_read(struct adapter *adap, unsigned int addr, unsigned int n,
+ unsigned int *valp)
+{
+ int ret = 0;
+
+ if (t4_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY)
+ return -EBUSY;
+
+ for ( ; !ret && n--; addr += 4) {
+ t4_write_reg(adap, A_CIM_HOST_ACC_CTRL, addr);
+ ret = t4_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY,
+ 0, 5, 2);
+ if (!ret)
+ *valp++ = t4_read_reg(adap, A_CIM_HOST_ACC_DATA);
+ }
+ return ret;
+}
+
+/**
+ * t4_cim_write - write a block into CIM internal address space
+ * @adap: the adapter
+ * @addr: the start address within the CIM address space
+ * @n: number of words to write
+ * @valp: set of values to write
+ *
+ * Writes a block of 4-byte words into the CIM intenal address space.
+ */
+int t4_cim_write(struct adapter *adap, unsigned int addr, unsigned int n,
+ const unsigned int *valp)
+{
+ int ret = 0;
+
+ if (t4_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY)
+ return -EBUSY;
+
+ for ( ; !ret && n--; addr += 4) {
+ t4_write_reg(adap, A_CIM_HOST_ACC_DATA, *valp++);
+ t4_write_reg(adap, A_CIM_HOST_ACC_CTRL, addr | F_HOSTWRITE);
+ ret = t4_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY,
+ 0, 5, 2);
+ }
+ return ret;
+}
+
+static int t4_cim_write1(struct adapter *adap, unsigned int addr,
+ unsigned int val)
+{
+ return t4_cim_write(adap, addr, 1, &val);
+}
+
+/**
+ * t4_cim_ctl_read - read a block from CIM control region
+ * @adap: the adapter
+ * @addr: the start address within the CIM control region
+ * @n: number of words to read
+ * @valp: where to store the result
+ *
+ * Reads a block of 4-byte words from the CIM control region.
+ */
+int t4_cim_ctl_read(struct adapter *adap, unsigned int addr, unsigned int n,
+ unsigned int *valp)
+{
+ return t4_cim_read(adap, addr + CIM_CTL_BASE, n, valp);
+}
+
+/**
+ * t4_cim_read_la - read CIM LA capture buffer
+ * @adap: the adapter
+ * @la_buf: where to store the LA data
+ * @wrptr: the HW write pointer within the capture buffer
+ *
+ * Reads the contents of the CIM LA buffer with the most recent entry at
+ * the end of the returned data and with the entry at @wrptr first.
+ * We try to leave the LA in the running state we find it in.
+ */
+int t4_cim_read_la(struct adapter *adap, u32 *la_buf, unsigned int *wrptr)
+{
+ int i, ret;
+ unsigned int cfg, val, idx;
+
+ ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &cfg);
+ if (ret)
+ return ret;
+
+ if (cfg & F_UPDBGLAEN) { /* LA is running, freeze it */
+ ret = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG, 0);
+ if (ret)
+ return ret;
+ }
+
+ ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &val);
+ if (ret)
+ goto restart;
+
+ idx = G_UPDBGLAWRPTR(val);
+ if (wrptr)
+ *wrptr = idx;
+
+ for (i = 0; i < adap->params.cim_la_size; i++) {
+ ret = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG,
+ V_UPDBGLARDPTR(idx) | F_UPDBGLARDEN);
+ if (ret)
+ break;
+ ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &val);
+ if (ret)
+ break;
+ if (val & F_UPDBGLARDEN) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ ret = t4_cim_read(adap, A_UP_UP_DBG_LA_DATA, 1, &la_buf[i]);
+ if (ret)
+ break;
+
+ /* address can't exceed 0xfff (UpDbgLaRdPtr is of 12-bits) */
+ idx = (idx + 1) & M_UPDBGLARDPTR;
+ /*
+ * Bits 0-3 of UpDbgLaRdPtr can be between 0000 to 1001 to
+ * identify the 32-bit portion of the full 312-bit data
+ */
+ if (is_t6(adap))
+ while ((idx & 0xf) > 9)
+ idx = (idx + 1) % M_UPDBGLARDPTR;
+ }
+restart:
+ if (cfg & F_UPDBGLAEN) {
+ int r = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG,
+ cfg & ~F_UPDBGLARDEN);
+ if (!ret)
+ ret = r;
+ }
+ return ret;
+}
+
+/**
+ * t4_tp_read_la - read TP LA capture buffer
+ * @adap: the adapter
+ * @la_buf: where to store the LA data
+ * @wrptr: the HW write pointer within the capture buffer
+ *
+ * Reads the contents of the TP LA buffer with the most recent entry at
+ * the end of the returned data and with the entry at @wrptr first.
+ * We leave the LA in the running state we find it in.
+ */
+void t4_tp_read_la(struct adapter *adap, u64 *la_buf, unsigned int *wrptr)
+{
+ bool last_incomplete;
+ unsigned int i, cfg, val, idx;
+
+ cfg = t4_read_reg(adap, A_TP_DBG_LA_CONFIG) & 0xffff;
+ if (cfg & F_DBGLAENABLE) /* freeze LA */
+ t4_write_reg(adap, A_TP_DBG_LA_CONFIG,
+ adap->params.tp.la_mask | (cfg ^ F_DBGLAENABLE));
+
+ val = t4_read_reg(adap, A_TP_DBG_LA_CONFIG);
+ idx = G_DBGLAWPTR(val);
+ last_incomplete = G_DBGLAMODE(val) >= 2 && (val & F_DBGLAWHLF) == 0;
+ if (last_incomplete)
+ idx = (idx + 1) & M_DBGLARPTR;
+ if (wrptr)
+ *wrptr = idx;
+
+ val &= 0xffff;
+ val &= ~V_DBGLARPTR(M_DBGLARPTR);
+ val |= adap->params.tp.la_mask;
+
+ for (i = 0; i < TPLA_SIZE; i++) {
+ t4_write_reg(adap, A_TP_DBG_LA_CONFIG, V_DBGLARPTR(idx) | val);
+ la_buf[i] = t4_read_reg64(adap, A_TP_DBG_LA_DATAL);
+ idx = (idx + 1) & M_DBGLARPTR;
+ }
+
+ /* Wipe out last entry if it isn't valid */
+ if (last_incomplete)
+ la_buf[TPLA_SIZE - 1] = ~0ULL;
+
+ if (cfg & F_DBGLAENABLE) /* restore running state */
+ t4_write_reg(adap, A_TP_DBG_LA_CONFIG,
+ cfg | adap->params.tp.la_mask);
+}
+
+/*
+ * SGE Hung Ingress DMA Warning Threshold time and Warning Repeat Rate (in
+ * seconds). If we find one of the SGE Ingress DMA State Machines in the same
+ * state for more than the Warning Threshold then we'll issue a warning about
+ * a potential hang. We'll repeat the warning as the SGE Ingress DMA Channel
+ * appears to be hung every Warning Repeat second till the situation clears.
+ * If the situation clears, we'll note that as well.
+ */
+#define SGE_IDMA_WARN_THRESH 1
+#define SGE_IDMA_WARN_REPEAT 300
+
+/**
+ * t4_idma_monitor_init - initialize SGE Ingress DMA Monitor
+ * @adapter: the adapter
+ * @idma: the adapter IDMA Monitor state
+ *
+ * Initialize the state of an SGE Ingress DMA Monitor.
+ */
+void t4_idma_monitor_init(struct adapter *adapter,
+ struct sge_idma_monitor_state *idma)
+{
+ /* Initialize the state variables for detecting an SGE Ingress DMA
+ * hang. The SGE has internal counters which count up on each clock
+ * tick whenever the SGE finds its Ingress DMA State Engines in the
+ * same state they were on the previous clock tick. The clock used is
+ * the Core Clock so we have a limit on the maximum "time" they can
+ * record; typically a very small number of seconds. For instance,
+ * with a 600MHz Core Clock, we can only count up to a bit more than
+ * 7s. So we'll synthesize a larger counter in order to not run the
+ * risk of having the "timers" overflow and give us the flexibility to
+ * maintain a Hung SGE State Machine of our own which operates across
+ * a longer time frame.
+ */
+ idma->idma_1s_thresh = core_ticks_per_usec(adapter) * 1000000; /* 1s */
+ idma->idma_stalled[0] = idma->idma_stalled[1] = 0;
+}
+
+/**
+ * t4_idma_monitor - monitor SGE Ingress DMA state
+ * @adapter: the adapter
+ * @idma: the adapter IDMA Monitor state
+ * @hz: number of ticks/second
+ * @ticks: number of ticks since the last IDMA Monitor call
+ */
+void t4_idma_monitor(struct adapter *adapter,
+ struct sge_idma_monitor_state *idma,
+ int hz, int ticks)
+{
+ int i, idma_same_state_cnt[2];
+
+ /* Read the SGE Debug Ingress DMA Same State Count registers. These
+ * are counters inside the SGE which count up on each clock when the
+ * SGE finds its Ingress DMA State Engines in the same states they
+ * were in the previous clock. The counters will peg out at
+ * 0xffffffff without wrapping around so once they pass the 1s
+ * threshold they'll stay above that till the IDMA state changes.
+ */
+ t4_write_reg(adapter, A_SGE_DEBUG_INDEX, 13);
+ idma_same_state_cnt[0] = t4_read_reg(adapter, A_SGE_DEBUG_DATA_HIGH);
+ idma_same_state_cnt[1] = t4_read_reg(adapter, A_SGE_DEBUG_DATA_LOW);
+
+ for (i = 0; i < 2; i++) {
+ u32 debug0, debug11;
+
+ /* If the Ingress DMA Same State Counter ("timer") is less
+ * than 1s, then we can reset our synthesized Stall Timer and
+ * continue. If we have previously emitted warnings about a
+ * potential stalled Ingress Queue, issue a note indicating
+ * that the Ingress Queue has resumed forward progress.
+ */
+ if (idma_same_state_cnt[i] < idma->idma_1s_thresh) {
+ if (idma->idma_stalled[i] >= SGE_IDMA_WARN_THRESH*hz)
+ CH_WARN(adapter, "SGE idma%d, queue %u, "
+ "resumed after %d seconds\n",
+ i, idma->idma_qid[i],
+ idma->idma_stalled[i]/hz);
+ idma->idma_stalled[i] = 0;
+ continue;
+ }
+
+ /* Synthesize an SGE Ingress DMA Same State Timer in the Hz
+ * domain. The first time we get here it'll be because we
+ * passed the 1s Threshold; each additional time it'll be
+ * because the RX Timer Callback is being fired on its regular
+ * schedule.
+ *
+ * If the stall is below our Potential Hung Ingress Queue
+ * Warning Threshold, continue.
+ */
+ if (idma->idma_stalled[i] == 0) {
+ idma->idma_stalled[i] = hz;
+ idma->idma_warn[i] = 0;
+ } else {
+ idma->idma_stalled[i] += ticks;
+ idma->idma_warn[i] -= ticks;
+ }
+
+ if (idma->idma_stalled[i] < SGE_IDMA_WARN_THRESH*hz)
+ continue;
+
+ /* We'll issue a warning every SGE_IDMA_WARN_REPEAT seconds.
+ */
+ if (idma->idma_warn[i] > 0)
+ continue;
+ idma->idma_warn[i] = SGE_IDMA_WARN_REPEAT*hz;
+
+ /* Read and save the SGE IDMA State and Queue ID information.
+ * We do this every time in case it changes across time ...
+ * can't be too careful ...
+ */
+ t4_write_reg(adapter, A_SGE_DEBUG_INDEX, 0);
+ debug0 = t4_read_reg(adapter, A_SGE_DEBUG_DATA_LOW);
+ idma->idma_state[i] = (debug0 >> (i * 9)) & 0x3f;
+
+ t4_write_reg(adapter, A_SGE_DEBUG_INDEX, 11);
+ debug11 = t4_read_reg(adapter, A_SGE_DEBUG_DATA_LOW);
+ idma->idma_qid[i] = (debug11 >> (i * 16)) & 0xffff;
+
+ CH_WARN(adapter, "SGE idma%u, queue %u, potentially stuck in "
+ " state %u for %d seconds (debug0=%#x, debug11=%#x)\n",
+ i, idma->idma_qid[i], idma->idma_state[i],
+ idma->idma_stalled[i]/hz,
+ debug0, debug11);
+ t4_sge_decode_idma_state(adapter, idma->idma_state[i]);
+ }
+}
+
+/**
+ * t4_read_pace_tbl - read the pace table
+ * @adap: the adapter
+ * @pace_vals: holds the returned values
+ *
+ * Returns the values of TP's pace table in microseconds.
+ */
+void t4_read_pace_tbl(struct adapter *adap, unsigned int pace_vals[NTX_SCHED])
+{
+ unsigned int i, v;
+
+ for (i = 0; i < NTX_SCHED; i++) {
+ t4_write_reg(adap, A_TP_PACE_TABLE, 0xffff0000 + i);
+ v = t4_read_reg(adap, A_TP_PACE_TABLE);
+ pace_vals[i] = dack_ticks_to_usec(adap, v);
+ }
+}
+
+/**
+ * t4_get_tx_sched - get the configuration of a Tx HW traffic scheduler
+ * @adap: the adapter
+ * @sched: the scheduler index
+ * @kbps: the byte rate in Kbps
+ * @ipg: the interpacket delay in tenths of nanoseconds
+ *
+ * Return the current configuration of a HW Tx scheduler.
+ */
+void t4_get_tx_sched(struct adapter *adap, unsigned int sched, unsigned int *kbps,
+ unsigned int *ipg)
+{
+ unsigned int v, addr, bpt, cpt;
+
+ if (kbps) {
+ addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2;
+ t4_write_reg(adap, A_TP_TM_PIO_ADDR, addr);
+ v = t4_read_reg(adap, A_TP_TM_PIO_DATA);
+ if (sched & 1)
+ v >>= 16;
+ bpt = (v >> 8) & 0xff;
+ cpt = v & 0xff;
+ if (!cpt)
+ *kbps = 0; /* scheduler disabled */
+ else {
+ v = (adap->params.vpd.cclk * 1000) / cpt; /* ticks/s */
+ *kbps = (v * bpt) / 125;
+ }
+ }
+ if (ipg) {
+ addr = A_TP_TX_MOD_Q1_Q0_TIMER_SEPARATOR - sched / 2;
+ t4_write_reg(adap, A_TP_TM_PIO_ADDR, addr);
+ v = t4_read_reg(adap, A_TP_TM_PIO_DATA);
+ if (sched & 1)
+ v >>= 16;
+ v &= 0xffff;
+ *ipg = (10000 * v) / core_ticks_per_usec(adap);
+ }
+}
+
+/**
+ * t4_load_cfg - download config file
+ * @adap: the adapter
+ * @cfg_data: the cfg text file to write
+ * @size: text file size
+ *
+ * Write the supplied config text file to the card's serial flash.
+ */
+int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
+{
+ int ret, i, n, cfg_addr;
+ unsigned int addr;
+ unsigned int flash_cfg_start_sec;
+ unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
+
+ cfg_addr = t4_flash_cfg_addr(adap);
+ if (cfg_addr < 0)
+ return cfg_addr;
+
+ addr = cfg_addr;
+ flash_cfg_start_sec = addr / SF_SEC_SIZE;
+
+ if (size > FLASH_CFG_MAX_SIZE) {
+ CH_ERR(adap, "cfg file too large, max is %u bytes\n",
+ FLASH_CFG_MAX_SIZE);
+ return -EFBIG;
+ }
+
+ i = DIV_ROUND_UP(FLASH_CFG_MAX_SIZE, /* # of sectors spanned */
+ sf_sec_size);
+ ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec,
+ flash_cfg_start_sec + i - 1);
+ /*
+ * If size == 0 then we're simply erasing the FLASH sectors associated
+ * with the on-adapter Firmware Configuration File.
+ */
+ if (ret || size == 0)
+ goto out;
+
+ /* this will write to the flash up to SF_PAGE_SIZE at a time */
+ for (i = 0; i< size; i+= SF_PAGE_SIZE) {
+ if ( (size - i) < SF_PAGE_SIZE)
+ n = size - i;
+ else
+ n = SF_PAGE_SIZE;
+ ret = t4_write_flash(adap, addr, n, cfg_data, 1);
+ if (ret)
+ goto out;
+
+ addr += SF_PAGE_SIZE;
+ cfg_data += SF_PAGE_SIZE;
+ }
+
+out:
+ if (ret)
+ CH_ERR(adap, "config file %s failed %d\n",
+ (size == 0 ? "clear" : "download"), ret);
+ return ret;
+}
+
+/**
+ * t5_fw_init_extern_mem - initialize the external memory
+ * @adap: the adapter
+ *
+ * Initializes the external memory on T5.
+ */
+int t5_fw_init_extern_mem(struct adapter *adap)
+{
+ u32 params[1], val[1];
+ int ret;
+
+ if (!is_t5(adap))
+ return 0;
+
+ val[0] = 0xff; /* Initialize all MCs */
+ params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
+ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_MCINIT));
+ ret = t4_set_params_timeout(adap, adap->mbox, adap->pf, 0, 1, params, val,
+ FW_CMD_MAX_TIMEOUT);
+
+ return ret;
+}
+
+/* BIOS boot headers */
+typedef struct pci_expansion_rom_header {
+ u8 signature[2]; /* ROM Signature. Should be 0xaa55 */
+ u8 reserved[22]; /* Reserved per processor Architecture data */
+ u8 pcir_offset[2]; /* Offset to PCI Data Structure */
+} pci_exp_rom_header_t; /* PCI_EXPANSION_ROM_HEADER */
+
+/* Legacy PCI Expansion ROM Header */
+typedef struct legacy_pci_expansion_rom_header {
+ u8 signature[2]; /* ROM Signature. Should be 0xaa55 */
+ u8 size512; /* Current Image Size in units of 512 bytes */
+ u8 initentry_point[4];
+ u8 cksum; /* Checksum computed on the entire Image */
+ u8 reserved[16]; /* Reserved */
+ u8 pcir_offset[2]; /* Offset to PCI Data Struture */
+} legacy_pci_exp_rom_header_t; /* LEGACY_PCI_EXPANSION_ROM_HEADER */
+
+/* EFI PCI Expansion ROM Header */
+typedef struct efi_pci_expansion_rom_header {
+ u8 signature[2]; // ROM signature. The value 0xaa55
+ u8 initialization_size[2]; /* Units 512. Includes this header */
+ u8 efi_signature[4]; /* Signature from EFI image header. 0x0EF1 */
+ u8 efi_subsystem[2]; /* Subsystem value for EFI image header */
+ u8 efi_machine_type[2]; /* Machine type from EFI image header */
+ u8 compression_type[2]; /* Compression type. */
+ /*
+ * Compression type definition
+ * 0x0: uncompressed
+ * 0x1: Compressed
+ * 0x2-0xFFFF: Reserved
+ */
+ u8 reserved[8]; /* Reserved */
+ u8 efi_image_header_offset[2]; /* Offset to EFI Image */
+ u8 pcir_offset[2]; /* Offset to PCI Data Structure */
+} efi_pci_exp_rom_header_t; /* EFI PCI Expansion ROM Header */
+
+/* PCI Data Structure Format */
+typedef struct pcir_data_structure { /* PCI Data Structure */
+ u8 signature[4]; /* Signature. The string "PCIR" */
+ u8 vendor_id[2]; /* Vendor Identification */
+ u8 device_id[2]; /* Device Identification */
+ u8 vital_product[2]; /* Pointer to Vital Product Data */
+ u8 length[2]; /* PCIR Data Structure Length */
+ u8 revision; /* PCIR Data Structure Revision */
+ u8 class_code[3]; /* Class Code */
+ u8 image_length[2]; /* Image Length. Multiple of 512B */
+ u8 code_revision[2]; /* Revision Level of Code/Data */
+ u8 code_type; /* Code Type. */
+ /*
+ * PCI Expansion ROM Code Types
+ * 0x00: Intel IA-32, PC-AT compatible. Legacy
+ * 0x01: Open Firmware standard for PCI. FCODE
+ * 0x02: Hewlett-Packard PA RISC. HP reserved
+ * 0x03: EFI Image. EFI
+ * 0x04-0xFF: Reserved.
+ */
+ u8 indicator; /* Indicator. Identifies the last image in the ROM */
+ u8 reserved[2]; /* Reserved */
+} pcir_data_t; /* PCI__DATA_STRUCTURE */
+
+/* BOOT constants */
+enum {
+ BOOT_FLASH_BOOT_ADDR = 0x0,/* start address of boot image in flash */
+ BOOT_SIGNATURE = 0xaa55, /* signature of BIOS boot ROM */
+ BOOT_SIZE_INC = 512, /* image size measured in 512B chunks */
+ BOOT_MIN_SIZE = sizeof(pci_exp_rom_header_t), /* basic header */
+ BOOT_MAX_SIZE = 1024*BOOT_SIZE_INC, /* 1 byte * length increment */
+ VENDOR_ID = 0x1425, /* Vendor ID */
+ PCIR_SIGNATURE = 0x52494350 /* PCIR signature */
+};
+
+/*
+ * modify_device_id - Modifies the device ID of the Boot BIOS image
+ * @adatper: the device ID to write.
+ * @boot_data: the boot image to modify.
+ *
+ * Write the supplied device ID to the boot BIOS image.
+ */
+static void modify_device_id(int device_id, u8 *boot_data)
+{
+ legacy_pci_exp_rom_header_t *header;
+ pcir_data_t *pcir_header;
+ u32 cur_header = 0;
+
+ /*
+ * Loop through all chained images and change the device ID's
+ */
+ while (1) {
+ header = (legacy_pci_exp_rom_header_t *) &boot_data[cur_header];
+ pcir_header = (pcir_data_t *) &boot_data[cur_header +
+ le16_to_cpu(*(u16*)header->pcir_offset)];
+
+ /*
+ * Only modify the Device ID if code type is Legacy or HP.
+ * 0x00: Okay to modify
+ * 0x01: FCODE. Do not be modify
+ * 0x03: Okay to modify
+ * 0x04-0xFF: Do not modify
+ */
+ if (pcir_header->code_type == 0x00) {
+ u8 csum = 0;
+ int i;
+
+ /*
+ * Modify Device ID to match current adatper
+ */
+ *(u16*) pcir_header->device_id = device_id;
+
+ /*
+ * Set checksum temporarily to 0.
+ * We will recalculate it later.
+ */
+ header->cksum = 0x0;
+
+ /*
+ * Calculate and update checksum
+ */
+ for (i = 0; i < (header->size512 * 512); i++)
+ csum += (u8)boot_data[cur_header + i];
+
+ /*
+ * Invert summed value to create the checksum
+ * Writing new checksum value directly to the boot data
+ */
+ boot_data[cur_header + 7] = -csum;
+
+ } else if (pcir_header->code_type == 0x03) {
+
+ /*
+ * Modify Device ID to match current adatper
+ */
+ *(u16*) pcir_header->device_id = device_id;
+
+ }
+
+
+ /*
+ * Check indicator element to identify if this is the last
+ * image in the ROM.
+ */
+ if (pcir_header->indicator & 0x80)
+ break;
+
+ /*
+ * Move header pointer up to the next image in the ROM.
+ */
+ cur_header += header->size512 * 512;
+ }
+}
+
+/*
+ * t4_load_boot - download boot flash
+ * @adapter: the adapter
+ * @boot_data: the boot image to write
+ * @boot_addr: offset in flash to write boot_data
+ * @size: image size
+ *
+ * Write the supplied boot image to the card's serial flash.
+ * The boot image has the following sections: a 28-byte header and the
+ * boot image.
+ */
+int t4_load_boot(struct adapter *adap, u8 *boot_data,
+ unsigned int boot_addr, unsigned int size)
+{
+ pci_exp_rom_header_t *header;
+ int pcir_offset ;
+ pcir_data_t *pcir_header;
+ int ret, addr;
+ uint16_t device_id;
+ unsigned int i;
+ unsigned int boot_sector = (boot_addr * 1024 );
+ unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
+
+ /*
+ * Make sure the boot image does not encroach on the firmware region
+ */
+ if ((boot_sector + size) >> 16 > FLASH_FW_START_SEC) {
+ CH_ERR(adap, "boot image encroaching on firmware region\n");
+ return -EFBIG;
+ }
+
+ /*
+ * The boot sector is comprised of the Expansion-ROM boot, iSCSI boot,
+ * and Boot configuration data sections. These 3 boot sections span
+ * sectors 0 to 7 in flash and live right before the FW image location.
+ */
+ i = DIV_ROUND_UP(size ? size : FLASH_FW_START,
+ sf_sec_size);
+ ret = t4_flash_erase_sectors(adap, boot_sector >> 16,
+ (boot_sector >> 16) + i - 1);
+
+ /*
+ * If size == 0 then we're simply erasing the FLASH sectors associated
+ * with the on-adapter option ROM file
+ */
+ if (ret || (size == 0))
+ goto out;
+
+ /* Get boot header */
+ header = (pci_exp_rom_header_t *)boot_data;
+ pcir_offset = le16_to_cpu(*(u16 *)header->pcir_offset);
+ /* PCIR Data Structure */
+ pcir_header = (pcir_data_t *) &boot_data[pcir_offset];
+
+ /*
+ * Perform some primitive sanity testing to avoid accidentally
+ * writing garbage over the boot sectors. We ought to check for
+ * more but it's not worth it for now ...
+ */
+ if (size < BOOT_MIN_SIZE || size > BOOT_MAX_SIZE) {
+ CH_ERR(adap, "boot image too small/large\n");
+ return -EFBIG;
+ }
+
+#ifndef CHELSIO_T4_DIAGS
+ /*
+ * Check BOOT ROM header signature
+ */
+ if (le16_to_cpu(*(u16*)header->signature) != BOOT_SIGNATURE ) {
+ CH_ERR(adap, "Boot image missing signature\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Check PCI header signature
+ */
+ if (le32_to_cpu(*(u32*)pcir_header->signature) != PCIR_SIGNATURE) {
+ CH_ERR(adap, "PCI header missing signature\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Check Vendor ID matches Chelsio ID
+ */
+ if (le16_to_cpu(*(u16*)pcir_header->vendor_id) != VENDOR_ID) {
+ CH_ERR(adap, "Vendor ID missing signature\n");
+ return -EINVAL;
+ }
+#endif
+
+ /*
+ * Retrieve adapter's device ID
+ */
+ t4_os_pci_read_cfg2(adap, PCI_DEVICE_ID, &device_id);
+ /* Want to deal with PF 0 so I strip off PF 4 indicator */
+ device_id = device_id & 0xf0ff;
+
+ /*
+ * Check PCIE Device ID
+ */
+ if (le16_to_cpu(*(u16*)pcir_header->device_id) != device_id) {
+ /*
+ * Change the device ID in the Boot BIOS image to match
+ * the Device ID of the current adapter.
+ */
+ modify_device_id(device_id, boot_data);
+ }
+
+ /*
+ * Skip over the first SF_PAGE_SIZE worth of data and write it after
+ * we finish copying the rest of the boot image. This will ensure
+ * that the BIOS boot header will only be written if the boot image
+ * was written in full.
+ */
+ addr = boot_sector;
+ for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
+ addr += SF_PAGE_SIZE;
+ boot_data += SF_PAGE_SIZE;
+ ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, boot_data, 0);
+ if (ret)
+ goto out;
+ }
+
+ ret = t4_write_flash(adap, boot_sector, SF_PAGE_SIZE,
+ (const u8 *)header, 0);
+
+out:
+ if (ret)
+ CH_ERR(adap, "boot image download failed, error %d\n", ret);
+ return ret;
+}
+
+/*
+ * t4_flash_bootcfg_addr - return the address of the flash optionrom configuration
+ * @adapter: the adapter
+ *
+ * Return the address within the flash where the OptionROM Configuration
+ * is stored, or an error if the device FLASH is too small to contain
+ * a OptionROM Configuration.
+ */
+static int t4_flash_bootcfg_addr(struct adapter *adapter)
+{
+ /*
+ * If the device FLASH isn't large enough to hold a Firmware
+ * Configuration File, return an error.
+ */
+ if (adapter->params.sf_size < FLASH_BOOTCFG_START + FLASH_BOOTCFG_MAX_SIZE)
+ return -ENOSPC;
+
+ return FLASH_BOOTCFG_START;
+}
+
+int t4_load_bootcfg(struct adapter *adap,const u8 *cfg_data, unsigned int size)
+{
+ int ret, i, n, cfg_addr;
+ unsigned int addr;
+ unsigned int flash_cfg_start_sec;
+ unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
+
+ cfg_addr = t4_flash_bootcfg_addr(adap);
+ if (cfg_addr < 0)
+ return cfg_addr;
+
+ addr = cfg_addr;
+ flash_cfg_start_sec = addr / SF_SEC_SIZE;
+
+ if (size > FLASH_BOOTCFG_MAX_SIZE) {
+ CH_ERR(adap, "bootcfg file too large, max is %u bytes\n",
+ FLASH_BOOTCFG_MAX_SIZE);
+ return -EFBIG;
+ }
+
+ i = DIV_ROUND_UP(FLASH_BOOTCFG_MAX_SIZE,/* # of sectors spanned */
+ sf_sec_size);
+ ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec,
+ flash_cfg_start_sec + i - 1);
+
+ /*
+ * If size == 0 then we're simply erasing the FLASH sectors associated
+ * with the on-adapter OptionROM Configuration File.
+ */
+ if (ret || size == 0)
+ goto out;
+
+ /* this will write to the flash up to SF_PAGE_SIZE at a time */
+ for (i = 0; i< size; i+= SF_PAGE_SIZE) {
+ if ( (size - i) < SF_PAGE_SIZE)
+ n = size - i;
+ else
+ n = SF_PAGE_SIZE;
+ ret = t4_write_flash(adap, addr, n, cfg_data, 0);
+ if (ret)
+ goto out;
+
+ addr += SF_PAGE_SIZE;
+ cfg_data += SF_PAGE_SIZE;
+ }
+
+out:
+ if (ret)
+ CH_ERR(adap, "boot config data %s failed %d\n",
+ (size == 0 ? "clear" : "download"), ret);
+ return ret;
+}
+
+/**
+ * t4_set_filter_mode - configure the optional components of filter tuples
+ * @adap: the adapter
+ * @mode_map: a bitmap selcting which optional filter components to enable
+ *
+ * Sets the filter mode by selecting the optional components to enable
+ * in filter tuples. Returns 0 on success and a negative error if the
+ * requested mode needs more bits than are available for optional
+ * components.
+ */
+int t4_set_filter_mode(struct adapter *adap, unsigned int mode_map)
+{
+ static u8 width[] = { 1, 3, 17, 17, 8, 8, 16, 9, 3, 1 };
+
+ int i, nbits = 0;
+
+ for (i = S_FCOE; i <= S_FRAGMENTATION; i++)
+ if (mode_map & (1 << i))
+ nbits += width[i];
+ if (nbits > FILTER_OPT_LEN)
+ return -EINVAL;
+ if (t4_use_ldst(adap))
+ t4_fw_tp_pio_rw(adap, &mode_map, 1, A_TP_VLAN_PRI_MAP, 0);
+ else
+ t4_write_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, &mode_map,
+ 1, A_TP_VLAN_PRI_MAP);
+ read_filter_mode_and_ingress_config(adap);
+
+ return 0;
+}
+
+/**
+ * t4_clr_port_stats - clear port statistics
+ * @adap: the adapter
+ * @idx: the port index
+ *
+ * Clear HW statistics for the given port.
+ */
+void t4_clr_port_stats(struct adapter *adap, int idx)
+{
+ unsigned int i;
+ u32 bgmap = t4_get_mps_bg_map(adap, idx);
+ u32 port_base_addr;
+
+ if (is_t4(adap))
+ port_base_addr = PORT_BASE(idx);
+ else
+ port_base_addr = T5_PORT_BASE(idx);
+
+ for (i = A_MPS_PORT_STAT_TX_PORT_BYTES_L;
+ i <= A_MPS_PORT_STAT_TX_PORT_PPP7_H; i += 8)
+ t4_write_reg(adap, port_base_addr + i, 0);
+ for (i = A_MPS_PORT_STAT_RX_PORT_BYTES_L;
+ i <= A_MPS_PORT_STAT_RX_PORT_LESS_64B_H; i += 8)
+ t4_write_reg(adap, port_base_addr + i, 0);
+ for (i = 0; i < 4; i++)
+ if (bgmap & (1 << i)) {
+ t4_write_reg(adap,
+ A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + i * 8, 0);
+ t4_write_reg(adap,
+ A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + i * 8, 0);
+ }
+}
+
+/**
+ * t4_i2c_rd - read I2C data from adapter
+ * @adap: the adapter
+ * @port: Port number if per-port device; <0 if not
+ * @devid: per-port device ID or absolute device ID
+ * @offset: byte offset into device I2C space
+ * @len: byte length of I2C space data
+ * @buf: buffer in which to return I2C data
+ *
+ * Reads the I2C data from the indicated device and location.
+ */
+int t4_i2c_rd(struct adapter *adap, unsigned int mbox,
+ int port, unsigned int devid,
+ unsigned int offset, unsigned int len,
+ u8 *buf)
+{
+ u32 ldst_addrspace;
+ struct fw_ldst_cmd ldst;
+ int ret;
+
+ if (port >= 4 ||
+ devid >= 256 ||
+ offset >= 256 ||
+ len > sizeof ldst.u.i2c.data)
+ return -EINVAL;
+
+ memset(&ldst, 0, sizeof ldst);
+ ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C);
+ ldst.op_to_addrspace =
+ cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_READ |
+ ldst_addrspace);
+ ldst.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst));
+ ldst.u.i2c.pid = (port < 0 ? 0xff : port);
+ ldst.u.i2c.did = devid;
+ ldst.u.i2c.boffset = offset;
+ ldst.u.i2c.blen = len;
+ ret = t4_wr_mbox(adap, mbox, &ldst, sizeof ldst, &ldst);
+ if (!ret)
+ memcpy(buf, ldst.u.i2c.data, len);
+ return ret;
+}
+
+/**
+ * t4_i2c_wr - write I2C data to adapter
+ * @adap: the adapter
+ * @port: Port number if per-port device; <0 if not
+ * @devid: per-port device ID or absolute device ID
+ * @offset: byte offset into device I2C space
+ * @len: byte length of I2C space data
+ * @buf: buffer containing new I2C data
+ *
+ * Write the I2C data to the indicated device and location.
+ */
+int t4_i2c_wr(struct adapter *adap, unsigned int mbox,
+ int port, unsigned int devid,
+ unsigned int offset, unsigned int len,
+ u8 *buf)
+{
+ u32 ldst_addrspace;
+ struct fw_ldst_cmd ldst;
+
+ if (port >= 4 ||
+ devid >= 256 ||
+ offset >= 256 ||
+ len > sizeof ldst.u.i2c.data)
+ return -EINVAL;
+
+ memset(&ldst, 0, sizeof ldst);
+ ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C);
+ ldst.op_to_addrspace =
+ cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE |
+ ldst_addrspace);
+ ldst.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst));
+ ldst.u.i2c.pid = (port < 0 ? 0xff : port);
+ ldst.u.i2c.did = devid;
+ ldst.u.i2c.boffset = offset;
+ ldst.u.i2c.blen = len;
+ memcpy(ldst.u.i2c.data, buf, len);
+ return t4_wr_mbox(adap, mbox, &ldst, sizeof ldst, &ldst);
+}
+
+/**
+ * t4_sge_ctxt_rd - read an SGE context through FW
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @cid: the context id
+ * @ctype: the context type
+ * @data: where to store the context data
+ *
+ * Issues a FW command through the given mailbox to read an SGE context.
+ */
+int t4_sge_ctxt_rd(struct adapter *adap, unsigned int mbox, unsigned int cid,
+ enum ctxt_type ctype, u32 *data)
+{
+ int ret;
+ struct fw_ldst_cmd c;
+
+ if (ctype == CTXT_EGRESS)
+ ret = FW_LDST_ADDRSPC_SGE_EGRC;
+ else if (ctype == CTXT_INGRESS)
+ ret = FW_LDST_ADDRSPC_SGE_INGC;
+ else if (ctype == CTXT_FLM)
+ ret = FW_LDST_ADDRSPC_SGE_FLMC;
+ else
+ ret = FW_LDST_ADDRSPC_SGE_CONMC;
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_READ |
+ V_FW_LDST_CMD_ADDRSPACE(ret));
+ c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
+ c.u.idctxt.physid = cpu_to_be32(cid);
+
+ ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
+ if (ret == 0) {
+ data[0] = be32_to_cpu(c.u.idctxt.ctxt_data0);
+ data[1] = be32_to_cpu(c.u.idctxt.ctxt_data1);
+ data[2] = be32_to_cpu(c.u.idctxt.ctxt_data2);
+ data[3] = be32_to_cpu(c.u.idctxt.ctxt_data3);
+ data[4] = be32_to_cpu(c.u.idctxt.ctxt_data4);
+ data[5] = be32_to_cpu(c.u.idctxt.ctxt_data5);
+ }
+ return ret;
+}
+
+/**
+ * t4_sge_ctxt_rd_bd - read an SGE context bypassing FW
+ * @adap: the adapter
+ * @cid: the context id
+ * @ctype: the context type
+ * @data: where to store the context data
+ *
+ * Reads an SGE context directly, bypassing FW. This is only for
+ * debugging when FW is unavailable.
+ */
+int t4_sge_ctxt_rd_bd(struct adapter *adap, unsigned int cid, enum ctxt_type ctype,
+ u32 *data)
+{
+ int i, ret;
+
+ t4_write_reg(adap, A_SGE_CTXT_CMD, V_CTXTQID(cid) | V_CTXTTYPE(ctype));
+ ret = t4_wait_op_done(adap, A_SGE_CTXT_CMD, F_BUSY, 0, 3, 1);
+ if (!ret)
+ for (i = A_SGE_CTXT_DATA0; i <= A_SGE_CTXT_DATA5; i += 4)
+ *data++ = t4_read_reg(adap, i);
+ return ret;
+}
+
int t4_sched_config(struct adapter *adapter, int type, int minmaxen,
int sleep_ok)
{
@@ -5797,3 +9079,78 @@ int t4_sched_params(struct adapter *adapter, int type, int level, int mode,
return t4_wr_mbox_meat(adapter,adapter->mbox, &cmd, sizeof(cmd),
NULL, sleep_ok);
}
+
+/*
+ * t4_config_watchdog - configure (enable/disable) a watchdog timer
+ * @adapter: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @pf: the PF owning the queue
+ * @vf: the VF owning the queue
+ * @timeout: watchdog timeout in ms
+ * @action: watchdog timer / action
+ *
+ * There are separate watchdog timers for each possible watchdog
+ * action. Configure one of the watchdog timers by setting a non-zero
+ * timeout. Disable a watchdog timer by using a timeout of zero.
+ */
+int t4_config_watchdog(struct adapter *adapter, unsigned int mbox,
+ unsigned int pf, unsigned int vf,
+ unsigned int timeout, unsigned int action)
+{
+ struct fw_watchdog_cmd wdog;
+ unsigned int ticks;
+
+ /*
+ * The watchdog command expects a timeout in units of 10ms so we need
+ * to convert it here (via rounding) and force a minimum of one 10ms
+ * "tick" if the timeout is non-zero but the convertion results in 0
+ * ticks.
+ */
+ ticks = (timeout + 5)/10;
+ if (timeout && !ticks)
+ ticks = 1;
+
+ memset(&wdog, 0, sizeof wdog);
+ wdog.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_WATCHDOG_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE |
+ V_FW_PARAMS_CMD_PFN(pf) |
+ V_FW_PARAMS_CMD_VFN(vf));
+ wdog.retval_len16 = cpu_to_be32(FW_LEN16(wdog));
+ wdog.timeout = cpu_to_be32(ticks);
+ wdog.action = cpu_to_be32(action);
+
+ return t4_wr_mbox(adapter, mbox, &wdog, sizeof wdog, NULL);
+}
+
+int t4_get_devlog_level(struct adapter *adapter, unsigned int *level)
+{
+ struct fw_devlog_cmd devlog_cmd;
+ int ret;
+
+ memset(&devlog_cmd, 0, sizeof(devlog_cmd));
+ devlog_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_DEVLOG_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_READ);
+ devlog_cmd.retval_len16 = cpu_to_be32(FW_LEN16(devlog_cmd));
+ ret = t4_wr_mbox(adapter, adapter->mbox, &devlog_cmd,
+ sizeof(devlog_cmd), &devlog_cmd);
+ if (ret)
+ return ret;
+
+ *level = devlog_cmd.level;
+ return 0;
+}
+
+int t4_set_devlog_level(struct adapter *adapter, unsigned int level)
+{
+ struct fw_devlog_cmd devlog_cmd;
+
+ memset(&devlog_cmd, 0, sizeof(devlog_cmd));
+ devlog_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_DEVLOG_CMD) |
+ F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE);
+ devlog_cmd.level = level;
+ devlog_cmd.retval_len16 = cpu_to_be32(FW_LEN16(devlog_cmd));
+ return t4_wr_mbox(adapter, adapter->mbox, &devlog_cmd,
+ sizeof(devlog_cmd), &devlog_cmd);
+}
OpenPOWER on IntegriCloud