summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgbe/common/t4_hw.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2016-11-04 18:45:06 +0000
committerjhb <jhb@FreeBSD.org>2016-11-04 18:45:06 +0000
commit2d52438878459dffe15fcd7dc5430d9873313f77 (patch)
tree57aae4f4cf8ec017ded2fd5e284ea0a702b1f09b /sys/dev/cxgbe/common/t4_hw.c
parentd0d0f648f604c9ca282aed80a50a7aa1bcdc72df (diff)
downloadFreeBSD-src-2d52438878459dffe15fcd7dc5430d9873313f77.zip
FreeBSD-src-2d52438878459dffe15fcd7dc5430d9873313f77.tar.gz
MFC 295778,296249,296333,296383,296471,296478,296481,296485,296488-296491,
296493-296496,296544,296710-296711,297863,299685: Catch up to changes to the internal shared code. Note that this merge includes two different firmware updates, but the effective change is to update to the last version (1.15.37.0). As such, I've trimmed the log message of the first update (1.15.28.0). In addition, the M_WAIT macro added in t4_regs.h had to be renamed to CXGBE_M_WAIT to avoid a collision on 10.x that is not present on 11. 295778: cxgbe: catch up with the latest hardware-related definitions. 296249: cxgbe(4): Update T5 and T4 firmwares to 1.15.28.0. 296333: cxgbe(4): First of many changes to reduce diffs with internal shared code: - Rename some CamelCase variables. - s/t4_link_start/t4_link_l1cfg/g - Pull in t4_get_port_type_description. - Move t4_wait_op_done to t4_hw.c. - Flip the order of the RDMA stats. - Remove unsused function t4_iq_start_stop. - Move t4_wait_op_done and t4_wait_op_done_val to t4_hw.c 296383: cxgbe(4): Very basic T6 awareness. This is part of ongoing work to update to the latest internal shared code. - Add a chip_params structure to keep track of hardware constants for all generations of Terminators handled by cxgbe. - Update t4_hw_pci_read_cfg4 to work with T6. - Update the hardware debug sysctls (hidden within dev.<tNnex>.<n>.misc.*) to work with T6. Most of the changes are in the decoders for the CIM logic analyzer and the MPS TCAM. - Acquire the regwin lock around indirect register accesses. 296471: cxgbe(4): Updated register dumps. - Get the list of registers to read during a regdump from the shared code instead of the OS specific code. This follows a similar move internally. The shared code includes the list for T6. - Update cxgbetool to be able to decode T5 VF, T6, and T6 VF register dumps (and catch up with some updates to T4 and T5 register decode). 296478: cxgbe(4): Add a struct sge_params to store per-adapter SGE parameters. Move the code that reads all the parameters to t4_init_sge_params in the shared code. Use these per-adapter values instead of globals. 296481: cxgbe(4): Overhaul the shared code that deals with the chip's TP block, which is responsible for filtering and RSS. Add the ability to use filters that match on PF/VF (aka "VNIC id") while here. This is mutually exclusive with filtering on outer VLAN tag with Q-in-Q. 296485: cxgbe(4): Update the interrupt handlers for hardware errors. 296488: cxgbe(4): Updates to mailbox routines in the shared code. 296489: cxgbe(4): Updates to the shared routines that deal with the serial EEPROM, flash, and VPD. 296490: cxgbe(4): Remove __devinit and SPEED_<foo> as part of catch up with internal shared code. 296491: cxgbe(4): Updates to shared routines that get/set various parameters via the firmware. 296493: cxgbe(4): Use t4_link_down_rc_str in shared code to decode the reason the link is down, instead of doing it in OS specific code. 296494: cxgbe(4): Many new functions in the shared code, unused at this time. 296495: cxgbe(4): Fix t4_tp_get_rdma_stats. 296496: cxgbe(4): Minor updates to the shared routines that deal with firmware images. 296544: cxgbe(4): Reshuffle and rototill t4_hw.c, solely to reduce diffs with the internal shared code. 296710: cxgbe(4): Catch up with the latest list of card capabilities as reported by the firmware. 296711: cxgbe(4): Fix typo in previous commit. 297863: Rename the 'M_B' macro in t4_regs.h to 'CXGBE_M_B'. This fixes a conflict with the M_B macro in powerpc's <machine/db_machdep.h> exposed by the recent addition of DDB commands to the cxgbe driver. 299685: cxgbe(4): Update T5 and T4 firmwares to 1.15.37.0. These firmwares were obtained from the "Chelsio T5/T4 Unified Wire v2.12.0.3 for Linux" release. Changes since 1.14.4.0 (which is the firmware in -STABLE branches) are in the "Release Notes" accompanying the Unified Wire release and are copy-pasted here as well. 22.1. T5 Firmware +++++++++++++++++++++++++++++++++ Version : 1.15.37.0 Date : 04/27/2016 ================================================================================ FIXES ----- BASE: - Fixed an issue in FW_RSS_VI_CONFIG_CMD handling where the default ingress queue was ignored. - Fixed an issue where adapter failed to load fw by adjusting DRAM frequency. - Fixed an issue in watchdog which was causing VM bring-up failure after reboot. - Fixed 40G link failures with some switches when auto-negotiation enabled. - Fixed to improve on link bring-up time. - Per port buffer groups size doubled to improve performance. - Fixed an issue where bogus d3hot bits were set causing traffic stall. - Fixed an issue where sometimes adapter was not seen after reboot. - Fixed an issue where iWARP was crashing in conjunction with traffic management. - Fixed an issue where link failed to come up after removing twinax cable and inserting optical module. ETH - Fixed a link flap issue on T580-CR. OFLD - Fixed a potential iSCSI data corruption issue by disabling RxFragEn flag. FOiSCSI - Fixed an issue in recovery path where connection was getting closed before recovery processing was done. - Fixed an issue in TCP port reuse. - Fixed an issue in recovery path when large number (>64) of iSCSI connections were in use. - Returned ENETUNREACH if IP was not been provisioned yet and driver tried to use given inerface. - Fixed an issue where fw was sending ENETUNREACH event for normal tcp disconnection. DCBX - Fixed an issue where iscsi tlv is sent incorrectly to host. (DCBX CEE) - Fixed an issue where apply bit set for APP id was affecting the ETS and PFC settings.(DCBX IEEE) - Fixed an issue where app priority values are not handled correctly in fw. (DCBX IEEE) - Fixed an issue where enable/disable dcbx can cause crash. (DCBX CEE,DCBX IEEE) FOFCoE - Removed BB6 support. ENHANCEMENTS ------------ BASE: - Added new interface to program DCA settings in SGE contexts; allow 32-byte IQE size - Added PTP interface fw_ptp_ts to support PTP Frequeny and Offset adjustment. - Added MPS raw interface. ETH: - New mailbox command FW_DCB_IEEE_CMD api added for IEEE dcbx. OFLD: - WR opcode is returned to host in cqe error response. 22.2. T4 Firmware +++++++++++++++++ Version : 1.15.37.0 Date : 04/27/2016 ================================================================================ FIXES ----- BASE: - Fixed an issue in FW_RSS_VI_CONFIG_CMD handling where default ingress queue was ignored. - Fixed an issue in watchdog which was causing VM bring-up failure after reboot. - Per port buffer groups size doubled to improve performance. - Fixed an issue where iWARP was crashing in conjunction with traffic management. FOiSCSI: - Fixed an issue in recovery path where connection was getting closed before recovery processing was done. - Fixed an issue in TCP port reuse. - Fixed an issue in recovery path when large number (>64) of iSCSI connections were in use. - Returned ENETUNREACH if IP had not been provisioned yet and driver tried to use given inerface. DCBX - Fixed an issue where iscsi tlv is sent incorrectly to host.(DCBX CEE) - Fixed an issue where enable/disable dcbx can cause crash in firmware.(DCBX CEE) FOiSCSI - Fixes an issue where fw was sending ENETUNREACH event for normal tcp disconnection. FOFCoE - Removed BB6 support. ENHANCEMENTS ------------ BASE: - Added MPS raw interface. ETH: - New mailbox command FW_DCB_IEEE_CMD api added for IEEE dcbx. ================================================================================ Sponsored by: Chelsio Communications
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