156b2bdd1SGireesh Nagabhushana /*
256b2bdd1SGireesh Nagabhushana * This file and its contents are supplied under the terms of the
356b2bdd1SGireesh Nagabhushana * Common Development and Distribution License ("CDDL"), version 1.0.
456b2bdd1SGireesh Nagabhushana * You may only use this file in accordance with the terms of version
556b2bdd1SGireesh Nagabhushana * 1.0 of the CDDL.
656b2bdd1SGireesh Nagabhushana *
756b2bdd1SGireesh Nagabhushana * A full copy of the text of the CDDL should have accompanied this
856b2bdd1SGireesh Nagabhushana * source. A copy of the CDDL is also available via the Internet at
956b2bdd1SGireesh Nagabhushana * http://www.illumos.org/license/CDDL.
1056b2bdd1SGireesh Nagabhushana */
1156b2bdd1SGireesh Nagabhushana
1256b2bdd1SGireesh Nagabhushana /*
133dde7c95SVishal Kulkarni * This file is part of the Chelsio T4/T5/T6 Ethernet driver.
1456b2bdd1SGireesh Nagabhushana *
157e6ad469SVishal Kulkarni * Copyright (C) 2003-2019 Chelsio Communications. All rights reserved.
1656b2bdd1SGireesh Nagabhushana *
1756b2bdd1SGireesh Nagabhushana * This program is distributed in the hope that it will be useful, but WITHOUT
1856b2bdd1SGireesh Nagabhushana * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1956b2bdd1SGireesh Nagabhushana * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
2056b2bdd1SGireesh Nagabhushana * release for licensing terms and conditions.
2156b2bdd1SGireesh Nagabhushana */
223dde7c95SVishal Kulkarni
23d77e6e0fSPaul Winder /*
24d77e6e0fSPaul Winder * Copyright 2020 RackTop Systems, Inc.
25d77e6e0fSPaul Winder */
26d77e6e0fSPaul Winder
2756b2bdd1SGireesh Nagabhushana #include "common.h"
2856b2bdd1SGireesh Nagabhushana #include "t4_regs.h"
2956b2bdd1SGireesh Nagabhushana #include "t4_regs_values.h"
3056b2bdd1SGireesh Nagabhushana #include "t4fw_interface.h"
3156b2bdd1SGireesh Nagabhushana
323dde7c95SVishal Kulkarni /**
3356b2bdd1SGireesh Nagabhushana * t4_wait_op_done_val - wait until an operation is completed
3456b2bdd1SGireesh Nagabhushana * @adapter: the adapter performing the operation
3556b2bdd1SGireesh Nagabhushana * @reg: the register to check for completion
3656b2bdd1SGireesh Nagabhushana * @mask: a single-bit field within @reg that indicates completion
3756b2bdd1SGireesh Nagabhushana * @polarity: the value of the field when the operation is completed
3856b2bdd1SGireesh Nagabhushana * @attempts: number of check iterations
3956b2bdd1SGireesh Nagabhushana * @delay: delay in usecs between iterations
4056b2bdd1SGireesh Nagabhushana * @valp: where to store the value of the register at completion time
4156b2bdd1SGireesh Nagabhushana *
4256b2bdd1SGireesh Nagabhushana * Wait until an operation is completed by checking a bit in a register
4356b2bdd1SGireesh Nagabhushana * up to @attempts times. If @valp is not NULL the value of the register
4456b2bdd1SGireesh Nagabhushana * at the time it indicated completion is stored there. Returns 0 if the
4556b2bdd1SGireesh Nagabhushana * operation completes and -EAGAIN otherwise.
4656b2bdd1SGireesh Nagabhushana */
t4_wait_op_done_val(struct adapter * adapter,int reg,u32 mask,int polarity,int attempts,int delay,u32 * valp)473dde7c95SVishal Kulkarni static int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
48de483253SVishal Kulkarni int polarity, int attempts, int delay, u32 *valp)
4956b2bdd1SGireesh Nagabhushana {
5056b2bdd1SGireesh Nagabhushana while (1) {
5156b2bdd1SGireesh Nagabhushana u32 val = t4_read_reg(adapter, reg);
5256b2bdd1SGireesh Nagabhushana
5356b2bdd1SGireesh Nagabhushana if (!!(val & mask) == polarity) {
543dde7c95SVishal Kulkarni if (valp)
5556b2bdd1SGireesh Nagabhushana *valp = val;
563dde7c95SVishal Kulkarni return 0;
5756b2bdd1SGireesh Nagabhushana }
583dde7c95SVishal Kulkarni if (--attempts == 0)
593dde7c95SVishal Kulkarni return -EAGAIN;
603dde7c95SVishal Kulkarni if (delay)
61de483253SVishal Kulkarni udelay(delay);
6256b2bdd1SGireesh Nagabhushana }
6356b2bdd1SGireesh Nagabhushana }
6456b2bdd1SGireesh Nagabhushana
t4_wait_op_done(struct adapter * adapter,int reg,u32 mask,int polarity,int attempts,int delay)653dde7c95SVishal Kulkarni static inline int t4_wait_op_done(struct adapter *adapter, int reg, u32 mask,
663dde7c95SVishal Kulkarni int polarity, int attempts, int delay)
673dde7c95SVishal Kulkarni {
683dde7c95SVishal Kulkarni return t4_wait_op_done_val(adapter, reg, mask, polarity, attempts,
693dde7c95SVishal Kulkarni delay, NULL);
703dde7c95SVishal Kulkarni }
713dde7c95SVishal Kulkarni
723dde7c95SVishal Kulkarni /**
7356b2bdd1SGireesh Nagabhushana * t4_set_reg_field - set a register field to a value
7456b2bdd1SGireesh Nagabhushana * @adapter: the adapter to program
7556b2bdd1SGireesh Nagabhushana * @addr: the register address
7656b2bdd1SGireesh Nagabhushana * @mask: specifies the portion of the register to modify
7756b2bdd1SGireesh Nagabhushana * @val: the new value for the register field
7856b2bdd1SGireesh Nagabhushana *
7956b2bdd1SGireesh Nagabhushana * Sets a register field specified by the supplied mask to the
8056b2bdd1SGireesh Nagabhushana * given value.
8156b2bdd1SGireesh Nagabhushana */
t4_set_reg_field(struct adapter * adapter,unsigned int addr,u32 mask,u32 val)823dde7c95SVishal Kulkarni void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask,
833dde7c95SVishal Kulkarni u32 val)
8456b2bdd1SGireesh Nagabhushana {
8556b2bdd1SGireesh Nagabhushana u32 v = t4_read_reg(adapter, addr) & ~mask;
8656b2bdd1SGireesh Nagabhushana
8756b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, addr, v | val);
8856b2bdd1SGireesh Nagabhushana (void) t4_read_reg(adapter, addr); /* flush */
8956b2bdd1SGireesh Nagabhushana }
9056b2bdd1SGireesh Nagabhushana
913dde7c95SVishal Kulkarni /**
9256b2bdd1SGireesh Nagabhushana * t4_read_indirect - read indirectly addressed registers
9356b2bdd1SGireesh Nagabhushana * @adap: the adapter
9456b2bdd1SGireesh Nagabhushana * @addr_reg: register holding the indirect address
9556b2bdd1SGireesh Nagabhushana * @data_reg: register holding the value of the indirect register
9656b2bdd1SGireesh Nagabhushana * @vals: where the read register values are stored
9756b2bdd1SGireesh Nagabhushana * @nregs: how many indirect registers to read
9856b2bdd1SGireesh Nagabhushana * @start_idx: index of first indirect register to read
9956b2bdd1SGireesh Nagabhushana *
10056b2bdd1SGireesh Nagabhushana * Reads registers that are accessed indirectly through an address/data
10156b2bdd1SGireesh Nagabhushana * register pair.
10256b2bdd1SGireesh Nagabhushana */
t4_read_indirect(struct adapter * adap,unsigned int addr_reg,unsigned int data_reg,u32 * vals,unsigned int nregs,unsigned int start_idx)1033dde7c95SVishal Kulkarni void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
1043dde7c95SVishal Kulkarni unsigned int data_reg, u32 *vals,
1053dde7c95SVishal Kulkarni unsigned int nregs, unsigned int start_idx)
10656b2bdd1SGireesh Nagabhushana {
10756b2bdd1SGireesh Nagabhushana while (nregs--) {
10856b2bdd1SGireesh Nagabhushana t4_write_reg(adap, addr_reg, start_idx);
10956b2bdd1SGireesh Nagabhushana *vals++ = t4_read_reg(adap, data_reg);
11056b2bdd1SGireesh Nagabhushana start_idx++;
11156b2bdd1SGireesh Nagabhushana }
11256b2bdd1SGireesh Nagabhushana }
11356b2bdd1SGireesh Nagabhushana
1143dde7c95SVishal Kulkarni /**
11556b2bdd1SGireesh Nagabhushana * t4_write_indirect - write indirectly addressed registers
11656b2bdd1SGireesh Nagabhushana * @adap: the adapter
11756b2bdd1SGireesh Nagabhushana * @addr_reg: register holding the indirect addresses
11856b2bdd1SGireesh Nagabhushana * @data_reg: register holding the value for the indirect registers
11956b2bdd1SGireesh Nagabhushana * @vals: values to write
12056b2bdd1SGireesh Nagabhushana * @nregs: how many indirect registers to write
12156b2bdd1SGireesh Nagabhushana * @start_idx: address of first indirect register to write
12256b2bdd1SGireesh Nagabhushana *
12356b2bdd1SGireesh Nagabhushana * Writes a sequential block of registers that are accessed indirectly
12456b2bdd1SGireesh Nagabhushana * through an address/data register pair.
12556b2bdd1SGireesh Nagabhushana */
t4_write_indirect(struct adapter * adap,unsigned int addr_reg,unsigned int data_reg,const u32 * vals,unsigned int nregs,unsigned int start_idx)1263dde7c95SVishal Kulkarni void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
1273dde7c95SVishal Kulkarni unsigned int data_reg, const u32 *vals,
1283dde7c95SVishal Kulkarni unsigned int nregs, unsigned int start_idx)
12956b2bdd1SGireesh Nagabhushana {
13056b2bdd1SGireesh Nagabhushana while (nregs--) {
13156b2bdd1SGireesh Nagabhushana t4_write_reg(adap, addr_reg, start_idx++);
13256b2bdd1SGireesh Nagabhushana t4_write_reg(adap, data_reg, *vals++);
13356b2bdd1SGireesh Nagabhushana }
13456b2bdd1SGireesh Nagabhushana }
13556b2bdd1SGireesh Nagabhushana
13656b2bdd1SGireesh Nagabhushana /*
1373dde7c95SVishal Kulkarni * Read a 32-bit PCI Configuration Space register via the PCI-E backdoor
1383dde7c95SVishal Kulkarni * mechanism. This guarantees that we get the real value even if we're
1393dde7c95SVishal Kulkarni * operating within a Virtual Machine and the Hypervisor is trapping our
1403dde7c95SVishal Kulkarni * Configuration Space accesses.
1413dde7c95SVishal Kulkarni *
1423dde7c95SVishal Kulkarni * N.B. This routine should only be used as a last resort: the firmware uses
1433dde7c95SVishal Kulkarni * the backdoor registers on a regular basis and we can end up
1443dde7c95SVishal Kulkarni * conflicting with it's uses!
1453dde7c95SVishal Kulkarni */
t4_hw_pci_read_cfg4(struct adapter * adap,int reg,u32 * val)1463dde7c95SVishal Kulkarni void t4_hw_pci_read_cfg4(struct adapter *adap, int reg, u32 *val)
1473dde7c95SVishal Kulkarni {
1483dde7c95SVishal Kulkarni u32 req = V_FUNCTION(adap->pf) | V_REGISTER(reg);
1493dde7c95SVishal Kulkarni
1503dde7c95SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5)
1513dde7c95SVishal Kulkarni req |= F_ENABLE;
1523dde7c95SVishal Kulkarni else
1533dde7c95SVishal Kulkarni req |= F_T6_ENABLE;
1543dde7c95SVishal Kulkarni
1553dde7c95SVishal Kulkarni if (is_t4(adap->params.chip))
1563dde7c95SVishal Kulkarni req |= F_LOCALCFG;
1573dde7c95SVishal Kulkarni
1583dde7c95SVishal Kulkarni t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ, req);
1593dde7c95SVishal Kulkarni *val = t4_read_reg(adap, A_PCIE_CFG_SPACE_DATA);
1603dde7c95SVishal Kulkarni
1613dde7c95SVishal Kulkarni /* Reset F_ENABLE to 0 so reads of PCIE_CFG_SPACE_DATA won't cause a
1623dde7c95SVishal Kulkarni * Configuration Space read. (None of the other fields matter when
1633dde7c95SVishal Kulkarni * F_ENABLE is 0 so a simple register write is easier than a
1643dde7c95SVishal Kulkarni * read-modify-write via t4_set_reg_field().)
1653dde7c95SVishal Kulkarni */
1663dde7c95SVishal Kulkarni t4_write_reg(adap, A_PCIE_CFG_SPACE_REQ, 0);
1673dde7c95SVishal Kulkarni }
1683dde7c95SVishal Kulkarni
1693dde7c95SVishal Kulkarni /*
170de483253SVishal Kulkarni * t4_report_fw_error - report firmware error
171de483253SVishal Kulkarni * @adap: the adapter
172de483253SVishal Kulkarni *
173de483253SVishal Kulkarni * The adapter firmware can indicate error conditions to the host.
1743dde7c95SVishal Kulkarni * If the firmware has indicated an error, print out the reason for
1753dde7c95SVishal Kulkarni * the firmware error.
176de483253SVishal Kulkarni */
t4_report_fw_error(struct adapter * adap)177de483253SVishal Kulkarni static void t4_report_fw_error(struct adapter *adap)
178de483253SVishal Kulkarni {
1793dde7c95SVishal Kulkarni static const char *const reason[] = {
180de483253SVishal Kulkarni "Crash", /* PCIE_FW_EVAL_CRASH */
181de483253SVishal Kulkarni "During Device Preparation", /* PCIE_FW_EVAL_PREP */
182de483253SVishal Kulkarni "During Device Configuration", /* PCIE_FW_EVAL_CONF */
183de483253SVishal Kulkarni "During Device Initialization", /* PCIE_FW_EVAL_INIT */
184de483253SVishal Kulkarni "Unexpected Event", /* PCIE_FW_EVAL_UNEXPECTEDEVENT */
185de483253SVishal Kulkarni "Insufficient Airflow", /* PCIE_FW_EVAL_OVERHEAT */
186de483253SVishal Kulkarni "Device Shutdown", /* PCIE_FW_EVAL_DEVICESHUTDOWN */
187de483253SVishal Kulkarni "Reserved", /* reserved */
188de483253SVishal Kulkarni };
189de483253SVishal Kulkarni u32 pcie_fw;
190de483253SVishal Kulkarni
191de483253SVishal Kulkarni pcie_fw = t4_read_reg(adap, A_PCIE_FW);
1927e6ad469SVishal Kulkarni if (pcie_fw & F_PCIE_FW_ERR) {
193de483253SVishal Kulkarni CH_ERR(adap, "Firmware reports adapter error: %s\n",
194de483253SVishal Kulkarni reason[G_PCIE_FW_EVAL(pcie_fw)]);
1957e6ad469SVishal Kulkarni adap->flags &= ~FW_OK;
1967e6ad469SVishal Kulkarni }
197de483253SVishal Kulkarni }
198de483253SVishal Kulkarni
199de483253SVishal Kulkarni /*
20056b2bdd1SGireesh Nagabhushana * Get the reply to a mailbox command and store it in @rpl in big-endian order.
20156b2bdd1SGireesh Nagabhushana */
get_mbox_rpl(struct adapter * adap,__be64 * rpl,int nflit,u32 mbox_addr)2023dde7c95SVishal Kulkarni static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
2033dde7c95SVishal Kulkarni u32 mbox_addr)
20456b2bdd1SGireesh Nagabhushana {
2053dde7c95SVishal Kulkarni for ( ; nflit; nflit--, mbox_addr += 8)
20656b2bdd1SGireesh Nagabhushana *rpl++ = cpu_to_be64(t4_read_reg64(adap, mbox_addr));
20756b2bdd1SGireesh Nagabhushana }
20856b2bdd1SGireesh Nagabhushana
20956b2bdd1SGireesh Nagabhushana /*
21056b2bdd1SGireesh Nagabhushana * Handle a FW assertion reported in a mailbox.
21156b2bdd1SGireesh Nagabhushana */
fw_asrt(struct adapter * adap,struct fw_debug_cmd * asrt)2123dde7c95SVishal Kulkarni static void fw_asrt(struct adapter *adap, struct fw_debug_cmd *asrt)
21356b2bdd1SGireesh Nagabhushana {
2143dde7c95SVishal Kulkarni CH_ALERT(adap,
2153dde7c95SVishal Kulkarni "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n",
2163dde7c95SVishal Kulkarni asrt->u.assert.filename_0_7,
2173dde7c95SVishal Kulkarni be32_to_cpu(asrt->u.assert.line),
2183dde7c95SVishal Kulkarni be32_to_cpu(asrt->u.assert.x),
2193dde7c95SVishal Kulkarni be32_to_cpu(asrt->u.assert.y));
22056b2bdd1SGireesh Nagabhushana }
22156b2bdd1SGireesh Nagabhushana
22256b2bdd1SGireesh Nagabhushana #define X_CIM_PF_NOACCESS 0xeeeeeeee
2233dde7c95SVishal Kulkarni
22456b2bdd1SGireesh Nagabhushana /*
2253dde7c95SVishal Kulkarni * If the OS Driver wants busy waits to keep a watchdog happy, tap it during
2263dde7c95SVishal Kulkarni * busy loops which don't sleep.
2273dde7c95SVishal Kulkarni */
2283dde7c95SVishal Kulkarni #ifdef T4_OS_NEEDS_TOUCH_NMI_WATCHDOG
2293dde7c95SVishal Kulkarni #define T4_OS_TOUCH_NMI_WATCHDOG() t4_os_touch_nmi_watchdog()
2303dde7c95SVishal Kulkarni #else
2313dde7c95SVishal Kulkarni #define T4_OS_TOUCH_NMI_WATCHDOG()
2323dde7c95SVishal Kulkarni #endif
2333dde7c95SVishal Kulkarni
2343dde7c95SVishal Kulkarni #ifdef T4_OS_LOG_MBOX_CMDS
2353dde7c95SVishal Kulkarni /**
2363dde7c95SVishal Kulkarni * t4_record_mbox - record a Firmware Mailbox Command/Reply in the log
2373dde7c95SVishal Kulkarni * @adapter: the adapter
2383dde7c95SVishal Kulkarni * @cmd: the Firmware Mailbox Command or Reply
2393dde7c95SVishal Kulkarni * @size: command length in bytes
2403dde7c95SVishal Kulkarni * @access: the time (ms) needed to access the Firmware Mailbox
2413dde7c95SVishal Kulkarni * @execute: the time (ms) the command spent being executed
2423dde7c95SVishal Kulkarni */
t4_record_mbox(struct adapter * adapter,const __be64 * cmd,unsigned int size,int access,int execute)2433dde7c95SVishal Kulkarni static void t4_record_mbox(struct adapter *adapter,
2443dde7c95SVishal Kulkarni const __be64 *cmd, unsigned int size,
2453dde7c95SVishal Kulkarni int access, int execute)
2463dde7c95SVishal Kulkarni {
2473dde7c95SVishal Kulkarni struct mbox_cmd_log *log = adapter->mbox_log;
2483dde7c95SVishal Kulkarni struct mbox_cmd *entry;
2493dde7c95SVishal Kulkarni int i;
2503dde7c95SVishal Kulkarni
2513dde7c95SVishal Kulkarni entry = mbox_cmd_log_entry(log, log->cursor++);
2523dde7c95SVishal Kulkarni if (log->cursor == log->size)
2533dde7c95SVishal Kulkarni log->cursor = 0;
2543dde7c95SVishal Kulkarni
2553dde7c95SVishal Kulkarni for (i = 0; i < size/8; i++)
2563dde7c95SVishal Kulkarni entry->cmd[i] = be64_to_cpu(cmd[i]);
2573dde7c95SVishal Kulkarni while (i < MBOX_LEN/8)
2583dde7c95SVishal Kulkarni entry->cmd[i++] = 0;
2593dde7c95SVishal Kulkarni entry->timestamp = t4_os_timestamp();
2603dde7c95SVishal Kulkarni entry->seqno = log->seqno++;
2613dde7c95SVishal Kulkarni entry->access = access;
2623dde7c95SVishal Kulkarni entry->execute = execute;
2633dde7c95SVishal Kulkarni }
2643dde7c95SVishal Kulkarni
2653dde7c95SVishal Kulkarni #define T4_RECORD_MBOX(__adapter, __cmd, __size, __access, __execute) \
2663dde7c95SVishal Kulkarni t4_record_mbox(__adapter, __cmd, __size, __access, __execute)
2673dde7c95SVishal Kulkarni
2683dde7c95SVishal Kulkarni #else /* !T4_OS_LOG_MBOX_CMDS */
2693dde7c95SVishal Kulkarni
2703dde7c95SVishal Kulkarni #define T4_RECORD_MBOX(__adapter, __cmd, __size, __access, __execute) \
2713dde7c95SVishal Kulkarni /* nothing */
2723dde7c95SVishal Kulkarni
2733dde7c95SVishal Kulkarni #endif /* !T4_OS_LOG_MBOX_CMDS */
2743dde7c95SVishal Kulkarni
2753dde7c95SVishal Kulkarni /**
2763dde7c95SVishal Kulkarni * t4_record_mbox_marker - record a marker in the mailbox log
2773dde7c95SVishal Kulkarni * @adapter: the adapter
2783dde7c95SVishal Kulkarni * @marker: byte array marker
2793dde7c95SVishal Kulkarni * @size: marker size in bytes
2803dde7c95SVishal Kulkarni *
2813dde7c95SVishal Kulkarni * We inject a "fake mailbox command" into the Firmware Mailbox Log
2823dde7c95SVishal Kulkarni * using a known command token and then the bytes of the specified
2833dde7c95SVishal Kulkarni * marker. This lets debugging code inject markers into the log to
2843dde7c95SVishal Kulkarni * help identify which commands are in response to higher level code.
2853dde7c95SVishal Kulkarni */
t4_record_mbox_marker(struct adapter * adapter,const void * marker,unsigned int size)2863dde7c95SVishal Kulkarni void t4_record_mbox_marker(struct adapter *adapter,
2873dde7c95SVishal Kulkarni const void *marker, unsigned int size)
2883dde7c95SVishal Kulkarni {
2893dde7c95SVishal Kulkarni #ifdef T4_OS_LOG_MBOX_CMDS
2903dde7c95SVishal Kulkarni __be64 marker_cmd[MBOX_LEN/8];
2913dde7c95SVishal Kulkarni const unsigned int max_marker = sizeof marker_cmd - sizeof (__be64);
2923dde7c95SVishal Kulkarni unsigned int marker_cmd_size;
2933dde7c95SVishal Kulkarni
2943dde7c95SVishal Kulkarni if (size > max_marker)
2953dde7c95SVishal Kulkarni size = max_marker;
2963dde7c95SVishal Kulkarni
2973dde7c95SVishal Kulkarni marker_cmd[0] = cpu_to_be64(~0LLU);
2983dde7c95SVishal Kulkarni memcpy(&marker_cmd[1], marker, size);
2993dde7c95SVishal Kulkarni memset((unsigned char *)&marker_cmd[1] + size, 0, max_marker - size);
3003dde7c95SVishal Kulkarni marker_cmd_size = sizeof (__be64) + roundup(size, sizeof (__be64));
3013dde7c95SVishal Kulkarni
3023dde7c95SVishal Kulkarni t4_record_mbox(adapter, marker_cmd, marker_cmd_size, 0, 0);
3033dde7c95SVishal Kulkarni #endif /* T4_OS_LOG_MBOX_CMDS */
3043dde7c95SVishal Kulkarni }
3053dde7c95SVishal Kulkarni
3063dde7c95SVishal Kulkarni /*
3073dde7c95SVishal Kulkarni * Delay time in microseconds to wait for mailbox access/fw reply
3083dde7c95SVishal Kulkarni * to mailbox command
3093dde7c95SVishal Kulkarni */
3103dde7c95SVishal Kulkarni #define MIN_MBOX_CMD_DELAY 900
3113dde7c95SVishal Kulkarni #define MBOX_CMD_DELAY 1000
3123dde7c95SVishal Kulkarni
3133dde7c95SVishal Kulkarni /**
3143dde7c95SVishal Kulkarni * t4_wr_mbox_meat_timeout - send a command to FW through the given mailbox
31556b2bdd1SGireesh Nagabhushana * @adap: the adapter
31656b2bdd1SGireesh Nagabhushana * @mbox: index of the mailbox to use
31756b2bdd1SGireesh Nagabhushana * @cmd: the command to write
31856b2bdd1SGireesh Nagabhushana * @size: command length in bytes
31956b2bdd1SGireesh Nagabhushana * @rpl: where to optionally store the reply
32056b2bdd1SGireesh Nagabhushana * @sleep_ok: if true we may sleep while awaiting command completion
3213dde7c95SVishal Kulkarni * @timeout: time to wait for command to finish before timing out
3223dde7c95SVishal Kulkarni * (negative implies @sleep_ok=false)
32356b2bdd1SGireesh Nagabhushana *
32456b2bdd1SGireesh Nagabhushana * Sends the given command to FW through the selected mailbox and waits
32556b2bdd1SGireesh Nagabhushana * for the FW to execute the command. If @rpl is not %NULL it is used to
32656b2bdd1SGireesh Nagabhushana * store the FW's reply to the command. The command and its optional
32756b2bdd1SGireesh Nagabhushana * reply are of the same length. Some FW commands like RESET and
32856b2bdd1SGireesh Nagabhushana * INITIALIZE can take a considerable amount of time to execute.
32956b2bdd1SGireesh Nagabhushana * @sleep_ok determines whether we may sleep while awaiting the response.
33056b2bdd1SGireesh Nagabhushana * If sleeping is allowed we use progressive backoff otherwise we spin.
3313dde7c95SVishal Kulkarni * Note that passing in a negative @timeout is an alternate mechanism
3323dde7c95SVishal Kulkarni * for specifying @sleep_ok=false. This is useful when a higher level
3333dde7c95SVishal Kulkarni * interface allows for specification of @timeout but not @sleep_ok ...
33456b2bdd1SGireesh Nagabhushana *
33556b2bdd1SGireesh Nagabhushana * The return value is 0 on success or a negative errno on failure. A
33656b2bdd1SGireesh Nagabhushana * failure can happen either because we are not able to execute the
33756b2bdd1SGireesh Nagabhushana * command or FW executes it but signals an error. In the latter case
33856b2bdd1SGireesh Nagabhushana * the return value is the error code indicated by FW (negated).
33956b2bdd1SGireesh Nagabhushana */
t4_wr_mbox_meat_timeout(struct adapter * adap,int mbox,const void * cmd,int size,void * rpl,bool sleep_ok,int timeout)3403dde7c95SVishal Kulkarni int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
3413dde7c95SVishal Kulkarni int size, void *rpl, bool sleep_ok, int timeout)
34256b2bdd1SGireesh Nagabhushana {
3436feac2e3SRahul Lakkireddy #ifdef T4_OS_LOG_MBOX_CMDS
3443dde7c95SVishal Kulkarni u16 access = 0;
3456feac2e3SRahul Lakkireddy #endif /* T4_OS_LOG_MBOX_CMDS */
34656b2bdd1SGireesh Nagabhushana u32 v;
34756b2bdd1SGireesh Nagabhushana u64 res;
3483dde7c95SVishal Kulkarni int i, ret;
34956b2bdd1SGireesh Nagabhushana const __be64 *p = cmd;
35056b2bdd1SGireesh Nagabhushana u32 data_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_DATA);
35156b2bdd1SGireesh Nagabhushana u32 ctl_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_CTRL);
3523dde7c95SVishal Kulkarni u32 ctl;
3533dde7c95SVishal Kulkarni __be64 cmd_rpl[MBOX_LEN/8];
3546feac2e3SRahul Lakkireddy struct t4_mbox_list entry;
3553dde7c95SVishal Kulkarni u32 pcie_fw;
35656b2bdd1SGireesh Nagabhushana
35756b2bdd1SGireesh Nagabhushana if ((size & 15) || size > MBOX_LEN)
3583dde7c95SVishal Kulkarni return -EINVAL;
35956b2bdd1SGireesh Nagabhushana
3603dde7c95SVishal Kulkarni /*
3613dde7c95SVishal Kulkarni * If we have a negative timeout, that implies that we can't sleep.
3623dde7c95SVishal Kulkarni */
3633dde7c95SVishal Kulkarni if (timeout < 0) {
3643dde7c95SVishal Kulkarni sleep_ok = false;
3653dde7c95SVishal Kulkarni timeout = -timeout;
3663dde7c95SVishal Kulkarni }
36756b2bdd1SGireesh Nagabhushana
3683dde7c95SVishal Kulkarni /*
3693dde7c95SVishal Kulkarni * Queue ourselves onto the mailbox access list. When our entry is at
3703dde7c95SVishal Kulkarni * the front of the list, we have rights to access the mailbox. So we
3713dde7c95SVishal Kulkarni * wait [for a while] till we're at the front [or bail out with an
3723dde7c95SVishal Kulkarni * EBUSY] ...
3733dde7c95SVishal Kulkarni */
3746feac2e3SRahul Lakkireddy t4_mbox_list_add(adap, &entry);
37556b2bdd1SGireesh Nagabhushana
3763dde7c95SVishal Kulkarni for (i = 0; ; i++) {
3773dde7c95SVishal Kulkarni /*
3783dde7c95SVishal Kulkarni * If we've waited too long, return a busy indication. This
3793dde7c95SVishal Kulkarni * really ought to be based on our initial position in the
3803dde7c95SVishal Kulkarni * mailbox access list but this is a start. We very rarely
3813dde7c95SVishal Kulkarni * contend on access to the mailbox ... Also check for a
3823dde7c95SVishal Kulkarni * firmware error which we'll report as a device error.
3833dde7c95SVishal Kulkarni */
3843dde7c95SVishal Kulkarni pcie_fw = t4_read_reg(adap, A_PCIE_FW);
3853dde7c95SVishal Kulkarni if (i > 4*timeout || (pcie_fw & F_PCIE_FW_ERR)) {
3866feac2e3SRahul Lakkireddy t4_mbox_list_del(adap, &entry);
3873dde7c95SVishal Kulkarni t4_report_fw_error(adap);
3883dde7c95SVishal Kulkarni ret = (pcie_fw & F_PCIE_FW_ERR) ? -ENXIO : -EBUSY;
3893dde7c95SVishal Kulkarni T4_RECORD_MBOX(adap, cmd, size, ret, 0);
3903dde7c95SVishal Kulkarni return ret;
3913dde7c95SVishal Kulkarni }
3923dde7c95SVishal Kulkarni
3933dde7c95SVishal Kulkarni /*
3943dde7c95SVishal Kulkarni * If we're at the head, break out and start the mailbox
3953dde7c95SVishal Kulkarni * protocol.
3963dde7c95SVishal Kulkarni */
3976feac2e3SRahul Lakkireddy if (t4_mbox_list_first_entry(adap) == &entry)
3983dde7c95SVishal Kulkarni break;
3993dde7c95SVishal Kulkarni
4003dde7c95SVishal Kulkarni /*
4013dde7c95SVishal Kulkarni * Delay for a bit before checking again ...
4023dde7c95SVishal Kulkarni */
4033dde7c95SVishal Kulkarni if (sleep_ok) {
4043dde7c95SVishal Kulkarni usleep_range(MIN_MBOX_CMD_DELAY, MBOX_CMD_DELAY);
4053dde7c95SVishal Kulkarni } else {
4063dde7c95SVishal Kulkarni T4_OS_TOUCH_NMI_WATCHDOG();
4073dde7c95SVishal Kulkarni udelay(MBOX_CMD_DELAY);
4083dde7c95SVishal Kulkarni }
4093dde7c95SVishal Kulkarni }
4106feac2e3SRahul Lakkireddy #ifdef T4_OS_LOG_MBOX_CMDS
4113dde7c95SVishal Kulkarni access = i;
4126feac2e3SRahul Lakkireddy #endif /* T4_OS_LOG_MBOX_CMDS */
4133dde7c95SVishal Kulkarni
4143dde7c95SVishal Kulkarni /*
4153dde7c95SVishal Kulkarni * Attempt to gain access to the mailbox.
4163dde7c95SVishal Kulkarni */
4173dde7c95SVishal Kulkarni for (i = 0; i < 4; i++) {
4183dde7c95SVishal Kulkarni ctl = t4_read_reg(adap, ctl_reg);
4193dde7c95SVishal Kulkarni v = G_MBOWNER(ctl);
4203dde7c95SVishal Kulkarni if (v != X_MBOWNER_NONE)
4213dde7c95SVishal Kulkarni break;
4223dde7c95SVishal Kulkarni }
4233dde7c95SVishal Kulkarni
4243dde7c95SVishal Kulkarni /*
4253dde7c95SVishal Kulkarni * If we were unable to gain access, dequeue ourselves from the
4263dde7c95SVishal Kulkarni * mailbox atomic access list and report the error to our caller.
4273dde7c95SVishal Kulkarni */
4283dde7c95SVishal Kulkarni if (v != X_MBOWNER_PL) {
4296feac2e3SRahul Lakkireddy t4_mbox_list_del(adap, &entry);
4303dde7c95SVishal Kulkarni t4_report_fw_error(adap);
4313dde7c95SVishal Kulkarni ret = (v == X_MBOWNER_FW) ? -EBUSY : -ETIMEDOUT;
4323dde7c95SVishal Kulkarni T4_RECORD_MBOX(adap, cmd, size, access, ret);
4333dde7c95SVishal Kulkarni return ret;
4343dde7c95SVishal Kulkarni }
4353dde7c95SVishal Kulkarni
4363dde7c95SVishal Kulkarni /*
4373dde7c95SVishal Kulkarni * If we gain ownership of the mailbox and there's a "valid" message
4383dde7c95SVishal Kulkarni * in it, this is likely an asynchronous error message from the
4393dde7c95SVishal Kulkarni * firmware. So we'll report that and then proceed on with attempting
4403dde7c95SVishal Kulkarni * to issue our own command ... which may well fail if the error
4413dde7c95SVishal Kulkarni * presaged the firmware crashing ...
4423dde7c95SVishal Kulkarni */
4433dde7c95SVishal Kulkarni if (ctl & F_MBMSGVALID) {
4443dde7c95SVishal Kulkarni CH_ERR(adap, "found VALID command in mbox %u: "
4453dde7c95SVishal Kulkarni "%llx %llx %llx %llx %llx %llx %llx %llx\n", mbox,
4463dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg),
4473dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 8),
4483dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 16),
4493dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 24),
4503dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 32),
4513dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 40),
4523dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 48),
4533dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 56));
4543dde7c95SVishal Kulkarni }
4553dde7c95SVishal Kulkarni
4563dde7c95SVishal Kulkarni /*
4573dde7c95SVishal Kulkarni * Copy in the new mailbox command and send it on its way ...
4583dde7c95SVishal Kulkarni */
4593dde7c95SVishal Kulkarni T4_RECORD_MBOX(adap, cmd, size, access, 0);
46056b2bdd1SGireesh Nagabhushana for (i = 0; i < size; i += 8, p++)
46156b2bdd1SGireesh Nagabhushana t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p));
46256b2bdd1SGireesh Nagabhushana
4633dde7c95SVishal Kulkarni /*
4643dde7c95SVishal Kulkarni * XXX It's not clear that we need this anymore now
4653dde7c95SVishal Kulkarni * XXX that we have mailbox logging ...
4663dde7c95SVishal Kulkarni */
4673dde7c95SVishal Kulkarni CH_DUMP_MBOX(adap, mbox, data_reg, size / 8);
4683dde7c95SVishal Kulkarni
46956b2bdd1SGireesh Nagabhushana t4_write_reg(adap, ctl_reg, F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW));
47056b2bdd1SGireesh Nagabhushana (void) t4_read_reg(adap, ctl_reg); /* flush write */
47156b2bdd1SGireesh Nagabhushana
4723dde7c95SVishal Kulkarni /*
4733dde7c95SVishal Kulkarni * Loop waiting for the reply; bail out if we time out or the firmware
4743dde7c95SVishal Kulkarni * reports an error.
4753dde7c95SVishal Kulkarni */
4763dde7c95SVishal Kulkarni for (i = 0;
4773dde7c95SVishal Kulkarni !((pcie_fw = t4_read_reg(adap, A_PCIE_FW)) & F_PCIE_FW_ERR) &&
4783dde7c95SVishal Kulkarni i < timeout;
4793dde7c95SVishal Kulkarni i++) {
4803dde7c95SVishal Kulkarni if (sleep_ok) {
4813dde7c95SVishal Kulkarni usleep_range(MIN_MBOX_CMD_DELAY, MBOX_CMD_DELAY);
4823dde7c95SVishal Kulkarni } else {
4833dde7c95SVishal Kulkarni T4_OS_TOUCH_NMI_WATCHDOG();
4843dde7c95SVishal Kulkarni udelay(MBOX_CMD_DELAY);
4853dde7c95SVishal Kulkarni }
48656b2bdd1SGireesh Nagabhushana
48756b2bdd1SGireesh Nagabhushana v = t4_read_reg(adap, ctl_reg);
48856b2bdd1SGireesh Nagabhushana if (v == X_CIM_PF_NOACCESS)
48956b2bdd1SGireesh Nagabhushana continue;
49056b2bdd1SGireesh Nagabhushana if (G_MBOWNER(v) == X_MBOWNER_PL) {
49156b2bdd1SGireesh Nagabhushana if (!(v & F_MBMSGVALID)) {
49256b2bdd1SGireesh Nagabhushana t4_write_reg(adap, ctl_reg,
49356b2bdd1SGireesh Nagabhushana V_MBOWNER(X_MBOWNER_NONE));
49456b2bdd1SGireesh Nagabhushana continue;
49556b2bdd1SGireesh Nagabhushana }
49656b2bdd1SGireesh Nagabhushana
4973dde7c95SVishal Kulkarni /*
4983dde7c95SVishal Kulkarni * Retrieve the command reply and release the mailbox.
4993dde7c95SVishal Kulkarni */
5003dde7c95SVishal Kulkarni get_mbox_rpl(adap, cmd_rpl, size/8, data_reg);
50156b2bdd1SGireesh Nagabhushana t4_write_reg(adap, ctl_reg, V_MBOWNER(X_MBOWNER_NONE));
5026feac2e3SRahul Lakkireddy t4_mbox_list_del(adap, &entry);
5033dde7c95SVishal Kulkarni
504baa1db26SToomas Soome T4_RECORD_MBOX(adap, cmd_rpl, size, access, i + 1);
5053dde7c95SVishal Kulkarni
5063dde7c95SVishal Kulkarni /*
5073dde7c95SVishal Kulkarni * XXX It's not clear that we need this anymore now
5083dde7c95SVishal Kulkarni * XXX that we have mailbox logging ...
5093dde7c95SVishal Kulkarni */
5103dde7c95SVishal Kulkarni CH_DUMP_MBOX(adap, mbox, data_reg, size / 8);
5113dde7c95SVishal Kulkarni CH_MSG(adap, INFO, HW,
5123dde7c95SVishal Kulkarni "command completed in %d ms (%ssleeping)\n",
513baa1db26SToomas Soome i + 1, sleep_ok ? "" : "non-");
5143dde7c95SVishal Kulkarni
5153dde7c95SVishal Kulkarni res = be64_to_cpu(cmd_rpl[0]);
5163dde7c95SVishal Kulkarni if (G_FW_CMD_OP(res >> 32) == FW_DEBUG_CMD) {
5173dde7c95SVishal Kulkarni fw_asrt(adap, (struct fw_debug_cmd *)cmd_rpl);
5183dde7c95SVishal Kulkarni res = V_FW_CMD_RETVAL(EIO);
5193dde7c95SVishal Kulkarni } else if (rpl)
5203dde7c95SVishal Kulkarni memcpy(rpl, cmd_rpl, size);
5213dde7c95SVishal Kulkarni return -G_FW_CMD_RETVAL((int)res);
52256b2bdd1SGireesh Nagabhushana }
52356b2bdd1SGireesh Nagabhushana }
52456b2bdd1SGireesh Nagabhushana
525de483253SVishal Kulkarni /*
526de483253SVishal Kulkarni * We timed out waiting for a reply to our mailbox command. Report
527de483253SVishal Kulkarni * the error and also check to see if the firmware reported any
528de483253SVishal Kulkarni * errors ...
529de483253SVishal Kulkarni */
5306feac2e3SRahul Lakkireddy t4_mbox_list_del(adap, &entry);
5313dde7c95SVishal Kulkarni
5323dde7c95SVishal Kulkarni ret = (pcie_fw & F_PCIE_FW_ERR) ? -ENXIO : -ETIMEDOUT;
5333dde7c95SVishal Kulkarni T4_RECORD_MBOX(adap, cmd, size, access, ret);
5346feac2e3SRahul Lakkireddy CH_ERR(adap, "command 0x%x in mailbox %d timed out\n",
53556b2bdd1SGireesh Nagabhushana *(const u8 *)cmd, mbox);
5363dde7c95SVishal Kulkarni
537de483253SVishal Kulkarni t4_report_fw_error(adap);
5383dde7c95SVishal Kulkarni t4_fatal_err(adap);
5393dde7c95SVishal Kulkarni return ret;
5403dde7c95SVishal Kulkarni }
5413dde7c95SVishal Kulkarni
5423dde7c95SVishal Kulkarni #ifdef CONFIG_CUDBG
5433dde7c95SVishal Kulkarni /*
5443dde7c95SVishal Kulkarni * The maximum number of times to iterate for FW reply before
5453dde7c95SVishal Kulkarni * issuing a mailbox timeout
5463dde7c95SVishal Kulkarni */
5473dde7c95SVishal Kulkarni #define FW_REPLY_WAIT_LOOP 6000000
5483dde7c95SVishal Kulkarni
5493dde7c95SVishal Kulkarni /**
5503dde7c95SVishal Kulkarni * t4_wr_mbox_meat_timeout_panic - send a command to FW through the given
5513dde7c95SVishal Kulkarni * mailbox. This function is a minimal version of t4_wr_mbox_meat_timeout()
5523dde7c95SVishal Kulkarni * and is only invoked during a kernel crash. Since this function is
5533dde7c95SVishal Kulkarni * called through a atomic notifier chain ,we cannot sleep awaiting a
5543dde7c95SVishal Kulkarni * response from FW, hence repeatedly loop until we get a reply.
5553dde7c95SVishal Kulkarni *
5563dde7c95SVishal Kulkarni * @adap: the adapter
5573dde7c95SVishal Kulkarni * @mbox: index of the mailbox to use
5583dde7c95SVishal Kulkarni * @cmd: the command to write
5593dde7c95SVishal Kulkarni * @size: command length in bytes
5603dde7c95SVishal Kulkarni * @rpl: where to optionally store the reply
5613dde7c95SVishal Kulkarni */
5623dde7c95SVishal Kulkarni
t4_wr_mbox_meat_timeout_panic(struct adapter * adap,int mbox,const void * cmd,int size,void * rpl)5633dde7c95SVishal Kulkarni static int t4_wr_mbox_meat_timeout_panic(struct adapter *adap, int mbox,
5643dde7c95SVishal Kulkarni const void *cmd, int size, void *rpl)
5653dde7c95SVishal Kulkarni {
5663dde7c95SVishal Kulkarni u32 v;
5673dde7c95SVishal Kulkarni u64 res;
5683dde7c95SVishal Kulkarni int i, ret;
5693dde7c95SVishal Kulkarni u64 cnt;
5703dde7c95SVishal Kulkarni const __be64 *p = cmd;
5713dde7c95SVishal Kulkarni u32 data_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_DATA);
5723dde7c95SVishal Kulkarni u32 ctl_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_CTRL);
5733dde7c95SVishal Kulkarni u32 ctl;
5743dde7c95SVishal Kulkarni __be64 cmd_rpl[MBOX_LEN/8];
5753dde7c95SVishal Kulkarni u32 pcie_fw;
5763dde7c95SVishal Kulkarni
5773dde7c95SVishal Kulkarni if ((size & 15) || size > MBOX_LEN)
5783dde7c95SVishal Kulkarni return -EINVAL;
5793dde7c95SVishal Kulkarni
5803dde7c95SVishal Kulkarni /*
5813dde7c95SVishal Kulkarni * Check for a firmware error which we'll report as a
5823dde7c95SVishal Kulkarni * device error.
5833dde7c95SVishal Kulkarni */
5843dde7c95SVishal Kulkarni pcie_fw = t4_read_reg(adap, A_PCIE_FW);
5853dde7c95SVishal Kulkarni if (pcie_fw & F_PCIE_FW_ERR) {
5863dde7c95SVishal Kulkarni t4_report_fw_error(adap);
5873dde7c95SVishal Kulkarni ret = (pcie_fw & F_PCIE_FW_ERR) ? -ENXIO : -EBUSY;
5883dde7c95SVishal Kulkarni return ret;
58956b2bdd1SGireesh Nagabhushana }
59056b2bdd1SGireesh Nagabhushana
59156b2bdd1SGireesh Nagabhushana /*
5923dde7c95SVishal Kulkarni * Attempt to gain access to the mailbox.
59356b2bdd1SGireesh Nagabhushana */
5943dde7c95SVishal Kulkarni for (i = 0; i < 4; i++) {
5953dde7c95SVishal Kulkarni ctl = t4_read_reg(adap, ctl_reg);
5963dde7c95SVishal Kulkarni v = G_MBOWNER(ctl);
5973dde7c95SVishal Kulkarni if (v != X_MBOWNER_NONE)
5983dde7c95SVishal Kulkarni break;
5993dde7c95SVishal Kulkarni }
60056b2bdd1SGireesh Nagabhushana
6013dde7c95SVishal Kulkarni /*
6023dde7c95SVishal Kulkarni * If we were unable to gain access, report the error to our caller.
6033dde7c95SVishal Kulkarni */
6043dde7c95SVishal Kulkarni if (v != X_MBOWNER_PL) {
6053dde7c95SVishal Kulkarni t4_report_fw_error(adap);
6063dde7c95SVishal Kulkarni ret = (v == X_MBOWNER_FW) ? -EBUSY : -ETIMEDOUT;
6073dde7c95SVishal Kulkarni return ret;
6083dde7c95SVishal Kulkarni }
6093dde7c95SVishal Kulkarni
6103dde7c95SVishal Kulkarni /*
6113dde7c95SVishal Kulkarni * If we gain ownership of the mailbox and there's a "valid" message
6123dde7c95SVishal Kulkarni * in it, this is likely an asynchronous error message from the
6133dde7c95SVishal Kulkarni * firmware. So we'll report that and then proceed on with attempting
6143dde7c95SVishal Kulkarni * to issue our own command ... which may well fail if the error
6153dde7c95SVishal Kulkarni * presaged the firmware crashing ...
6163dde7c95SVishal Kulkarni */
6173dde7c95SVishal Kulkarni if (ctl & F_MBMSGVALID) {
6183dde7c95SVishal Kulkarni CH_ERR(adap, "found VALID command in mbox %u: "
6193dde7c95SVishal Kulkarni "%llx %llx %llx %llx %llx %llx %llx %llx\n", mbox,
6203dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg),
6213dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 8),
6223dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 16),
6233dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 24),
6243dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 32),
6253dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 40),
6263dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 48),
6273dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, data_reg + 56));
6283dde7c95SVishal Kulkarni }
6293dde7c95SVishal Kulkarni
6303dde7c95SVishal Kulkarni /*
6313dde7c95SVishal Kulkarni * Copy in the new mailbox command and send it on its way ...
6323dde7c95SVishal Kulkarni */
6333dde7c95SVishal Kulkarni for (i = 0; i < size; i += 8, p++)
6343dde7c95SVishal Kulkarni t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p));
6353dde7c95SVishal Kulkarni
6363dde7c95SVishal Kulkarni CH_DUMP_MBOX(adap, mbox, data_reg, size / 8);
6373dde7c95SVishal Kulkarni
6383dde7c95SVishal Kulkarni t4_write_reg(adap, ctl_reg, F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW));
6393dde7c95SVishal Kulkarni t4_read_reg(adap, ctl_reg); /* flush write */
6403dde7c95SVishal Kulkarni
6413dde7c95SVishal Kulkarni /*
6423dde7c95SVishal Kulkarni * Loop waiting for the reply; bail out if we time out or the firmware
6433dde7c95SVishal Kulkarni * reports an error.
6443dde7c95SVishal Kulkarni */
6453dde7c95SVishal Kulkarni for (cnt = 0;
6463dde7c95SVishal Kulkarni !((pcie_fw = t4_read_reg(adap, A_PCIE_FW)) & F_PCIE_FW_ERR) &&
6473dde7c95SVishal Kulkarni cnt < FW_REPLY_WAIT_LOOP;
6483dde7c95SVishal Kulkarni cnt++) {
6493dde7c95SVishal Kulkarni v = t4_read_reg(adap, ctl_reg);
6503dde7c95SVishal Kulkarni if (v == X_CIM_PF_NOACCESS)
6513dde7c95SVishal Kulkarni continue;
6523dde7c95SVishal Kulkarni if (G_MBOWNER(v) == X_MBOWNER_PL) {
6533dde7c95SVishal Kulkarni if (!(v & F_MBMSGVALID)) {
6543dde7c95SVishal Kulkarni t4_write_reg(adap, ctl_reg,
6553dde7c95SVishal Kulkarni V_MBOWNER(X_MBOWNER_NONE));
6563dde7c95SVishal Kulkarni continue;
6573dde7c95SVishal Kulkarni }
6583dde7c95SVishal Kulkarni
6593dde7c95SVishal Kulkarni /*
6603dde7c95SVishal Kulkarni * Retrieve the command reply and release the mailbox.
6613dde7c95SVishal Kulkarni */
6623dde7c95SVishal Kulkarni get_mbox_rpl(adap, cmd_rpl, size/8, data_reg);
6633dde7c95SVishal Kulkarni t4_write_reg(adap, ctl_reg, V_MBOWNER(X_MBOWNER_NONE));
6643dde7c95SVishal Kulkarni
6653dde7c95SVishal Kulkarni CH_DUMP_MBOX(adap, mbox, data_reg, size / 8);
6663dde7c95SVishal Kulkarni
6673dde7c95SVishal Kulkarni res = be64_to_cpu(cmd_rpl[0]);
6683dde7c95SVishal Kulkarni if (G_FW_CMD_OP(res >> 32) == FW_DEBUG_CMD) {
6693dde7c95SVishal Kulkarni fw_asrt(adap, (struct fw_debug_cmd *)cmd_rpl);
6703dde7c95SVishal Kulkarni res = V_FW_CMD_RETVAL(EIO);
6713dde7c95SVishal Kulkarni } else if (rpl)
6723dde7c95SVishal Kulkarni memcpy(rpl, cmd_rpl, size);
6733dde7c95SVishal Kulkarni return -G_FW_CMD_RETVAL((int)res);
6743dde7c95SVishal Kulkarni }
6753dde7c95SVishal Kulkarni }
6763dde7c95SVishal Kulkarni
6773dde7c95SVishal Kulkarni /*
6783dde7c95SVishal Kulkarni * We timed out waiting for a reply to our mailbox command. Report
6793dde7c95SVishal Kulkarni * the error and also check to see if the firmware reported any
6803dde7c95SVishal Kulkarni * errors ...
6813dde7c95SVishal Kulkarni */
6823dde7c95SVishal Kulkarni ret = (pcie_fw & F_PCIE_FW_ERR) ? -ENXIO : -ETIMEDOUT;
6833dde7c95SVishal Kulkarni CH_ERR(adap, "command %#x in mailbox %d timed out\n",
6843dde7c95SVishal Kulkarni *(const u8 *)cmd, mbox);
6853dde7c95SVishal Kulkarni
6863dde7c95SVishal Kulkarni t4_report_fw_error(adap);
6873dde7c95SVishal Kulkarni t4_fatal_err(adap);
6883dde7c95SVishal Kulkarni return ret;
6893dde7c95SVishal Kulkarni }
6903dde7c95SVishal Kulkarni #endif
6913dde7c95SVishal Kulkarni
t4_wr_mbox_meat(struct adapter * adap,int mbox,const void * cmd,int size,void * rpl,bool sleep_ok)6923dde7c95SVishal Kulkarni int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
6933dde7c95SVishal Kulkarni void *rpl, bool sleep_ok)
6943dde7c95SVishal Kulkarni {
6953dde7c95SVishal Kulkarni #ifdef CONFIG_CUDBG
6963dde7c95SVishal Kulkarni if (adap->flags & K_CRASH)
6973dde7c95SVishal Kulkarni return t4_wr_mbox_meat_timeout_panic(adap, mbox, cmd, size,
6983dde7c95SVishal Kulkarni rpl);
6993dde7c95SVishal Kulkarni else
7003dde7c95SVishal Kulkarni #endif
7013dde7c95SVishal Kulkarni return t4_wr_mbox_meat_timeout(adap, mbox, cmd, size, rpl,
7023dde7c95SVishal Kulkarni sleep_ok, FW_CMD_MAX_TIMEOUT);
7033dde7c95SVishal Kulkarni
7043dde7c95SVishal Kulkarni }
7053dde7c95SVishal Kulkarni
t4_edc_err_read(struct adapter * adap,int idx)7063dde7c95SVishal Kulkarni static int t4_edc_err_read(struct adapter *adap, int idx)
7073dde7c95SVishal Kulkarni {
7083dde7c95SVishal Kulkarni u32 edc_ecc_err_addr_reg;
7093dde7c95SVishal Kulkarni u32 edc_bist_status_rdata_reg;
710de483253SVishal Kulkarni
711de483253SVishal Kulkarni if (is_t4(adap->params.chip)) {
7123dde7c95SVishal Kulkarni CH_WARN(adap, "%s: T4 NOT supported.\n", __func__);
7133dde7c95SVishal Kulkarni return 0;
7143dde7c95SVishal Kulkarni }
7153dde7c95SVishal Kulkarni if (idx != MEM_EDC0 && idx != MEM_EDC1) {
7163dde7c95SVishal Kulkarni CH_WARN(adap, "%s: idx %d NOT supported.\n", __func__, idx);
7173dde7c95SVishal Kulkarni return 0;
718de483253SVishal Kulkarni }
719de483253SVishal Kulkarni
7203dde7c95SVishal Kulkarni edc_ecc_err_addr_reg = EDC_T5_REG(A_EDC_H_ECC_ERR_ADDR, idx);
7213dde7c95SVishal Kulkarni edc_bist_status_rdata_reg = EDC_T5_REG(A_EDC_H_BIST_STATUS_RDATA, idx);
72256b2bdd1SGireesh Nagabhushana
7233dde7c95SVishal Kulkarni CH_WARN(adap,
7243dde7c95SVishal Kulkarni "edc%d err addr 0x%x: 0x%x.\n",
7253dde7c95SVishal Kulkarni idx, edc_ecc_err_addr_reg,
7263dde7c95SVishal Kulkarni t4_read_reg(adap, edc_ecc_err_addr_reg));
7273dde7c95SVishal Kulkarni CH_WARN(adap,
7283dde7c95SVishal Kulkarni "bist: 0x%x, status %llx %llx %llx %llx %llx %llx %llx %llx %llx.\n",
7293dde7c95SVishal Kulkarni edc_bist_status_rdata_reg,
7303dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg),
7313dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 8),
7323dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 16),
7333dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 24),
7343dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 32),
7353dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 40),
7363dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 48),
7373dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 56),
7383dde7c95SVishal Kulkarni (unsigned long long)t4_read_reg64(adap, edc_bist_status_rdata_reg + 64));
7393dde7c95SVishal Kulkarni
7403dde7c95SVishal Kulkarni return 0;
74156b2bdd1SGireesh Nagabhushana }
74256b2bdd1SGireesh Nagabhushana
7433dde7c95SVishal Kulkarni /**
7443dde7c95SVishal Kulkarni * t4_memory_rw_addr - read/write adapter memory via PCIE memory window
74556b2bdd1SGireesh Nagabhushana * @adap: the adapter
7463dde7c95SVishal Kulkarni * @win: PCI-E Memory Window to use
7473dde7c95SVishal Kulkarni * @addr: address within adapter memory
7483dde7c95SVishal Kulkarni * @len: amount of memory to transfer
7493dde7c95SVishal Kulkarni * @hbuf: host memory buffer
7503dde7c95SVishal Kulkarni * @dir: direction of transfer T4_MEMORY_READ (1) or T4_MEMORY_WRITE (0)
75156b2bdd1SGireesh Nagabhushana *
7523dde7c95SVishal Kulkarni * Reads/writes an [almost] arbitrary memory region in the firmware: the
7533dde7c95SVishal Kulkarni * firmware memory address and host buffer must be aligned on 32-bit
7543dde7c95SVishal Kulkarni * boudaries; the length may be arbitrary.
75556b2bdd1SGireesh Nagabhushana *
7563dde7c95SVishal Kulkarni * NOTES:
7573dde7c95SVishal Kulkarni * 1. The memory is transferred as a raw byte sequence from/to the
7583dde7c95SVishal Kulkarni * firmware's memory. If this memory contains data structures which
7593dde7c95SVishal Kulkarni * contain multi-byte integers, it's the caller's responsibility to
76056b2bdd1SGireesh Nagabhushana * perform appropriate byte order conversions.
7613dde7c95SVishal Kulkarni *
7623dde7c95SVishal Kulkarni * 2. It is the Caller's responsibility to ensure that no other code
7633dde7c95SVishal Kulkarni * uses the specified PCI-E Memory Window while this routine is
7643dde7c95SVishal Kulkarni * using it. This is typically done via the use of OS-specific
7653dde7c95SVishal Kulkarni * locks, etc.
76656b2bdd1SGireesh Nagabhushana */
t4_memory_rw_addr(struct adapter * adap,int win,u32 addr,u32 len,void * hbuf,int dir)7673dde7c95SVishal Kulkarni int t4_memory_rw_addr(struct adapter *adap, int win, u32 addr,
7683dde7c95SVishal Kulkarni u32 len, void *hbuf, int dir)
76956b2bdd1SGireesh Nagabhushana {
7703dde7c95SVishal Kulkarni u32 pos, offset, resid;
7713dde7c95SVishal Kulkarni u32 win_pf, mem_reg, mem_aperture, mem_base;
7723dde7c95SVishal Kulkarni u32 *buf;
7733dde7c95SVishal Kulkarni
7743dde7c95SVishal Kulkarni /* Argument sanity checks ...
7753dde7c95SVishal Kulkarni */
7763dde7c95SVishal Kulkarni if (addr & 0x3 || (uintptr_t)hbuf & 0x3)
7773dde7c95SVishal Kulkarni return -EINVAL;
7783dde7c95SVishal Kulkarni buf = (u32 *)hbuf;
7793dde7c95SVishal Kulkarni
7803dde7c95SVishal Kulkarni /* It's convenient to be able to handle lengths which aren't a
7813dde7c95SVishal Kulkarni * multiple of 32-bits because we often end up transferring files to
7823dde7c95SVishal Kulkarni * the firmware. So we'll handle that by normalizing the length here
7833dde7c95SVishal Kulkarni * and then handling any residual transfer at the end.
7843dde7c95SVishal Kulkarni */
7853dde7c95SVishal Kulkarni resid = len & 0x3;
7863dde7c95SVishal Kulkarni len -= resid;
7873dde7c95SVishal Kulkarni
7883dde7c95SVishal Kulkarni /* Each PCI-E Memory Window is programmed with a window size -- or
7893dde7c95SVishal Kulkarni * "aperture" -- which controls the granularity of its mapping onto
7903dde7c95SVishal Kulkarni * adapter memory. We need to grab that aperture in order to know
7913dde7c95SVishal Kulkarni * how to use the specified window. The window is also programmed
7923dde7c95SVishal Kulkarni * with the base address of the Memory Window in BAR0's address
7933dde7c95SVishal Kulkarni * space. For T4 this is an absolute PCI-E Bus Address. For T5
7943dde7c95SVishal Kulkarni * the address is relative to BAR0.
7953dde7c95SVishal Kulkarni */
7963dde7c95SVishal Kulkarni mem_reg = t4_read_reg(adap,
7973dde7c95SVishal Kulkarni PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN,
7983dde7c95SVishal Kulkarni win));
7993dde7c95SVishal Kulkarni
8003dde7c95SVishal Kulkarni /* a dead adapter will return 0xffffffff for PIO reads */
8013dde7c95SVishal Kulkarni if (mem_reg == 0xffffffff) {
8023dde7c95SVishal Kulkarni CH_WARN(adap, "Unable to read PCI-E Memory Window Base[%d]\n",
8033dde7c95SVishal Kulkarni win);
8043dde7c95SVishal Kulkarni return -ENXIO;
8053dde7c95SVishal Kulkarni }
8063dde7c95SVishal Kulkarni
8073dde7c95SVishal Kulkarni mem_aperture = 1 << (G_WINDOW(mem_reg) + X_WINDOW_SHIFT);
8083dde7c95SVishal Kulkarni mem_base = G_PCIEOFST(mem_reg) << X_PCIEOFST_SHIFT;
8093dde7c95SVishal Kulkarni if (is_t4(adap->params.chip))
8103dde7c95SVishal Kulkarni mem_base -= adap->t4_bar0;
8113dde7c95SVishal Kulkarni win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->pf);
8123dde7c95SVishal Kulkarni
8133dde7c95SVishal Kulkarni /* Calculate our initial PCI-E Memory Window Position and Offset into
8143dde7c95SVishal Kulkarni * that Window.
8153dde7c95SVishal Kulkarni */
8163dde7c95SVishal Kulkarni pos = addr & ~(mem_aperture-1);
8173dde7c95SVishal Kulkarni offset = addr - pos;
8183dde7c95SVishal Kulkarni
8193dde7c95SVishal Kulkarni /* Set up initial PCI-E Memory Window to cover the start of our
8203dde7c95SVishal Kulkarni * transfer. (Read it back to ensure that changes propagate before we
8213dde7c95SVishal Kulkarni * attempt to use the new value.)
8223dde7c95SVishal Kulkarni */
8233dde7c95SVishal Kulkarni t4_write_reg(adap,
8243dde7c95SVishal Kulkarni PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, win),
8253dde7c95SVishal Kulkarni pos | win_pf);
8263dde7c95SVishal Kulkarni t4_read_reg(adap,
8273dde7c95SVishal Kulkarni PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, win));
8283dde7c95SVishal Kulkarni
8293dde7c95SVishal Kulkarni /* Transfer data to/from the adapter as long as there's an integral
8303dde7c95SVishal Kulkarni * number of 32-bit transfers to complete.
8313dde7c95SVishal Kulkarni *
8323dde7c95SVishal Kulkarni * A note on Endianness issues:
8333dde7c95SVishal Kulkarni *
8343dde7c95SVishal Kulkarni * The "register" reads and writes below from/to the PCI-E Memory
8353dde7c95SVishal Kulkarni * Window invoke the standard adapter Big-Endian to PCI-E Link
8363dde7c95SVishal Kulkarni * Little-Endian "swizzel." As a result, if we have the following
8373dde7c95SVishal Kulkarni * data in adapter memory:
8383dde7c95SVishal Kulkarni *
8393dde7c95SVishal Kulkarni * Memory: ... | b0 | b1 | b2 | b3 | ...
8403dde7c95SVishal Kulkarni * Address: i+0 i+1 i+2 i+3
8413dde7c95SVishal Kulkarni *
8423dde7c95SVishal Kulkarni * Then a read of the adapter memory via the PCI-E Memory Window
8433dde7c95SVishal Kulkarni * will yield:
8443dde7c95SVishal Kulkarni *
8453dde7c95SVishal Kulkarni * x = readl(i)
8463dde7c95SVishal Kulkarni * 31 0
8473dde7c95SVishal Kulkarni * [ b3 | b2 | b1 | b0 ]
8483dde7c95SVishal Kulkarni *
8493dde7c95SVishal Kulkarni * If this value is stored into local memory on a Little-Endian system
8503dde7c95SVishal Kulkarni * it will show up correctly in local memory as:
8513dde7c95SVishal Kulkarni *
8523dde7c95SVishal Kulkarni * ( ..., b0, b1, b2, b3, ... )
8533dde7c95SVishal Kulkarni *
8543dde7c95SVishal Kulkarni * But on a Big-Endian system, the store will show up in memory
8553dde7c95SVishal Kulkarni * incorrectly swizzled as:
8563dde7c95SVishal Kulkarni *
8573dde7c95SVishal Kulkarni * ( ..., b3, b2, b1, b0, ... )
8583dde7c95SVishal Kulkarni *
8593dde7c95SVishal Kulkarni * So we need to account for this in the reads and writes to the
8603dde7c95SVishal Kulkarni * PCI-E Memory Window below by undoing the register read/write
8613dde7c95SVishal Kulkarni * swizzels.
8623dde7c95SVishal Kulkarni */
8633dde7c95SVishal Kulkarni while (len > 0) {
8643dde7c95SVishal Kulkarni if (dir == T4_MEMORY_READ)
8653dde7c95SVishal Kulkarni *buf++ = le32_to_cpu((__force __le32)t4_read_reg(adap,
8663dde7c95SVishal Kulkarni mem_base + offset));
8673dde7c95SVishal Kulkarni else
8683dde7c95SVishal Kulkarni t4_write_reg(adap, mem_base + offset,
8693dde7c95SVishal Kulkarni (__force u32)cpu_to_le32(*buf++));
8703dde7c95SVishal Kulkarni offset += sizeof(__be32);
8713dde7c95SVishal Kulkarni len -= sizeof(__be32);
8723dde7c95SVishal Kulkarni
8733dde7c95SVishal Kulkarni /* If we've reached the end of our current window aperture,
8743dde7c95SVishal Kulkarni * move the PCI-E Memory Window on to the next. Note that
8753dde7c95SVishal Kulkarni * doing this here after "len" may be 0 allows us to set up
8763dde7c95SVishal Kulkarni * the PCI-E Memory Window for a possible final residual
8773dde7c95SVishal Kulkarni * transfer below ...
8783dde7c95SVishal Kulkarni */
8793dde7c95SVishal Kulkarni if (offset == mem_aperture) {
8803dde7c95SVishal Kulkarni pos += mem_aperture;
8813dde7c95SVishal Kulkarni offset = 0;
8823dde7c95SVishal Kulkarni t4_write_reg(adap,
8833dde7c95SVishal Kulkarni PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET,
8843dde7c95SVishal Kulkarni win), pos | win_pf);
8853dde7c95SVishal Kulkarni t4_read_reg(adap,
8863dde7c95SVishal Kulkarni PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET,
8873dde7c95SVishal Kulkarni win));
8883dde7c95SVishal Kulkarni }
8893dde7c95SVishal Kulkarni }
8903dde7c95SVishal Kulkarni
8913dde7c95SVishal Kulkarni /* If the original transfer had a length which wasn't a multiple of
8923dde7c95SVishal Kulkarni * 32-bits, now's where we need to finish off the transfer of the
8933dde7c95SVishal Kulkarni * residual amount. The PCI-E Memory Window has already been moved
8943dde7c95SVishal Kulkarni * above (if necessary) to cover this final transfer.
8953dde7c95SVishal Kulkarni */
8963dde7c95SVishal Kulkarni if (resid) {
8973dde7c95SVishal Kulkarni union {
8983dde7c95SVishal Kulkarni u32 word;
8993dde7c95SVishal Kulkarni char byte[4];
9003dde7c95SVishal Kulkarni } last;
9013dde7c95SVishal Kulkarni unsigned char *bp;
9023dde7c95SVishal Kulkarni int i;
9033dde7c95SVishal Kulkarni
9043dde7c95SVishal Kulkarni if (dir == T4_MEMORY_READ) {
9053dde7c95SVishal Kulkarni last.word = le32_to_cpu(
9063dde7c95SVishal Kulkarni (__force __le32)t4_read_reg(adap,
9073dde7c95SVishal Kulkarni mem_base + offset));
9083dde7c95SVishal Kulkarni for (bp = (unsigned char *)buf, i = resid; i < 4; i++)
9093dde7c95SVishal Kulkarni bp[i] = last.byte[i];
9103dde7c95SVishal Kulkarni } else {
9113dde7c95SVishal Kulkarni last.word = *buf;
9123dde7c95SVishal Kulkarni for (i = resid; i < 4; i++)
9133dde7c95SVishal Kulkarni last.byte[i] = 0;
9143dde7c95SVishal Kulkarni t4_write_reg(adap, mem_base + offset,
9153dde7c95SVishal Kulkarni (__force u32)cpu_to_le32(last.word));
9163dde7c95SVishal Kulkarni }
9173dde7c95SVishal Kulkarni }
9183dde7c95SVishal Kulkarni
9193dde7c95SVishal Kulkarni return 0;
9203dde7c95SVishal Kulkarni }
9213dde7c95SVishal Kulkarni
9223dde7c95SVishal Kulkarni /**
9233dde7c95SVishal Kulkarni * t4_memory_rw_mtype - read/write EDC 0, EDC 1 or MC via PCIE memory window
9243dde7c95SVishal Kulkarni * @adap: the adapter
9253dde7c95SVishal Kulkarni * @win: PCI-E Memory Window to use
9267e6ad469SVishal Kulkarni * @mtype: memory type: MEM_EDC0, MEM_EDC1, MEM_HMA or MEM_MC
9273dde7c95SVishal Kulkarni * @maddr: address within indicated memory type
9283dde7c95SVishal Kulkarni * @len: amount of memory to transfer
9293dde7c95SVishal Kulkarni * @hbuf: host memory buffer
9303dde7c95SVishal Kulkarni * @dir: direction of transfer T4_MEMORY_READ (1) or T4_MEMORY_WRITE (0)
9313dde7c95SVishal Kulkarni *
9323dde7c95SVishal Kulkarni * Reads/writes adapter memory using t4_memory_rw_addr(). This routine
9333dde7c95SVishal Kulkarni * provides an (memory type, address withing memory type) interface.
9343dde7c95SVishal Kulkarni */
t4_memory_rw_mtype(struct adapter * adap,int win,int mtype,u32 maddr,u32 len,void * hbuf,int dir)9353dde7c95SVishal Kulkarni int t4_memory_rw_mtype(struct adapter *adap, int win, int mtype, u32 maddr,
9363dde7c95SVishal Kulkarni u32 len, void *hbuf, int dir)
9373dde7c95SVishal Kulkarni {
9383dde7c95SVishal Kulkarni u32 mtype_offset;
9393dde7c95SVishal Kulkarni u32 edc_size, mc_size;
9403dde7c95SVishal Kulkarni
9413dde7c95SVishal Kulkarni /* Offset into the region of memory which is being accessed
9423dde7c95SVishal Kulkarni * MEM_EDC0 = 0
9433dde7c95SVishal Kulkarni * MEM_EDC1 = 1
9443dde7c95SVishal Kulkarni * MEM_MC = 2 -- MEM_MC for chips with only 1 memory controller
9453dde7c95SVishal Kulkarni * MEM_MC1 = 3 -- for chips with 2 memory controllers (e.g. T5)
9467e6ad469SVishal Kulkarni * MEM_HMA = 4
9473dde7c95SVishal Kulkarni */
9483dde7c95SVishal Kulkarni edc_size = G_EDRAM0_SIZE(t4_read_reg(adap, A_MA_EDRAM0_BAR));
9497e6ad469SVishal Kulkarni if (mtype == MEM_HMA) {
9507e6ad469SVishal Kulkarni mtype_offset = 2 * (edc_size * 1024 * 1024);
9517e6ad469SVishal Kulkarni } else if (mtype != MEM_MC1)
9523dde7c95SVishal Kulkarni mtype_offset = (mtype * (edc_size * 1024 * 1024));
9533dde7c95SVishal Kulkarni else {
9543dde7c95SVishal Kulkarni mc_size = G_EXT_MEM0_SIZE(t4_read_reg(adap,
9553dde7c95SVishal Kulkarni A_MA_EXT_MEMORY0_BAR));
9563dde7c95SVishal Kulkarni mtype_offset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
9573dde7c95SVishal Kulkarni }
9583dde7c95SVishal Kulkarni
9593dde7c95SVishal Kulkarni return t4_memory_rw_addr(adap, win,
9603dde7c95SVishal Kulkarni mtype_offset + maddr, len,
9613dde7c95SVishal Kulkarni hbuf, dir);
9623dde7c95SVishal Kulkarni }
9633dde7c95SVishal Kulkarni
9643dde7c95SVishal Kulkarni /*
9653dde7c95SVishal Kulkarni * Return the specified PCI-E Configuration Space register from our Physical
9663dde7c95SVishal Kulkarni * Function. We try first via a Firmware LDST Command (if fw_attach != 0)
9673dde7c95SVishal Kulkarni * since we prefer to let the firmware own all of these registers, but if that
9683dde7c95SVishal Kulkarni * fails we go for it directly ourselves.
9693dde7c95SVishal Kulkarni */
t4_read_pcie_cfg4(struct adapter * adap,int reg,int drv_fw_attach)9703dde7c95SVishal Kulkarni u32 t4_read_pcie_cfg4(struct adapter *adap, int reg, int drv_fw_attach)
9713dde7c95SVishal Kulkarni {
9723dde7c95SVishal Kulkarni u32 val;
9733dde7c95SVishal Kulkarni
9743dde7c95SVishal Kulkarni /*
9753dde7c95SVishal Kulkarni * If fw_attach != 0, construct and send the Firmware LDST Command to
9763dde7c95SVishal Kulkarni * retrieve the specified PCI-E Configuration Space register.
9773dde7c95SVishal Kulkarni */
9783dde7c95SVishal Kulkarni if (drv_fw_attach != 0) {
9793dde7c95SVishal Kulkarni struct fw_ldst_cmd ldst_cmd;
98056b2bdd1SGireesh Nagabhushana int ret;
98156b2bdd1SGireesh Nagabhushana
9823dde7c95SVishal Kulkarni memset(&ldst_cmd, 0, sizeof(ldst_cmd));
9833dde7c95SVishal Kulkarni ldst_cmd.op_to_addrspace =
9843dde7c95SVishal Kulkarni cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
9853dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
9863dde7c95SVishal Kulkarni F_FW_CMD_READ |
9873dde7c95SVishal Kulkarni V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
9883dde7c95SVishal Kulkarni ldst_cmd.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst_cmd));
9893dde7c95SVishal Kulkarni ldst_cmd.u.pcie.select_naccess = V_FW_LDST_CMD_NACCESS(1);
9903dde7c95SVishal Kulkarni ldst_cmd.u.pcie.ctrl_to_fn =
9913dde7c95SVishal Kulkarni (F_FW_LDST_CMD_LC | V_FW_LDST_CMD_FN(adap->pf));
9923dde7c95SVishal Kulkarni ldst_cmd.u.pcie.r = reg;
99356b2bdd1SGireesh Nagabhushana
99456b2bdd1SGireesh Nagabhushana /*
9953dde7c95SVishal Kulkarni * If the LDST Command succeeds, return the result, otherwise
9963dde7c95SVishal Kulkarni * fall through to reading it directly ourselves ...
99756b2bdd1SGireesh Nagabhushana */
9983dde7c95SVishal Kulkarni ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd, sizeof(ldst_cmd),
9993dde7c95SVishal Kulkarni &ldst_cmd);
10003dde7c95SVishal Kulkarni if (ret == 0)
10013dde7c95SVishal Kulkarni return be32_to_cpu(ldst_cmd.u.pcie.data[0]);
100256b2bdd1SGireesh Nagabhushana
10033dde7c95SVishal Kulkarni CH_WARN(adap, "Firmware failed to return "
10043dde7c95SVishal Kulkarni "Configuration Space register %d, err = %d\n",
10053dde7c95SVishal Kulkarni reg, -ret);
100656b2bdd1SGireesh Nagabhushana }
100756b2bdd1SGireesh Nagabhushana
100856b2bdd1SGireesh Nagabhushana /*
10093dde7c95SVishal Kulkarni * Read the desired Configuration Space register via the PCI-E
10103dde7c95SVishal Kulkarni * Backdoor mechanism.
10113dde7c95SVishal Kulkarni */
10123dde7c95SVishal Kulkarni t4_hw_pci_read_cfg4(adap, reg, &val);
10133dde7c95SVishal Kulkarni return val;
10143dde7c95SVishal Kulkarni }
10153dde7c95SVishal Kulkarni
10163dde7c95SVishal Kulkarni /*
10173dde7c95SVishal Kulkarni * Get the window based on base passed to it.
10183dde7c95SVishal Kulkarni * Window aperture is currently unhandled, but there is no use case for it
10193dde7c95SVishal Kulkarni * right now
10203dde7c95SVishal Kulkarni */
t4_get_window(struct adapter * adap,u64 pci_base,u64 pci_mask,u64 memwin_base,int drv_fw_attach)10213dde7c95SVishal Kulkarni static int t4_get_window(struct adapter *adap, u64 pci_base, u64 pci_mask, u64 memwin_base, int drv_fw_attach)
10223dde7c95SVishal Kulkarni {
10233dde7c95SVishal Kulkarni if (is_t4(adap->params.chip)) {
10243dde7c95SVishal Kulkarni u32 bar0;
10253dde7c95SVishal Kulkarni
10263dde7c95SVishal Kulkarni /*
10273dde7c95SVishal Kulkarni * Truncation intentional: we only read the bottom 32-bits of
10283dde7c95SVishal Kulkarni * the 64-bit BAR0/BAR1 ... We use the hardware backdoor
10293dde7c95SVishal Kulkarni * mechanism to read BAR0 instead of using
10303dde7c95SVishal Kulkarni * pci_resource_start() because we could be operating from
10313dde7c95SVishal Kulkarni * within a Virtual Machine which is trapping our accesses to
10323dde7c95SVishal Kulkarni * our Configuration Space and we need to set up the PCI-E
10333dde7c95SVishal Kulkarni * Memory Window decoders with the actual addresses which will
10343dde7c95SVishal Kulkarni * be coming across the PCI-E link.
10353dde7c95SVishal Kulkarni */
10363dde7c95SVishal Kulkarni bar0 = t4_read_pcie_cfg4(adap, pci_base, drv_fw_attach);
10373dde7c95SVishal Kulkarni bar0 &= pci_mask;
10383dde7c95SVishal Kulkarni adap->t4_bar0 = bar0;
10393dde7c95SVishal Kulkarni
10403dde7c95SVishal Kulkarni return bar0 + memwin_base;
10413dde7c95SVishal Kulkarni } else {
10423dde7c95SVishal Kulkarni /* For T5, only relative offset inside the PCIe BAR is passed */
10433dde7c95SVishal Kulkarni return memwin_base;
10443dde7c95SVishal Kulkarni }
10453dde7c95SVishal Kulkarni }
10463dde7c95SVishal Kulkarni
10473dde7c95SVishal Kulkarni /* Get the default utility window (win0) used by everyone */
t4_get_util_window(struct adapter * adap,int drv_fw_attach)10483dde7c95SVishal Kulkarni int t4_get_util_window(struct adapter *adap, int drv_fw_attach)
10493dde7c95SVishal Kulkarni {
10503dde7c95SVishal Kulkarni return t4_get_window(adap, PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_MEM_MASK, MEMWIN0_BASE, drv_fw_attach);
10513dde7c95SVishal Kulkarni }
10523dde7c95SVishal Kulkarni
10533dde7c95SVishal Kulkarni /*
10543dde7c95SVishal Kulkarni * Set up memory window for accessing adapter memory ranges. (Read
10553dde7c95SVishal Kulkarni * back MA register to ensure that changes propagate before we attempt
10563dde7c95SVishal Kulkarni * to use the new values.)
10573dde7c95SVishal Kulkarni */
t4_setup_memwin(struct adapter * adap,u32 memwin_base,u32 window)10583dde7c95SVishal Kulkarni void t4_setup_memwin(struct adapter *adap, u32 memwin_base, u32 window)
10593dde7c95SVishal Kulkarni {
10603dde7c95SVishal Kulkarni t4_write_reg(adap, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, window),
10613dde7c95SVishal Kulkarni memwin_base | V_BIR(0) |
10623dde7c95SVishal Kulkarni V_WINDOW(ilog2(MEMWIN0_APERTURE) - X_WINDOW_SHIFT));
10633dde7c95SVishal Kulkarni t4_read_reg(adap, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, window));
10643dde7c95SVishal Kulkarni }
10653dde7c95SVishal Kulkarni
10663dde7c95SVishal Kulkarni /**
10673dde7c95SVishal Kulkarni * t4_get_regs_len - return the size of the chips register set
10683dde7c95SVishal Kulkarni * @adapter: the adapter
106956b2bdd1SGireesh Nagabhushana *
10703dde7c95SVishal Kulkarni * Returns the size of the chip's BAR0 register space.
107156b2bdd1SGireesh Nagabhushana */
t4_get_regs_len(struct adapter * adapter)10723dde7c95SVishal Kulkarni unsigned int t4_get_regs_len(struct adapter *adapter)
107356b2bdd1SGireesh Nagabhushana {
10743dde7c95SVishal Kulkarni unsigned int chip_version = CHELSIO_CHIP_VERSION(adapter->params.chip);
107556b2bdd1SGireesh Nagabhushana
10763dde7c95SVishal Kulkarni switch (chip_version) {
10773dde7c95SVishal Kulkarni case CHELSIO_T4:
10783dde7c95SVishal Kulkarni return T4_REGMAP_SIZE;
10793dde7c95SVishal Kulkarni
10803dde7c95SVishal Kulkarni case CHELSIO_T5:
10813dde7c95SVishal Kulkarni case CHELSIO_T6:
10823dde7c95SVishal Kulkarni return T5_REGMAP_SIZE;
10833dde7c95SVishal Kulkarni }
10843dde7c95SVishal Kulkarni
10853dde7c95SVishal Kulkarni CH_ERR(adapter,
10863dde7c95SVishal Kulkarni "Unsupported chip version %d\n", chip_version);
10873dde7c95SVishal Kulkarni return 0;
10883dde7c95SVishal Kulkarni }
10893dde7c95SVishal Kulkarni
10903dde7c95SVishal Kulkarni /**
10913dde7c95SVishal Kulkarni * t4_get_regs - read chip registers into provided buffer
10923dde7c95SVishal Kulkarni * @adap: the adapter
10933dde7c95SVishal Kulkarni * @buf: register buffer
10943dde7c95SVishal Kulkarni * @buf_size: size (in bytes) of register buffer
10953dde7c95SVishal Kulkarni *
10963dde7c95SVishal Kulkarni * If the provided register buffer isn't large enough for the chip's
10973dde7c95SVishal Kulkarni * full register range, the register dump will be truncated to the
10983dde7c95SVishal Kulkarni * register buffer's size.
109956b2bdd1SGireesh Nagabhushana */
t4_get_regs(struct adapter * adap,void * buf,size_t buf_size)11003dde7c95SVishal Kulkarni void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
110156b2bdd1SGireesh Nagabhushana {
11023dde7c95SVishal Kulkarni static const unsigned int t4_reg_ranges[] = {
11033dde7c95SVishal Kulkarni 0x1008, 0x1108,
11043dde7c95SVishal Kulkarni 0x1180, 0x1184,
11053dde7c95SVishal Kulkarni 0x1190, 0x1194,
11063dde7c95SVishal Kulkarni 0x11a0, 0x11a4,
11073dde7c95SVishal Kulkarni 0x11b0, 0x11b4,
11083dde7c95SVishal Kulkarni 0x11fc, 0x123c,
11093dde7c95SVishal Kulkarni 0x1300, 0x173c,
11103dde7c95SVishal Kulkarni 0x1800, 0x18fc,
11113dde7c95SVishal Kulkarni 0x3000, 0x30d8,
11123dde7c95SVishal Kulkarni 0x30e0, 0x30e4,
11133dde7c95SVishal Kulkarni 0x30ec, 0x5910,
11143dde7c95SVishal Kulkarni 0x5920, 0x5924,
11153dde7c95SVishal Kulkarni 0x5960, 0x5960,
11163dde7c95SVishal Kulkarni 0x5968, 0x5968,
11173dde7c95SVishal Kulkarni 0x5970, 0x5970,
11183dde7c95SVishal Kulkarni 0x5978, 0x5978,
11193dde7c95SVishal Kulkarni 0x5980, 0x5980,
11203dde7c95SVishal Kulkarni 0x5988, 0x5988,
11213dde7c95SVishal Kulkarni 0x5990, 0x5990,
11223dde7c95SVishal Kulkarni 0x5998, 0x5998,
11233dde7c95SVishal Kulkarni 0x59a0, 0x59d4,
11243dde7c95SVishal Kulkarni 0x5a00, 0x5ae0,
11253dde7c95SVishal Kulkarni 0x5ae8, 0x5ae8,
11263dde7c95SVishal Kulkarni 0x5af0, 0x5af0,
11273dde7c95SVishal Kulkarni 0x5af8, 0x5af8,
11283dde7c95SVishal Kulkarni 0x6000, 0x6098,
11293dde7c95SVishal Kulkarni 0x6100, 0x6150,
11303dde7c95SVishal Kulkarni 0x6200, 0x6208,
11313dde7c95SVishal Kulkarni 0x6240, 0x6248,
11323dde7c95SVishal Kulkarni 0x6280, 0x62b0,
11333dde7c95SVishal Kulkarni 0x62c0, 0x6338,
11343dde7c95SVishal Kulkarni 0x6370, 0x638c,
11353dde7c95SVishal Kulkarni 0x6400, 0x643c,
11363dde7c95SVishal Kulkarni 0x6500, 0x6524,
11373dde7c95SVishal Kulkarni 0x6a00, 0x6a04,
11383dde7c95SVishal Kulkarni 0x6a14, 0x6a38,
11393dde7c95SVishal Kulkarni 0x6a60, 0x6a70,
11403dde7c95SVishal Kulkarni 0x6a78, 0x6a78,
11413dde7c95SVishal Kulkarni 0x6b00, 0x6b0c,
11423dde7c95SVishal Kulkarni 0x6b1c, 0x6b84,
11433dde7c95SVishal Kulkarni 0x6bf0, 0x6bf8,
11443dde7c95SVishal Kulkarni 0x6c00, 0x6c0c,
11453dde7c95SVishal Kulkarni 0x6c1c, 0x6c84,
11463dde7c95SVishal Kulkarni 0x6cf0, 0x6cf8,
11473dde7c95SVishal Kulkarni 0x6d00, 0x6d0c,
11483dde7c95SVishal Kulkarni 0x6d1c, 0x6d84,
11493dde7c95SVishal Kulkarni 0x6df0, 0x6df8,
11503dde7c95SVishal Kulkarni 0x6e00, 0x6e0c,
11513dde7c95SVishal Kulkarni 0x6e1c, 0x6e84,
11523dde7c95SVishal Kulkarni 0x6ef0, 0x6ef8,
11533dde7c95SVishal Kulkarni 0x6f00, 0x6f0c,
11543dde7c95SVishal Kulkarni 0x6f1c, 0x6f84,
11553dde7c95SVishal Kulkarni 0x6ff0, 0x6ff8,
11563dde7c95SVishal Kulkarni 0x7000, 0x700c,
11573dde7c95SVishal Kulkarni 0x701c, 0x7084,
11583dde7c95SVishal Kulkarni 0x70f0, 0x70f8,
11593dde7c95SVishal Kulkarni 0x7100, 0x710c,
11603dde7c95SVishal Kulkarni 0x711c, 0x7184,
11613dde7c95SVishal Kulkarni 0x71f0, 0x71f8,
11623dde7c95SVishal Kulkarni 0x7200, 0x720c,
11633dde7c95SVishal Kulkarni 0x721c, 0x7284,
11643dde7c95SVishal Kulkarni 0x72f0, 0x72f8,
11653dde7c95SVishal Kulkarni 0x7300, 0x730c,
11663dde7c95SVishal Kulkarni 0x731c, 0x7384,
11673dde7c95SVishal Kulkarni 0x73f0, 0x73f8,
11683dde7c95SVishal Kulkarni 0x7400, 0x7450,
11693dde7c95SVishal Kulkarni 0x7500, 0x7530,
11703dde7c95SVishal Kulkarni 0x7600, 0x760c,
11713dde7c95SVishal Kulkarni 0x7614, 0x761c,
11723dde7c95SVishal Kulkarni 0x7680, 0x76cc,
11733dde7c95SVishal Kulkarni 0x7700, 0x7798,
11743dde7c95SVishal Kulkarni 0x77c0, 0x77fc,
11753dde7c95SVishal Kulkarni 0x7900, 0x79fc,
11763dde7c95SVishal Kulkarni 0x7b00, 0x7b58,
11773dde7c95SVishal Kulkarni 0x7b60, 0x7b84,
11783dde7c95SVishal Kulkarni 0x7b8c, 0x7c38,
11793dde7c95SVishal Kulkarni 0x7d00, 0x7d38,
11803dde7c95SVishal Kulkarni 0x7d40, 0x7d80,
11813dde7c95SVishal Kulkarni 0x7d8c, 0x7ddc,
11823dde7c95SVishal Kulkarni 0x7de4, 0x7e04,
11833dde7c95SVishal Kulkarni 0x7e10, 0x7e1c,
11843dde7c95SVishal Kulkarni 0x7e24, 0x7e38,
11853dde7c95SVishal Kulkarni 0x7e40, 0x7e44,
11863dde7c95SVishal Kulkarni 0x7e4c, 0x7e78,
11873dde7c95SVishal Kulkarni 0x7e80, 0x7ea4,
11883dde7c95SVishal Kulkarni 0x7eac, 0x7edc,
11893dde7c95SVishal Kulkarni 0x7ee8, 0x7efc,
11903dde7c95SVishal Kulkarni 0x8dc0, 0x8e04,
11913dde7c95SVishal Kulkarni 0x8e10, 0x8e1c,
11923dde7c95SVishal Kulkarni 0x8e30, 0x8e78,
11933dde7c95SVishal Kulkarni 0x8ea0, 0x8eb8,
11943dde7c95SVishal Kulkarni 0x8ec0, 0x8f6c,
11953dde7c95SVishal Kulkarni 0x8fc0, 0x9008,
11963dde7c95SVishal Kulkarni 0x9010, 0x9058,
11973dde7c95SVishal Kulkarni 0x9060, 0x9060,
11983dde7c95SVishal Kulkarni 0x9068, 0x9074,
11993dde7c95SVishal Kulkarni 0x90fc, 0x90fc,
12003dde7c95SVishal Kulkarni 0x9400, 0x9408,
12013dde7c95SVishal Kulkarni 0x9410, 0x9458,
12023dde7c95SVishal Kulkarni 0x9600, 0x9600,
12033dde7c95SVishal Kulkarni 0x9608, 0x9638,
12043dde7c95SVishal Kulkarni 0x9640, 0x96bc,
12053dde7c95SVishal Kulkarni 0x9800, 0x9808,
12063dde7c95SVishal Kulkarni 0x9820, 0x983c,
12073dde7c95SVishal Kulkarni 0x9850, 0x9864,
12083dde7c95SVishal Kulkarni 0x9c00, 0x9c6c,
12093dde7c95SVishal Kulkarni 0x9c80, 0x9cec,
12103dde7c95SVishal Kulkarni 0x9d00, 0x9d6c,
12113dde7c95SVishal Kulkarni 0x9d80, 0x9dec,
12123dde7c95SVishal Kulkarni 0x9e00, 0x9e6c,
12133dde7c95SVishal Kulkarni 0x9e80, 0x9eec,
12143dde7c95SVishal Kulkarni 0x9f00, 0x9f6c,
12153dde7c95SVishal Kulkarni 0x9f80, 0x9fec,
12163dde7c95SVishal Kulkarni 0xd004, 0xd004,
12173dde7c95SVishal Kulkarni 0xd010, 0xd03c,
12183dde7c95SVishal Kulkarni 0xdfc0, 0xdfe0,
12193dde7c95SVishal Kulkarni 0xe000, 0xea7c,
12203dde7c95SVishal Kulkarni 0xf000, 0x11110,
12213dde7c95SVishal Kulkarni 0x11118, 0x11190,
12223dde7c95SVishal Kulkarni 0x19040, 0x1906c,
12233dde7c95SVishal Kulkarni 0x19078, 0x19080,
12243dde7c95SVishal Kulkarni 0x1908c, 0x190e4,
12253dde7c95SVishal Kulkarni 0x190f0, 0x190f8,
12263dde7c95SVishal Kulkarni 0x19100, 0x19110,
12273dde7c95SVishal Kulkarni 0x19120, 0x19124,
12283dde7c95SVishal Kulkarni 0x19150, 0x19194,
12293dde7c95SVishal Kulkarni 0x1919c, 0x191b0,
12303dde7c95SVishal Kulkarni 0x191d0, 0x191e8,
12313dde7c95SVishal Kulkarni 0x19238, 0x1924c,
12323dde7c95SVishal Kulkarni 0x193f8, 0x1943c,
12333dde7c95SVishal Kulkarni 0x1944c, 0x19474,
12343dde7c95SVishal Kulkarni 0x19490, 0x194e0,
12353dde7c95SVishal Kulkarni 0x194f0, 0x194f8,
12363dde7c95SVishal Kulkarni 0x19800, 0x19c08,
12373dde7c95SVishal Kulkarni 0x19c10, 0x19c90,
12383dde7c95SVishal Kulkarni 0x19ca0, 0x19ce4,
12393dde7c95SVishal Kulkarni 0x19cf0, 0x19d40,
12403dde7c95SVishal Kulkarni 0x19d50, 0x19d94,
12413dde7c95SVishal Kulkarni 0x19da0, 0x19de8,
12423dde7c95SVishal Kulkarni 0x19df0, 0x19e40,
12433dde7c95SVishal Kulkarni 0x19e50, 0x19e90,
12443dde7c95SVishal Kulkarni 0x19ea0, 0x19f4c,
12453dde7c95SVishal Kulkarni 0x1a000, 0x1a004,
12463dde7c95SVishal Kulkarni 0x1a010, 0x1a06c,
12473dde7c95SVishal Kulkarni 0x1a0b0, 0x1a0e4,
12483dde7c95SVishal Kulkarni 0x1a0ec, 0x1a0f4,
12493dde7c95SVishal Kulkarni 0x1a100, 0x1a108,
12503dde7c95SVishal Kulkarni 0x1a114, 0x1a120,
12513dde7c95SVishal Kulkarni 0x1a128, 0x1a130,
12523dde7c95SVishal Kulkarni 0x1a138, 0x1a138,
12533dde7c95SVishal Kulkarni 0x1a190, 0x1a1c4,
12543dde7c95SVishal Kulkarni 0x1a1fc, 0x1a1fc,
12553dde7c95SVishal Kulkarni 0x1e040, 0x1e04c,
12563dde7c95SVishal Kulkarni 0x1e284, 0x1e28c,
12573dde7c95SVishal Kulkarni 0x1e2c0, 0x1e2c0,
12583dde7c95SVishal Kulkarni 0x1e2e0, 0x1e2e0,
12593dde7c95SVishal Kulkarni 0x1e300, 0x1e384,
12603dde7c95SVishal Kulkarni 0x1e3c0, 0x1e3c8,
12613dde7c95SVishal Kulkarni 0x1e440, 0x1e44c,
12623dde7c95SVishal Kulkarni 0x1e684, 0x1e68c,
12633dde7c95SVishal Kulkarni 0x1e6c0, 0x1e6c0,
12643dde7c95SVishal Kulkarni 0x1e6e0, 0x1e6e0,
12653dde7c95SVishal Kulkarni 0x1e700, 0x1e784,
12663dde7c95SVishal Kulkarni 0x1e7c0, 0x1e7c8,
12673dde7c95SVishal Kulkarni 0x1e840, 0x1e84c,
12683dde7c95SVishal Kulkarni 0x1ea84, 0x1ea8c,
12693dde7c95SVishal Kulkarni 0x1eac0, 0x1eac0,
12703dde7c95SVishal Kulkarni 0x1eae0, 0x1eae0,
12713dde7c95SVishal Kulkarni 0x1eb00, 0x1eb84,
12723dde7c95SVishal Kulkarni 0x1ebc0, 0x1ebc8,
12733dde7c95SVishal Kulkarni 0x1ec40, 0x1ec4c,
12743dde7c95SVishal Kulkarni 0x1ee84, 0x1ee8c,
12753dde7c95SVishal Kulkarni 0x1eec0, 0x1eec0,
12763dde7c95SVishal Kulkarni 0x1eee0, 0x1eee0,
12773dde7c95SVishal Kulkarni 0x1ef00, 0x1ef84,
12783dde7c95SVishal Kulkarni 0x1efc0, 0x1efc8,
12793dde7c95SVishal Kulkarni 0x1f040, 0x1f04c,
12803dde7c95SVishal Kulkarni 0x1f284, 0x1f28c,
12813dde7c95SVishal Kulkarni 0x1f2c0, 0x1f2c0,
12823dde7c95SVishal Kulkarni 0x1f2e0, 0x1f2e0,
12833dde7c95SVishal Kulkarni 0x1f300, 0x1f384,
12843dde7c95SVishal Kulkarni 0x1f3c0, 0x1f3c8,
12853dde7c95SVishal Kulkarni 0x1f440, 0x1f44c,
12863dde7c95SVishal Kulkarni 0x1f684, 0x1f68c,
12873dde7c95SVishal Kulkarni 0x1f6c0, 0x1f6c0,
12883dde7c95SVishal Kulkarni 0x1f6e0, 0x1f6e0,
12893dde7c95SVishal Kulkarni 0x1f700, 0x1f784,
12903dde7c95SVishal Kulkarni 0x1f7c0, 0x1f7c8,
12913dde7c95SVishal Kulkarni 0x1f840, 0x1f84c,
12923dde7c95SVishal Kulkarni 0x1fa84, 0x1fa8c,
12933dde7c95SVishal Kulkarni 0x1fac0, 0x1fac0,
12943dde7c95SVishal Kulkarni 0x1fae0, 0x1fae0,
12953dde7c95SVishal Kulkarni 0x1fb00, 0x1fb84,
12963dde7c95SVishal Kulkarni 0x1fbc0, 0x1fbc8,
12973dde7c95SVishal Kulkarni 0x1fc40, 0x1fc4c,
12983dde7c95SVishal Kulkarni 0x1fe84, 0x1fe8c,
12993dde7c95SVishal Kulkarni 0x1fec0, 0x1fec0,
13003dde7c95SVishal Kulkarni 0x1fee0, 0x1fee0,
13013dde7c95SVishal Kulkarni 0x1ff00, 0x1ff84,
13023dde7c95SVishal Kulkarni 0x1ffc0, 0x1ffc8,
13033dde7c95SVishal Kulkarni 0x20000, 0x2002c,
13043dde7c95SVishal Kulkarni 0x20100, 0x2013c,
13053dde7c95SVishal Kulkarni 0x20190, 0x201a0,
13063dde7c95SVishal Kulkarni 0x201a8, 0x201b8,
13073dde7c95SVishal Kulkarni 0x201c4, 0x201c8,
13083dde7c95SVishal Kulkarni 0x20200, 0x20318,
13093dde7c95SVishal Kulkarni 0x20400, 0x204b4,
13103dde7c95SVishal Kulkarni 0x204c0, 0x20528,
13113dde7c95SVishal Kulkarni 0x20540, 0x20614,
13123dde7c95SVishal Kulkarni 0x21000, 0x21040,
13133dde7c95SVishal Kulkarni 0x2104c, 0x21060,
13143dde7c95SVishal Kulkarni 0x210c0, 0x210ec,
13153dde7c95SVishal Kulkarni 0x21200, 0x21268,
13163dde7c95SVishal Kulkarni 0x21270, 0x21284,
13173dde7c95SVishal Kulkarni 0x212fc, 0x21388,
13183dde7c95SVishal Kulkarni 0x21400, 0x21404,
13193dde7c95SVishal Kulkarni 0x21500, 0x21500,
13203dde7c95SVishal Kulkarni 0x21510, 0x21518,
13213dde7c95SVishal Kulkarni 0x2152c, 0x21530,
13223dde7c95SVishal Kulkarni 0x2153c, 0x2153c,
13233dde7c95SVishal Kulkarni 0x21550, 0x21554,
13243dde7c95SVishal Kulkarni 0x21600, 0x21600,
13253dde7c95SVishal Kulkarni 0x21608, 0x2161c,
13263dde7c95SVishal Kulkarni 0x21624, 0x21628,
13273dde7c95SVishal Kulkarni 0x21630, 0x21634,
13283dde7c95SVishal Kulkarni 0x2163c, 0x2163c,
13293dde7c95SVishal Kulkarni 0x21700, 0x2171c,
13303dde7c95SVishal Kulkarni 0x21780, 0x2178c,
13313dde7c95SVishal Kulkarni 0x21800, 0x21818,
13323dde7c95SVishal Kulkarni 0x21820, 0x21828,
13333dde7c95SVishal Kulkarni 0x21830, 0x21848,
13343dde7c95SVishal Kulkarni 0x21850, 0x21854,
13353dde7c95SVishal Kulkarni 0x21860, 0x21868,
13363dde7c95SVishal Kulkarni 0x21870, 0x21870,
13373dde7c95SVishal Kulkarni 0x21878, 0x21898,
13383dde7c95SVishal Kulkarni 0x218a0, 0x218a8,
13393dde7c95SVishal Kulkarni 0x218b0, 0x218c8,
13403dde7c95SVishal Kulkarni 0x218d0, 0x218d4,
13413dde7c95SVishal Kulkarni 0x218e0, 0x218e8,
13423dde7c95SVishal Kulkarni 0x218f0, 0x218f0,
13433dde7c95SVishal Kulkarni 0x218f8, 0x21a18,
13443dde7c95SVishal Kulkarni 0x21a20, 0x21a28,
13453dde7c95SVishal Kulkarni 0x21a30, 0x21a48,
13463dde7c95SVishal Kulkarni 0x21a50, 0x21a54,
13473dde7c95SVishal Kulkarni 0x21a60, 0x21a68,
13483dde7c95SVishal Kulkarni 0x21a70, 0x21a70,
13493dde7c95SVishal Kulkarni 0x21a78, 0x21a98,
13503dde7c95SVishal Kulkarni 0x21aa0, 0x21aa8,
13513dde7c95SVishal Kulkarni 0x21ab0, 0x21ac8,
13523dde7c95SVishal Kulkarni 0x21ad0, 0x21ad4,
13533dde7c95SVishal Kulkarni 0x21ae0, 0x21ae8,
13543dde7c95SVishal Kulkarni 0x21af0, 0x21af0,
13553dde7c95SVishal Kulkarni 0x21af8, 0x21c18,
13563dde7c95SVishal Kulkarni 0x21c20, 0x21c20,
13573dde7c95SVishal Kulkarni 0x21c28, 0x21c30,
13583dde7c95SVishal Kulkarni 0x21c38, 0x21c38,
13593dde7c95SVishal Kulkarni 0x21c80, 0x21c98,
13603dde7c95SVishal Kulkarni 0x21ca0, 0x21ca8,
13613dde7c95SVishal Kulkarni 0x21cb0, 0x21cc8,
13623dde7c95SVishal Kulkarni 0x21cd0, 0x21cd4,
13633dde7c95SVishal Kulkarni 0x21ce0, 0x21ce8,
13643dde7c95SVishal Kulkarni 0x21cf0, 0x21cf0,
13653dde7c95SVishal Kulkarni 0x21cf8, 0x21d7c,
13663dde7c95SVishal Kulkarni 0x21e00, 0x21e04,
13673dde7c95SVishal Kulkarni 0x22000, 0x2202c,
13683dde7c95SVishal Kulkarni 0x22100, 0x2213c,
13693dde7c95SVishal Kulkarni 0x22190, 0x221a0,
13703dde7c95SVishal Kulkarni 0x221a8, 0x221b8,
13713dde7c95SVishal Kulkarni 0x221c4, 0x221c8,
13723dde7c95SVishal Kulkarni 0x22200, 0x22318,
13733dde7c95SVishal Kulkarni 0x22400, 0x224b4,
13743dde7c95SVishal Kulkarni 0x224c0, 0x22528,
13753dde7c95SVishal Kulkarni 0x22540, 0x22614,
13763dde7c95SVishal Kulkarni 0x23000, 0x23040,
13773dde7c95SVishal Kulkarni 0x2304c, 0x23060,
13783dde7c95SVishal Kulkarni 0x230c0, 0x230ec,
13793dde7c95SVishal Kulkarni 0x23200, 0x23268,
13803dde7c95SVishal Kulkarni 0x23270, 0x23284,
13813dde7c95SVishal Kulkarni 0x232fc, 0x23388,
13823dde7c95SVishal Kulkarni 0x23400, 0x23404,
13833dde7c95SVishal Kulkarni 0x23500, 0x23500,
13843dde7c95SVishal Kulkarni 0x23510, 0x23518,
13853dde7c95SVishal Kulkarni 0x2352c, 0x23530,
13863dde7c95SVishal Kulkarni 0x2353c, 0x2353c,
13873dde7c95SVishal Kulkarni 0x23550, 0x23554,
13883dde7c95SVishal Kulkarni 0x23600, 0x23600,
13893dde7c95SVishal Kulkarni 0x23608, 0x2361c,
13903dde7c95SVishal Kulkarni 0x23624, 0x23628,
13913dde7c95SVishal Kulkarni 0x23630, 0x23634,
13923dde7c95SVishal Kulkarni 0x2363c, 0x2363c,
13933dde7c95SVishal Kulkarni 0x23700, 0x2371c,
13943dde7c95SVishal Kulkarni 0x23780, 0x2378c,
13953dde7c95SVishal Kulkarni 0x23800, 0x23818,
13963dde7c95SVishal Kulkarni 0x23820, 0x23828,
13973dde7c95SVishal Kulkarni 0x23830, 0x23848,
13983dde7c95SVishal Kulkarni 0x23850, 0x23854,
13993dde7c95SVishal Kulkarni 0x23860, 0x23868,
14003dde7c95SVishal Kulkarni 0x23870, 0x23870,
14013dde7c95SVishal Kulkarni 0x23878, 0x23898,
14023dde7c95SVishal Kulkarni 0x238a0, 0x238a8,
14033dde7c95SVishal Kulkarni 0x238b0, 0x238c8,
14043dde7c95SVishal Kulkarni 0x238d0, 0x238d4,
14053dde7c95SVishal Kulkarni 0x238e0, 0x238e8,
14063dde7c95SVishal Kulkarni 0x238f0, 0x238f0,
14073dde7c95SVishal Kulkarni 0x238f8, 0x23a18,
14083dde7c95SVishal Kulkarni 0x23a20, 0x23a28,
14093dde7c95SVishal Kulkarni 0x23a30, 0x23a48,
14103dde7c95SVishal Kulkarni 0x23a50, 0x23a54,
14113dde7c95SVishal Kulkarni 0x23a60, 0x23a68,
14123dde7c95SVishal Kulkarni 0x23a70, 0x23a70,
14133dde7c95SVishal Kulkarni 0x23a78, 0x23a98,
14143dde7c95SVishal Kulkarni 0x23aa0, 0x23aa8,
14153dde7c95SVishal Kulkarni 0x23ab0, 0x23ac8,
14163dde7c95SVishal Kulkarni 0x23ad0, 0x23ad4,
14173dde7c95SVishal Kulkarni 0x23ae0, 0x23ae8,
14183dde7c95SVishal Kulkarni 0x23af0, 0x23af0,
14193dde7c95SVishal Kulkarni 0x23af8, 0x23c18,
14203dde7c95SVishal Kulkarni 0x23c20, 0x23c20,
14213dde7c95SVishal Kulkarni 0x23c28, 0x23c30,
14223dde7c95SVishal Kulkarni 0x23c38, 0x23c38,
14233dde7c95SVishal Kulkarni 0x23c80, 0x23c98,
14243dde7c95SVishal Kulkarni 0x23ca0, 0x23ca8,
14253dde7c95SVishal Kulkarni 0x23cb0, 0x23cc8,
14263dde7c95SVishal Kulkarni 0x23cd0, 0x23cd4,
14273dde7c95SVishal Kulkarni 0x23ce0, 0x23ce8,
14283dde7c95SVishal Kulkarni 0x23cf0, 0x23cf0,
14293dde7c95SVishal Kulkarni 0x23cf8, 0x23d7c,
14303dde7c95SVishal Kulkarni 0x23e00, 0x23e04,
14313dde7c95SVishal Kulkarni 0x24000, 0x2402c,
14323dde7c95SVishal Kulkarni 0x24100, 0x2413c,
14333dde7c95SVishal Kulkarni 0x24190, 0x241a0,
14343dde7c95SVishal Kulkarni 0x241a8, 0x241b8,
14353dde7c95SVishal Kulkarni 0x241c4, 0x241c8,
14363dde7c95SVishal Kulkarni 0x24200, 0x24318,
14373dde7c95SVishal Kulkarni 0x24400, 0x244b4,
14383dde7c95SVishal Kulkarni 0x244c0, 0x24528,
14393dde7c95SVishal Kulkarni 0x24540, 0x24614,
14403dde7c95SVishal Kulkarni 0x25000, 0x25040,
14413dde7c95SVishal Kulkarni 0x2504c, 0x25060,
14423dde7c95SVishal Kulkarni 0x250c0, 0x250ec,
14433dde7c95SVishal Kulkarni 0x25200, 0x25268,
14443dde7c95SVishal Kulkarni 0x25270, 0x25284,
14453dde7c95SVishal Kulkarni 0x252fc, 0x25388,
14463dde7c95SVishal Kulkarni 0x25400, 0x25404,
14473dde7c95SVishal Kulkarni 0x25500, 0x25500,
14483dde7c95SVishal Kulkarni 0x25510, 0x25518,
14493dde7c95SVishal Kulkarni 0x2552c, 0x25530,
14503dde7c95SVishal Kulkarni 0x2553c, 0x2553c,
14513dde7c95SVishal Kulkarni 0x25550, 0x25554,
14523dde7c95SVishal Kulkarni 0x25600, 0x25600,
14533dde7c95SVishal Kulkarni 0x25608, 0x2561c,
14543dde7c95SVishal Kulkarni 0x25624, 0x25628,
14553dde7c95SVishal Kulkarni 0x25630, 0x25634,
14563dde7c95SVishal Kulkarni 0x2563c, 0x2563c,
14573dde7c95SVishal Kulkarni 0x25700, 0x2571c,
14583dde7c95SVishal Kulkarni 0x25780, 0x2578c,
14593dde7c95SVishal Kulkarni 0x25800, 0x25818,
14603dde7c95SVishal Kulkarni 0x25820, 0x25828,
14613dde7c95SVishal Kulkarni 0x25830, 0x25848,
14623dde7c95SVishal Kulkarni 0x25850, 0x25854,
14633dde7c95SVishal Kulkarni 0x25860, 0x25868,
14643dde7c95SVishal Kulkarni 0x25870, 0x25870,
14653dde7c95SVishal Kulkarni 0x25878, 0x25898,
14663dde7c95SVishal Kulkarni 0x258a0, 0x258a8,
14673dde7c95SVishal Kulkarni 0x258b0, 0x258c8,
14683dde7c95SVishal Kulkarni 0x258d0, 0x258d4,
14693dde7c95SVishal Kulkarni 0x258e0, 0x258e8,
14703dde7c95SVishal Kulkarni 0x258f0, 0x258f0,
14713dde7c95SVishal Kulkarni 0x258f8, 0x25a18,
14723dde7c95SVishal Kulkarni 0x25a20, 0x25a28,
14733dde7c95SVishal Kulkarni 0x25a30, 0x25a48,
14743dde7c95SVishal Kulkarni 0x25a50, 0x25a54,
14753dde7c95SVishal Kulkarni 0x25a60, 0x25a68,
14763dde7c95SVishal Kulkarni 0x25a70, 0x25a70,
14773dde7c95SVishal Kulkarni 0x25a78, 0x25a98,
14783dde7c95SVishal Kulkarni 0x25aa0, 0x25aa8,
14793dde7c95SVishal Kulkarni 0x25ab0, 0x25ac8,
14803dde7c95SVishal Kulkarni 0x25ad0, 0x25ad4,
14813dde7c95SVishal Kulkarni 0x25ae0, 0x25ae8,
14823dde7c95SVishal Kulkarni 0x25af0, 0x25af0,
14833dde7c95SVishal Kulkarni 0x25af8, 0x25c18,
14843dde7c95SVishal Kulkarni 0x25c20, 0x25c20,
14853dde7c95SVishal Kulkarni 0x25c28, 0x25c30,
14863dde7c95SVishal Kulkarni 0x25c38, 0x25c38,
14873dde7c95SVishal Kulkarni 0x25c80, 0x25c98,
14883dde7c95SVishal Kulkarni 0x25ca0, 0x25ca8,
14893dde7c95SVishal Kulkarni 0x25cb0, 0x25cc8,
14903dde7c95SVishal Kulkarni 0x25cd0, 0x25cd4,
14913dde7c95SVishal Kulkarni 0x25ce0, 0x25ce8,
14923dde7c95SVishal Kulkarni 0x25cf0, 0x25cf0,
14933dde7c95SVishal Kulkarni 0x25cf8, 0x25d7c,
14943dde7c95SVishal Kulkarni 0x25e00, 0x25e04,
14953dde7c95SVishal Kulkarni 0x26000, 0x2602c,
14963dde7c95SVishal Kulkarni 0x26100, 0x2613c,
14973dde7c95SVishal Kulkarni 0x26190, 0x261a0,
14983dde7c95SVishal Kulkarni 0x261a8, 0x261b8,
14993dde7c95SVishal Kulkarni 0x261c4, 0x261c8,
15003dde7c95SVishal Kulkarni 0x26200, 0x26318,
15013dde7c95SVishal Kulkarni 0x26400, 0x264b4,
15023dde7c95SVishal Kulkarni 0x264c0, 0x26528,
15033dde7c95SVishal Kulkarni 0x26540, 0x26614,
15043dde7c95SVishal Kulkarni 0x27000, 0x27040,
15053dde7c95SVishal Kulkarni 0x2704c, 0x27060,
15063dde7c95SVishal Kulkarni 0x270c0, 0x270ec,
15073dde7c95SVishal Kulkarni 0x27200, 0x27268,
15083dde7c95SVishal Kulkarni 0x27270, 0x27284,
15093dde7c95SVishal Kulkarni 0x272fc, 0x27388,
15103dde7c95SVishal Kulkarni 0x27400, 0x27404,
15113dde7c95SVishal Kulkarni 0x27500, 0x27500,
15123dde7c95SVishal Kulkarni 0x27510, 0x27518,
15133dde7c95SVishal Kulkarni 0x2752c, 0x27530,
15143dde7c95SVishal Kulkarni 0x2753c, 0x2753c,
15153dde7c95SVishal Kulkarni 0x27550, 0x27554,
15163dde7c95SVishal Kulkarni 0x27600, 0x27600,
15173dde7c95SVishal Kulkarni 0x27608, 0x2761c,
15183dde7c95SVishal Kulkarni 0x27624, 0x27628,
15193dde7c95SVishal Kulkarni 0x27630, 0x27634,
15203dde7c95SVishal Kulkarni 0x2763c, 0x2763c,
15213dde7c95SVishal Kulkarni 0x27700, 0x2771c,
15223dde7c95SVishal Kulkarni 0x27780, 0x2778c,
15233dde7c95SVishal Kulkarni 0x27800, 0x27818,
15243dde7c95SVishal Kulkarni 0x27820, 0x27828,
15253dde7c95SVishal Kulkarni 0x27830, 0x27848,
15263dde7c95SVishal Kulkarni 0x27850, 0x27854,
15273dde7c95SVishal Kulkarni 0x27860, 0x27868,
15283dde7c95SVishal Kulkarni 0x27870, 0x27870,
15293dde7c95SVishal Kulkarni 0x27878, 0x27898,
15303dde7c95SVishal Kulkarni 0x278a0, 0x278a8,
15313dde7c95SVishal Kulkarni 0x278b0, 0x278c8,
15323dde7c95SVishal Kulkarni 0x278d0, 0x278d4,
15333dde7c95SVishal Kulkarni 0x278e0, 0x278e8,
15343dde7c95SVishal Kulkarni 0x278f0, 0x278f0,
15353dde7c95SVishal Kulkarni 0x278f8, 0x27a18,
15363dde7c95SVishal Kulkarni 0x27a20, 0x27a28,
15373dde7c95SVishal Kulkarni 0x27a30, 0x27a48,
15383dde7c95SVishal Kulkarni 0x27a50, 0x27a54,
15393dde7c95SVishal Kulkarni 0x27a60, 0x27a68,
15403dde7c95SVishal Kulkarni 0x27a70, 0x27a70,
15413dde7c95SVishal Kulkarni 0x27a78, 0x27a98,
15423dde7c95SVishal Kulkarni 0x27aa0, 0x27aa8,
15433dde7c95SVishal Kulkarni 0x27ab0, 0x27ac8,
15443dde7c95SVishal Kulkarni 0x27ad0, 0x27ad4,
15453dde7c95SVishal Kulkarni 0x27ae0, 0x27ae8,
15463dde7c95SVishal Kulkarni 0x27af0, 0x27af0,
15473dde7c95SVishal Kulkarni 0x27af8, 0x27c18,
15483dde7c95SVishal Kulkarni 0x27c20, 0x27c20,
15493dde7c95SVishal Kulkarni 0x27c28, 0x27c30,
15503dde7c95SVishal Kulkarni 0x27c38, 0x27c38,
15513dde7c95SVishal Kulkarni 0x27c80, 0x27c98,
15523dde7c95SVishal Kulkarni 0x27ca0, 0x27ca8,
15533dde7c95SVishal Kulkarni 0x27cb0, 0x27cc8,
15543dde7c95SVishal Kulkarni 0x27cd0, 0x27cd4,
15553dde7c95SVishal Kulkarni 0x27ce0, 0x27ce8,
15563dde7c95SVishal Kulkarni 0x27cf0, 0x27cf0,
15573dde7c95SVishal Kulkarni 0x27cf8, 0x27d7c,
15583dde7c95SVishal Kulkarni 0x27e00, 0x27e04,
155956b2bdd1SGireesh Nagabhushana };
156056b2bdd1SGireesh Nagabhushana
15613dde7c95SVishal Kulkarni static const unsigned int t5_reg_ranges[] = {
15623dde7c95SVishal Kulkarni 0x1008, 0x10c0,
15633dde7c95SVishal Kulkarni 0x10cc, 0x10f8,
15643dde7c95SVishal Kulkarni 0x1100, 0x1100,
15653dde7c95SVishal Kulkarni 0x110c, 0x1148,
15663dde7c95SVishal Kulkarni 0x1180, 0x1184,
15673dde7c95SVishal Kulkarni 0x1190, 0x1194,
15683dde7c95SVishal Kulkarni 0x11a0, 0x11a4,
15693dde7c95SVishal Kulkarni 0x11b0, 0x11b4,
15703dde7c95SVishal Kulkarni 0x11fc, 0x123c,
15713dde7c95SVishal Kulkarni 0x1280, 0x173c,
15723dde7c95SVishal Kulkarni 0x1800, 0x18fc,
15733dde7c95SVishal Kulkarni 0x3000, 0x3028,
15743dde7c95SVishal Kulkarni 0x3060, 0x30b0,
15753dde7c95SVishal Kulkarni 0x30b8, 0x30d8,
15763dde7c95SVishal Kulkarni 0x30e0, 0x30fc,
15773dde7c95SVishal Kulkarni 0x3140, 0x357c,
15783dde7c95SVishal Kulkarni 0x35a8, 0x35cc,
15793dde7c95SVishal Kulkarni 0x35ec, 0x35ec,
15803dde7c95SVishal Kulkarni 0x3600, 0x5624,
15813dde7c95SVishal Kulkarni 0x56cc, 0x56ec,
15823dde7c95SVishal Kulkarni 0x56f4, 0x5720,
15833dde7c95SVishal Kulkarni 0x5728, 0x575c,
15843dde7c95SVishal Kulkarni 0x580c, 0x5814,
15853dde7c95SVishal Kulkarni 0x5890, 0x589c,
15863dde7c95SVishal Kulkarni 0x58a4, 0x58ac,
15873dde7c95SVishal Kulkarni 0x58b8, 0x58bc,
15883dde7c95SVishal Kulkarni 0x5940, 0x59c8,
15893dde7c95SVishal Kulkarni 0x59d0, 0x59dc,
15903dde7c95SVishal Kulkarni 0x59fc, 0x5a18,
15913dde7c95SVishal Kulkarni 0x5a60, 0x5a70,
15923dde7c95SVishal Kulkarni 0x5a80, 0x5a9c,
15933dde7c95SVishal Kulkarni 0x5b94, 0x5bfc,
15943dde7c95SVishal Kulkarni 0x6000, 0x6020,
15953dde7c95SVishal Kulkarni 0x6028, 0x6040,
15963dde7c95SVishal Kulkarni 0x6058, 0x609c,
15973dde7c95SVishal Kulkarni 0x60a8, 0x614c,
15983dde7c95SVishal Kulkarni 0x7700, 0x7798,
15993dde7c95SVishal Kulkarni 0x77c0, 0x78fc,
16003dde7c95SVishal Kulkarni 0x7b00, 0x7b58,
16013dde7c95SVishal Kulkarni 0x7b60, 0x7b84,
16023dde7c95SVishal Kulkarni 0x7b8c, 0x7c54,
16033dde7c95SVishal Kulkarni 0x7d00, 0x7d38,
16043dde7c95SVishal Kulkarni 0x7d40, 0x7d80,
16053dde7c95SVishal Kulkarni 0x7d8c, 0x7ddc,
16063dde7c95SVishal Kulkarni 0x7de4, 0x7e04,
16073dde7c95SVishal Kulkarni 0x7e10, 0x7e1c,
16083dde7c95SVishal Kulkarni 0x7e24, 0x7e38,
16093dde7c95SVishal Kulkarni 0x7e40, 0x7e44,
16103dde7c95SVishal Kulkarni 0x7e4c, 0x7e78,
16113dde7c95SVishal Kulkarni 0x7e80, 0x7edc,
16123dde7c95SVishal Kulkarni 0x7ee8, 0x7efc,
16133dde7c95SVishal Kulkarni 0x8dc0, 0x8de0,
16143dde7c95SVishal Kulkarni 0x8df8, 0x8e04,
16153dde7c95SVishal Kulkarni 0x8e10, 0x8e84,
16163dde7c95SVishal Kulkarni 0x8ea0, 0x8f84,
16173dde7c95SVishal Kulkarni 0x8fc0, 0x9058,
16183dde7c95SVishal Kulkarni 0x9060, 0x9060,
16193dde7c95SVishal Kulkarni 0x9068, 0x90f8,
16203dde7c95SVishal Kulkarni 0x9400, 0x9408,
16213dde7c95SVishal Kulkarni 0x9410, 0x9470,
16223dde7c95SVishal Kulkarni 0x9600, 0x9600,
16233dde7c95SVishal Kulkarni 0x9608, 0x9638,
16243dde7c95SVishal Kulkarni 0x9640, 0x96f4,
16253dde7c95SVishal Kulkarni 0x9800, 0x9808,
16263dde7c95SVishal Kulkarni 0x9820, 0x983c,
16273dde7c95SVishal Kulkarni 0x9850, 0x9864,
16283dde7c95SVishal Kulkarni 0x9c00, 0x9c6c,
16293dde7c95SVishal Kulkarni 0x9c80, 0x9cec,
16303dde7c95SVishal Kulkarni 0x9d00, 0x9d6c,
16313dde7c95SVishal Kulkarni 0x9d80, 0x9dec,
16323dde7c95SVishal Kulkarni 0x9e00, 0x9e6c,
16333dde7c95SVishal Kulkarni 0x9e80, 0x9eec,
16343dde7c95SVishal Kulkarni 0x9f00, 0x9f6c,
16353dde7c95SVishal Kulkarni 0x9f80, 0xa020,
16363dde7c95SVishal Kulkarni 0xd004, 0xd004,
16373dde7c95SVishal Kulkarni 0xd010, 0xd03c,
16383dde7c95SVishal Kulkarni 0xdfc0, 0xdfe0,
16393dde7c95SVishal Kulkarni 0xe000, 0x1106c,
16403dde7c95SVishal Kulkarni 0x11074, 0x11088,
16413dde7c95SVishal Kulkarni 0x1109c, 0x1117c,
16423dde7c95SVishal Kulkarni 0x11190, 0x11204,
16433dde7c95SVishal Kulkarni 0x19040, 0x1906c,
16443dde7c95SVishal Kulkarni 0x19078, 0x19080,
16453dde7c95SVishal Kulkarni 0x1908c, 0x190e8,
16463dde7c95SVishal Kulkarni 0x190f0, 0x190f8,
16473dde7c95SVishal Kulkarni 0x19100, 0x19110,
16483dde7c95SVishal Kulkarni 0x19120, 0x19124,
16493dde7c95SVishal Kulkarni 0x19150, 0x19194,
16503dde7c95SVishal Kulkarni 0x1919c, 0x191b0,
16513dde7c95SVishal Kulkarni 0x191d0, 0x191e8,
16523dde7c95SVishal Kulkarni 0x19238, 0x19290,
16533dde7c95SVishal Kulkarni 0x193f8, 0x19428,
16543dde7c95SVishal Kulkarni 0x19430, 0x19444,
16553dde7c95SVishal Kulkarni 0x1944c, 0x1946c,
16563dde7c95SVishal Kulkarni 0x19474, 0x19474,
16573dde7c95SVishal Kulkarni 0x19490, 0x194cc,
16583dde7c95SVishal Kulkarni 0x194f0, 0x194f8,
16593dde7c95SVishal Kulkarni 0x19c00, 0x19c08,
16603dde7c95SVishal Kulkarni 0x19c10, 0x19c60,
16613dde7c95SVishal Kulkarni 0x19c94, 0x19ce4,
16623dde7c95SVishal Kulkarni 0x19cf0, 0x19d40,
16633dde7c95SVishal Kulkarni 0x19d50, 0x19d94,
16643dde7c95SVishal Kulkarni 0x19da0, 0x19de8,
16653dde7c95SVishal Kulkarni 0x19df0, 0x19e10,
16663dde7c95SVishal Kulkarni 0x19e50, 0x19e90,
16673dde7c95SVishal Kulkarni 0x19ea0, 0x19f24,
16683dde7c95SVishal Kulkarni 0x19f34, 0x19f34,
16693dde7c95SVishal Kulkarni 0x19f40, 0x19f50,
16703dde7c95SVishal Kulkarni 0x19f90, 0x19fb4,
16713dde7c95SVishal Kulkarni 0x19fc4, 0x19fe4,
16723dde7c95SVishal Kulkarni 0x1a000, 0x1a004,
16733dde7c95SVishal Kulkarni 0x1a010, 0x1a06c,
16743dde7c95SVishal Kulkarni 0x1a0b0, 0x1a0e4,
16753dde7c95SVishal Kulkarni 0x1a0ec, 0x1a0f8,
16763dde7c95SVishal Kulkarni 0x1a100, 0x1a108,
16773dde7c95SVishal Kulkarni 0x1a114, 0x1a120,
16783dde7c95SVishal Kulkarni 0x1a128, 0x1a130,
16793dde7c95SVishal Kulkarni 0x1a138, 0x1a138,
16803dde7c95SVishal Kulkarni 0x1a190, 0x1a1c4,
16813dde7c95SVishal Kulkarni 0x1a1fc, 0x1a1fc,
16823dde7c95SVishal Kulkarni 0x1e008, 0x1e00c,
16833dde7c95SVishal Kulkarni 0x1e040, 0x1e044,
16843dde7c95SVishal Kulkarni 0x1e04c, 0x1e04c,
16853dde7c95SVishal Kulkarni 0x1e284, 0x1e290,
16863dde7c95SVishal Kulkarni 0x1e2c0, 0x1e2c0,
16873dde7c95SVishal Kulkarni 0x1e2e0, 0x1e2e0,
16883dde7c95SVishal Kulkarni 0x1e300, 0x1e384,
16893dde7c95SVishal Kulkarni 0x1e3c0, 0x1e3c8,
16903dde7c95SVishal Kulkarni 0x1e408, 0x1e40c,
16913dde7c95SVishal Kulkarni 0x1e440, 0x1e444,
16923dde7c95SVishal Kulkarni 0x1e44c, 0x1e44c,
16933dde7c95SVishal Kulkarni 0x1e684, 0x1e690,
16943dde7c95SVishal Kulkarni 0x1e6c0, 0x1e6c0,
16953dde7c95SVishal Kulkarni 0x1e6e0, 0x1e6e0,
16963dde7c95SVishal Kulkarni 0x1e700, 0x1e784,
16973dde7c95SVishal Kulkarni 0x1e7c0, 0x1e7c8,
16983dde7c95SVishal Kulkarni 0x1e808, 0x1e80c,
16993dde7c95SVishal Kulkarni 0x1e840, 0x1e844,
17003dde7c95SVishal Kulkarni 0x1e84c, 0x1e84c,
17013dde7c95SVishal Kulkarni 0x1ea84, 0x1ea90,
17023dde7c95SVishal Kulkarni 0x1eac0, 0x1eac0,
17033dde7c95SVishal Kulkarni 0x1eae0, 0x1eae0,
17043dde7c95SVishal Kulkarni 0x1eb00, 0x1eb84,
17053dde7c95SVishal Kulkarni 0x1ebc0, 0x1ebc8,
17063dde7c95SVishal Kulkarni 0x1ec08, 0x1ec0c,
17073dde7c95SVishal Kulkarni 0x1ec40, 0x1ec44,
17083dde7c95SVishal Kulkarni 0x1ec4c, 0x1ec4c,
17093dde7c95SVishal Kulkarni 0x1ee84, 0x1ee90,
17103dde7c95SVishal Kulkarni 0x1eec0, 0x1eec0,
17113dde7c95SVishal Kulkarni 0x1eee0, 0x1eee0,
17123dde7c95SVishal Kulkarni 0x1ef00, 0x1ef84,
17133dde7c95SVishal Kulkarni 0x1efc0, 0x1efc8,
17143dde7c95SVishal Kulkarni 0x1f008, 0x1f00c,
17153dde7c95SVishal Kulkarni 0x1f040, 0x1f044,
17163dde7c95SVishal Kulkarni 0x1f04c, 0x1f04c,
17173dde7c95SVishal Kulkarni 0x1f284, 0x1f290,
17183dde7c95SVishal Kulkarni 0x1f2c0, 0x1f2c0,
17193dde7c95SVishal Kulkarni 0x1f2e0, 0x1f2e0,
17203dde7c95SVishal Kulkarni 0x1f300, 0x1f384,
17213dde7c95SVishal Kulkarni 0x1f3c0, 0x1f3c8,
17223dde7c95SVishal Kulkarni 0x1f408, 0x1f40c,
17233dde7c95SVishal Kulkarni 0x1f440, 0x1f444,
17243dde7c95SVishal Kulkarni 0x1f44c, 0x1f44c,
17253dde7c95SVishal Kulkarni 0x1f684, 0x1f690,
17263dde7c95SVishal Kulkarni 0x1f6c0, 0x1f6c0,
17273dde7c95SVishal Kulkarni 0x1f6e0, 0x1f6e0,
17283dde7c95SVishal Kulkarni 0x1f700, 0x1f784,
17293dde7c95SVishal Kulkarni 0x1f7c0, 0x1f7c8,
17303dde7c95SVishal Kulkarni 0x1f808, 0x1f80c,
17313dde7c95SVishal Kulkarni 0x1f840, 0x1f844,
17323dde7c95SVishal Kulkarni 0x1f84c, 0x1f84c,
17333dde7c95SVishal Kulkarni 0x1fa84, 0x1fa90,
17343dde7c95SVishal Kulkarni 0x1fac0, 0x1fac0,
17353dde7c95SVishal Kulkarni 0x1fae0, 0x1fae0,
17363dde7c95SVishal Kulkarni 0x1fb00, 0x1fb84,
17373dde7c95SVishal Kulkarni 0x1fbc0, 0x1fbc8,
17383dde7c95SVishal Kulkarni 0x1fc08, 0x1fc0c,
17393dde7c95SVishal Kulkarni 0x1fc40, 0x1fc44,
17403dde7c95SVishal Kulkarni 0x1fc4c, 0x1fc4c,
17413dde7c95SVishal Kulkarni 0x1fe84, 0x1fe90,
17423dde7c95SVishal Kulkarni 0x1fec0, 0x1fec0,
17433dde7c95SVishal Kulkarni 0x1fee0, 0x1fee0,
17443dde7c95SVishal Kulkarni 0x1ff00, 0x1ff84,
17453dde7c95SVishal Kulkarni 0x1ffc0, 0x1ffc8,
17463dde7c95SVishal Kulkarni 0x30000, 0x30030,
17473dde7c95SVishal Kulkarni 0x30100, 0x30144,
17483dde7c95SVishal Kulkarni 0x30190, 0x301a0,
17493dde7c95SVishal Kulkarni 0x301a8, 0x301b8,
17503dde7c95SVishal Kulkarni 0x301c4, 0x301c8,
17513dde7c95SVishal Kulkarni 0x301d0, 0x301d0,
17523dde7c95SVishal Kulkarni 0x30200, 0x30318,
17533dde7c95SVishal Kulkarni 0x30400, 0x304b4,
17543dde7c95SVishal Kulkarni 0x304c0, 0x3052c,
17553dde7c95SVishal Kulkarni 0x30540, 0x3061c,
17563dde7c95SVishal Kulkarni 0x30800, 0x30828,
17573dde7c95SVishal Kulkarni 0x30834, 0x30834,
17583dde7c95SVishal Kulkarni 0x308c0, 0x30908,
17593dde7c95SVishal Kulkarni 0x30910, 0x309ac,
17603dde7c95SVishal Kulkarni 0x30a00, 0x30a14,
17613dde7c95SVishal Kulkarni 0x30a1c, 0x30a2c,
17623dde7c95SVishal Kulkarni 0x30a44, 0x30a50,
17633dde7c95SVishal Kulkarni 0x30a74, 0x30a74,
17643dde7c95SVishal Kulkarni 0x30a7c, 0x30afc,
17653dde7c95SVishal Kulkarni 0x30b08, 0x30c24,
17663dde7c95SVishal Kulkarni 0x30d00, 0x30d00,
17673dde7c95SVishal Kulkarni 0x30d08, 0x30d14,
17683dde7c95SVishal Kulkarni 0x30d1c, 0x30d20,
17693dde7c95SVishal Kulkarni 0x30d3c, 0x30d3c,
17703dde7c95SVishal Kulkarni 0x30d48, 0x30d50,
17713dde7c95SVishal Kulkarni 0x31200, 0x3120c,
17723dde7c95SVishal Kulkarni 0x31220, 0x31220,
17733dde7c95SVishal Kulkarni 0x31240, 0x31240,
17743dde7c95SVishal Kulkarni 0x31600, 0x3160c,
17753dde7c95SVishal Kulkarni 0x31a00, 0x31a1c,
17763dde7c95SVishal Kulkarni 0x31e00, 0x31e20,
17773dde7c95SVishal Kulkarni 0x31e38, 0x31e3c,
17783dde7c95SVishal Kulkarni 0x31e80, 0x31e80,
17793dde7c95SVishal Kulkarni 0x31e88, 0x31ea8,
17803dde7c95SVishal Kulkarni 0x31eb0, 0x31eb4,
17813dde7c95SVishal Kulkarni 0x31ec8, 0x31ed4,
17823dde7c95SVishal Kulkarni 0x31fb8, 0x32004,
17833dde7c95SVishal Kulkarni 0x32200, 0x32200,
17843dde7c95SVishal Kulkarni 0x32208, 0x32240,
17853dde7c95SVishal Kulkarni 0x32248, 0x32280,
17863dde7c95SVishal Kulkarni 0x32288, 0x322c0,
17873dde7c95SVishal Kulkarni 0x322c8, 0x322fc,
17883dde7c95SVishal Kulkarni 0x32600, 0x32630,
17893dde7c95SVishal Kulkarni 0x32a00, 0x32abc,
17903dde7c95SVishal Kulkarni 0x32b00, 0x32b10,
17913dde7c95SVishal Kulkarni 0x32b20, 0x32b30,
17923dde7c95SVishal Kulkarni 0x32b40, 0x32b50,
17933dde7c95SVishal Kulkarni 0x32b60, 0x32b70,
17943dde7c95SVishal Kulkarni 0x33000, 0x33028,
17953dde7c95SVishal Kulkarni 0x33030, 0x33048,
17963dde7c95SVishal Kulkarni 0x33060, 0x33068,
17973dde7c95SVishal Kulkarni 0x33070, 0x3309c,
17983dde7c95SVishal Kulkarni 0x330f0, 0x33128,
17993dde7c95SVishal Kulkarni 0x33130, 0x33148,
18003dde7c95SVishal Kulkarni 0x33160, 0x33168,
18013dde7c95SVishal Kulkarni 0x33170, 0x3319c,
18023dde7c95SVishal Kulkarni 0x331f0, 0x33238,
18033dde7c95SVishal Kulkarni 0x33240, 0x33240,
18043dde7c95SVishal Kulkarni 0x33248, 0x33250,
18053dde7c95SVishal Kulkarni 0x3325c, 0x33264,
18063dde7c95SVishal Kulkarni 0x33270, 0x332b8,
18073dde7c95SVishal Kulkarni 0x332c0, 0x332e4,
18083dde7c95SVishal Kulkarni 0x332f8, 0x33338,
18093dde7c95SVishal Kulkarni 0x33340, 0x33340,
18103dde7c95SVishal Kulkarni 0x33348, 0x33350,
18113dde7c95SVishal Kulkarni 0x3335c, 0x33364,
18123dde7c95SVishal Kulkarni 0x33370, 0x333b8,
18133dde7c95SVishal Kulkarni 0x333c0, 0x333e4,
18143dde7c95SVishal Kulkarni 0x333f8, 0x33428,
18153dde7c95SVishal Kulkarni 0x33430, 0x33448,
18163dde7c95SVishal Kulkarni 0x33460, 0x33468,
18173dde7c95SVishal Kulkarni 0x33470, 0x3349c,
18183dde7c95SVishal Kulkarni 0x334f0, 0x33528,
18193dde7c95SVishal Kulkarni 0x33530, 0x33548,
18203dde7c95SVishal Kulkarni 0x33560, 0x33568,
18213dde7c95SVishal Kulkarni 0x33570, 0x3359c,
18223dde7c95SVishal Kulkarni 0x335f0, 0x33638,
18233dde7c95SVishal Kulkarni 0x33640, 0x33640,
18243dde7c95SVishal Kulkarni 0x33648, 0x33650,
18253dde7c95SVishal Kulkarni 0x3365c, 0x33664,
18263dde7c95SVishal Kulkarni 0x33670, 0x336b8,
18273dde7c95SVishal Kulkarni 0x336c0, 0x336e4,
18283dde7c95SVishal Kulkarni 0x336f8, 0x33738,
18293dde7c95SVishal Kulkarni 0x33740, 0x33740,
18303dde7c95SVishal Kulkarni 0x33748, 0x33750,
18313dde7c95SVishal Kulkarni 0x3375c, 0x33764,
18323dde7c95SVishal Kulkarni 0x33770, 0x337b8,
18333dde7c95SVishal Kulkarni 0x337c0, 0x337e4,
18343dde7c95SVishal Kulkarni 0x337f8, 0x337fc,
18353dde7c95SVishal Kulkarni 0x33814, 0x33814,
18363dde7c95SVishal Kulkarni 0x3382c, 0x3382c,
18373dde7c95SVishal Kulkarni 0x33880, 0x3388c,
18383dde7c95SVishal Kulkarni 0x338e8, 0x338ec,
18393dde7c95SVishal Kulkarni 0x33900, 0x33928,
18403dde7c95SVishal Kulkarni 0x33930, 0x33948,
18413dde7c95SVishal Kulkarni 0x33960, 0x33968,
18423dde7c95SVishal Kulkarni 0x33970, 0x3399c,
18433dde7c95SVishal Kulkarni 0x339f0, 0x33a38,
18443dde7c95SVishal Kulkarni 0x33a40, 0x33a40,
18453dde7c95SVishal Kulkarni 0x33a48, 0x33a50,
18463dde7c95SVishal Kulkarni 0x33a5c, 0x33a64,
18473dde7c95SVishal Kulkarni 0x33a70, 0x33ab8,
18483dde7c95SVishal Kulkarni 0x33ac0, 0x33ae4,
18493dde7c95SVishal Kulkarni 0x33af8, 0x33b10,
18503dde7c95SVishal Kulkarni 0x33b28, 0x33b28,
18513dde7c95SVishal Kulkarni 0x33b3c, 0x33b50,
18523dde7c95SVishal Kulkarni 0x33bf0, 0x33c10,
18533dde7c95SVishal Kulkarni 0x33c28, 0x33c28,
18543dde7c95SVishal Kulkarni 0x33c3c, 0x33c50,
18553dde7c95SVishal Kulkarni 0x33cf0, 0x33cfc,
18563dde7c95SVishal Kulkarni 0x34000, 0x34030,
18573dde7c95SVishal Kulkarni 0x34100, 0x34144,
18583dde7c95SVishal Kulkarni 0x34190, 0x341a0,
18593dde7c95SVishal Kulkarni 0x341a8, 0x341b8,
18603dde7c95SVishal Kulkarni 0x341c4, 0x341c8,
18613dde7c95SVishal Kulkarni 0x341d0, 0x341d0,
18623dde7c95SVishal Kulkarni 0x34200, 0x34318,
18633dde7c95SVishal Kulkarni 0x34400, 0x344b4,
18643dde7c95SVishal Kulkarni 0x344c0, 0x3452c,
18653dde7c95SVishal Kulkarni 0x34540, 0x3461c,
18663dde7c95SVishal Kulkarni 0x34800, 0x34828,
18673dde7c95SVishal Kulkarni 0x34834, 0x34834,
18683dde7c95SVishal Kulkarni 0x348c0, 0x34908,
18693dde7c95SVishal Kulkarni 0x34910, 0x349ac,
18703dde7c95SVishal Kulkarni 0x34a00, 0x34a14,
18713dde7c95SVishal Kulkarni 0x34a1c, 0x34a2c,
18723dde7c95SVishal Kulkarni 0x34a44, 0x34a50,
18733dde7c95SVishal Kulkarni 0x34a74, 0x34a74,
18743dde7c95SVishal Kulkarni 0x34a7c, 0x34afc,
18753dde7c95SVishal Kulkarni 0x34b08, 0x34c24,
18763dde7c95SVishal Kulkarni 0x34d00, 0x34d00,
18773dde7c95SVishal Kulkarni 0x34d08, 0x34d14,
18783dde7c95SVishal Kulkarni 0x34d1c, 0x34d20,
18793dde7c95SVishal Kulkarni 0x34d3c, 0x34d3c,
18803dde7c95SVishal Kulkarni 0x34d48, 0x34d50,
18813dde7c95SVishal Kulkarni 0x35200, 0x3520c,
18823dde7c95SVishal Kulkarni 0x35220, 0x35220,
18833dde7c95SVishal Kulkarni 0x35240, 0x35240,
18843dde7c95SVishal Kulkarni 0x35600, 0x3560c,
18853dde7c95SVishal Kulkarni 0x35a00, 0x35a1c,
18863dde7c95SVishal Kulkarni 0x35e00, 0x35e20,
18873dde7c95SVishal Kulkarni 0x35e38, 0x35e3c,
18883dde7c95SVishal Kulkarni 0x35e80, 0x35e80,
18893dde7c95SVishal Kulkarni 0x35e88, 0x35ea8,
18903dde7c95SVishal Kulkarni 0x35eb0, 0x35eb4,
18913dde7c95SVishal Kulkarni 0x35ec8, 0x35ed4,
18923dde7c95SVishal Kulkarni 0x35fb8, 0x36004,
18933dde7c95SVishal Kulkarni 0x36200, 0x36200,
18943dde7c95SVishal Kulkarni 0x36208, 0x36240,
18953dde7c95SVishal Kulkarni 0x36248, 0x36280,
18963dde7c95SVishal Kulkarni 0x36288, 0x362c0,
18973dde7c95SVishal Kulkarni 0x362c8, 0x362fc,
18983dde7c95SVishal Kulkarni 0x36600, 0x36630,
18993dde7c95SVishal Kulkarni 0x36a00, 0x36abc,
19003dde7c95SVishal Kulkarni 0x36b00, 0x36b10,
19013dde7c95SVishal Kulkarni 0x36b20, 0x36b30,
19023dde7c95SVishal Kulkarni 0x36b40, 0x36b50,
19033dde7c95SVishal Kulkarni 0x36b60, 0x36b70,
19043dde7c95SVishal Kulkarni 0x37000, 0x37028,
19053dde7c95SVishal Kulkarni 0x37030, 0x37048,
19063dde7c95SVishal Kulkarni 0x37060, 0x37068,
19073dde7c95SVishal Kulkarni 0x37070, 0x3709c,
19083dde7c95SVishal Kulkarni 0x370f0, 0x37128,
19093dde7c95SVishal Kulkarni 0x37130, 0x37148,
19103dde7c95SVishal Kulkarni 0x37160, 0x37168,
19113dde7c95SVishal Kulkarni 0x37170, 0x3719c,
19123dde7c95SVishal Kulkarni 0x371f0, 0x37238,
19133dde7c95SVishal Kulkarni 0x37240, 0x37240,
19143dde7c95SVishal Kulkarni 0x37248, 0x37250,
19153dde7c95SVishal Kulkarni 0x3725c, 0x37264,
19163dde7c95SVishal Kulkarni 0x37270, 0x372b8,
19173dde7c95SVishal Kulkarni 0x372c0, 0x372e4,
19183dde7c95SVishal Kulkarni 0x372f8, 0x37338,
19193dde7c95SVishal Kulkarni 0x37340, 0x37340,
19203dde7c95SVishal Kulkarni 0x37348, 0x37350,
19213dde7c95SVishal Kulkarni 0x3735c, 0x37364,
19223dde7c95SVishal Kulkarni 0x37370, 0x373b8,
19233dde7c95SVishal Kulkarni 0x373c0, 0x373e4,
19243dde7c95SVishal Kulkarni 0x373f8, 0x37428,
19253dde7c95SVishal Kulkarni 0x37430, 0x37448,
19263dde7c95SVishal Kulkarni 0x37460, 0x37468,
19273dde7c95SVishal Kulkarni 0x37470, 0x3749c,
19283dde7c95SVishal Kulkarni 0x374f0, 0x37528,
19293dde7c95SVishal Kulkarni 0x37530, 0x37548,
19303dde7c95SVishal Kulkarni 0x37560, 0x37568,
19313dde7c95SVishal Kulkarni 0x37570, 0x3759c,
19323dde7c95SVishal Kulkarni 0x375f0, 0x37638,
19333dde7c95SVishal Kulkarni 0x37640, 0x37640,
19343dde7c95SVishal Kulkarni 0x37648, 0x37650,
19353dde7c95SVishal Kulkarni 0x3765c, 0x37664,
19363dde7c95SVishal Kulkarni 0x37670, 0x376b8,
19373dde7c95SVishal Kulkarni 0x376c0, 0x376e4,
19383dde7c95SVishal Kulkarni 0x376f8, 0x37738,
19393dde7c95SVishal Kulkarni 0x37740, 0x37740,
19403dde7c95SVishal Kulkarni 0x37748, 0x37750,
19413dde7c95SVishal Kulkarni 0x3775c, 0x37764,
19423dde7c95SVishal Kulkarni 0x37770, 0x377b8,
19433dde7c95SVishal Kulkarni 0x377c0, 0x377e4,
19443dde7c95SVishal Kulkarni 0x377f8, 0x377fc,
19453dde7c95SVishal Kulkarni 0x37814, 0x37814,
19463dde7c95SVishal Kulkarni 0x3782c, 0x3782c,
19473dde7c95SVishal Kulkarni 0x37880, 0x3788c,
19483dde7c95SVishal Kulkarni 0x378e8, 0x378ec,
19493dde7c95SVishal Kulkarni 0x37900, 0x37928,
19503dde7c95SVishal Kulkarni 0x37930, 0x37948,
19513dde7c95SVishal Kulkarni 0x37960, 0x37968,
19523dde7c95SVishal Kulkarni 0x37970, 0x3799c,
19533dde7c95SVishal Kulkarni 0x379f0, 0x37a38,
19543dde7c95SVishal Kulkarni 0x37a40, 0x37a40,
19553dde7c95SVishal Kulkarni 0x37a48, 0x37a50,
19563dde7c95SVishal Kulkarni 0x37a5c, 0x37a64,
19573dde7c95SVishal Kulkarni 0x37a70, 0x37ab8,
19583dde7c95SVishal Kulkarni 0x37ac0, 0x37ae4,
19593dde7c95SVishal Kulkarni 0x37af8, 0x37b10,
19603dde7c95SVishal Kulkarni 0x37b28, 0x37b28,
19613dde7c95SVishal Kulkarni 0x37b3c, 0x37b50,
19623dde7c95SVishal Kulkarni 0x37bf0, 0x37c10,
19633dde7c95SVishal Kulkarni 0x37c28, 0x37c28,
19643dde7c95SVishal Kulkarni 0x37c3c, 0x37c50,
19653dde7c95SVishal Kulkarni 0x37cf0, 0x37cfc,
19663dde7c95SVishal Kulkarni 0x38000, 0x38030,
19673dde7c95SVishal Kulkarni 0x38100, 0x38144,
19683dde7c95SVishal Kulkarni 0x38190, 0x381a0,
19693dde7c95SVishal Kulkarni 0x381a8, 0x381b8,
19703dde7c95SVishal Kulkarni 0x381c4, 0x381c8,
19713dde7c95SVishal Kulkarni 0x381d0, 0x381d0,
19723dde7c95SVishal Kulkarni 0x38200, 0x38318,
19733dde7c95SVishal Kulkarni 0x38400, 0x384b4,
19743dde7c95SVishal Kulkarni 0x384c0, 0x3852c,
19753dde7c95SVishal Kulkarni 0x38540, 0x3861c,
19763dde7c95SVishal Kulkarni 0x38800, 0x38828,
19773dde7c95SVishal Kulkarni 0x38834, 0x38834,
19783dde7c95SVishal Kulkarni 0x388c0, 0x38908,
19793dde7c95SVishal Kulkarni 0x38910, 0x389ac,
19803dde7c95SVishal Kulkarni 0x38a00, 0x38a14,
19813dde7c95SVishal Kulkarni 0x38a1c, 0x38a2c,
19823dde7c95SVishal Kulkarni 0x38a44, 0x38a50,
19833dde7c95SVishal Kulkarni 0x38a74, 0x38a74,
19843dde7c95SVishal Kulkarni 0x38a7c, 0x38afc,
19853dde7c95SVishal Kulkarni 0x38b08, 0x38c24,
19863dde7c95SVishal Kulkarni 0x38d00, 0x38d00,
19873dde7c95SVishal Kulkarni 0x38d08, 0x38d14,
19883dde7c95SVishal Kulkarni 0x38d1c, 0x38d20,
19893dde7c95SVishal Kulkarni 0x38d3c, 0x38d3c,
19903dde7c95SVishal Kulkarni 0x38d48, 0x38d50,
19913dde7c95SVishal Kulkarni 0x39200, 0x3920c,
19923dde7c95SVishal Kulkarni 0x39220, 0x39220,
19933dde7c95SVishal Kulkarni 0x39240, 0x39240,
19943dde7c95SVishal Kulkarni 0x39600, 0x3960c,
19953dde7c95SVishal Kulkarni 0x39a00, 0x39a1c,
19963dde7c95SVishal Kulkarni 0x39e00, 0x39e20,
19973dde7c95SVishal Kulkarni 0x39e38, 0x39e3c,
19983dde7c95SVishal Kulkarni 0x39e80, 0x39e80,
19993dde7c95SVishal Kulkarni 0x39e88, 0x39ea8,
20003dde7c95SVishal Kulkarni 0x39eb0, 0x39eb4,
20013dde7c95SVishal Kulkarni 0x39ec8, 0x39ed4,
20023dde7c95SVishal Kulkarni 0x39fb8, 0x3a004,
20033dde7c95SVishal Kulkarni 0x3a200, 0x3a200,
20043dde7c95SVishal Kulkarni 0x3a208, 0x3a240,
20053dde7c95SVishal Kulkarni 0x3a248, 0x3a280,
20063dde7c95SVishal Kulkarni 0x3a288, 0x3a2c0,
20073dde7c95SVishal Kulkarni 0x3a2c8, 0x3a2fc,
20083dde7c95SVishal Kulkarni 0x3a600, 0x3a630,
20093dde7c95SVishal Kulkarni 0x3aa00, 0x3aabc,
20103dde7c95SVishal Kulkarni 0x3ab00, 0x3ab10,
20113dde7c95SVishal Kulkarni 0x3ab20, 0x3ab30,
20123dde7c95SVishal Kulkarni 0x3ab40, 0x3ab50,
20133dde7c95SVishal Kulkarni 0x3ab60, 0x3ab70,
20143dde7c95SVishal Kulkarni 0x3b000, 0x3b028,
20153dde7c95SVishal Kulkarni 0x3b030, 0x3b048,
20163dde7c95SVishal Kulkarni 0x3b060, 0x3b068,
20173dde7c95SVishal Kulkarni 0x3b070, 0x3b09c,
20183dde7c95SVishal Kulkarni 0x3b0f0, 0x3b128,
20193dde7c95SVishal Kulkarni 0x3b130, 0x3b148,
20203dde7c95SVishal Kulkarni 0x3b160, 0x3b168,
20213dde7c95SVishal Kulkarni 0x3b170, 0x3b19c,
20223dde7c95SVishal Kulkarni 0x3b1f0, 0x3b238,
20233dde7c95SVishal Kulkarni 0x3b240, 0x3b240,
20243dde7c95SVishal Kulkarni 0x3b248, 0x3b250,
20253dde7c95SVishal Kulkarni 0x3b25c, 0x3b264,
20263dde7c95SVishal Kulkarni 0x3b270, 0x3b2b8,
20273dde7c95SVishal Kulkarni 0x3b2c0, 0x3b2e4,
20283dde7c95SVishal Kulkarni 0x3b2f8, 0x3b338,
20293dde7c95SVishal Kulkarni 0x3b340, 0x3b340,
20303dde7c95SVishal Kulkarni 0x3b348, 0x3b350,
20313dde7c95SVishal Kulkarni 0x3b35c, 0x3b364,
20323dde7c95SVishal Kulkarni 0x3b370, 0x3b3b8,
20333dde7c95SVishal Kulkarni 0x3b3c0, 0x3b3e4,
20343dde7c95SVishal Kulkarni 0x3b3f8, 0x3b428,
20353dde7c95SVishal Kulkarni 0x3b430, 0x3b448,
20363dde7c95SVishal Kulkarni 0x3b460, 0x3b468,
20373dde7c95SVishal Kulkarni 0x3b470, 0x3b49c,
20383dde7c95SVishal Kulkarni 0x3b4f0, 0x3b528,
20393dde7c95SVishal Kulkarni 0x3b530, 0x3b548,
20403dde7c95SVishal Kulkarni 0x3b560, 0x3b568,
20413dde7c95SVishal Kulkarni 0x3b570, 0x3b59c,
20423dde7c95SVishal Kulkarni 0x3b5f0, 0x3b638,
20433dde7c95SVishal Kulkarni 0x3b640, 0x3b640,
20443dde7c95SVishal Kulkarni 0x3b648, 0x3b650,
20453dde7c95SVishal Kulkarni 0x3b65c, 0x3b664,
20463dde7c95SVishal Kulkarni 0x3b670, 0x3b6b8,
20473dde7c95SVishal Kulkarni 0x3b6c0, 0x3b6e4,
20483dde7c95SVishal Kulkarni 0x3b6f8, 0x3b738,
20493dde7c95SVishal Kulkarni 0x3b740, 0x3b740,
20503dde7c95SVishal Kulkarni 0x3b748, 0x3b750,
20513dde7c95SVishal Kulkarni 0x3b75c, 0x3b764,
20523dde7c95SVishal Kulkarni 0x3b770, 0x3b7b8,
20533dde7c95SVishal Kulkarni 0x3b7c0, 0x3b7e4,
20543dde7c95SVishal Kulkarni 0x3b7f8, 0x3b7fc,
20553dde7c95SVishal Kulkarni 0x3b814, 0x3b814,
20563dde7c95SVishal Kulkarni 0x3b82c, 0x3b82c,
20573dde7c95SVishal Kulkarni 0x3b880, 0x3b88c,
20583dde7c95SVishal Kulkarni 0x3b8e8, 0x3b8ec,
20593dde7c95SVishal Kulkarni 0x3b900, 0x3b928,
20603dde7c95SVishal Kulkarni 0x3b930, 0x3b948,
20613dde7c95SVishal Kulkarni 0x3b960, 0x3b968,
20623dde7c95SVishal Kulkarni 0x3b970, 0x3b99c,
20633dde7c95SVishal Kulkarni 0x3b9f0, 0x3ba38,
20643dde7c95SVishal Kulkarni 0x3ba40, 0x3ba40,
20653dde7c95SVishal Kulkarni 0x3ba48, 0x3ba50,
20663dde7c95SVishal Kulkarni 0x3ba5c, 0x3ba64,
20673dde7c95SVishal Kulkarni 0x3ba70, 0x3bab8,
20683dde7c95SVishal Kulkarni 0x3bac0, 0x3bae4,
20693dde7c95SVishal Kulkarni 0x3baf8, 0x3bb10,
20703dde7c95SVishal Kulkarni 0x3bb28, 0x3bb28,
20713dde7c95SVishal Kulkarni 0x3bb3c, 0x3bb50,
20723dde7c95SVishal Kulkarni 0x3bbf0, 0x3bc10,
20733dde7c95SVishal Kulkarni 0x3bc28, 0x3bc28,
20743dde7c95SVishal Kulkarni 0x3bc3c, 0x3bc50,
20753dde7c95SVishal Kulkarni 0x3bcf0, 0x3bcfc,
20763dde7c95SVishal Kulkarni 0x3c000, 0x3c030,
20773dde7c95SVishal Kulkarni 0x3c100, 0x3c144,
20783dde7c95SVishal Kulkarni 0x3c190, 0x3c1a0,
20793dde7c95SVishal Kulkarni 0x3c1a8, 0x3c1b8,
20803dde7c95SVishal Kulkarni 0x3c1c4, 0x3c1c8,
20813dde7c95SVishal Kulkarni 0x3c1d0, 0x3c1d0,
20823dde7c95SVishal Kulkarni 0x3c200, 0x3c318,
20833dde7c95SVishal Kulkarni 0x3c400, 0x3c4b4,
20843dde7c95SVishal Kulkarni 0x3c4c0, 0x3c52c,
20853dde7c95SVishal Kulkarni 0x3c540, 0x3c61c,
20863dde7c95SVishal Kulkarni 0x3c800, 0x3c828,
20873dde7c95SVishal Kulkarni 0x3c834, 0x3c834,
20883dde7c95SVishal Kulkarni 0x3c8c0, 0x3c908,
20893dde7c95SVishal Kulkarni 0x3c910, 0x3c9ac,
20903dde7c95SVishal Kulkarni 0x3ca00, 0x3ca14,
20913dde7c95SVishal Kulkarni 0x3ca1c, 0x3ca2c,
20923dde7c95SVishal Kulkarni 0x3ca44, 0x3ca50,
20933dde7c95SVishal Kulkarni 0x3ca74, 0x3ca74,
20943dde7c95SVishal Kulkarni 0x3ca7c, 0x3cafc,
20953dde7c95SVishal Kulkarni 0x3cb08, 0x3cc24,
20963dde7c95SVishal Kulkarni 0x3cd00, 0x3cd00,
20973dde7c95SVishal Kulkarni 0x3cd08, 0x3cd14,
20983dde7c95SVishal Kulkarni 0x3cd1c, 0x3cd20,
20993dde7c95SVishal Kulkarni 0x3cd3c, 0x3cd3c,
21003dde7c95SVishal Kulkarni 0x3cd48, 0x3cd50,
21013dde7c95SVishal Kulkarni 0x3d200, 0x3d20c,
21023dde7c95SVishal Kulkarni 0x3d220, 0x3d220,
21033dde7c95SVishal Kulkarni 0x3d240, 0x3d240,
21043dde7c95SVishal Kulkarni 0x3d600, 0x3d60c,
21053dde7c95SVishal Kulkarni 0x3da00, 0x3da1c,
21063dde7c95SVishal Kulkarni 0x3de00, 0x3de20,
21073dde7c95SVishal Kulkarni 0x3de38, 0x3de3c,
21083dde7c95SVishal Kulkarni 0x3de80, 0x3de80,
21093dde7c95SVishal Kulkarni 0x3de88, 0x3dea8,
21103dde7c95SVishal Kulkarni 0x3deb0, 0x3deb4,
21113dde7c95SVishal Kulkarni 0x3dec8, 0x3ded4,
21123dde7c95SVishal Kulkarni 0x3dfb8, 0x3e004,
21133dde7c95SVishal Kulkarni 0x3e200, 0x3e200,
21143dde7c95SVishal Kulkarni 0x3e208, 0x3e240,
21153dde7c95SVishal Kulkarni 0x3e248, 0x3e280,
21163dde7c95SVishal Kulkarni 0x3e288, 0x3e2c0,
21173dde7c95SVishal Kulkarni 0x3e2c8, 0x3e2fc,
21183dde7c95SVishal Kulkarni 0x3e600, 0x3e630,
21193dde7c95SVishal Kulkarni 0x3ea00, 0x3eabc,
21203dde7c95SVishal Kulkarni 0x3eb00, 0x3eb10,
21213dde7c95SVishal Kulkarni 0x3eb20, 0x3eb30,
21223dde7c95SVishal Kulkarni 0x3eb40, 0x3eb50,
21233dde7c95SVishal Kulkarni 0x3eb60, 0x3eb70,
21243dde7c95SVishal Kulkarni 0x3f000, 0x3f028,
21253dde7c95SVishal Kulkarni 0x3f030, 0x3f048,
21263dde7c95SVishal Kulkarni 0x3f060, 0x3f068,
21273dde7c95SVishal Kulkarni 0x3f070, 0x3f09c,
21283dde7c95SVishal Kulkarni 0x3f0f0, 0x3f128,
21293dde7c95SVishal Kulkarni 0x3f130, 0x3f148,
21303dde7c95SVishal Kulkarni 0x3f160, 0x3f168,
21313dde7c95SVishal Kulkarni 0x3f170, 0x3f19c,
21323dde7c95SVishal Kulkarni 0x3f1f0, 0x3f238,
21333dde7c95SVishal Kulkarni 0x3f240, 0x3f240,
21343dde7c95SVishal Kulkarni 0x3f248, 0x3f250,
21353dde7c95SVishal Kulkarni 0x3f25c, 0x3f264,
21363dde7c95SVishal Kulkarni 0x3f270, 0x3f2b8,
21373dde7c95SVishal Kulkarni 0x3f2c0, 0x3f2e4,
21383dde7c95SVishal Kulkarni 0x3f2f8, 0x3f338,
21393dde7c95SVishal Kulkarni 0x3f340, 0x3f340,
21403dde7c95SVishal Kulkarni 0x3f348, 0x3f350,
21413dde7c95SVishal Kulkarni 0x3f35c, 0x3f364,
21423dde7c95SVishal Kulkarni 0x3f370, 0x3f3b8,
21433dde7c95SVishal Kulkarni 0x3f3c0, 0x3f3e4,
21443dde7c95SVishal Kulkarni 0x3f3f8, 0x3f428,
21453dde7c95SVishal Kulkarni 0x3f430, 0x3f448,
21463dde7c95SVishal Kulkarni 0x3f460, 0x3f468,
21473dde7c95SVishal Kulkarni 0x3f470, 0x3f49c,
21483dde7c95SVishal Kulkarni 0x3f4f0, 0x3f528,
21493dde7c95SVishal Kulkarni 0x3f530, 0x3f548,
21503dde7c95SVishal Kulkarni 0x3f560, 0x3f568,
21513dde7c95SVishal Kulkarni 0x3f570, 0x3f59c,
21523dde7c95SVishal Kulkarni 0x3f5f0, 0x3f638,
21533dde7c95SVishal Kulkarni 0x3f640, 0x3f640,
21543dde7c95SVishal Kulkarni 0x3f648, 0x3f650,
21553dde7c95SVishal Kulkarni 0x3f65c, 0x3f664,
21563dde7c95SVishal Kulkarni 0x3f670, 0x3f6b8,
21573dde7c95SVishal Kulkarni 0x3f6c0, 0x3f6e4,
21583dde7c95SVishal Kulkarni 0x3f6f8, 0x3f738,
21593dde7c95SVishal Kulkarni 0x3f740, 0x3f740,
21603dde7c95SVishal Kulkarni 0x3f748, 0x3f750,
21613dde7c95SVishal Kulkarni 0x3f75c, 0x3f764,
21623dde7c95SVishal Kulkarni 0x3f770, 0x3f7b8,
21633dde7c95SVishal Kulkarni 0x3f7c0, 0x3f7e4,
21643dde7c95SVishal Kulkarni 0x3f7f8, 0x3f7fc,
21653dde7c95SVishal Kulkarni 0x3f814, 0x3f814,
21663dde7c95SVishal Kulkarni 0x3f82c, 0x3f82c,
21673dde7c95SVishal Kulkarni 0x3f880, 0x3f88c,
21683dde7c95SVishal Kulkarni 0x3f8e8, 0x3f8ec,
21693dde7c95SVishal Kulkarni 0x3f900, 0x3f928,
21703dde7c95SVishal Kulkarni 0x3f930, 0x3f948,
21713dde7c95SVishal Kulkarni 0x3f960, 0x3f968,
21723dde7c95SVishal Kulkarni 0x3f970, 0x3f99c,
21733dde7c95SVishal Kulkarni 0x3f9f0, 0x3fa38,
21743dde7c95SVishal Kulkarni 0x3fa40, 0x3fa40,
21753dde7c95SVishal Kulkarni 0x3fa48, 0x3fa50,
21763dde7c95SVishal Kulkarni 0x3fa5c, 0x3fa64,
21773dde7c95SVishal Kulkarni 0x3fa70, 0x3fab8,
21783dde7c95SVishal Kulkarni 0x3fac0, 0x3fae4,
21793dde7c95SVishal Kulkarni 0x3faf8, 0x3fb10,
21803dde7c95SVishal Kulkarni 0x3fb28, 0x3fb28,
21813dde7c95SVishal Kulkarni 0x3fb3c, 0x3fb50,
21823dde7c95SVishal Kulkarni 0x3fbf0, 0x3fc10,
21833dde7c95SVishal Kulkarni 0x3fc28, 0x3fc28,
21843dde7c95SVishal Kulkarni 0x3fc3c, 0x3fc50,
21853dde7c95SVishal Kulkarni 0x3fcf0, 0x3fcfc,
21863dde7c95SVishal Kulkarni 0x40000, 0x4000c,
21873dde7c95SVishal Kulkarni 0x40040, 0x40050,
21883dde7c95SVishal Kulkarni 0x40060, 0x40068,
21893dde7c95SVishal Kulkarni 0x4007c, 0x4008c,
21903dde7c95SVishal Kulkarni 0x40094, 0x400b0,
21913dde7c95SVishal Kulkarni 0x400c0, 0x40144,
21923dde7c95SVishal Kulkarni 0x40180, 0x4018c,
21933dde7c95SVishal Kulkarni 0x40200, 0x40254,
21943dde7c95SVishal Kulkarni 0x40260, 0x40264,
21953dde7c95SVishal Kulkarni 0x40270, 0x40288,
21963dde7c95SVishal Kulkarni 0x40290, 0x40298,
21973dde7c95SVishal Kulkarni 0x402ac, 0x402c8,
21983dde7c95SVishal Kulkarni 0x402d0, 0x402e0,
21993dde7c95SVishal Kulkarni 0x402f0, 0x402f0,
22003dde7c95SVishal Kulkarni 0x40300, 0x4033c,
22013dde7c95SVishal Kulkarni 0x403f8, 0x403fc,
22023dde7c95SVishal Kulkarni 0x41304, 0x413c4,
22033dde7c95SVishal Kulkarni 0x41400, 0x4140c,
22043dde7c95SVishal Kulkarni 0x41414, 0x4141c,
22053dde7c95SVishal Kulkarni 0x41480, 0x414d0,
22063dde7c95SVishal Kulkarni 0x44000, 0x44054,
22073dde7c95SVishal Kulkarni 0x4405c, 0x44078,
22083dde7c95SVishal Kulkarni 0x440c0, 0x44174,
22093dde7c95SVishal Kulkarni 0x44180, 0x441ac,
22103dde7c95SVishal Kulkarni 0x441b4, 0x441b8,
22113dde7c95SVishal Kulkarni 0x441c0, 0x44254,
22123dde7c95SVishal Kulkarni 0x4425c, 0x44278,
22133dde7c95SVishal Kulkarni 0x442c0, 0x44374,
22143dde7c95SVishal Kulkarni 0x44380, 0x443ac,
22153dde7c95SVishal Kulkarni 0x443b4, 0x443b8,
22163dde7c95SVishal Kulkarni 0x443c0, 0x44454,
22173dde7c95SVishal Kulkarni 0x4445c, 0x44478,
22183dde7c95SVishal Kulkarni 0x444c0, 0x44574,
22193dde7c95SVishal Kulkarni 0x44580, 0x445ac,
22203dde7c95SVishal Kulkarni 0x445b4, 0x445b8,
22213dde7c95SVishal Kulkarni 0x445c0, 0x44654,
22223dde7c95SVishal Kulkarni 0x4465c, 0x44678,
22233dde7c95SVishal Kulkarni 0x446c0, 0x44774,
22243dde7c95SVishal Kulkarni 0x44780, 0x447ac,
22253dde7c95SVishal Kulkarni 0x447b4, 0x447b8,
22263dde7c95SVishal Kulkarni 0x447c0, 0x44854,
22273dde7c95SVishal Kulkarni 0x4485c, 0x44878,
22283dde7c95SVishal Kulkarni 0x448c0, 0x44974,
22293dde7c95SVishal Kulkarni 0x44980, 0x449ac,
22303dde7c95SVishal Kulkarni 0x449b4, 0x449b8,
22313dde7c95SVishal Kulkarni 0x449c0, 0x449fc,
22323dde7c95SVishal Kulkarni 0x45000, 0x45004,
22333dde7c95SVishal Kulkarni 0x45010, 0x45030,
22343dde7c95SVishal Kulkarni 0x45040, 0x45060,
22353dde7c95SVishal Kulkarni 0x45068, 0x45068,
22363dde7c95SVishal Kulkarni 0x45080, 0x45084,
22373dde7c95SVishal Kulkarni 0x450a0, 0x450b0,
22383dde7c95SVishal Kulkarni 0x45200, 0x45204,
22393dde7c95SVishal Kulkarni 0x45210, 0x45230,
22403dde7c95SVishal Kulkarni 0x45240, 0x45260,
22413dde7c95SVishal Kulkarni 0x45268, 0x45268,
22423dde7c95SVishal Kulkarni 0x45280, 0x45284,
22433dde7c95SVishal Kulkarni 0x452a0, 0x452b0,
22443dde7c95SVishal Kulkarni 0x460c0, 0x460e4,
22453dde7c95SVishal Kulkarni 0x47000, 0x4703c,
22463dde7c95SVishal Kulkarni 0x47044, 0x4708c,
22473dde7c95SVishal Kulkarni 0x47200, 0x47250,
22483dde7c95SVishal Kulkarni 0x47400, 0x47408,
22493dde7c95SVishal Kulkarni 0x47414, 0x47420,
22503dde7c95SVishal Kulkarni 0x47600, 0x47618,
22513dde7c95SVishal Kulkarni 0x47800, 0x47814,
22523dde7c95SVishal Kulkarni 0x48000, 0x4800c,
22533dde7c95SVishal Kulkarni 0x48040, 0x48050,
22543dde7c95SVishal Kulkarni 0x48060, 0x48068,
22553dde7c95SVishal Kulkarni 0x4807c, 0x4808c,
22563dde7c95SVishal Kulkarni 0x48094, 0x480b0,
22573dde7c95SVishal Kulkarni 0x480c0, 0x48144,
22583dde7c95SVishal Kulkarni 0x48180, 0x4818c,
22593dde7c95SVishal Kulkarni 0x48200, 0x48254,
22603dde7c95SVishal Kulkarni 0x48260, 0x48264,
22613dde7c95SVishal Kulkarni 0x48270, 0x48288,
22623dde7c95SVishal Kulkarni 0x48290, 0x48298,
22633dde7c95SVishal Kulkarni 0x482ac, 0x482c8,
22643dde7c95SVishal Kulkarni 0x482d0, 0x482e0,
22653dde7c95SVishal Kulkarni 0x482f0, 0x482f0,
22663dde7c95SVishal Kulkarni 0x48300, 0x4833c,
22673dde7c95SVishal Kulkarni 0x483f8, 0x483fc,
22683dde7c95SVishal Kulkarni 0x49304, 0x493c4,
22693dde7c95SVishal Kulkarni 0x49400, 0x4940c,
22703dde7c95SVishal Kulkarni 0x49414, 0x4941c,
22713dde7c95SVishal Kulkarni 0x49480, 0x494d0,
22723dde7c95SVishal Kulkarni 0x4c000, 0x4c054,
22733dde7c95SVishal Kulkarni 0x4c05c, 0x4c078,
22743dde7c95SVishal Kulkarni 0x4c0c0, 0x4c174,
22753dde7c95SVishal Kulkarni 0x4c180, 0x4c1ac,
22763dde7c95SVishal Kulkarni 0x4c1b4, 0x4c1b8,
22773dde7c95SVishal Kulkarni 0x4c1c0, 0x4c254,
22783dde7c95SVishal Kulkarni 0x4c25c, 0x4c278,
22793dde7c95SVishal Kulkarni 0x4c2c0, 0x4c374,
22803dde7c95SVishal Kulkarni 0x4c380, 0x4c3ac,
22813dde7c95SVishal Kulkarni 0x4c3b4, 0x4c3b8,
22823dde7c95SVishal Kulkarni 0x4c3c0, 0x4c454,
22833dde7c95SVishal Kulkarni 0x4c45c, 0x4c478,
22843dde7c95SVishal Kulkarni 0x4c4c0, 0x4c574,
22853dde7c95SVishal Kulkarni 0x4c580, 0x4c5ac,
22863dde7c95SVishal Kulkarni 0x4c5b4, 0x4c5b8,
22873dde7c95SVishal Kulkarni 0x4c5c0, 0x4c654,
22883dde7c95SVishal Kulkarni 0x4c65c, 0x4c678,
22893dde7c95SVishal Kulkarni 0x4c6c0, 0x4c774,
22903dde7c95SVishal Kulkarni 0x4c780, 0x4c7ac,
22913dde7c95SVishal Kulkarni 0x4c7b4, 0x4c7b8,
22923dde7c95SVishal Kulkarni 0x4c7c0, 0x4c854,
22933dde7c95SVishal Kulkarni 0x4c85c, 0x4c878,
22943dde7c95SVishal Kulkarni 0x4c8c0, 0x4c974,
22953dde7c95SVishal Kulkarni 0x4c980, 0x4c9ac,
22963dde7c95SVishal Kulkarni 0x4c9b4, 0x4c9b8,
22973dde7c95SVishal Kulkarni 0x4c9c0, 0x4c9fc,
22983dde7c95SVishal Kulkarni 0x4d000, 0x4d004,
22993dde7c95SVishal Kulkarni 0x4d010, 0x4d030,
23003dde7c95SVishal Kulkarni 0x4d040, 0x4d060,
23013dde7c95SVishal Kulkarni 0x4d068, 0x4d068,
23023dde7c95SVishal Kulkarni 0x4d080, 0x4d084,
23033dde7c95SVishal Kulkarni 0x4d0a0, 0x4d0b0,
23043dde7c95SVishal Kulkarni 0x4d200, 0x4d204,
23053dde7c95SVishal Kulkarni 0x4d210, 0x4d230,
23063dde7c95SVishal Kulkarni 0x4d240, 0x4d260,
23073dde7c95SVishal Kulkarni 0x4d268, 0x4d268,
23083dde7c95SVishal Kulkarni 0x4d280, 0x4d284,
23093dde7c95SVishal Kulkarni 0x4d2a0, 0x4d2b0,
23103dde7c95SVishal Kulkarni 0x4e0c0, 0x4e0e4,
23113dde7c95SVishal Kulkarni 0x4f000, 0x4f03c,
23123dde7c95SVishal Kulkarni 0x4f044, 0x4f08c,
23133dde7c95SVishal Kulkarni 0x4f200, 0x4f250,
23143dde7c95SVishal Kulkarni 0x4f400, 0x4f408,
23153dde7c95SVishal Kulkarni 0x4f414, 0x4f420,
23163dde7c95SVishal Kulkarni 0x4f600, 0x4f618,
23173dde7c95SVishal Kulkarni 0x4f800, 0x4f814,
23183dde7c95SVishal Kulkarni 0x50000, 0x50084,
23193dde7c95SVishal Kulkarni 0x50090, 0x500cc,
23203dde7c95SVishal Kulkarni 0x50400, 0x50400,
23213dde7c95SVishal Kulkarni 0x50800, 0x50884,
23223dde7c95SVishal Kulkarni 0x50890, 0x508cc,
23233dde7c95SVishal Kulkarni 0x50c00, 0x50c00,
23243dde7c95SVishal Kulkarni 0x51000, 0x5101c,
23253dde7c95SVishal Kulkarni 0x51300, 0x51308,
23263dde7c95SVishal Kulkarni };
23273dde7c95SVishal Kulkarni
23283dde7c95SVishal Kulkarni static const unsigned int t6_reg_ranges[] = {
23293dde7c95SVishal Kulkarni 0x1008, 0x101c,
23303dde7c95SVishal Kulkarni 0x1024, 0x10a8,
23313dde7c95SVishal Kulkarni 0x10b4, 0x10f8,
23323dde7c95SVishal Kulkarni 0x1100, 0x1114,
23333dde7c95SVishal Kulkarni 0x111c, 0x112c,
23343dde7c95SVishal Kulkarni 0x1138, 0x113c,
23353dde7c95SVishal Kulkarni 0x1144, 0x114c,
23363dde7c95SVishal Kulkarni 0x1180, 0x1184,
23373dde7c95SVishal Kulkarni 0x1190, 0x1194,
23383dde7c95SVishal Kulkarni 0x11a0, 0x11a4,
23397e6ad469SVishal Kulkarni 0x11b0, 0x11c4,
23403dde7c95SVishal Kulkarni 0x11fc, 0x1274,
23413dde7c95SVishal Kulkarni 0x1280, 0x133c,
23423dde7c95SVishal Kulkarni 0x1800, 0x18fc,
23433dde7c95SVishal Kulkarni 0x3000, 0x302c,
23443dde7c95SVishal Kulkarni 0x3060, 0x30b0,
23453dde7c95SVishal Kulkarni 0x30b8, 0x30d8,
23463dde7c95SVishal Kulkarni 0x30e0, 0x30fc,
23473dde7c95SVishal Kulkarni 0x3140, 0x357c,
23483dde7c95SVishal Kulkarni 0x35a8, 0x35cc,
23493dde7c95SVishal Kulkarni 0x35ec, 0x35ec,
23503dde7c95SVishal Kulkarni 0x3600, 0x5624,
23513dde7c95SVishal Kulkarni 0x56cc, 0x56ec,
23523dde7c95SVishal Kulkarni 0x56f4, 0x5720,
23533dde7c95SVishal Kulkarni 0x5728, 0x575c,
23543dde7c95SVishal Kulkarni 0x580c, 0x5814,
23553dde7c95SVishal Kulkarni 0x5890, 0x589c,
23563dde7c95SVishal Kulkarni 0x58a4, 0x58ac,
23573dde7c95SVishal Kulkarni 0x58b8, 0x58bc,
23583dde7c95SVishal Kulkarni 0x5940, 0x595c,
23593dde7c95SVishal Kulkarni 0x5980, 0x598c,
23603dde7c95SVishal Kulkarni 0x59b0, 0x59c8,
23613dde7c95SVishal Kulkarni 0x59d0, 0x59dc,
23623dde7c95SVishal Kulkarni 0x59fc, 0x5a18,
23633dde7c95SVishal Kulkarni 0x5a60, 0x5a6c,
23643dde7c95SVishal Kulkarni 0x5a80, 0x5a8c,
23653dde7c95SVishal Kulkarni 0x5a94, 0x5a9c,
23663dde7c95SVishal Kulkarni 0x5b94, 0x5bfc,
23673dde7c95SVishal Kulkarni 0x5c10, 0x5e48,
23683dde7c95SVishal Kulkarni 0x5e50, 0x5e94,
23693dde7c95SVishal Kulkarni 0x5ea0, 0x5eb0,
23703dde7c95SVishal Kulkarni 0x5ec0, 0x5ec0,
23713dde7c95SVishal Kulkarni 0x5ec8, 0x5ed0,
23723dde7c95SVishal Kulkarni 0x5ee0, 0x5ee0,
23733dde7c95SVishal Kulkarni 0x5ef0, 0x5ef0,
23743dde7c95SVishal Kulkarni 0x5f00, 0x5f00,
23753dde7c95SVishal Kulkarni 0x6000, 0x6020,
23763dde7c95SVishal Kulkarni 0x6028, 0x6040,
23773dde7c95SVishal Kulkarni 0x6058, 0x609c,
23783dde7c95SVishal Kulkarni 0x60a8, 0x619c,
23793dde7c95SVishal Kulkarni 0x7700, 0x7798,
23803dde7c95SVishal Kulkarni 0x77c0, 0x7880,
23813dde7c95SVishal Kulkarni 0x78cc, 0x78fc,
23823dde7c95SVishal Kulkarni 0x7b00, 0x7b58,
23833dde7c95SVishal Kulkarni 0x7b60, 0x7b84,
23843dde7c95SVishal Kulkarni 0x7b8c, 0x7c54,
23853dde7c95SVishal Kulkarni 0x7d00, 0x7d38,
23863dde7c95SVishal Kulkarni 0x7d40, 0x7d84,
23873dde7c95SVishal Kulkarni 0x7d8c, 0x7ddc,
23883dde7c95SVishal Kulkarni 0x7de4, 0x7e04,
23893dde7c95SVishal Kulkarni 0x7e10, 0x7e1c,
23903dde7c95SVishal Kulkarni 0x7e24, 0x7e38,
23913dde7c95SVishal Kulkarni 0x7e40, 0x7e44,
23923dde7c95SVishal Kulkarni 0x7e4c, 0x7e78,
23933dde7c95SVishal Kulkarni 0x7e80, 0x7edc,
23943dde7c95SVishal Kulkarni 0x7ee8, 0x7efc,
23957e6ad469SVishal Kulkarni 0x8dc0, 0x8de0,
23963dde7c95SVishal Kulkarni 0x8df8, 0x8e04,
23973dde7c95SVishal Kulkarni 0x8e10, 0x8e84,
23983dde7c95SVishal Kulkarni 0x8ea0, 0x8f88,
23993dde7c95SVishal Kulkarni 0x8fb8, 0x9058,
24003dde7c95SVishal Kulkarni 0x9060, 0x9060,
24013dde7c95SVishal Kulkarni 0x9068, 0x90f8,
24023dde7c95SVishal Kulkarni 0x9100, 0x9124,
24033dde7c95SVishal Kulkarni 0x9400, 0x9470,
24043dde7c95SVishal Kulkarni 0x9600, 0x9600,
24053dde7c95SVishal Kulkarni 0x9608, 0x9638,
24063dde7c95SVishal Kulkarni 0x9640, 0x9704,
24073dde7c95SVishal Kulkarni 0x9710, 0x971c,
24083dde7c95SVishal Kulkarni 0x9800, 0x9808,
24093dde7c95SVishal Kulkarni 0x9820, 0x983c,
24103dde7c95SVishal Kulkarni 0x9850, 0x9864,
24113dde7c95SVishal Kulkarni 0x9c00, 0x9c6c,
24123dde7c95SVishal Kulkarni 0x9c80, 0x9cec,
24133dde7c95SVishal Kulkarni 0x9d00, 0x9d6c,
24143dde7c95SVishal Kulkarni 0x9d80, 0x9dec,
24153dde7c95SVishal Kulkarni 0x9e00, 0x9e6c,
24163dde7c95SVishal Kulkarni 0x9e80, 0x9eec,
24173dde7c95SVishal Kulkarni 0x9f00, 0x9f6c,
24183dde7c95SVishal Kulkarni 0x9f80, 0xa020,
24193dde7c95SVishal Kulkarni 0xd004, 0xd03c,
24203dde7c95SVishal Kulkarni 0xd100, 0xd118,
24213dde7c95SVishal Kulkarni 0xd200, 0xd214,
24223dde7c95SVishal Kulkarni 0xd220, 0xd234,
24233dde7c95SVishal Kulkarni 0xd240, 0xd254,
24243dde7c95SVishal Kulkarni 0xd260, 0xd274,
24253dde7c95SVishal Kulkarni 0xd280, 0xd294,
24263dde7c95SVishal Kulkarni 0xd2a0, 0xd2b4,
24273dde7c95SVishal Kulkarni 0xd2c0, 0xd2d4,
24283dde7c95SVishal Kulkarni 0xd2e0, 0xd2f4,
24293dde7c95SVishal Kulkarni 0xd300, 0xd31c,
24303dde7c95SVishal Kulkarni 0xdfc0, 0xdfe0,
24313dde7c95SVishal Kulkarni 0xe000, 0xf008,
24323dde7c95SVishal Kulkarni 0xf010, 0xf018,
24333dde7c95SVishal Kulkarni 0xf020, 0xf028,
24343dde7c95SVishal Kulkarni 0x11000, 0x11014,
24353dde7c95SVishal Kulkarni 0x11048, 0x1106c,
24363dde7c95SVishal Kulkarni 0x11074, 0x11088,
24373dde7c95SVishal Kulkarni 0x11098, 0x11120,
24383dde7c95SVishal Kulkarni 0x1112c, 0x1117c,
24393dde7c95SVishal Kulkarni 0x11190, 0x112e0,
24403dde7c95SVishal Kulkarni 0x11300, 0x1130c,
24413dde7c95SVishal Kulkarni 0x12000, 0x1206c,
24423dde7c95SVishal Kulkarni 0x19040, 0x1906c,
24433dde7c95SVishal Kulkarni 0x19078, 0x19080,
24443dde7c95SVishal Kulkarni 0x1908c, 0x190e8,
24453dde7c95SVishal Kulkarni 0x190f0, 0x190f8,
24463dde7c95SVishal Kulkarni 0x19100, 0x19110,
24473dde7c95SVishal Kulkarni 0x19120, 0x19124,
24483dde7c95SVishal Kulkarni 0x19150, 0x19194,
24493dde7c95SVishal Kulkarni 0x1919c, 0x191b0,
24503dde7c95SVishal Kulkarni 0x191d0, 0x191e8,
24513dde7c95SVishal Kulkarni 0x19238, 0x19290,
24523dde7c95SVishal Kulkarni 0x192a4, 0x192b0,
24533dde7c95SVishal Kulkarni 0x19348, 0x1934c,
24543dde7c95SVishal Kulkarni 0x193f8, 0x19418,
24553dde7c95SVishal Kulkarni 0x19420, 0x19428,
24563dde7c95SVishal Kulkarni 0x19430, 0x19444,
24573dde7c95SVishal Kulkarni 0x1944c, 0x1946c,
24583dde7c95SVishal Kulkarni 0x19474, 0x19474,
24593dde7c95SVishal Kulkarni 0x19490, 0x194cc,
24603dde7c95SVishal Kulkarni 0x194f0, 0x194f8,
24613dde7c95SVishal Kulkarni 0x19c00, 0x19c48,
24623dde7c95SVishal Kulkarni 0x19c50, 0x19c80,
24633dde7c95SVishal Kulkarni 0x19c94, 0x19c98,
24643dde7c95SVishal Kulkarni 0x19ca0, 0x19cbc,
24653dde7c95SVishal Kulkarni 0x19ce4, 0x19ce4,
24663dde7c95SVishal Kulkarni 0x19cf0, 0x19cf8,
24673dde7c95SVishal Kulkarni 0x19d00, 0x19d28,
24683dde7c95SVishal Kulkarni 0x19d50, 0x19d78,
24693dde7c95SVishal Kulkarni 0x19d94, 0x19d98,
24707e6ad469SVishal Kulkarni 0x19da0, 0x19de0,
24713dde7c95SVishal Kulkarni 0x19df0, 0x19e10,
24723dde7c95SVishal Kulkarni 0x19e50, 0x19e6c,
24733dde7c95SVishal Kulkarni 0x19ea0, 0x19ebc,
24743dde7c95SVishal Kulkarni 0x19ec4, 0x19ef4,
24753dde7c95SVishal Kulkarni 0x19f04, 0x19f2c,
24763dde7c95SVishal Kulkarni 0x19f34, 0x19f34,
24773dde7c95SVishal Kulkarni 0x19f40, 0x19f50,
24783dde7c95SVishal Kulkarni 0x19f90, 0x19fac,
24793dde7c95SVishal Kulkarni 0x19fc4, 0x19fc8,
24803dde7c95SVishal Kulkarni 0x19fd0, 0x19fe4,
24813dde7c95SVishal Kulkarni 0x1a000, 0x1a004,
24823dde7c95SVishal Kulkarni 0x1a010, 0x1a06c,
24833dde7c95SVishal Kulkarni 0x1a0b0, 0x1a0e4,
24843dde7c95SVishal Kulkarni 0x1a0ec, 0x1a0f8,
24853dde7c95SVishal Kulkarni 0x1a100, 0x1a108,
24863dde7c95SVishal Kulkarni 0x1a114, 0x1a120,
24873dde7c95SVishal Kulkarni 0x1a128, 0x1a130,
24883dde7c95SVishal Kulkarni 0x1a138, 0x1a138,
24893dde7c95SVishal Kulkarni 0x1a190, 0x1a1c4,
24903dde7c95SVishal Kulkarni 0x1a1fc, 0x1a1fc,
24913dde7c95SVishal Kulkarni 0x1e008, 0x1e00c,
24923dde7c95SVishal Kulkarni 0x1e040, 0x1e044,
24933dde7c95SVishal Kulkarni 0x1e04c, 0x1e04c,
24943dde7c95SVishal Kulkarni 0x1e284, 0x1e290,
24953dde7c95SVishal Kulkarni 0x1e2c0, 0x1e2c0,
24963dde7c95SVishal Kulkarni 0x1e2e0, 0x1e2e0,
24973dde7c95SVishal Kulkarni 0x1e300, 0x1e384,
24983dde7c95SVishal Kulkarni 0x1e3c0, 0x1e3c8,
24993dde7c95SVishal Kulkarni 0x1e408, 0x1e40c,
25003dde7c95SVishal Kulkarni 0x1e440, 0x1e444,
25013dde7c95SVishal Kulkarni 0x1e44c, 0x1e44c,
25023dde7c95SVishal Kulkarni 0x1e684, 0x1e690,
25033dde7c95SVishal Kulkarni 0x1e6c0, 0x1e6c0,
25043dde7c95SVishal Kulkarni 0x1e6e0, 0x1e6e0,
25053dde7c95SVishal Kulkarni 0x1e700, 0x1e784,
25063dde7c95SVishal Kulkarni 0x1e7c0, 0x1e7c8,
25073dde7c95SVishal Kulkarni 0x1e808, 0x1e80c,
25083dde7c95SVishal Kulkarni 0x1e840, 0x1e844,
25093dde7c95SVishal Kulkarni 0x1e84c, 0x1e84c,
25103dde7c95SVishal Kulkarni 0x1ea84, 0x1ea90,
25113dde7c95SVishal Kulkarni 0x1eac0, 0x1eac0,
25123dde7c95SVishal Kulkarni 0x1eae0, 0x1eae0,
25133dde7c95SVishal Kulkarni 0x1eb00, 0x1eb84,
25143dde7c95SVishal Kulkarni 0x1ebc0, 0x1ebc8,
25153dde7c95SVishal Kulkarni 0x1ec08, 0x1ec0c,
25163dde7c95SVishal Kulkarni 0x1ec40, 0x1ec44,
25173dde7c95SVishal Kulkarni 0x1ec4c, 0x1ec4c,
25183dde7c95SVishal Kulkarni 0x1ee84, 0x1ee90,
25193dde7c95SVishal Kulkarni 0x1eec0, 0x1eec0,
25203dde7c95SVishal Kulkarni 0x1eee0, 0x1eee0,
25213dde7c95SVishal Kulkarni 0x1ef00, 0x1ef84,
25223dde7c95SVishal Kulkarni 0x1efc0, 0x1efc8,
25233dde7c95SVishal Kulkarni 0x1f008, 0x1f00c,
25243dde7c95SVishal Kulkarni 0x1f040, 0x1f044,
25253dde7c95SVishal Kulkarni 0x1f04c, 0x1f04c,
25263dde7c95SVishal Kulkarni 0x1f284, 0x1f290,
25273dde7c95SVishal Kulkarni 0x1f2c0, 0x1f2c0,
25283dde7c95SVishal Kulkarni 0x1f2e0, 0x1f2e0,
25293dde7c95SVishal Kulkarni 0x1f300, 0x1f384,
25303dde7c95SVishal Kulkarni 0x1f3c0, 0x1f3c8,
25313dde7c95SVishal Kulkarni 0x1f408, 0x1f40c,
25323dde7c95SVishal Kulkarni 0x1f440, 0x1f444,
25333dde7c95SVishal Kulkarni 0x1f44c, 0x1f44c,
25343dde7c95SVishal Kulkarni 0x1f684, 0x1f690,
25353dde7c95SVishal Kulkarni 0x1f6c0, 0x1f6c0,
25363dde7c95SVishal Kulkarni 0x1f6e0, 0x1f6e0,
25373dde7c95SVishal Kulkarni 0x1f700, 0x1f784,
25383dde7c95SVishal Kulkarni 0x1f7c0, 0x1f7c8,
25393dde7c95SVishal Kulkarni 0x1f808, 0x1f80c,
25403dde7c95SVishal Kulkarni 0x1f840, 0x1f844,
25413dde7c95SVishal Kulkarni 0x1f84c, 0x1f84c,
25423dde7c95SVishal Kulkarni 0x1fa84, 0x1fa90,
25433dde7c95SVishal Kulkarni 0x1fac0, 0x1fac0,
25443dde7c95SVishal Kulkarni 0x1fae0, 0x1fae0,
25453dde7c95SVishal Kulkarni 0x1fb00, 0x1fb84,
25463dde7c95SVishal Kulkarni 0x1fbc0, 0x1fbc8,
25473dde7c95SVishal Kulkarni 0x1fc08, 0x1fc0c,
25483dde7c95SVishal Kulkarni 0x1fc40, 0x1fc44,
25493dde7c95SVishal Kulkarni 0x1fc4c, 0x1fc4c,
25503dde7c95SVishal Kulkarni 0x1fe84, 0x1fe90,
25513dde7c95SVishal Kulkarni 0x1fec0, 0x1fec0,
25523dde7c95SVishal Kulkarni 0x1fee0, 0x1fee0,
25533dde7c95SVishal Kulkarni 0x1ff00, 0x1ff84,
25543dde7c95SVishal Kulkarni 0x1ffc0, 0x1ffc8,
25553dde7c95SVishal Kulkarni 0x30000, 0x30030,
25563dde7c95SVishal Kulkarni 0x30100, 0x30168,
25573dde7c95SVishal Kulkarni 0x30190, 0x301a0,
25583dde7c95SVishal Kulkarni 0x301a8, 0x301b8,
25593dde7c95SVishal Kulkarni 0x301c4, 0x301c8,
25603dde7c95SVishal Kulkarni 0x301d0, 0x301d0,
25613dde7c95SVishal Kulkarni 0x30200, 0x30320,
25623dde7c95SVishal Kulkarni 0x30400, 0x304b4,
25633dde7c95SVishal Kulkarni 0x304c0, 0x3052c,
25643dde7c95SVishal Kulkarni 0x30540, 0x3061c,
25653dde7c95SVishal Kulkarni 0x30800, 0x308a0,
25663dde7c95SVishal Kulkarni 0x308c0, 0x30908,
25673dde7c95SVishal Kulkarni 0x30910, 0x309b8,
25683dde7c95SVishal Kulkarni 0x30a00, 0x30a04,
25693dde7c95SVishal Kulkarni 0x30a0c, 0x30a14,
25703dde7c95SVishal Kulkarni 0x30a1c, 0x30a2c,
25713dde7c95SVishal Kulkarni 0x30a44, 0x30a50,
25723dde7c95SVishal Kulkarni 0x30a74, 0x30a74,
25733dde7c95SVishal Kulkarni 0x30a7c, 0x30afc,
25743dde7c95SVishal Kulkarni 0x30b08, 0x30c24,
25753dde7c95SVishal Kulkarni 0x30d00, 0x30d14,
25763dde7c95SVishal Kulkarni 0x30d1c, 0x30d3c,
25773dde7c95SVishal Kulkarni 0x30d44, 0x30d4c,
25783dde7c95SVishal Kulkarni 0x30d54, 0x30d74,
25793dde7c95SVishal Kulkarni 0x30d7c, 0x30d7c,
25803dde7c95SVishal Kulkarni 0x30de0, 0x30de0,
25813dde7c95SVishal Kulkarni 0x30e00, 0x30ed4,
25823dde7c95SVishal Kulkarni 0x30f00, 0x30fa4,
25833dde7c95SVishal Kulkarni 0x30fc0, 0x30fc4,
25843dde7c95SVishal Kulkarni 0x31000, 0x31004,
25853dde7c95SVishal Kulkarni 0x31080, 0x310fc,
25863dde7c95SVishal Kulkarni 0x31208, 0x31220,
25873dde7c95SVishal Kulkarni 0x3123c, 0x31254,
25883dde7c95SVishal Kulkarni 0x31300, 0x31300,
25893dde7c95SVishal Kulkarni 0x31308, 0x3131c,
25903dde7c95SVishal Kulkarni 0x31338, 0x3133c,
25913dde7c95SVishal Kulkarni 0x31380, 0x31380,
25923dde7c95SVishal Kulkarni 0x31388, 0x313a8,
25933dde7c95SVishal Kulkarni 0x313b4, 0x313b4,
25943dde7c95SVishal Kulkarni 0x31400, 0x31420,
25953dde7c95SVishal Kulkarni 0x31438, 0x3143c,
25963dde7c95SVishal Kulkarni 0x31480, 0x31480,
25973dde7c95SVishal Kulkarni 0x314a8, 0x314a8,
25983dde7c95SVishal Kulkarni 0x314b0, 0x314b4,
25993dde7c95SVishal Kulkarni 0x314c8, 0x314d4,
26003dde7c95SVishal Kulkarni 0x31a40, 0x31a4c,
26013dde7c95SVishal Kulkarni 0x31af0, 0x31b20,
26023dde7c95SVishal Kulkarni 0x31b38, 0x31b3c,
26033dde7c95SVishal Kulkarni 0x31b80, 0x31b80,
26043dde7c95SVishal Kulkarni 0x31ba8, 0x31ba8,
26053dde7c95SVishal Kulkarni 0x31bb0, 0x31bb4,
26063dde7c95SVishal Kulkarni 0x31bc8, 0x31bd4,
26073dde7c95SVishal Kulkarni 0x32140, 0x3218c,
26083dde7c95SVishal Kulkarni 0x321f0, 0x321f4,
26093dde7c95SVishal Kulkarni 0x32200, 0x32200,
26103dde7c95SVishal Kulkarni 0x32218, 0x32218,
26113dde7c95SVishal Kulkarni 0x32400, 0x32400,
26123dde7c95SVishal Kulkarni 0x32408, 0x3241c,
26133dde7c95SVishal Kulkarni 0x32618, 0x32620,
26143dde7c95SVishal Kulkarni 0x32664, 0x32664,
26153dde7c95SVishal Kulkarni 0x326a8, 0x326a8,
26163dde7c95SVishal Kulkarni 0x326ec, 0x326ec,
26173dde7c95SVishal Kulkarni 0x32a00, 0x32abc,
26183dde7c95SVishal Kulkarni 0x32b00, 0x32b18,
26193dde7c95SVishal Kulkarni 0x32b20, 0x32b38,
26203dde7c95SVishal Kulkarni 0x32b40, 0x32b58,
26213dde7c95SVishal Kulkarni 0x32b60, 0x32b78,
26223dde7c95SVishal Kulkarni 0x32c00, 0x32c00,
26233dde7c95SVishal Kulkarni 0x32c08, 0x32c3c,
26243dde7c95SVishal Kulkarni 0x33000, 0x3302c,
26253dde7c95SVishal Kulkarni 0x33034, 0x33050,
26263dde7c95SVishal Kulkarni 0x33058, 0x33058,
26273dde7c95SVishal Kulkarni 0x33060, 0x3308c,
26283dde7c95SVishal Kulkarni 0x3309c, 0x330ac,
26293dde7c95SVishal Kulkarni 0x330c0, 0x330c0,
26303dde7c95SVishal Kulkarni 0x330c8, 0x330d0,
26313dde7c95SVishal Kulkarni 0x330d8, 0x330e0,
26323dde7c95SVishal Kulkarni 0x330ec, 0x3312c,
26333dde7c95SVishal Kulkarni 0x33134, 0x33150,
26343dde7c95SVishal Kulkarni 0x33158, 0x33158,
26353dde7c95SVishal Kulkarni 0x33160, 0x3318c,
26363dde7c95SVishal Kulkarni 0x3319c, 0x331ac,
26373dde7c95SVishal Kulkarni 0x331c0, 0x331c0,
26383dde7c95SVishal Kulkarni 0x331c8, 0x331d0,
26393dde7c95SVishal Kulkarni 0x331d8, 0x331e0,
26403dde7c95SVishal Kulkarni 0x331ec, 0x33290,
26413dde7c95SVishal Kulkarni 0x33298, 0x332c4,
26423dde7c95SVishal Kulkarni 0x332e4, 0x33390,
26433dde7c95SVishal Kulkarni 0x33398, 0x333c4,
26443dde7c95SVishal Kulkarni 0x333e4, 0x3342c,
26453dde7c95SVishal Kulkarni 0x33434, 0x33450,
26463dde7c95SVishal Kulkarni 0x33458, 0x33458,
26473dde7c95SVishal Kulkarni 0x33460, 0x3348c,
26483dde7c95SVishal Kulkarni 0x3349c, 0x334ac,
26493dde7c95SVishal Kulkarni 0x334c0, 0x334c0,
26503dde7c95SVishal Kulkarni 0x334c8, 0x334d0,
26513dde7c95SVishal Kulkarni 0x334d8, 0x334e0,
26523dde7c95SVishal Kulkarni 0x334ec, 0x3352c,
26533dde7c95SVishal Kulkarni 0x33534, 0x33550,
26543dde7c95SVishal Kulkarni 0x33558, 0x33558,
26553dde7c95SVishal Kulkarni 0x33560, 0x3358c,
26563dde7c95SVishal Kulkarni 0x3359c, 0x335ac,
26573dde7c95SVishal Kulkarni 0x335c0, 0x335c0,
26583dde7c95SVishal Kulkarni 0x335c8, 0x335d0,
26593dde7c95SVishal Kulkarni 0x335d8, 0x335e0,
26603dde7c95SVishal Kulkarni 0x335ec, 0x33690,
26613dde7c95SVishal Kulkarni 0x33698, 0x336c4,
26623dde7c95SVishal Kulkarni 0x336e4, 0x33790,
26633dde7c95SVishal Kulkarni 0x33798, 0x337c4,
26643dde7c95SVishal Kulkarni 0x337e4, 0x337fc,
26653dde7c95SVishal Kulkarni 0x33814, 0x33814,
26663dde7c95SVishal Kulkarni 0x33854, 0x33868,
26673dde7c95SVishal Kulkarni 0x33880, 0x3388c,
26683dde7c95SVishal Kulkarni 0x338c0, 0x338d0,
26693dde7c95SVishal Kulkarni 0x338e8, 0x338ec,
26703dde7c95SVishal Kulkarni 0x33900, 0x3392c,
26713dde7c95SVishal Kulkarni 0x33934, 0x33950,
26723dde7c95SVishal Kulkarni 0x33958, 0x33958,
26733dde7c95SVishal Kulkarni 0x33960, 0x3398c,
26743dde7c95SVishal Kulkarni 0x3399c, 0x339ac,
26753dde7c95SVishal Kulkarni 0x339c0, 0x339c0,
26763dde7c95SVishal Kulkarni 0x339c8, 0x339d0,
26773dde7c95SVishal Kulkarni 0x339d8, 0x339e0,
26783dde7c95SVishal Kulkarni 0x339ec, 0x33a90,
26793dde7c95SVishal Kulkarni 0x33a98, 0x33ac4,
26803dde7c95SVishal Kulkarni 0x33ae4, 0x33b10,
26813dde7c95SVishal Kulkarni 0x33b24, 0x33b28,
26823dde7c95SVishal Kulkarni 0x33b38, 0x33b50,
26833dde7c95SVishal Kulkarni 0x33bf0, 0x33c10,
26843dde7c95SVishal Kulkarni 0x33c24, 0x33c28,
26853dde7c95SVishal Kulkarni 0x33c38, 0x33c50,
26863dde7c95SVishal Kulkarni 0x33cf0, 0x33cfc,
26873dde7c95SVishal Kulkarni 0x34000, 0x34030,
26883dde7c95SVishal Kulkarni 0x34100, 0x34168,
26893dde7c95SVishal Kulkarni 0x34190, 0x341a0,
26903dde7c95SVishal Kulkarni 0x341a8, 0x341b8,
26913dde7c95SVishal Kulkarni 0x341c4, 0x341c8,
26923dde7c95SVishal Kulkarni 0x341d0, 0x341d0,
26933dde7c95SVishal Kulkarni 0x34200, 0x34320,
26943dde7c95SVishal Kulkarni 0x34400, 0x344b4,
26953dde7c95SVishal Kulkarni 0x344c0, 0x3452c,
26963dde7c95SVishal Kulkarni 0x34540, 0x3461c,
26973dde7c95SVishal Kulkarni 0x34800, 0x348a0,
26983dde7c95SVishal Kulkarni 0x348c0, 0x34908,
26993dde7c95SVishal Kulkarni 0x34910, 0x349b8,
27003dde7c95SVishal Kulkarni 0x34a00, 0x34a04,
27013dde7c95SVishal Kulkarni 0x34a0c, 0x34a14,
27023dde7c95SVishal Kulkarni 0x34a1c, 0x34a2c,
27033dde7c95SVishal Kulkarni 0x34a44, 0x34a50,
27043dde7c95SVishal Kulkarni 0x34a74, 0x34a74,
27053dde7c95SVishal Kulkarni 0x34a7c, 0x34afc,
27063dde7c95SVishal Kulkarni 0x34b08, 0x34c24,
27073dde7c95SVishal Kulkarni 0x34d00, 0x34d14,
27083dde7c95SVishal Kulkarni 0x34d1c, 0x34d3c,
27093dde7c95SVishal Kulkarni 0x34d44, 0x34d4c,
27103dde7c95SVishal Kulkarni 0x34d54, 0x34d74,
27113dde7c95SVishal Kulkarni 0x34d7c, 0x34d7c,
27123dde7c95SVishal Kulkarni 0x34de0, 0x34de0,
27133dde7c95SVishal Kulkarni 0x34e00, 0x34ed4,
27143dde7c95SVishal Kulkarni 0x34f00, 0x34fa4,
27153dde7c95SVishal Kulkarni 0x34fc0, 0x34fc4,
27163dde7c95SVishal Kulkarni 0x35000, 0x35004,
27173dde7c95SVishal Kulkarni 0x35080, 0x350fc,
27183dde7c95SVishal Kulkarni 0x35208, 0x35220,
27193dde7c95SVishal Kulkarni 0x3523c, 0x35254,
27203dde7c95SVishal Kulkarni 0x35300, 0x35300,
27213dde7c95SVishal Kulkarni 0x35308, 0x3531c,
27223dde7c95SVishal Kulkarni 0x35338, 0x3533c,
27233dde7c95SVishal Kulkarni 0x35380, 0x35380,
27243dde7c95SVishal Kulkarni 0x35388, 0x353a8,
27253dde7c95SVishal Kulkarni 0x353b4, 0x353b4,
27263dde7c95SVishal Kulkarni 0x35400, 0x35420,
27273dde7c95SVishal Kulkarni 0x35438, 0x3543c,
27283dde7c95SVishal Kulkarni 0x35480, 0x35480,
27293dde7c95SVishal Kulkarni 0x354a8, 0x354a8,
27303dde7c95SVishal Kulkarni 0x354b0, 0x354b4,
27313dde7c95SVishal Kulkarni 0x354c8, 0x354d4,
27323dde7c95SVishal Kulkarni 0x35a40, 0x35a4c,
27333dde7c95SVishal Kulkarni 0x35af0, 0x35b20,
27343dde7c95SVishal Kulkarni 0x35b38, 0x35b3c,
27353dde7c95SVishal Kulkarni 0x35b80, 0x35b80,
27363dde7c95SVishal Kulkarni 0x35ba8, 0x35ba8,
27373dde7c95SVishal Kulkarni 0x35bb0, 0x35bb4,
27383dde7c95SVishal Kulkarni 0x35bc8, 0x35bd4,
27393dde7c95SVishal Kulkarni 0x36140, 0x3618c,
27403dde7c95SVishal Kulkarni 0x361f0, 0x361f4,
27413dde7c95SVishal Kulkarni 0x36200, 0x36200,
27423dde7c95SVishal Kulkarni 0x36218, 0x36218,
27433dde7c95SVishal Kulkarni 0x36400, 0x36400,
27443dde7c95SVishal Kulkarni 0x36408, 0x3641c,
27453dde7c95SVishal Kulkarni 0x36618, 0x36620,
27463dde7c95SVishal Kulkarni 0x36664, 0x36664,
27473dde7c95SVishal Kulkarni 0x366a8, 0x366a8,
27483dde7c95SVishal Kulkarni 0x366ec, 0x366ec,
27493dde7c95SVishal Kulkarni 0x36a00, 0x36abc,
27503dde7c95SVishal Kulkarni 0x36b00, 0x36b18,
27513dde7c95SVishal Kulkarni 0x36b20, 0x36b38,
27523dde7c95SVishal Kulkarni 0x36b40, 0x36b58,
27533dde7c95SVishal Kulkarni 0x36b60, 0x36b78,
27543dde7c95SVishal Kulkarni 0x36c00, 0x36c00,
27553dde7c95SVishal Kulkarni 0x36c08, 0x36c3c,
27563dde7c95SVishal Kulkarni 0x37000, 0x3702c,
27573dde7c95SVishal Kulkarni 0x37034, 0x37050,
27583dde7c95SVishal Kulkarni 0x37058, 0x37058,
27593dde7c95SVishal Kulkarni 0x37060, 0x3708c,
27603dde7c95SVishal Kulkarni 0x3709c, 0x370ac,
27613dde7c95SVishal Kulkarni 0x370c0, 0x370c0,
27623dde7c95SVishal Kulkarni 0x370c8, 0x370d0,
27633dde7c95SVishal Kulkarni 0x370d8, 0x370e0,
27643dde7c95SVishal Kulkarni 0x370ec, 0x3712c,
27653dde7c95SVishal Kulkarni 0x37134, 0x37150,
27663dde7c95SVishal Kulkarni 0x37158, 0x37158,
27673dde7c95SVishal Kulkarni 0x37160, 0x3718c,
27683dde7c95SVishal Kulkarni 0x3719c, 0x371ac,
27693dde7c95SVishal Kulkarni 0x371c0, 0x371c0,
27703dde7c95SVishal Kulkarni 0x371c8, 0x371d0,
27713dde7c95SVishal Kulkarni 0x371d8, 0x371e0,
27723dde7c95SVishal Kulkarni 0x371ec, 0x37290,
27733dde7c95SVishal Kulkarni 0x37298, 0x372c4,
27743dde7c95SVishal Kulkarni 0x372e4, 0x37390,
27753dde7c95SVishal Kulkarni 0x37398, 0x373c4,
27763dde7c95SVishal Kulkarni 0x373e4, 0x3742c,
27773dde7c95SVishal Kulkarni 0x37434, 0x37450,
27783dde7c95SVishal Kulkarni 0x37458, 0x37458,
27793dde7c95SVishal Kulkarni 0x37460, 0x3748c,
27803dde7c95SVishal Kulkarni 0x3749c, 0x374ac,
27813dde7c95SVishal Kulkarni 0x374c0, 0x374c0,
27823dde7c95SVishal Kulkarni 0x374c8, 0x374d0,
27833dde7c95SVishal Kulkarni 0x374d8, 0x374e0,
27843dde7c95SVishal Kulkarni 0x374ec, 0x3752c,
27853dde7c95SVishal Kulkarni 0x37534, 0x37550,
27863dde7c95SVishal Kulkarni 0x37558, 0x37558,
27873dde7c95SVishal Kulkarni 0x37560, 0x3758c,
27883dde7c95SVishal Kulkarni 0x3759c, 0x375ac,
27893dde7c95SVishal Kulkarni 0x375c0, 0x375c0,
27903dde7c95SVishal Kulkarni 0x375c8, 0x375d0,
27913dde7c95SVishal Kulkarni 0x375d8, 0x375e0,
27923dde7c95SVishal Kulkarni 0x375ec, 0x37690,
27933dde7c95SVishal Kulkarni 0x37698, 0x376c4,
27943dde7c95SVishal Kulkarni 0x376e4, 0x37790,
27953dde7c95SVishal Kulkarni 0x37798, 0x377c4,
27963dde7c95SVishal Kulkarni 0x377e4, 0x377fc,
27973dde7c95SVishal Kulkarni 0x37814, 0x37814,
27983dde7c95SVishal Kulkarni 0x37854, 0x37868,
27993dde7c95SVishal Kulkarni 0x37880, 0x3788c,
28003dde7c95SVishal Kulkarni 0x378c0, 0x378d0,
28013dde7c95SVishal Kulkarni 0x378e8, 0x378ec,
28023dde7c95SVishal Kulkarni 0x37900, 0x3792c,
28033dde7c95SVishal Kulkarni 0x37934, 0x37950,
28043dde7c95SVishal Kulkarni 0x37958, 0x37958,
28053dde7c95SVishal Kulkarni 0x37960, 0x3798c,
28063dde7c95SVishal Kulkarni 0x3799c, 0x379ac,
28073dde7c95SVishal Kulkarni 0x379c0, 0x379c0,
28083dde7c95SVishal Kulkarni 0x379c8, 0x379d0,
28093dde7c95SVishal Kulkarni 0x379d8, 0x379e0,
28103dde7c95SVishal Kulkarni 0x379ec, 0x37a90,
28113dde7c95SVishal Kulkarni 0x37a98, 0x37ac4,
28123dde7c95SVishal Kulkarni 0x37ae4, 0x37b10,
28133dde7c95SVishal Kulkarni 0x37b24, 0x37b28,
28143dde7c95SVishal Kulkarni 0x37b38, 0x37b50,
28153dde7c95SVishal Kulkarni 0x37bf0, 0x37c10,
28163dde7c95SVishal Kulkarni 0x37c24, 0x37c28,
28173dde7c95SVishal Kulkarni 0x37c38, 0x37c50,
28183dde7c95SVishal Kulkarni 0x37cf0, 0x37cfc,
28193dde7c95SVishal Kulkarni 0x40040, 0x40040,
28203dde7c95SVishal Kulkarni 0x40080, 0x40084,
28213dde7c95SVishal Kulkarni 0x40100, 0x40100,
28223dde7c95SVishal Kulkarni 0x40140, 0x401bc,
28233dde7c95SVishal Kulkarni 0x40200, 0x40214,
28243dde7c95SVishal Kulkarni 0x40228, 0x40228,
28253dde7c95SVishal Kulkarni 0x40240, 0x40258,
28263dde7c95SVishal Kulkarni 0x40280, 0x40280,
28273dde7c95SVishal Kulkarni 0x40304, 0x40304,
28283dde7c95SVishal Kulkarni 0x40330, 0x4033c,
28293dde7c95SVishal Kulkarni 0x41304, 0x413c8,
28303dde7c95SVishal Kulkarni 0x413d0, 0x413dc,
28313dde7c95SVishal Kulkarni 0x413f0, 0x413f0,
28323dde7c95SVishal Kulkarni 0x41400, 0x4140c,
28333dde7c95SVishal Kulkarni 0x41414, 0x4141c,
28343dde7c95SVishal Kulkarni 0x41480, 0x414d0,
28353dde7c95SVishal Kulkarni 0x44000, 0x4407c,
28363dde7c95SVishal Kulkarni 0x440c0, 0x441ac,
28373dde7c95SVishal Kulkarni 0x441b4, 0x4427c,
28383dde7c95SVishal Kulkarni 0x442c0, 0x443ac,
28393dde7c95SVishal Kulkarni 0x443b4, 0x4447c,
28403dde7c95SVishal Kulkarni 0x444c0, 0x445ac,
28413dde7c95SVishal Kulkarni 0x445b4, 0x4467c,
28423dde7c95SVishal Kulkarni 0x446c0, 0x447ac,
28433dde7c95SVishal Kulkarni 0x447b4, 0x4487c,
28443dde7c95SVishal Kulkarni 0x448c0, 0x449ac,
28453dde7c95SVishal Kulkarni 0x449b4, 0x44a7c,
28463dde7c95SVishal Kulkarni 0x44ac0, 0x44bac,
28473dde7c95SVishal Kulkarni 0x44bb4, 0x44c7c,
28483dde7c95SVishal Kulkarni 0x44cc0, 0x44dac,
28493dde7c95SVishal Kulkarni 0x44db4, 0x44e7c,
28503dde7c95SVishal Kulkarni 0x44ec0, 0x44fac,
28513dde7c95SVishal Kulkarni 0x44fb4, 0x4507c,
28523dde7c95SVishal Kulkarni 0x450c0, 0x451ac,
28533dde7c95SVishal Kulkarni 0x451b4, 0x451fc,
28543dde7c95SVishal Kulkarni 0x45800, 0x45804,
28553dde7c95SVishal Kulkarni 0x45810, 0x45830,
28563dde7c95SVishal Kulkarni 0x45840, 0x45860,
28573dde7c95SVishal Kulkarni 0x45868, 0x45868,
28583dde7c95SVishal Kulkarni 0x45880, 0x45884,
28593dde7c95SVishal Kulkarni 0x458a0, 0x458b0,
28603dde7c95SVishal Kulkarni 0x45a00, 0x45a04,
28613dde7c95SVishal Kulkarni 0x45a10, 0x45a30,
28623dde7c95SVishal Kulkarni 0x45a40, 0x45a60,
28633dde7c95SVishal Kulkarni 0x45a68, 0x45a68,
28643dde7c95SVishal Kulkarni 0x45a80, 0x45a84,
28653dde7c95SVishal Kulkarni 0x45aa0, 0x45ab0,
28663dde7c95SVishal Kulkarni 0x460c0, 0x460e4,
28673dde7c95SVishal Kulkarni 0x47000, 0x4703c,
28683dde7c95SVishal Kulkarni 0x47044, 0x4708c,
28693dde7c95SVishal Kulkarni 0x47200, 0x47250,
28703dde7c95SVishal Kulkarni 0x47400, 0x47408,
28713dde7c95SVishal Kulkarni 0x47414, 0x47420,
28723dde7c95SVishal Kulkarni 0x47600, 0x47618,
28733dde7c95SVishal Kulkarni 0x47800, 0x47814,
28743dde7c95SVishal Kulkarni 0x47820, 0x4782c,
28753dde7c95SVishal Kulkarni 0x50000, 0x50084,
28763dde7c95SVishal Kulkarni 0x50090, 0x500cc,
28773dde7c95SVishal Kulkarni 0x50300, 0x50384,
28783dde7c95SVishal Kulkarni 0x50400, 0x50400,
28793dde7c95SVishal Kulkarni 0x50800, 0x50884,
28803dde7c95SVishal Kulkarni 0x50890, 0x508cc,
28813dde7c95SVishal Kulkarni 0x50b00, 0x50b84,
28823dde7c95SVishal Kulkarni 0x50c00, 0x50c00,
28833dde7c95SVishal Kulkarni 0x51000, 0x51020,
28843dde7c95SVishal Kulkarni 0x51028, 0x510b0,
28853dde7c95SVishal Kulkarni 0x51300, 0x51324,
28863dde7c95SVishal Kulkarni };
28873dde7c95SVishal Kulkarni
28883dde7c95SVishal Kulkarni u32 *buf_end = (u32 *)((char *)buf + buf_size);
28893dde7c95SVishal Kulkarni const unsigned int *reg_ranges;
28903dde7c95SVishal Kulkarni int reg_ranges_size, range;
28913dde7c95SVishal Kulkarni unsigned int chip_version = CHELSIO_CHIP_VERSION(adap->params.chip);
28923dde7c95SVishal Kulkarni
28933dde7c95SVishal Kulkarni /* Select the right set of register ranges to dump depending on the
28943dde7c95SVishal Kulkarni * adapter chip type.
28953dde7c95SVishal Kulkarni */
28963dde7c95SVishal Kulkarni switch (chip_version) {
28973dde7c95SVishal Kulkarni case CHELSIO_T4:
28983dde7c95SVishal Kulkarni reg_ranges = t4_reg_ranges;
28993dde7c95SVishal Kulkarni reg_ranges_size = ARRAY_SIZE(t4_reg_ranges);
29003dde7c95SVishal Kulkarni break;
29013dde7c95SVishal Kulkarni
29023dde7c95SVishal Kulkarni case CHELSIO_T5:
29033dde7c95SVishal Kulkarni reg_ranges = t5_reg_ranges;
29043dde7c95SVishal Kulkarni reg_ranges_size = ARRAY_SIZE(t5_reg_ranges);
29053dde7c95SVishal Kulkarni break;
29063dde7c95SVishal Kulkarni
29073dde7c95SVishal Kulkarni case CHELSIO_T6:
29083dde7c95SVishal Kulkarni reg_ranges = t6_reg_ranges;
29093dde7c95SVishal Kulkarni reg_ranges_size = ARRAY_SIZE(t6_reg_ranges);
29103dde7c95SVishal Kulkarni break;
29113dde7c95SVishal Kulkarni
29123dde7c95SVishal Kulkarni default:
29133dde7c95SVishal Kulkarni CH_ERR(adap,
29143dde7c95SVishal Kulkarni "Unsupported chip version %d\n", chip_version);
29153dde7c95SVishal Kulkarni return;
29163dde7c95SVishal Kulkarni }
29173dde7c95SVishal Kulkarni
29183dde7c95SVishal Kulkarni /* Clear the register buffer and insert the appropriate register
29193dde7c95SVishal Kulkarni * values selected by the above register ranges.
29203dde7c95SVishal Kulkarni */
29213dde7c95SVishal Kulkarni memset(buf, 0, buf_size);
29223dde7c95SVishal Kulkarni for (range = 0; range < reg_ranges_size; range += 2) {
29233dde7c95SVishal Kulkarni unsigned int reg = reg_ranges[range];
29243dde7c95SVishal Kulkarni unsigned int last_reg = reg_ranges[range + 1];
29253dde7c95SVishal Kulkarni u32 *bufp = (u32 *)((char *)buf + reg);
29263dde7c95SVishal Kulkarni
29273dde7c95SVishal Kulkarni /* Iterate across the register range filling in the register
29283dde7c95SVishal Kulkarni * buffer but don't write past the end of the register buffer.
29293dde7c95SVishal Kulkarni */
29303dde7c95SVishal Kulkarni while (reg <= last_reg && bufp < buf_end) {
29313dde7c95SVishal Kulkarni *bufp++ = t4_read_reg(adap, reg);
29323dde7c95SVishal Kulkarni reg += sizeof(u32);
29333dde7c95SVishal Kulkarni }
29343dde7c95SVishal Kulkarni }
29353dde7c95SVishal Kulkarni }
29363dde7c95SVishal Kulkarni
293756b2bdd1SGireesh Nagabhushana /*
293856b2bdd1SGireesh Nagabhushana * EEPROM reads take a few tens of us while writes can take a bit over 5 ms.
293956b2bdd1SGireesh Nagabhushana */
29403dde7c95SVishal Kulkarni #define EEPROM_DELAY 10 // 10us per poll spin
29413dde7c95SVishal Kulkarni #define EEPROM_MAX_POLL 5000 // x 5000 == 50ms
29423dde7c95SVishal Kulkarni
294356b2bdd1SGireesh Nagabhushana #define EEPROM_STAT_ADDR 0x7bfc
29443dde7c95SVishal Kulkarni #define VPD_SIZE 0x800
294556b2bdd1SGireesh Nagabhushana #define VPD_BASE 0x400
294656b2bdd1SGireesh Nagabhushana #define VPD_BASE_OLD 0
2947de483253SVishal Kulkarni #define VPD_LEN 1024
294856b2bdd1SGireesh Nagabhushana #define VPD_INFO_FLD_HDR_SIZE 3
2949de483253SVishal Kulkarni #define CHELSIO_VPD_UNIQUE_ID 0x82
295056b2bdd1SGireesh Nagabhushana
295156b2bdd1SGireesh Nagabhushana /*
29523dde7c95SVishal Kulkarni * Small utility function to wait till any outstanding VPD Access is complete.
29533dde7c95SVishal Kulkarni * We have a per-adapter state variable "VPD Busy" to indicate when we have a
29543dde7c95SVishal Kulkarni * VPD Access in flight. This allows us to handle the problem of having a
29553dde7c95SVishal Kulkarni * previous VPD Access time out and prevent an attempt to inject a new VPD
29563dde7c95SVishal Kulkarni * Request before any in-flight VPD reguest has completed.
29573dde7c95SVishal Kulkarni */
t4_seeprom_wait(struct adapter * adapter)29583dde7c95SVishal Kulkarni static int t4_seeprom_wait(struct adapter *adapter)
29593dde7c95SVishal Kulkarni {
29603dde7c95SVishal Kulkarni unsigned int base = adapter->params.pci.vpd_cap_addr;
29613dde7c95SVishal Kulkarni int max_poll;
29623dde7c95SVishal Kulkarni
29633dde7c95SVishal Kulkarni /*
29643dde7c95SVishal Kulkarni * If no VPD Access is in flight, we can just return success right
29653dde7c95SVishal Kulkarni * away.
29663dde7c95SVishal Kulkarni */
29673dde7c95SVishal Kulkarni if (!adapter->vpd_busy)
29683dde7c95SVishal Kulkarni return 0;
29693dde7c95SVishal Kulkarni
29703dde7c95SVishal Kulkarni /*
29713dde7c95SVishal Kulkarni * Poll the VPD Capability Address/Flag register waiting for it
29723dde7c95SVishal Kulkarni * to indicate that the operation is complete.
29733dde7c95SVishal Kulkarni */
29743dde7c95SVishal Kulkarni max_poll = EEPROM_MAX_POLL;
29753dde7c95SVishal Kulkarni do {
29763dde7c95SVishal Kulkarni u16 val;
29773dde7c95SVishal Kulkarni
29783dde7c95SVishal Kulkarni udelay(EEPROM_DELAY);
29793dde7c95SVishal Kulkarni t4_os_pci_read_cfg2(adapter, base + PCI_VPD_ADDR, &val);
29803dde7c95SVishal Kulkarni
29813dde7c95SVishal Kulkarni /*
29823dde7c95SVishal Kulkarni * If the operation is complete, mark the VPD as no longer
29833dde7c95SVishal Kulkarni * busy and return success.
29843dde7c95SVishal Kulkarni */
29853dde7c95SVishal Kulkarni if ((val & PCI_VPD_ADDR_F) == adapter->vpd_flag) {
29863dde7c95SVishal Kulkarni adapter->vpd_busy = 0;
29873dde7c95SVishal Kulkarni return 0;
29883dde7c95SVishal Kulkarni }
29893dde7c95SVishal Kulkarni } while (--max_poll);
29903dde7c95SVishal Kulkarni
29913dde7c95SVishal Kulkarni /*
29923dde7c95SVishal Kulkarni * Failure! Note that we leave the VPD Busy status set in order to
29933dde7c95SVishal Kulkarni * avoid pushing a new VPD Access request into the VPD Capability till
29943dde7c95SVishal Kulkarni * the current operation eventually succeeds. It's a bug to issue a
29953dde7c95SVishal Kulkarni * new request when an existing request is in flight and will result
29963dde7c95SVishal Kulkarni * in corrupt hardware state.
29973dde7c95SVishal Kulkarni */
29983dde7c95SVishal Kulkarni return -ETIMEDOUT;
29993dde7c95SVishal Kulkarni }
30003dde7c95SVishal Kulkarni
30013dde7c95SVishal Kulkarni /**
300256b2bdd1SGireesh Nagabhushana * t4_seeprom_read - read a serial EEPROM location
300356b2bdd1SGireesh Nagabhushana * @adapter: adapter to read
300456b2bdd1SGireesh Nagabhushana * @addr: EEPROM virtual address
300556b2bdd1SGireesh Nagabhushana * @data: where to store the read data
300656b2bdd1SGireesh Nagabhushana *
300756b2bdd1SGireesh Nagabhushana * Read a 32-bit word from a location in serial EEPROM using the card's PCI
300856b2bdd1SGireesh Nagabhushana * VPD capability. Note that this function must be called with a virtual
300956b2bdd1SGireesh Nagabhushana * address.
301056b2bdd1SGireesh Nagabhushana */
t4_seeprom_read(struct adapter * adapter,u32 addr,u32 * data)30113dde7c95SVishal Kulkarni int t4_seeprom_read(struct adapter *adapter, u32 addr, u32 *data)
301256b2bdd1SGireesh Nagabhushana {
301356b2bdd1SGireesh Nagabhushana unsigned int base = adapter->params.pci.vpd_cap_addr;
30143dde7c95SVishal Kulkarni int ret;
301556b2bdd1SGireesh Nagabhushana
30163dde7c95SVishal Kulkarni /*
30173dde7c95SVishal Kulkarni * VPD Accesses must alway be 4-byte aligned!
30183dde7c95SVishal Kulkarni */
301956b2bdd1SGireesh Nagabhushana if (addr >= EEPROMVSIZE || (addr & 3))
30203dde7c95SVishal Kulkarni return -EINVAL;
302156b2bdd1SGireesh Nagabhushana
30223dde7c95SVishal Kulkarni /*
30233dde7c95SVishal Kulkarni * Wait for any previous operation which may still be in flight to
30243dde7c95SVishal Kulkarni * complete.
30253dde7c95SVishal Kulkarni */
30263dde7c95SVishal Kulkarni ret = t4_seeprom_wait(adapter);
30273dde7c95SVishal Kulkarni if (ret) {
30283dde7c95SVishal Kulkarni CH_ERR(adapter, "VPD still busy from previous operation\n");
30293dde7c95SVishal Kulkarni return ret;
303056b2bdd1SGireesh Nagabhushana }
303156b2bdd1SGireesh Nagabhushana
303256b2bdd1SGireesh Nagabhushana /*
30333dde7c95SVishal Kulkarni * Issue our new VPD Read request, mark the VPD as being busy and wait
30343dde7c95SVishal Kulkarni * for our request to complete. If it doesn't complete, note the
30353dde7c95SVishal Kulkarni * error and return it to our caller. Note that we do not reset the
30363dde7c95SVishal Kulkarni * VPD Busy status!
30373dde7c95SVishal Kulkarni */
30383dde7c95SVishal Kulkarni t4_os_pci_write_cfg2(adapter, base + PCI_VPD_ADDR, (u16)addr);
30393dde7c95SVishal Kulkarni adapter->vpd_busy = 1;
30403dde7c95SVishal Kulkarni adapter->vpd_flag = PCI_VPD_ADDR_F;
30413dde7c95SVishal Kulkarni ret = t4_seeprom_wait(adapter);
30423dde7c95SVishal Kulkarni if (ret) {
30433dde7c95SVishal Kulkarni CH_ERR(adapter, "VPD read of address %#x failed\n", addr);
30443dde7c95SVishal Kulkarni return ret;
30453dde7c95SVishal Kulkarni }
30463dde7c95SVishal Kulkarni
30473dde7c95SVishal Kulkarni /*
30483dde7c95SVishal Kulkarni * Grab the returned data, swizzle it into our endianess and
30493dde7c95SVishal Kulkarni * return success.
30503dde7c95SVishal Kulkarni */
30513dde7c95SVishal Kulkarni t4_os_pci_read_cfg4(adapter, base + PCI_VPD_DATA, data);
30523dde7c95SVishal Kulkarni *data = le32_to_cpu(*data);
30533dde7c95SVishal Kulkarni return 0;
30543dde7c95SVishal Kulkarni }
30553dde7c95SVishal Kulkarni
30563dde7c95SVishal Kulkarni /**
305756b2bdd1SGireesh Nagabhushana * t4_seeprom_write - write a serial EEPROM location
305856b2bdd1SGireesh Nagabhushana * @adapter: adapter to write
305956b2bdd1SGireesh Nagabhushana * @addr: virtual EEPROM address
306056b2bdd1SGireesh Nagabhushana * @data: value to write
306156b2bdd1SGireesh Nagabhushana *
306256b2bdd1SGireesh Nagabhushana * Write a 32-bit word to a location in serial EEPROM using the card's PCI
306356b2bdd1SGireesh Nagabhushana * VPD capability. Note that this function must be called with a virtual
306456b2bdd1SGireesh Nagabhushana * address.
306556b2bdd1SGireesh Nagabhushana */
t4_seeprom_write(struct adapter * adapter,u32 addr,u32 data)30663dde7c95SVishal Kulkarni int t4_seeprom_write(struct adapter *adapter, u32 addr, u32 data)
306756b2bdd1SGireesh Nagabhushana {
306856b2bdd1SGireesh Nagabhushana unsigned int base = adapter->params.pci.vpd_cap_addr;
30693dde7c95SVishal Kulkarni int ret;
30703dde7c95SVishal Kulkarni u32 stats_reg;
30713dde7c95SVishal Kulkarni int max_poll;
307256b2bdd1SGireesh Nagabhushana
30733dde7c95SVishal Kulkarni /*
30743dde7c95SVishal Kulkarni * VPD Accesses must alway be 4-byte aligned!
30753dde7c95SVishal Kulkarni */
307656b2bdd1SGireesh Nagabhushana if (addr >= EEPROMVSIZE || (addr & 3))
30773dde7c95SVishal Kulkarni return -EINVAL;
307856b2bdd1SGireesh Nagabhushana
30793dde7c95SVishal Kulkarni /*
30803dde7c95SVishal Kulkarni * Wait for any previous operation which may still be in flight to
30813dde7c95SVishal Kulkarni * complete.
30823dde7c95SVishal Kulkarni */
30833dde7c95SVishal Kulkarni ret = t4_seeprom_wait(adapter);
30843dde7c95SVishal Kulkarni if (ret) {
30853dde7c95SVishal Kulkarni CH_ERR(adapter, "VPD still busy from previous operation\n");
30863dde7c95SVishal Kulkarni return ret;
30873dde7c95SVishal Kulkarni }
30883dde7c95SVishal Kulkarni
30893dde7c95SVishal Kulkarni /*
30903dde7c95SVishal Kulkarni * Issue our new VPD Read request, mark the VPD as being busy and wait
30913dde7c95SVishal Kulkarni * for our request to complete. If it doesn't complete, note the
30923dde7c95SVishal Kulkarni * error and return it to our caller. Note that we do not reset the
30933dde7c95SVishal Kulkarni * VPD Busy status!
30943dde7c95SVishal Kulkarni */
309556b2bdd1SGireesh Nagabhushana t4_os_pci_write_cfg4(adapter, base + PCI_VPD_DATA,
309656b2bdd1SGireesh Nagabhushana cpu_to_le32(data));
309756b2bdd1SGireesh Nagabhushana t4_os_pci_write_cfg2(adapter, base + PCI_VPD_ADDR,
309856b2bdd1SGireesh Nagabhushana (u16)addr | PCI_VPD_ADDR_F);
30993dde7c95SVishal Kulkarni adapter->vpd_busy = 1;
31003dde7c95SVishal Kulkarni adapter->vpd_flag = 0;
31013dde7c95SVishal Kulkarni ret = t4_seeprom_wait(adapter);
31023dde7c95SVishal Kulkarni if (ret) {
31033dde7c95SVishal Kulkarni CH_ERR(adapter, "VPD write of address %#x failed\n", addr);
31043dde7c95SVishal Kulkarni return ret;
310556b2bdd1SGireesh Nagabhushana }
310656b2bdd1SGireesh Nagabhushana
310756b2bdd1SGireesh Nagabhushana /*
31083dde7c95SVishal Kulkarni * Reset PCI_VPD_DATA register after a transaction and wait for our
31093dde7c95SVishal Kulkarni * request to complete. If it doesn't complete, return error.
31103dde7c95SVishal Kulkarni */
31113dde7c95SVishal Kulkarni t4_os_pci_write_cfg4(adapter, base + PCI_VPD_DATA, 0);
31123dde7c95SVishal Kulkarni max_poll = EEPROM_MAX_POLL;
31133dde7c95SVishal Kulkarni do {
31143dde7c95SVishal Kulkarni udelay(EEPROM_DELAY);
31157e6ad469SVishal Kulkarni t4_seeprom_read(adapter, EEPROM_STAT_ADDR, &stats_reg);
31167e6ad469SVishal Kulkarni } while ((stats_reg & 0x1) && --max_poll);
31173dde7c95SVishal Kulkarni if (!max_poll)
31183dde7c95SVishal Kulkarni return -ETIMEDOUT;
31193dde7c95SVishal Kulkarni
31203dde7c95SVishal Kulkarni /* Return success! */
31213dde7c95SVishal Kulkarni return 0;
31223dde7c95SVishal Kulkarni }
31233dde7c95SVishal Kulkarni
31243dde7c95SVishal Kulkarni /**
312556b2bdd1SGireesh Nagabhushana * t4_eeprom_ptov - translate a physical EEPROM address to virtual
312656b2bdd1SGireesh Nagabhushana * @phys_addr: the physical EEPROM address
312756b2bdd1SGireesh Nagabhushana * @fn: the PCI function number
312856b2bdd1SGireesh Nagabhushana * @sz: size of function-specific area
312956b2bdd1SGireesh Nagabhushana *
313056b2bdd1SGireesh Nagabhushana * Translate a physical EEPROM address to virtual. The first 1K is
313156b2bdd1SGireesh Nagabhushana * accessed through virtual addresses starting at 31K, the rest is
313256b2bdd1SGireesh Nagabhushana * accessed through virtual addresses starting at 0.
313356b2bdd1SGireesh Nagabhushana *
313456b2bdd1SGireesh Nagabhushana * The mapping is as follows:
313556b2bdd1SGireesh Nagabhushana * [0..1K) -> [31K..32K)
313656b2bdd1SGireesh Nagabhushana * [1K..1K+A) -> [ES-A..ES)
313756b2bdd1SGireesh Nagabhushana * [1K+A..ES) -> [0..ES-A-1K)
313856b2bdd1SGireesh Nagabhushana *
313956b2bdd1SGireesh Nagabhushana * where A = @fn * @sz, and ES = EEPROM size.
314056b2bdd1SGireesh Nagabhushana */
t4_eeprom_ptov(unsigned int phys_addr,unsigned int fn,unsigned int sz)31413dde7c95SVishal Kulkarni int t4_eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz)
314256b2bdd1SGireesh Nagabhushana {
314356b2bdd1SGireesh Nagabhushana fn *= sz;
314456b2bdd1SGireesh Nagabhushana if (phys_addr < 1024)
31453dde7c95SVishal Kulkarni return phys_addr + (31 << 10);
314656b2bdd1SGireesh Nagabhushana if (phys_addr < 1024 + fn)
31473dde7c95SVishal Kulkarni return EEPROMSIZE - fn + phys_addr - 1024;
314856b2bdd1SGireesh Nagabhushana if (phys_addr < EEPROMSIZE)
31493dde7c95SVishal Kulkarni return phys_addr - 1024 - fn;
31503dde7c95SVishal Kulkarni return -EINVAL;
315156b2bdd1SGireesh Nagabhushana }
315256b2bdd1SGireesh Nagabhushana
31533dde7c95SVishal Kulkarni /**
315456b2bdd1SGireesh Nagabhushana * t4_seeprom_wp - enable/disable EEPROM write protection
315556b2bdd1SGireesh Nagabhushana * @adapter: the adapter
315656b2bdd1SGireesh Nagabhushana * @enable: whether to enable or disable write protection
315756b2bdd1SGireesh Nagabhushana *
315856b2bdd1SGireesh Nagabhushana * Enables or disables write protection on the serial EEPROM.
315956b2bdd1SGireesh Nagabhushana */
t4_seeprom_wp(struct adapter * adapter,int enable)31603dde7c95SVishal Kulkarni int t4_seeprom_wp(struct adapter *adapter, int enable)
316156b2bdd1SGireesh Nagabhushana {
31623dde7c95SVishal Kulkarni return t4_os_pci_write_seeprom(adapter, EEPROM_STAT_ADDR, enable ? 0xc : 0);
31633dde7c95SVishal Kulkarni }
31643dde7c95SVishal Kulkarni
31653dde7c95SVishal Kulkarni /**
31663dde7c95SVishal Kulkarni * get_vpd_keyword_val - Locates an information field keyword in the VPD
31673dde7c95SVishal Kulkarni * @v: Pointer to buffered vpd data structure
31683dde7c95SVishal Kulkarni * @kw: The keyword to search for
31693dde7c95SVishal Kulkarni *
31703dde7c95SVishal Kulkarni * Returns the value of the information field keyword or
31713dde7c95SVishal Kulkarni * -ENOENT otherwise.
31723dde7c95SVishal Kulkarni */
get_vpd_keyword_val(const struct t4_vpd_hdr * v,const char * kw)31733dde7c95SVishal Kulkarni int get_vpd_keyword_val(const struct t4_vpd_hdr *v, const char *kw)
31743dde7c95SVishal Kulkarni {
31753dde7c95SVishal Kulkarni int i;
31763dde7c95SVishal Kulkarni unsigned int offset , len;
31773dde7c95SVishal Kulkarni const u8 *buf = (const u8 *)v;
31783dde7c95SVishal Kulkarni const u8 *vpdr_len = &v->vpdr_len[0];
31793dde7c95SVishal Kulkarni offset = sizeof(struct t4_vpd_hdr);
31803dde7c95SVishal Kulkarni len = (u16)vpdr_len[0] + ((u16)vpdr_len[1] << 8);
31813dde7c95SVishal Kulkarni
31823dde7c95SVishal Kulkarni if (len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
31833dde7c95SVishal Kulkarni return -ENOENT;
31843dde7c95SVishal Kulkarni }
31853dde7c95SVishal Kulkarni
31863dde7c95SVishal Kulkarni for (i = offset; i + VPD_INFO_FLD_HDR_SIZE <= offset + len;) {
31873dde7c95SVishal Kulkarni if(memcmp(buf + i , kw , 2) == 0){
31883dde7c95SVishal Kulkarni i += VPD_INFO_FLD_HDR_SIZE;
31893dde7c95SVishal Kulkarni return i;
31903dde7c95SVishal Kulkarni }
31913dde7c95SVishal Kulkarni
31923dde7c95SVishal Kulkarni i += VPD_INFO_FLD_HDR_SIZE + buf[i+2];
31933dde7c95SVishal Kulkarni }
31943dde7c95SVishal Kulkarni
31953dde7c95SVishal Kulkarni return -ENOENT;
31963dde7c95SVishal Kulkarni }
31973dde7c95SVishal Kulkarni
31983dde7c95SVishal Kulkarni /*
31993dde7c95SVishal Kulkarni * str_strip
32003dde7c95SVishal Kulkarni * Removes trailing whitespaces from string "s"
32013dde7c95SVishal Kulkarni * Based on strstrip() implementation in string.c
32023dde7c95SVishal Kulkarni */
str_strip(char * s)32033dde7c95SVishal Kulkarni static void str_strip(char *s)
32043dde7c95SVishal Kulkarni {
32053dde7c95SVishal Kulkarni size_t size;
32063dde7c95SVishal Kulkarni char *end;
32073dde7c95SVishal Kulkarni
32083dde7c95SVishal Kulkarni size = strlen(s);
32093dde7c95SVishal Kulkarni if (!size)
32103dde7c95SVishal Kulkarni return;
32113dde7c95SVishal Kulkarni
32123dde7c95SVishal Kulkarni end = s + size - 1;
32133dde7c95SVishal Kulkarni while (end >= s && isspace(*end))
32143dde7c95SVishal Kulkarni end--;
32153dde7c95SVishal Kulkarni *(end + 1) = '\0';
32163dde7c95SVishal Kulkarni }
32173dde7c95SVishal Kulkarni
32183dde7c95SVishal Kulkarni /**
32193dde7c95SVishal Kulkarni * t4_get_raw_vpd_params - read VPD parameters from VPD EEPROM
32203dde7c95SVishal Kulkarni * @adapter: adapter to read
32213dde7c95SVishal Kulkarni * @p: where to store the parameters
32223dde7c95SVishal Kulkarni *
32233dde7c95SVishal Kulkarni * Reads card parameters stored in VPD EEPROM.
32243dde7c95SVishal Kulkarni */
t4_get_raw_vpd_params(struct adapter * adapter,struct vpd_params * p)32253dde7c95SVishal Kulkarni int t4_get_raw_vpd_params(struct adapter *adapter, struct vpd_params *p)
32263dde7c95SVishal Kulkarni {
32273dde7c95SVishal Kulkarni int i, ret = 0, addr;
32283dde7c95SVishal Kulkarni int ec, sn, pn, na;
32293dde7c95SVishal Kulkarni u8 *vpd, csum;
32303dde7c95SVishal Kulkarni const struct t4_vpd_hdr *v;
32313dde7c95SVishal Kulkarni
32323dde7c95SVishal Kulkarni vpd = (u8 *)t4_os_alloc(sizeof(u8) * VPD_LEN);
32333dde7c95SVishal Kulkarni if (!vpd)
32343dde7c95SVishal Kulkarni return -ENOMEM;
32353dde7c95SVishal Kulkarni
32363dde7c95SVishal Kulkarni /* We have two VPD data structures stored in the adapter VPD area.
32373dde7c95SVishal Kulkarni * By default, Linux calculates the size of the VPD area by traversing
32383dde7c95SVishal Kulkarni * the first VPD area at offset 0x0, so we need to tell the OS what
32393dde7c95SVishal Kulkarni * our real VPD size is.
32403dde7c95SVishal Kulkarni */
32413dde7c95SVishal Kulkarni ret = t4_os_pci_set_vpd_size(adapter, VPD_SIZE);
32423dde7c95SVishal Kulkarni if (ret < 0)
32433dde7c95SVishal Kulkarni goto out;
32443dde7c95SVishal Kulkarni
32453dde7c95SVishal Kulkarni /* Card information normally starts at VPD_BASE but early cards had
32463dde7c95SVishal Kulkarni * it at 0.
32473dde7c95SVishal Kulkarni */
32483dde7c95SVishal Kulkarni ret = t4_os_pci_read_seeprom(adapter, VPD_BASE, (u32 *)(vpd));
32493dde7c95SVishal Kulkarni if (ret)
32503dde7c95SVishal Kulkarni goto out;
32513dde7c95SVishal Kulkarni
32523dde7c95SVishal Kulkarni /* The VPD shall have a unique identifier specified by the PCI SIG.
32533dde7c95SVishal Kulkarni * For chelsio adapters, the identifier is 0x82. The first byte of a VPD
32543dde7c95SVishal Kulkarni * shall be CHELSIO_VPD_UNIQUE_ID (0x82). The VPD programming software
32553dde7c95SVishal Kulkarni * is expected to automatically put this entry at the
32563dde7c95SVishal Kulkarni * beginning of the VPD.
32573dde7c95SVishal Kulkarni */
32583dde7c95SVishal Kulkarni addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD;
32593dde7c95SVishal Kulkarni
32603dde7c95SVishal Kulkarni for (i = 0; i < VPD_LEN; i += 4) {
32613dde7c95SVishal Kulkarni ret = t4_os_pci_read_seeprom(adapter, addr+i, (u32 *)(vpd+i));
32623dde7c95SVishal Kulkarni if (ret)
32633dde7c95SVishal Kulkarni goto out;
32643dde7c95SVishal Kulkarni }
32653dde7c95SVishal Kulkarni v = (const struct t4_vpd_hdr *)vpd;
32663dde7c95SVishal Kulkarni
32673dde7c95SVishal Kulkarni #define FIND_VPD_KW(var,name) do { \
32683dde7c95SVishal Kulkarni var = get_vpd_keyword_val(v , name); \
32693dde7c95SVishal Kulkarni if (var < 0) { \
32703dde7c95SVishal Kulkarni CH_ERR(adapter, "missing VPD keyword " name "\n"); \
32713dde7c95SVishal Kulkarni ret = -EINVAL; \
32723dde7c95SVishal Kulkarni goto out; \
32733dde7c95SVishal Kulkarni } \
32743dde7c95SVishal Kulkarni } while (0)
32753dde7c95SVishal Kulkarni
32763dde7c95SVishal Kulkarni FIND_VPD_KW(i, "RV");
32773dde7c95SVishal Kulkarni for (csum = 0; i >= 0; i--)
32783dde7c95SVishal Kulkarni csum += vpd[i];
32793dde7c95SVishal Kulkarni
32803dde7c95SVishal Kulkarni if (csum) {
32813dde7c95SVishal Kulkarni CH_ERR(adapter,
32823dde7c95SVishal Kulkarni "corrupted VPD EEPROM, actual csum %u\n", csum);
32833dde7c95SVishal Kulkarni ret = -EINVAL;
32843dde7c95SVishal Kulkarni goto out;
32853dde7c95SVishal Kulkarni }
32863dde7c95SVishal Kulkarni
32873dde7c95SVishal Kulkarni FIND_VPD_KW(ec, "EC");
32883dde7c95SVishal Kulkarni FIND_VPD_KW(sn, "SN");
32893dde7c95SVishal Kulkarni FIND_VPD_KW(pn, "PN");
32903dde7c95SVishal Kulkarni FIND_VPD_KW(na, "NA");
32913dde7c95SVishal Kulkarni #undef FIND_VPD_KW
32923dde7c95SVishal Kulkarni
32933dde7c95SVishal Kulkarni memcpy(p->id, v->id_data, ID_LEN);
32943dde7c95SVishal Kulkarni str_strip((char *)p->id);
32953dde7c95SVishal Kulkarni memcpy(p->ec, vpd + ec, EC_LEN);
32963dde7c95SVishal Kulkarni str_strip((char *)p->ec);
32973dde7c95SVishal Kulkarni i = vpd[sn - VPD_INFO_FLD_HDR_SIZE + 2];
32983dde7c95SVishal Kulkarni memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
32993dde7c95SVishal Kulkarni str_strip((char *)p->sn);
33003dde7c95SVishal Kulkarni i = vpd[pn - VPD_INFO_FLD_HDR_SIZE + 2];
33013dde7c95SVishal Kulkarni memcpy(p->pn, vpd + pn, min(i, PN_LEN));
33023dde7c95SVishal Kulkarni str_strip((char *)p->pn);
33033dde7c95SVishal Kulkarni i = vpd[na - VPD_INFO_FLD_HDR_SIZE + 2];
33043dde7c95SVishal Kulkarni memcpy(p->na, vpd + na, min(i, MACADDR_LEN));
33053dde7c95SVishal Kulkarni str_strip((char *)p->na);
33063dde7c95SVishal Kulkarni
33073dde7c95SVishal Kulkarni out:
33083dde7c95SVishal Kulkarni kmem_free(vpd, sizeof(u8) * VPD_LEN);
33093dde7c95SVishal Kulkarni return ret < 0 ? ret : 0;
33103dde7c95SVishal Kulkarni }
33113dde7c95SVishal Kulkarni
33123dde7c95SVishal Kulkarni /**
33133dde7c95SVishal Kulkarni * t4_get_vpd_params - read VPD parameters & retrieve Core Clock
33143dde7c95SVishal Kulkarni * @adapter: adapter to read
33153dde7c95SVishal Kulkarni * @p: where to store the parameters
33163dde7c95SVishal Kulkarni *
33173dde7c95SVishal Kulkarni * Reads card parameters stored in VPD EEPROM and retrieves the Core
33183dde7c95SVishal Kulkarni * Clock. This can only be called after a connection to the firmware
33193dde7c95SVishal Kulkarni * is established.
33203dde7c95SVishal Kulkarni */
t4_get_vpd_params(struct adapter * adapter,struct vpd_params * p)33213dde7c95SVishal Kulkarni int t4_get_vpd_params(struct adapter *adapter, struct vpd_params *p)
33223dde7c95SVishal Kulkarni {
33233dde7c95SVishal Kulkarni u32 cclk_param, cclk_val;
33243dde7c95SVishal Kulkarni int ret;
33253dde7c95SVishal Kulkarni
33263dde7c95SVishal Kulkarni /*
33273dde7c95SVishal Kulkarni * Grab the raw VPD parameters.
33283dde7c95SVishal Kulkarni */
33293dde7c95SVishal Kulkarni ret = t4_get_raw_vpd_params(adapter, p);
33303dde7c95SVishal Kulkarni if (ret)
33313dde7c95SVishal Kulkarni return ret;
33323dde7c95SVishal Kulkarni
33333dde7c95SVishal Kulkarni /*
33343dde7c95SVishal Kulkarni * Ask firmware for the Core Clock since it knows how to translate the
33353dde7c95SVishal Kulkarni * Reference Clock ('V2') VPD field into a Core Clock value ...
33363dde7c95SVishal Kulkarni */
33373dde7c95SVishal Kulkarni cclk_param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
33383dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK));
33393dde7c95SVishal Kulkarni ret = t4_query_params(adapter, adapter->mbox, adapter->pf, 0,
33403dde7c95SVishal Kulkarni 1, &cclk_param, &cclk_val);
33413dde7c95SVishal Kulkarni
33423dde7c95SVishal Kulkarni if (ret)
33433dde7c95SVishal Kulkarni return ret;
33443dde7c95SVishal Kulkarni p->cclk = cclk_val;
33453dde7c95SVishal Kulkarni
33463dde7c95SVishal Kulkarni return 0;
334756b2bdd1SGireesh Nagabhushana }
334856b2bdd1SGireesh Nagabhushana
33497e6ad469SVishal Kulkarni /**
33507e6ad469SVishal Kulkarni * t4_get_pfres - retrieve VF resource limits
33517e6ad469SVishal Kulkarni * @adapter: the adapter
33527e6ad469SVishal Kulkarni *
33537e6ad469SVishal Kulkarni * Retrieves configured resource limits and capabilities for a physical
33547e6ad469SVishal Kulkarni * function. The results are stored in @adapter->pfres.
33557e6ad469SVishal Kulkarni */
t4_get_pfres(struct adapter * adapter)33567e6ad469SVishal Kulkarni int t4_get_pfres(struct adapter *adapter)
33577e6ad469SVishal Kulkarni {
33587e6ad469SVishal Kulkarni struct pf_resources *pfres = &adapter->params.pfres;
33597e6ad469SVishal Kulkarni struct fw_pfvf_cmd cmd, rpl;
33607e6ad469SVishal Kulkarni int v;
33617e6ad469SVishal Kulkarni u32 word;
33627e6ad469SVishal Kulkarni
33637e6ad469SVishal Kulkarni /*
33647e6ad469SVishal Kulkarni * Execute PFVF Read command to get VF resource limits; bail out early
33657e6ad469SVishal Kulkarni * with error on command failure.
33667e6ad469SVishal Kulkarni */
33677e6ad469SVishal Kulkarni memset(&cmd, 0, sizeof(cmd));
33687e6ad469SVishal Kulkarni cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) |
33697e6ad469SVishal Kulkarni F_FW_CMD_REQUEST |
33707e6ad469SVishal Kulkarni F_FW_CMD_READ |
33717e6ad469SVishal Kulkarni V_FW_PFVF_CMD_PFN(adapter->pf) |
33727e6ad469SVishal Kulkarni V_FW_PFVF_CMD_VFN(0));
33737e6ad469SVishal Kulkarni cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
33747e6ad469SVishal Kulkarni v = t4_wr_mbox(adapter, adapter->mbox, &cmd, sizeof(cmd), &rpl);
33757e6ad469SVishal Kulkarni if (v != FW_SUCCESS)
33767e6ad469SVishal Kulkarni return v;
33777e6ad469SVishal Kulkarni
33787e6ad469SVishal Kulkarni /*
33797e6ad469SVishal Kulkarni * Extract PF resource limits and return success.
33807e6ad469SVishal Kulkarni */
33817e6ad469SVishal Kulkarni word = be32_to_cpu(rpl.niqflint_niq);
33827e6ad469SVishal Kulkarni pfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word);
33837e6ad469SVishal Kulkarni
33847e6ad469SVishal Kulkarni word = be32_to_cpu(rpl.type_to_neq);
33857e6ad469SVishal Kulkarni pfres->neq = G_FW_PFVF_CMD_NEQ(word);
33867e6ad469SVishal Kulkarni pfres->pmask = G_FW_PFVF_CMD_PMASK(word);
33877e6ad469SVishal Kulkarni
33887e6ad469SVishal Kulkarni word = be32_to_cpu(rpl.tc_to_nexactf);
33897e6ad469SVishal Kulkarni pfres->tc = G_FW_PFVF_CMD_TC(word);
33907e6ad469SVishal Kulkarni pfres->nvi = G_FW_PFVF_CMD_NVI(word);
33917e6ad469SVishal Kulkarni pfres->nexactf = G_FW_PFVF_CMD_NEXACTF(word);
33927e6ad469SVishal Kulkarni
33937e6ad469SVishal Kulkarni word = be32_to_cpu(rpl.r_caps_to_nethctrl);
33947e6ad469SVishal Kulkarni pfres->r_caps = G_FW_PFVF_CMD_R_CAPS(word);
33957e6ad469SVishal Kulkarni pfres->wx_caps = G_FW_PFVF_CMD_WX_CAPS(word);
33967e6ad469SVishal Kulkarni pfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word);
33977e6ad469SVishal Kulkarni
33987e6ad469SVishal Kulkarni return 0;
33997e6ad469SVishal Kulkarni }
34007e6ad469SVishal Kulkarni
340156b2bdd1SGireesh Nagabhushana /* serial flash and firmware constants and flash config file constants */
340256b2bdd1SGireesh Nagabhushana enum {
340356b2bdd1SGireesh Nagabhushana SF_ATTEMPTS = 10, /* max retries for SF operations */
340456b2bdd1SGireesh Nagabhushana
340556b2bdd1SGireesh Nagabhushana /* flash command opcodes */
340656b2bdd1SGireesh Nagabhushana SF_PROG_PAGE = 2, /* program page */
340756b2bdd1SGireesh Nagabhushana SF_WR_DISABLE = 4, /* disable writes */
340856b2bdd1SGireesh Nagabhushana SF_RD_STATUS = 5, /* read status register */
340956b2bdd1SGireesh Nagabhushana SF_WR_ENABLE = 6, /* enable writes */
341056b2bdd1SGireesh Nagabhushana SF_RD_DATA_FAST = 0xb, /* read flash */
341156b2bdd1SGireesh Nagabhushana SF_RD_ID = 0x9f, /* read ID */
341256b2bdd1SGireesh Nagabhushana SF_ERASE_SECTOR = 0xd8, /* erase sector */
341356b2bdd1SGireesh Nagabhushana };
341456b2bdd1SGireesh Nagabhushana
34153dde7c95SVishal Kulkarni /**
341656b2bdd1SGireesh Nagabhushana * sf1_read - read data from the serial flash
341756b2bdd1SGireesh Nagabhushana * @adapter: the adapter
341856b2bdd1SGireesh Nagabhushana * @byte_cnt: number of bytes to read
341956b2bdd1SGireesh Nagabhushana * @cont: whether another operation will be chained
342056b2bdd1SGireesh Nagabhushana * @lock: whether to lock SF for PL access only
342156b2bdd1SGireesh Nagabhushana * @valp: where to store the read data
342256b2bdd1SGireesh Nagabhushana *
342356b2bdd1SGireesh Nagabhushana * Reads up to 4 bytes of data from the serial flash. The location of
342456b2bdd1SGireesh Nagabhushana * the read needs to be specified prior to calling this by issuing the
342556b2bdd1SGireesh Nagabhushana * appropriate commands to the serial flash.
342656b2bdd1SGireesh Nagabhushana */
sf1_read(struct adapter * adapter,unsigned int byte_cnt,int cont,int lock,u32 * valp)34273dde7c95SVishal Kulkarni static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont,
34283dde7c95SVishal Kulkarni int lock, u32 *valp)
342956b2bdd1SGireesh Nagabhushana {
343056b2bdd1SGireesh Nagabhushana int ret;
343156b2bdd1SGireesh Nagabhushana
343256b2bdd1SGireesh Nagabhushana if (!byte_cnt || byte_cnt > 4)
34333dde7c95SVishal Kulkarni return -EINVAL;
343456b2bdd1SGireesh Nagabhushana if (t4_read_reg(adapter, A_SF_OP) & F_BUSY)
34353dde7c95SVishal Kulkarni return -EBUSY;
343656b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_SF_OP,
343756b2bdd1SGireesh Nagabhushana V_SF_LOCK(lock) | V_CONT(cont) | V_BYTECNT(byte_cnt - 1));
343856b2bdd1SGireesh Nagabhushana ret = t4_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 5);
343956b2bdd1SGireesh Nagabhushana if (!ret)
344056b2bdd1SGireesh Nagabhushana *valp = t4_read_reg(adapter, A_SF_DATA);
34413dde7c95SVishal Kulkarni return ret;
344256b2bdd1SGireesh Nagabhushana }
344356b2bdd1SGireesh Nagabhushana
34443dde7c95SVishal Kulkarni /**
344556b2bdd1SGireesh Nagabhushana * sf1_write - write data to the serial flash
344656b2bdd1SGireesh Nagabhushana * @adapter: the adapter
344756b2bdd1SGireesh Nagabhushana * @byte_cnt: number of bytes to write
344856b2bdd1SGireesh Nagabhushana * @cont: whether another operation will be chained
344956b2bdd1SGireesh Nagabhushana * @lock: whether to lock SF for PL access only
345056b2bdd1SGireesh Nagabhushana * @val: value to write
345156b2bdd1SGireesh Nagabhushana *
345256b2bdd1SGireesh Nagabhushana * Writes up to 4 bytes of data to the serial flash. The location of
345356b2bdd1SGireesh Nagabhushana * the write needs to be specified prior to calling this by issuing the
345456b2bdd1SGireesh Nagabhushana * appropriate commands to the serial flash.
345556b2bdd1SGireesh Nagabhushana */
sf1_write(struct adapter * adapter,unsigned int byte_cnt,int cont,int lock,u32 val)34563dde7c95SVishal Kulkarni static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont,
34573dde7c95SVishal Kulkarni int lock, u32 val)
345856b2bdd1SGireesh Nagabhushana {
345956b2bdd1SGireesh Nagabhushana if (!byte_cnt || byte_cnt > 4)
34603dde7c95SVishal Kulkarni return -EINVAL;
346156b2bdd1SGireesh Nagabhushana if (t4_read_reg(adapter, A_SF_OP) & F_BUSY)
34623dde7c95SVishal Kulkarni return -EBUSY;
346356b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_SF_DATA, val);
346456b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_SF_OP, V_SF_LOCK(lock) |
346556b2bdd1SGireesh Nagabhushana V_CONT(cont) | V_BYTECNT(byte_cnt - 1) | V_OP(1));
34663dde7c95SVishal Kulkarni return t4_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 5);
346756b2bdd1SGireesh Nagabhushana }
346856b2bdd1SGireesh Nagabhushana
34693dde7c95SVishal Kulkarni /**
347056b2bdd1SGireesh Nagabhushana * flash_wait_op - wait for a flash operation to complete
347156b2bdd1SGireesh Nagabhushana * @adapter: the adapter
347256b2bdd1SGireesh Nagabhushana * @attempts: max number of polls of the status register
347356b2bdd1SGireesh Nagabhushana * @delay: delay between polls in ms
347456b2bdd1SGireesh Nagabhushana *
347556b2bdd1SGireesh Nagabhushana * Wait for a flash operation to complete by polling the status register.
347656b2bdd1SGireesh Nagabhushana */
flash_wait_op(struct adapter * adapter,int attempts,int ch_delay)34773dde7c95SVishal Kulkarni static int flash_wait_op(struct adapter *adapter, int attempts, int ch_delay)
347856b2bdd1SGireesh Nagabhushana {
34793dde7c95SVishal Kulkarni int ret;
348056b2bdd1SGireesh Nagabhushana u32 status;
348156b2bdd1SGireesh Nagabhushana
348256b2bdd1SGireesh Nagabhushana while (1) {
348356b2bdd1SGireesh Nagabhushana if ((ret = sf1_write(adapter, 1, 1, 1, SF_RD_STATUS)) != 0 ||
348456b2bdd1SGireesh Nagabhushana (ret = sf1_read(adapter, 1, 0, 1, &status)) != 0)
34853dde7c95SVishal Kulkarni return ret;
348656b2bdd1SGireesh Nagabhushana if (!(status & 1))
34873dde7c95SVishal Kulkarni return 0;
34883dde7c95SVishal Kulkarni if (--attempts == 0)
34893dde7c95SVishal Kulkarni return -EAGAIN;
34903dde7c95SVishal Kulkarni if (ch_delay) {
34913dde7c95SVishal Kulkarni #ifdef CONFIG_CUDBG
34923dde7c95SVishal Kulkarni if (adapter->flags & K_CRASH)
34933dde7c95SVishal Kulkarni mdelay(ch_delay);
34943dde7c95SVishal Kulkarni else
34953dde7c95SVishal Kulkarni #endif
34963dde7c95SVishal Kulkarni msleep(ch_delay);
349756b2bdd1SGireesh Nagabhushana }
34983dde7c95SVishal Kulkarni }
349956b2bdd1SGireesh Nagabhushana }
350056b2bdd1SGireesh Nagabhushana
35013dde7c95SVishal Kulkarni /**
350256b2bdd1SGireesh Nagabhushana * t4_read_flash - read words from serial flash
350356b2bdd1SGireesh Nagabhushana * @adapter: the adapter
350456b2bdd1SGireesh Nagabhushana * @addr: the start address for the read
350556b2bdd1SGireesh Nagabhushana * @nwords: how many 32-bit words to read
350656b2bdd1SGireesh Nagabhushana * @data: where to store the read data
350756b2bdd1SGireesh Nagabhushana * @byte_oriented: whether to store data as bytes or as words
350856b2bdd1SGireesh Nagabhushana *
350956b2bdd1SGireesh Nagabhushana * Read the specified number of 32-bit words from the serial flash.
351056b2bdd1SGireesh Nagabhushana * If @byte_oriented is set the read data is stored as a byte array
351156b2bdd1SGireesh Nagabhushana * (i.e., big-endian), otherwise as 32-bit words in the platform's
35123dde7c95SVishal Kulkarni * natural endianness.
351356b2bdd1SGireesh Nagabhushana */
t4_read_flash(struct adapter * adapter,unsigned int addr,unsigned int nwords,u32 * data,int byte_oriented)35143dde7c95SVishal Kulkarni int t4_read_flash(struct adapter *adapter, unsigned int addr,
35153dde7c95SVishal Kulkarni unsigned int nwords, u32 *data, int byte_oriented)
351656b2bdd1SGireesh Nagabhushana {
351756b2bdd1SGireesh Nagabhushana int ret;
351856b2bdd1SGireesh Nagabhushana
35193dde7c95SVishal Kulkarni if (addr + nwords * sizeof(u32) > adapter->params.sf_size || (addr & 3))
35203dde7c95SVishal Kulkarni return -EINVAL;
352156b2bdd1SGireesh Nagabhushana
352256b2bdd1SGireesh Nagabhushana addr = swab32(addr) | SF_RD_DATA_FAST;
352356b2bdd1SGireesh Nagabhushana
352456b2bdd1SGireesh Nagabhushana if ((ret = sf1_write(adapter, 4, 1, 0, addr)) != 0 ||
352556b2bdd1SGireesh Nagabhushana (ret = sf1_read(adapter, 1, 1, 0, data)) != 0)
35263dde7c95SVishal Kulkarni return ret;
352756b2bdd1SGireesh Nagabhushana
35283dde7c95SVishal Kulkarni for ( ; nwords; nwords--, data++) {
352956b2bdd1SGireesh Nagabhushana ret = sf1_read(adapter, 4, nwords > 1, nwords == 1, data);
353056b2bdd1SGireesh Nagabhushana if (nwords == 1)
353156b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
35323dde7c95SVishal Kulkarni if (ret)
35333dde7c95SVishal Kulkarni return ret;
35343dde7c95SVishal Kulkarni if (byte_oriented)
35353dde7c95SVishal Kulkarni *data = (__force __u32)(cpu_to_be32(*data));
353656b2bdd1SGireesh Nagabhushana }
35373dde7c95SVishal Kulkarni return 0;
353856b2bdd1SGireesh Nagabhushana }
353956b2bdd1SGireesh Nagabhushana
35403dde7c95SVishal Kulkarni /**
354156b2bdd1SGireesh Nagabhushana * t4_write_flash - write up to a page of data to the serial flash
354256b2bdd1SGireesh Nagabhushana * @adapter: the adapter
354356b2bdd1SGireesh Nagabhushana * @addr: the start address to write
354456b2bdd1SGireesh Nagabhushana * @n: length of data to write in bytes
354556b2bdd1SGireesh Nagabhushana * @data: the data to write
3546de483253SVishal Kulkarni * @byte_oriented: whether to store data as bytes or as words
354756b2bdd1SGireesh Nagabhushana *
354856b2bdd1SGireesh Nagabhushana * Writes up to a page of data (256 bytes) to the serial flash starting
354956b2bdd1SGireesh Nagabhushana * at the given address. All the data must be written to the same page.
3550de483253SVishal Kulkarni * If @byte_oriented is set the write data is stored as byte stream
3551de483253SVishal Kulkarni * (i.e. matches what on disk), otherwise in big-endian.
355256b2bdd1SGireesh Nagabhushana */
t4_write_flash(struct adapter * adapter,unsigned int addr,unsigned int n,const u8 * data,int byte_oriented)35533dde7c95SVishal Kulkarni int t4_write_flash(struct adapter *adapter, unsigned int addr,
35543dde7c95SVishal Kulkarni unsigned int n, const u8 *data, int byte_oriented)
355556b2bdd1SGireesh Nagabhushana {
355656b2bdd1SGireesh Nagabhushana int ret;
35573dde7c95SVishal Kulkarni u32 buf[64];
355856b2bdd1SGireesh Nagabhushana unsigned int i, c, left, val, offset = addr & 0xff;
355956b2bdd1SGireesh Nagabhushana
356056b2bdd1SGireesh Nagabhushana if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE)
35613dde7c95SVishal Kulkarni return -EINVAL;
356256b2bdd1SGireesh Nagabhushana
356356b2bdd1SGireesh Nagabhushana val = swab32(addr) | SF_PROG_PAGE;
356456b2bdd1SGireesh Nagabhushana
356556b2bdd1SGireesh Nagabhushana if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 ||
356656b2bdd1SGireesh Nagabhushana (ret = sf1_write(adapter, 4, 1, 1, val)) != 0)
356756b2bdd1SGireesh Nagabhushana goto unlock;
356856b2bdd1SGireesh Nagabhushana
356956b2bdd1SGireesh Nagabhushana for (left = n; left; left -= c) {
357056b2bdd1SGireesh Nagabhushana c = min(left, 4U);
357156b2bdd1SGireesh Nagabhushana for (val = 0, i = 0; i < c; ++i)
357256b2bdd1SGireesh Nagabhushana val = (val << 8) + *data++;
357356b2bdd1SGireesh Nagabhushana
3574de483253SVishal Kulkarni if (!byte_oriented)
35753dde7c95SVishal Kulkarni val = cpu_to_be32(val);
3576de483253SVishal Kulkarni
357756b2bdd1SGireesh Nagabhushana ret = sf1_write(adapter, c, c != left, 1, val);
35783dde7c95SVishal Kulkarni if (ret)
357956b2bdd1SGireesh Nagabhushana goto unlock;
358056b2bdd1SGireesh Nagabhushana }
358156b2bdd1SGireesh Nagabhushana ret = flash_wait_op(adapter, 8, 1);
35823dde7c95SVishal Kulkarni if (ret)
358356b2bdd1SGireesh Nagabhushana goto unlock;
358456b2bdd1SGireesh Nagabhushana
358556b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
358656b2bdd1SGireesh Nagabhushana
358756b2bdd1SGireesh Nagabhushana /* Read the page to verify the write succeeded */
3588de483253SVishal Kulkarni ret = t4_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf,
3589de483253SVishal Kulkarni byte_oriented);
35903dde7c95SVishal Kulkarni if (ret)
35913dde7c95SVishal Kulkarni return ret;
359256b2bdd1SGireesh Nagabhushana
359356b2bdd1SGireesh Nagabhushana if (memcmp(data - n, (u8 *)buf + offset, n)) {
35943dde7c95SVishal Kulkarni CH_ERR(adapter,
35953dde7c95SVishal Kulkarni "failed to correctly write the flash page at %#x\n",
35963dde7c95SVishal Kulkarni addr);
35973dde7c95SVishal Kulkarni return -EIO;
359856b2bdd1SGireesh Nagabhushana }
35993dde7c95SVishal Kulkarni return 0;
360056b2bdd1SGireesh Nagabhushana
360156b2bdd1SGireesh Nagabhushana unlock:
360256b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
36033dde7c95SVishal Kulkarni return ret;
360456b2bdd1SGireesh Nagabhushana }
360556b2bdd1SGireesh Nagabhushana
36063dde7c95SVishal Kulkarni /**
360756b2bdd1SGireesh Nagabhushana * t4_get_fw_version - read the firmware version
360856b2bdd1SGireesh Nagabhushana * @adapter: the adapter
360956b2bdd1SGireesh Nagabhushana * @vers: where to place the version
361056b2bdd1SGireesh Nagabhushana *
361156b2bdd1SGireesh Nagabhushana * Reads the FW version from flash.
361256b2bdd1SGireesh Nagabhushana */
t4_get_fw_version(struct adapter * adapter,u32 * vers)36133dde7c95SVishal Kulkarni int t4_get_fw_version(struct adapter *adapter, u32 *vers)
361456b2bdd1SGireesh Nagabhushana {
36153dde7c95SVishal Kulkarni return t4_read_flash(adapter, FLASH_FW_START +
36163dde7c95SVishal Kulkarni offsetof(struct fw_hdr, fw_ver), 1,
36173dde7c95SVishal Kulkarni vers, 0);
361856b2bdd1SGireesh Nagabhushana }
361956b2bdd1SGireesh Nagabhushana
36203dde7c95SVishal Kulkarni /**
36213dde7c95SVishal Kulkarni * t4_get_bs_version - read the firmware bootstrap version
36223dde7c95SVishal Kulkarni * @adapter: the adapter
36233dde7c95SVishal Kulkarni * @vers: where to place the version
36243dde7c95SVishal Kulkarni *
36253dde7c95SVishal Kulkarni * Reads the FW Bootstrap version from flash.
36263dde7c95SVishal Kulkarni */
t4_get_bs_version(struct adapter * adapter,u32 * vers)36273dde7c95SVishal Kulkarni int t4_get_bs_version(struct adapter *adapter, u32 *vers)
36283dde7c95SVishal Kulkarni {
36293dde7c95SVishal Kulkarni return t4_read_flash(adapter, FLASH_FWBOOTSTRAP_START +
36303dde7c95SVishal Kulkarni offsetof(struct fw_hdr, fw_ver), 1,
36313dde7c95SVishal Kulkarni vers, 0);
36323dde7c95SVishal Kulkarni }
36333dde7c95SVishal Kulkarni
36343dde7c95SVishal Kulkarni /**
363556b2bdd1SGireesh Nagabhushana * t4_get_tp_version - read the TP microcode version
363656b2bdd1SGireesh Nagabhushana * @adapter: the adapter
363756b2bdd1SGireesh Nagabhushana * @vers: where to place the version
363856b2bdd1SGireesh Nagabhushana *
363956b2bdd1SGireesh Nagabhushana * Reads the TP microcode version from flash.
364056b2bdd1SGireesh Nagabhushana */
t4_get_tp_version(struct adapter * adapter,u32 * vers)36413dde7c95SVishal Kulkarni int t4_get_tp_version(struct adapter *adapter, u32 *vers)
364256b2bdd1SGireesh Nagabhushana {
36433dde7c95SVishal Kulkarni return t4_read_flash(adapter, FLASH_FW_START +
36443dde7c95SVishal Kulkarni offsetof(struct fw_hdr, tp_microcode_ver),
36453dde7c95SVishal Kulkarni 1, vers, 0);
364656b2bdd1SGireesh Nagabhushana }
364756b2bdd1SGireesh Nagabhushana
36483dde7c95SVishal Kulkarni /**
36493dde7c95SVishal Kulkarni * t4_get_exprom_version - return the Expansion ROM version (if any)
365056b2bdd1SGireesh Nagabhushana * @adapter: the adapter
36513dde7c95SVishal Kulkarni * @vers: where to place the version
36523dde7c95SVishal Kulkarni *
36533dde7c95SVishal Kulkarni * Reads the Expansion ROM header from FLASH and returns the version
36543dde7c95SVishal Kulkarni * number (if present) through the @vers return value pointer. We return
36553dde7c95SVishal Kulkarni * this in the Firmware Version Format since it's convenient. Return
36563dde7c95SVishal Kulkarni * 0 on success, -ENOENT if no Expansion ROM is present.
36573dde7c95SVishal Kulkarni */
t4_get_exprom_version(struct adapter * adapter,u32 * vers)36583dde7c95SVishal Kulkarni int t4_get_exprom_version(struct adapter *adapter, u32 *vers)
36593dde7c95SVishal Kulkarni {
36603dde7c95SVishal Kulkarni struct exprom_header {
36613dde7c95SVishal Kulkarni unsigned char hdr_arr[16]; /* must start with 0x55aa */
36623dde7c95SVishal Kulkarni unsigned char hdr_ver[4]; /* Expansion ROM version */
36633dde7c95SVishal Kulkarni } *hdr;
36643dde7c95SVishal Kulkarni u32 exprom_header_buf[DIV_ROUND_UP(sizeof(struct exprom_header),
36653dde7c95SVishal Kulkarni sizeof(u32))];
36663dde7c95SVishal Kulkarni int ret;
36673dde7c95SVishal Kulkarni
36683dde7c95SVishal Kulkarni ret = t4_read_flash(adapter, FLASH_EXP_ROM_START,
36693dde7c95SVishal Kulkarni ARRAY_SIZE(exprom_header_buf), exprom_header_buf,
36703dde7c95SVishal Kulkarni 0);
36713dde7c95SVishal Kulkarni if (ret)
36723dde7c95SVishal Kulkarni return ret;
36733dde7c95SVishal Kulkarni
36743dde7c95SVishal Kulkarni hdr = (struct exprom_header *)exprom_header_buf;
36753dde7c95SVishal Kulkarni if (hdr->hdr_arr[0] != 0x55 || hdr->hdr_arr[1] != 0xaa)
36763dde7c95SVishal Kulkarni return -ENOENT;
36773dde7c95SVishal Kulkarni
36783dde7c95SVishal Kulkarni *vers = (V_FW_HDR_FW_VER_MAJOR(hdr->hdr_ver[0]) |
36793dde7c95SVishal Kulkarni V_FW_HDR_FW_VER_MINOR(hdr->hdr_ver[1]) |
36803dde7c95SVishal Kulkarni V_FW_HDR_FW_VER_MICRO(hdr->hdr_ver[2]) |
36813dde7c95SVishal Kulkarni V_FW_HDR_FW_VER_BUILD(hdr->hdr_ver[3]));
36823dde7c95SVishal Kulkarni return 0;
36833dde7c95SVishal Kulkarni }
36843dde7c95SVishal Kulkarni
36853dde7c95SVishal Kulkarni /**
36863dde7c95SVishal Kulkarni * t4_get_scfg_version - return the Serial Configuration version
36873dde7c95SVishal Kulkarni * @adapter: the adapter
36883dde7c95SVishal Kulkarni * @vers: where to place the version
36893dde7c95SVishal Kulkarni *
36903dde7c95SVishal Kulkarni * Reads the Serial Configuration Version via the Firmware interface
36913dde7c95SVishal Kulkarni * (thus this can only be called once we're ready to issue Firmware
36923dde7c95SVishal Kulkarni * commands). The format of the Serial Configuration version is
36933dde7c95SVishal Kulkarni * adapter specific. Returns 0 on success, an error on failure.
36943dde7c95SVishal Kulkarni *
36953dde7c95SVishal Kulkarni * Note that early versions of the Firmware didn't include the ability
36963dde7c95SVishal Kulkarni * to retrieve the Serial Configuration version, so we zero-out the
36973dde7c95SVishal Kulkarni * return-value parameter in that case to avoid leaving it with
36983dde7c95SVishal Kulkarni * garbage in it.
36993dde7c95SVishal Kulkarni *
37003dde7c95SVishal Kulkarni * Also note that the Firmware will return its cached copy of the Serial
37013dde7c95SVishal Kulkarni * Initialization Revision ID, not the actual Revision ID as written in
37023dde7c95SVishal Kulkarni * the Serial EEPROM. This is only an issue if a new VPD has been written
37033dde7c95SVishal Kulkarni * and the Firmware/Chip haven't yet gone through a RESET sequence. So
37043dde7c95SVishal Kulkarni * it's best to defer calling this routine till after a FW_RESET_CMD has
37053dde7c95SVishal Kulkarni * been issued if the Host Driver will be performing a full adapter
37063dde7c95SVishal Kulkarni * initialization.
37073dde7c95SVishal Kulkarni */
t4_get_scfg_version(struct adapter * adapter,u32 * vers)37083dde7c95SVishal Kulkarni int t4_get_scfg_version(struct adapter *adapter, u32 *vers)
37093dde7c95SVishal Kulkarni {
37103dde7c95SVishal Kulkarni u32 scfgrev_param;
37113dde7c95SVishal Kulkarni int ret;
37123dde7c95SVishal Kulkarni
37133dde7c95SVishal Kulkarni scfgrev_param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
37143dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_SCFGREV));
37153dde7c95SVishal Kulkarni ret = t4_query_params(adapter, adapter->mbox, adapter->pf, 0,
37163dde7c95SVishal Kulkarni 1, &scfgrev_param, vers);
37173dde7c95SVishal Kulkarni if (ret)
37183dde7c95SVishal Kulkarni *vers = 0;
37193dde7c95SVishal Kulkarni return ret;
37203dde7c95SVishal Kulkarni }
37213dde7c95SVishal Kulkarni
37223dde7c95SVishal Kulkarni /**
37233dde7c95SVishal Kulkarni * t4_get_vpd_version - return the VPD version
37243dde7c95SVishal Kulkarni * @adapter: the adapter
37253dde7c95SVishal Kulkarni * @vers: where to place the version
37263dde7c95SVishal Kulkarni *
37273dde7c95SVishal Kulkarni * Reads the VPD via the Firmware interface (thus this can only be called
37283dde7c95SVishal Kulkarni * once we're ready to issue Firmware commands). The format of the
37293dde7c95SVishal Kulkarni * VPD version is adapter specific. Returns 0 on success, an error on
37303dde7c95SVishal Kulkarni * failure.
37313dde7c95SVishal Kulkarni *
37323dde7c95SVishal Kulkarni * Note that early versions of the Firmware didn't include the ability
37333dde7c95SVishal Kulkarni * to retrieve the VPD version, so we zero-out the return-value parameter
37343dde7c95SVishal Kulkarni * in that case to avoid leaving it with garbage in it.
37353dde7c95SVishal Kulkarni *
37363dde7c95SVishal Kulkarni * Also note that the Firmware will return its cached copy of the VPD
37373dde7c95SVishal Kulkarni * Revision ID, not the actual Revision ID as written in the Serial
37383dde7c95SVishal Kulkarni * EEPROM. This is only an issue if a new VPD has been written and the
37393dde7c95SVishal Kulkarni * Firmware/Chip haven't yet gone through a RESET sequence. So it's best
37403dde7c95SVishal Kulkarni * to defer calling this routine till after a FW_RESET_CMD has been issued
37413dde7c95SVishal Kulkarni * if the Host Driver will be performing a full adapter initialization.
37423dde7c95SVishal Kulkarni */
t4_get_vpd_version(struct adapter * adapter,u32 * vers)37433dde7c95SVishal Kulkarni int t4_get_vpd_version(struct adapter *adapter, u32 *vers)
37443dde7c95SVishal Kulkarni {
37453dde7c95SVishal Kulkarni u32 vpdrev_param;
37463dde7c95SVishal Kulkarni int ret;
37473dde7c95SVishal Kulkarni
37483dde7c95SVishal Kulkarni vpdrev_param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
37493dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_VPDREV));
37503dde7c95SVishal Kulkarni ret = t4_query_params(adapter, adapter->mbox, adapter->pf, 0,
37513dde7c95SVishal Kulkarni 1, &vpdrev_param, vers);
37523dde7c95SVishal Kulkarni if (ret)
37533dde7c95SVishal Kulkarni *vers = 0;
37543dde7c95SVishal Kulkarni return ret;
37553dde7c95SVishal Kulkarni }
37563dde7c95SVishal Kulkarni
37573dde7c95SVishal Kulkarni /**
37583dde7c95SVishal Kulkarni * t4_get_version_info - extract various chip/firmware version information
37593dde7c95SVishal Kulkarni * @adapter: the adapter
37603dde7c95SVishal Kulkarni *
37613dde7c95SVishal Kulkarni * Reads various chip/firmware version numbers and stores them into the
37623dde7c95SVishal Kulkarni * adapter Adapter Parameters structure. If any of the efforts fails
37633dde7c95SVishal Kulkarni * the first failure will be returned, but all of the version numbers
37643dde7c95SVishal Kulkarni * will be read.
37653dde7c95SVishal Kulkarni */
t4_get_version_info(struct adapter * adapter)37663dde7c95SVishal Kulkarni int t4_get_version_info(struct adapter *adapter)
37673dde7c95SVishal Kulkarni {
37683dde7c95SVishal Kulkarni int ret = 0;
37693dde7c95SVishal Kulkarni
37703dde7c95SVishal Kulkarni #define FIRST_RET(__getvinfo) \
37713dde7c95SVishal Kulkarni do { \
37723dde7c95SVishal Kulkarni int __ret = __getvinfo; \
37733dde7c95SVishal Kulkarni if (__ret && !ret) \
37743dde7c95SVishal Kulkarni ret = __ret; \
37753dde7c95SVishal Kulkarni } while (0)
37763dde7c95SVishal Kulkarni
37773dde7c95SVishal Kulkarni FIRST_RET(t4_get_fw_version(adapter, &adapter->params.fw_vers));
37783dde7c95SVishal Kulkarni FIRST_RET(t4_get_bs_version(adapter, &adapter->params.bs_vers));
37793dde7c95SVishal Kulkarni FIRST_RET(t4_get_tp_version(adapter, &adapter->params.tp_vers));
37803dde7c95SVishal Kulkarni FIRST_RET(t4_get_exprom_version(adapter, &adapter->params.er_vers));
37813dde7c95SVishal Kulkarni FIRST_RET(t4_get_scfg_version(adapter, &adapter->params.scfg_vers));
37823dde7c95SVishal Kulkarni FIRST_RET(t4_get_vpd_version(adapter, &adapter->params.vpd_vers));
37833dde7c95SVishal Kulkarni
37843dde7c95SVishal Kulkarni #undef FIRST_RET
37853dde7c95SVishal Kulkarni
37863dde7c95SVishal Kulkarni return ret;
37873dde7c95SVishal Kulkarni }
37883dde7c95SVishal Kulkarni
37893dde7c95SVishal Kulkarni /**
37903dde7c95SVishal Kulkarni * t4_dump_version_info - dump all of the adapter configuration IDs
37913dde7c95SVishal Kulkarni * @adapter: the adapter
37923dde7c95SVishal Kulkarni *
37933dde7c95SVishal Kulkarni * Dumps all of the various bits of adapter configuration version/revision
37943dde7c95SVishal Kulkarni * IDs information. This is typically called at some point after
37953dde7c95SVishal Kulkarni * t4_get_version_info() has been called.
37963dde7c95SVishal Kulkarni */
t4_dump_version_info(struct adapter * adapter)37973dde7c95SVishal Kulkarni void t4_dump_version_info(struct adapter *adapter)
37983dde7c95SVishal Kulkarni {
37993dde7c95SVishal Kulkarni /*
38003dde7c95SVishal Kulkarni * Device information.
38013dde7c95SVishal Kulkarni */
38023dde7c95SVishal Kulkarni CH_INFO(adapter, "Chelsio %s rev %d\n",
38033dde7c95SVishal Kulkarni adapter->params.vpd.id,
38043dde7c95SVishal Kulkarni CHELSIO_CHIP_RELEASE(adapter->params.chip));
38053dde7c95SVishal Kulkarni CH_INFO(adapter, "S/N: %s, P/N: %s\n",
38063dde7c95SVishal Kulkarni adapter->params.vpd.sn,
38073dde7c95SVishal Kulkarni adapter->params.vpd.pn);
38083dde7c95SVishal Kulkarni
38093dde7c95SVishal Kulkarni /*
38103dde7c95SVishal Kulkarni * Firmware Version.
38113dde7c95SVishal Kulkarni */
38123dde7c95SVishal Kulkarni if (!adapter->params.fw_vers)
38133dde7c95SVishal Kulkarni CH_WARN(adapter, "No firmware loaded\n");
38143dde7c95SVishal Kulkarni else
38153dde7c95SVishal Kulkarni CH_INFO(adapter, "Firmware version: %u.%u.%u.%u\n",
38163dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(adapter->params.fw_vers),
38173dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MINOR(adapter->params.fw_vers),
38183dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(adapter->params.fw_vers),
38193dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_BUILD(adapter->params.fw_vers));
38203dde7c95SVishal Kulkarni
38213dde7c95SVishal Kulkarni /*
38223dde7c95SVishal Kulkarni * Bootstrap Firmware Version. (Some adapters don't have Bootstrap
38233dde7c95SVishal Kulkarni * Firmware, so dev_info() is more appropriate here.)
38243dde7c95SVishal Kulkarni */
38253dde7c95SVishal Kulkarni if (!adapter->params.bs_vers)
38263dde7c95SVishal Kulkarni CH_INFO(adapter, "No bootstrap loaded\n");
38273dde7c95SVishal Kulkarni else
38283dde7c95SVishal Kulkarni CH_INFO(adapter, "Bootstrap version: %u.%u.%u.%u\n",
38293dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(adapter->params.bs_vers),
38303dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MINOR(adapter->params.bs_vers),
38313dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(adapter->params.bs_vers),
38323dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_BUILD(adapter->params.bs_vers));
38333dde7c95SVishal Kulkarni
38343dde7c95SVishal Kulkarni /*
38353dde7c95SVishal Kulkarni * TP Microcode Version.
38363dde7c95SVishal Kulkarni */
38373dde7c95SVishal Kulkarni if (!adapter->params.tp_vers)
38383dde7c95SVishal Kulkarni CH_WARN(adapter, "No TP Microcode loaded\n");
38393dde7c95SVishal Kulkarni else
38403dde7c95SVishal Kulkarni CH_INFO(adapter, "TP Microcode version: %u.%u.%u.%u\n",
38413dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(adapter->params.tp_vers),
38423dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MINOR(adapter->params.tp_vers),
38433dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(adapter->params.tp_vers),
38443dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_BUILD(adapter->params.tp_vers));
38453dde7c95SVishal Kulkarni
38463dde7c95SVishal Kulkarni /*
38473dde7c95SVishal Kulkarni * Expansion ROM version.
38483dde7c95SVishal Kulkarni */
38493dde7c95SVishal Kulkarni if (!adapter->params.er_vers)
38503dde7c95SVishal Kulkarni CH_INFO(adapter, "No Expansion ROM loaded\n");
38513dde7c95SVishal Kulkarni else
38523dde7c95SVishal Kulkarni CH_INFO(adapter, "Expansion ROM version: %u.%u.%u.%u\n",
38533dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(adapter->params.er_vers),
38543dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MINOR(adapter->params.er_vers),
38553dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(adapter->params.er_vers),
38563dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_BUILD(adapter->params.er_vers));
38573dde7c95SVishal Kulkarni
38583dde7c95SVishal Kulkarni
38593dde7c95SVishal Kulkarni /*
38603dde7c95SVishal Kulkarni * Serial Configuration version.
38613dde7c95SVishal Kulkarni */
38623dde7c95SVishal Kulkarni CH_INFO(adapter, "Serial Configuration version: %x\n",
38633dde7c95SVishal Kulkarni adapter->params.scfg_vers);
38643dde7c95SVishal Kulkarni
38653dde7c95SVishal Kulkarni /*
38663dde7c95SVishal Kulkarni * VPD version.
38673dde7c95SVishal Kulkarni */
38683dde7c95SVishal Kulkarni CH_INFO(adapter, "VPD version: %x\n",
38693dde7c95SVishal Kulkarni adapter->params.vpd_vers);
38703dde7c95SVishal Kulkarni }
38713dde7c95SVishal Kulkarni
38723dde7c95SVishal Kulkarni /**
38733dde7c95SVishal Kulkarni * t4_check_fw_version - check if the FW is supported with this driver
38743dde7c95SVishal Kulkarni * @adap: the adapter
387556b2bdd1SGireesh Nagabhushana *
387656b2bdd1SGireesh Nagabhushana * Checks if an adapter's FW is compatible with the driver. Returns 0
387756b2bdd1SGireesh Nagabhushana * if there's exact match, a negative error if the version could not be
38783dde7c95SVishal Kulkarni * read or there's a major version mismatch
387956b2bdd1SGireesh Nagabhushana */
t4_check_fw_version(struct adapter * adap)38803dde7c95SVishal Kulkarni int t4_check_fw_version(struct adapter *adap)
388156b2bdd1SGireesh Nagabhushana {
388256b2bdd1SGireesh Nagabhushana int ret, major, minor, micro;
3883de483253SVishal Kulkarni int exp_major, exp_minor, exp_micro;
38843dde7c95SVishal Kulkarni unsigned int chip_version = CHELSIO_CHIP_VERSION(adap->params.chip);
388556b2bdd1SGireesh Nagabhushana
38863dde7c95SVishal Kulkarni ret = t4_get_fw_version(adap, &adap->params.fw_vers);
38873dde7c95SVishal Kulkarni if (ret)
38883dde7c95SVishal Kulkarni return ret;
3889de483253SVishal Kulkarni
38903dde7c95SVishal Kulkarni major = G_FW_HDR_FW_VER_MAJOR(adap->params.fw_vers);
38913dde7c95SVishal Kulkarni minor = G_FW_HDR_FW_VER_MINOR(adap->params.fw_vers);
38923dde7c95SVishal Kulkarni micro = G_FW_HDR_FW_VER_MICRO(adap->params.fw_vers);
389356b2bdd1SGireesh Nagabhushana
38943dde7c95SVishal Kulkarni switch (chip_version) {
3895de483253SVishal Kulkarni case CHELSIO_T4:
38963dde7c95SVishal Kulkarni exp_major = T4FW_MIN_VERSION_MAJOR;
38973dde7c95SVishal Kulkarni exp_minor = T4FW_MIN_VERSION_MINOR;
38983dde7c95SVishal Kulkarni exp_micro = T4FW_MIN_VERSION_MICRO;
3899de483253SVishal Kulkarni break;
3900de483253SVishal Kulkarni case CHELSIO_T5:
39013dde7c95SVishal Kulkarni exp_major = T5FW_MIN_VERSION_MAJOR;
39023dde7c95SVishal Kulkarni exp_minor = T5FW_MIN_VERSION_MINOR;
39033dde7c95SVishal Kulkarni exp_micro = T5FW_MIN_VERSION_MICRO;
39043dde7c95SVishal Kulkarni break;
39053dde7c95SVishal Kulkarni case CHELSIO_T6:
39063dde7c95SVishal Kulkarni exp_major = T6FW_MIN_VERSION_MAJOR;
39073dde7c95SVishal Kulkarni exp_minor = T6FW_MIN_VERSION_MINOR;
39083dde7c95SVishal Kulkarni exp_micro = T6FW_MIN_VERSION_MICRO;
3909de483253SVishal Kulkarni break;
3910de483253SVishal Kulkarni default:
39113dde7c95SVishal Kulkarni CH_ERR(adap, "Unsupported chip type, %x\n",
39123dde7c95SVishal Kulkarni adap->params.chip);
3913de483253SVishal Kulkarni return -EINVAL;
3914de483253SVishal Kulkarni }
3915de483253SVishal Kulkarni
39163dde7c95SVishal Kulkarni if (major < exp_major || (major == exp_major && minor < exp_minor) ||
39173dde7c95SVishal Kulkarni (major == exp_major && minor == exp_minor && micro < exp_micro)) {
39183dde7c95SVishal Kulkarni CH_ERR(adap, "Card has firmware version %u.%u.%u, minimum "
39193dde7c95SVishal Kulkarni "supported firmware is %u.%u.%u.\n", major, minor,
39203dde7c95SVishal Kulkarni micro, exp_major, exp_minor, exp_micro);
39213dde7c95SVishal Kulkarni return -EFAULT;
39223dde7c95SVishal Kulkarni }
39233dde7c95SVishal Kulkarni return 0;
392456b2bdd1SGireesh Nagabhushana }
392556b2bdd1SGireesh Nagabhushana
39263dde7c95SVishal Kulkarni /* Is the given firmware API compatible with the one the driver was compiled
39273dde7c95SVishal Kulkarni * with?
39283dde7c95SVishal Kulkarni */
fw_compatible(const struct fw_hdr * hdr1,const struct fw_hdr * hdr2)39293dde7c95SVishal Kulkarni static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2)
39303dde7c95SVishal Kulkarni {
39313dde7c95SVishal Kulkarni
39323dde7c95SVishal Kulkarni /* short circuit if it's the exact same firmware version */
39333dde7c95SVishal Kulkarni if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver)
39343dde7c95SVishal Kulkarni return 1;
39353dde7c95SVishal Kulkarni
393656b2bdd1SGireesh Nagabhushana /*
39373dde7c95SVishal Kulkarni * XXX: Is this too conservative? Perhaps I should limit this to the
39383dde7c95SVishal Kulkarni * features that are supported in the driver.
39393dde7c95SVishal Kulkarni */
39403dde7c95SVishal Kulkarni #define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x)
39413dde7c95SVishal Kulkarni if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) &&
39423dde7c95SVishal Kulkarni SAME_INTF(ofld) && SAME_INTF(ri) && SAME_INTF(iscsipdu) &&
39433dde7c95SVishal Kulkarni SAME_INTF(iscsi) && SAME_INTF(fcoepdu) && SAME_INTF(fcoe))
39443dde7c95SVishal Kulkarni return 1;
39453dde7c95SVishal Kulkarni #undef SAME_INTF
39463dde7c95SVishal Kulkarni
39473dde7c95SVishal Kulkarni return 0;
39483dde7c95SVishal Kulkarni }
39493dde7c95SVishal Kulkarni
39503dde7c95SVishal Kulkarni /* The firmware in the filesystem is usable, but should it be installed?
39513dde7c95SVishal Kulkarni * This routine explains itself in detail if it indicates the filesystem
39523dde7c95SVishal Kulkarni * firmware should be installed.
39533dde7c95SVishal Kulkarni */
should_install_fs_fw(struct adapter * adap,int card_fw_usable,int k,int c,int t4_fw_install)39543dde7c95SVishal Kulkarni static int should_install_fs_fw(struct adapter *adap, int card_fw_usable,
39553dde7c95SVishal Kulkarni int k, int c, int t4_fw_install)
39563dde7c95SVishal Kulkarni {
39573dde7c95SVishal Kulkarni const char *reason;
39583dde7c95SVishal Kulkarni
39593dde7c95SVishal Kulkarni if (!card_fw_usable) {
39603dde7c95SVishal Kulkarni reason = "incompatible or unusable";
39613dde7c95SVishal Kulkarni goto install;
39623dde7c95SVishal Kulkarni }
39633dde7c95SVishal Kulkarni
39643dde7c95SVishal Kulkarni if (k > c) {
39653dde7c95SVishal Kulkarni reason = "older than the version bundled with this driver";
39663dde7c95SVishal Kulkarni goto install;
39673dde7c95SVishal Kulkarni }
39683dde7c95SVishal Kulkarni
39693dde7c95SVishal Kulkarni if (t4_fw_install == 2 && k != c) {
39703dde7c95SVishal Kulkarni reason = "different than the version bundled with this driver";
39713dde7c95SVishal Kulkarni goto install;
39723dde7c95SVishal Kulkarni }
39733dde7c95SVishal Kulkarni
39743dde7c95SVishal Kulkarni return 0;
39753dde7c95SVishal Kulkarni
39763dde7c95SVishal Kulkarni install:
39773dde7c95SVishal Kulkarni if (t4_fw_install == 0) {
39783dde7c95SVishal Kulkarni CH_ERR(adap, "firmware on card (%u.%u.%u.%u) is %s, "
39793dde7c95SVishal Kulkarni "but the driver is prohibited from installing a "
39803dde7c95SVishal Kulkarni "different firmware on the card.\n",
39813dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(c), G_FW_HDR_FW_VER_MINOR(c),
39823dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(c), G_FW_HDR_FW_VER_BUILD(c),
39833dde7c95SVishal Kulkarni reason);
39843dde7c95SVishal Kulkarni
39853dde7c95SVishal Kulkarni return (0);
39863dde7c95SVishal Kulkarni }
39873dde7c95SVishal Kulkarni
39883dde7c95SVishal Kulkarni CH_ERR(adap, "firmware on card (%u.%u.%u.%u) is %s, "
39893dde7c95SVishal Kulkarni "installing firmware %u.%u.%u.%u on card.\n",
39903dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(c), G_FW_HDR_FW_VER_MINOR(c),
39913dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(c), G_FW_HDR_FW_VER_BUILD(c), reason,
39923dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(k), G_FW_HDR_FW_VER_MINOR(k),
39933dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(k), G_FW_HDR_FW_VER_BUILD(k));
39943dde7c95SVishal Kulkarni
39953dde7c95SVishal Kulkarni return 1;
39963dde7c95SVishal Kulkarni }
39973dde7c95SVishal Kulkarni
t4_prep_fw(struct adapter * adap,struct fw_info * fw_info,const u8 * fw_data,unsigned int fw_size,struct fw_hdr * card_fw,const int t4_fw_install,enum dev_state state,int * reset)39983dde7c95SVishal Kulkarni int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
39993dde7c95SVishal Kulkarni const u8 *fw_data, unsigned int fw_size,
40003dde7c95SVishal Kulkarni struct fw_hdr *card_fw, const int t4_fw_install,
40013dde7c95SVishal Kulkarni enum dev_state state, int *reset)
40023dde7c95SVishal Kulkarni {
40033dde7c95SVishal Kulkarni int ret, card_fw_usable, fs_fw_usable;
40043dde7c95SVishal Kulkarni const struct fw_hdr *fs_fw;
40053dde7c95SVishal Kulkarni const struct fw_hdr *drv_fw;
40063dde7c95SVishal Kulkarni
40073dde7c95SVishal Kulkarni drv_fw = &fw_info->fw_hdr;
40083dde7c95SVishal Kulkarni
40093dde7c95SVishal Kulkarni /* Read the header of the firmware on the card */
40103dde7c95SVishal Kulkarni ret = -t4_read_flash(adap, FLASH_FW_START,
40113dde7c95SVishal Kulkarni sizeof(*card_fw) / sizeof(uint32_t),
40123dde7c95SVishal Kulkarni (uint32_t *)card_fw, 1);
40133dde7c95SVishal Kulkarni if (ret == 0) {
40143dde7c95SVishal Kulkarni card_fw_usable = fw_compatible(drv_fw, (const void *)card_fw);
40153dde7c95SVishal Kulkarni } else {
40163dde7c95SVishal Kulkarni CH_ERR(adap,
40173dde7c95SVishal Kulkarni "Unable to read card's firmware header: %d\n", ret);
40183dde7c95SVishal Kulkarni card_fw_usable = 0;
40193dde7c95SVishal Kulkarni }
40203dde7c95SVishal Kulkarni
40213dde7c95SVishal Kulkarni if (fw_data != NULL) {
40223dde7c95SVishal Kulkarni fs_fw = (const void *)fw_data;
40233dde7c95SVishal Kulkarni fs_fw_usable = fw_compatible(drv_fw, fs_fw);
40243dde7c95SVishal Kulkarni } else {
40253dde7c95SVishal Kulkarni fs_fw = NULL;
40263dde7c95SVishal Kulkarni fs_fw_usable = 0;
40273dde7c95SVishal Kulkarni }
40283dde7c95SVishal Kulkarni
40293dde7c95SVishal Kulkarni if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
40303dde7c95SVishal Kulkarni (!fs_fw_usable || fs_fw->fw_ver == drv_fw->fw_ver)) {
40313dde7c95SVishal Kulkarni /* Common case: the firmware on the card is an exact match and
40323dde7c95SVishal Kulkarni * the filesystem one is an exact match too, or the filesystem
40333dde7c95SVishal Kulkarni * one is absent/incompatible. Note that t4_fw_install = 2
40343dde7c95SVishal Kulkarni * is ignored here -- use cxgbtool loadfw if you want to
40353dde7c95SVishal Kulkarni * reinstall the same firmware as the one on the card.
40363dde7c95SVishal Kulkarni */
40373dde7c95SVishal Kulkarni } else if (fs_fw_usable && state == DEV_STATE_UNINIT &&
40383dde7c95SVishal Kulkarni should_install_fs_fw(adap, card_fw_usable,
40393dde7c95SVishal Kulkarni be32_to_cpu(fs_fw->fw_ver),
40403dde7c95SVishal Kulkarni be32_to_cpu(card_fw->fw_ver),
40413dde7c95SVishal Kulkarni t4_fw_install)) {
40423dde7c95SVishal Kulkarni
40433dde7c95SVishal Kulkarni ret = -t4_fw_upgrade(adap, adap->mbox, fw_data,
40443dde7c95SVishal Kulkarni fw_size, 0);
40453dde7c95SVishal Kulkarni if (ret != 0) {
40463dde7c95SVishal Kulkarni CH_ERR(adap,
40473dde7c95SVishal Kulkarni "failed to install firmware: %d\n", ret);
40483dde7c95SVishal Kulkarni goto bye;
40493dde7c95SVishal Kulkarni }
40503dde7c95SVishal Kulkarni
40513dde7c95SVishal Kulkarni /* Installed successfully, update cached information */
40523dde7c95SVishal Kulkarni memcpy(card_fw, fs_fw, sizeof(*card_fw));
40533dde7c95SVishal Kulkarni (void)t4_init_devlog_params(adap, 1);
40543dde7c95SVishal Kulkarni card_fw_usable = 1;
40553dde7c95SVishal Kulkarni *reset = 0; /* already reset as part of load_fw */
40563dde7c95SVishal Kulkarni }
40573dde7c95SVishal Kulkarni
40583dde7c95SVishal Kulkarni if (!card_fw_usable) {
40593dde7c95SVishal Kulkarni uint32_t d, c, k;
40603dde7c95SVishal Kulkarni
40613dde7c95SVishal Kulkarni d = be32_to_cpu(drv_fw->fw_ver);
40623dde7c95SVishal Kulkarni c = be32_to_cpu(card_fw->fw_ver);
40633dde7c95SVishal Kulkarni k = fs_fw ? be32_to_cpu(fs_fw->fw_ver) : 0;
40643dde7c95SVishal Kulkarni
40653dde7c95SVishal Kulkarni CH_ERR(adap, "Cannot find a usable firmware: "
40663dde7c95SVishal Kulkarni "fw_install %d, chip state %d, "
40673dde7c95SVishal Kulkarni "driver compiled with %d.%d.%d.%d, "
40683dde7c95SVishal Kulkarni "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n",
40693dde7c95SVishal Kulkarni t4_fw_install, state,
40703dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(d), G_FW_HDR_FW_VER_MINOR(d),
40713dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(d), G_FW_HDR_FW_VER_BUILD(d),
40723dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(c), G_FW_HDR_FW_VER_MINOR(c),
40733dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(c), G_FW_HDR_FW_VER_BUILD(c),
40743dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MAJOR(k), G_FW_HDR_FW_VER_MINOR(k),
40753dde7c95SVishal Kulkarni G_FW_HDR_FW_VER_MICRO(k), G_FW_HDR_FW_VER_BUILD(k));
40763dde7c95SVishal Kulkarni ret = EINVAL;
40773dde7c95SVishal Kulkarni goto bye;
40783dde7c95SVishal Kulkarni }
40793dde7c95SVishal Kulkarni
40803dde7c95SVishal Kulkarni /* We're using whatever's on the card and it's known to be good. */
40813dde7c95SVishal Kulkarni adap->params.fw_vers = be32_to_cpu(card_fw->fw_ver);
40823dde7c95SVishal Kulkarni adap->params.tp_vers = be32_to_cpu(card_fw->tp_microcode_ver);
40833dde7c95SVishal Kulkarni
40843dde7c95SVishal Kulkarni bye:
40853dde7c95SVishal Kulkarni return ret;
40863dde7c95SVishal Kulkarni
40873dde7c95SVishal Kulkarni }
40883dde7c95SVishal Kulkarni
40893dde7c95SVishal Kulkarni /**
409056b2bdd1SGireesh Nagabhushana * t4_flash_erase_sectors - erase a range of flash sectors
409156b2bdd1SGireesh Nagabhushana * @adapter: the adapter
409256b2bdd1SGireesh Nagabhushana * @start: the first sector to erase
409356b2bdd1SGireesh Nagabhushana * @end: the last sector to erase
409456b2bdd1SGireesh Nagabhushana *
409556b2bdd1SGireesh Nagabhushana * Erases the sectors in the given inclusive range.
409656b2bdd1SGireesh Nagabhushana */
t4_flash_erase_sectors(struct adapter * adapter,int start,int end)40973dde7c95SVishal Kulkarni int t4_flash_erase_sectors(struct adapter *adapter, int start, int end)
409856b2bdd1SGireesh Nagabhushana {
409956b2bdd1SGireesh Nagabhushana int ret = 0;
410056b2bdd1SGireesh Nagabhushana
41013dde7c95SVishal Kulkarni if (end >= adapter->params.sf_nsec)
41023dde7c95SVishal Kulkarni return -EINVAL;
41033dde7c95SVishal Kulkarni
410456b2bdd1SGireesh Nagabhushana while (start <= end) {
410556b2bdd1SGireesh Nagabhushana if ((ret = sf1_write(adapter, 1, 0, 1, SF_WR_ENABLE)) != 0 ||
410656b2bdd1SGireesh Nagabhushana (ret = sf1_write(adapter, 4, 0, 1,
410756b2bdd1SGireesh Nagabhushana SF_ERASE_SECTOR | (start << 8))) != 0 ||
410856b2bdd1SGireesh Nagabhushana (ret = flash_wait_op(adapter, 14, 500)) != 0) {
41093dde7c95SVishal Kulkarni CH_ERR(adapter,
41103dde7c95SVishal Kulkarni "erase of flash sector %d failed, error %d\n",
41113dde7c95SVishal Kulkarni start, ret);
411256b2bdd1SGireesh Nagabhushana break;
411356b2bdd1SGireesh Nagabhushana }
411456b2bdd1SGireesh Nagabhushana start++;
411556b2bdd1SGireesh Nagabhushana }
411656b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
41173dde7c95SVishal Kulkarni return ret;
411856b2bdd1SGireesh Nagabhushana }
411956b2bdd1SGireesh Nagabhushana
41203dde7c95SVishal Kulkarni /**
412156b2bdd1SGireesh Nagabhushana * t4_flash_cfg_addr - return the address of the flash configuration file
412256b2bdd1SGireesh Nagabhushana * @adapter: the adapter
412356b2bdd1SGireesh Nagabhushana *
412456b2bdd1SGireesh Nagabhushana * Return the address within the flash where the Firmware Configuration
4125de483253SVishal Kulkarni * File is stored, or an error if the device FLASH is too small to contain
4126de483253SVishal Kulkarni * a Firmware Configuration File.
412756b2bdd1SGireesh Nagabhushana */
t4_flash_cfg_addr(struct adapter * adapter)41283dde7c95SVishal Kulkarni int t4_flash_cfg_addr(struct adapter *adapter)
412956b2bdd1SGireesh Nagabhushana {
4130de483253SVishal Kulkarni /*
4131de483253SVishal Kulkarni * If the device FLASH isn't large enough to hold a Firmware
4132de483253SVishal Kulkarni * Configuration File, return an error.
4133de483253SVishal Kulkarni */
4134de483253SVishal Kulkarni if (adapter->params.sf_size < FLASH_CFG_START + FLASH_CFG_MAX_SIZE)
4135de483253SVishal Kulkarni return -ENOSPC;
4136de483253SVishal Kulkarni
4137de483253SVishal Kulkarni return FLASH_CFG_START;
413856b2bdd1SGireesh Nagabhushana }
413956b2bdd1SGireesh Nagabhushana
41403dde7c95SVishal Kulkarni /* Return TRUE if the specified firmware matches the adapter. I.e. T4
41413dde7c95SVishal Kulkarni * firmware for T4 adapters, T5 firmware for T5 adapters, etc. We go ahead
41423dde7c95SVishal Kulkarni * and emit an error message for mismatched firmware to save our caller the
41433dde7c95SVishal Kulkarni * effort ...
414456b2bdd1SGireesh Nagabhushana */
t4_fw_matches_chip(const struct adapter * adap,const struct fw_hdr * hdr)41453dde7c95SVishal Kulkarni static int t4_fw_matches_chip(const struct adapter *adap,
41463dde7c95SVishal Kulkarni const struct fw_hdr *hdr)
414756b2bdd1SGireesh Nagabhushana {
4148de483253SVishal Kulkarni /*
41493dde7c95SVishal Kulkarni * The expression below will return FALSE for any unsupported adapter
41503dde7c95SVishal Kulkarni * which will keep us "honest" in the future ...
4151de483253SVishal Kulkarni */
41523dde7c95SVishal Kulkarni if ((is_t4(adap->params.chip) && hdr->chip == FW_HDR_CHIP_T4) ||
41533dde7c95SVishal Kulkarni (is_t5(adap->params.chip) && hdr->chip == FW_HDR_CHIP_T5) ||
41543dde7c95SVishal Kulkarni (is_t6(adap->params.chip) && hdr->chip == FW_HDR_CHIP_T6))
41553dde7c95SVishal Kulkarni return 1;
415656b2bdd1SGireesh Nagabhushana
41573dde7c95SVishal Kulkarni CH_ERR(adap,
41583dde7c95SVishal Kulkarni "FW image (%d) is not suitable for this adapter (%d)\n",
41593dde7c95SVishal Kulkarni hdr->chip, CHELSIO_CHIP_VERSION(adap->params.chip));
41603dde7c95SVishal Kulkarni return 0;
416156b2bdd1SGireesh Nagabhushana }
416256b2bdd1SGireesh Nagabhushana
41633dde7c95SVishal Kulkarni /**
416456b2bdd1SGireesh Nagabhushana * t4_load_fw - download firmware
416556b2bdd1SGireesh Nagabhushana * @adap: the adapter
416656b2bdd1SGireesh Nagabhushana * @fw_data: the firmware image to write
416756b2bdd1SGireesh Nagabhushana * @size: image size
41683dde7c95SVishal Kulkarni * @bootstrap: indicates if the binary is a bootstrap fw
416956b2bdd1SGireesh Nagabhushana *
417056b2bdd1SGireesh Nagabhushana * Write the supplied firmware image to the card's serial flash.
417156b2bdd1SGireesh Nagabhushana */
t4_load_fw(struct adapter * adap,const u8 * fw_data,unsigned int size,unsigned int bootstrap)41723dde7c95SVishal Kulkarni int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size,
41733dde7c95SVishal Kulkarni unsigned int bootstrap)
417456b2bdd1SGireesh Nagabhushana {
417556b2bdd1SGireesh Nagabhushana u32 csum;
417656b2bdd1SGireesh Nagabhushana int ret, addr;
417756b2bdd1SGireesh Nagabhushana unsigned int i;
417856b2bdd1SGireesh Nagabhushana u8 first_page[SF_PAGE_SIZE];
41793dde7c95SVishal Kulkarni const __be32 *p = (const __be32 *)fw_data;
418056b2bdd1SGireesh Nagabhushana const struct fw_hdr *hdr = (const struct fw_hdr *)fw_data;
418156b2bdd1SGireesh Nagabhushana unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
4182de483253SVishal Kulkarni unsigned int fw_start_sec;
4183de483253SVishal Kulkarni unsigned int fw_start;
4184de483253SVishal Kulkarni unsigned int fw_size;
4185de483253SVishal Kulkarni
41863dde7c95SVishal Kulkarni if (bootstrap) {
4187de483253SVishal Kulkarni fw_start_sec = FLASH_FWBOOTSTRAP_START_SEC;
4188de483253SVishal Kulkarni fw_start = FLASH_FWBOOTSTRAP_START;
4189de483253SVishal Kulkarni fw_size = FLASH_FWBOOTSTRAP_MAX_SIZE;
4190de483253SVishal Kulkarni } else {
4191de483253SVishal Kulkarni fw_start_sec = FLASH_FW_START_SEC;
4192de483253SVishal Kulkarni fw_start = FLASH_FW_START;
4193de483253SVishal Kulkarni fw_size = FLASH_FW_MAX_SIZE;
4194de483253SVishal Kulkarni }
4195de483253SVishal Kulkarni
419656b2bdd1SGireesh Nagabhushana if (!size) {
4197de483253SVishal Kulkarni CH_ERR(adap, "FW image has no data\n");
41983dde7c95SVishal Kulkarni return -EINVAL;
419956b2bdd1SGireesh Nagabhushana }
420056b2bdd1SGireesh Nagabhushana if (size & 511) {
42013dde7c95SVishal Kulkarni CH_ERR(adap,
42023dde7c95SVishal Kulkarni "FW image size not multiple of 512 bytes\n");
42033dde7c95SVishal Kulkarni return -EINVAL;
420456b2bdd1SGireesh Nagabhushana }
42053dde7c95SVishal Kulkarni if ((unsigned int) be16_to_cpu(hdr->len512) * 512 != size) {
42063dde7c95SVishal Kulkarni CH_ERR(adap,
42073dde7c95SVishal Kulkarni "FW image size differs from size in FW header\n");
42083dde7c95SVishal Kulkarni return -EINVAL;
420956b2bdd1SGireesh Nagabhushana }
4210de483253SVishal Kulkarni if (size > fw_size) {
42113dde7c95SVishal Kulkarni CH_ERR(adap, "FW image too large, max is %u bytes\n",
42123dde7c95SVishal Kulkarni fw_size);
42133dde7c95SVishal Kulkarni return -EFBIG;
421456b2bdd1SGireesh Nagabhushana }
42153dde7c95SVishal Kulkarni if (!t4_fw_matches_chip(adap, hdr))
42163dde7c95SVishal Kulkarni return -EINVAL;
42173dde7c95SVishal Kulkarni
42183dde7c95SVishal Kulkarni for (csum = 0, i = 0; i < size / sizeof(csum); i++)
42193dde7c95SVishal Kulkarni csum += be32_to_cpu(p[i]);
42203dde7c95SVishal Kulkarni
42213dde7c95SVishal Kulkarni if (csum != 0xffffffff) {
4222de483253SVishal Kulkarni CH_ERR(adap,
42233dde7c95SVishal Kulkarni "corrupted firmware image, checksum %#x\n", csum);
4224de483253SVishal Kulkarni return -EINVAL;
4225de483253SVishal Kulkarni }
422656b2bdd1SGireesh Nagabhushana
422756b2bdd1SGireesh Nagabhushana i = DIV_ROUND_UP(size, sf_sec_size); /* # of sectors spanned */
42283dde7c95SVishal Kulkarni ret = t4_flash_erase_sectors(adap, fw_start_sec, fw_start_sec + i - 1);
42293dde7c95SVishal Kulkarni if (ret)
423056b2bdd1SGireesh Nagabhushana goto out;
423156b2bdd1SGireesh Nagabhushana
423256b2bdd1SGireesh Nagabhushana /*
423356b2bdd1SGireesh Nagabhushana * We write the correct version at the end so the driver can see a bad
423456b2bdd1SGireesh Nagabhushana * version if the FW write fails. Start by writing a copy of the
423556b2bdd1SGireesh Nagabhushana * first page with a bad version.
423656b2bdd1SGireesh Nagabhushana */
42373dde7c95SVishal Kulkarni memcpy(first_page, fw_data, SF_PAGE_SIZE);
42383dde7c95SVishal Kulkarni ((struct fw_hdr *)first_page)->fw_ver = cpu_to_be32(0xffffffff);
4239de483253SVishal Kulkarni ret = t4_write_flash(adap, fw_start, SF_PAGE_SIZE, first_page, 1);
42403dde7c95SVishal Kulkarni if (ret)
424156b2bdd1SGireesh Nagabhushana goto out;
424256b2bdd1SGireesh Nagabhushana
4243de483253SVishal Kulkarni addr = fw_start;
424456b2bdd1SGireesh Nagabhushana for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
424556b2bdd1SGireesh Nagabhushana addr += SF_PAGE_SIZE;
424656b2bdd1SGireesh Nagabhushana fw_data += SF_PAGE_SIZE;
4247de483253SVishal Kulkarni ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, fw_data, 1);
42483dde7c95SVishal Kulkarni if (ret)
424956b2bdd1SGireesh Nagabhushana goto out;
425056b2bdd1SGireesh Nagabhushana }
425156b2bdd1SGireesh Nagabhushana
42523dde7c95SVishal Kulkarni ret = t4_write_flash(adap,
42533dde7c95SVishal Kulkarni fw_start + offsetof(struct fw_hdr, fw_ver),
4254de483253SVishal Kulkarni sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver, 1);
425556b2bdd1SGireesh Nagabhushana out:
42563dde7c95SVishal Kulkarni if (ret)
42573dde7c95SVishal Kulkarni CH_ERR(adap, "firmware download failed, error %d\n",
42583dde7c95SVishal Kulkarni ret);
42593dde7c95SVishal Kulkarni else {
42603dde7c95SVishal Kulkarni if (bootstrap)
42613dde7c95SVishal Kulkarni ret = t4_get_bs_version(adap, &adap->params.bs_vers);
42623dde7c95SVishal Kulkarni else
42633dde7c95SVishal Kulkarni ret = t4_get_fw_version(adap, &adap->params.fw_vers);
42643dde7c95SVishal Kulkarni }
42653dde7c95SVishal Kulkarni return ret;
426656b2bdd1SGireesh Nagabhushana }
426756b2bdd1SGireesh Nagabhushana
42683dde7c95SVishal Kulkarni /**
42693dde7c95SVishal Kulkarni * t4_phy_fw_ver - return current PHY firmware version
427056b2bdd1SGireesh Nagabhushana * @adap: the adapter
42713dde7c95SVishal Kulkarni * @phy_fw_ver: return value buffer for PHY firmware version
427256b2bdd1SGireesh Nagabhushana *
42733dde7c95SVishal Kulkarni * Returns the current version of external PHY firmware on the
42743dde7c95SVishal Kulkarni * adapter.
427556b2bdd1SGireesh Nagabhushana */
t4_phy_fw_ver(struct adapter * adap,int * phy_fw_ver)42763dde7c95SVishal Kulkarni int t4_phy_fw_ver(struct adapter *adap, int *phy_fw_ver)
427756b2bdd1SGireesh Nagabhushana {
42783dde7c95SVishal Kulkarni u32 param, val;
42793dde7c95SVishal Kulkarni int ret;
428056b2bdd1SGireesh Nagabhushana
42813dde7c95SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
42823dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PHYFW) |
42833dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_Y(adap->params.portvec) |
42843dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_Z(FW_PARAMS_PARAM_DEV_PHYFW_VERSION));
42853dde7c95SVishal Kulkarni ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,
42863dde7c95SVishal Kulkarni ¶m, &val);
42873dde7c95SVishal Kulkarni if (ret < 0)
42883dde7c95SVishal Kulkarni return ret;
42893dde7c95SVishal Kulkarni *phy_fw_ver = val;
42903dde7c95SVishal Kulkarni return 0;
429156b2bdd1SGireesh Nagabhushana }
429256b2bdd1SGireesh Nagabhushana
42933dde7c95SVishal Kulkarni /**
42943dde7c95SVishal Kulkarni * t4_load_phy_fw - download port PHY firmware
429556b2bdd1SGireesh Nagabhushana * @adap: the adapter
42963dde7c95SVishal Kulkarni * @win: the PCI-E Memory Window index to use for t4_memory_rw()
42973dde7c95SVishal Kulkarni * @lock: the lock to use to guard the memory copy
42983dde7c95SVishal Kulkarni * @phy_fw_version: function to check PHY firmware versions
42993dde7c95SVishal Kulkarni * @phy_fw_data: the PHY firmware image to write
43003dde7c95SVishal Kulkarni * @phy_fw_size: image size
430156b2bdd1SGireesh Nagabhushana *
43023dde7c95SVishal Kulkarni * Transfer the specified PHY firmware to the adapter. If a non-NULL
43033dde7c95SVishal Kulkarni * @phy_fw_version is supplied, then it will be used to determine if
43043dde7c95SVishal Kulkarni * it's necessary to perform the transfer by comparing the version
43053dde7c95SVishal Kulkarni * of any existing adapter PHY firmware with that of the passed in
43063dde7c95SVishal Kulkarni * PHY firmware image. If @lock is non-NULL then it will be used
43073dde7c95SVishal Kulkarni * around the call to t4_memory_rw() which transfers the PHY firmware
43083dde7c95SVishal Kulkarni * to the adapter.
43093dde7c95SVishal Kulkarni *
43103dde7c95SVishal Kulkarni * A negative error number will be returned if an error occurs. If
43113dde7c95SVishal Kulkarni * version number support is available and there's no need to upgrade
43123dde7c95SVishal Kulkarni * the firmware, 0 will be returned. If firmware is successfully
43133dde7c95SVishal Kulkarni * transferred to the adapter, 1 will be retured.
43143dde7c95SVishal Kulkarni *
43153dde7c95SVishal Kulkarni * NOTE: some adapters only have local RAM to store the PHY firmware. As
43163dde7c95SVishal Kulkarni * a result, a RESET of the adapter would cause that RAM to lose its
43173dde7c95SVishal Kulkarni * contents. Thus, loading PHY firmware on such adapters must happen after any
43183dde7c95SVishal Kulkarni * FW_RESET_CMDs ...
431956b2bdd1SGireesh Nagabhushana */
t4_load_phy_fw(struct adapter * adap,int win,t4_os_lock_t * lock,int (* phy_fw_version)(const u8 *,size_t),const u8 * phy_fw_data,size_t phy_fw_size)43203dde7c95SVishal Kulkarni int t4_load_phy_fw(struct adapter *adap,
43213dde7c95SVishal Kulkarni int win, t4_os_lock_t *lock,
43223dde7c95SVishal Kulkarni int (*phy_fw_version)(const u8 *, size_t),
43233dde7c95SVishal Kulkarni const u8 *phy_fw_data, size_t phy_fw_size)
432456b2bdd1SGireesh Nagabhushana {
43253dde7c95SVishal Kulkarni unsigned long mtype = 0, maddr = 0;
43263dde7c95SVishal Kulkarni u32 param, val;
43273dde7c95SVishal Kulkarni int cur_phy_fw_ver = 0, new_phy_fw_vers = 0;
43283dde7c95SVishal Kulkarni int ret;
432956b2bdd1SGireesh Nagabhushana
4330de483253SVishal Kulkarni /*
43313dde7c95SVishal Kulkarni * If we have version number support, then check to see if the adapter
43323dde7c95SVishal Kulkarni * already has up-to-date PHY firmware loaded.
4333de483253SVishal Kulkarni */
43343dde7c95SVishal Kulkarni if (phy_fw_version) {
43353dde7c95SVishal Kulkarni new_phy_fw_vers = phy_fw_version(phy_fw_data, phy_fw_size);
43363dde7c95SVishal Kulkarni ret = t4_phy_fw_ver(adap, &cur_phy_fw_ver);
43373dde7c95SVishal Kulkarni if (ret < 0)
43383dde7c95SVishal Kulkarni return ret;;
43393dde7c95SVishal Kulkarni
43403dde7c95SVishal Kulkarni if (cur_phy_fw_ver >= new_phy_fw_vers) {
43413dde7c95SVishal Kulkarni CH_WARN(adap, "PHY Firmware already up-to-date, "
43423dde7c95SVishal Kulkarni "version %#x\n", cur_phy_fw_ver);
43433dde7c95SVishal Kulkarni return 0;
434456b2bdd1SGireesh Nagabhushana }
434556b2bdd1SGireesh Nagabhushana }
434656b2bdd1SGireesh Nagabhushana
434756b2bdd1SGireesh Nagabhushana /*
43483dde7c95SVishal Kulkarni * Ask the firmware where it wants us to copy the PHY firmware image.
43493dde7c95SVishal Kulkarni * The size of the file requires a special version of the READ coommand
43503dde7c95SVishal Kulkarni * which will pass the file size via the values field in PARAMS_CMD and
43513dde7c95SVishal Kulkarni * retreive the return value from firmware and place it in the same
43523dde7c95SVishal Kulkarni * buffer values
43533dde7c95SVishal Kulkarni */
43543dde7c95SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
43553dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PHYFW) |
43563dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_Y(adap->params.portvec) |
43573dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_Z(FW_PARAMS_PARAM_DEV_PHYFW_DOWNLOAD));
43583dde7c95SVishal Kulkarni val = phy_fw_size;
43593dde7c95SVishal Kulkarni ret = t4_query_params_rw(adap, adap->mbox, adap->pf, 0, 1,
43603dde7c95SVishal Kulkarni ¶m, &val, 1, true);
43613dde7c95SVishal Kulkarni if (ret < 0)
43623dde7c95SVishal Kulkarni return ret;
43633dde7c95SVishal Kulkarni mtype = val >> 8;
43643dde7c95SVishal Kulkarni maddr = (val & 0xff) << 16;
43653dde7c95SVishal Kulkarni
43663dde7c95SVishal Kulkarni /*
43673dde7c95SVishal Kulkarni * Copy the supplied PHY Firmware image to the adapter memory location
43683dde7c95SVishal Kulkarni * allocated by the adapter firmware.
43693dde7c95SVishal Kulkarni */
43703dde7c95SVishal Kulkarni if (lock)
43713dde7c95SVishal Kulkarni t4_os_lock(lock);
43723dde7c95SVishal Kulkarni ret = t4_memory_rw(adap, win, mtype, maddr,
43733dde7c95SVishal Kulkarni phy_fw_size, (__be32*)phy_fw_data,
43743dde7c95SVishal Kulkarni T4_MEMORY_WRITE);
43753dde7c95SVishal Kulkarni if (lock)
43763dde7c95SVishal Kulkarni t4_os_unlock(lock);
43773dde7c95SVishal Kulkarni if (ret)
43783dde7c95SVishal Kulkarni return ret;
43793dde7c95SVishal Kulkarni
43803dde7c95SVishal Kulkarni /*
43813dde7c95SVishal Kulkarni * Tell the firmware that the PHY firmware image has been written to
43823dde7c95SVishal Kulkarni * RAM and it can now start copying it over to the PHYs. The chip
43833dde7c95SVishal Kulkarni * firmware will RESET the affected PHYs as part of this operation
43843dde7c95SVishal Kulkarni * leaving them running the new PHY firmware image.
43853dde7c95SVishal Kulkarni */
43863dde7c95SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
43873dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PHYFW) |
43883dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_Y(adap->params.portvec) |
43893dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_Z(FW_PARAMS_PARAM_DEV_PHYFW_DOWNLOAD));
43903dde7c95SVishal Kulkarni ret = t4_set_params_timeout(adap, adap->mbox, adap->pf, 0, 1,
43913dde7c95SVishal Kulkarni ¶m, &val, 30000);
43923dde7c95SVishal Kulkarni
43933dde7c95SVishal Kulkarni /*
43943dde7c95SVishal Kulkarni * If we have version number support, then check to see that the new
43953dde7c95SVishal Kulkarni * firmware got loaded properly.
43963dde7c95SVishal Kulkarni */
43973dde7c95SVishal Kulkarni if (phy_fw_version) {
43983dde7c95SVishal Kulkarni ret = t4_phy_fw_ver(adap, &cur_phy_fw_ver);
43993dde7c95SVishal Kulkarni if (ret < 0)
44003dde7c95SVishal Kulkarni return ret;
44013dde7c95SVishal Kulkarni
44023dde7c95SVishal Kulkarni if (cur_phy_fw_ver != new_phy_fw_vers) {
44033dde7c95SVishal Kulkarni CH_WARN(adap, "PHY Firmware did not update: "
44043dde7c95SVishal Kulkarni "version on adapter %#x, "
44053dde7c95SVishal Kulkarni "version flashed %#x\n",
44063dde7c95SVishal Kulkarni cur_phy_fw_ver, new_phy_fw_vers);
44073dde7c95SVishal Kulkarni return -ENXIO;
44083dde7c95SVishal Kulkarni }
44093dde7c95SVishal Kulkarni }
44103dde7c95SVishal Kulkarni
44113dde7c95SVishal Kulkarni return 1;
44123dde7c95SVishal Kulkarni }
44133dde7c95SVishal Kulkarni
44143dde7c95SVishal Kulkarni /**
44153dde7c95SVishal Kulkarni * t4_fwcache - firmware cache operation
441656b2bdd1SGireesh Nagabhushana * @adap: the adapter
44173dde7c95SVishal Kulkarni * @op : the operation (flush or flush and invalidate)
441856b2bdd1SGireesh Nagabhushana */
t4_fwcache(struct adapter * adap,enum fw_params_param_dev_fwcache op)44193dde7c95SVishal Kulkarni int t4_fwcache(struct adapter *adap, enum fw_params_param_dev_fwcache op)
442056b2bdd1SGireesh Nagabhushana {
44213dde7c95SVishal Kulkarni struct fw_params_cmd c;
442256b2bdd1SGireesh Nagabhushana
44233dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
44243dde7c95SVishal Kulkarni c.op_to_vfn =
44253dde7c95SVishal Kulkarni cpu_to_be32(V_FW_CMD_OP(FW_PARAMS_CMD) |
44263dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
44273dde7c95SVishal Kulkarni V_FW_PARAMS_CMD_PFN(adap->pf) |
44283dde7c95SVishal Kulkarni V_FW_PARAMS_CMD_VFN(0));
44293dde7c95SVishal Kulkarni c.retval_len16 = cpu_to_be32(FW_LEN16(c));
44303dde7c95SVishal Kulkarni c.param[0].mnem =
44313dde7c95SVishal Kulkarni cpu_to_be32(V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
44323dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FWCACHE));
44333dde7c95SVishal Kulkarni c.param[0].val = (__force __be32)op;
443456b2bdd1SGireesh Nagabhushana
44353dde7c95SVishal Kulkarni return t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), NULL);
443656b2bdd1SGireesh Nagabhushana }
443756b2bdd1SGireesh Nagabhushana
t4_cim_read_pif_la(struct adapter * adap,u32 * pif_req,u32 * pif_rsp,unsigned int * pif_req_wrptr,unsigned int * pif_rsp_wrptr)44383dde7c95SVishal Kulkarni void t4_cim_read_pif_la(struct adapter *adap, u32 *pif_req, u32 *pif_rsp,
44393dde7c95SVishal Kulkarni unsigned int *pif_req_wrptr,
44403dde7c95SVishal Kulkarni unsigned int *pif_rsp_wrptr)
444156b2bdd1SGireesh Nagabhushana {
444256b2bdd1SGireesh Nagabhushana int i, j;
444356b2bdd1SGireesh Nagabhushana u32 cfg, val, req, rsp;
444456b2bdd1SGireesh Nagabhushana
444556b2bdd1SGireesh Nagabhushana cfg = t4_read_reg(adap, A_CIM_DEBUGCFG);
444656b2bdd1SGireesh Nagabhushana if (cfg & F_LADBGEN)
444756b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_CIM_DEBUGCFG, cfg ^ F_LADBGEN);
444856b2bdd1SGireesh Nagabhushana
444956b2bdd1SGireesh Nagabhushana val = t4_read_reg(adap, A_CIM_DEBUGSTS);
445056b2bdd1SGireesh Nagabhushana req = G_POLADBGWRPTR(val);
445156b2bdd1SGireesh Nagabhushana rsp = G_PILADBGWRPTR(val);
44523dde7c95SVishal Kulkarni if (pif_req_wrptr)
445356b2bdd1SGireesh Nagabhushana *pif_req_wrptr = req;
44543dde7c95SVishal Kulkarni if (pif_rsp_wrptr)
445556b2bdd1SGireesh Nagabhushana *pif_rsp_wrptr = rsp;
445656b2bdd1SGireesh Nagabhushana
445756b2bdd1SGireesh Nagabhushana for (i = 0; i < CIM_PIFLA_SIZE; i++) {
445856b2bdd1SGireesh Nagabhushana for (j = 0; j < 6; j++) {
445956b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_CIM_DEBUGCFG, V_POLADBGRDPTR(req) |
446056b2bdd1SGireesh Nagabhushana V_PILADBGRDPTR(rsp));
446156b2bdd1SGireesh Nagabhushana *pif_req++ = t4_read_reg(adap, A_CIM_PO_LA_DEBUGDATA);
446256b2bdd1SGireesh Nagabhushana *pif_rsp++ = t4_read_reg(adap, A_CIM_PI_LA_DEBUGDATA);
446356b2bdd1SGireesh Nagabhushana req++;
446456b2bdd1SGireesh Nagabhushana rsp++;
446556b2bdd1SGireesh Nagabhushana }
446656b2bdd1SGireesh Nagabhushana req = (req + 2) & M_POLADBGRDPTR;
446756b2bdd1SGireesh Nagabhushana rsp = (rsp + 2) & M_PILADBGRDPTR;
446856b2bdd1SGireesh Nagabhushana }
446956b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_CIM_DEBUGCFG, cfg);
447056b2bdd1SGireesh Nagabhushana }
447156b2bdd1SGireesh Nagabhushana
t4_cim_read_ma_la(struct adapter * adap,u32 * ma_req,u32 * ma_rsp)44723dde7c95SVishal Kulkarni void t4_cim_read_ma_la(struct adapter *adap, u32 *ma_req, u32 *ma_rsp)
447356b2bdd1SGireesh Nagabhushana {
447456b2bdd1SGireesh Nagabhushana u32 cfg;
447556b2bdd1SGireesh Nagabhushana int i, j, idx;
447656b2bdd1SGireesh Nagabhushana
447756b2bdd1SGireesh Nagabhushana cfg = t4_read_reg(adap, A_CIM_DEBUGCFG);
447856b2bdd1SGireesh Nagabhushana if (cfg & F_LADBGEN)
447956b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_CIM_DEBUGCFG, cfg ^ F_LADBGEN);
448056b2bdd1SGireesh Nagabhushana
448156b2bdd1SGireesh Nagabhushana for (i = 0; i < CIM_MALA_SIZE; i++) {
448256b2bdd1SGireesh Nagabhushana for (j = 0; j < 5; j++) {
448356b2bdd1SGireesh Nagabhushana idx = 8 * i + j;
448456b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_CIM_DEBUGCFG, V_POLADBGRDPTR(idx) |
448556b2bdd1SGireesh Nagabhushana V_PILADBGRDPTR(idx));
448656b2bdd1SGireesh Nagabhushana *ma_req++ = t4_read_reg(adap, A_CIM_PO_LA_MADEBUGDATA);
448756b2bdd1SGireesh Nagabhushana *ma_rsp++ = t4_read_reg(adap, A_CIM_PI_LA_MADEBUGDATA);
448856b2bdd1SGireesh Nagabhushana }
448956b2bdd1SGireesh Nagabhushana }
449056b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_CIM_DEBUGCFG, cfg);
449156b2bdd1SGireesh Nagabhushana }
449256b2bdd1SGireesh Nagabhushana
t4_ulprx_read_la(struct adapter * adap,u32 * la_buf)44933dde7c95SVishal Kulkarni void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
449456b2bdd1SGireesh Nagabhushana {
449556b2bdd1SGireesh Nagabhushana unsigned int i, j;
449656b2bdd1SGireesh Nagabhushana
449756b2bdd1SGireesh Nagabhushana for (i = 0; i < 8; i++) {
449856b2bdd1SGireesh Nagabhushana u32 *p = la_buf + i;
449956b2bdd1SGireesh Nagabhushana
450056b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_ULP_RX_LA_CTL, i);
450156b2bdd1SGireesh Nagabhushana j = t4_read_reg(adap, A_ULP_RX_LA_WRPTR);
450256b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_ULP_RX_LA_RDPTR, j);
450356b2bdd1SGireesh Nagabhushana for (j = 0; j < ULPRX_LA_SIZE; j++, p += 8)
450456b2bdd1SGireesh Nagabhushana *p = t4_read_reg(adap, A_ULP_RX_LA_RDDATA);
450556b2bdd1SGireesh Nagabhushana }
450656b2bdd1SGireesh Nagabhushana }
450756b2bdd1SGireesh Nagabhushana
45083dde7c95SVishal Kulkarni typedef void (*int_handler_t)(struct adapter *adap);
45093dde7c95SVishal Kulkarni
451056b2bdd1SGireesh Nagabhushana struct intr_info {
451156b2bdd1SGireesh Nagabhushana unsigned int mask; /* bits to check in interrupt status */
451256b2bdd1SGireesh Nagabhushana const char *msg; /* message to print or NULL */
451356b2bdd1SGireesh Nagabhushana short stat_idx; /* stat counter to increment or -1 */
451456b2bdd1SGireesh Nagabhushana unsigned short fatal; /* whether the condition reported is fatal */
45153dde7c95SVishal Kulkarni int_handler_t int_handler; /* platform-specific int handler */
451656b2bdd1SGireesh Nagabhushana };
451756b2bdd1SGireesh Nagabhushana
45183dde7c95SVishal Kulkarni /**
451956b2bdd1SGireesh Nagabhushana * t4_handle_intr_status - table driven interrupt handler
452056b2bdd1SGireesh Nagabhushana * @adapter: the adapter that generated the interrupt
452156b2bdd1SGireesh Nagabhushana * @reg: the interrupt status register to process
452256b2bdd1SGireesh Nagabhushana * @acts: table of interrupt actions
452356b2bdd1SGireesh Nagabhushana *
452456b2bdd1SGireesh Nagabhushana * A table driven interrupt handler that applies a set of masks to an
452556b2bdd1SGireesh Nagabhushana * interrupt status word and performs the corresponding actions if the
45263dde7c95SVishal Kulkarni * interrupts described by the mask have occurred. The actions include
452756b2bdd1SGireesh Nagabhushana * optionally emitting a warning or alert message. The table is terminated
452856b2bdd1SGireesh Nagabhushana * by an entry specifying mask 0. Returns the number of fatal interrupt
452956b2bdd1SGireesh Nagabhushana * conditions.
453056b2bdd1SGireesh Nagabhushana */
t4_handle_intr_status(struct adapter * adapter,unsigned int reg,const struct intr_info * acts)45313dde7c95SVishal Kulkarni static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg,
453256b2bdd1SGireesh Nagabhushana const struct intr_info *acts)
453356b2bdd1SGireesh Nagabhushana {
453456b2bdd1SGireesh Nagabhushana int fatal = 0;
453556b2bdd1SGireesh Nagabhushana unsigned int mask = 0;
453656b2bdd1SGireesh Nagabhushana unsigned int status = t4_read_reg(adapter, reg);
453756b2bdd1SGireesh Nagabhushana
45383dde7c95SVishal Kulkarni for ( ; acts->mask; ++acts) {
453956b2bdd1SGireesh Nagabhushana if (!(status & acts->mask))
454056b2bdd1SGireesh Nagabhushana continue;
45413dde7c95SVishal Kulkarni if (acts->fatal) {
454256b2bdd1SGireesh Nagabhushana fatal++;
45433dde7c95SVishal Kulkarni CH_ALERT(adapter, "%s (0x%x)\n", acts->msg,
45443dde7c95SVishal Kulkarni status & acts->mask);
45453dde7c95SVishal Kulkarni } else if (acts->msg)
45463dde7c95SVishal Kulkarni CH_WARN_RATELIMIT(adapter, "%s (0x%x)\n", acts->msg,
45473dde7c95SVishal Kulkarni status & acts->mask);
45483dde7c95SVishal Kulkarni if (acts->int_handler)
45493dde7c95SVishal Kulkarni acts->int_handler(adapter);
455056b2bdd1SGireesh Nagabhushana mask |= acts->mask;
455156b2bdd1SGireesh Nagabhushana }
455256b2bdd1SGireesh Nagabhushana status &= mask;
45533dde7c95SVishal Kulkarni if (status) /* clear processed interrupts */
455456b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, reg, status);
45553dde7c95SVishal Kulkarni return fatal;
455656b2bdd1SGireesh Nagabhushana }
455756b2bdd1SGireesh Nagabhushana
455856b2bdd1SGireesh Nagabhushana /*
455956b2bdd1SGireesh Nagabhushana * Interrupt handler for the PCIE module.
456056b2bdd1SGireesh Nagabhushana */
pcie_intr_handler(struct adapter * adapter)45613dde7c95SVishal Kulkarni static void pcie_intr_handler(struct adapter *adapter)
456256b2bdd1SGireesh Nagabhushana {
45633dde7c95SVishal Kulkarni static const struct intr_info sysbus_intr_info[] = {
456456b2bdd1SGireesh Nagabhushana { F_RNPP, "RXNP array parity error", -1, 1 },
456556b2bdd1SGireesh Nagabhushana { F_RPCP, "RXPC array parity error", -1, 1 },
456656b2bdd1SGireesh Nagabhushana { F_RCIP, "RXCIF array parity error", -1, 1 },
456756b2bdd1SGireesh Nagabhushana { F_RCCP, "Rx completions control array parity error", -1, 1 },
456856b2bdd1SGireesh Nagabhushana { F_RFTP, "RXFT array parity error", -1, 1 },
456956b2bdd1SGireesh Nagabhushana { 0 }
457056b2bdd1SGireesh Nagabhushana };
45713dde7c95SVishal Kulkarni static const struct intr_info pcie_port_intr_info[] = {
457256b2bdd1SGireesh Nagabhushana { F_TPCP, "TXPC array parity error", -1, 1 },
457356b2bdd1SGireesh Nagabhushana { F_TNPP, "TXNP array parity error", -1, 1 },
457456b2bdd1SGireesh Nagabhushana { F_TFTP, "TXFT array parity error", -1, 1 },
457556b2bdd1SGireesh Nagabhushana { F_TCAP, "TXCA array parity error", -1, 1 },
457656b2bdd1SGireesh Nagabhushana { F_TCIP, "TXCIF array parity error", -1, 1 },
457756b2bdd1SGireesh Nagabhushana { F_RCAP, "RXCA array parity error", -1, 1 },
457856b2bdd1SGireesh Nagabhushana { F_OTDD, "outbound request TLP discarded", -1, 1 },
457956b2bdd1SGireesh Nagabhushana { F_RDPE, "Rx data parity error", -1, 1 },
458056b2bdd1SGireesh Nagabhushana { F_TDUE, "Tx uncorrectable data error", -1, 1 },
458156b2bdd1SGireesh Nagabhushana { 0 }
458256b2bdd1SGireesh Nagabhushana };
45833dde7c95SVishal Kulkarni static const struct intr_info pcie_intr_info[] = {
458456b2bdd1SGireesh Nagabhushana { F_MSIADDRLPERR, "MSI AddrL parity error", -1, 1 },
458556b2bdd1SGireesh Nagabhushana { F_MSIADDRHPERR, "MSI AddrH parity error", -1, 1 },
458656b2bdd1SGireesh Nagabhushana { F_MSIDATAPERR, "MSI data parity error", -1, 1 },
458756b2bdd1SGireesh Nagabhushana { F_MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
458856b2bdd1SGireesh Nagabhushana { F_MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
458956b2bdd1SGireesh Nagabhushana { F_MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
459056b2bdd1SGireesh Nagabhushana { F_MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
459156b2bdd1SGireesh Nagabhushana { F_PIOCPLPERR, "PCI PIO completion FIFO parity error", -1, 1 },
459256b2bdd1SGireesh Nagabhushana { F_PIOREQPERR, "PCI PIO request FIFO parity error", -1, 1 },
459356b2bdd1SGireesh Nagabhushana { F_TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
459456b2bdd1SGireesh Nagabhushana { F_CCNTPERR, "PCI CMD channel count parity error", -1, 1 },
459556b2bdd1SGireesh Nagabhushana { F_CREQPERR, "PCI CMD channel request parity error", -1, 1 },
459656b2bdd1SGireesh Nagabhushana { F_CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
459756b2bdd1SGireesh Nagabhushana { F_DCNTPERR, "PCI DMA channel count parity error", -1, 1 },
459856b2bdd1SGireesh Nagabhushana { F_DREQPERR, "PCI DMA channel request parity error", -1, 1 },
459956b2bdd1SGireesh Nagabhushana { F_DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
460056b2bdd1SGireesh Nagabhushana { F_HCNTPERR, "PCI HMA channel count parity error", -1, 1 },
460156b2bdd1SGireesh Nagabhushana { F_HREQPERR, "PCI HMA channel request parity error", -1, 1 },
460256b2bdd1SGireesh Nagabhushana { F_HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
460356b2bdd1SGireesh Nagabhushana { F_CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
460456b2bdd1SGireesh Nagabhushana { F_FIDPERR, "PCI FID parity error", -1, 1 },
460556b2bdd1SGireesh Nagabhushana { F_INTXCLRPERR, "PCI INTx clear parity error", -1, 1 },
460656b2bdd1SGireesh Nagabhushana { F_MATAGPERR, "PCI MA tag parity error", -1, 1 },
460756b2bdd1SGireesh Nagabhushana { F_PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
460856b2bdd1SGireesh Nagabhushana { F_RXCPLPERR, "PCI Rx completion parity error", -1, 1 },
460956b2bdd1SGireesh Nagabhushana { F_RXWRPERR, "PCI Rx write parity error", -1, 1 },
461056b2bdd1SGireesh Nagabhushana { F_RPLPERR, "PCI replay buffer parity error", -1, 1 },
461156b2bdd1SGireesh Nagabhushana { F_PCIESINT, "PCI core secondary fault", -1, 1 },
461256b2bdd1SGireesh Nagabhushana { F_PCIEPINT, "PCI core primary fault", -1, 1 },
461356b2bdd1SGireesh Nagabhushana { F_UNXSPLCPLERR, "PCI unexpected split completion error", -1,
461456b2bdd1SGireesh Nagabhushana 0 },
461556b2bdd1SGireesh Nagabhushana { 0 }
461656b2bdd1SGireesh Nagabhushana };
461756b2bdd1SGireesh Nagabhushana
4618de483253SVishal Kulkarni static struct intr_info t5_pcie_intr_info[] = {
4619de483253SVishal Kulkarni { F_MSTGRPPERR, "Master Response Read Queue parity error",
4620de483253SVishal Kulkarni -1, 1 },
4621de483253SVishal Kulkarni { F_MSTTIMEOUTPERR, "Master Timeout FIFO parity error", -1, 1 },
4622de483253SVishal Kulkarni { F_MSIXSTIPERR, "MSI-X STI SRAM parity error", -1, 1 },
4623de483253SVishal Kulkarni { F_MSIXADDRLPERR, "MSI-X AddrL parity error", -1, 1 },
4624de483253SVishal Kulkarni { F_MSIXADDRHPERR, "MSI-X AddrH parity error", -1, 1 },
4625de483253SVishal Kulkarni { F_MSIXDATAPERR, "MSI-X data parity error", -1, 1 },
4626de483253SVishal Kulkarni { F_MSIXDIPERR, "MSI-X DI parity error", -1, 1 },
4627de483253SVishal Kulkarni { F_PIOCPLGRPPERR, "PCI PIO completion Group FIFO parity error",
4628de483253SVishal Kulkarni -1, 1 },
4629de483253SVishal Kulkarni { F_PIOREQGRPPERR, "PCI PIO request Group FIFO parity error",
4630de483253SVishal Kulkarni -1, 1 },
4631de483253SVishal Kulkarni { F_TARTAGPERR, "PCI PCI target tag FIFO parity error", -1, 1 },
4632de483253SVishal Kulkarni { F_MSTTAGQPERR, "PCI master tag queue parity error", -1, 1 },
4633de483253SVishal Kulkarni { F_CREQPERR, "PCI CMD channel request parity error", -1, 1 },
4634de483253SVishal Kulkarni { F_CRSPPERR, "PCI CMD channel response parity error", -1, 1 },
4635de483253SVishal Kulkarni { F_DREQWRPERR, "PCI DMA channel write request parity error",
4636de483253SVishal Kulkarni -1, 1 },
4637de483253SVishal Kulkarni { F_DREQPERR, "PCI DMA channel request parity error", -1, 1 },
4638de483253SVishal Kulkarni { F_DRSPPERR, "PCI DMA channel response parity error", -1, 1 },
4639de483253SVishal Kulkarni { F_HREQWRPERR, "PCI HMA channel count parity error", -1, 1 },
4640de483253SVishal Kulkarni { F_HREQPERR, "PCI HMA channel request parity error", -1, 1 },
4641de483253SVishal Kulkarni { F_HRSPPERR, "PCI HMA channel response parity error", -1, 1 },
4642de483253SVishal Kulkarni { F_CFGSNPPERR, "PCI config snoop FIFO parity error", -1, 1 },
4643de483253SVishal Kulkarni { F_FIDPERR, "PCI FID parity error", -1, 1 },
4644de483253SVishal Kulkarni { F_VFIDPERR, "PCI INTx clear parity error", -1, 1 },
4645de483253SVishal Kulkarni { F_MAGRPPERR, "PCI MA group FIFO parity error", -1, 1 },
4646de483253SVishal Kulkarni { F_PIOTAGPERR, "PCI PIO tag parity error", -1, 1 },
4647de483253SVishal Kulkarni { F_IPRXHDRGRPPERR, "PCI IP Rx header group parity error",
4648de483253SVishal Kulkarni -1, 1 },
4649de483253SVishal Kulkarni { F_IPRXDATAGRPPERR, "PCI IP Rx data group parity error",
4650de483253SVishal Kulkarni -1, 1 },
4651de483253SVishal Kulkarni { F_RPLPERR, "PCI IP replay buffer parity error", -1, 1 },
4652de483253SVishal Kulkarni { F_IPSOTPERR, "PCI IP SOT buffer parity error", -1, 1 },
4653de483253SVishal Kulkarni { F_TRGT1GRPPERR, "PCI TRGT1 group FIFOs parity error", -1, 1 },
4654de483253SVishal Kulkarni { F_READRSPERR, "Outbound read error", -1,
4655de483253SVishal Kulkarni 0 },
4656de483253SVishal Kulkarni { 0 }
4657de483253SVishal Kulkarni };
4658de483253SVishal Kulkarni
465956b2bdd1SGireesh Nagabhushana int fat;
466056b2bdd1SGireesh Nagabhushana
46613dde7c95SVishal Kulkarni if (is_t4(adapter->params.chip))
466256b2bdd1SGireesh Nagabhushana fat = t4_handle_intr_status(adapter,
46633dde7c95SVishal Kulkarni A_PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
46643dde7c95SVishal Kulkarni sysbus_intr_info) +
466556b2bdd1SGireesh Nagabhushana t4_handle_intr_status(adapter,
46663dde7c95SVishal Kulkarni A_PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
46673dde7c95SVishal Kulkarni pcie_port_intr_info) +
4668de483253SVishal Kulkarni t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
46693dde7c95SVishal Kulkarni pcie_intr_info);
46703dde7c95SVishal Kulkarni else
46713dde7c95SVishal Kulkarni fat = t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
46723dde7c95SVishal Kulkarni t5_pcie_intr_info);
46733dde7c95SVishal Kulkarni if (fat)
467456b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
467556b2bdd1SGireesh Nagabhushana }
467656b2bdd1SGireesh Nagabhushana
467756b2bdd1SGireesh Nagabhushana /*
467856b2bdd1SGireesh Nagabhushana * TP interrupt handler.
467956b2bdd1SGireesh Nagabhushana */
tp_intr_handler(struct adapter * adapter)46803dde7c95SVishal Kulkarni static void tp_intr_handler(struct adapter *adapter)
468156b2bdd1SGireesh Nagabhushana {
46823dde7c95SVishal Kulkarni static const struct intr_info tp_intr_info[] = {
468356b2bdd1SGireesh Nagabhushana { 0x3fffffff, "TP parity error", -1, 1 },
468456b2bdd1SGireesh Nagabhushana { F_FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1 },
468556b2bdd1SGireesh Nagabhushana { 0 }
468656b2bdd1SGireesh Nagabhushana };
468756b2bdd1SGireesh Nagabhushana
46883dde7c95SVishal Kulkarni if (t4_handle_intr_status(adapter, A_TP_INT_CAUSE, tp_intr_info))
468956b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
469056b2bdd1SGireesh Nagabhushana }
469156b2bdd1SGireesh Nagabhushana
469256b2bdd1SGireesh Nagabhushana /*
469356b2bdd1SGireesh Nagabhushana * SGE interrupt handler.
469456b2bdd1SGireesh Nagabhushana */
sge_intr_handler(struct adapter * adapter)46953dde7c95SVishal Kulkarni static void sge_intr_handler(struct adapter *adapter)
469656b2bdd1SGireesh Nagabhushana {
46977e6ad469SVishal Kulkarni u32 v = 0, perr;
469856b2bdd1SGireesh Nagabhushana u32 err;
469956b2bdd1SGireesh Nagabhushana
47003dde7c95SVishal Kulkarni static const struct intr_info sge_intr_info[] = {
470156b2bdd1SGireesh Nagabhushana { F_ERR_CPL_EXCEED_IQE_SIZE,
470256b2bdd1SGireesh Nagabhushana "SGE received CPL exceeding IQE size", -1, 1 },
470356b2bdd1SGireesh Nagabhushana { F_ERR_INVALID_CIDX_INC,
470456b2bdd1SGireesh Nagabhushana "SGE GTS CIDX increment too large", -1, 0 },
470556b2bdd1SGireesh Nagabhushana { F_ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
47063dde7c95SVishal Kulkarni { F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full },
470756b2bdd1SGireesh Nagabhushana { F_ERR_DATA_CPL_ON_HIGH_QID1 | F_ERR_DATA_CPL_ON_HIGH_QID0,
470856b2bdd1SGireesh Nagabhushana "SGE IQID > 1023 received CPL for FL", -1, 0 },
470956b2bdd1SGireesh Nagabhushana { F_ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
471056b2bdd1SGireesh Nagabhushana 0 },
471156b2bdd1SGireesh Nagabhushana { F_ERR_BAD_DB_PIDX2, "SGE DBP 2 pidx increment too large", -1,
471256b2bdd1SGireesh Nagabhushana 0 },
471356b2bdd1SGireesh Nagabhushana { F_ERR_BAD_DB_PIDX1, "SGE DBP 1 pidx increment too large", -1,
471456b2bdd1SGireesh Nagabhushana 0 },
471556b2bdd1SGireesh Nagabhushana { F_ERR_BAD_DB_PIDX0, "SGE DBP 0 pidx increment too large", -1,
471656b2bdd1SGireesh Nagabhushana 0 },
471756b2bdd1SGireesh Nagabhushana { F_ERR_ING_CTXT_PRIO,
471856b2bdd1SGireesh Nagabhushana "SGE too many priority ingress contexts", -1, 0 },
471956b2bdd1SGireesh Nagabhushana { F_INGRESS_SIZE_ERR, "SGE illegal ingress QID", -1, 0 },
472056b2bdd1SGireesh Nagabhushana { F_EGRESS_SIZE_ERR, "SGE illegal egress QID", -1, 0 },
47213dde7c95SVishal Kulkarni { F_ERR_PCIE_ERROR0 | F_ERR_PCIE_ERROR1 |
47223dde7c95SVishal Kulkarni F_ERR_PCIE_ERROR2 | F_ERR_PCIE_ERROR3,
47233dde7c95SVishal Kulkarni "SGE PCIe error for a DBP thread", -1, 0 },
47243dde7c95SVishal Kulkarni { 0 }
47253dde7c95SVishal Kulkarni };
47263dde7c95SVishal Kulkarni
47273dde7c95SVishal Kulkarni static struct intr_info t4t5_sge_intr_info[] = {
47283dde7c95SVishal Kulkarni { F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped },
47293dde7c95SVishal Kulkarni { F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full },
47303dde7c95SVishal Kulkarni { F_ERR_EGR_CTXT_PRIO,
47313dde7c95SVishal Kulkarni "SGE too many priority egress contexts", -1, 0 },
47323dde7c95SVishal Kulkarni { 0 }
47333dde7c95SVishal Kulkarni };
47343dde7c95SVishal Kulkarni
47353dde7c95SVishal Kulkarni /*
47363dde7c95SVishal Kulkarni * For now, treat below interrupts as fatal so that we disable SGE and
47373dde7c95SVishal Kulkarni * get better debug */
47383dde7c95SVishal Kulkarni static struct intr_info t6_sge_intr_info[] = {
47393dde7c95SVishal Kulkarni { F_FATAL_WRE_LEN,
47403dde7c95SVishal Kulkarni "SGE Actual WRE packet is less than advertized length",
47413dde7c95SVishal Kulkarni -1, 1 },
474256b2bdd1SGireesh Nagabhushana { 0 }
474356b2bdd1SGireesh Nagabhushana };
474456b2bdd1SGireesh Nagabhushana
47457e6ad469SVishal Kulkarni perr = t4_read_reg(adapter, A_SGE_INT_CAUSE1);
47467e6ad469SVishal Kulkarni if (perr) {
47477e6ad469SVishal Kulkarni v |= perr;
47487e6ad469SVishal Kulkarni CH_ALERT(adapter, "SGE Cause1 Parity Error %#x\n", perr);
47497e6ad469SVishal Kulkarni }
47507e6ad469SVishal Kulkarni perr = t4_read_reg(adapter, A_SGE_INT_CAUSE2);
47517e6ad469SVishal Kulkarni if (perr) {
47527e6ad469SVishal Kulkarni v |= perr;
47537e6ad469SVishal Kulkarni CH_ALERT(adapter, "SGE Cause2 Parity Error %#x\n", perr);
47547e6ad469SVishal Kulkarni }
47557e6ad469SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adapter->params.chip) >= CHELSIO_T5) {
47567e6ad469SVishal Kulkarni perr = t4_read_reg(adapter, A_SGE_INT_CAUSE5);
47577e6ad469SVishal Kulkarni if (perr) {
47587e6ad469SVishal Kulkarni v |= perr;
47597e6ad469SVishal Kulkarni CH_ALERT(adapter, "SGE Cause5 Parity Error %#x\n", perr);
47607e6ad469SVishal Kulkarni }
476156b2bdd1SGireesh Nagabhushana }
476256b2bdd1SGireesh Nagabhushana
476356b2bdd1SGireesh Nagabhushana v |= t4_handle_intr_status(adapter, A_SGE_INT_CAUSE3, sge_intr_info);
47643dde7c95SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5)
47653dde7c95SVishal Kulkarni v |= t4_handle_intr_status(adapter, A_SGE_INT_CAUSE3,
47663dde7c95SVishal Kulkarni t4t5_sge_intr_info);
47673dde7c95SVishal Kulkarni else
47683dde7c95SVishal Kulkarni v |= t4_handle_intr_status(adapter, A_SGE_INT_CAUSE3,
47693dde7c95SVishal Kulkarni t6_sge_intr_info);
477056b2bdd1SGireesh Nagabhushana
477156b2bdd1SGireesh Nagabhushana err = t4_read_reg(adapter, A_SGE_ERROR_STATS);
477256b2bdd1SGireesh Nagabhushana if (err & F_ERROR_QID_VALID) {
4773de483253SVishal Kulkarni CH_ERR(adapter, "SGE error for queue %u\n", G_ERROR_QID(err));
4774de483253SVishal Kulkarni if (err & F_UNCAPTURED_ERROR)
4775de483253SVishal Kulkarni CH_ERR(adapter, "SGE UNCAPTURED_ERROR set (clearing)\n");
4776de483253SVishal Kulkarni t4_write_reg(adapter, A_SGE_ERROR_STATS, F_ERROR_QID_VALID |
4777de483253SVishal Kulkarni F_UNCAPTURED_ERROR);
477856b2bdd1SGireesh Nagabhushana }
477956b2bdd1SGireesh Nagabhushana
478056b2bdd1SGireesh Nagabhushana if (v != 0)
478156b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
478256b2bdd1SGireesh Nagabhushana }
478356b2bdd1SGireesh Nagabhushana
478456b2bdd1SGireesh Nagabhushana #define CIM_OBQ_INTR (F_OBQULP0PARERR | F_OBQULP1PARERR | F_OBQULP2PARERR |\
478556b2bdd1SGireesh Nagabhushana F_OBQULP3PARERR | F_OBQSGEPARERR | F_OBQNCSIPARERR)
478656b2bdd1SGireesh Nagabhushana #define CIM_IBQ_INTR (F_IBQTP0PARERR | F_IBQTP1PARERR | F_IBQULPPARERR |\
478756b2bdd1SGireesh Nagabhushana F_IBQSGEHIPARERR | F_IBQSGELOPARERR | F_IBQNCSIPARERR)
478856b2bdd1SGireesh Nagabhushana
478956b2bdd1SGireesh Nagabhushana /*
479056b2bdd1SGireesh Nagabhushana * CIM interrupt handler.
479156b2bdd1SGireesh Nagabhushana */
cim_intr_handler(struct adapter * adapter)47923dde7c95SVishal Kulkarni static void cim_intr_handler(struct adapter *adapter)
479356b2bdd1SGireesh Nagabhushana {
47943dde7c95SVishal Kulkarni static const struct intr_info cim_intr_info[] = {
479556b2bdd1SGireesh Nagabhushana { F_PREFDROPINT, "CIM control register prefetch drop", -1, 1 },
479656b2bdd1SGireesh Nagabhushana { CIM_OBQ_INTR, "CIM OBQ parity error", -1, 1 },
479756b2bdd1SGireesh Nagabhushana { CIM_IBQ_INTR, "CIM IBQ parity error", -1, 1 },
479856b2bdd1SGireesh Nagabhushana { F_MBUPPARERR, "CIM mailbox uP parity error", -1, 1 },
479956b2bdd1SGireesh Nagabhushana { F_MBHOSTPARERR, "CIM mailbox host parity error", -1, 1 },
480056b2bdd1SGireesh Nagabhushana { F_TIEQINPARERRINT, "CIM TIEQ outgoing parity error", -1, 1 },
480156b2bdd1SGireesh Nagabhushana { F_TIEQOUTPARERRINT, "CIM TIEQ incoming parity error", -1, 1 },
48027e6ad469SVishal Kulkarni { F_TIMER0INT, "CIM TIMER0 interrupt", -1, 1 },
480356b2bdd1SGireesh Nagabhushana { 0 }
480456b2bdd1SGireesh Nagabhushana };
48053dde7c95SVishal Kulkarni static const struct intr_info cim_upintr_info[] = {
480656b2bdd1SGireesh Nagabhushana { F_RSVDSPACEINT, "CIM reserved space access", -1, 1 },
480756b2bdd1SGireesh Nagabhushana { F_ILLTRANSINT, "CIM illegal transaction", -1, 1 },
480856b2bdd1SGireesh Nagabhushana { F_ILLWRINT, "CIM illegal write", -1, 1 },
480956b2bdd1SGireesh Nagabhushana { F_ILLRDINT, "CIM illegal read", -1, 1 },
481056b2bdd1SGireesh Nagabhushana { F_ILLRDBEINT, "CIM illegal read BE", -1, 1 },
481156b2bdd1SGireesh Nagabhushana { F_ILLWRBEINT, "CIM illegal write BE", -1, 1 },
481256b2bdd1SGireesh Nagabhushana { F_SGLRDBOOTINT, "CIM single read from boot space", -1, 1 },
481356b2bdd1SGireesh Nagabhushana { F_SGLWRBOOTINT, "CIM single write to boot space", -1, 1 },
481456b2bdd1SGireesh Nagabhushana { F_BLKWRBOOTINT, "CIM block write to boot space", -1, 1 },
481556b2bdd1SGireesh Nagabhushana { F_SGLRDFLASHINT, "CIM single read from flash space", -1, 1 },
481656b2bdd1SGireesh Nagabhushana { F_SGLWRFLASHINT, "CIM single write to flash space", -1, 1 },
481756b2bdd1SGireesh Nagabhushana { F_BLKWRFLASHINT, "CIM block write to flash space", -1, 1 },
481856b2bdd1SGireesh Nagabhushana { F_SGLRDEEPROMINT, "CIM single EEPROM read", -1, 1 },
481956b2bdd1SGireesh Nagabhushana { F_SGLWREEPROMINT, "CIM single EEPROM write", -1, 1 },
482056b2bdd1SGireesh Nagabhushana { F_BLKRDEEPROMINT, "CIM block EEPROM read", -1, 1 },
482156b2bdd1SGireesh Nagabhushana { F_BLKWREEPROMINT, "CIM block EEPROM write", -1, 1 },
482256b2bdd1SGireesh Nagabhushana { F_SGLRDCTLINT , "CIM single read from CTL space", -1, 1 },
482356b2bdd1SGireesh Nagabhushana { F_SGLWRCTLINT , "CIM single write to CTL space", -1, 1 },
482456b2bdd1SGireesh Nagabhushana { F_BLKRDCTLINT , "CIM block read from CTL space", -1, 1 },
482556b2bdd1SGireesh Nagabhushana { F_BLKWRCTLINT , "CIM block write to CTL space", -1, 1 },
482656b2bdd1SGireesh Nagabhushana { F_SGLRDPLINT , "CIM single read from PL space", -1, 1 },
482756b2bdd1SGireesh Nagabhushana { F_SGLWRPLINT , "CIM single write to PL space", -1, 1 },
482856b2bdd1SGireesh Nagabhushana { F_BLKRDPLINT , "CIM block read from PL space", -1, 1 },
482956b2bdd1SGireesh Nagabhushana { F_BLKWRPLINT , "CIM block write to PL space", -1, 1 },
483056b2bdd1SGireesh Nagabhushana { F_REQOVRLOOKUPINT , "CIM request FIFO overwrite", -1, 1 },
483156b2bdd1SGireesh Nagabhushana { F_RSPOVRLOOKUPINT , "CIM response FIFO overwrite", -1, 1 },
483256b2bdd1SGireesh Nagabhushana { F_TIMEOUTINT , "CIM PIF timeout", -1, 1 },
483356b2bdd1SGireesh Nagabhushana { F_TIMEOUTMAINT , "CIM PIF MA timeout", -1, 1 },
483456b2bdd1SGireesh Nagabhushana { 0 }
483556b2bdd1SGireesh Nagabhushana };
48367e6ad469SVishal Kulkarni u32 val, fw_err;
483756b2bdd1SGireesh Nagabhushana int fat;
483856b2bdd1SGireesh Nagabhushana
48397e6ad469SVishal Kulkarni fw_err = t4_read_reg(adapter, A_PCIE_FW);
48407e6ad469SVishal Kulkarni if (fw_err & F_PCIE_FW_ERR)
4841de483253SVishal Kulkarni t4_report_fw_error(adapter);
4842de483253SVishal Kulkarni
48437e6ad469SVishal Kulkarni /* When the Firmware detects an internal error which normally wouldn't
48447e6ad469SVishal Kulkarni * raise a Host Interrupt, it forces a CIM Timer0 interrupt in order
48457e6ad469SVishal Kulkarni * to make sure the Host sees the Firmware Crash. So if we have a
48467e6ad469SVishal Kulkarni * Timer0 interrupt and don't see a Firmware Crash, ignore the Timer0
48477e6ad469SVishal Kulkarni * interrupt.
48487e6ad469SVishal Kulkarni */
48497e6ad469SVishal Kulkarni val = t4_read_reg(adapter, A_CIM_HOST_INT_CAUSE);
48507e6ad469SVishal Kulkarni if (val & F_TIMER0INT)
48517e6ad469SVishal Kulkarni if (!(fw_err & F_PCIE_FW_ERR) ||
48527e6ad469SVishal Kulkarni (G_PCIE_FW_EVAL(fw_err) != PCIE_FW_EVAL_CRASH))
48537e6ad469SVishal Kulkarni t4_write_reg(adapter, A_CIM_HOST_INT_CAUSE,
48547e6ad469SVishal Kulkarni F_TIMER0INT);
48557e6ad469SVishal Kulkarni
485656b2bdd1SGireesh Nagabhushana fat = t4_handle_intr_status(adapter, A_CIM_HOST_INT_CAUSE,
485756b2bdd1SGireesh Nagabhushana cim_intr_info) +
485856b2bdd1SGireesh Nagabhushana t4_handle_intr_status(adapter, A_CIM_HOST_UPACC_INT_CAUSE,
485956b2bdd1SGireesh Nagabhushana cim_upintr_info);
48603dde7c95SVishal Kulkarni if (fat)
486156b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
486256b2bdd1SGireesh Nagabhushana }
486356b2bdd1SGireesh Nagabhushana
486456b2bdd1SGireesh Nagabhushana /*
486556b2bdd1SGireesh Nagabhushana * ULP RX interrupt handler.
486656b2bdd1SGireesh Nagabhushana */
ulprx_intr_handler(struct adapter * adapter)48673dde7c95SVishal Kulkarni static void ulprx_intr_handler(struct adapter *adapter)
486856b2bdd1SGireesh Nagabhushana {
48693dde7c95SVishal Kulkarni static const struct intr_info ulprx_intr_info[] = {
487056b2bdd1SGireesh Nagabhushana { F_CAUSE_CTX_1, "ULPRX channel 1 context error", -1, 1 },
487156b2bdd1SGireesh Nagabhushana { F_CAUSE_CTX_0, "ULPRX channel 0 context error", -1, 1 },
487256b2bdd1SGireesh Nagabhushana { 0x7fffff, "ULPRX parity error", -1, 1 },
487356b2bdd1SGireesh Nagabhushana { 0 }
487456b2bdd1SGireesh Nagabhushana };
487556b2bdd1SGireesh Nagabhushana
48763dde7c95SVishal Kulkarni if (t4_handle_intr_status(adapter, A_ULP_RX_INT_CAUSE, ulprx_intr_info))
487756b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
487856b2bdd1SGireesh Nagabhushana }
487956b2bdd1SGireesh Nagabhushana
488056b2bdd1SGireesh Nagabhushana /*
488156b2bdd1SGireesh Nagabhushana * ULP TX interrupt handler.
488256b2bdd1SGireesh Nagabhushana */
ulptx_intr_handler(struct adapter * adapter)48833dde7c95SVishal Kulkarni static void ulptx_intr_handler(struct adapter *adapter)
488456b2bdd1SGireesh Nagabhushana {
48853dde7c95SVishal Kulkarni static const struct intr_info ulptx_intr_info[] = {
488656b2bdd1SGireesh Nagabhushana { F_PBL_BOUND_ERR_CH3, "ULPTX channel 3 PBL out of bounds", -1,
488756b2bdd1SGireesh Nagabhushana 0 },
488856b2bdd1SGireesh Nagabhushana { F_PBL_BOUND_ERR_CH2, "ULPTX channel 2 PBL out of bounds", -1,
488956b2bdd1SGireesh Nagabhushana 0 },
489056b2bdd1SGireesh Nagabhushana { F_PBL_BOUND_ERR_CH1, "ULPTX channel 1 PBL out of bounds", -1,
489156b2bdd1SGireesh Nagabhushana 0 },
489256b2bdd1SGireesh Nagabhushana { F_PBL_BOUND_ERR_CH0, "ULPTX channel 0 PBL out of bounds", -1,
489356b2bdd1SGireesh Nagabhushana 0 },
489456b2bdd1SGireesh Nagabhushana { 0xfffffff, "ULPTX parity error", -1, 1 },
489556b2bdd1SGireesh Nagabhushana { 0 }
489656b2bdd1SGireesh Nagabhushana };
489756b2bdd1SGireesh Nagabhushana
48983dde7c95SVishal Kulkarni if (t4_handle_intr_status(adapter, A_ULP_TX_INT_CAUSE, ulptx_intr_info))
489956b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
490056b2bdd1SGireesh Nagabhushana }
490156b2bdd1SGireesh Nagabhushana
490256b2bdd1SGireesh Nagabhushana /*
490356b2bdd1SGireesh Nagabhushana * PM TX interrupt handler.
490456b2bdd1SGireesh Nagabhushana */
pmtx_intr_handler(struct adapter * adapter)49053dde7c95SVishal Kulkarni static void pmtx_intr_handler(struct adapter *adapter)
490656b2bdd1SGireesh Nagabhushana {
49073dde7c95SVishal Kulkarni static const struct intr_info pmtx_intr_info[] = {
490856b2bdd1SGireesh Nagabhushana { F_PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large", -1, 1 },
490956b2bdd1SGireesh Nagabhushana { F_PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large", -1, 1 },
491056b2bdd1SGireesh Nagabhushana { F_PCMD_LEN_OVFL2, "PMTX channel 2 pcmd too large", -1, 1 },
491156b2bdd1SGireesh Nagabhushana { F_ZERO_C_CMD_ERROR, "PMTX 0-length pcmd", -1, 1 },
491256b2bdd1SGireesh Nagabhushana { 0xffffff0, "PMTX framing error", -1, 1 },
491356b2bdd1SGireesh Nagabhushana { F_OESPI_PAR_ERROR, "PMTX oespi parity error", -1, 1 },
491456b2bdd1SGireesh Nagabhushana { F_DB_OPTIONS_PAR_ERROR, "PMTX db_options parity error", -1,
491556b2bdd1SGireesh Nagabhushana 1 },
491656b2bdd1SGireesh Nagabhushana { F_ICSPI_PAR_ERROR, "PMTX icspi parity error", -1, 1 },
491756b2bdd1SGireesh Nagabhushana { F_C_PCMD_PAR_ERROR, "PMTX c_pcmd parity error", -1, 1},
491856b2bdd1SGireesh Nagabhushana { 0 }
491956b2bdd1SGireesh Nagabhushana };
492056b2bdd1SGireesh Nagabhushana
492156b2bdd1SGireesh Nagabhushana if (t4_handle_intr_status(adapter, A_PM_TX_INT_CAUSE, pmtx_intr_info))
492256b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
492356b2bdd1SGireesh Nagabhushana }
492456b2bdd1SGireesh Nagabhushana
492556b2bdd1SGireesh Nagabhushana /*
492656b2bdd1SGireesh Nagabhushana * PM RX interrupt handler.
492756b2bdd1SGireesh Nagabhushana */
pmrx_intr_handler(struct adapter * adapter)49283dde7c95SVishal Kulkarni static void pmrx_intr_handler(struct adapter *adapter)
492956b2bdd1SGireesh Nagabhushana {
49303dde7c95SVishal Kulkarni static const struct intr_info pmrx_intr_info[] = {
493156b2bdd1SGireesh Nagabhushana { F_ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1 },
493256b2bdd1SGireesh Nagabhushana { 0x3ffff0, "PMRX framing error", -1, 1 },
493356b2bdd1SGireesh Nagabhushana { F_OCSPI_PAR_ERROR, "PMRX ocspi parity error", -1, 1 },
493456b2bdd1SGireesh Nagabhushana { F_DB_OPTIONS_PAR_ERROR, "PMRX db_options parity error", -1,
493556b2bdd1SGireesh Nagabhushana 1 },
493656b2bdd1SGireesh Nagabhushana { F_IESPI_PAR_ERROR, "PMRX iespi parity error", -1, 1 },
493756b2bdd1SGireesh Nagabhushana { F_E_PCMD_PAR_ERROR, "PMRX e_pcmd parity error", -1, 1},
493856b2bdd1SGireesh Nagabhushana { 0 }
493956b2bdd1SGireesh Nagabhushana };
494056b2bdd1SGireesh Nagabhushana
494156b2bdd1SGireesh Nagabhushana if (t4_handle_intr_status(adapter, A_PM_RX_INT_CAUSE, pmrx_intr_info))
494256b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
494356b2bdd1SGireesh Nagabhushana }
494456b2bdd1SGireesh Nagabhushana
494556b2bdd1SGireesh Nagabhushana /*
494656b2bdd1SGireesh Nagabhushana * CPL switch interrupt handler.
494756b2bdd1SGireesh Nagabhushana */
cplsw_intr_handler(struct adapter * adapter)49483dde7c95SVishal Kulkarni static void cplsw_intr_handler(struct adapter *adapter)
494956b2bdd1SGireesh Nagabhushana {
49503dde7c95SVishal Kulkarni static const struct intr_info cplsw_intr_info[] = {
495156b2bdd1SGireesh Nagabhushana { F_CIM_OP_MAP_PERR, "CPLSW CIM op_map parity error", -1, 1 },
495256b2bdd1SGireesh Nagabhushana { F_CIM_OVFL_ERROR, "CPLSW CIM overflow", -1, 1 },
495356b2bdd1SGireesh Nagabhushana { F_TP_FRAMING_ERROR, "CPLSW TP framing error", -1, 1 },
495456b2bdd1SGireesh Nagabhushana { F_SGE_FRAMING_ERROR, "CPLSW SGE framing error", -1, 1 },
495556b2bdd1SGireesh Nagabhushana { F_CIM_FRAMING_ERROR, "CPLSW CIM framing error", -1, 1 },
495656b2bdd1SGireesh Nagabhushana { F_ZERO_SWITCH_ERROR, "CPLSW no-switch error", -1, 1 },
495756b2bdd1SGireesh Nagabhushana { 0 }
495856b2bdd1SGireesh Nagabhushana };
495956b2bdd1SGireesh Nagabhushana
496056b2bdd1SGireesh Nagabhushana if (t4_handle_intr_status(adapter, A_CPL_INTR_CAUSE, cplsw_intr_info))
496156b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
496256b2bdd1SGireesh Nagabhushana }
496356b2bdd1SGireesh Nagabhushana
496456b2bdd1SGireesh Nagabhushana /*
496556b2bdd1SGireesh Nagabhushana * LE interrupt handler.
496656b2bdd1SGireesh Nagabhushana */
le_intr_handler(struct adapter * adap)49673dde7c95SVishal Kulkarni static void le_intr_handler(struct adapter *adap)
496856b2bdd1SGireesh Nagabhushana {
49693dde7c95SVishal Kulkarni unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
49703dde7c95SVishal Kulkarni static const struct intr_info le_intr_info[] = {
497156b2bdd1SGireesh Nagabhushana { F_LIPMISS, "LE LIP miss", -1, 0 },
497256b2bdd1SGireesh Nagabhushana { F_LIP0, "LE 0 LIP error", -1, 0 },
497356b2bdd1SGireesh Nagabhushana { F_PARITYERR, "LE parity error", -1, 1 },
497456b2bdd1SGireesh Nagabhushana { F_UNKNOWNCMD, "LE unknown command", -1, 1 },
497556b2bdd1SGireesh Nagabhushana { F_REQQPARERR, "LE request queue parity error", -1, 1 },
497656b2bdd1SGireesh Nagabhushana { 0 }
497756b2bdd1SGireesh Nagabhushana };
497856b2bdd1SGireesh Nagabhushana
49793dde7c95SVishal Kulkarni static struct intr_info t6_le_intr_info[] = {
49807e6ad469SVishal Kulkarni /* log an error for HASHTBLMEMCRCERR and clear the bit */
49817e6ad469SVishal Kulkarni { F_T6_HASHTBLMEMCRCERR, "LE hash table mem crc error", -1, 0 },
49823dde7c95SVishal Kulkarni { F_T6_LIPMISS, "LE LIP miss", -1, 0 },
49833dde7c95SVishal Kulkarni { F_T6_LIP0, "LE 0 LIP error", -1, 0 },
49843dde7c95SVishal Kulkarni { F_TCAMINTPERR, "LE parity error", -1, 1 },
49853dde7c95SVishal Kulkarni { F_T6_UNKNOWNCMD, "LE unknown command", -1, 1 },
49863dde7c95SVishal Kulkarni { F_SSRAMINTPERR, "LE request queue parity error", -1, 1 },
49873dde7c95SVishal Kulkarni { 0 }
49883dde7c95SVishal Kulkarni };
49893dde7c95SVishal Kulkarni
49903dde7c95SVishal Kulkarni if (t4_handle_intr_status(adap, A_LE_DB_INT_CAUSE,
49913dde7c95SVishal Kulkarni (chip_ver <= CHELSIO_T5) ?
49923dde7c95SVishal Kulkarni le_intr_info : t6_le_intr_info))
499356b2bdd1SGireesh Nagabhushana t4_fatal_err(adap);
499456b2bdd1SGireesh Nagabhushana }
499556b2bdd1SGireesh Nagabhushana
499656b2bdd1SGireesh Nagabhushana /*
499756b2bdd1SGireesh Nagabhushana * MPS interrupt handler.
499856b2bdd1SGireesh Nagabhushana */
mps_intr_handler(struct adapter * adapter)49993dde7c95SVishal Kulkarni static void mps_intr_handler(struct adapter *adapter)
500056b2bdd1SGireesh Nagabhushana {
50013dde7c95SVishal Kulkarni static const struct intr_info mps_rx_intr_info[] = {
500256b2bdd1SGireesh Nagabhushana { 0xffffff, "MPS Rx parity error", -1, 1 },
500356b2bdd1SGireesh Nagabhushana { 0 }
500456b2bdd1SGireesh Nagabhushana };
50053dde7c95SVishal Kulkarni static const struct intr_info mps_tx_intr_info[] = {
500656b2bdd1SGireesh Nagabhushana { V_TPFIFO(M_TPFIFO), "MPS Tx TP FIFO parity error", -1, 1 },
500756b2bdd1SGireesh Nagabhushana { F_NCSIFIFO, "MPS Tx NC-SI FIFO parity error", -1, 1 },
500856b2bdd1SGireesh Nagabhushana { V_TXDATAFIFO(M_TXDATAFIFO), "MPS Tx data FIFO parity error",
500956b2bdd1SGireesh Nagabhushana -1, 1 },
501056b2bdd1SGireesh Nagabhushana { V_TXDESCFIFO(M_TXDESCFIFO), "MPS Tx desc FIFO parity error",
501156b2bdd1SGireesh Nagabhushana -1, 1 },
501256b2bdd1SGireesh Nagabhushana { F_BUBBLE, "MPS Tx underflow", -1, 1 },
501356b2bdd1SGireesh Nagabhushana { F_SECNTERR, "MPS Tx SOP/EOP error", -1, 1 },
501456b2bdd1SGireesh Nagabhushana { F_FRMERR, "MPS Tx framing error", -1, 1 },
501556b2bdd1SGireesh Nagabhushana { 0 }
501656b2bdd1SGireesh Nagabhushana };
50177e6ad469SVishal Kulkarni static const struct intr_info t6_mps_tx_intr_info[] = {
50187e6ad469SVishal Kulkarni { V_TPFIFO(M_TPFIFO), "MPS Tx TP FIFO parity error", -1, 1 },
50197e6ad469SVishal Kulkarni { F_NCSIFIFO, "MPS Tx NC-SI FIFO parity error", -1, 1 },
50207e6ad469SVishal Kulkarni { V_TXDATAFIFO(M_TXDATAFIFO), "MPS Tx data FIFO parity error",
50217e6ad469SVishal Kulkarni -1, 1 },
50227e6ad469SVishal Kulkarni { V_TXDESCFIFO(M_TXDESCFIFO), "MPS Tx desc FIFO parity error",
50237e6ad469SVishal Kulkarni -1, 1 },
50247e6ad469SVishal Kulkarni /* MPS Tx Bubble is normal for T6 */
50257e6ad469SVishal Kulkarni { F_SECNTERR, "MPS Tx SOP/EOP error", -1, 1 },
50267e6ad469SVishal Kulkarni { F_FRMERR, "MPS Tx framing error", -1, 1 },
50277e6ad469SVishal Kulkarni { 0 }
50287e6ad469SVishal Kulkarni };
50293dde7c95SVishal Kulkarni static const struct intr_info mps_trc_intr_info[] = {
503056b2bdd1SGireesh Nagabhushana { V_FILTMEM(M_FILTMEM), "MPS TRC filter parity error", -1, 1 },
503156b2bdd1SGireesh Nagabhushana { V_PKTFIFO(M_PKTFIFO), "MPS TRC packet FIFO parity error", -1,
503256b2bdd1SGireesh Nagabhushana 1 },
503356b2bdd1SGireesh Nagabhushana { F_MISCPERR, "MPS TRC misc parity error", -1, 1 },
503456b2bdd1SGireesh Nagabhushana { 0 }
503556b2bdd1SGireesh Nagabhushana };
50363dde7c95SVishal Kulkarni static const struct intr_info mps_stat_sram_intr_info[] = {
503756b2bdd1SGireesh Nagabhushana { 0x1fffff, "MPS statistics SRAM parity error", -1, 1 },
503856b2bdd1SGireesh Nagabhushana { 0 }
503956b2bdd1SGireesh Nagabhushana };
50403dde7c95SVishal Kulkarni static const struct intr_info mps_stat_tx_intr_info[] = {
504156b2bdd1SGireesh Nagabhushana { 0xfffff, "MPS statistics Tx FIFO parity error", -1, 1 },
504256b2bdd1SGireesh Nagabhushana { 0 }
504356b2bdd1SGireesh Nagabhushana };
50443dde7c95SVishal Kulkarni static const struct intr_info mps_stat_rx_intr_info[] = {
504556b2bdd1SGireesh Nagabhushana { 0xffffff, "MPS statistics Rx FIFO parity error", -1, 1 },
504656b2bdd1SGireesh Nagabhushana { 0 }
504756b2bdd1SGireesh Nagabhushana };
50483dde7c95SVishal Kulkarni static const struct intr_info mps_cls_intr_info[] = {
504956b2bdd1SGireesh Nagabhushana { F_MATCHSRAM, "MPS match SRAM parity error", -1, 1 },
505056b2bdd1SGireesh Nagabhushana { F_MATCHTCAM, "MPS match TCAM parity error", -1, 1 },
505156b2bdd1SGireesh Nagabhushana { F_HASHSRAM, "MPS hash SRAM parity error", -1, 1 },
505256b2bdd1SGireesh Nagabhushana { 0 }
505356b2bdd1SGireesh Nagabhushana };
505456b2bdd1SGireesh Nagabhushana
505556b2bdd1SGireesh Nagabhushana int fat;
505656b2bdd1SGireesh Nagabhushana
505756b2bdd1SGireesh Nagabhushana fat = t4_handle_intr_status(adapter, A_MPS_RX_PERR_INT_CAUSE,
505856b2bdd1SGireesh Nagabhushana mps_rx_intr_info) +
505956b2bdd1SGireesh Nagabhushana t4_handle_intr_status(adapter, A_MPS_TX_INT_CAUSE,
50607e6ad469SVishal Kulkarni is_t6(adapter->params.chip)
50617e6ad469SVishal Kulkarni ? t6_mps_tx_intr_info
50627e6ad469SVishal Kulkarni : mps_tx_intr_info) +
506356b2bdd1SGireesh Nagabhushana t4_handle_intr_status(adapter, A_MPS_TRC_INT_CAUSE,
506456b2bdd1SGireesh Nagabhushana mps_trc_intr_info) +
506556b2bdd1SGireesh Nagabhushana t4_handle_intr_status(adapter, A_MPS_STAT_PERR_INT_CAUSE_SRAM,
506656b2bdd1SGireesh Nagabhushana mps_stat_sram_intr_info) +
50673dde7c95SVishal Kulkarni t4_handle_intr_status(adapter, A_MPS_STAT_PERR_INT_CAUSE_TX_FIFO,
506856b2bdd1SGireesh Nagabhushana mps_stat_tx_intr_info) +
50693dde7c95SVishal Kulkarni t4_handle_intr_status(adapter, A_MPS_STAT_PERR_INT_CAUSE_RX_FIFO,
507056b2bdd1SGireesh Nagabhushana mps_stat_rx_intr_info) +
507156b2bdd1SGireesh Nagabhushana t4_handle_intr_status(adapter, A_MPS_CLS_INT_CAUSE,
507256b2bdd1SGireesh Nagabhushana mps_cls_intr_info);
507356b2bdd1SGireesh Nagabhushana
507456b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_MPS_INT_CAUSE, 0);
50753dde7c95SVishal Kulkarni t4_read_reg(adapter, A_MPS_INT_CAUSE); /* flush */
50763dde7c95SVishal Kulkarni if (fat)
507756b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
507856b2bdd1SGireesh Nagabhushana }
507956b2bdd1SGireesh Nagabhushana
50803dde7c95SVishal Kulkarni #define MEM_INT_MASK (F_PERR_INT_CAUSE | F_ECC_CE_INT_CAUSE | \
50813dde7c95SVishal Kulkarni F_ECC_UE_INT_CAUSE)
508256b2bdd1SGireesh Nagabhushana
508356b2bdd1SGireesh Nagabhushana /*
508456b2bdd1SGireesh Nagabhushana * EDC/MC interrupt handler.
508556b2bdd1SGireesh Nagabhushana */
mem_intr_handler(struct adapter * adapter,int idx)50863dde7c95SVishal Kulkarni static void mem_intr_handler(struct adapter *adapter, int idx)
508756b2bdd1SGireesh Nagabhushana {
50883dde7c95SVishal Kulkarni static const char name[4][7] = { "EDC0", "EDC1", "MC/MC0", "MC1" };
508956b2bdd1SGireesh Nagabhushana
509056b2bdd1SGireesh Nagabhushana unsigned int addr, cnt_addr, v;
509156b2bdd1SGireesh Nagabhushana
509256b2bdd1SGireesh Nagabhushana if (idx <= MEM_EDC1) {
509356b2bdd1SGireesh Nagabhushana addr = EDC_REG(A_EDC_INT_CAUSE, idx);
509456b2bdd1SGireesh Nagabhushana cnt_addr = EDC_REG(A_EDC_ECC_STATUS, idx);
50953dde7c95SVishal Kulkarni } else if (idx == MEM_MC) {
5096de483253SVishal Kulkarni if (is_t4(adapter->params.chip)) {
509756b2bdd1SGireesh Nagabhushana addr = A_MC_INT_CAUSE;
509856b2bdd1SGireesh Nagabhushana cnt_addr = A_MC_ECC_STATUS;
5099de483253SVishal Kulkarni } else {
5100de483253SVishal Kulkarni addr = A_MC_P_INT_CAUSE;
5101de483253SVishal Kulkarni cnt_addr = A_MC_P_ECC_STATUS;
5102de483253SVishal Kulkarni }
51033dde7c95SVishal Kulkarni } else {
51043dde7c95SVishal Kulkarni addr = MC_REG(A_MC_P_INT_CAUSE, 1);
51053dde7c95SVishal Kulkarni cnt_addr = MC_REG(A_MC_P_ECC_STATUS, 1);
510656b2bdd1SGireesh Nagabhushana }
510756b2bdd1SGireesh Nagabhushana
510856b2bdd1SGireesh Nagabhushana v = t4_read_reg(adapter, addr) & MEM_INT_MASK;
510956b2bdd1SGireesh Nagabhushana if (v & F_PERR_INT_CAUSE)
51103dde7c95SVishal Kulkarni CH_ALERT(adapter, "%s FIFO parity error\n",
51113dde7c95SVishal Kulkarni name[idx]);
511256b2bdd1SGireesh Nagabhushana if (v & F_ECC_CE_INT_CAUSE) {
511356b2bdd1SGireesh Nagabhushana u32 cnt = G_ECC_CECNT(t4_read_reg(adapter, cnt_addr));
511456b2bdd1SGireesh Nagabhushana
51153dde7c95SVishal Kulkarni if (idx <= MEM_EDC1)
51163dde7c95SVishal Kulkarni t4_edc_err_read(adapter, idx);
51173dde7c95SVishal Kulkarni
511856b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, cnt_addr, V_ECC_CECNT(M_ECC_CECNT));
511956b2bdd1SGireesh Nagabhushana CH_WARN_RATELIMIT(adapter,
51203dde7c95SVishal Kulkarni "%u %s correctable ECC data error%s\n",
51213dde7c95SVishal Kulkarni cnt, name[idx], cnt > 1 ? "s" : "");
512256b2bdd1SGireesh Nagabhushana }
512356b2bdd1SGireesh Nagabhushana if (v & F_ECC_UE_INT_CAUSE)
51243dde7c95SVishal Kulkarni CH_ALERT(adapter,
51253dde7c95SVishal Kulkarni "%s uncorrectable ECC data error\n", name[idx]);
512656b2bdd1SGireesh Nagabhushana
512756b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, addr, v);
512856b2bdd1SGireesh Nagabhushana if (v & (F_PERR_INT_CAUSE | F_ECC_UE_INT_CAUSE))
512956b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
513056b2bdd1SGireesh Nagabhushana }
513156b2bdd1SGireesh Nagabhushana
513256b2bdd1SGireesh Nagabhushana /*
513356b2bdd1SGireesh Nagabhushana * MA interrupt handler.
513456b2bdd1SGireesh Nagabhushana */
ma_intr_handler(struct adapter * adapter)51353dde7c95SVishal Kulkarni static void ma_intr_handler(struct adapter *adapter)
513656b2bdd1SGireesh Nagabhushana {
513756b2bdd1SGireesh Nagabhushana u32 v, status = t4_read_reg(adapter, A_MA_INT_CAUSE);
513856b2bdd1SGireesh Nagabhushana
51393dde7c95SVishal Kulkarni if (status & F_MEM_PERR_INT_CAUSE) {
51403dde7c95SVishal Kulkarni CH_ALERT(adapter,
51413dde7c95SVishal Kulkarni "MA parity error, parity status %#x\n",
51423dde7c95SVishal Kulkarni t4_read_reg(adapter, A_MA_PARITY_ERROR_STATUS1));
51433dde7c95SVishal Kulkarni if (is_t5(adapter->params.chip))
51443dde7c95SVishal Kulkarni CH_ALERT(adapter,
51453dde7c95SVishal Kulkarni "MA parity error, parity status %#x\n",
51463dde7c95SVishal Kulkarni t4_read_reg(adapter,
51473dde7c95SVishal Kulkarni A_MA_PARITY_ERROR_STATUS2));
51483dde7c95SVishal Kulkarni }
514956b2bdd1SGireesh Nagabhushana if (status & F_MEM_WRAP_INT_CAUSE) {
515056b2bdd1SGireesh Nagabhushana v = t4_read_reg(adapter, A_MA_INT_WRAP_STATUS);
51513dde7c95SVishal Kulkarni CH_ALERT(adapter, "MA address wrap-around error by "
51523dde7c95SVishal Kulkarni "client %u to address %#x\n",
51533dde7c95SVishal Kulkarni G_MEM_WRAP_CLIENT_NUM(v),
515456b2bdd1SGireesh Nagabhushana G_MEM_WRAP_ADDRESS(v) << 4);
515556b2bdd1SGireesh Nagabhushana }
515656b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_MA_INT_CAUSE, status);
515756b2bdd1SGireesh Nagabhushana t4_fatal_err(adapter);
515856b2bdd1SGireesh Nagabhushana }
515956b2bdd1SGireesh Nagabhushana
516056b2bdd1SGireesh Nagabhushana /*
516156b2bdd1SGireesh Nagabhushana * SMB interrupt handler.
516256b2bdd1SGireesh Nagabhushana */
smb_intr_handler(struct adapter * adap)51633dde7c95SVishal Kulkarni static void smb_intr_handler(struct adapter *adap)
516456b2bdd1SGireesh Nagabhushana {
51653dde7c95SVishal Kulkarni static const struct intr_info smb_intr_info[] = {
516656b2bdd1SGireesh Nagabhushana { F_MSTTXFIFOPARINT, "SMB master Tx FIFO parity error", -1, 1 },
516756b2bdd1SGireesh Nagabhushana { F_MSTRXFIFOPARINT, "SMB master Rx FIFO parity error", -1, 1 },
516856b2bdd1SGireesh Nagabhushana { F_SLVFIFOPARINT, "SMB slave FIFO parity error", -1, 1 },
516956b2bdd1SGireesh Nagabhushana { 0 }
517056b2bdd1SGireesh Nagabhushana };
517156b2bdd1SGireesh Nagabhushana
51723dde7c95SVishal Kulkarni if (t4_handle_intr_status(adap, A_SMB_INT_CAUSE, smb_intr_info))
517356b2bdd1SGireesh Nagabhushana t4_fatal_err(adap);
517456b2bdd1SGireesh Nagabhushana }
517556b2bdd1SGireesh Nagabhushana
517656b2bdd1SGireesh Nagabhushana /*
517756b2bdd1SGireesh Nagabhushana * NC-SI interrupt handler.
517856b2bdd1SGireesh Nagabhushana */
ncsi_intr_handler(struct adapter * adap)51793dde7c95SVishal Kulkarni static void ncsi_intr_handler(struct adapter *adap)
518056b2bdd1SGireesh Nagabhushana {
51813dde7c95SVishal Kulkarni static const struct intr_info ncsi_intr_info[] = {
518256b2bdd1SGireesh Nagabhushana { F_CIM_DM_PRTY_ERR, "NC-SI CIM parity error", -1, 1 },
518356b2bdd1SGireesh Nagabhushana { F_MPS_DM_PRTY_ERR, "NC-SI MPS parity error", -1, 1 },
518456b2bdd1SGireesh Nagabhushana { F_TXFIFO_PRTY_ERR, "NC-SI Tx FIFO parity error", -1, 1 },
518556b2bdd1SGireesh Nagabhushana { F_RXFIFO_PRTY_ERR, "NC-SI Rx FIFO parity error", -1, 1 },
518656b2bdd1SGireesh Nagabhushana { 0 }
518756b2bdd1SGireesh Nagabhushana };
518856b2bdd1SGireesh Nagabhushana
51893dde7c95SVishal Kulkarni if (t4_handle_intr_status(adap, A_NCSI_INT_CAUSE, ncsi_intr_info))
519056b2bdd1SGireesh Nagabhushana t4_fatal_err(adap);
519156b2bdd1SGireesh Nagabhushana }
519256b2bdd1SGireesh Nagabhushana
519356b2bdd1SGireesh Nagabhushana /*
519456b2bdd1SGireesh Nagabhushana * XGMAC interrupt handler.
519556b2bdd1SGireesh Nagabhushana */
xgmac_intr_handler(struct adapter * adap,int port)51963dde7c95SVishal Kulkarni static void xgmac_intr_handler(struct adapter *adap, int port)
519756b2bdd1SGireesh Nagabhushana {
5198de483253SVishal Kulkarni u32 v, int_cause_reg;
519956b2bdd1SGireesh Nagabhushana
5200de483253SVishal Kulkarni if (is_t4(adap->params.chip))
5201de483253SVishal Kulkarni int_cause_reg = PORT_REG(port, A_XGMAC_PORT_INT_CAUSE);
5202de483253SVishal Kulkarni else
5203de483253SVishal Kulkarni int_cause_reg = T5_PORT_REG(port, A_MAC_PORT_INT_CAUSE);
5204de483253SVishal Kulkarni
5205de483253SVishal Kulkarni v = t4_read_reg(adap, int_cause_reg);
5206de483253SVishal Kulkarni
52073dde7c95SVishal Kulkarni v &= (F_TXFIFO_PRTY_ERR | F_RXFIFO_PRTY_ERR);
520856b2bdd1SGireesh Nagabhushana if (!v)
520956b2bdd1SGireesh Nagabhushana return;
521056b2bdd1SGireesh Nagabhushana
521156b2bdd1SGireesh Nagabhushana if (v & F_TXFIFO_PRTY_ERR)
52123dde7c95SVishal Kulkarni CH_ALERT(adap, "XGMAC %d Tx FIFO parity error\n",
52133dde7c95SVishal Kulkarni port);
521456b2bdd1SGireesh Nagabhushana if (v & F_RXFIFO_PRTY_ERR)
52153dde7c95SVishal Kulkarni CH_ALERT(adap, "XGMAC %d Rx FIFO parity error\n",
52163dde7c95SVishal Kulkarni port);
5217de483253SVishal Kulkarni t4_write_reg(adap, int_cause_reg, v);
521856b2bdd1SGireesh Nagabhushana t4_fatal_err(adap);
521956b2bdd1SGireesh Nagabhushana }
522056b2bdd1SGireesh Nagabhushana
522156b2bdd1SGireesh Nagabhushana /*
52227e6ad469SVishal Kulkarni * PL Parity Error interrupt handler.
52237e6ad469SVishal Kulkarni */
pl_perr_intr_handler(struct adapter * adap)52247e6ad469SVishal Kulkarni static void pl_perr_intr_handler(struct adapter *adap)
52257e6ad469SVishal Kulkarni {
52267e6ad469SVishal Kulkarni static const struct intr_info pl_perr_info[] = {
52277e6ad469SVishal Kulkarni { F_UART, "UART Parity Error", -1, },
52287e6ad469SVishal Kulkarni { F_ULP_TX, "ULP TX Parity Error", -1 },
52297e6ad469SVishal Kulkarni { F_SGE, "SGE Parity Error", -1 },
52307e6ad469SVishal Kulkarni { F_HMA, "HMA Parity Error", -1 },
52317e6ad469SVishal Kulkarni { F_CPL_SWITCH, "CPL Switch Parity Error", -1 },
52327e6ad469SVishal Kulkarni { F_ULP_RX, "ULP RX Parity Error", -1 },
52337e6ad469SVishal Kulkarni { F_PM_RX, "PM RX Parity Error", -1 },
52347e6ad469SVishal Kulkarni { F_PM_TX, "PM TX Parity Error", -1 },
52357e6ad469SVishal Kulkarni { F_MA, "MA Parity Error", -1 },
52367e6ad469SVishal Kulkarni { F_TP, "TP Parity Error", -1 },
52377e6ad469SVishal Kulkarni { F_LE, "LE Parity Error", -1 },
52387e6ad469SVishal Kulkarni { F_EDC1, "EDC1 Parity Error", -1 },
52397e6ad469SVishal Kulkarni { F_EDC0, "EDC0 Parity Error", -1 },
52407e6ad469SVishal Kulkarni { F_MC, "MC Parity Error", -1 },
52417e6ad469SVishal Kulkarni { F_PCIE, "PCIE Parity Error", -1 },
52427e6ad469SVishal Kulkarni { F_PMU, "PMU Parity Error", -1 },
52437e6ad469SVishal Kulkarni { F_XGMAC_KR1, "XGMAC_KR1 Parity Error", -1 },
52447e6ad469SVishal Kulkarni { F_XGMAC_KR0, "XGMAC_KR0 Parity Error", -1 },
52457e6ad469SVishal Kulkarni { F_XGMAC1, "XGMAC1 Parity Error", -1 },
52467e6ad469SVishal Kulkarni { F_XGMAC0, "XGMAC0 Parity Error", -1 },
52477e6ad469SVishal Kulkarni { F_SMB, "SMB Parity Error", -1 },
52487e6ad469SVishal Kulkarni { F_SF, "SF Parity Error", -1 },
52497e6ad469SVishal Kulkarni { F_PL, "PL Parity Error", -1 },
52507e6ad469SVishal Kulkarni { F_NCSI, "NCSI Parity Error", -1 },
52517e6ad469SVishal Kulkarni { F_MPS, "MPS Parity Error", -1 },
52527e6ad469SVishal Kulkarni { F_MI, "MI Parity Error", -1 },
52537e6ad469SVishal Kulkarni { F_DBG, "DBG Parity Error", -1 },
52547e6ad469SVishal Kulkarni { F_I2CM, "I2CM Parity Error", -1 },
52557e6ad469SVishal Kulkarni { F_CIM, "CIM Parity Error", -1 },
52567e6ad469SVishal Kulkarni };
52577e6ad469SVishal Kulkarni
52587e6ad469SVishal Kulkarni t4_handle_intr_status(adap, A_PL_PERR_CAUSE, pl_perr_info);
52597e6ad469SVishal Kulkarni /* pl_intr_handler() will do the t4_fatal_err(adap) */
52607e6ad469SVishal Kulkarni }
52617e6ad469SVishal Kulkarni
52627e6ad469SVishal Kulkarni /*
526356b2bdd1SGireesh Nagabhushana * PL interrupt handler.
526456b2bdd1SGireesh Nagabhushana */
pl_intr_handler(struct adapter * adap)52653dde7c95SVishal Kulkarni static void pl_intr_handler(struct adapter *adap)
526656b2bdd1SGireesh Nagabhushana {
52673dde7c95SVishal Kulkarni static const struct intr_info pl_intr_info[] = {
52687e6ad469SVishal Kulkarni { F_FATALPERR, "Fatal parity error", -1, 1,
52697e6ad469SVishal Kulkarni pl_perr_intr_handler },
527056b2bdd1SGireesh Nagabhushana { F_PERRVFID, "PL VFID_MAP parity error", -1, 1 },
527156b2bdd1SGireesh Nagabhushana { 0 }
527256b2bdd1SGireesh Nagabhushana };
527356b2bdd1SGireesh Nagabhushana
5274de483253SVishal Kulkarni static struct intr_info t5_pl_intr_info[] = {
52757e6ad469SVishal Kulkarni { F_FATALPERR, "Fatal parity error", -1, 1,
52767e6ad469SVishal Kulkarni pl_perr_intr_handler },
5277de483253SVishal Kulkarni { 0 }
5278de483253SVishal Kulkarni };
5279de483253SVishal Kulkarni
5280de483253SVishal Kulkarni if (t4_handle_intr_status(adap, A_PL_PL_INT_CAUSE,
52813dde7c95SVishal Kulkarni is_t4(adap->params.chip) ?
52823dde7c95SVishal Kulkarni pl_intr_info : t5_pl_intr_info))
528356b2bdd1SGireesh Nagabhushana t4_fatal_err(adap);
528456b2bdd1SGireesh Nagabhushana }
528556b2bdd1SGireesh Nagabhushana
528656b2bdd1SGireesh Nagabhushana #define PF_INTR_MASK (F_PFSW | F_PFCIM)
528756b2bdd1SGireesh Nagabhushana
52883dde7c95SVishal Kulkarni /**
528956b2bdd1SGireesh Nagabhushana * t4_slow_intr_handler - control path interrupt handler
529056b2bdd1SGireesh Nagabhushana * @adapter: the adapter
529156b2bdd1SGireesh Nagabhushana *
529256b2bdd1SGireesh Nagabhushana * T4 interrupt handler for non-data global interrupt events, e.g., errors.
529356b2bdd1SGireesh Nagabhushana * The designation 'slow' is because it involves register reads, while
529456b2bdd1SGireesh Nagabhushana * data interrupts typically don't involve any MMIOs.
529556b2bdd1SGireesh Nagabhushana */
t4_slow_intr_handler(struct adapter * adapter)52963dde7c95SVishal Kulkarni int t4_slow_intr_handler(struct adapter *adapter)
529756b2bdd1SGireesh Nagabhushana {
52987e6ad469SVishal Kulkarni /* There are rare cases where a PL_INT_CAUSE bit may end up getting
52997e6ad469SVishal Kulkarni * set when the corresponding PL_INT_ENABLE bit isn't set. It's
53007e6ad469SVishal Kulkarni * easiest just to mask that case here.
53017e6ad469SVishal Kulkarni */
53027e6ad469SVishal Kulkarni u32 raw_cause = t4_read_reg(adapter, A_PL_INT_CAUSE);
53037e6ad469SVishal Kulkarni u32 enable = t4_read_reg(adapter, A_PL_INT_ENABLE);
53047e6ad469SVishal Kulkarni u32 cause = raw_cause & enable;
530556b2bdd1SGireesh Nagabhushana
530656b2bdd1SGireesh Nagabhushana if (!(cause & GLBL_INTR_MASK))
53073dde7c95SVishal Kulkarni return 0;
53087e6ad469SVishal Kulkarni
53097e6ad469SVishal Kulkarni /* Disable all the interrupt(bits) in PL_INT_ENABLE */
53107e6ad469SVishal Kulkarni t4_write_reg(adapter, A_PL_INT_ENABLE, 0);
53117e6ad469SVishal Kulkarni (void)t4_read_reg(adapter, A_PL_INT_ENABLE); /* flush */
53127e6ad469SVishal Kulkarni
531356b2bdd1SGireesh Nagabhushana if (cause & F_CIM)
531456b2bdd1SGireesh Nagabhushana cim_intr_handler(adapter);
531556b2bdd1SGireesh Nagabhushana if (cause & F_MPS)
531656b2bdd1SGireesh Nagabhushana mps_intr_handler(adapter);
531756b2bdd1SGireesh Nagabhushana if (cause & F_NCSI)
531856b2bdd1SGireesh Nagabhushana ncsi_intr_handler(adapter);
531956b2bdd1SGireesh Nagabhushana if (cause & F_PL)
532056b2bdd1SGireesh Nagabhushana pl_intr_handler(adapter);
532156b2bdd1SGireesh Nagabhushana if (cause & F_SMB)
532256b2bdd1SGireesh Nagabhushana smb_intr_handler(adapter);
53233dde7c95SVishal Kulkarni if (cause & F_MAC0)
532456b2bdd1SGireesh Nagabhushana xgmac_intr_handler(adapter, 0);
53253dde7c95SVishal Kulkarni if (cause & F_MAC1)
532656b2bdd1SGireesh Nagabhushana xgmac_intr_handler(adapter, 1);
53273dde7c95SVishal Kulkarni if (cause & F_MAC2)
532856b2bdd1SGireesh Nagabhushana xgmac_intr_handler(adapter, 2);
53293dde7c95SVishal Kulkarni if (cause & F_MAC3)
533056b2bdd1SGireesh Nagabhushana xgmac_intr_handler(adapter, 3);
533156b2bdd1SGireesh Nagabhushana if (cause & F_PCIE)
533256b2bdd1SGireesh Nagabhushana pcie_intr_handler(adapter);
53333dde7c95SVishal Kulkarni if (cause & F_MC0)
533456b2bdd1SGireesh Nagabhushana mem_intr_handler(adapter, MEM_MC);
53353dde7c95SVishal Kulkarni if (is_t5(adapter->params.chip) && (cause & F_MC1))
53363dde7c95SVishal Kulkarni mem_intr_handler(adapter, MEM_MC1);
533756b2bdd1SGireesh Nagabhushana if (cause & F_EDC0)
533856b2bdd1SGireesh Nagabhushana mem_intr_handler(adapter, MEM_EDC0);
533956b2bdd1SGireesh Nagabhushana if (cause & F_EDC1)
534056b2bdd1SGireesh Nagabhushana mem_intr_handler(adapter, MEM_EDC1);
534156b2bdd1SGireesh Nagabhushana if (cause & F_LE)
534256b2bdd1SGireesh Nagabhushana le_intr_handler(adapter);
534356b2bdd1SGireesh Nagabhushana if (cause & F_TP)
534456b2bdd1SGireesh Nagabhushana tp_intr_handler(adapter);
534556b2bdd1SGireesh Nagabhushana if (cause & F_MA)
534656b2bdd1SGireesh Nagabhushana ma_intr_handler(adapter);
534756b2bdd1SGireesh Nagabhushana if (cause & F_PM_TX)
534856b2bdd1SGireesh Nagabhushana pmtx_intr_handler(adapter);
534956b2bdd1SGireesh Nagabhushana if (cause & F_PM_RX)
535056b2bdd1SGireesh Nagabhushana pmrx_intr_handler(adapter);
535156b2bdd1SGireesh Nagabhushana if (cause & F_ULP_RX)
535256b2bdd1SGireesh Nagabhushana ulprx_intr_handler(adapter);
535356b2bdd1SGireesh Nagabhushana if (cause & F_CPL_SWITCH)
535456b2bdd1SGireesh Nagabhushana cplsw_intr_handler(adapter);
535556b2bdd1SGireesh Nagabhushana if (cause & F_SGE)
535656b2bdd1SGireesh Nagabhushana sge_intr_handler(adapter);
535756b2bdd1SGireesh Nagabhushana if (cause & F_ULP_TX)
535856b2bdd1SGireesh Nagabhushana ulptx_intr_handler(adapter);
535956b2bdd1SGireesh Nagabhushana
536056b2bdd1SGireesh Nagabhushana /* Clear the interrupts just processed for which we are the master. */
53617e6ad469SVishal Kulkarni t4_write_reg(adapter, A_PL_INT_CAUSE, raw_cause & GLBL_INTR_MASK);
53627e6ad469SVishal Kulkarni
53637e6ad469SVishal Kulkarni /* re-enable the interrupts (bits that were disabled
53647e6ad469SVishal Kulkarni * earlier in PL_INT_ENABLE)
53657e6ad469SVishal Kulkarni */
53667e6ad469SVishal Kulkarni t4_write_reg(adapter, A_PL_INT_ENABLE, enable);
53677e6ad469SVishal Kulkarni (void)t4_read_reg(adapter, A_PL_INT_ENABLE); /* flush */
53683dde7c95SVishal Kulkarni return 1;
536956b2bdd1SGireesh Nagabhushana }
537056b2bdd1SGireesh Nagabhushana
53713dde7c95SVishal Kulkarni /**
537256b2bdd1SGireesh Nagabhushana * t4_intr_enable - enable interrupts
537356b2bdd1SGireesh Nagabhushana * @adapter: the adapter whose interrupts should be enabled
537456b2bdd1SGireesh Nagabhushana *
537556b2bdd1SGireesh Nagabhushana * Enable PF-specific interrupts for the calling function and the top-level
537656b2bdd1SGireesh Nagabhushana * interrupt concentrator for global interrupts. Interrupts are already
537756b2bdd1SGireesh Nagabhushana * enabled at each module, here we just enable the roots of the interrupt
537856b2bdd1SGireesh Nagabhushana * hierarchies.
537956b2bdd1SGireesh Nagabhushana *
538056b2bdd1SGireesh Nagabhushana * Note: this function should be called only when the driver manages
538156b2bdd1SGireesh Nagabhushana * non PF-specific interrupts from the various HW modules. Only one PCI
538256b2bdd1SGireesh Nagabhushana * function at a time should be doing this.
538356b2bdd1SGireesh Nagabhushana */
t4_intr_enable(struct adapter * adapter)53843dde7c95SVishal Kulkarni void t4_intr_enable(struct adapter *adapter)
538556b2bdd1SGireesh Nagabhushana {
53863dde7c95SVishal Kulkarni u32 val = 0;
53873dde7c95SVishal Kulkarni u32 whoami = t4_read_reg(adapter, A_PL_WHOAMI);
53883dde7c95SVishal Kulkarni u32 pf = (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5
53893dde7c95SVishal Kulkarni ? G_SOURCEPF(whoami)
53903dde7c95SVishal Kulkarni : G_T6_SOURCEPF(whoami));
539156b2bdd1SGireesh Nagabhushana
53923dde7c95SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5)
53933dde7c95SVishal Kulkarni val = F_ERR_DROPPED_DB | F_ERR_EGR_CTXT_PRIO | F_DBFIFO_HP_INT;
53943dde7c95SVishal Kulkarni else
53953dde7c95SVishal Kulkarni val = F_ERR_PCIE_ERROR0 | F_ERR_PCIE_ERROR1 | F_FATAL_WRE_LEN;
539656b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_SGE_INT_ENABLE3, F_ERR_CPL_EXCEED_IQE_SIZE |
53973dde7c95SVishal Kulkarni F_ERR_INVALID_CIDX_INC | F_ERR_CPL_OPCODE_0 |
53983dde7c95SVishal Kulkarni F_ERR_DATA_CPL_ON_HIGH_QID1 | F_INGRESS_SIZE_ERR |
53993dde7c95SVishal Kulkarni F_ERR_DATA_CPL_ON_HIGH_QID0 | F_ERR_BAD_DB_PIDX3 |
54003dde7c95SVishal Kulkarni F_ERR_BAD_DB_PIDX2 | F_ERR_BAD_DB_PIDX1 |
54013dde7c95SVishal Kulkarni F_ERR_BAD_DB_PIDX0 | F_ERR_ING_CTXT_PRIO |
54023dde7c95SVishal Kulkarni F_DBFIFO_LP_INT | F_EGRESS_SIZE_ERR | val);
540356b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, MYPF_REG(A_PL_PF_INT_ENABLE), PF_INTR_MASK);
540456b2bdd1SGireesh Nagabhushana t4_set_reg_field(adapter, A_PL_INT_MAP0, 0, 1 << pf);
540556b2bdd1SGireesh Nagabhushana }
540656b2bdd1SGireesh Nagabhushana
54073dde7c95SVishal Kulkarni /**
540856b2bdd1SGireesh Nagabhushana * t4_intr_disable - disable interrupts
540956b2bdd1SGireesh Nagabhushana * @adapter: the adapter whose interrupts should be disabled
541056b2bdd1SGireesh Nagabhushana *
541156b2bdd1SGireesh Nagabhushana * Disable interrupts. We only disable the top-level interrupt
541256b2bdd1SGireesh Nagabhushana * concentrators. The caller must be a PCI function managing global
541356b2bdd1SGireesh Nagabhushana * interrupts.
541456b2bdd1SGireesh Nagabhushana */
t4_intr_disable(struct adapter * adapter)54153dde7c95SVishal Kulkarni void t4_intr_disable(struct adapter *adapter)
541656b2bdd1SGireesh Nagabhushana {
54173dde7c95SVishal Kulkarni u32 whoami = t4_read_reg(adapter, A_PL_WHOAMI);
54183dde7c95SVishal Kulkarni u32 pf = (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5
54193dde7c95SVishal Kulkarni ? G_SOURCEPF(whoami)
54203dde7c95SVishal Kulkarni : G_T6_SOURCEPF(whoami));
542156b2bdd1SGireesh Nagabhushana
542256b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, MYPF_REG(A_PL_PF_INT_ENABLE), 0);
542356b2bdd1SGireesh Nagabhushana t4_set_reg_field(adapter, A_PL_INT_MAP0, 1 << pf, 0);
542456b2bdd1SGireesh Nagabhushana }
542556b2bdd1SGireesh Nagabhushana
t4_chip_rss_size(struct adapter * adap)54267e6ad469SVishal Kulkarni unsigned int t4_chip_rss_size(struct adapter *adap)
54277e6ad469SVishal Kulkarni {
54287e6ad469SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5)
54297e6ad469SVishal Kulkarni return RSS_NENTRIES;
54307e6ad469SVishal Kulkarni else
54317e6ad469SVishal Kulkarni return T6_RSS_NENTRIES;
54327e6ad469SVishal Kulkarni }
54337e6ad469SVishal Kulkarni
54343dde7c95SVishal Kulkarni /**
543556b2bdd1SGireesh Nagabhushana * t4_config_rss_range - configure a portion of the RSS mapping table
543656b2bdd1SGireesh Nagabhushana * @adapter: the adapter
543756b2bdd1SGireesh Nagabhushana * @mbox: mbox to use for the FW command
543856b2bdd1SGireesh Nagabhushana * @viid: virtual interface whose RSS subtable is to be written
543956b2bdd1SGireesh Nagabhushana * @start: start entry in the table to write
544056b2bdd1SGireesh Nagabhushana * @n: how many table entries to write
544156b2bdd1SGireesh Nagabhushana * @rspq: values for the "response queue" (Ingress Queue) lookup table
544256b2bdd1SGireesh Nagabhushana * @nrspq: number of values in @rspq
544356b2bdd1SGireesh Nagabhushana *
544456b2bdd1SGireesh Nagabhushana * Programs the selected part of the VI's RSS mapping table with the
544556b2bdd1SGireesh Nagabhushana * provided values. If @nrspq < @n the supplied values are used repeatedly
544656b2bdd1SGireesh Nagabhushana * until the full table range is populated.
544756b2bdd1SGireesh Nagabhushana *
544856b2bdd1SGireesh Nagabhushana * The caller must ensure the values in @rspq are in the range allowed for
544956b2bdd1SGireesh Nagabhushana * @viid.
545056b2bdd1SGireesh Nagabhushana */
t4_config_rss_range(struct adapter * adapter,int mbox,unsigned int viid,int start,int n,const u16 * rspq,unsigned int nrspq)54513dde7c95SVishal Kulkarni int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
545256b2bdd1SGireesh Nagabhushana int start, int n, const u16 *rspq, unsigned int nrspq)
545356b2bdd1SGireesh Nagabhushana {
545456b2bdd1SGireesh Nagabhushana int ret;
545556b2bdd1SGireesh Nagabhushana const u16 *rsp = rspq;
545656b2bdd1SGireesh Nagabhushana const u16 *rsp_end = rspq + nrspq;
545756b2bdd1SGireesh Nagabhushana struct fw_rss_ind_tbl_cmd cmd;
545856b2bdd1SGireesh Nagabhushana
54593dde7c95SVishal Kulkarni memset(&cmd, 0, sizeof(cmd));
54603dde7c95SVishal Kulkarni cmd.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_RSS_IND_TBL_CMD) |
546156b2bdd1SGireesh Nagabhushana F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
546256b2bdd1SGireesh Nagabhushana V_FW_RSS_IND_TBL_CMD_VIID(viid));
54633dde7c95SVishal Kulkarni cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
546456b2bdd1SGireesh Nagabhushana
54653dde7c95SVishal Kulkarni /* Each firmware RSS command can accommodate up to 32 RSS Ingress
546656b2bdd1SGireesh Nagabhushana * Queue Identifiers. These Ingress Queue IDs are packed three to
546756b2bdd1SGireesh Nagabhushana * a 32-bit word as 10-bit values with the upper remaining 2 bits
546856b2bdd1SGireesh Nagabhushana * reserved.
546956b2bdd1SGireesh Nagabhushana */
547056b2bdd1SGireesh Nagabhushana while (n > 0) {
547156b2bdd1SGireesh Nagabhushana int nq = min(n, 32);
5472de483253SVishal Kulkarni int nq_packed = 0;
547356b2bdd1SGireesh Nagabhushana __be32 *qp = &cmd.iq0_to_iq2;
547456b2bdd1SGireesh Nagabhushana
54753dde7c95SVishal Kulkarni /* Set up the firmware RSS command header to send the next
547656b2bdd1SGireesh Nagabhushana * "nq" Ingress Queue IDs to the firmware.
547756b2bdd1SGireesh Nagabhushana */
54783dde7c95SVishal Kulkarni cmd.niqid = cpu_to_be16(nq);
54793dde7c95SVishal Kulkarni cmd.startidx = cpu_to_be16(start);
548056b2bdd1SGireesh Nagabhushana
54813dde7c95SVishal Kulkarni /* "nq" more done for the start of the next loop.
548256b2bdd1SGireesh Nagabhushana */
548356b2bdd1SGireesh Nagabhushana start += nq;
548456b2bdd1SGireesh Nagabhushana n -= nq;
548556b2bdd1SGireesh Nagabhushana
54863dde7c95SVishal Kulkarni /* While there are still Ingress Queue IDs to stuff into the
548756b2bdd1SGireesh Nagabhushana * current firmware RSS command, retrieve them from the
548856b2bdd1SGireesh Nagabhushana * Ingress Queue ID array and insert them into the command.
548956b2bdd1SGireesh Nagabhushana */
549056b2bdd1SGireesh Nagabhushana while (nq > 0) {
54913dde7c95SVishal Kulkarni /* Grab up to the next 3 Ingress Queue IDs (wrapping
549256b2bdd1SGireesh Nagabhushana * around the Ingress Queue ID array if necessary) and
549356b2bdd1SGireesh Nagabhushana * insert them into the firmware RSS command at the
549456b2bdd1SGireesh Nagabhushana * current 3-tuple position within the commad.
549556b2bdd1SGireesh Nagabhushana */
5496de483253SVishal Kulkarni u16 qbuf[3];
5497de483253SVishal Kulkarni u16 *qbp = qbuf;
5498de483253SVishal Kulkarni int nqbuf = min(3, nq);
549956b2bdd1SGireesh Nagabhushana
5500de483253SVishal Kulkarni nq -= nqbuf;
5501de483253SVishal Kulkarni qbuf[0] = qbuf[1] = qbuf[2] = 0;
5502de483253SVishal Kulkarni while (nqbuf && nq_packed < 32) {
5503de483253SVishal Kulkarni nqbuf--;
5504de483253SVishal Kulkarni nq_packed++;
5505de483253SVishal Kulkarni *qbp++ = *rsp++;
5506de483253SVishal Kulkarni if (rsp >= rsp_end)
5507de483253SVishal Kulkarni rsp = rspq;
5508de483253SVishal Kulkarni }
5509de483253SVishal Kulkarni *qp++ = cpu_to_be32(V_FW_RSS_IND_TBL_CMD_IQ0(qbuf[0]) |
5510de483253SVishal Kulkarni V_FW_RSS_IND_TBL_CMD_IQ1(qbuf[1]) |
5511de483253SVishal Kulkarni V_FW_RSS_IND_TBL_CMD_IQ2(qbuf[2]));
551256b2bdd1SGireesh Nagabhushana }
551356b2bdd1SGireesh Nagabhushana
55143dde7c95SVishal Kulkarni /* Send this portion of the RRS table update to the firmware;
551556b2bdd1SGireesh Nagabhushana * bail out on any errors.
551656b2bdd1SGireesh Nagabhushana */
551756b2bdd1SGireesh Nagabhushana ret = t4_wr_mbox(adapter, mbox, &cmd, sizeof(cmd), NULL);
55183dde7c95SVishal Kulkarni if (ret)
55193dde7c95SVishal Kulkarni return ret;
55203dde7c95SVishal Kulkarni }
55213dde7c95SVishal Kulkarni return 0;
552256b2bdd1SGireesh Nagabhushana }
552356b2bdd1SGireesh Nagabhushana
55243dde7c95SVishal Kulkarni /**
552556b2bdd1SGireesh Nagabhushana * t4_config_glbl_rss - configure the global RSS mode
552656b2bdd1SGireesh Nagabhushana * @adapter: the adapter
552756b2bdd1SGireesh Nagabhushana * @mbox: mbox to use for the FW command
552856b2bdd1SGireesh Nagabhushana * @mode: global RSS mode
552956b2bdd1SGireesh Nagabhushana * @flags: mode-specific flags
553056b2bdd1SGireesh Nagabhushana *
553156b2bdd1SGireesh Nagabhushana * Sets the global RSS mode.
553256b2bdd1SGireesh Nagabhushana */
t4_config_glbl_rss(struct adapter * adapter,int mbox,unsigned int mode,unsigned int flags)55333dde7c95SVishal Kulkarni int t4_config_glbl_rss(struct adapter *adapter, int mbox, unsigned int mode,
553456b2bdd1SGireesh Nagabhushana unsigned int flags)
553556b2bdd1SGireesh Nagabhushana {
553656b2bdd1SGireesh Nagabhushana struct fw_rss_glb_config_cmd c;
553756b2bdd1SGireesh Nagabhushana
55383dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
55393dde7c95SVishal Kulkarni c.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
554056b2bdd1SGireesh Nagabhushana F_FW_CMD_REQUEST | F_FW_CMD_WRITE);
55413dde7c95SVishal Kulkarni c.retval_len16 = cpu_to_be32(FW_LEN16(c));
554256b2bdd1SGireesh Nagabhushana if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) {
55433dde7c95SVishal Kulkarni c.u.manual.mode_pkd =
55443dde7c95SVishal Kulkarni cpu_to_be32(V_FW_RSS_GLB_CONFIG_CMD_MODE(mode));
554556b2bdd1SGireesh Nagabhushana } else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) {
55463dde7c95SVishal Kulkarni c.u.basicvirtual.mode_keymode =
55473dde7c95SVishal Kulkarni cpu_to_be32(V_FW_RSS_GLB_CONFIG_CMD_MODE(mode));
55483dde7c95SVishal Kulkarni c.u.basicvirtual.synmapen_to_hashtoeplitz = cpu_to_be32(flags);
554956b2bdd1SGireesh Nagabhushana } else
55503dde7c95SVishal Kulkarni return -EINVAL;
55513dde7c95SVishal Kulkarni return t4_wr_mbox(adapter, mbox, &c, sizeof(c), NULL);
555256b2bdd1SGireesh Nagabhushana }
555356b2bdd1SGireesh Nagabhushana
55543dde7c95SVishal Kulkarni /**
555556b2bdd1SGireesh Nagabhushana * t4_config_vi_rss - configure per VI RSS settings
555656b2bdd1SGireesh Nagabhushana * @adapter: the adapter
555756b2bdd1SGireesh Nagabhushana * @mbox: mbox to use for the FW command
555856b2bdd1SGireesh Nagabhushana * @viid: the VI id
555956b2bdd1SGireesh Nagabhushana * @flags: RSS flags
556056b2bdd1SGireesh Nagabhushana * @defq: id of the default RSS queue for the VI.
55613dde7c95SVishal Kulkarni * @skeyidx: RSS secret key table index for non-global mode
55623dde7c95SVishal Kulkarni * @skey: RSS vf_scramble key for VI.
556356b2bdd1SGireesh Nagabhushana *
556456b2bdd1SGireesh Nagabhushana * Configures VI-specific RSS properties.
556556b2bdd1SGireesh Nagabhushana */
t4_config_vi_rss(struct adapter * adapter,int mbox,unsigned int viid,unsigned int flags,unsigned int defq,unsigned int skeyidx,unsigned int skey)55663dde7c95SVishal Kulkarni int t4_config_vi_rss(struct adapter *adapter, int mbox, unsigned int viid,
55673dde7c95SVishal Kulkarni unsigned int flags, unsigned int defq, unsigned int skeyidx,
55683dde7c95SVishal Kulkarni unsigned int skey)
556956b2bdd1SGireesh Nagabhushana {
557056b2bdd1SGireesh Nagabhushana struct fw_rss_vi_config_cmd c;
557156b2bdd1SGireesh Nagabhushana
55723dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
55733dde7c95SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) |
557456b2bdd1SGireesh Nagabhushana F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
557556b2bdd1SGireesh Nagabhushana V_FW_RSS_VI_CONFIG_CMD_VIID(viid));
55763dde7c95SVishal Kulkarni c.retval_len16 = cpu_to_be32(FW_LEN16(c));
55773dde7c95SVishal Kulkarni c.u.basicvirtual.defaultq_to_udpen = cpu_to_be32(flags |
557856b2bdd1SGireesh Nagabhushana V_FW_RSS_VI_CONFIG_CMD_DEFAULTQ(defq));
55793dde7c95SVishal Kulkarni c.u.basicvirtual.secretkeyidx_pkd = cpu_to_be32(
55803dde7c95SVishal Kulkarni V_FW_RSS_VI_CONFIG_CMD_SECRETKEYIDX(skeyidx));
55813dde7c95SVishal Kulkarni c.u.basicvirtual.secretkeyxor = cpu_to_be32(skey);
55823dde7c95SVishal Kulkarni
55833dde7c95SVishal Kulkarni return t4_wr_mbox(adapter, mbox, &c, sizeof(c), NULL);
558456b2bdd1SGireesh Nagabhushana }
558556b2bdd1SGireesh Nagabhushana
558656b2bdd1SGireesh Nagabhushana /* Read an RSS table row */
rd_rss_row(struct adapter * adap,int row,u32 * val)55873dde7c95SVishal Kulkarni static int rd_rss_row(struct adapter *adap, int row, u32 *val)
558856b2bdd1SGireesh Nagabhushana {
558956b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_TP_RSS_LKP_TABLE, 0xfff00000 | row);
55903dde7c95SVishal Kulkarni return t4_wait_op_done_val(adap, A_TP_RSS_LKP_TABLE, F_LKPTBLROWVLD, 1,
55913dde7c95SVishal Kulkarni 5, 0, val);
559256b2bdd1SGireesh Nagabhushana }
559356b2bdd1SGireesh Nagabhushana
55943dde7c95SVishal Kulkarni /**
559556b2bdd1SGireesh Nagabhushana * t4_read_rss - read the contents of the RSS mapping table
559656b2bdd1SGireesh Nagabhushana * @adapter: the adapter
559756b2bdd1SGireesh Nagabhushana * @map: holds the contents of the RSS mapping table
559856b2bdd1SGireesh Nagabhushana *
559956b2bdd1SGireesh Nagabhushana * Reads the contents of the RSS hash->queue mapping table.
560056b2bdd1SGireesh Nagabhushana */
t4_read_rss(struct adapter * adapter,u16 * map)56013dde7c95SVishal Kulkarni int t4_read_rss(struct adapter *adapter, u16 *map)
560256b2bdd1SGireesh Nagabhushana {
560356b2bdd1SGireesh Nagabhushana u32 val;
56047e6ad469SVishal Kulkarni int i, ret, nentries;
560556b2bdd1SGireesh Nagabhushana
56067e6ad469SVishal Kulkarni nentries = t4_chip_rss_size(adapter);
56077e6ad469SVishal Kulkarni for (i = 0; i < nentries / 2; ++i) {
560856b2bdd1SGireesh Nagabhushana ret = rd_rss_row(adapter, i, &val);
56093dde7c95SVishal Kulkarni if (ret)
56103dde7c95SVishal Kulkarni return ret;
561156b2bdd1SGireesh Nagabhushana *map++ = G_LKPTBLQUEUE0(val);
561256b2bdd1SGireesh Nagabhushana *map++ = G_LKPTBLQUEUE1(val);
561356b2bdd1SGireesh Nagabhushana }
56143dde7c95SVishal Kulkarni return 0;
561556b2bdd1SGireesh Nagabhushana }
561656b2bdd1SGireesh Nagabhushana
56173dde7c95SVishal Kulkarni /**
56183dde7c95SVishal Kulkarni * t4_tp_fw_ldst_rw - Access TP indirect register through LDST
56193dde7c95SVishal Kulkarni * @adap: the adapter
56203dde7c95SVishal Kulkarni * @cmd: TP fw ldst address space type
56213dde7c95SVishal Kulkarni * @vals: where the indirect register values are stored/written
56223dde7c95SVishal Kulkarni * @nregs: how many indirect registers to read/write
56233dde7c95SVishal Kulkarni * @start_idx: index of first indirect register to read/write
56243dde7c95SVishal Kulkarni * @rw: Read (1) or Write (0)
56253dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
56263dde7c95SVishal Kulkarni *
56273dde7c95SVishal Kulkarni * Access TP indirect registers through LDST
56283dde7c95SVishal Kulkarni **/
t4_tp_fw_ldst_rw(struct adapter * adap,int cmd,u32 * vals,unsigned int nregs,unsigned int start_index,unsigned int rw,bool sleep_ok)56293dde7c95SVishal Kulkarni static int t4_tp_fw_ldst_rw(struct adapter *adap, int cmd, u32 *vals,
56303dde7c95SVishal Kulkarni unsigned int nregs, unsigned int start_index,
56313dde7c95SVishal Kulkarni unsigned int rw, bool sleep_ok)
56323dde7c95SVishal Kulkarni {
56333dde7c95SVishal Kulkarni int ret = 0;
56343dde7c95SVishal Kulkarni unsigned int i;
56353dde7c95SVishal Kulkarni struct fw_ldst_cmd c;
56363dde7c95SVishal Kulkarni
56373dde7c95SVishal Kulkarni for (i = 0; i < nregs; i++) {
56383dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
56393dde7c95SVishal Kulkarni c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
56403dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
56413dde7c95SVishal Kulkarni (rw ? F_FW_CMD_READ :
56423dde7c95SVishal Kulkarni F_FW_CMD_WRITE) |
56433dde7c95SVishal Kulkarni V_FW_LDST_CMD_ADDRSPACE(cmd));
56443dde7c95SVishal Kulkarni c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
56453dde7c95SVishal Kulkarni
56463dde7c95SVishal Kulkarni c.u.addrval.addr = cpu_to_be32(start_index + i);
56473dde7c95SVishal Kulkarni c.u.addrval.val = rw ? 0 : cpu_to_be32(vals[i]);
56483dde7c95SVishal Kulkarni ret = t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c,
56493dde7c95SVishal Kulkarni sleep_ok);
56503dde7c95SVishal Kulkarni if (ret)
56513dde7c95SVishal Kulkarni return ret;
56523dde7c95SVishal Kulkarni
56533dde7c95SVishal Kulkarni if (rw)
56543dde7c95SVishal Kulkarni vals[i] = be32_to_cpu(c.u.addrval.val);
56553dde7c95SVishal Kulkarni }
56563dde7c95SVishal Kulkarni return 0;
56573dde7c95SVishal Kulkarni }
56583dde7c95SVishal Kulkarni
56593dde7c95SVishal Kulkarni /**
56603dde7c95SVishal Kulkarni * t4_tp_indirect_rw - Read/Write TP indirect register through LDST or backdoor
56613dde7c95SVishal Kulkarni * @adap: the adapter
56623dde7c95SVishal Kulkarni * @reg_addr: Address Register
56633dde7c95SVishal Kulkarni * @reg_data: Data register
56643dde7c95SVishal Kulkarni * @buff: where the indirect register values are stored/written
56653dde7c95SVishal Kulkarni * @nregs: how many indirect registers to read/write
56663dde7c95SVishal Kulkarni * @start_index: index of first indirect register to read/write
56673dde7c95SVishal Kulkarni * @rw: READ(1) or WRITE(0)
56683dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
56693dde7c95SVishal Kulkarni *
56703dde7c95SVishal Kulkarni * Read/Write TP indirect registers through LDST if possible.
56713dde7c95SVishal Kulkarni * Else, use backdoor access
56723dde7c95SVishal Kulkarni **/
t4_tp_indirect_rw(struct adapter * adap,u32 reg_addr,u32 reg_data,u32 * buff,u32 nregs,u32 start_index,int rw,bool sleep_ok)56733dde7c95SVishal Kulkarni static void t4_tp_indirect_rw(struct adapter *adap, u32 reg_addr, u32 reg_data,
56743dde7c95SVishal Kulkarni u32 *buff, u32 nregs, u32 start_index, int rw,
56753dde7c95SVishal Kulkarni bool sleep_ok)
56763dde7c95SVishal Kulkarni {
56773dde7c95SVishal Kulkarni int rc = -EINVAL;
56783dde7c95SVishal Kulkarni int cmd;
56793dde7c95SVishal Kulkarni
56803dde7c95SVishal Kulkarni switch (reg_addr) {
56813dde7c95SVishal Kulkarni case A_TP_PIO_ADDR:
56823dde7c95SVishal Kulkarni cmd = FW_LDST_ADDRSPC_TP_PIO;
56833dde7c95SVishal Kulkarni break;
56843dde7c95SVishal Kulkarni case A_TP_TM_PIO_ADDR:
56853dde7c95SVishal Kulkarni cmd = FW_LDST_ADDRSPC_TP_TM_PIO;
56863dde7c95SVishal Kulkarni break;
56873dde7c95SVishal Kulkarni case A_TP_MIB_INDEX:
56883dde7c95SVishal Kulkarni cmd = FW_LDST_ADDRSPC_TP_MIB;
56893dde7c95SVishal Kulkarni break;
56903dde7c95SVishal Kulkarni default:
56913dde7c95SVishal Kulkarni goto indirect_access;
56923dde7c95SVishal Kulkarni }
56933dde7c95SVishal Kulkarni
56943dde7c95SVishal Kulkarni if (t4_use_ldst(adap))
56953dde7c95SVishal Kulkarni rc = t4_tp_fw_ldst_rw(adap, cmd, buff, nregs, start_index, rw,
56963dde7c95SVishal Kulkarni sleep_ok);
56973dde7c95SVishal Kulkarni
56983dde7c95SVishal Kulkarni indirect_access:
56993dde7c95SVishal Kulkarni
57003dde7c95SVishal Kulkarni if (rc) {
57013dde7c95SVishal Kulkarni if (rw)
57023dde7c95SVishal Kulkarni t4_read_indirect(adap, reg_addr, reg_data, buff, nregs,
57033dde7c95SVishal Kulkarni start_index);
57043dde7c95SVishal Kulkarni else
57053dde7c95SVishal Kulkarni t4_write_indirect(adap, reg_addr, reg_data, buff, nregs,
57063dde7c95SVishal Kulkarni start_index);
57073dde7c95SVishal Kulkarni }
57083dde7c95SVishal Kulkarni }
57093dde7c95SVishal Kulkarni
57103dde7c95SVishal Kulkarni /**
57113dde7c95SVishal Kulkarni * t4_tp_pio_read - Read TP PIO registers
57123dde7c95SVishal Kulkarni * @adap: the adapter
57133dde7c95SVishal Kulkarni * @buff: where the indirect register values are written
57143dde7c95SVishal Kulkarni * @nregs: how many indirect registers to read
57153dde7c95SVishal Kulkarni * @start_index: index of first indirect register to read
57163dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
57173dde7c95SVishal Kulkarni *
57183dde7c95SVishal Kulkarni * Read TP PIO Registers
57193dde7c95SVishal Kulkarni **/
t4_tp_pio_read(struct adapter * adap,u32 * buff,u32 nregs,u32 start_index,bool sleep_ok)57203dde7c95SVishal Kulkarni void t4_tp_pio_read(struct adapter *adap, u32 *buff, u32 nregs,
57213dde7c95SVishal Kulkarni u32 start_index, bool sleep_ok)
57223dde7c95SVishal Kulkarni {
57233dde7c95SVishal Kulkarni t4_tp_indirect_rw(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, buff, nregs,
57243dde7c95SVishal Kulkarni start_index, 1, sleep_ok);
57253dde7c95SVishal Kulkarni }
57263dde7c95SVishal Kulkarni
57273dde7c95SVishal Kulkarni /**
57283dde7c95SVishal Kulkarni * t4_tp_pio_write - Write TP PIO registers
57293dde7c95SVishal Kulkarni * @adap: the adapter
57303dde7c95SVishal Kulkarni * @buff: where the indirect register values are stored
57313dde7c95SVishal Kulkarni * @nregs: how many indirect registers to write
57323dde7c95SVishal Kulkarni * @start_index: index of first indirect register to write
57333dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
57343dde7c95SVishal Kulkarni *
57353dde7c95SVishal Kulkarni * Write TP PIO Registers
57363dde7c95SVishal Kulkarni **/
t4_tp_pio_write(struct adapter * adap,u32 * buff,u32 nregs,u32 start_index,bool sleep_ok)57373dde7c95SVishal Kulkarni void t4_tp_pio_write(struct adapter *adap, u32 *buff, u32 nregs,
57383dde7c95SVishal Kulkarni u32 start_index, bool sleep_ok)
57393dde7c95SVishal Kulkarni {
57403dde7c95SVishal Kulkarni t4_tp_indirect_rw(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, buff, nregs,
57413dde7c95SVishal Kulkarni start_index, 0, sleep_ok);
57423dde7c95SVishal Kulkarni }
57433dde7c95SVishal Kulkarni
57443dde7c95SVishal Kulkarni /**
57453dde7c95SVishal Kulkarni * t4_tp_tm_pio_read - Read TP TM PIO registers
57463dde7c95SVishal Kulkarni * @adap: the adapter
57473dde7c95SVishal Kulkarni * @buff: where the indirect register values are written
57483dde7c95SVishal Kulkarni * @nregs: how many indirect registers to read
57493dde7c95SVishal Kulkarni * @start_index: index of first indirect register to read
57503dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
57513dde7c95SVishal Kulkarni *
57523dde7c95SVishal Kulkarni * Read TP TM PIO Registers
57533dde7c95SVishal Kulkarni **/
t4_tp_tm_pio_read(struct adapter * adap,u32 * buff,u32 nregs,u32 start_index,bool sleep_ok)57543dde7c95SVishal Kulkarni void t4_tp_tm_pio_read(struct adapter *adap, u32 *buff, u32 nregs,
57553dde7c95SVishal Kulkarni u32 start_index, bool sleep_ok)
57563dde7c95SVishal Kulkarni {
57573dde7c95SVishal Kulkarni t4_tp_indirect_rw(adap, A_TP_TM_PIO_ADDR, A_TP_TM_PIO_DATA, buff,
57583dde7c95SVishal Kulkarni nregs, start_index, 1, sleep_ok);
57593dde7c95SVishal Kulkarni }
57603dde7c95SVishal Kulkarni
57613dde7c95SVishal Kulkarni /**
57623dde7c95SVishal Kulkarni * t4_tp_mib_read - Read TP MIB registers
57633dde7c95SVishal Kulkarni * @adap: the adapter
57643dde7c95SVishal Kulkarni * @buff: where the indirect register values are written
57653dde7c95SVishal Kulkarni * @nregs: how many indirect registers to read
57663dde7c95SVishal Kulkarni * @start_index: index of first indirect register to read
57673dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
57683dde7c95SVishal Kulkarni *
57693dde7c95SVishal Kulkarni * Read TP MIB Registers
57703dde7c95SVishal Kulkarni **/
t4_tp_mib_read(struct adapter * adap,u32 * buff,u32 nregs,u32 start_index,bool sleep_ok)57713dde7c95SVishal Kulkarni void t4_tp_mib_read(struct adapter *adap, u32 *buff, u32 nregs, u32 start_index,
57723dde7c95SVishal Kulkarni bool sleep_ok)
57733dde7c95SVishal Kulkarni {
57743dde7c95SVishal Kulkarni t4_tp_indirect_rw(adap, A_TP_MIB_INDEX, A_TP_MIB_DATA, buff, nregs,
57753dde7c95SVishal Kulkarni start_index, 1, sleep_ok);
57763dde7c95SVishal Kulkarni }
57773dde7c95SVishal Kulkarni
57783dde7c95SVishal Kulkarni /**
577956b2bdd1SGireesh Nagabhushana * t4_read_rss_key - read the global RSS key
578056b2bdd1SGireesh Nagabhushana * @adap: the adapter
578156b2bdd1SGireesh Nagabhushana * @key: 10-entry array holding the 320-bit RSS key
57823dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
578356b2bdd1SGireesh Nagabhushana *
578456b2bdd1SGireesh Nagabhushana * Reads the global 320-bit RSS key.
578556b2bdd1SGireesh Nagabhushana */
t4_read_rss_key(struct adapter * adap,u32 * key,bool sleep_ok)57863dde7c95SVishal Kulkarni void t4_read_rss_key(struct adapter *adap, u32 *key, bool sleep_ok)
578756b2bdd1SGireesh Nagabhushana {
57883dde7c95SVishal Kulkarni t4_tp_pio_read(adap, key, 10, A_TP_RSS_SECRET_KEY0, sleep_ok);
578956b2bdd1SGireesh Nagabhushana }
579056b2bdd1SGireesh Nagabhushana
57913dde7c95SVishal Kulkarni /**
579256b2bdd1SGireesh Nagabhushana * t4_write_rss_key - program one of the RSS keys
579356b2bdd1SGireesh Nagabhushana * @adap: the adapter
579456b2bdd1SGireesh Nagabhushana * @key: 10-entry array holding the 320-bit RSS key
579556b2bdd1SGireesh Nagabhushana * @idx: which RSS key to write
57963dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
579756b2bdd1SGireesh Nagabhushana *
579856b2bdd1SGireesh Nagabhushana * Writes one of the RSS keys with the given 320-bit value. If @idx is
579956b2bdd1SGireesh Nagabhushana * 0..15 the corresponding entry in the RSS key table is written,
580056b2bdd1SGireesh Nagabhushana * otherwise the global RSS key is written.
580156b2bdd1SGireesh Nagabhushana */
t4_write_rss_key(struct adapter * adap,const u32 * key,int idx,bool sleep_ok)58023dde7c95SVishal Kulkarni void t4_write_rss_key(struct adapter *adap, const u32 *key, int idx,
58033dde7c95SVishal Kulkarni bool sleep_ok)
580456b2bdd1SGireesh Nagabhushana {
58053dde7c95SVishal Kulkarni u8 rss_key_addr_cnt = 16;
58063dde7c95SVishal Kulkarni u32 vrt = t4_read_reg(adap, A_TP_RSS_CONFIG_VRT);
58073dde7c95SVishal Kulkarni
58083dde7c95SVishal Kulkarni /* T6 and later: for KeyMode 3 (per-vf and per-vf scramble),
58093dde7c95SVishal Kulkarni * allows access to key addresses 16-63 by using KeyWrAddrX
58103dde7c95SVishal Kulkarni * as index[5:4](upper 2) into key table
58113dde7c95SVishal Kulkarni */
58123dde7c95SVishal Kulkarni if ((CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) &&
58133dde7c95SVishal Kulkarni (vrt & F_KEYEXTEND) && (G_KEYMODE(vrt) == 3))
58143dde7c95SVishal Kulkarni rss_key_addr_cnt = 32;
58153dde7c95SVishal Kulkarni
58163dde7c95SVishal Kulkarni t4_tp_pio_write(adap, (void *)key, 10, A_TP_RSS_SECRET_KEY0, sleep_ok);
58173dde7c95SVishal Kulkarni
58183dde7c95SVishal Kulkarni if (idx >= 0 && idx < rss_key_addr_cnt) {
58193dde7c95SVishal Kulkarni if (rss_key_addr_cnt > 16)
582056b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_TP_RSS_CONFIG_VRT,
58213dde7c95SVishal Kulkarni vrt | V_KEYWRADDRX(idx >> 4) |
58223dde7c95SVishal Kulkarni V_T6_VFWRADDR(idx) | F_KEYWREN);
58233dde7c95SVishal Kulkarni else
58243dde7c95SVishal Kulkarni t4_write_reg(adap, A_TP_RSS_CONFIG_VRT,
58253dde7c95SVishal Kulkarni vrt| V_KEYWRADDR(idx) | F_KEYWREN);
58263dde7c95SVishal Kulkarni }
582756b2bdd1SGireesh Nagabhushana }
582856b2bdd1SGireesh Nagabhushana
58293dde7c95SVishal Kulkarni /**
583056b2bdd1SGireesh Nagabhushana * t4_read_rss_pf_config - read PF RSS Configuration Table
583156b2bdd1SGireesh Nagabhushana * @adapter: the adapter
583256b2bdd1SGireesh Nagabhushana * @index: the entry in the PF RSS table to read
583356b2bdd1SGireesh Nagabhushana * @valp: where to store the returned value
58343dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
583556b2bdd1SGireesh Nagabhushana *
583656b2bdd1SGireesh Nagabhushana * Reads the PF RSS Configuration Table at the specified index and returns
583756b2bdd1SGireesh Nagabhushana * the value found there.
583856b2bdd1SGireesh Nagabhushana */
t4_read_rss_pf_config(struct adapter * adapter,unsigned int index,u32 * valp,bool sleep_ok)58393dde7c95SVishal Kulkarni void t4_read_rss_pf_config(struct adapter *adapter, unsigned int index,
58403dde7c95SVishal Kulkarni u32 *valp, bool sleep_ok)
584156b2bdd1SGireesh Nagabhushana {
58423dde7c95SVishal Kulkarni t4_tp_pio_read(adapter, valp, 1, A_TP_RSS_PF0_CONFIG + index, sleep_ok);
584356b2bdd1SGireesh Nagabhushana }
584456b2bdd1SGireesh Nagabhushana
58453dde7c95SVishal Kulkarni /**
584656b2bdd1SGireesh Nagabhushana * t4_write_rss_pf_config - write PF RSS Configuration Table
584756b2bdd1SGireesh Nagabhushana * @adapter: the adapter
584856b2bdd1SGireesh Nagabhushana * @index: the entry in the VF RSS table to read
584956b2bdd1SGireesh Nagabhushana * @val: the value to store
58503dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
585156b2bdd1SGireesh Nagabhushana *
585256b2bdd1SGireesh Nagabhushana * Writes the PF RSS Configuration Table at the specified index with the
585356b2bdd1SGireesh Nagabhushana * specified value.
585456b2bdd1SGireesh Nagabhushana */
t4_write_rss_pf_config(struct adapter * adapter,unsigned int index,u32 val,bool sleep_ok)58553dde7c95SVishal Kulkarni void t4_write_rss_pf_config(struct adapter *adapter, unsigned int index,
58563dde7c95SVishal Kulkarni u32 val, bool sleep_ok)
585756b2bdd1SGireesh Nagabhushana {
58583dde7c95SVishal Kulkarni t4_tp_pio_write(adapter, &val, 1, A_TP_RSS_PF0_CONFIG + index,
58593dde7c95SVishal Kulkarni sleep_ok);
586056b2bdd1SGireesh Nagabhushana }
586156b2bdd1SGireesh Nagabhushana
58623dde7c95SVishal Kulkarni /**
586356b2bdd1SGireesh Nagabhushana * t4_read_rss_vf_config - read VF RSS Configuration Table
586456b2bdd1SGireesh Nagabhushana * @adapter: the adapter
586556b2bdd1SGireesh Nagabhushana * @index: the entry in the VF RSS table to read
586656b2bdd1SGireesh Nagabhushana * @vfl: where to store the returned VFL
586756b2bdd1SGireesh Nagabhushana * @vfh: where to store the returned VFH
58683dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
586956b2bdd1SGireesh Nagabhushana *
587056b2bdd1SGireesh Nagabhushana * Reads the VF RSS Configuration Table at the specified index and returns
587156b2bdd1SGireesh Nagabhushana * the (VFL, VFH) values found there.
587256b2bdd1SGireesh Nagabhushana */
t4_read_rss_vf_config(struct adapter * adapter,unsigned int index,u32 * vfl,u32 * vfh,bool sleep_ok)58733dde7c95SVishal Kulkarni void t4_read_rss_vf_config(struct adapter *adapter, unsigned int index,
58743dde7c95SVishal Kulkarni u32 *vfl, u32 *vfh, bool sleep_ok)
587556b2bdd1SGireesh Nagabhushana {
58763dde7c95SVishal Kulkarni u32 vrt, mask, data;
587756b2bdd1SGireesh Nagabhushana
58783dde7c95SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5) {
58793dde7c95SVishal Kulkarni mask = V_VFWRADDR(M_VFWRADDR);
58803dde7c95SVishal Kulkarni data = V_VFWRADDR(index);
58813dde7c95SVishal Kulkarni } else {
58823dde7c95SVishal Kulkarni mask = V_T6_VFWRADDR(M_T6_VFWRADDR);
58833dde7c95SVishal Kulkarni data = V_T6_VFWRADDR(index);
58843dde7c95SVishal Kulkarni }
588556b2bdd1SGireesh Nagabhushana /*
588656b2bdd1SGireesh Nagabhushana * Request that the index'th VF Table values be read into VFL/VFH.
588756b2bdd1SGireesh Nagabhushana */
588856b2bdd1SGireesh Nagabhushana vrt = t4_read_reg(adapter, A_TP_RSS_CONFIG_VRT);
58893dde7c95SVishal Kulkarni vrt &= ~(F_VFRDRG | F_VFWREN | F_KEYWREN | mask);
58903dde7c95SVishal Kulkarni vrt |= data | F_VFRDEN;
589156b2bdd1SGireesh Nagabhushana t4_write_reg(adapter, A_TP_RSS_CONFIG_VRT, vrt);
589256b2bdd1SGireesh Nagabhushana
589356b2bdd1SGireesh Nagabhushana /*
589456b2bdd1SGireesh Nagabhushana * Grab the VFL/VFH values ...
589556b2bdd1SGireesh Nagabhushana */
58963dde7c95SVishal Kulkarni t4_tp_pio_read(adapter, vfl, 1, A_TP_RSS_VFL_CONFIG, sleep_ok);
58973dde7c95SVishal Kulkarni t4_tp_pio_read(adapter, vfh, 1, A_TP_RSS_VFH_CONFIG, sleep_ok);
589856b2bdd1SGireesh Nagabhushana }
589956b2bdd1SGireesh Nagabhushana
59003dde7c95SVishal Kulkarni /**
590156b2bdd1SGireesh Nagabhushana * t4_read_rss_pf_map - read PF RSS Map
590256b2bdd1SGireesh Nagabhushana * @adapter: the adapter
59033dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
590456b2bdd1SGireesh Nagabhushana *
590556b2bdd1SGireesh Nagabhushana * Reads the PF RSS Map register and returns its value.
590656b2bdd1SGireesh Nagabhushana */
t4_read_rss_pf_map(struct adapter * adapter,bool sleep_ok)59073dde7c95SVishal Kulkarni u32 t4_read_rss_pf_map(struct adapter *adapter, bool sleep_ok)
590856b2bdd1SGireesh Nagabhushana {
590956b2bdd1SGireesh Nagabhushana u32 pfmap;
591056b2bdd1SGireesh Nagabhushana
59113dde7c95SVishal Kulkarni t4_tp_pio_read(adapter, &pfmap, 1, A_TP_RSS_PF_MAP, sleep_ok);
59123dde7c95SVishal Kulkarni
59133dde7c95SVishal Kulkarni return pfmap;
591456b2bdd1SGireesh Nagabhushana }
591556b2bdd1SGireesh Nagabhushana
59163dde7c95SVishal Kulkarni /**
591756b2bdd1SGireesh Nagabhushana * t4_read_rss_pf_mask - read PF RSS Mask
591856b2bdd1SGireesh Nagabhushana * @adapter: the adapter
59193dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
592056b2bdd1SGireesh Nagabhushana *
592156b2bdd1SGireesh Nagabhushana * Reads the PF RSS Mask register and returns its value.
592256b2bdd1SGireesh Nagabhushana */
t4_read_rss_pf_mask(struct adapter * adapter,bool sleep_ok)59233dde7c95SVishal Kulkarni u32 t4_read_rss_pf_mask(struct adapter *adapter, bool sleep_ok)
592456b2bdd1SGireesh Nagabhushana {
592556b2bdd1SGireesh Nagabhushana u32 pfmask;
592656b2bdd1SGireesh Nagabhushana
59273dde7c95SVishal Kulkarni t4_tp_pio_read(adapter, &pfmask, 1, A_TP_RSS_PF_MSK, sleep_ok);
59283dde7c95SVishal Kulkarni
59293dde7c95SVishal Kulkarni return pfmask;
593056b2bdd1SGireesh Nagabhushana }
593156b2bdd1SGireesh Nagabhushana
59323dde7c95SVishal Kulkarni /**
593356b2bdd1SGireesh Nagabhushana * t4_tp_get_tcp_stats - read TP's TCP MIB counters
593456b2bdd1SGireesh Nagabhushana * @adap: the adapter
593556b2bdd1SGireesh Nagabhushana * @v4: holds the TCP/IP counter values
593656b2bdd1SGireesh Nagabhushana * @v6: holds the TCP/IPv6 counter values
59373dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
593856b2bdd1SGireesh Nagabhushana *
593956b2bdd1SGireesh Nagabhushana * Returns the values of TP's TCP/IP and TCP/IPv6 MIB counters.
594056b2bdd1SGireesh Nagabhushana * Either @v4 or @v6 may be %NULL to skip the corresponding stats.
594156b2bdd1SGireesh Nagabhushana */
t4_tp_get_tcp_stats(struct adapter * adap,struct tp_tcp_stats * v4,struct tp_tcp_stats * v6,bool sleep_ok)59423dde7c95SVishal Kulkarni void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
59433dde7c95SVishal Kulkarni struct tp_tcp_stats *v6, bool sleep_ok)
594456b2bdd1SGireesh Nagabhushana {
594556b2bdd1SGireesh Nagabhushana u32 val[A_TP_MIB_TCP_RXT_SEG_LO - A_TP_MIB_TCP_OUT_RST + 1];
594656b2bdd1SGireesh Nagabhushana
594756b2bdd1SGireesh Nagabhushana #define STAT_IDX(x) ((A_TP_MIB_TCP_##x) - A_TP_MIB_TCP_OUT_RST)
594856b2bdd1SGireesh Nagabhushana #define STAT(x) val[STAT_IDX(x)]
594956b2bdd1SGireesh Nagabhushana #define STAT64(x) (((u64)STAT(x##_HI) << 32) | STAT(x##_LO))
595056b2bdd1SGireesh Nagabhushana
59513dde7c95SVishal Kulkarni if (v4) {
59523dde7c95SVishal Kulkarni t4_tp_mib_read(adap, val, ARRAY_SIZE(val),
59533dde7c95SVishal Kulkarni A_TP_MIB_TCP_OUT_RST, sleep_ok);
59543dde7c95SVishal Kulkarni v4->tcp_out_rsts = STAT(OUT_RST);
59553dde7c95SVishal Kulkarni v4->tcp_in_segs = STAT64(IN_SEG);
59563dde7c95SVishal Kulkarni v4->tcp_out_segs = STAT64(OUT_SEG);
59573dde7c95SVishal Kulkarni v4->tcp_retrans_segs = STAT64(RXT_SEG);
595856b2bdd1SGireesh Nagabhushana }
59593dde7c95SVishal Kulkarni if (v6) {
59603dde7c95SVishal Kulkarni t4_tp_mib_read(adap, val, ARRAY_SIZE(val),
59613dde7c95SVishal Kulkarni A_TP_MIB_TCP_V6OUT_RST, sleep_ok);
59623dde7c95SVishal Kulkarni v6->tcp_out_rsts = STAT(OUT_RST);
59633dde7c95SVishal Kulkarni v6->tcp_in_segs = STAT64(IN_SEG);
59643dde7c95SVishal Kulkarni v6->tcp_out_segs = STAT64(OUT_SEG);
59653dde7c95SVishal Kulkarni v6->tcp_retrans_segs = STAT64(RXT_SEG);
596656b2bdd1SGireesh Nagabhushana }
596756b2bdd1SGireesh Nagabhushana #undef STAT64
596856b2bdd1SGireesh Nagabhushana #undef STAT
596956b2bdd1SGireesh Nagabhushana #undef STAT_IDX
597056b2bdd1SGireesh Nagabhushana }
597156b2bdd1SGireesh Nagabhushana
59723dde7c95SVishal Kulkarni /**
597356b2bdd1SGireesh Nagabhushana * t4_tp_get_err_stats - read TP's error MIB counters
597456b2bdd1SGireesh Nagabhushana * @adap: the adapter
597556b2bdd1SGireesh Nagabhushana * @st: holds the counter values
59763dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
597756b2bdd1SGireesh Nagabhushana *
597856b2bdd1SGireesh Nagabhushana * Returns the values of TP's error counters.
597956b2bdd1SGireesh Nagabhushana */
t4_tp_get_err_stats(struct adapter * adap,struct tp_err_stats * st,bool sleep_ok)59803dde7c95SVishal Kulkarni void t4_tp_get_err_stats(struct adapter *adap, struct tp_err_stats *st,
59813dde7c95SVishal Kulkarni bool sleep_ok)
598256b2bdd1SGireesh Nagabhushana {
59833dde7c95SVishal Kulkarni int nchan = adap->params.arch.nchan;
59843dde7c95SVishal Kulkarni
59853dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->mac_in_errs, nchan, A_TP_MIB_MAC_IN_ERR_0,
59863dde7c95SVishal Kulkarni sleep_ok);
59873dde7c95SVishal Kulkarni
59883dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->hdr_in_errs, nchan, A_TP_MIB_HDR_IN_ERR_0,
59893dde7c95SVishal Kulkarni sleep_ok);
59903dde7c95SVishal Kulkarni
59913dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->tcp_in_errs, nchan, A_TP_MIB_TCP_IN_ERR_0,
59923dde7c95SVishal Kulkarni sleep_ok);
59933dde7c95SVishal Kulkarni
59943dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->tnl_cong_drops, nchan,
59953dde7c95SVishal Kulkarni A_TP_MIB_TNL_CNG_DROP_0, sleep_ok);
59963dde7c95SVishal Kulkarni
59973dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->ofld_chan_drops, nchan,
59983dde7c95SVishal Kulkarni A_TP_MIB_OFD_CHN_DROP_0, sleep_ok);
59993dde7c95SVishal Kulkarni
60003dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->tnl_tx_drops, nchan, A_TP_MIB_TNL_DROP_0,
60013dde7c95SVishal Kulkarni sleep_ok);
60023dde7c95SVishal Kulkarni
60033dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->ofld_vlan_drops, nchan,
60043dde7c95SVishal Kulkarni A_TP_MIB_OFD_VLN_DROP_0, sleep_ok);
60053dde7c95SVishal Kulkarni
60063dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->tcp6_in_errs, nchan,
60073dde7c95SVishal Kulkarni A_TP_MIB_TCP_V6IN_ERR_0, sleep_ok);
60083dde7c95SVishal Kulkarni
60093dde7c95SVishal Kulkarni t4_tp_mib_read(adap, &st->ofld_no_neigh, 2, A_TP_MIB_OFD_ARP_DROP,
60103dde7c95SVishal Kulkarni sleep_ok);
601156b2bdd1SGireesh Nagabhushana }
601256b2bdd1SGireesh Nagabhushana
60133dde7c95SVishal Kulkarni /**
601456b2bdd1SGireesh Nagabhushana * t4_tp_get_cpl_stats - read TP's CPL MIB counters
601556b2bdd1SGireesh Nagabhushana * @adap: the adapter
601656b2bdd1SGireesh Nagabhushana * @st: holds the counter values
60173dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
601856b2bdd1SGireesh Nagabhushana *
601956b2bdd1SGireesh Nagabhushana * Returns the values of TP's CPL counters.
602056b2bdd1SGireesh Nagabhushana */
t4_tp_get_cpl_stats(struct adapter * adap,struct tp_cpl_stats * st,bool sleep_ok)60213dde7c95SVishal Kulkarni void t4_tp_get_cpl_stats(struct adapter *adap, struct tp_cpl_stats *st,
60223dde7c95SVishal Kulkarni bool sleep_ok)
602356b2bdd1SGireesh Nagabhushana {
60243dde7c95SVishal Kulkarni int nchan = adap->params.arch.nchan;
60253dde7c95SVishal Kulkarni
60263dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->req, nchan, A_TP_MIB_CPL_IN_REQ_0, sleep_ok);
60273dde7c95SVishal Kulkarni
60283dde7c95SVishal Kulkarni t4_tp_mib_read(adap, st->rsp, nchan, A_TP_MIB_CPL_OUT_RSP_0, sleep_ok);
602956b2bdd1SGireesh Nagabhushana }
603056b2bdd1SGireesh Nagabhushana
60313dde7c95SVishal Kulkarni /**
603256b2bdd1SGireesh Nagabhushana * t4_tp_get_rdma_stats - read TP's RDMA MIB counters
603356b2bdd1SGireesh Nagabhushana * @adap: the adapter
603456b2bdd1SGireesh Nagabhushana * @st: holds the counter values
603556b2bdd1SGireesh Nagabhushana *
603656b2bdd1SGireesh Nagabhushana * Returns the values of TP's RDMA counters.
603756b2bdd1SGireesh Nagabhushana */
t4_tp_get_rdma_stats(struct adapter * adap,struct tp_rdma_stats * st,bool sleep_ok)60383dde7c95SVishal Kulkarni void t4_tp_get_rdma_stats(struct adapter *adap, struct tp_rdma_stats *st,
60393dde7c95SVishal Kulkarni bool sleep_ok)
604056b2bdd1SGireesh Nagabhushana {
60413dde7c95SVishal Kulkarni t4_tp_mib_read(adap, &st->rqe_dfr_pkt, 2, A_TP_MIB_RQE_DFR_PKT,
60423dde7c95SVishal Kulkarni sleep_ok);
604356b2bdd1SGireesh Nagabhushana }
604456b2bdd1SGireesh Nagabhushana
60453dde7c95SVishal Kulkarni /**
604656b2bdd1SGireesh Nagabhushana * t4_get_fcoe_stats - read TP's FCoE MIB counters for a port
604756b2bdd1SGireesh Nagabhushana * @adap: the adapter
604856b2bdd1SGireesh Nagabhushana * @idx: the port index
604956b2bdd1SGireesh Nagabhushana * @st: holds the counter values
60503dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
605156b2bdd1SGireesh Nagabhushana *
605256b2bdd1SGireesh Nagabhushana * Returns the values of TP's FCoE counters for the selected port.
605356b2bdd1SGireesh Nagabhushana */
t4_get_fcoe_stats(struct adapter * adap,unsigned int idx,struct tp_fcoe_stats * st,bool sleep_ok)60543dde7c95SVishal Kulkarni void t4_get_fcoe_stats(struct adapter *adap, unsigned int idx,
60553dde7c95SVishal Kulkarni struct tp_fcoe_stats *st, bool sleep_ok)
605656b2bdd1SGireesh Nagabhushana {
605756b2bdd1SGireesh Nagabhushana u32 val[2];
605856b2bdd1SGireesh Nagabhushana
60593dde7c95SVishal Kulkarni t4_tp_mib_read(adap, &st->frames_ddp, 1, A_TP_MIB_FCOE_DDP_0 + idx,
60603dde7c95SVishal Kulkarni sleep_ok);
60613dde7c95SVishal Kulkarni
60623dde7c95SVishal Kulkarni t4_tp_mib_read(adap, &st->frames_drop, 1,
60633dde7c95SVishal Kulkarni A_TP_MIB_FCOE_DROP_0 + idx, sleep_ok);
60643dde7c95SVishal Kulkarni
60653dde7c95SVishal Kulkarni t4_tp_mib_read(adap, val, 2, A_TP_MIB_FCOE_BYTE_0_HI + 2 * idx,
60663dde7c95SVishal Kulkarni sleep_ok);
60673dde7c95SVishal Kulkarni
60683dde7c95SVishal Kulkarni st->octets_ddp = ((u64)val[0] << 32) | val[1];
606956b2bdd1SGireesh Nagabhushana }
607056b2bdd1SGireesh Nagabhushana
60713dde7c95SVishal Kulkarni /**
607256b2bdd1SGireesh Nagabhushana * t4_get_usm_stats - read TP's non-TCP DDP MIB counters
607356b2bdd1SGireesh Nagabhushana * @adap: the adapter
607456b2bdd1SGireesh Nagabhushana * @st: holds the counter values
60753dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
607656b2bdd1SGireesh Nagabhushana *
607756b2bdd1SGireesh Nagabhushana * Returns the values of TP's counters for non-TCP directly-placed packets.
607856b2bdd1SGireesh Nagabhushana */
t4_get_usm_stats(struct adapter * adap,struct tp_usm_stats * st,bool sleep_ok)60793dde7c95SVishal Kulkarni void t4_get_usm_stats(struct adapter *adap, struct tp_usm_stats *st,
60803dde7c95SVishal Kulkarni bool sleep_ok)
608156b2bdd1SGireesh Nagabhushana {
608256b2bdd1SGireesh Nagabhushana u32 val[4];
608356b2bdd1SGireesh Nagabhushana
60843dde7c95SVishal Kulkarni t4_tp_mib_read(adap, val, 4, A_TP_MIB_USM_PKTS, sleep_ok);
60853dde7c95SVishal Kulkarni
608656b2bdd1SGireesh Nagabhushana st->frames = val[0];
608756b2bdd1SGireesh Nagabhushana st->drops = val[1];
608856b2bdd1SGireesh Nagabhushana st->octets = ((u64)val[2] << 32) | val[3];
608956b2bdd1SGireesh Nagabhushana }
609056b2bdd1SGireesh Nagabhushana
60913dde7c95SVishal Kulkarni /**
609256b2bdd1SGireesh Nagabhushana * t4_read_mtu_tbl - returns the values in the HW path MTU table
609356b2bdd1SGireesh Nagabhushana * @adap: the adapter
609456b2bdd1SGireesh Nagabhushana * @mtus: where to store the MTU values
609556b2bdd1SGireesh Nagabhushana * @mtu_log: where to store the MTU base-2 log (may be %NULL)
609656b2bdd1SGireesh Nagabhushana *
609756b2bdd1SGireesh Nagabhushana * Reads the HW path MTU table.
609856b2bdd1SGireesh Nagabhushana */
t4_read_mtu_tbl(struct adapter * adap,u16 * mtus,u8 * mtu_log)60993dde7c95SVishal Kulkarni void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log)
610056b2bdd1SGireesh Nagabhushana {
610156b2bdd1SGireesh Nagabhushana u32 v;
610256b2bdd1SGireesh Nagabhushana int i;
610356b2bdd1SGireesh Nagabhushana
610456b2bdd1SGireesh Nagabhushana for (i = 0; i < NMTUS; ++i) {
610556b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_TP_MTU_TABLE,
610656b2bdd1SGireesh Nagabhushana V_MTUINDEX(0xffU) | V_MTUVALUE(i));
610756b2bdd1SGireesh Nagabhushana v = t4_read_reg(adap, A_TP_MTU_TABLE);
610856b2bdd1SGireesh Nagabhushana mtus[i] = G_MTUVALUE(v);
61093dde7c95SVishal Kulkarni if (mtu_log)
611056b2bdd1SGireesh Nagabhushana mtu_log[i] = G_MTUWIDTH(v);
611156b2bdd1SGireesh Nagabhushana }
611256b2bdd1SGireesh Nagabhushana }
611356b2bdd1SGireesh Nagabhushana
61143dde7c95SVishal Kulkarni /**
611556b2bdd1SGireesh Nagabhushana * t4_read_cong_tbl - reads the congestion control table
611656b2bdd1SGireesh Nagabhushana * @adap: the adapter
611756b2bdd1SGireesh Nagabhushana * @incr: where to store the alpha values
611856b2bdd1SGireesh Nagabhushana *
611956b2bdd1SGireesh Nagabhushana * Reads the additive increments programmed into the HW congestion
612056b2bdd1SGireesh Nagabhushana * control table.
612156b2bdd1SGireesh Nagabhushana */
t4_read_cong_tbl(struct adapter * adap,u16 incr[NMTUS][NCCTRL_WIN])61223dde7c95SVishal Kulkarni void t4_read_cong_tbl(struct adapter *adap, u16 incr[NMTUS][NCCTRL_WIN])
612356b2bdd1SGireesh Nagabhushana {
612456b2bdd1SGireesh Nagabhushana unsigned int mtu, w;
612556b2bdd1SGireesh Nagabhushana
612656b2bdd1SGireesh Nagabhushana for (mtu = 0; mtu < NMTUS; ++mtu)
612756b2bdd1SGireesh Nagabhushana for (w = 0; w < NCCTRL_WIN; ++w) {
612856b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_TP_CCTRL_TABLE,
612956b2bdd1SGireesh Nagabhushana V_ROWINDEX(0xffffU) | (mtu << 5) | w);
613056b2bdd1SGireesh Nagabhushana incr[mtu][w] = (u16)t4_read_reg(adap,
613156b2bdd1SGireesh Nagabhushana A_TP_CCTRL_TABLE) & 0x1fff;
613256b2bdd1SGireesh Nagabhushana }
613356b2bdd1SGireesh Nagabhushana }
613456b2bdd1SGireesh Nagabhushana
61353dde7c95SVishal Kulkarni /**
613656b2bdd1SGireesh Nagabhushana * t4_tp_wr_bits_indirect - set/clear bits in an indirect TP register
613756b2bdd1SGireesh Nagabhushana * @adap: the adapter
613856b2bdd1SGireesh Nagabhushana * @addr: the indirect TP register address
613956b2bdd1SGireesh Nagabhushana * @mask: specifies the field within the register to modify
614056b2bdd1SGireesh Nagabhushana * @val: new value for the field
614156b2bdd1SGireesh Nagabhushana *
614256b2bdd1SGireesh Nagabhushana * Sets a field of an indirect TP register to the given value.
614356b2bdd1SGireesh Nagabhushana */
t4_tp_wr_bits_indirect(struct adapter * adap,unsigned int addr,unsigned int mask,unsigned int val)61443dde7c95SVishal Kulkarni void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
614556b2bdd1SGireesh Nagabhushana unsigned int mask, unsigned int val)
614656b2bdd1SGireesh Nagabhushana {
614756b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_TP_PIO_ADDR, addr);
614856b2bdd1SGireesh Nagabhushana val |= t4_read_reg(adap, A_TP_PIO_DATA) & ~mask;
614956b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_TP_PIO_DATA, val);
615056b2bdd1SGireesh Nagabhushana }
615156b2bdd1SGireesh Nagabhushana
61523dde7c95SVishal Kulkarni /**
615356b2bdd1SGireesh Nagabhushana * init_cong_ctrl - initialize congestion control parameters
615456b2bdd1SGireesh Nagabhushana * @a: the alpha values for congestion control
615556b2bdd1SGireesh Nagabhushana * @b: the beta values for congestion control
615656b2bdd1SGireesh Nagabhushana *
615756b2bdd1SGireesh Nagabhushana * Initialize the congestion control parameters.
615856b2bdd1SGireesh Nagabhushana */
init_cong_ctrl(unsigned short * a,unsigned short * b)61593dde7c95SVishal Kulkarni static void init_cong_ctrl(unsigned short *a, unsigned short *b)
616056b2bdd1SGireesh Nagabhushana {
616156b2bdd1SGireesh Nagabhushana a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
616256b2bdd1SGireesh Nagabhushana a[9] = 2;
616356b2bdd1SGireesh Nagabhushana a[10] = 3;
616456b2bdd1SGireesh Nagabhushana a[11] = 4;
616556b2bdd1SGireesh Nagabhushana a[12] = 5;
616656b2bdd1SGireesh Nagabhushana a[13] = 6;
616756b2bdd1SGireesh Nagabhushana a[14] = 7;
616856b2bdd1SGireesh Nagabhushana a[15] = 8;
616956b2bdd1SGireesh Nagabhushana a[16] = 9;
617056b2bdd1SGireesh Nagabhushana a[17] = 10;
617156b2bdd1SGireesh Nagabhushana a[18] = 14;
617256b2bdd1SGireesh Nagabhushana a[19] = 17;
617356b2bdd1SGireesh Nagabhushana a[20] = 21;
617456b2bdd1SGireesh Nagabhushana a[21] = 25;
617556b2bdd1SGireesh Nagabhushana a[22] = 30;
617656b2bdd1SGireesh Nagabhushana a[23] = 35;
617756b2bdd1SGireesh Nagabhushana a[24] = 45;
617856b2bdd1SGireesh Nagabhushana a[25] = 60;
617956b2bdd1SGireesh Nagabhushana a[26] = 80;
618056b2bdd1SGireesh Nagabhushana a[27] = 100;
618156b2bdd1SGireesh Nagabhushana a[28] = 200;
618256b2bdd1SGireesh Nagabhushana a[29] = 300;
618356b2bdd1SGireesh Nagabhushana a[30] = 400;
618456b2bdd1SGireesh Nagabhushana a[31] = 500;
618556b2bdd1SGireesh Nagabhushana
618656b2bdd1SGireesh Nagabhushana b[0] = b[1] = b[2] = b[3] = b[4] = b[5] = b[6] = b[7] = b[8] = 0;
618756b2bdd1SGireesh Nagabhushana b[9] = b[10] = 1;
618856b2bdd1SGireesh Nagabhushana b[11] = b[12] = 2;
618956b2bdd1SGireesh Nagabhushana b[13] = b[14] = b[15] = b[16] = 3;
619056b2bdd1SGireesh Nagabhushana b[17] = b[18] = b[19] = b[20] = b[21] = 4;
619156b2bdd1SGireesh Nagabhushana b[22] = b[23] = b[24] = b[25] = b[26] = b[27] = 5;
619256b2bdd1SGireesh Nagabhushana b[28] = b[29] = 6;
619356b2bdd1SGireesh Nagabhushana b[30] = b[31] = 7;
619456b2bdd1SGireesh Nagabhushana }
619556b2bdd1SGireesh Nagabhushana
619656b2bdd1SGireesh Nagabhushana /* The minimum additive increment value for the congestion control table */
619756b2bdd1SGireesh Nagabhushana #define CC_MIN_INCR 2U
619856b2bdd1SGireesh Nagabhushana
61993dde7c95SVishal Kulkarni /**
620056b2bdd1SGireesh Nagabhushana * t4_load_mtus - write the MTU and congestion control HW tables
620156b2bdd1SGireesh Nagabhushana * @adap: the adapter
620256b2bdd1SGireesh Nagabhushana * @mtus: the values for the MTU table
620356b2bdd1SGireesh Nagabhushana * @alpha: the values for the congestion control alpha parameter
620456b2bdd1SGireesh Nagabhushana * @beta: the values for the congestion control beta parameter
620556b2bdd1SGireesh Nagabhushana *
620656b2bdd1SGireesh Nagabhushana * Write the HW MTU table with the supplied MTUs and the high-speed
620756b2bdd1SGireesh Nagabhushana * congestion control table with the supplied alpha, beta, and MTUs.
620856b2bdd1SGireesh Nagabhushana * We write the two tables together because the additive increments
620956b2bdd1SGireesh Nagabhushana * depend on the MTUs.
621056b2bdd1SGireesh Nagabhushana */
t4_load_mtus(struct adapter * adap,const unsigned short * mtus,const unsigned short * alpha,const unsigned short * beta)62113dde7c95SVishal Kulkarni void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
621256b2bdd1SGireesh Nagabhushana const unsigned short *alpha, const unsigned short *beta)
621356b2bdd1SGireesh Nagabhushana {
621456b2bdd1SGireesh Nagabhushana static const unsigned int avg_pkts[NCCTRL_WIN] = {
621556b2bdd1SGireesh Nagabhushana 2, 6, 10, 14, 20, 28, 40, 56, 80, 112, 160, 224, 320, 448, 640,
621656b2bdd1SGireesh Nagabhushana 896, 1281, 1792, 2560, 3584, 5120, 7168, 10240, 14336, 20480,
621756b2bdd1SGireesh Nagabhushana 28672, 40960, 57344, 81920, 114688, 163840, 229376
621856b2bdd1SGireesh Nagabhushana };
621956b2bdd1SGireesh Nagabhushana
622056b2bdd1SGireesh Nagabhushana unsigned int i, w;
622156b2bdd1SGireesh Nagabhushana
622256b2bdd1SGireesh Nagabhushana for (i = 0; i < NMTUS; ++i) {
622356b2bdd1SGireesh Nagabhushana unsigned int mtu = mtus[i];
622456b2bdd1SGireesh Nagabhushana unsigned int log2 = fls(mtu);
622556b2bdd1SGireesh Nagabhushana
622656b2bdd1SGireesh Nagabhushana if (!(mtu & ((1 << log2) >> 2))) /* round */
622756b2bdd1SGireesh Nagabhushana log2--;
622856b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_TP_MTU_TABLE, V_MTUINDEX(i) |
622956b2bdd1SGireesh Nagabhushana V_MTUWIDTH(log2) | V_MTUVALUE(mtu));
623056b2bdd1SGireesh Nagabhushana
623156b2bdd1SGireesh Nagabhushana for (w = 0; w < NCCTRL_WIN; ++w) {
623256b2bdd1SGireesh Nagabhushana unsigned int inc;
623356b2bdd1SGireesh Nagabhushana
623456b2bdd1SGireesh Nagabhushana inc = max(((mtu - 40) * alpha[w]) / avg_pkts[w],
623556b2bdd1SGireesh Nagabhushana CC_MIN_INCR);
623656b2bdd1SGireesh Nagabhushana
623756b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_TP_CCTRL_TABLE, (i << 21) |
623856b2bdd1SGireesh Nagabhushana (w << 16) | (beta[w] << 13) | inc);
623956b2bdd1SGireesh Nagabhushana }
624056b2bdd1SGireesh Nagabhushana }
624156b2bdd1SGireesh Nagabhushana }
624256b2bdd1SGireesh Nagabhushana
624356b2bdd1SGireesh Nagabhushana /*
624456b2bdd1SGireesh Nagabhushana * Calculates a rate in bytes/s given the number of 256-byte units per 4K core
624556b2bdd1SGireesh Nagabhushana * clocks. The formula is
624656b2bdd1SGireesh Nagabhushana *
624756b2bdd1SGireesh Nagabhushana * bytes/s = bytes256 * 256 * ClkFreq / 4096
624856b2bdd1SGireesh Nagabhushana *
624956b2bdd1SGireesh Nagabhushana * which is equivalent to
625056b2bdd1SGireesh Nagabhushana *
625156b2bdd1SGireesh Nagabhushana * bytes/s = 62.5 * bytes256 * ClkFreq_ms
625256b2bdd1SGireesh Nagabhushana */
chan_rate(struct adapter * adap,unsigned int bytes256)62533dde7c95SVishal Kulkarni static u64 chan_rate(struct adapter *adap, unsigned int bytes256)
625456b2bdd1SGireesh Nagabhushana {
625556b2bdd1SGireesh Nagabhushana u64 v = bytes256 * adap->params.vpd.cclk;
625656b2bdd1SGireesh Nagabhushana
62573dde7c95SVishal Kulkarni return v * 62 + v / 2;
625856b2bdd1SGireesh Nagabhushana }
625956b2bdd1SGireesh Nagabhushana
62603dde7c95SVishal Kulkarni /**
626156b2bdd1SGireesh Nagabhushana * t4_get_chan_txrate - get the current per channel Tx rates
626256b2bdd1SGireesh Nagabhushana * @adap: the adapter
626356b2bdd1SGireesh Nagabhushana * @nic_rate: rates for NIC traffic
626456b2bdd1SGireesh Nagabhushana * @ofld_rate: rates for offloaded traffic
626556b2bdd1SGireesh Nagabhushana *
626656b2bdd1SGireesh Nagabhushana * Return the current Tx rates in bytes/s for NIC and offloaded traffic
626756b2bdd1SGireesh Nagabhushana * for each channel.
626856b2bdd1SGireesh Nagabhushana */
t4_get_chan_txrate(struct adapter * adap,u64 * nic_rate,u64 * ofld_rate)62693dde7c95SVishal Kulkarni void t4_get_chan_txrate(struct adapter *adap, u64 *nic_rate, u64 *ofld_rate)
627056b2bdd1SGireesh Nagabhushana {
627156b2bdd1SGireesh Nagabhushana u32 v;
627256b2bdd1SGireesh Nagabhushana
627356b2bdd1SGireesh Nagabhushana v = t4_read_reg(adap, A_TP_TX_TRATE);
627456b2bdd1SGireesh Nagabhushana nic_rate[0] = chan_rate(adap, G_TNLRATE0(v));
627556b2bdd1SGireesh Nagabhushana nic_rate[1] = chan_rate(adap, G_TNLRATE1(v));
62763dde7c95SVishal Kulkarni if (adap->params.arch.nchan == NCHAN) {
627756b2bdd1SGireesh Nagabhushana nic_rate[2] = chan_rate(adap, G_TNLRATE2(v));
627856b2bdd1SGireesh Nagabhushana nic_rate[3] = chan_rate(adap, G_TNLRATE3(v));
62793dde7c95SVishal Kulkarni }
628056b2bdd1SGireesh Nagabhushana
628156b2bdd1SGireesh Nagabhushana v = t4_read_reg(adap, A_TP_TX_ORATE);
628256b2bdd1SGireesh Nagabhushana ofld_rate[0] = chan_rate(adap, G_OFDRATE0(v));
628356b2bdd1SGireesh Nagabhushana ofld_rate[1] = chan_rate(adap, G_OFDRATE1(v));
62843dde7c95SVishal Kulkarni if (adap->params.arch.nchan == NCHAN) {
628556b2bdd1SGireesh Nagabhushana ofld_rate[2] = chan_rate(adap, G_OFDRATE2(v));
628656b2bdd1SGireesh Nagabhushana ofld_rate[3] = chan_rate(adap, G_OFDRATE3(v));
628756b2bdd1SGireesh Nagabhushana }
62883dde7c95SVishal Kulkarni }
628956b2bdd1SGireesh Nagabhushana
62903dde7c95SVishal Kulkarni /**
629156b2bdd1SGireesh Nagabhushana * t4_set_trace_filter - configure one of the tracing filters
629256b2bdd1SGireesh Nagabhushana * @adap: the adapter
629356b2bdd1SGireesh Nagabhushana * @tp: the desired trace filter parameters
629456b2bdd1SGireesh Nagabhushana * @idx: which filter to configure
629556b2bdd1SGireesh Nagabhushana * @enable: whether to enable or disable the filter
629656b2bdd1SGireesh Nagabhushana *
629756b2bdd1SGireesh Nagabhushana * Configures one of the tracing filters available in HW. If @enable is
62983dde7c95SVishal Kulkarni * %0 @tp is not examined and may be %NULL. The user is responsible to
62993dde7c95SVishal Kulkarni * set the single/multiple trace mode by writing to A_MPS_TRC_CFG register
63003dde7c95SVishal Kulkarni * by using "cxgbtool iface reg reg_addr=val" command. See t4_sniffer/
63013dde7c95SVishal Kulkarni * docs/readme.txt for a complete description of how to setup traceing on
63023dde7c95SVishal Kulkarni * T4.
630356b2bdd1SGireesh Nagabhushana */
t4_set_trace_filter(struct adapter * adap,const struct trace_params * tp,int idx,int enable)63043dde7c95SVishal Kulkarni int t4_set_trace_filter(struct adapter *adap, const struct trace_params *tp, int idx,
63053dde7c95SVishal Kulkarni int enable)
630656b2bdd1SGireesh Nagabhushana {
630756b2bdd1SGireesh Nagabhushana int i, ofst = idx * 4;
630856b2bdd1SGireesh Nagabhushana u32 data_reg, mask_reg, cfg;
630956b2bdd1SGireesh Nagabhushana
631056b2bdd1SGireesh Nagabhushana if (!enable) {
631156b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + ofst, 0);
6312de483253SVishal Kulkarni return 0;
6313de483253SVishal Kulkarni }
6314de483253SVishal Kulkarni
6315de483253SVishal Kulkarni /*
6316de483253SVishal Kulkarni * TODO - After T4 data book is updated, specify the exact
6317de483253SVishal Kulkarni * section below.
6318de483253SVishal Kulkarni *
6319de483253SVishal Kulkarni * See T4 data book - MPS section for a complete description
6320de483253SVishal Kulkarni * of the below if..else handling of A_MPS_TRC_CFG register
6321de483253SVishal Kulkarni * value.
6322de483253SVishal Kulkarni */
6323de483253SVishal Kulkarni cfg = t4_read_reg(adap, A_MPS_TRC_CFG);
6324de483253SVishal Kulkarni if (cfg & F_TRCMULTIFILTER) {
6325de483253SVishal Kulkarni /*
6326de483253SVishal Kulkarni * If multiple tracers are enabled, then maximum
6327de483253SVishal Kulkarni * capture size is 2.5KB (FIFO size of a single channel)
6328de483253SVishal Kulkarni * minus 2 flits for CPL_TRACE_PKT header.
6329de483253SVishal Kulkarni */
6330de483253SVishal Kulkarni if (tp->snap_len > ((10 * 1024 / 4) - (2 * 8)))
6331de483253SVishal Kulkarni return -EINVAL;
6332de483253SVishal Kulkarni }
6333de483253SVishal Kulkarni else {
6334de483253SVishal Kulkarni /*
6335de483253SVishal Kulkarni * If multiple tracers are disabled, to avoid deadlocks
6336de483253SVishal Kulkarni * maximum packet capture size of 9600 bytes is recommended.
6337de483253SVishal Kulkarni * Also in this mode, only trace0 can be enabled and running.
6338de483253SVishal Kulkarni */
6339de483253SVishal Kulkarni if (tp->snap_len > 9600 || idx)
6340de483253SVishal Kulkarni return -EINVAL;
634156b2bdd1SGireesh Nagabhushana }
634256b2bdd1SGireesh Nagabhushana
63433dde7c95SVishal Kulkarni if (tp->port > (is_t4(adap->params.chip) ? 11 : 19) || tp->invert > 1 ||
63443dde7c95SVishal Kulkarni tp->skip_len > M_TFLENGTH || tp->skip_ofst > M_TFOFFSET ||
63453dde7c95SVishal Kulkarni tp->min_len > M_TFMINPKTSIZE)
6346de483253SVishal Kulkarni return -EINVAL;
634756b2bdd1SGireesh Nagabhushana
634856b2bdd1SGireesh Nagabhushana /* stop the tracer we'll be changing */
634956b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + ofst, 0);
635056b2bdd1SGireesh Nagabhushana
635156b2bdd1SGireesh Nagabhushana idx *= (A_MPS_TRC_FILTER1_MATCH - A_MPS_TRC_FILTER0_MATCH);
635256b2bdd1SGireesh Nagabhushana data_reg = A_MPS_TRC_FILTER0_MATCH + idx;
635356b2bdd1SGireesh Nagabhushana mask_reg = A_MPS_TRC_FILTER0_DONT_CARE + idx;
635456b2bdd1SGireesh Nagabhushana
635556b2bdd1SGireesh Nagabhushana for (i = 0; i < TRACE_LEN / 4; i++, data_reg += 4, mask_reg += 4) {
635656b2bdd1SGireesh Nagabhushana t4_write_reg(adap, data_reg, tp->data[i]);
635756b2bdd1SGireesh Nagabhushana t4_write_reg(adap, mask_reg, ~tp->mask[i]);
635856b2bdd1SGireesh Nagabhushana }
635956b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_B + ofst,
63603dde7c95SVishal Kulkarni V_TFCAPTUREMAX(tp->snap_len) |
63613dde7c95SVishal Kulkarni V_TFMINPKTSIZE(tp->min_len));
636256b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + ofst,
636356b2bdd1SGireesh Nagabhushana V_TFOFFSET(tp->skip_ofst) | V_TFLENGTH(tp->skip_len) |
63643dde7c95SVishal Kulkarni (is_t4(adap->params.chip) ?
6365de483253SVishal Kulkarni V_TFPORT(tp->port) | F_TFEN | V_TFINVERTMATCH(tp->invert) :
6366de483253SVishal Kulkarni V_T5_TFPORT(tp->port) | F_T5_TFEN |
63673dde7c95SVishal Kulkarni V_T5_TFINVERTMATCH(tp->invert)));
636856b2bdd1SGireesh Nagabhushana
63693dde7c95SVishal Kulkarni return 0;
637056b2bdd1SGireesh Nagabhushana }
637156b2bdd1SGireesh Nagabhushana
63723dde7c95SVishal Kulkarni /**
637356b2bdd1SGireesh Nagabhushana * t4_get_trace_filter - query one of the tracing filters
637456b2bdd1SGireesh Nagabhushana * @adap: the adapter
637556b2bdd1SGireesh Nagabhushana * @tp: the current trace filter parameters
637656b2bdd1SGireesh Nagabhushana * @idx: which trace filter to query
637756b2bdd1SGireesh Nagabhushana * @enabled: non-zero if the filter is enabled
637856b2bdd1SGireesh Nagabhushana *
637956b2bdd1SGireesh Nagabhushana * Returns the current settings of one of the HW tracing filters.
638056b2bdd1SGireesh Nagabhushana */
t4_get_trace_filter(struct adapter * adap,struct trace_params * tp,int idx,int * enabled)63813dde7c95SVishal Kulkarni void t4_get_trace_filter(struct adapter *adap, struct trace_params *tp, int idx,
638256b2bdd1SGireesh Nagabhushana int *enabled)
638356b2bdd1SGireesh Nagabhushana {
638456b2bdd1SGireesh Nagabhushana u32 ctla, ctlb;
638556b2bdd1SGireesh Nagabhushana int i, ofst = idx * 4;
638656b2bdd1SGireesh Nagabhushana u32 data_reg, mask_reg;
638756b2bdd1SGireesh Nagabhushana
638856b2bdd1SGireesh Nagabhushana ctla = t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_A + ofst);
638956b2bdd1SGireesh Nagabhushana ctlb = t4_read_reg(adap, A_MPS_TRC_FILTER_MATCH_CTL_B + ofst);
639056b2bdd1SGireesh Nagabhushana
6391de483253SVishal Kulkarni if (is_t4(adap->params.chip)) {
639256b2bdd1SGireesh Nagabhushana *enabled = !!(ctla & F_TFEN);
6393de483253SVishal Kulkarni tp->port = G_TFPORT(ctla);
63943dde7c95SVishal Kulkarni tp->invert = !!(ctla & F_TFINVERTMATCH);
6395de483253SVishal Kulkarni } else {
6396de483253SVishal Kulkarni *enabled = !!(ctla & F_T5_TFEN);
6397de483253SVishal Kulkarni tp->port = G_T5_TFPORT(ctla);
63983dde7c95SVishal Kulkarni tp->invert = !!(ctla & F_T5_TFINVERTMATCH);
6399de483253SVishal Kulkarni }
640056b2bdd1SGireesh Nagabhushana tp->snap_len = G_TFCAPTUREMAX(ctlb);
640156b2bdd1SGireesh Nagabhushana tp->min_len = G_TFMINPKTSIZE(ctlb);
640256b2bdd1SGireesh Nagabhushana tp->skip_ofst = G_TFOFFSET(ctla);
640356b2bdd1SGireesh Nagabhushana tp->skip_len = G_TFLENGTH(ctla);
640456b2bdd1SGireesh Nagabhushana
640556b2bdd1SGireesh Nagabhushana ofst = (A_MPS_TRC_FILTER1_MATCH - A_MPS_TRC_FILTER0_MATCH) * idx;
640656b2bdd1SGireesh Nagabhushana data_reg = A_MPS_TRC_FILTER0_MATCH + ofst;
640756b2bdd1SGireesh Nagabhushana mask_reg = A_MPS_TRC_FILTER0_DONT_CARE + ofst;
640856b2bdd1SGireesh Nagabhushana
640956b2bdd1SGireesh Nagabhushana for (i = 0; i < TRACE_LEN / 4; i++, data_reg += 4, mask_reg += 4) {
641056b2bdd1SGireesh Nagabhushana tp->mask[i] = ~t4_read_reg(adap, mask_reg);
641156b2bdd1SGireesh Nagabhushana tp->data[i] = t4_read_reg(adap, data_reg) & tp->mask[i];
641256b2bdd1SGireesh Nagabhushana }
641356b2bdd1SGireesh Nagabhushana }
641456b2bdd1SGireesh Nagabhushana
64153dde7c95SVishal Kulkarni /**
64163dde7c95SVishal Kulkarni * t4_read_tcb - read a hardware TCP Control Block structure
64173dde7c95SVishal Kulkarni * @adap: the adapter
64183dde7c95SVishal Kulkarni * @win: PCI-E Memory Window to use
64193dde7c95SVishal Kulkarni * @tid: the TCB ID
64203dde7c95SVishal Kulkarni * @tcb: the buffer to return the TCB in
64213dde7c95SVishal Kulkarni *
64223dde7c95SVishal Kulkarni * Reads the indicated hardware TCP Control Block and returns it in
64233dde7c95SVishal Kulkarni * the supplied buffer. Returns 0 on success.
64243dde7c95SVishal Kulkarni */
t4_read_tcb(struct adapter * adap,int win,int tid,u32 tcb[TCB_SIZE/4])64253dde7c95SVishal Kulkarni int t4_read_tcb(struct adapter *adap, int win, int tid, u32 tcb[TCB_SIZE/4])
64263dde7c95SVishal Kulkarni {
64273dde7c95SVishal Kulkarni u32 tcb_base = t4_read_reg(adap, A_TP_CMM_TCB_BASE);
64283dde7c95SVishal Kulkarni u32 tcb_addr = tcb_base + tid * TCB_SIZE;
64293dde7c95SVishal Kulkarni __be32 raw_tcb[TCB_SIZE/4];
64303dde7c95SVishal Kulkarni int ret, word;
64313dde7c95SVishal Kulkarni
64323dde7c95SVishal Kulkarni ret = t4_memory_rw_addr(adap, win,
64333dde7c95SVishal Kulkarni tcb_addr, sizeof raw_tcb, raw_tcb,
64343dde7c95SVishal Kulkarni T4_MEMORY_READ);
64353dde7c95SVishal Kulkarni if (ret)
64363dde7c95SVishal Kulkarni return ret;
64373dde7c95SVishal Kulkarni
64383dde7c95SVishal Kulkarni for (word = 0; word < 32; word++)
64393dde7c95SVishal Kulkarni tcb[word] = be32_to_cpu(raw_tcb[word]);
64403dde7c95SVishal Kulkarni return 0;
64413dde7c95SVishal Kulkarni }
64423dde7c95SVishal Kulkarni
64433dde7c95SVishal Kulkarni /**
644456b2bdd1SGireesh Nagabhushana * t4_pmtx_get_stats - returns the HW stats from PMTX
644556b2bdd1SGireesh Nagabhushana * @adap: the adapter
644656b2bdd1SGireesh Nagabhushana * @cnt: where to store the count statistics
644756b2bdd1SGireesh Nagabhushana * @cycles: where to store the cycle statistics
644856b2bdd1SGireesh Nagabhushana *
644956b2bdd1SGireesh Nagabhushana * Returns performance statistics from PMTX.
645056b2bdd1SGireesh Nagabhushana */
t4_pmtx_get_stats(struct adapter * adap,u32 cnt[],u64 cycles[])64513dde7c95SVishal Kulkarni void t4_pmtx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
645256b2bdd1SGireesh Nagabhushana {
645356b2bdd1SGireesh Nagabhushana int i;
6454de483253SVishal Kulkarni u32 data[2];
645556b2bdd1SGireesh Nagabhushana
64563dde7c95SVishal Kulkarni for (i = 0; i < adap->params.arch.pm_stats_cnt; i++) {
645756b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_PM_TX_STAT_CONFIG, i + 1);
645856b2bdd1SGireesh Nagabhushana cnt[i] = t4_read_reg(adap, A_PM_TX_STAT_COUNT);
64593dde7c95SVishal Kulkarni if (is_t4(adap->params.chip)) {
646056b2bdd1SGireesh Nagabhushana cycles[i] = t4_read_reg64(adap, A_PM_TX_STAT_LSB);
64613dde7c95SVishal Kulkarni } else {
6462de483253SVishal Kulkarni t4_read_indirect(adap, A_PM_TX_DBG_CTRL,
6463de483253SVishal Kulkarni A_PM_TX_DBG_DATA, data, 2,
6464de483253SVishal Kulkarni A_PM_TX_DBG_STAT_MSB);
6465de483253SVishal Kulkarni cycles[i] = (((u64)data[0] << 32) | data[1]);
6466de483253SVishal Kulkarni }
646756b2bdd1SGireesh Nagabhushana }
646856b2bdd1SGireesh Nagabhushana }
646956b2bdd1SGireesh Nagabhushana
64703dde7c95SVishal Kulkarni /**
647156b2bdd1SGireesh Nagabhushana * t4_pmrx_get_stats - returns the HW stats from PMRX
647256b2bdd1SGireesh Nagabhushana * @adap: the adapter
647356b2bdd1SGireesh Nagabhushana * @cnt: where to store the count statistics
647456b2bdd1SGireesh Nagabhushana * @cycles: where to store the cycle statistics
647556b2bdd1SGireesh Nagabhushana *
647656b2bdd1SGireesh Nagabhushana * Returns performance statistics from PMRX.
647756b2bdd1SGireesh Nagabhushana */
t4_pmrx_get_stats(struct adapter * adap,u32 cnt[],u64 cycles[])64783dde7c95SVishal Kulkarni void t4_pmrx_get_stats(struct adapter *adap, u32 cnt[], u64 cycles[])
647956b2bdd1SGireesh Nagabhushana {
648056b2bdd1SGireesh Nagabhushana int i;
6481de483253SVishal Kulkarni u32 data[2];
648256b2bdd1SGireesh Nagabhushana
64833dde7c95SVishal Kulkarni for (i = 0; i < adap->params.arch.pm_stats_cnt; i++) {
648456b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_PM_RX_STAT_CONFIG, i + 1);
648556b2bdd1SGireesh Nagabhushana cnt[i] = t4_read_reg(adap, A_PM_RX_STAT_COUNT);
64863dde7c95SVishal Kulkarni if (is_t4(adap->params.chip)) {
648756b2bdd1SGireesh Nagabhushana cycles[i] = t4_read_reg64(adap, A_PM_RX_STAT_LSB);
64883dde7c95SVishal Kulkarni } else {
6489de483253SVishal Kulkarni t4_read_indirect(adap, A_PM_RX_DBG_CTRL,
6490de483253SVishal Kulkarni A_PM_RX_DBG_DATA, data, 2,
6491de483253SVishal Kulkarni A_PM_RX_DBG_STAT_MSB);
6492de483253SVishal Kulkarni cycles[i] = (((u64)data[0] << 32) | data[1]);
6493de483253SVishal Kulkarni }
649456b2bdd1SGireesh Nagabhushana }
649556b2bdd1SGireesh Nagabhushana }
649656b2bdd1SGireesh Nagabhushana
64973dde7c95SVishal Kulkarni /**
64987e6ad469SVishal Kulkarni * compute_mps_bg_map - compute the MPS Buffer Group Map for a Port
64993dde7c95SVishal Kulkarni * @adapter: the adapter
65003dde7c95SVishal Kulkarni * @pidx: the port index
650156b2bdd1SGireesh Nagabhushana *
65027e6ad469SVishal Kulkarni * Compuytes and returns a bitmap indicating which MPS buffer groups are
65037e6ad469SVishal Kulkarni * associated with the given Port. Bit i is set if buffer group i is
65047e6ad469SVishal Kulkarni * used by the Port.
650556b2bdd1SGireesh Nagabhushana */
compute_mps_bg_map(struct adapter * adapter,int pidx)65067e6ad469SVishal Kulkarni static inline unsigned int compute_mps_bg_map(struct adapter *adapter,
65077e6ad469SVishal Kulkarni int pidx)
650856b2bdd1SGireesh Nagabhushana {
65097e6ad469SVishal Kulkarni unsigned int chip_version, nports;
651056b2bdd1SGireesh Nagabhushana
65117e6ad469SVishal Kulkarni chip_version = CHELSIO_CHIP_VERSION(adapter->params.chip);
65127e6ad469SVishal Kulkarni nports = 1 << G_NUMPORTS(t4_read_reg(adapter, A_MPS_CMN_CTL));
651356b2bdd1SGireesh Nagabhushana
65143dde7c95SVishal Kulkarni switch (chip_version) {
65153dde7c95SVishal Kulkarni case CHELSIO_T4:
65163dde7c95SVishal Kulkarni case CHELSIO_T5:
65173dde7c95SVishal Kulkarni switch (nports) {
65183dde7c95SVishal Kulkarni case 1: return 0xf;
65193dde7c95SVishal Kulkarni case 2: return 3 << (2 * pidx);
65203dde7c95SVishal Kulkarni case 4: return 1 << pidx;
65213dde7c95SVishal Kulkarni }
65223dde7c95SVishal Kulkarni break;
65233dde7c95SVishal Kulkarni
65243dde7c95SVishal Kulkarni case CHELSIO_T6:
65253dde7c95SVishal Kulkarni switch (nports) {
65263dde7c95SVishal Kulkarni case 2: return 1 << (2 * pidx);
65273dde7c95SVishal Kulkarni }
65283dde7c95SVishal Kulkarni break;
65293dde7c95SVishal Kulkarni }
65303dde7c95SVishal Kulkarni
65313dde7c95SVishal Kulkarni CH_ERR(adapter, "Need MPS Buffer Group Map for Chip %0x, Nports %d\n",
65323dde7c95SVishal Kulkarni chip_version, nports);
65337e6ad469SVishal Kulkarni
65343dde7c95SVishal Kulkarni return 0;
65353dde7c95SVishal Kulkarni }
65363dde7c95SVishal Kulkarni
65373dde7c95SVishal Kulkarni /**
65387e6ad469SVishal Kulkarni * t4_get_mps_bg_map - return the buffer groups associated with a port
65397e6ad469SVishal Kulkarni * @adapter: the adapter
65407e6ad469SVishal Kulkarni * @pidx: the port index
65417e6ad469SVishal Kulkarni *
65427e6ad469SVishal Kulkarni * Returns a bitmap indicating which MPS buffer groups are associated
65437e6ad469SVishal Kulkarni * with the given Port. Bit i is set if buffer group i is used by the
65447e6ad469SVishal Kulkarni * Port.
65457e6ad469SVishal Kulkarni */
t4_get_mps_bg_map(struct adapter * adapter,int pidx)65467e6ad469SVishal Kulkarni unsigned int t4_get_mps_bg_map(struct adapter *adapter, int pidx)
65477e6ad469SVishal Kulkarni {
65487e6ad469SVishal Kulkarni u8 *mps_bg_map;
65497e6ad469SVishal Kulkarni unsigned int nports;
65507e6ad469SVishal Kulkarni
65517e6ad469SVishal Kulkarni nports = 1 << G_NUMPORTS(t4_read_reg(adapter, A_MPS_CMN_CTL));
65527e6ad469SVishal Kulkarni if (pidx >= nports) {
65537e6ad469SVishal Kulkarni CH_WARN(adapter, "MPS Port Index %d >= Nports %d\n", pidx, nports);
65547e6ad469SVishal Kulkarni return 0;
65557e6ad469SVishal Kulkarni }
65567e6ad469SVishal Kulkarni
65577e6ad469SVishal Kulkarni /* If we've already retrieved/computed this, just return the result.
65587e6ad469SVishal Kulkarni */
65597e6ad469SVishal Kulkarni mps_bg_map = adapter->params.mps_bg_map;
65607e6ad469SVishal Kulkarni if (mps_bg_map[pidx])
65617e6ad469SVishal Kulkarni return mps_bg_map[pidx];
65627e6ad469SVishal Kulkarni
65637e6ad469SVishal Kulkarni /* Newer Firmware can tell us what the MPS Buffer Group Map is.
65647e6ad469SVishal Kulkarni * If we're talking to such Firmware, let it tell us. If the new
65657e6ad469SVishal Kulkarni * API isn't supported, revert back to old hardcoded way. The value
65667e6ad469SVishal Kulkarni * obtained from Firmware is encoded in below format:
65677e6ad469SVishal Kulkarni *
65687e6ad469SVishal Kulkarni * val = (( MPSBGMAP[Port 3] << 24 ) |
65697e6ad469SVishal Kulkarni * ( MPSBGMAP[Port 2] << 16 ) |
65707e6ad469SVishal Kulkarni * ( MPSBGMAP[Port 1] << 8 ) |
65717e6ad469SVishal Kulkarni * ( MPSBGMAP[Port 0] << 0 ))
65727e6ad469SVishal Kulkarni */
65737e6ad469SVishal Kulkarni if (adapter->flags & FW_OK) {
65747e6ad469SVishal Kulkarni u32 param, val;
65757e6ad469SVishal Kulkarni int ret;
65767e6ad469SVishal Kulkarni
65777e6ad469SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
65787e6ad469SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_MPSBGMAP));
65797e6ad469SVishal Kulkarni ret = t4_query_params_ns(adapter, adapter->mbox, adapter->pf,
65807e6ad469SVishal Kulkarni 0, 1, ¶m, &val);
65817e6ad469SVishal Kulkarni if (!ret) {
65827e6ad469SVishal Kulkarni int p;
65837e6ad469SVishal Kulkarni
65847e6ad469SVishal Kulkarni /* Store the BG Map for all of the Ports in order to
65857e6ad469SVishal Kulkarni * avoid more calls to the Firmware in the future.
65867e6ad469SVishal Kulkarni */
65877e6ad469SVishal Kulkarni for (p = 0; p < MAX_NPORTS; p++, val >>= 8)
65887e6ad469SVishal Kulkarni mps_bg_map[p] = val & 0xff;
65897e6ad469SVishal Kulkarni
65907e6ad469SVishal Kulkarni return mps_bg_map[pidx];
65917e6ad469SVishal Kulkarni }
65927e6ad469SVishal Kulkarni }
65937e6ad469SVishal Kulkarni
65947e6ad469SVishal Kulkarni /* Either we're not talking to the Firmware or we're dealing with
65957e6ad469SVishal Kulkarni * older Firmware which doesn't support the new API to get the MPS
65967e6ad469SVishal Kulkarni * Buffer Group Map. Fall back to computing it ourselves.
65977e6ad469SVishal Kulkarni */
65987e6ad469SVishal Kulkarni mps_bg_map[pidx] = compute_mps_bg_map(adapter, pidx);
65997e6ad469SVishal Kulkarni return mps_bg_map[pidx];
66007e6ad469SVishal Kulkarni }
66017e6ad469SVishal Kulkarni
66027e6ad469SVishal Kulkarni /**
66033dde7c95SVishal Kulkarni * t4_get_tp_e2c_map - return the E2C channel map associated with a port
66043dde7c95SVishal Kulkarni * @adapter: the adapter
66053dde7c95SVishal Kulkarni * @pidx: the port index
66063dde7c95SVishal Kulkarni */
t4_get_tp_e2c_map(struct adapter * adapter,int pidx)66073dde7c95SVishal Kulkarni unsigned int t4_get_tp_e2c_map(struct adapter *adapter, int pidx)
66083dde7c95SVishal Kulkarni {
66093dde7c95SVishal Kulkarni unsigned int nports = 1 << G_NUMPORTS(t4_read_reg(adapter, A_MPS_CMN_CTL));
66103dde7c95SVishal Kulkarni u32 param, val = 0;
66113dde7c95SVishal Kulkarni int ret;
66123dde7c95SVishal Kulkarni
66133dde7c95SVishal Kulkarni if (pidx >= nports) {
66143dde7c95SVishal Kulkarni CH_WARN(adapter, "TP E2C Channel Port Index %d >= Nports %d\n", pidx, nports);
66153dde7c95SVishal Kulkarni return 0;
66163dde7c95SVishal Kulkarni }
66173dde7c95SVishal Kulkarni
66183dde7c95SVishal Kulkarni /* FW version >= 1.16.44.0 can determine E2C channel map using
66193dde7c95SVishal Kulkarni * FW_PARAMS_PARAM_DEV_TPCHMAP API.
66203dde7c95SVishal Kulkarni */
66213dde7c95SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
66223dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_TPCHMAP));
66233dde7c95SVishal Kulkarni ret = t4_query_params_ns(adapter, adapter->mbox, adapter->pf,
66243dde7c95SVishal Kulkarni 0, 1, ¶m, &val);
66253dde7c95SVishal Kulkarni if (!ret)
66263dde7c95SVishal Kulkarni return (val >> (8*pidx)) & 0xff;
66273dde7c95SVishal Kulkarni
66283dde7c95SVishal Kulkarni return 0;
66293dde7c95SVishal Kulkarni }
66303dde7c95SVishal Kulkarni
66313dde7c95SVishal Kulkarni /**
66323dde7c95SVishal Kulkarni * t4_get_tp_ch_map - return TP ingress channels associated with a port
66333dde7c95SVishal Kulkarni * @adapter: the adapter
66343dde7c95SVishal Kulkarni * @pidx: the port index
66353dde7c95SVishal Kulkarni *
66363dde7c95SVishal Kulkarni * Returns a bitmap indicating which TP Ingress Channels are associated with
66373dde7c95SVishal Kulkarni * a given Port. Bit i is set if TP Ingress Channel i is used by the Port.
66383dde7c95SVishal Kulkarni */
t4_get_tp_ch_map(struct adapter * adapter,int pidx)66393dde7c95SVishal Kulkarni unsigned int t4_get_tp_ch_map(struct adapter *adapter, int pidx)
66403dde7c95SVishal Kulkarni {
66413dde7c95SVishal Kulkarni unsigned int chip_version = CHELSIO_CHIP_VERSION(adapter->params.chip);
66423dde7c95SVishal Kulkarni unsigned int nports = 1 << G_NUMPORTS(t4_read_reg(adapter, A_MPS_CMN_CTL));
66433dde7c95SVishal Kulkarni
66443dde7c95SVishal Kulkarni if (pidx >= nports) {
66453dde7c95SVishal Kulkarni CH_WARN(adapter, "TP Port Index %d >= Nports %d\n", pidx, nports);
66463dde7c95SVishal Kulkarni return 0;
66473dde7c95SVishal Kulkarni }
66483dde7c95SVishal Kulkarni
66493dde7c95SVishal Kulkarni switch (chip_version) {
66503dde7c95SVishal Kulkarni case CHELSIO_T4:
66513dde7c95SVishal Kulkarni case CHELSIO_T5:
665256b2bdd1SGireesh Nagabhushana /*
66533dde7c95SVishal Kulkarni * Note that this happens to be the same values as the MPS
66543dde7c95SVishal Kulkarni * Buffer Group Map for these Chips. But we replicate the code
66553dde7c95SVishal Kulkarni * here because they're really separate concepts.
66563dde7c95SVishal Kulkarni */
66573dde7c95SVishal Kulkarni switch (nports) {
66583dde7c95SVishal Kulkarni case 1: return 0xf;
66593dde7c95SVishal Kulkarni case 2: return 3 << (2 * pidx);
66603dde7c95SVishal Kulkarni case 4: return 1 << pidx;
66613dde7c95SVishal Kulkarni }
66623dde7c95SVishal Kulkarni break;
66633dde7c95SVishal Kulkarni
66643dde7c95SVishal Kulkarni case CHELSIO_T6:
66653dde7c95SVishal Kulkarni switch (nports) {
66667e6ad469SVishal Kulkarni case 1: return 1 << pidx;
66673dde7c95SVishal Kulkarni case 2: return 1 << pidx;
66683dde7c95SVishal Kulkarni }
66693dde7c95SVishal Kulkarni break;
66703dde7c95SVishal Kulkarni }
66713dde7c95SVishal Kulkarni
66723dde7c95SVishal Kulkarni CH_ERR(adapter, "Need TP Channel Map for Chip %0x, Nports %d\n",
66733dde7c95SVishal Kulkarni chip_version, nports);
66743dde7c95SVishal Kulkarni return 0;
66753dde7c95SVishal Kulkarni }
66763dde7c95SVishal Kulkarni
66773dde7c95SVishal Kulkarni /**
66783dde7c95SVishal Kulkarni * t4_get_port_type_description - return Port Type string description
66793dde7c95SVishal Kulkarni * @port_type: firmware Port Type enumeration
66803dde7c95SVishal Kulkarni */
t4_get_port_type_description(enum fw_port_type port_type)66813dde7c95SVishal Kulkarni const char *t4_get_port_type_description(enum fw_port_type port_type)
66823dde7c95SVishal Kulkarni {
66833dde7c95SVishal Kulkarni static const char *const port_type_description[] = {
66843dde7c95SVishal Kulkarni "Fiber_XFI",
66853dde7c95SVishal Kulkarni "Fiber_XAUI",
66863dde7c95SVishal Kulkarni "BT_SGMII",
66873dde7c95SVishal Kulkarni "BT_XFI",
66883dde7c95SVishal Kulkarni "BT_XAUI",
66893dde7c95SVishal Kulkarni "KX4",
66903dde7c95SVishal Kulkarni "CX4",
66913dde7c95SVishal Kulkarni "KX",
66923dde7c95SVishal Kulkarni "KR",
66933dde7c95SVishal Kulkarni "SFP",
66943dde7c95SVishal Kulkarni "BP_AP",
66953dde7c95SVishal Kulkarni "BP4_AP",
66963dde7c95SVishal Kulkarni "QSFP_10G",
66973dde7c95SVishal Kulkarni "QSA",
66983dde7c95SVishal Kulkarni "QSFP",
66993dde7c95SVishal Kulkarni "BP40_BA",
67003dde7c95SVishal Kulkarni "KR4_100G",
67013dde7c95SVishal Kulkarni "CR4_QSFP",
67023dde7c95SVishal Kulkarni "CR_QSFP",
67033dde7c95SVishal Kulkarni "CR2_QSFP",
67043dde7c95SVishal Kulkarni "SFP28",
67053dde7c95SVishal Kulkarni "KR_SFP28",
67067e6ad469SVishal Kulkarni "KR_XLAUI",
67073dde7c95SVishal Kulkarni };
67083dde7c95SVishal Kulkarni
67093dde7c95SVishal Kulkarni if (port_type < ARRAY_SIZE(port_type_description))
67103dde7c95SVishal Kulkarni return port_type_description[port_type];
67113dde7c95SVishal Kulkarni return "UNKNOWN";
67123dde7c95SVishal Kulkarni }
67133dde7c95SVishal Kulkarni
67143dde7c95SVishal Kulkarni /**
67153dde7c95SVishal Kulkarni * t4_get_port_stats_offset - collect port stats relative to a previous
67163dde7c95SVishal Kulkarni * snapshot
67173dde7c95SVishal Kulkarni * @adap: The adapter
67183dde7c95SVishal Kulkarni * @idx: The port
67193dde7c95SVishal Kulkarni * @stats: Current stats to fill
67203dde7c95SVishal Kulkarni * @offset: Previous stats snapshot
67213dde7c95SVishal Kulkarni */
t4_get_port_stats_offset(struct adapter * adap,int idx,struct port_stats * stats,struct port_stats * offset)67223dde7c95SVishal Kulkarni void t4_get_port_stats_offset(struct adapter *adap, int idx,
67233dde7c95SVishal Kulkarni struct port_stats *stats,
67243dde7c95SVishal Kulkarni struct port_stats *offset)
67253dde7c95SVishal Kulkarni {
67263dde7c95SVishal Kulkarni u64 *s, *o;
67273dde7c95SVishal Kulkarni int i;
67283dde7c95SVishal Kulkarni
67293dde7c95SVishal Kulkarni t4_get_port_stats(adap, idx, stats);
67303dde7c95SVishal Kulkarni for (i = 0, s = (u64 *)stats, o = (u64 *)offset ;
67313dde7c95SVishal Kulkarni i < (sizeof(struct port_stats)/sizeof(u64)) ;
67323dde7c95SVishal Kulkarni i++, s++, o++)
67333dde7c95SVishal Kulkarni *s -= *o;
67343dde7c95SVishal Kulkarni }
67353dde7c95SVishal Kulkarni
67363dde7c95SVishal Kulkarni /**
673756b2bdd1SGireesh Nagabhushana * t4_get_port_stats - collect port statistics
673856b2bdd1SGireesh Nagabhushana * @adap: the adapter
673956b2bdd1SGireesh Nagabhushana * @idx: the port index
674056b2bdd1SGireesh Nagabhushana * @p: the stats structure to fill
674156b2bdd1SGireesh Nagabhushana *
674256b2bdd1SGireesh Nagabhushana * Collect statistics related to the given port from HW.
674356b2bdd1SGireesh Nagabhushana */
t4_get_port_stats(struct adapter * adap,int idx,struct port_stats * p)67443dde7c95SVishal Kulkarni void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
674556b2bdd1SGireesh Nagabhushana {
67463dde7c95SVishal Kulkarni u32 bgmap = t4_get_mps_bg_map(adap, idx);
67473dde7c95SVishal Kulkarni u32 stat_ctl = t4_read_reg(adap, A_MPS_STAT_CTL);
674856b2bdd1SGireesh Nagabhushana
674956b2bdd1SGireesh Nagabhushana #define GET_STAT(name) \
6750de483253SVishal Kulkarni t4_read_reg64(adap, \
6751de483253SVishal Kulkarni (is_t4(adap->params.chip) ? PORT_REG(idx, A_MPS_PORT_STAT_##name##_L) : \
6752de483253SVishal Kulkarni T5_PORT_REG(idx, A_MPS_PORT_STAT_##name##_L)))
675356b2bdd1SGireesh Nagabhushana #define GET_STAT_COM(name) t4_read_reg64(adap, A_MPS_STAT_##name##_L)
675456b2bdd1SGireesh Nagabhushana
675556b2bdd1SGireesh Nagabhushana p->tx_octets = GET_STAT(TX_PORT_BYTES);
675656b2bdd1SGireesh Nagabhushana p->tx_frames = GET_STAT(TX_PORT_FRAMES);
675756b2bdd1SGireesh Nagabhushana p->tx_bcast_frames = GET_STAT(TX_PORT_BCAST);
675856b2bdd1SGireesh Nagabhushana p->tx_mcast_frames = GET_STAT(TX_PORT_MCAST);
675956b2bdd1SGireesh Nagabhushana p->tx_ucast_frames = GET_STAT(TX_PORT_UCAST);
676056b2bdd1SGireesh Nagabhushana p->tx_error_frames = GET_STAT(TX_PORT_ERROR);
676156b2bdd1SGireesh Nagabhushana p->tx_frames_64 = GET_STAT(TX_PORT_64B);
676256b2bdd1SGireesh Nagabhushana p->tx_frames_65_127 = GET_STAT(TX_PORT_65B_127B);
676356b2bdd1SGireesh Nagabhushana p->tx_frames_128_255 = GET_STAT(TX_PORT_128B_255B);
676456b2bdd1SGireesh Nagabhushana p->tx_frames_256_511 = GET_STAT(TX_PORT_256B_511B);
676556b2bdd1SGireesh Nagabhushana p->tx_frames_512_1023 = GET_STAT(TX_PORT_512B_1023B);
676656b2bdd1SGireesh Nagabhushana p->tx_frames_1024_1518 = GET_STAT(TX_PORT_1024B_1518B);
676756b2bdd1SGireesh Nagabhushana p->tx_frames_1519_max = GET_STAT(TX_PORT_1519B_MAX);
676856b2bdd1SGireesh Nagabhushana p->tx_drop = GET_STAT(TX_PORT_DROP);
67693dde7c95SVishal Kulkarni p->tx_pause = GET_STAT(TX_PORT_PAUSE);
677056b2bdd1SGireesh Nagabhushana p->tx_ppp0 = GET_STAT(TX_PORT_PPP0);
677156b2bdd1SGireesh Nagabhushana p->tx_ppp1 = GET_STAT(TX_PORT_PPP1);
677256b2bdd1SGireesh Nagabhushana p->tx_ppp2 = GET_STAT(TX_PORT_PPP2);
677356b2bdd1SGireesh Nagabhushana p->tx_ppp3 = GET_STAT(TX_PORT_PPP3);
677456b2bdd1SGireesh Nagabhushana p->tx_ppp4 = GET_STAT(TX_PORT_PPP4);
677556b2bdd1SGireesh Nagabhushana p->tx_ppp5 = GET_STAT(TX_PORT_PPP5);
677656b2bdd1SGireesh Nagabhushana p->tx_ppp6 = GET_STAT(TX_PORT_PPP6);
677756b2bdd1SGireesh Nagabhushana p->tx_ppp7 = GET_STAT(TX_PORT_PPP7);
677856b2bdd1SGireesh Nagabhushana
67793dde7c95SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adap->params.chip) >= CHELSIO_T5) {
67807e6ad469SVishal Kulkarni if (stat_ctl & F_COUNTPAUSESTATTX)
67817e6ad469SVishal Kulkarni p->tx_frames_64 -= p->tx_pause;
67823dde7c95SVishal Kulkarni if (stat_ctl & F_COUNTPAUSEMCTX)
67833dde7c95SVishal Kulkarni p->tx_mcast_frames -= p->tx_pause;
67843dde7c95SVishal Kulkarni }
67853dde7c95SVishal Kulkarni
678656b2bdd1SGireesh Nagabhushana p->rx_octets = GET_STAT(RX_PORT_BYTES);
678756b2bdd1SGireesh Nagabhushana p->rx_frames = GET_STAT(RX_PORT_FRAMES);
678856b2bdd1SGireesh Nagabhushana p->rx_bcast_frames = GET_STAT(RX_PORT_BCAST);
678956b2bdd1SGireesh Nagabhushana p->rx_mcast_frames = GET_STAT(RX_PORT_MCAST);
679056b2bdd1SGireesh Nagabhushana p->rx_ucast_frames = GET_STAT(RX_PORT_UCAST);
679156b2bdd1SGireesh Nagabhushana p->rx_too_long = GET_STAT(RX_PORT_MTU_ERROR);
679256b2bdd1SGireesh Nagabhushana p->rx_jabber = GET_STAT(RX_PORT_MTU_CRC_ERROR);
679356b2bdd1SGireesh Nagabhushana p->rx_fcs_err = GET_STAT(RX_PORT_CRC_ERROR);
679456b2bdd1SGireesh Nagabhushana p->rx_len_err = GET_STAT(RX_PORT_LEN_ERROR);
679556b2bdd1SGireesh Nagabhushana p->rx_symbol_err = GET_STAT(RX_PORT_SYM_ERROR);
679656b2bdd1SGireesh Nagabhushana p->rx_runt = GET_STAT(RX_PORT_LESS_64B);
679756b2bdd1SGireesh Nagabhushana p->rx_frames_64 = GET_STAT(RX_PORT_64B);
679856b2bdd1SGireesh Nagabhushana p->rx_frames_65_127 = GET_STAT(RX_PORT_65B_127B);
679956b2bdd1SGireesh Nagabhushana p->rx_frames_128_255 = GET_STAT(RX_PORT_128B_255B);
680056b2bdd1SGireesh Nagabhushana p->rx_frames_256_511 = GET_STAT(RX_PORT_256B_511B);
680156b2bdd1SGireesh Nagabhushana p->rx_frames_512_1023 = GET_STAT(RX_PORT_512B_1023B);
680256b2bdd1SGireesh Nagabhushana p->rx_frames_1024_1518 = GET_STAT(RX_PORT_1024B_1518B);
680356b2bdd1SGireesh Nagabhushana p->rx_frames_1519_max = GET_STAT(RX_PORT_1519B_MAX);
68043dde7c95SVishal Kulkarni p->rx_pause = GET_STAT(RX_PORT_PAUSE);
680556b2bdd1SGireesh Nagabhushana p->rx_ppp0 = GET_STAT(RX_PORT_PPP0);
680656b2bdd1SGireesh Nagabhushana p->rx_ppp1 = GET_STAT(RX_PORT_PPP1);
680756b2bdd1SGireesh Nagabhushana p->rx_ppp2 = GET_STAT(RX_PORT_PPP2);
680856b2bdd1SGireesh Nagabhushana p->rx_ppp3 = GET_STAT(RX_PORT_PPP3);
680956b2bdd1SGireesh Nagabhushana p->rx_ppp4 = GET_STAT(RX_PORT_PPP4);
681056b2bdd1SGireesh Nagabhushana p->rx_ppp5 = GET_STAT(RX_PORT_PPP5);
681156b2bdd1SGireesh Nagabhushana p->rx_ppp6 = GET_STAT(RX_PORT_PPP6);
681256b2bdd1SGireesh Nagabhushana p->rx_ppp7 = GET_STAT(RX_PORT_PPP7);
681356b2bdd1SGireesh Nagabhushana
68143dde7c95SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adap->params.chip) >= CHELSIO_T5) {
68157e6ad469SVishal Kulkarni if (stat_ctl & F_COUNTPAUSESTATRX)
68167e6ad469SVishal Kulkarni p->rx_frames_64 -= p->rx_pause;
68173dde7c95SVishal Kulkarni if (stat_ctl & F_COUNTPAUSEMCRX)
68183dde7c95SVishal Kulkarni p->rx_mcast_frames -= p->rx_pause;
68193dde7c95SVishal Kulkarni }
68203dde7c95SVishal Kulkarni
682156b2bdd1SGireesh Nagabhushana p->rx_ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_MAC_DROP_FRAME) : 0;
682256b2bdd1SGireesh Nagabhushana p->rx_ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_MAC_DROP_FRAME) : 0;
682356b2bdd1SGireesh Nagabhushana p->rx_ovflow2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_MAC_DROP_FRAME) : 0;
682456b2bdd1SGireesh Nagabhushana p->rx_ovflow3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_MAC_DROP_FRAME) : 0;
682556b2bdd1SGireesh Nagabhushana p->rx_trunc0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_MAC_TRUNC_FRAME) : 0;
682656b2bdd1SGireesh Nagabhushana p->rx_trunc1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_MAC_TRUNC_FRAME) : 0;
682756b2bdd1SGireesh Nagabhushana p->rx_trunc2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_MAC_TRUNC_FRAME) : 0;
682856b2bdd1SGireesh Nagabhushana p->rx_trunc3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_MAC_TRUNC_FRAME) : 0;
682956b2bdd1SGireesh Nagabhushana
683056b2bdd1SGireesh Nagabhushana #undef GET_STAT
683156b2bdd1SGireesh Nagabhushana #undef GET_STAT_COM
683256b2bdd1SGireesh Nagabhushana }
683356b2bdd1SGireesh Nagabhushana
68343dde7c95SVishal Kulkarni /**
683556b2bdd1SGireesh Nagabhushana * t4_get_lb_stats - collect loopback port statistics
683656b2bdd1SGireesh Nagabhushana * @adap: the adapter
683756b2bdd1SGireesh Nagabhushana * @idx: the loopback port index
683856b2bdd1SGireesh Nagabhushana * @p: the stats structure to fill
683956b2bdd1SGireesh Nagabhushana *
684056b2bdd1SGireesh Nagabhushana * Return HW statistics for the given loopback port.
684156b2bdd1SGireesh Nagabhushana */
t4_get_lb_stats(struct adapter * adap,int idx,struct lb_port_stats * p)68423dde7c95SVishal Kulkarni void t4_get_lb_stats(struct adapter *adap, int idx, struct lb_port_stats *p)
684356b2bdd1SGireesh Nagabhushana {
68443dde7c95SVishal Kulkarni u32 bgmap = t4_get_mps_bg_map(adap, idx);
684556b2bdd1SGireesh Nagabhushana
684656b2bdd1SGireesh Nagabhushana #define GET_STAT(name) \
6847de483253SVishal Kulkarni t4_read_reg64(adap, \
6848de483253SVishal Kulkarni (is_t4(adap->params.chip) ? \
6849de483253SVishal Kulkarni PORT_REG(idx, A_MPS_PORT_STAT_LB_PORT_##name##_L) : \
6850de483253SVishal Kulkarni T5_PORT_REG(idx, A_MPS_PORT_STAT_LB_PORT_##name##_L)))
685156b2bdd1SGireesh Nagabhushana #define GET_STAT_COM(name) t4_read_reg64(adap, A_MPS_STAT_##name##_L)
685256b2bdd1SGireesh Nagabhushana
685356b2bdd1SGireesh Nagabhushana p->octets = GET_STAT(BYTES);
685456b2bdd1SGireesh Nagabhushana p->frames = GET_STAT(FRAMES);
685556b2bdd1SGireesh Nagabhushana p->bcast_frames = GET_STAT(BCAST);
685656b2bdd1SGireesh Nagabhushana p->mcast_frames = GET_STAT(MCAST);
685756b2bdd1SGireesh Nagabhushana p->ucast_frames = GET_STAT(UCAST);
685856b2bdd1SGireesh Nagabhushana p->error_frames = GET_STAT(ERROR);
685956b2bdd1SGireesh Nagabhushana
686056b2bdd1SGireesh Nagabhushana p->frames_64 = GET_STAT(64B);
686156b2bdd1SGireesh Nagabhushana p->frames_65_127 = GET_STAT(65B_127B);
686256b2bdd1SGireesh Nagabhushana p->frames_128_255 = GET_STAT(128B_255B);
686356b2bdd1SGireesh Nagabhushana p->frames_256_511 = GET_STAT(256B_511B);
686456b2bdd1SGireesh Nagabhushana p->frames_512_1023 = GET_STAT(512B_1023B);
686556b2bdd1SGireesh Nagabhushana p->frames_1024_1518 = GET_STAT(1024B_1518B);
686656b2bdd1SGireesh Nagabhushana p->frames_1519_max = GET_STAT(1519B_MAX);
6867de483253SVishal Kulkarni p->drop = GET_STAT(DROP_FRAMES);
686856b2bdd1SGireesh Nagabhushana
686956b2bdd1SGireesh Nagabhushana p->ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_DROP_FRAME) : 0;
687056b2bdd1SGireesh Nagabhushana p->ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_DROP_FRAME) : 0;
687156b2bdd1SGireesh Nagabhushana p->ovflow2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_LB_DROP_FRAME) : 0;
687256b2bdd1SGireesh Nagabhushana p->ovflow3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_LB_DROP_FRAME) : 0;
687356b2bdd1SGireesh Nagabhushana p->trunc0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_LB_TRUNC_FRAME) : 0;
687456b2bdd1SGireesh Nagabhushana p->trunc1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_LB_TRUNC_FRAME) : 0;
687556b2bdd1SGireesh Nagabhushana p->trunc2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_LB_TRUNC_FRAME) : 0;
687656b2bdd1SGireesh Nagabhushana p->trunc3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_LB_TRUNC_FRAME) : 0;
687756b2bdd1SGireesh Nagabhushana
687856b2bdd1SGireesh Nagabhushana #undef GET_STAT
687956b2bdd1SGireesh Nagabhushana #undef GET_STAT_COM
688056b2bdd1SGireesh Nagabhushana }
688156b2bdd1SGireesh Nagabhushana
68823dde7c95SVishal Kulkarni /* t4_mk_filtdelwr - create a delete filter WR
688356b2bdd1SGireesh Nagabhushana * @ftid: the filter ID
688456b2bdd1SGireesh Nagabhushana * @wr: the filter work request to populate
68853dde7c95SVishal Kulkarni * @rqtype: the filter Request Type: 0 => IPv4, 1 => IPv6
688656b2bdd1SGireesh Nagabhushana * @qid: ingress queue to receive the delete notification
688756b2bdd1SGireesh Nagabhushana *
68883dde7c95SVishal Kulkarni * Creates a filter work request to delete the supplied filter. If @qid
68893dde7c95SVishal Kulkarni * is negative the delete notification is suppressed.
689056b2bdd1SGireesh Nagabhushana */
t4_mk_filtdelwr(unsigned int ftid,struct fw_filter_wr * wr,int rqtype,int qid)68913dde7c95SVishal Kulkarni void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr,
68923dde7c95SVishal Kulkarni int rqtype, int qid)
689356b2bdd1SGireesh Nagabhushana {
68943dde7c95SVishal Kulkarni memset(wr, 0, sizeof(*wr));
68953dde7c95SVishal Kulkarni wr->op_pkd = cpu_to_be32(V_FW_WR_OP(FW_FILTER_WR));
68963dde7c95SVishal Kulkarni wr->len16_pkd = cpu_to_be32(V_FW_WR_LEN16(sizeof(*wr) / 16));
68973dde7c95SVishal Kulkarni wr->tid_to_iq = cpu_to_be32(V_FW_FILTER_WR_TID(ftid) |
68983dde7c95SVishal Kulkarni V_FW_FILTER_WR_RQTYPE(rqtype) |
689956b2bdd1SGireesh Nagabhushana V_FW_FILTER_WR_NOREPLY(qid < 0));
69003dde7c95SVishal Kulkarni wr->del_filter_to_l2tix = cpu_to_be32(F_FW_FILTER_WR_DEL_FILTER);
690156b2bdd1SGireesh Nagabhushana if (qid >= 0)
69023dde7c95SVishal Kulkarni wr->rx_chan_rx_rpl_iq =
69033dde7c95SVishal Kulkarni cpu_to_be16(V_FW_FILTER_WR_RX_RPL_IQ(qid));
690456b2bdd1SGireesh Nagabhushana }
690556b2bdd1SGireesh Nagabhushana
690656b2bdd1SGireesh Nagabhushana #define INIT_CMD(var, cmd, rd_wr) do { \
69073dde7c95SVishal Kulkarni (var).op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_##cmd##_CMD) | \
69083dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | \
69093dde7c95SVishal Kulkarni F_FW_CMD_##rd_wr); \
69103dde7c95SVishal Kulkarni (var).retval_len16 = cpu_to_be32(FW_LEN16(var)); \
691156b2bdd1SGireesh Nagabhushana } while (0)
691256b2bdd1SGireesh Nagabhushana
t4_fwaddrspace_write(struct adapter * adap,unsigned int mbox,u32 addr,u32 val)69133dde7c95SVishal Kulkarni int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
69143dde7c95SVishal Kulkarni u32 addr, u32 val)
69153dde7c95SVishal Kulkarni {
69163dde7c95SVishal Kulkarni u32 ldst_addrspace;
69173dde7c95SVishal Kulkarni struct fw_ldst_cmd c;
69183dde7c95SVishal Kulkarni
69193dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
69203dde7c95SVishal Kulkarni ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE);
69213dde7c95SVishal Kulkarni c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
69223dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
69233dde7c95SVishal Kulkarni F_FW_CMD_WRITE |
69243dde7c95SVishal Kulkarni ldst_addrspace);
69253dde7c95SVishal Kulkarni c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
69263dde7c95SVishal Kulkarni c.u.addrval.addr = cpu_to_be32(addr);
69273dde7c95SVishal Kulkarni c.u.addrval.val = cpu_to_be32(val);
69283dde7c95SVishal Kulkarni
69293dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
69303dde7c95SVishal Kulkarni }
69313dde7c95SVishal Kulkarni
69323dde7c95SVishal Kulkarni /**
693356b2bdd1SGireesh Nagabhushana * t4_mdio_rd - read a PHY register through MDIO
693456b2bdd1SGireesh Nagabhushana * @adap: the adapter
693556b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
693656b2bdd1SGireesh Nagabhushana * @phy_addr: the PHY address
693756b2bdd1SGireesh Nagabhushana * @mmd: the PHY MMD to access (0 for clause 22 PHYs)
693856b2bdd1SGireesh Nagabhushana * @reg: the register to read
693956b2bdd1SGireesh Nagabhushana * @valp: where to store the value
694056b2bdd1SGireesh Nagabhushana *
694156b2bdd1SGireesh Nagabhushana * Issues a FW command through the given mailbox to read a PHY register.
694256b2bdd1SGireesh Nagabhushana */
t4_mdio_rd(struct adapter * adap,unsigned int mbox,unsigned int phy_addr,unsigned int mmd,unsigned int reg,unsigned int * valp)69433dde7c95SVishal Kulkarni int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
694456b2bdd1SGireesh Nagabhushana unsigned int mmd, unsigned int reg, unsigned int *valp)
694556b2bdd1SGireesh Nagabhushana {
694656b2bdd1SGireesh Nagabhushana int ret;
69473dde7c95SVishal Kulkarni u32 ldst_addrspace;
694856b2bdd1SGireesh Nagabhushana struct fw_ldst_cmd c;
694956b2bdd1SGireesh Nagabhushana
69503dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
69513dde7c95SVishal Kulkarni ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO);
69523dde7c95SVishal Kulkarni c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
69533dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ |
69543dde7c95SVishal Kulkarni ldst_addrspace);
69553dde7c95SVishal Kulkarni c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
69563dde7c95SVishal Kulkarni c.u.mdio.paddr_mmd = cpu_to_be16(V_FW_LDST_CMD_PADDR(phy_addr) |
695756b2bdd1SGireesh Nagabhushana V_FW_LDST_CMD_MMD(mmd));
69583dde7c95SVishal Kulkarni c.u.mdio.raddr = cpu_to_be16(reg);
695956b2bdd1SGireesh Nagabhushana
696056b2bdd1SGireesh Nagabhushana ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
696156b2bdd1SGireesh Nagabhushana if (ret == 0)
69623dde7c95SVishal Kulkarni *valp = be16_to_cpu(c.u.mdio.rval);
69633dde7c95SVishal Kulkarni return ret;
696456b2bdd1SGireesh Nagabhushana }
696556b2bdd1SGireesh Nagabhushana
69663dde7c95SVishal Kulkarni /**
696756b2bdd1SGireesh Nagabhushana * t4_mdio_wr - write a PHY register through MDIO
696856b2bdd1SGireesh Nagabhushana * @adap: the adapter
696956b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
697056b2bdd1SGireesh Nagabhushana * @phy_addr: the PHY address
697156b2bdd1SGireesh Nagabhushana * @mmd: the PHY MMD to access (0 for clause 22 PHYs)
697256b2bdd1SGireesh Nagabhushana * @reg: the register to write
697356b2bdd1SGireesh Nagabhushana * @valp: value to write
697456b2bdd1SGireesh Nagabhushana *
697556b2bdd1SGireesh Nagabhushana * Issues a FW command through the given mailbox to write a PHY register.
697656b2bdd1SGireesh Nagabhushana */
t4_mdio_wr(struct adapter * adap,unsigned int mbox,unsigned int phy_addr,unsigned int mmd,unsigned int reg,unsigned int val)69773dde7c95SVishal Kulkarni int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr,
697856b2bdd1SGireesh Nagabhushana unsigned int mmd, unsigned int reg, unsigned int val)
697956b2bdd1SGireesh Nagabhushana {
69803dde7c95SVishal Kulkarni u32 ldst_addrspace;
698156b2bdd1SGireesh Nagabhushana struct fw_ldst_cmd c;
698256b2bdd1SGireesh Nagabhushana
69833dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
69843dde7c95SVishal Kulkarni ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO);
69853dde7c95SVishal Kulkarni c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
69863dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
69873dde7c95SVishal Kulkarni ldst_addrspace);
69883dde7c95SVishal Kulkarni c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
69893dde7c95SVishal Kulkarni c.u.mdio.paddr_mmd = cpu_to_be16(V_FW_LDST_CMD_PADDR(phy_addr) |
699056b2bdd1SGireesh Nagabhushana V_FW_LDST_CMD_MMD(mmd));
69913dde7c95SVishal Kulkarni c.u.mdio.raddr = cpu_to_be16(reg);
69923dde7c95SVishal Kulkarni c.u.mdio.rval = cpu_to_be16(val);
699356b2bdd1SGireesh Nagabhushana
69943dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
699556b2bdd1SGireesh Nagabhushana }
699656b2bdd1SGireesh Nagabhushana
69973dde7c95SVishal Kulkarni /**
69983dde7c95SVishal Kulkarni *
69993dde7c95SVishal Kulkarni * t4_sge_decode_idma_state - decode the idma state
70003dde7c95SVishal Kulkarni * @adap: the adapter
70013dde7c95SVishal Kulkarni * @state: the state idma is stuck in
70023dde7c95SVishal Kulkarni */
t4_sge_decode_idma_state(struct adapter * adapter,int state)70033dde7c95SVishal Kulkarni void t4_sge_decode_idma_state(struct adapter *adapter, int state)
70043dde7c95SVishal Kulkarni {
70053dde7c95SVishal Kulkarni static const char * const t4_decode[] = {
70063dde7c95SVishal Kulkarni "IDMA_IDLE",
70073dde7c95SVishal Kulkarni "IDMA_PUSH_MORE_CPL_FIFO",
70083dde7c95SVishal Kulkarni "IDMA_PUSH_CPL_MSG_HEADER_TO_FIFO",
70093dde7c95SVishal Kulkarni "Not used",
70103dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PCIEHDR",
70113dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PAYLOAD_FIRST",
70123dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PAYLOAD",
70133dde7c95SVishal Kulkarni "IDMA_SEND_FIFO_TO_IMSG",
70143dde7c95SVishal Kulkarni "IDMA_FL_REQ_DATA_FL_PREP",
70153dde7c95SVishal Kulkarni "IDMA_FL_REQ_DATA_FL",
70163dde7c95SVishal Kulkarni "IDMA_FL_DROP",
70173dde7c95SVishal Kulkarni "IDMA_FL_H_REQ_HEADER_FL",
70183dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_PCIEHDR",
70193dde7c95SVishal Kulkarni "IDMA_FL_H_PUSH_CPL_FIFO",
70203dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_CPL",
70213dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR_FIRST",
70223dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR",
70233dde7c95SVishal Kulkarni "IDMA_FL_H_REQ_NEXT_HEADER_FL",
70243dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_NEXT_PCIEHDR",
70253dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR_PADDING",
70263dde7c95SVishal Kulkarni "IDMA_FL_D_SEND_PCIEHDR",
70273dde7c95SVishal Kulkarni "IDMA_FL_D_SEND_CPL_AND_IP_HDR",
70283dde7c95SVishal Kulkarni "IDMA_FL_D_REQ_NEXT_DATA_FL",
70293dde7c95SVishal Kulkarni "IDMA_FL_SEND_PCIEHDR",
70303dde7c95SVishal Kulkarni "IDMA_FL_PUSH_CPL_FIFO",
70313dde7c95SVishal Kulkarni "IDMA_FL_SEND_CPL",
70323dde7c95SVishal Kulkarni "IDMA_FL_SEND_PAYLOAD_FIRST",
70333dde7c95SVishal Kulkarni "IDMA_FL_SEND_PAYLOAD",
70343dde7c95SVishal Kulkarni "IDMA_FL_REQ_NEXT_DATA_FL",
70353dde7c95SVishal Kulkarni "IDMA_FL_SEND_NEXT_PCIEHDR",
70363dde7c95SVishal Kulkarni "IDMA_FL_SEND_PADDING",
70373dde7c95SVishal Kulkarni "IDMA_FL_SEND_COMPLETION_TO_IMSG",
70383dde7c95SVishal Kulkarni "IDMA_FL_SEND_FIFO_TO_IMSG",
70393dde7c95SVishal Kulkarni "IDMA_FL_REQ_DATAFL_DONE",
70403dde7c95SVishal Kulkarni "IDMA_FL_REQ_HEADERFL_DONE",
70413dde7c95SVishal Kulkarni };
70423dde7c95SVishal Kulkarni static const char * const t5_decode[] = {
70433dde7c95SVishal Kulkarni "IDMA_IDLE",
70443dde7c95SVishal Kulkarni "IDMA_ALMOST_IDLE",
70453dde7c95SVishal Kulkarni "IDMA_PUSH_MORE_CPL_FIFO",
70463dde7c95SVishal Kulkarni "IDMA_PUSH_CPL_MSG_HEADER_TO_FIFO",
70473dde7c95SVishal Kulkarni "IDMA_SGEFLRFLUSH_SEND_PCIEHDR",
70483dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PCIEHDR",
70493dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PAYLOAD_FIRST",
70503dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PAYLOAD",
70513dde7c95SVishal Kulkarni "IDMA_SEND_FIFO_TO_IMSG",
70523dde7c95SVishal Kulkarni "IDMA_FL_REQ_DATA_FL",
70533dde7c95SVishal Kulkarni "IDMA_FL_DROP",
70543dde7c95SVishal Kulkarni "IDMA_FL_DROP_SEND_INC",
70553dde7c95SVishal Kulkarni "IDMA_FL_H_REQ_HEADER_FL",
70563dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_PCIEHDR",
70573dde7c95SVishal Kulkarni "IDMA_FL_H_PUSH_CPL_FIFO",
70583dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_CPL",
70593dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR_FIRST",
70603dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR",
70613dde7c95SVishal Kulkarni "IDMA_FL_H_REQ_NEXT_HEADER_FL",
70623dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_NEXT_PCIEHDR",
70633dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR_PADDING",
70643dde7c95SVishal Kulkarni "IDMA_FL_D_SEND_PCIEHDR",
70653dde7c95SVishal Kulkarni "IDMA_FL_D_SEND_CPL_AND_IP_HDR",
70663dde7c95SVishal Kulkarni "IDMA_FL_D_REQ_NEXT_DATA_FL",
70673dde7c95SVishal Kulkarni "IDMA_FL_SEND_PCIEHDR",
70683dde7c95SVishal Kulkarni "IDMA_FL_PUSH_CPL_FIFO",
70693dde7c95SVishal Kulkarni "IDMA_FL_SEND_CPL",
70703dde7c95SVishal Kulkarni "IDMA_FL_SEND_PAYLOAD_FIRST",
70713dde7c95SVishal Kulkarni "IDMA_FL_SEND_PAYLOAD",
70723dde7c95SVishal Kulkarni "IDMA_FL_REQ_NEXT_DATA_FL",
70733dde7c95SVishal Kulkarni "IDMA_FL_SEND_NEXT_PCIEHDR",
70743dde7c95SVishal Kulkarni "IDMA_FL_SEND_PADDING",
70753dde7c95SVishal Kulkarni "IDMA_FL_SEND_COMPLETION_TO_IMSG",
70763dde7c95SVishal Kulkarni };
70773dde7c95SVishal Kulkarni static const char * const t6_decode[] = {
70783dde7c95SVishal Kulkarni "IDMA_IDLE",
70793dde7c95SVishal Kulkarni "IDMA_PUSH_MORE_CPL_FIFO",
70803dde7c95SVishal Kulkarni "IDMA_PUSH_CPL_MSG_HEADER_TO_FIFO",
70813dde7c95SVishal Kulkarni "IDMA_SGEFLRFLUSH_SEND_PCIEHDR",
70823dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PCIEHDR",
70833dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PAYLOAD_FIRST",
70843dde7c95SVishal Kulkarni "IDMA_PHYSADDR_SEND_PAYLOAD",
70853dde7c95SVishal Kulkarni "IDMA_FL_REQ_DATA_FL",
70863dde7c95SVishal Kulkarni "IDMA_FL_DROP",
70873dde7c95SVishal Kulkarni "IDMA_FL_DROP_SEND_INC",
70883dde7c95SVishal Kulkarni "IDMA_FL_H_REQ_HEADER_FL",
70893dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_PCIEHDR",
70903dde7c95SVishal Kulkarni "IDMA_FL_H_PUSH_CPL_FIFO",
70913dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_CPL",
70923dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR_FIRST",
70933dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR",
70943dde7c95SVishal Kulkarni "IDMA_FL_H_REQ_NEXT_HEADER_FL",
70953dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_NEXT_PCIEHDR",
70963dde7c95SVishal Kulkarni "IDMA_FL_H_SEND_IP_HDR_PADDING",
70973dde7c95SVishal Kulkarni "IDMA_FL_D_SEND_PCIEHDR",
70983dde7c95SVishal Kulkarni "IDMA_FL_D_SEND_CPL_AND_IP_HDR",
70993dde7c95SVishal Kulkarni "IDMA_FL_D_REQ_NEXT_DATA_FL",
71003dde7c95SVishal Kulkarni "IDMA_FL_SEND_PCIEHDR",
71013dde7c95SVishal Kulkarni "IDMA_FL_PUSH_CPL_FIFO",
71023dde7c95SVishal Kulkarni "IDMA_FL_SEND_CPL",
71033dde7c95SVishal Kulkarni "IDMA_FL_SEND_PAYLOAD_FIRST",
71043dde7c95SVishal Kulkarni "IDMA_FL_SEND_PAYLOAD",
71053dde7c95SVishal Kulkarni "IDMA_FL_REQ_NEXT_DATA_FL",
71063dde7c95SVishal Kulkarni "IDMA_FL_SEND_NEXT_PCIEHDR",
71073dde7c95SVishal Kulkarni "IDMA_FL_SEND_PADDING",
71083dde7c95SVishal Kulkarni "IDMA_FL_SEND_COMPLETION_TO_IMSG",
71093dde7c95SVishal Kulkarni };
71103dde7c95SVishal Kulkarni static const u32 sge_regs[] = {
71113dde7c95SVishal Kulkarni A_SGE_DEBUG_DATA_LOW_INDEX_2,
71123dde7c95SVishal Kulkarni A_SGE_DEBUG_DATA_LOW_INDEX_3,
71133dde7c95SVishal Kulkarni A_SGE_DEBUG_DATA_HIGH_INDEX_10,
71143dde7c95SVishal Kulkarni };
71153dde7c95SVishal Kulkarni const char **sge_idma_decode;
71163dde7c95SVishal Kulkarni int sge_idma_decode_nstates;
71173dde7c95SVishal Kulkarni int i;
71183dde7c95SVishal Kulkarni unsigned int chip_version = CHELSIO_CHIP_VERSION(adapter->params.chip);
71193dde7c95SVishal Kulkarni
71203dde7c95SVishal Kulkarni /* Select the right set of decode strings to dump depending on the
71213dde7c95SVishal Kulkarni * adapter chip type.
71223dde7c95SVishal Kulkarni */
71233dde7c95SVishal Kulkarni switch (chip_version) {
71243dde7c95SVishal Kulkarni case CHELSIO_T4:
71253dde7c95SVishal Kulkarni sge_idma_decode = (const char **)t4_decode;
71263dde7c95SVishal Kulkarni sge_idma_decode_nstates = ARRAY_SIZE(t4_decode);
71273dde7c95SVishal Kulkarni break;
71283dde7c95SVishal Kulkarni
71293dde7c95SVishal Kulkarni case CHELSIO_T5:
71303dde7c95SVishal Kulkarni sge_idma_decode = (const char **)t5_decode;
71313dde7c95SVishal Kulkarni sge_idma_decode_nstates = ARRAY_SIZE(t5_decode);
71323dde7c95SVishal Kulkarni break;
71333dde7c95SVishal Kulkarni
71343dde7c95SVishal Kulkarni case CHELSIO_T6:
71353dde7c95SVishal Kulkarni sge_idma_decode = (const char **)t6_decode;
71363dde7c95SVishal Kulkarni sge_idma_decode_nstates = ARRAY_SIZE(t6_decode);
71373dde7c95SVishal Kulkarni break;
71383dde7c95SVishal Kulkarni
71393dde7c95SVishal Kulkarni default:
71403dde7c95SVishal Kulkarni CH_ERR(adapter, "Unsupported chip version %d\n", chip_version);
71413dde7c95SVishal Kulkarni return;
71423dde7c95SVishal Kulkarni }
71433dde7c95SVishal Kulkarni
71443dde7c95SVishal Kulkarni if (state < sge_idma_decode_nstates)
71453dde7c95SVishal Kulkarni CH_WARN(adapter, "idma state %s\n", sge_idma_decode[state]);
71463dde7c95SVishal Kulkarni else
71473dde7c95SVishal Kulkarni CH_WARN(adapter, "idma state %d unknown\n", state);
71483dde7c95SVishal Kulkarni
71493dde7c95SVishal Kulkarni for (i = 0; i < ARRAY_SIZE(sge_regs); i++)
71503dde7c95SVishal Kulkarni CH_WARN(adapter, "SGE register %#x value %#x\n",
71513dde7c95SVishal Kulkarni sge_regs[i], t4_read_reg(adapter, sge_regs[i]));
71523dde7c95SVishal Kulkarni }
71533dde7c95SVishal Kulkarni
71543dde7c95SVishal Kulkarni /**
71553dde7c95SVishal Kulkarni * t4_sge_ctxt_flush - flush the SGE context cache
715656b2bdd1SGireesh Nagabhushana * @adap: the adapter
715756b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
715856b2bdd1SGireesh Nagabhushana *
71593dde7c95SVishal Kulkarni * Issues a FW command through the given mailbox to flush the
71603dde7c95SVishal Kulkarni * SGE context cache.
716156b2bdd1SGireesh Nagabhushana */
t4_sge_ctxt_flush(struct adapter * adap,unsigned int mbox,int ctxt_type)71627e6ad469SVishal Kulkarni int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox, int ctxt_type)
716356b2bdd1SGireesh Nagabhushana {
716456b2bdd1SGireesh Nagabhushana int ret;
71653dde7c95SVishal Kulkarni u32 ldst_addrspace;
716656b2bdd1SGireesh Nagabhushana struct fw_ldst_cmd c;
716756b2bdd1SGireesh Nagabhushana
71683dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
71697e6ad469SVishal Kulkarni ldst_addrspace = V_FW_LDST_CMD_ADDRSPACE(ctxt_type == CTXT_EGRESS ?
71707e6ad469SVishal Kulkarni FW_LDST_ADDRSPC_SGE_EGRC :
71717e6ad469SVishal Kulkarni FW_LDST_ADDRSPC_SGE_INGC);
71723dde7c95SVishal Kulkarni c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
71733dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ |
71743dde7c95SVishal Kulkarni ldst_addrspace);
71753dde7c95SVishal Kulkarni c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
71763dde7c95SVishal Kulkarni c.u.idctxt.msg_ctxtflush = cpu_to_be32(F_FW_LDST_CMD_CTXTFLUSH);
717756b2bdd1SGireesh Nagabhushana
717856b2bdd1SGireesh Nagabhushana ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
71793dde7c95SVishal Kulkarni return ret;
718056b2bdd1SGireesh Nagabhushana }
718156b2bdd1SGireesh Nagabhushana
71823dde7c95SVishal Kulkarni /**
71837e6ad469SVishal Kulkarni * t4_read_sge_dbqtimers - reag SGE Doorbell Queue Timer values
71847e6ad469SVishal Kulkarni * @adap - the adapter
71857e6ad469SVishal Kulkarni * @ndbqtimers: size of the provided SGE Doorbell Queue Timer table
71867e6ad469SVishal Kulkarni * @dbqtimers: SGE Doorbell Queue Timer table
71877e6ad469SVishal Kulkarni *
71887e6ad469SVishal Kulkarni * Reads the SGE Doorbell Queue Timer values into the provided table.
71897e6ad469SVishal Kulkarni * Returns 0 on success (Firmware and Hardware support this feature),
71907e6ad469SVishal Kulkarni * an error on failure.
71917e6ad469SVishal Kulkarni */
t4_read_sge_dbqtimers(struct adapter * adap,unsigned int ndbqtimers,u16 * dbqtimers)71927e6ad469SVishal Kulkarni int t4_read_sge_dbqtimers(struct adapter *adap, unsigned int ndbqtimers,
71937e6ad469SVishal Kulkarni u16 *dbqtimers)
71947e6ad469SVishal Kulkarni {
71957e6ad469SVishal Kulkarni int ret, dbqtimerix;
71967e6ad469SVishal Kulkarni
71977e6ad469SVishal Kulkarni ret = 0;
71987e6ad469SVishal Kulkarni dbqtimerix = 0;
71997e6ad469SVishal Kulkarni while (dbqtimerix < ndbqtimers) {
72007e6ad469SVishal Kulkarni int nparams, param;
72017e6ad469SVishal Kulkarni u32 params[7], vals[7];
72027e6ad469SVishal Kulkarni
72037e6ad469SVishal Kulkarni nparams = ndbqtimers - dbqtimerix;
72047e6ad469SVishal Kulkarni if (nparams > ARRAY_SIZE(params))
72057e6ad469SVishal Kulkarni nparams = ARRAY_SIZE(params);
72067e6ad469SVishal Kulkarni
72077e6ad469SVishal Kulkarni for (param = 0; param < nparams; param++)
72087e6ad469SVishal Kulkarni params[param] =
72097e6ad469SVishal Kulkarni (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
72107e6ad469SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_DBQ_TIMER) |
72117e6ad469SVishal Kulkarni V_FW_PARAMS_PARAM_Y(dbqtimerix + param));
72127e6ad469SVishal Kulkarni ret = t4_query_params(adap, adap->mbox, adap->pf, 0,
72137e6ad469SVishal Kulkarni nparams, params, vals);
72147e6ad469SVishal Kulkarni if (ret)
72157e6ad469SVishal Kulkarni break;
72167e6ad469SVishal Kulkarni
72177e6ad469SVishal Kulkarni for (param = 0; param < nparams; param++)
72187e6ad469SVishal Kulkarni dbqtimers[dbqtimerix++] = vals[param];
72197e6ad469SVishal Kulkarni }
72207e6ad469SVishal Kulkarni return ret;
72217e6ad469SVishal Kulkarni }
72227e6ad469SVishal Kulkarni
72237e6ad469SVishal Kulkarni /**
722456b2bdd1SGireesh Nagabhushana * t4_fw_hello - establish communication with FW
722556b2bdd1SGireesh Nagabhushana * @adap: the adapter
722656b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
722756b2bdd1SGireesh Nagabhushana * @evt_mbox: mailbox to receive async FW events
722856b2bdd1SGireesh Nagabhushana * @master: specifies the caller's willingness to be the device master
722956b2bdd1SGireesh Nagabhushana * @state: returns the current device state (if non-NULL)
72303dde7c95SVishal Kulkarni *
723156b2bdd1SGireesh Nagabhushana * Issues a command to establish communication with FW. Returns either
723256b2bdd1SGireesh Nagabhushana * an error (negative integer) or the mailbox of the Master PF.
723356b2bdd1SGireesh Nagabhushana */
t4_fw_hello(struct adapter * adap,unsigned int mbox,unsigned int evt_mbox,enum dev_master master,enum dev_state * state)72343dde7c95SVishal Kulkarni int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
723556b2bdd1SGireesh Nagabhushana enum dev_master master, enum dev_state *state)
723656b2bdd1SGireesh Nagabhushana {
723756b2bdd1SGireesh Nagabhushana int ret;
723856b2bdd1SGireesh Nagabhushana struct fw_hello_cmd c;
723956b2bdd1SGireesh Nagabhushana u32 v;
724056b2bdd1SGireesh Nagabhushana unsigned int master_mbox;
724156b2bdd1SGireesh Nagabhushana int retries = FW_CMD_HELLO_RETRIES;
724256b2bdd1SGireesh Nagabhushana
724356b2bdd1SGireesh Nagabhushana retry:
72443dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
724556b2bdd1SGireesh Nagabhushana INIT_CMD(c, HELLO, WRITE);
72463dde7c95SVishal Kulkarni c.err_to_clearinit = cpu_to_be32(
724756b2bdd1SGireesh Nagabhushana V_FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) |
724856b2bdd1SGireesh Nagabhushana V_FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) |
72493dde7c95SVishal Kulkarni V_FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ?
72503dde7c95SVishal Kulkarni mbox : M_FW_HELLO_CMD_MBMASTER) |
725156b2bdd1SGireesh Nagabhushana V_FW_HELLO_CMD_MBASYNCNOT(evt_mbox) |
725256b2bdd1SGireesh Nagabhushana V_FW_HELLO_CMD_STAGE(FW_HELLO_CMD_STAGE_OS) |
725356b2bdd1SGireesh Nagabhushana F_FW_HELLO_CMD_CLEARINIT);
725456b2bdd1SGireesh Nagabhushana
725556b2bdd1SGireesh Nagabhushana /*
725656b2bdd1SGireesh Nagabhushana * Issue the HELLO command to the firmware. If it's not successful
725756b2bdd1SGireesh Nagabhushana * but indicates that we got a "busy" or "timeout" condition, retry
7258de483253SVishal Kulkarni * the HELLO until we exhaust our retry limit. If we do exceed our
7259de483253SVishal Kulkarni * retry limit, check to see if the firmware left us any error
7260de483253SVishal Kulkarni * information and report that if so ...
726156b2bdd1SGireesh Nagabhushana */
726256b2bdd1SGireesh Nagabhushana ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
726356b2bdd1SGireesh Nagabhushana if (ret != FW_SUCCESS) {
726456b2bdd1SGireesh Nagabhushana if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0)
726556b2bdd1SGireesh Nagabhushana goto retry;
7266de483253SVishal Kulkarni if (t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_ERR)
7267de483253SVishal Kulkarni t4_report_fw_error(adap);
72683dde7c95SVishal Kulkarni return ret;
726956b2bdd1SGireesh Nagabhushana }
727056b2bdd1SGireesh Nagabhushana
72713dde7c95SVishal Kulkarni v = be32_to_cpu(c.err_to_clearinit);
727256b2bdd1SGireesh Nagabhushana master_mbox = G_FW_HELLO_CMD_MBMASTER(v);
72733dde7c95SVishal Kulkarni if (state) {
727456b2bdd1SGireesh Nagabhushana if (v & F_FW_HELLO_CMD_ERR)
727556b2bdd1SGireesh Nagabhushana *state = DEV_STATE_ERR;
727656b2bdd1SGireesh Nagabhushana else if (v & F_FW_HELLO_CMD_INIT)
727756b2bdd1SGireesh Nagabhushana *state = DEV_STATE_INIT;
727856b2bdd1SGireesh Nagabhushana else
727956b2bdd1SGireesh Nagabhushana *state = DEV_STATE_UNINIT;
728056b2bdd1SGireesh Nagabhushana }
728156b2bdd1SGireesh Nagabhushana
728256b2bdd1SGireesh Nagabhushana /*
728356b2bdd1SGireesh Nagabhushana * If we're not the Master PF then we need to wait around for the
728456b2bdd1SGireesh Nagabhushana * Master PF Driver to finish setting up the adapter.
728556b2bdd1SGireesh Nagabhushana *
728656b2bdd1SGireesh Nagabhushana * Note that we also do this wait if we're a non-Master-capable PF and
728756b2bdd1SGireesh Nagabhushana * there is no current Master PF; a Master PF may show up momentarily
728856b2bdd1SGireesh Nagabhushana * and we wouldn't want to fail pointlessly. (This can happen when an
728956b2bdd1SGireesh Nagabhushana * OS loads lots of different drivers rapidly at the same time). In
729056b2bdd1SGireesh Nagabhushana * this case, the Master PF returned by the firmware will be
729156b2bdd1SGireesh Nagabhushana * M_PCIE_FW_MASTER so the test below will work ...
729256b2bdd1SGireesh Nagabhushana */
729356b2bdd1SGireesh Nagabhushana if ((v & (F_FW_HELLO_CMD_ERR|F_FW_HELLO_CMD_INIT)) == 0 &&
729456b2bdd1SGireesh Nagabhushana master_mbox != mbox) {
729556b2bdd1SGireesh Nagabhushana int waiting = FW_CMD_HELLO_TIMEOUT;
729656b2bdd1SGireesh Nagabhushana
729756b2bdd1SGireesh Nagabhushana /*
729856b2bdd1SGireesh Nagabhushana * Wait for the firmware to either indicate an error or
729956b2bdd1SGireesh Nagabhushana * initialized state. If we see either of these we bail out
730056b2bdd1SGireesh Nagabhushana * and report the issue to the caller. If we exhaust the
730156b2bdd1SGireesh Nagabhushana * "hello timeout" and we haven't exhausted our retries, try
730256b2bdd1SGireesh Nagabhushana * again. Otherwise bail with a timeout error.
730356b2bdd1SGireesh Nagabhushana */
730456b2bdd1SGireesh Nagabhushana for (;;) {
730556b2bdd1SGireesh Nagabhushana u32 pcie_fw;
730656b2bdd1SGireesh Nagabhushana
730756b2bdd1SGireesh Nagabhushana msleep(50);
730856b2bdd1SGireesh Nagabhushana waiting -= 50;
730956b2bdd1SGireesh Nagabhushana
731056b2bdd1SGireesh Nagabhushana /*
731156b2bdd1SGireesh Nagabhushana * If neither Error nor Initialialized are indicated
73123dde7c95SVishal Kulkarni * by the firmware keep waiting till we exaust our
731356b2bdd1SGireesh Nagabhushana * timeout ... and then retry if we haven't exhausted
731456b2bdd1SGireesh Nagabhushana * our retries ...
731556b2bdd1SGireesh Nagabhushana */
731656b2bdd1SGireesh Nagabhushana pcie_fw = t4_read_reg(adap, A_PCIE_FW);
731756b2bdd1SGireesh Nagabhushana if (!(pcie_fw & (F_PCIE_FW_ERR|F_PCIE_FW_INIT))) {
731856b2bdd1SGireesh Nagabhushana if (waiting <= 0) {
731956b2bdd1SGireesh Nagabhushana if (retries-- > 0)
732056b2bdd1SGireesh Nagabhushana goto retry;
732156b2bdd1SGireesh Nagabhushana
73223dde7c95SVishal Kulkarni return -ETIMEDOUT;
732356b2bdd1SGireesh Nagabhushana }
732456b2bdd1SGireesh Nagabhushana continue;
732556b2bdd1SGireesh Nagabhushana }
732656b2bdd1SGireesh Nagabhushana
732756b2bdd1SGireesh Nagabhushana /*
732856b2bdd1SGireesh Nagabhushana * We either have an Error or Initialized condition
732956b2bdd1SGireesh Nagabhushana * report errors preferentially.
733056b2bdd1SGireesh Nagabhushana */
73313dde7c95SVishal Kulkarni if (state) {
733256b2bdd1SGireesh Nagabhushana if (pcie_fw & F_PCIE_FW_ERR)
733356b2bdd1SGireesh Nagabhushana *state = DEV_STATE_ERR;
733456b2bdd1SGireesh Nagabhushana else if (pcie_fw & F_PCIE_FW_INIT)
733556b2bdd1SGireesh Nagabhushana *state = DEV_STATE_INIT;
733656b2bdd1SGireesh Nagabhushana }
733756b2bdd1SGireesh Nagabhushana
733856b2bdd1SGireesh Nagabhushana /*
733956b2bdd1SGireesh Nagabhushana * If we arrived before a Master PF was selected and
734056b2bdd1SGireesh Nagabhushana * there's not a valid Master PF, grab its identity
734156b2bdd1SGireesh Nagabhushana * for our caller.
734256b2bdd1SGireesh Nagabhushana */
734356b2bdd1SGireesh Nagabhushana if (master_mbox == M_PCIE_FW_MASTER &&
734456b2bdd1SGireesh Nagabhushana (pcie_fw & F_PCIE_FW_MASTER_VLD))
734556b2bdd1SGireesh Nagabhushana master_mbox = G_PCIE_FW_MASTER(pcie_fw);
734656b2bdd1SGireesh Nagabhushana break;
734756b2bdd1SGireesh Nagabhushana }
734856b2bdd1SGireesh Nagabhushana }
734956b2bdd1SGireesh Nagabhushana
73503dde7c95SVishal Kulkarni return master_mbox;
735156b2bdd1SGireesh Nagabhushana }
735256b2bdd1SGireesh Nagabhushana
73533dde7c95SVishal Kulkarni /**
735456b2bdd1SGireesh Nagabhushana * t4_fw_bye - end communication with FW
735556b2bdd1SGireesh Nagabhushana * @adap: the adapter
735656b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
735756b2bdd1SGireesh Nagabhushana *
735856b2bdd1SGireesh Nagabhushana * Issues a command to terminate communication with FW.
735956b2bdd1SGireesh Nagabhushana */
t4_fw_bye(struct adapter * adap,unsigned int mbox)73603dde7c95SVishal Kulkarni int t4_fw_bye(struct adapter *adap, unsigned int mbox)
736156b2bdd1SGireesh Nagabhushana {
736256b2bdd1SGireesh Nagabhushana struct fw_bye_cmd c;
736356b2bdd1SGireesh Nagabhushana
73643dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
736556b2bdd1SGireesh Nagabhushana INIT_CMD(c, BYE, WRITE);
73663dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
736756b2bdd1SGireesh Nagabhushana }
736856b2bdd1SGireesh Nagabhushana
73693dde7c95SVishal Kulkarni /**
737056b2bdd1SGireesh Nagabhushana * t4_fw_reset - issue a reset to FW
737156b2bdd1SGireesh Nagabhushana * @adap: the adapter
737256b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
737356b2bdd1SGireesh Nagabhushana * @reset: specifies the type of reset to perform
737456b2bdd1SGireesh Nagabhushana *
737556b2bdd1SGireesh Nagabhushana * Issues a reset command of the specified type to FW.
737656b2bdd1SGireesh Nagabhushana */
t4_fw_reset(struct adapter * adap,unsigned int mbox,int reset)73773dde7c95SVishal Kulkarni int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
737856b2bdd1SGireesh Nagabhushana {
737956b2bdd1SGireesh Nagabhushana struct fw_reset_cmd c;
738056b2bdd1SGireesh Nagabhushana
73813dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
738256b2bdd1SGireesh Nagabhushana INIT_CMD(c, RESET, WRITE);
73833dde7c95SVishal Kulkarni c.val = cpu_to_be32(reset);
73843dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
738556b2bdd1SGireesh Nagabhushana }
738656b2bdd1SGireesh Nagabhushana
73873dde7c95SVishal Kulkarni /**
73883dde7c95SVishal Kulkarni * t4_fw_halt - issue a reset/halt to FW and put uP into RESET
738956b2bdd1SGireesh Nagabhushana * @adap: the adapter
73903dde7c95SVishal Kulkarni * @mbox: mailbox to use for the FW RESET command (if desired)
73913dde7c95SVishal Kulkarni * @force: force uP into RESET even if FW RESET command fails
739256b2bdd1SGireesh Nagabhushana *
73933dde7c95SVishal Kulkarni * Issues a RESET command to firmware (if desired) with a HALT indication
73943dde7c95SVishal Kulkarni * and then puts the microprocessor into RESET state. The RESET command
73953dde7c95SVishal Kulkarni * will only be issued if a legitimate mailbox is provided (mbox <=
73963dde7c95SVishal Kulkarni * M_PCIE_FW_MASTER).
739756b2bdd1SGireesh Nagabhushana *
73983dde7c95SVishal Kulkarni * This is generally used in order for the host to safely manipulate the
73993dde7c95SVishal Kulkarni * adapter without fear of conflicting with whatever the firmware might
74003dde7c95SVishal Kulkarni * be doing. The only way out of this state is to RESTART the firmware
74013dde7c95SVishal Kulkarni * ...
740256b2bdd1SGireesh Nagabhushana */
t4_fw_halt(struct adapter * adap,unsigned int mbox,int force)74033dde7c95SVishal Kulkarni static int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
740456b2bdd1SGireesh Nagabhushana {
74053dde7c95SVishal Kulkarni int ret = 0;
740656b2bdd1SGireesh Nagabhushana
740756b2bdd1SGireesh Nagabhushana /*
74083dde7c95SVishal Kulkarni * If a legitimate mailbox is provided, issue a RESET command
74093dde7c95SVishal Kulkarni * with a HALT indication.
741056b2bdd1SGireesh Nagabhushana */
74113dde7c95SVishal Kulkarni if (mbox <= M_PCIE_FW_MASTER) {
74123dde7c95SVishal Kulkarni struct fw_reset_cmd c;
741356b2bdd1SGireesh Nagabhushana
74143dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
74153dde7c95SVishal Kulkarni INIT_CMD(c, RESET, WRITE);
74163dde7c95SVishal Kulkarni c.val = cpu_to_be32(F_PIORST | F_PIORSTMODE);
74173dde7c95SVishal Kulkarni c.halt_pkd = cpu_to_be32(F_FW_RESET_CMD_HALT);
74183dde7c95SVishal Kulkarni ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
741956b2bdd1SGireesh Nagabhushana }
742056b2bdd1SGireesh Nagabhushana
742156b2bdd1SGireesh Nagabhushana /*
74223dde7c95SVishal Kulkarni * Normally we won't complete the operation if the firmware RESET
74233dde7c95SVishal Kulkarni * command fails but if our caller insists we'll go ahead and put the
74243dde7c95SVishal Kulkarni * uP into RESET. This can be useful if the firmware is hung or even
74253dde7c95SVishal Kulkarni * missing ... We'll have to take the risk of putting the uP into
74263dde7c95SVishal Kulkarni * RESET without the cooperation of firmware in that case.
74273dde7c95SVishal Kulkarni *
74283dde7c95SVishal Kulkarni * We also force the firmware's HALT flag to be on in case we bypassed
74293dde7c95SVishal Kulkarni * the firmware RESET command above or we're dealing with old firmware
74303dde7c95SVishal Kulkarni * which doesn't have the HALT capability. This will serve as a flag
74313dde7c95SVishal Kulkarni * for the incoming firmware to know that it's coming out of a HALT
74323dde7c95SVishal Kulkarni * rather than a RESET ... if it's new enough to understand that ...
74333dde7c95SVishal Kulkarni */
74343dde7c95SVishal Kulkarni if (ret == 0 || force) {
74353dde7c95SVishal Kulkarni t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, F_UPCRST);
74363dde7c95SVishal Kulkarni t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT,
74373dde7c95SVishal Kulkarni F_PCIE_FW_HALT);
74383dde7c95SVishal Kulkarni }
74393dde7c95SVishal Kulkarni
74403dde7c95SVishal Kulkarni /*
74413dde7c95SVishal Kulkarni * And we always return the result of the firmware RESET command
74423dde7c95SVishal Kulkarni * even when we force the uP into RESET ...
74433dde7c95SVishal Kulkarni */
74443dde7c95SVishal Kulkarni return ret;
74453dde7c95SVishal Kulkarni }
74463dde7c95SVishal Kulkarni
74473dde7c95SVishal Kulkarni /**
74483dde7c95SVishal Kulkarni * t4_fw_restart - restart the firmware by taking the uP out of RESET
74493dde7c95SVishal Kulkarni * @adap: the adapter
74503dde7c95SVishal Kulkarni * @reset: if we want to do a RESET to restart things
74513dde7c95SVishal Kulkarni *
74523dde7c95SVishal Kulkarni * Restart firmware previously halted by t4_fw_halt(). On successful
74533dde7c95SVishal Kulkarni * return the previous PF Master remains as the new PF Master and there
74543dde7c95SVishal Kulkarni * is no need to issue a new HELLO command, etc.
74553dde7c95SVishal Kulkarni *
74563dde7c95SVishal Kulkarni * We do this in two ways:
74573dde7c95SVishal Kulkarni *
74583dde7c95SVishal Kulkarni * 1. If we're dealing with newer firmware we'll simply want to take
74593dde7c95SVishal Kulkarni * the chip's microprocessor out of RESET. This will cause the
74603dde7c95SVishal Kulkarni * firmware to start up from its start vector. And then we'll loop
74613dde7c95SVishal Kulkarni * until the firmware indicates it's started again (PCIE_FW.HALT
74623dde7c95SVishal Kulkarni * reset to 0) or we timeout.
74633dde7c95SVishal Kulkarni *
74643dde7c95SVishal Kulkarni * 2. If we're dealing with older firmware then we'll need to RESET
74653dde7c95SVishal Kulkarni * the chip since older firmware won't recognize the PCIE_FW.HALT
74663dde7c95SVishal Kulkarni * flag and automatically RESET itself on startup.
74673dde7c95SVishal Kulkarni */
t4_fw_restart(struct adapter * adap,unsigned int mbox,int reset)74683dde7c95SVishal Kulkarni static int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset)
74693dde7c95SVishal Kulkarni {
74703dde7c95SVishal Kulkarni if (reset) {
74713dde7c95SVishal Kulkarni /*
74723dde7c95SVishal Kulkarni * Since we're directing the RESET instead of the firmware
74733dde7c95SVishal Kulkarni * doing it automatically, we need to clear the PCIE_FW.HALT
74743dde7c95SVishal Kulkarni * bit.
74753dde7c95SVishal Kulkarni */
74763dde7c95SVishal Kulkarni t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT, 0);
74773dde7c95SVishal Kulkarni
74783dde7c95SVishal Kulkarni /*
74793dde7c95SVishal Kulkarni * If we've been given a valid mailbox, first try to get the
74803dde7c95SVishal Kulkarni * firmware to do the RESET. If that works, great and we can
74813dde7c95SVishal Kulkarni * return success. Otherwise, if we haven't been given a
74823dde7c95SVishal Kulkarni * valid mailbox or the RESET command failed, fall back to
74833dde7c95SVishal Kulkarni * hitting the chip with a hammer.
74843dde7c95SVishal Kulkarni */
74853dde7c95SVishal Kulkarni if (mbox <= M_PCIE_FW_MASTER) {
74863dde7c95SVishal Kulkarni t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, 0);
74873dde7c95SVishal Kulkarni msleep(100);
74883dde7c95SVishal Kulkarni if (t4_fw_reset(adap, mbox,
74893dde7c95SVishal Kulkarni F_PIORST | F_PIORSTMODE) == 0)
74903dde7c95SVishal Kulkarni return 0;
74913dde7c95SVishal Kulkarni }
74923dde7c95SVishal Kulkarni
74933dde7c95SVishal Kulkarni t4_write_reg(adap, A_PL_RST, F_PIORST | F_PIORSTMODE);
74943dde7c95SVishal Kulkarni msleep(2000);
74953dde7c95SVishal Kulkarni } else {
74963dde7c95SVishal Kulkarni int ms;
74973dde7c95SVishal Kulkarni
74983dde7c95SVishal Kulkarni t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, 0);
74993dde7c95SVishal Kulkarni for (ms = 0; ms < FW_CMD_MAX_TIMEOUT; ) {
75003dde7c95SVishal Kulkarni if (!(t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_HALT))
75013dde7c95SVishal Kulkarni return FW_SUCCESS;
75023dde7c95SVishal Kulkarni msleep(100);
75033dde7c95SVishal Kulkarni ms += 100;
75043dde7c95SVishal Kulkarni }
75053dde7c95SVishal Kulkarni return -ETIMEDOUT;
75063dde7c95SVishal Kulkarni }
75073dde7c95SVishal Kulkarni return 0;
75083dde7c95SVishal Kulkarni }
75093dde7c95SVishal Kulkarni
75103dde7c95SVishal Kulkarni /**
75113dde7c95SVishal Kulkarni * t4_fw_upgrade - perform all of the steps necessary to upgrade FW
75123dde7c95SVishal Kulkarni * @adap: the adapter
75133dde7c95SVishal Kulkarni * @mbox: mailbox to use for the FW RESET command (if desired)
75143dde7c95SVishal Kulkarni * @fw_data: the firmware image to write
75153dde7c95SVishal Kulkarni * @size: image size
75163dde7c95SVishal Kulkarni * @force: force upgrade even if firmware doesn't cooperate
75173dde7c95SVishal Kulkarni *
75183dde7c95SVishal Kulkarni * Perform all of the steps necessary for upgrading an adapter's
75193dde7c95SVishal Kulkarni * firmware image. Normally this requires the cooperation of the
75203dde7c95SVishal Kulkarni * existing firmware in order to halt all existing activities
75213dde7c95SVishal Kulkarni * but if an invalid mailbox token is passed in we skip that step
75223dde7c95SVishal Kulkarni * (though we'll still put the adapter microprocessor into RESET in
75233dde7c95SVishal Kulkarni * that case).
75243dde7c95SVishal Kulkarni *
75253dde7c95SVishal Kulkarni * On successful return the new firmware will have been loaded and
75263dde7c95SVishal Kulkarni * the adapter will have been fully RESET losing all previous setup
75273dde7c95SVishal Kulkarni * state. On unsuccessful return the adapter may be completely hosed ...
75283dde7c95SVishal Kulkarni * positive errno indicates that the adapter is ~probably~ intact, a
75293dde7c95SVishal Kulkarni * negative errno indicates that things are looking bad ...
75303dde7c95SVishal Kulkarni */
t4_fw_upgrade(struct adapter * adap,unsigned int mbox,const u8 * fw_data,unsigned int size,int force)75313dde7c95SVishal Kulkarni int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
75323dde7c95SVishal Kulkarni const u8 *fw_data, unsigned int size, int force)
75333dde7c95SVishal Kulkarni {
75343dde7c95SVishal Kulkarni const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
75353dde7c95SVishal Kulkarni unsigned int bootstrap =
75363dde7c95SVishal Kulkarni be32_to_cpu(fw_hdr->magic) == FW_HDR_MAGIC_BOOTSTRAP;
75373dde7c95SVishal Kulkarni int reset, ret;
75383dde7c95SVishal Kulkarni
75393dde7c95SVishal Kulkarni if (!t4_fw_matches_chip(adap, fw_hdr))
75403dde7c95SVishal Kulkarni return -EINVAL;
75413dde7c95SVishal Kulkarni
75423dde7c95SVishal Kulkarni /* Disable FW_OK flags so that mbox commands with FW_OK flags check
75433dde7c95SVishal Kulkarni * wont be send when we are flashing FW.
75443dde7c95SVishal Kulkarni */
75453dde7c95SVishal Kulkarni adap->flags &= ~FW_OK;
75463dde7c95SVishal Kulkarni
75473dde7c95SVishal Kulkarni if (!bootstrap) {
75483dde7c95SVishal Kulkarni ret = t4_fw_halt(adap, mbox, force);
75493dde7c95SVishal Kulkarni if (ret < 0 && !force)
75503dde7c95SVishal Kulkarni goto out;
75513dde7c95SVishal Kulkarni }
75523dde7c95SVishal Kulkarni
75533dde7c95SVishal Kulkarni ret = t4_load_fw(adap, fw_data, size, bootstrap);
75543dde7c95SVishal Kulkarni if (ret < 0 || bootstrap)
75553dde7c95SVishal Kulkarni goto out;
75563dde7c95SVishal Kulkarni
75573dde7c95SVishal Kulkarni /*
75587e6ad469SVishal Kulkarni * If there was a Firmware Configuration File staored in FLASH,
75597e6ad469SVishal Kulkarni * there's a good chance that it won't be compatible with the new
75607e6ad469SVishal Kulkarni * Firmware. In order to prevent difficult to diagnose adapter
75617e6ad469SVishal Kulkarni * initialization issues, we clear out the Firmware Configuration File
75627e6ad469SVishal Kulkarni * portion of the FLASH . The user will need to re-FLASH a new
75637e6ad469SVishal Kulkarni * Firmware Configuration File which is compatible with the new
75647e6ad469SVishal Kulkarni * Firmware if that's desired.
75657e6ad469SVishal Kulkarni */
75667e6ad469SVishal Kulkarni (void)t4_load_cfg(adap, NULL, 0);
75677e6ad469SVishal Kulkarni
75687e6ad469SVishal Kulkarni /*
75693dde7c95SVishal Kulkarni * Older versions of the firmware don't understand the new
75703dde7c95SVishal Kulkarni * PCIE_FW.HALT flag and so won't know to perform a RESET when they
75713dde7c95SVishal Kulkarni * restart. So for newly loaded older firmware we'll have to do the
75723dde7c95SVishal Kulkarni * RESET for it so it starts up on a clean slate. We can tell if
75733dde7c95SVishal Kulkarni * the newly loaded firmware will handle this right by checking
75743dde7c95SVishal Kulkarni * its header flags to see if it advertises the capability.
75753dde7c95SVishal Kulkarni */
75763dde7c95SVishal Kulkarni reset = ((be32_to_cpu(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0);
75773dde7c95SVishal Kulkarni ret = t4_fw_restart(adap, mbox, reset);
75787e6ad469SVishal Kulkarni
75797e6ad469SVishal Kulkarni /* Grab potentially new Firmware Device Log parameters so we can see
75807e6ad469SVishal Kulkarni * how helthy the new Firmware is. It's okay to contact the new
75817e6ad469SVishal Kulkarni * Firmware for these parameters even though, as far as it's
75827e6ad469SVishal Kulkarni * concerned, we've never said "HELLO" to it ...
75837e6ad469SVishal Kulkarni */
75847e6ad469SVishal Kulkarni (void)t4_init_devlog_params(adap, 1);
75857e6ad469SVishal Kulkarni
75863dde7c95SVishal Kulkarni out:
75873dde7c95SVishal Kulkarni adap->flags |= FW_OK;
75883dde7c95SVishal Kulkarni return ret;
75893dde7c95SVishal Kulkarni }
75903dde7c95SVishal Kulkarni
75913dde7c95SVishal Kulkarni /**
75923dde7c95SVishal Kulkarni * t4_fl_pkt_align - return the fl packet alignment
75933dde7c95SVishal Kulkarni * @adap: the adapter
75943dde7c95SVishal Kulkarni * is_packed: True when the driver uses packed FLM mode
75953dde7c95SVishal Kulkarni *
75963dde7c95SVishal Kulkarni * T4 has a single field to specify the packing and padding boundary.
75973dde7c95SVishal Kulkarni * T5 onwards has separate fields for this and hence the alignment for
75983dde7c95SVishal Kulkarni * next packet offset is maximum of these two.
75993dde7c95SVishal Kulkarni *
76003dde7c95SVishal Kulkarni */
t4_fl_pkt_align(struct adapter * adap,bool is_packed)76013dde7c95SVishal Kulkarni int t4_fl_pkt_align(struct adapter *adap, bool is_packed)
76023dde7c95SVishal Kulkarni {
76033dde7c95SVishal Kulkarni u32 sge_control, sge_control2;
76043dde7c95SVishal Kulkarni unsigned int ingpadboundary, ingpackboundary, fl_align, ingpad_shift;
76053dde7c95SVishal Kulkarni
76063dde7c95SVishal Kulkarni sge_control = t4_read_reg(adap, A_SGE_CONTROL);
76073dde7c95SVishal Kulkarni
76083dde7c95SVishal Kulkarni /* T4 uses a single control field to specify both the PCIe Padding and
76093dde7c95SVishal Kulkarni * Packing Boundary. T5 introduced the ability to specify these
76103dde7c95SVishal Kulkarni * separately. The actual Ingress Packet Data alignment boundary
76113dde7c95SVishal Kulkarni * within Packed Buffer Mode is the maximum of these two
76123dde7c95SVishal Kulkarni * specifications. (Note that it makes no real practical sense to
76133dde7c95SVishal Kulkarni * have the Pading Boudary be larger than the Packing Boundary but you
76143dde7c95SVishal Kulkarni * could set the chip up that way and, in fact, legacy T4 code would
76153dde7c95SVishal Kulkarni * end doing this because it would initialize the Padding Boundary and
76163dde7c95SVishal Kulkarni * leave the Packing Boundary initialized to 0 (16 bytes).)
76173dde7c95SVishal Kulkarni * Padding Boundary values in T6 starts from 8B,
76183dde7c95SVishal Kulkarni * where as it is 32B for T4 and T5.
76193dde7c95SVishal Kulkarni */
76203dde7c95SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5)
76213dde7c95SVishal Kulkarni ingpad_shift = X_INGPADBOUNDARY_SHIFT;
76223dde7c95SVishal Kulkarni else
76233dde7c95SVishal Kulkarni ingpad_shift = X_T6_INGPADBOUNDARY_SHIFT;
76243dde7c95SVishal Kulkarni
76253dde7c95SVishal Kulkarni ingpadboundary = 1 << (G_INGPADBOUNDARY(sge_control) + ingpad_shift);
76263dde7c95SVishal Kulkarni
76273dde7c95SVishal Kulkarni fl_align = ingpadboundary;
76283dde7c95SVishal Kulkarni if (!is_t4(adap->params.chip) && is_packed) {
76293dde7c95SVishal Kulkarni /* T5 has a weird interpretation of one of the PCIe Packing
76303dde7c95SVishal Kulkarni * Boundary values. No idea why ...
76313dde7c95SVishal Kulkarni */
76323dde7c95SVishal Kulkarni sge_control2 = t4_read_reg(adap, A_SGE_CONTROL2);
76333dde7c95SVishal Kulkarni ingpackboundary = G_INGPACKBOUNDARY(sge_control2);
76343dde7c95SVishal Kulkarni if (ingpackboundary == X_INGPACKBOUNDARY_16B)
76353dde7c95SVishal Kulkarni ingpackboundary = 16;
76363dde7c95SVishal Kulkarni else
76373dde7c95SVishal Kulkarni ingpackboundary = 1 << (ingpackboundary +
76383dde7c95SVishal Kulkarni X_INGPACKBOUNDARY_SHIFT);
76393dde7c95SVishal Kulkarni
76403dde7c95SVishal Kulkarni fl_align = max(ingpadboundary, ingpackboundary);
76413dde7c95SVishal Kulkarni }
76423dde7c95SVishal Kulkarni return fl_align;
76433dde7c95SVishal Kulkarni }
76443dde7c95SVishal Kulkarni
76453dde7c95SVishal Kulkarni /**
76463dde7c95SVishal Kulkarni * t4_fixup_host_params_compat - fix up host-dependent parameters
764756b2bdd1SGireesh Nagabhushana * @adap: the adapter
764856b2bdd1SGireesh Nagabhushana * @page_size: the host's Base Page Size
764956b2bdd1SGireesh Nagabhushana * @cache_line_size: the host's Cache Line Size
76503dde7c95SVishal Kulkarni * @chip_compat: maintain compatibility with designated chip
765156b2bdd1SGireesh Nagabhushana *
76523dde7c95SVishal Kulkarni * Various registers in the chip contain values which are dependent on the
765356b2bdd1SGireesh Nagabhushana * host's Base Page and Cache Line Sizes. This function will fix all of
765456b2bdd1SGireesh Nagabhushana * those registers with the appropriate values as passed in ...
76553dde7c95SVishal Kulkarni *
76563dde7c95SVishal Kulkarni * @chip_compat is used to limit the set of changes that are made
76573dde7c95SVishal Kulkarni * to be compatible with the indicated chip release. This is used by
76583dde7c95SVishal Kulkarni * drivers to maintain compatibility with chip register settings when
76593dde7c95SVishal Kulkarni * the drivers haven't [yet] been updated with new chip support.
766056b2bdd1SGireesh Nagabhushana */
t4_fixup_host_params_compat(struct adapter * adap,unsigned int page_size,unsigned int cache_line_size,enum chip_type chip_compat)76613dde7c95SVishal Kulkarni int t4_fixup_host_params_compat(struct adapter *adap,
76623dde7c95SVishal Kulkarni unsigned int page_size,
76633dde7c95SVishal Kulkarni unsigned int cache_line_size,
76643dde7c95SVishal Kulkarni enum chip_type chip_compat)
766556b2bdd1SGireesh Nagabhushana {
766656b2bdd1SGireesh Nagabhushana unsigned int page_shift = fls(page_size) - 1;
766756b2bdd1SGireesh Nagabhushana unsigned int sge_hps = page_shift - 10;
766856b2bdd1SGireesh Nagabhushana unsigned int stat_len = cache_line_size > 64 ? 128 : 64;
766956b2bdd1SGireesh Nagabhushana unsigned int fl_align = cache_line_size < 32 ? 32 : cache_line_size;
767056b2bdd1SGireesh Nagabhushana unsigned int fl_align_log = fls(fl_align) - 1;
767156b2bdd1SGireesh Nagabhushana
767256b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_SGE_HOST_PAGE_SIZE,
767356b2bdd1SGireesh Nagabhushana V_HOSTPAGESIZEPF0(sge_hps) |
767456b2bdd1SGireesh Nagabhushana V_HOSTPAGESIZEPF1(sge_hps) |
767556b2bdd1SGireesh Nagabhushana V_HOSTPAGESIZEPF2(sge_hps) |
767656b2bdd1SGireesh Nagabhushana V_HOSTPAGESIZEPF3(sge_hps) |
767756b2bdd1SGireesh Nagabhushana V_HOSTPAGESIZEPF4(sge_hps) |
767856b2bdd1SGireesh Nagabhushana V_HOSTPAGESIZEPF5(sge_hps) |
767956b2bdd1SGireesh Nagabhushana V_HOSTPAGESIZEPF6(sge_hps) |
768056b2bdd1SGireesh Nagabhushana V_HOSTPAGESIZEPF7(sge_hps));
768156b2bdd1SGireesh Nagabhushana
76823dde7c95SVishal Kulkarni if (is_t4(adap->params.chip) || is_t4(chip_compat)) {
768356b2bdd1SGireesh Nagabhushana t4_set_reg_field(adap, A_SGE_CONTROL,
768456b2bdd1SGireesh Nagabhushana V_INGPADBOUNDARY(M_INGPADBOUNDARY) |
768556b2bdd1SGireesh Nagabhushana F_EGRSTATUSPAGESIZE,
76863dde7c95SVishal Kulkarni V_INGPADBOUNDARY(fl_align_log -
76873dde7c95SVishal Kulkarni X_INGPADBOUNDARY_SHIFT) |
768856b2bdd1SGireesh Nagabhushana V_EGRSTATUSPAGESIZE(stat_len != 64));
76893dde7c95SVishal Kulkarni } else {
76903dde7c95SVishal Kulkarni unsigned int pack_align;
76913dde7c95SVishal Kulkarni unsigned int ingpad, ingpack;
76923dde7c95SVishal Kulkarni unsigned int pcie_cap;
769356b2bdd1SGireesh Nagabhushana
76943dde7c95SVishal Kulkarni /* T5 introduced the separation of the Free List Padding and
76953dde7c95SVishal Kulkarni * Packing Boundaries. Thus, we can select a smaller Padding
76963dde7c95SVishal Kulkarni * Boundary to avoid uselessly chewing up PCIe Link and Memory
76973dde7c95SVishal Kulkarni * Bandwidth, and use a Packing Boundary which is large enough
76983dde7c95SVishal Kulkarni * to avoid false sharing between CPUs, etc.
76993dde7c95SVishal Kulkarni *
77003dde7c95SVishal Kulkarni * For the PCI Link, the smaller the Padding Boundary the
77013dde7c95SVishal Kulkarni * better. For the Memory Controller, a smaller Padding
77023dde7c95SVishal Kulkarni * Boundary is better until we cross under the Memory Line
77033dde7c95SVishal Kulkarni * Size (the minimum unit of transfer to/from Memory). If we
77043dde7c95SVishal Kulkarni * have a Padding Boundary which is smaller than the Memory
77053dde7c95SVishal Kulkarni * Line Size, that'll involve a Read-Modify-Write cycle on the
77063dde7c95SVishal Kulkarni * Memory Controller which is never good.
77073dde7c95SVishal Kulkarni */
77083dde7c95SVishal Kulkarni
77093dde7c95SVishal Kulkarni /* We want the Packing Boundary to be based on the Cache Line
77103dde7c95SVishal Kulkarni * Size in order to help avoid False Sharing performance
77113dde7c95SVishal Kulkarni * issues between CPUs, etc. We also want the Packing
77123dde7c95SVishal Kulkarni * Boundary to incorporate the PCI-E Maximum Payload Size. We
77133dde7c95SVishal Kulkarni * get best performance when the Packing Boundary is a
77143dde7c95SVishal Kulkarni * multiple of the Maximum Payload Size.
77153dde7c95SVishal Kulkarni */
77163dde7c95SVishal Kulkarni pack_align = fl_align;
77173dde7c95SVishal Kulkarni pcie_cap = t4_os_find_pci_capability(adap, PCI_CAP_ID_EXP);
77183dde7c95SVishal Kulkarni if (pcie_cap) {
77193dde7c95SVishal Kulkarni unsigned int mps, mps_log;
77203dde7c95SVishal Kulkarni u16 devctl;
77213dde7c95SVishal Kulkarni
77223dde7c95SVishal Kulkarni /*
77233dde7c95SVishal Kulkarni * The PCIe Device Control Maximum Payload Size field
77243dde7c95SVishal Kulkarni * [bits 7:5] encodes sizes as powers of 2 starting at
77253dde7c95SVishal Kulkarni * 128 bytes.
77263dde7c95SVishal Kulkarni */
77273dde7c95SVishal Kulkarni t4_os_pci_read_cfg2(adap, pcie_cap + PCI_EXP_DEVCTL,
77283dde7c95SVishal Kulkarni &devctl);
77293dde7c95SVishal Kulkarni mps_log = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5) + 7;
77303dde7c95SVishal Kulkarni mps = 1 << mps_log;
77313dde7c95SVishal Kulkarni if (mps > pack_align)
77323dde7c95SVishal Kulkarni pack_align = mps;
77333dde7c95SVishal Kulkarni }
77343dde7c95SVishal Kulkarni
77353dde7c95SVishal Kulkarni /* N.B. T5/T6 have a crazy special interpretation of the "0"
77363dde7c95SVishal Kulkarni * value for the Packing Boundary. This corresponds to 16
77373dde7c95SVishal Kulkarni * bytes instead of the expected 32 bytes. So if we want 32
77383dde7c95SVishal Kulkarni * bytes, the best we can really do is 64 bytes ...
77393dde7c95SVishal Kulkarni */
77403dde7c95SVishal Kulkarni if (pack_align <= 16) {
77413dde7c95SVishal Kulkarni ingpack = X_INGPACKBOUNDARY_16B;
77423dde7c95SVishal Kulkarni fl_align = 16;
77433dde7c95SVishal Kulkarni } else if (pack_align == 32) {
77443dde7c95SVishal Kulkarni ingpack = X_INGPACKBOUNDARY_64B;
77453dde7c95SVishal Kulkarni fl_align = 64;
77463dde7c95SVishal Kulkarni } else {
77473dde7c95SVishal Kulkarni unsigned int pack_align_log = fls(pack_align) - 1;
77483dde7c95SVishal Kulkarni ingpack = pack_align_log - X_INGPACKBOUNDARY_SHIFT;
77493dde7c95SVishal Kulkarni fl_align = pack_align;
77503dde7c95SVishal Kulkarni }
77513dde7c95SVishal Kulkarni
77523dde7c95SVishal Kulkarni /* Use the smallest Ingress Padding which isn't smaller than
77533dde7c95SVishal Kulkarni * the Memory Controller Read/Write Size. We'll take that as
77543dde7c95SVishal Kulkarni * being 8 bytes since we don't know of any system with a
77553dde7c95SVishal Kulkarni * wider Memory Controller Bus Width.
77563dde7c95SVishal Kulkarni */
77573dde7c95SVishal Kulkarni if (is_t5(adap->params.chip))
77583dde7c95SVishal Kulkarni ingpad = X_INGPADBOUNDARY_32B;
77593dde7c95SVishal Kulkarni else
77603dde7c95SVishal Kulkarni ingpad = X_T6_INGPADBOUNDARY_8B;
77613dde7c95SVishal Kulkarni
77623dde7c95SVishal Kulkarni t4_set_reg_field(adap, A_SGE_CONTROL,
77633dde7c95SVishal Kulkarni V_INGPADBOUNDARY(M_INGPADBOUNDARY) |
77643dde7c95SVishal Kulkarni F_EGRSTATUSPAGESIZE,
77653dde7c95SVishal Kulkarni V_INGPADBOUNDARY(ingpad) |
77663dde7c95SVishal Kulkarni V_EGRSTATUSPAGESIZE(stat_len != 64));
77673dde7c95SVishal Kulkarni t4_set_reg_field(adap, A_SGE_CONTROL2,
77683dde7c95SVishal Kulkarni V_INGPACKBOUNDARY(M_INGPACKBOUNDARY),
77693dde7c95SVishal Kulkarni V_INGPACKBOUNDARY(ingpack));
77703dde7c95SVishal Kulkarni }
777156b2bdd1SGireesh Nagabhushana /*
777256b2bdd1SGireesh Nagabhushana * Adjust various SGE Free List Host Buffer Sizes.
777356b2bdd1SGireesh Nagabhushana *
777456b2bdd1SGireesh Nagabhushana * This is something of a crock since we're using fixed indices into
777556b2bdd1SGireesh Nagabhushana * the array which are also known by the sge.c code and the T4
777656b2bdd1SGireesh Nagabhushana * Firmware Configuration File. We need to come up with a much better
777756b2bdd1SGireesh Nagabhushana * approach to managing this array. For now, the first four entries
777856b2bdd1SGireesh Nagabhushana * are:
777956b2bdd1SGireesh Nagabhushana *
778056b2bdd1SGireesh Nagabhushana * 0: Host Page Size
778156b2bdd1SGireesh Nagabhushana * 1: 64KB
778256b2bdd1SGireesh Nagabhushana * 2: Buffer size corresponding to 1500 byte MTU (unpacked mode)
778356b2bdd1SGireesh Nagabhushana * 3: Buffer size corresponding to 9000 byte MTU (unpacked mode)
778456b2bdd1SGireesh Nagabhushana *
778556b2bdd1SGireesh Nagabhushana * For the single-MTU buffers in unpacked mode we need to include
778656b2bdd1SGireesh Nagabhushana * space for the SGE Control Packet Shift, 14 byte Ethernet header,
778756b2bdd1SGireesh Nagabhushana * possible 4 byte VLAN tag, all rounded up to the next Ingress Packet
77883dde7c95SVishal Kulkarni * Padding boundary. All of these are accommodated in the Factory
778956b2bdd1SGireesh Nagabhushana * Default Firmware Configuration File but we need to adjust it for
779056b2bdd1SGireesh Nagabhushana * this host's cache line size.
779156b2bdd1SGireesh Nagabhushana */
779256b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_SGE_FL_BUFFER_SIZE0, page_size);
779356b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_SGE_FL_BUFFER_SIZE2,
77943dde7c95SVishal Kulkarni (t4_read_reg(adap, A_SGE_FL_BUFFER_SIZE2) + fl_align-1)
77953dde7c95SVishal Kulkarni & ~(fl_align-1));
779656b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_SGE_FL_BUFFER_SIZE3,
77973dde7c95SVishal Kulkarni (t4_read_reg(adap, A_SGE_FL_BUFFER_SIZE3) + fl_align-1)
77983dde7c95SVishal Kulkarni & ~(fl_align-1));
779956b2bdd1SGireesh Nagabhushana
780056b2bdd1SGireesh Nagabhushana t4_write_reg(adap, A_ULP_RX_TDDP_PSZ, V_HPZ0(page_shift - 12));
780156b2bdd1SGireesh Nagabhushana
78023dde7c95SVishal Kulkarni return 0;
780356b2bdd1SGireesh Nagabhushana }
780456b2bdd1SGireesh Nagabhushana
78053dde7c95SVishal Kulkarni /**
78063dde7c95SVishal Kulkarni * t4_fixup_host_params - fix up host-dependent parameters (T4 compatible)
78073dde7c95SVishal Kulkarni * @adap: the adapter
78083dde7c95SVishal Kulkarni * @page_size: the host's Base Page Size
78093dde7c95SVishal Kulkarni * @cache_line_size: the host's Cache Line Size
78103dde7c95SVishal Kulkarni *
78113dde7c95SVishal Kulkarni * Various registers in T4 contain values which are dependent on the
78123dde7c95SVishal Kulkarni * host's Base Page and Cache Line Sizes. This function will fix all of
78133dde7c95SVishal Kulkarni * those registers with the appropriate values as passed in ...
78143dde7c95SVishal Kulkarni *
78153dde7c95SVishal Kulkarni * This routine makes changes which are compatible with T4 chips.
78163dde7c95SVishal Kulkarni */
t4_fixup_host_params(struct adapter * adap,unsigned int page_size,unsigned int cache_line_size)78173dde7c95SVishal Kulkarni int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
78183dde7c95SVishal Kulkarni unsigned int cache_line_size)
78193dde7c95SVishal Kulkarni {
78203dde7c95SVishal Kulkarni return t4_fixup_host_params_compat(adap, page_size, cache_line_size,
78213dde7c95SVishal Kulkarni T4_LAST_REV);
78223dde7c95SVishal Kulkarni }
78233dde7c95SVishal Kulkarni
78243dde7c95SVishal Kulkarni /**
782556b2bdd1SGireesh Nagabhushana * t4_fw_initialize - ask FW to initialize the device
782656b2bdd1SGireesh Nagabhushana * @adap: the adapter
782756b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
782856b2bdd1SGireesh Nagabhushana *
782956b2bdd1SGireesh Nagabhushana * Issues a command to FW to partially initialize the device. This
783056b2bdd1SGireesh Nagabhushana * performs initialization that generally doesn't depend on user input.
783156b2bdd1SGireesh Nagabhushana */
t4_fw_initialize(struct adapter * adap,unsigned int mbox)78323dde7c95SVishal Kulkarni int t4_fw_initialize(struct adapter *adap, unsigned int mbox)
783356b2bdd1SGireesh Nagabhushana {
783456b2bdd1SGireesh Nagabhushana struct fw_initialize_cmd c;
783556b2bdd1SGireesh Nagabhushana
78363dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
783756b2bdd1SGireesh Nagabhushana INIT_CMD(c, INITIALIZE, WRITE);
78383dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
783956b2bdd1SGireesh Nagabhushana }
784056b2bdd1SGireesh Nagabhushana
78413dde7c95SVishal Kulkarni /**
78423dde7c95SVishal Kulkarni * t4_query_params_rw - query FW or device parameters
784356b2bdd1SGireesh Nagabhushana * @adap: the adapter
784456b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
784556b2bdd1SGireesh Nagabhushana * @pf: the PF
784656b2bdd1SGireesh Nagabhushana * @vf: the VF
784756b2bdd1SGireesh Nagabhushana * @nparams: the number of parameters
784856b2bdd1SGireesh Nagabhushana * @params: the parameter names
784956b2bdd1SGireesh Nagabhushana * @val: the parameter values
78503dde7c95SVishal Kulkarni * @rw: Write and read flag
78513dde7c95SVishal Kulkarni * @sleep_ok: if true, we may sleep awaiting mbox cmd completion
785256b2bdd1SGireesh Nagabhushana *
785356b2bdd1SGireesh Nagabhushana * Reads the value of FW or device parameters. Up to 7 parameters can be
785456b2bdd1SGireesh Nagabhushana * queried at once.
785556b2bdd1SGireesh Nagabhushana */
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,bool sleep_ok)78563dde7c95SVishal Kulkarni int t4_query_params_rw(struct adapter *adap, unsigned int mbox, unsigned int pf,
78573dde7c95SVishal Kulkarni unsigned int vf, unsigned int nparams, const u32 *params,
78583dde7c95SVishal Kulkarni u32 *val, int rw, bool sleep_ok)
785956b2bdd1SGireesh Nagabhushana {
786056b2bdd1SGireesh Nagabhushana int i, ret;
786156b2bdd1SGireesh Nagabhushana struct fw_params_cmd c;
786256b2bdd1SGireesh Nagabhushana __be32 *p = &c.param[0].mnem;
786356b2bdd1SGireesh Nagabhushana
786456b2bdd1SGireesh Nagabhushana if (nparams > 7)
78653dde7c95SVishal Kulkarni return -EINVAL;
786656b2bdd1SGireesh Nagabhushana
78673dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
78683dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PARAMS_CMD) |
78693dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ |
78703dde7c95SVishal Kulkarni V_FW_PARAMS_CMD_PFN(pf) |
787156b2bdd1SGireesh Nagabhushana V_FW_PARAMS_CMD_VFN(vf));
78723dde7c95SVishal Kulkarni c.retval_len16 = cpu_to_be32(FW_LEN16(c));
787356b2bdd1SGireesh Nagabhushana
78743dde7c95SVishal Kulkarni for (i = 0; i < nparams; i++) {
78753dde7c95SVishal Kulkarni *p++ = cpu_to_be32(*params++);
78763dde7c95SVishal Kulkarni if (rw)
78773dde7c95SVishal Kulkarni *p = cpu_to_be32(*(val + i));
78783dde7c95SVishal Kulkarni p++;
787956b2bdd1SGireesh Nagabhushana }
788056b2bdd1SGireesh Nagabhushana
78813dde7c95SVishal Kulkarni ret = t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), &c, sleep_ok);
78827e6ad469SVishal Kulkarni
78837e6ad469SVishal Kulkarni /*
78847e6ad469SVishal Kulkarni * We always copy back the reults, even if there's an error. We'll
78857e6ad469SVishal Kulkarni * get an error if any of the parameters was unknown to the Firmware,
78867e6ad469SVishal Kulkarni * but there will be results for the others ... (Older Firmware
78877e6ad469SVishal Kulkarni * stopped at the first unknown parameter; newer Firmware processes
78887e6ad469SVishal Kulkarni * them all and flags the unknown parameters with a return value of
78897e6ad469SVishal Kulkarni * ~0UL.)
78907e6ad469SVishal Kulkarni */
78913dde7c95SVishal Kulkarni for (i = 0, p = &c.param[0].val; i < nparams; i++, p += 2)
78923dde7c95SVishal Kulkarni *val++ = be32_to_cpu(*p);
78937e6ad469SVishal Kulkarni
78943dde7c95SVishal Kulkarni return ret;
78953dde7c95SVishal Kulkarni }
78963dde7c95SVishal Kulkarni
t4_query_params(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int nparams,const u32 * params,u32 * val)78973dde7c95SVishal Kulkarni int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
78983dde7c95SVishal Kulkarni unsigned int vf, unsigned int nparams, const u32 *params,
78993dde7c95SVishal Kulkarni u32 *val)
79003dde7c95SVishal Kulkarni {
79013dde7c95SVishal Kulkarni return t4_query_params_rw(adap, mbox, pf, vf, nparams, params, val, 0,
79023dde7c95SVishal Kulkarni true);
79033dde7c95SVishal Kulkarni }
79043dde7c95SVishal Kulkarni
t4_query_params_ns(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int nparams,const u32 * params,u32 * val)79053dde7c95SVishal Kulkarni int t4_query_params_ns(struct adapter *adap, unsigned int mbox, unsigned int pf,
79063dde7c95SVishal Kulkarni unsigned int vf, unsigned int nparams, const u32 *params,
79073dde7c95SVishal Kulkarni u32 *val)
79083dde7c95SVishal Kulkarni {
79093dde7c95SVishal Kulkarni return t4_query_params_rw(adap, mbox, pf, vf, nparams, params, val, 0,
79103dde7c95SVishal Kulkarni false);
79113dde7c95SVishal Kulkarni }
79123dde7c95SVishal Kulkarni
79133dde7c95SVishal Kulkarni /**
79143dde7c95SVishal Kulkarni * t4_set_params_timeout - sets FW or device parameters
79153dde7c95SVishal Kulkarni * @adap: the adapter
79163dde7c95SVishal Kulkarni * @mbox: mailbox to use for the FW command
79173dde7c95SVishal Kulkarni * @pf: the PF
79183dde7c95SVishal Kulkarni * @vf: the VF
79193dde7c95SVishal Kulkarni * @nparams: the number of parameters
79203dde7c95SVishal Kulkarni * @params: the parameter names
79213dde7c95SVishal Kulkarni * @val: the parameter values
79223dde7c95SVishal Kulkarni * @timeout: the timeout time
79233dde7c95SVishal Kulkarni *
79243dde7c95SVishal Kulkarni * Sets the value of FW or device parameters. Up to 7 parameters can be
79253dde7c95SVishal Kulkarni * specified at once.
79263dde7c95SVishal Kulkarni */
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)79273dde7c95SVishal Kulkarni int t4_set_params_timeout(struct adapter *adap, unsigned int mbox,
79283dde7c95SVishal Kulkarni unsigned int pf, unsigned int vf,
79293dde7c95SVishal Kulkarni unsigned int nparams, const u32 *params,
79303dde7c95SVishal Kulkarni const u32 *val, int timeout)
79313dde7c95SVishal Kulkarni {
79323dde7c95SVishal Kulkarni struct fw_params_cmd c;
79333dde7c95SVishal Kulkarni __be32 *p = &c.param[0].mnem;
79343dde7c95SVishal Kulkarni
79353dde7c95SVishal Kulkarni if (nparams > 7)
79363dde7c95SVishal Kulkarni return -EINVAL;
79373dde7c95SVishal Kulkarni
79383dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
79393dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PARAMS_CMD) |
79403dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
79413dde7c95SVishal Kulkarni V_FW_PARAMS_CMD_PFN(pf) |
79423dde7c95SVishal Kulkarni V_FW_PARAMS_CMD_VFN(vf));
79433dde7c95SVishal Kulkarni c.retval_len16 = cpu_to_be32(FW_LEN16(c));
79443dde7c95SVishal Kulkarni
79453dde7c95SVishal Kulkarni while (nparams--) {
79463dde7c95SVishal Kulkarni *p++ = cpu_to_be32(*params++);
79473dde7c95SVishal Kulkarni *p++ = cpu_to_be32(*val++);
79483dde7c95SVishal Kulkarni }
79493dde7c95SVishal Kulkarni
79503dde7c95SVishal Kulkarni return t4_wr_mbox_timeout(adap, mbox, &c, sizeof(c), NULL, timeout);
79513dde7c95SVishal Kulkarni }
79523dde7c95SVishal Kulkarni
79533dde7c95SVishal Kulkarni /**
795456b2bdd1SGireesh Nagabhushana * t4_set_params - sets FW or device parameters
795556b2bdd1SGireesh Nagabhushana * @adap: the adapter
795656b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
795756b2bdd1SGireesh Nagabhushana * @pf: the PF
795856b2bdd1SGireesh Nagabhushana * @vf: the VF
795956b2bdd1SGireesh Nagabhushana * @nparams: the number of parameters
796056b2bdd1SGireesh Nagabhushana * @params: the parameter names
796156b2bdd1SGireesh Nagabhushana * @val: the parameter values
796256b2bdd1SGireesh Nagabhushana *
796356b2bdd1SGireesh Nagabhushana * Sets the value of FW or device parameters. Up to 7 parameters can be
796456b2bdd1SGireesh Nagabhushana * specified at once.
796556b2bdd1SGireesh Nagabhushana */
t4_set_params(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int nparams,const u32 * params,const u32 * val)79663dde7c95SVishal Kulkarni int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
79673dde7c95SVishal Kulkarni unsigned int vf, unsigned int nparams, const u32 *params,
79683dde7c95SVishal Kulkarni const u32 *val)
796956b2bdd1SGireesh Nagabhushana {
79703dde7c95SVishal Kulkarni return t4_set_params_timeout(adap, mbox, pf, vf, nparams, params, val,
79713dde7c95SVishal Kulkarni FW_CMD_MAX_TIMEOUT);
797256b2bdd1SGireesh Nagabhushana }
797356b2bdd1SGireesh Nagabhushana
79743dde7c95SVishal Kulkarni /**
797556b2bdd1SGireesh Nagabhushana * t4_cfg_pfvf - configure PF/VF resource limits
797656b2bdd1SGireesh Nagabhushana * @adap: the adapter
797756b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
797856b2bdd1SGireesh Nagabhushana * @pf: the PF being configured
797956b2bdd1SGireesh Nagabhushana * @vf: the VF being configured
798056b2bdd1SGireesh Nagabhushana * @txq: the max number of egress queues
798156b2bdd1SGireesh Nagabhushana * @txq_eth_ctrl: the max number of egress Ethernet or control queues
798256b2bdd1SGireesh Nagabhushana * @rxqi: the max number of interrupt-capable ingress queues
798356b2bdd1SGireesh Nagabhushana * @rxq: the max number of interruptless ingress queues
798456b2bdd1SGireesh Nagabhushana * @tc: the PCI traffic class
798556b2bdd1SGireesh Nagabhushana * @vi: the max number of virtual interfaces
798656b2bdd1SGireesh Nagabhushana * @cmask: the channel access rights mask for the PF/VF
798756b2bdd1SGireesh Nagabhushana * @pmask: the port access rights mask for the PF/VF
798856b2bdd1SGireesh Nagabhushana * @nexact: the maximum number of exact MPS filters
798956b2bdd1SGireesh Nagabhushana * @rcaps: read capabilities
799056b2bdd1SGireesh Nagabhushana * @wxcaps: write/execute capabilities
799156b2bdd1SGireesh Nagabhushana *
799256b2bdd1SGireesh Nagabhushana * Configures resource limits and capabilities for a physical or virtual
799356b2bdd1SGireesh Nagabhushana * function.
799456b2bdd1SGireesh Nagabhushana */
t4_cfg_pfvf(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int txq,unsigned int txq_eth_ctrl,unsigned int rxqi,unsigned int rxq,unsigned int tc,unsigned int vi,unsigned int cmask,unsigned int pmask,unsigned int nexact,unsigned int rcaps,unsigned int wxcaps)79953dde7c95SVishal Kulkarni int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
799656b2bdd1SGireesh Nagabhushana unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl,
79973dde7c95SVishal Kulkarni unsigned int rxqi, unsigned int rxq, unsigned int tc,
79983dde7c95SVishal Kulkarni unsigned int vi, unsigned int cmask, unsigned int pmask,
79993dde7c95SVishal Kulkarni unsigned int nexact, unsigned int rcaps, unsigned int wxcaps)
800056b2bdd1SGireesh Nagabhushana {
800156b2bdd1SGireesh Nagabhushana struct fw_pfvf_cmd c;
800256b2bdd1SGireesh Nagabhushana
80033dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
80043dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) | F_FW_CMD_REQUEST |
80053dde7c95SVishal Kulkarni F_FW_CMD_WRITE | V_FW_PFVF_CMD_PFN(pf) |
80063dde7c95SVishal Kulkarni V_FW_PFVF_CMD_VFN(vf));
80073dde7c95SVishal Kulkarni c.retval_len16 = cpu_to_be32(FW_LEN16(c));
80083dde7c95SVishal Kulkarni c.niqflint_niq = cpu_to_be32(V_FW_PFVF_CMD_NIQFLINT(rxqi) |
800956b2bdd1SGireesh Nagabhushana V_FW_PFVF_CMD_NIQ(rxq));
80103dde7c95SVishal Kulkarni c.type_to_neq = cpu_to_be32(V_FW_PFVF_CMD_CMASK(cmask) |
80113dde7c95SVishal Kulkarni V_FW_PFVF_CMD_PMASK(pmask) |
80123dde7c95SVishal Kulkarni V_FW_PFVF_CMD_NEQ(txq));
80133dde7c95SVishal Kulkarni c.tc_to_nexactf = cpu_to_be32(V_FW_PFVF_CMD_TC(tc) |
80143dde7c95SVishal Kulkarni V_FW_PFVF_CMD_NVI(vi) |
801556b2bdd1SGireesh Nagabhushana V_FW_PFVF_CMD_NEXACTF(nexact));
80163dde7c95SVishal Kulkarni c.r_caps_to_nethctrl = cpu_to_be32(V_FW_PFVF_CMD_R_CAPS(rcaps) |
801756b2bdd1SGireesh Nagabhushana V_FW_PFVF_CMD_WX_CAPS(wxcaps) |
801856b2bdd1SGireesh Nagabhushana V_FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl));
80193dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
802056b2bdd1SGireesh Nagabhushana }
802156b2bdd1SGireesh Nagabhushana
80223dde7c95SVishal Kulkarni /**
8023de483253SVishal Kulkarni * t4_alloc_vi_func - allocate a virtual interface
802456b2bdd1SGireesh Nagabhushana * @adap: the adapter
802556b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
802656b2bdd1SGireesh Nagabhushana * @port: physical port associated with the VI
802756b2bdd1SGireesh Nagabhushana * @pf: the PF owning the VI
802856b2bdd1SGireesh Nagabhushana * @vf: the VF owning the VI
802956b2bdd1SGireesh Nagabhushana * @nmac: number of MAC addresses needed (1 to 5)
803056b2bdd1SGireesh Nagabhushana * @mac: the MAC addresses of the VI
803156b2bdd1SGireesh Nagabhushana * @rss_size: size of RSS table slice associated with this VI
80323dde7c95SVishal Kulkarni * @portfunc: which Port Application Function MAC Address is desired
80333dde7c95SVishal Kulkarni * @idstype: Intrusion Detection Type
803456b2bdd1SGireesh Nagabhushana *
803556b2bdd1SGireesh Nagabhushana * Allocates a virtual interface for the given physical port. If @mac is
803656b2bdd1SGireesh Nagabhushana * not %NULL it contains the MAC addresses of the VI as assigned by FW.
80373dde7c95SVishal Kulkarni * If @rss_size is %NULL the VI is not assigned any RSS slice by FW.
803856b2bdd1SGireesh Nagabhushana * @mac should be large enough to hold @nmac Ethernet addresses, they are
803956b2bdd1SGireesh Nagabhushana * stored consecutively so the space needed is @nmac * 6 bytes.
804056b2bdd1SGireesh Nagabhushana * Returns a negative error number or the non-negative VI id.
804156b2bdd1SGireesh Nagabhushana */
t4_alloc_vi_func(struct adapter * adap,unsigned int mbox,unsigned int port,unsigned int pf,unsigned int vf,unsigned int nmac,u8 * mac,unsigned int * rss_size,u8 * vivld,u8 * vin,unsigned int portfunc,unsigned int idstype)80423dde7c95SVishal Kulkarni int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
8043de483253SVishal Kulkarni unsigned int port, unsigned int pf, unsigned int vf,
8044de483253SVishal Kulkarni unsigned int nmac, u8 *mac, unsigned int *rss_size,
80457e6ad469SVishal Kulkarni u8 *vivld, u8 *vin,
8046de483253SVishal Kulkarni unsigned int portfunc, unsigned int idstype)
804756b2bdd1SGireesh Nagabhushana {
804856b2bdd1SGireesh Nagabhushana int ret;
804956b2bdd1SGireesh Nagabhushana struct fw_vi_cmd c;
805056b2bdd1SGireesh Nagabhushana
80513dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
80523dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_VI_CMD) | F_FW_CMD_REQUEST |
805356b2bdd1SGireesh Nagabhushana F_FW_CMD_WRITE | F_FW_CMD_EXEC |
805456b2bdd1SGireesh Nagabhushana V_FW_VI_CMD_PFN(pf) | V_FW_VI_CMD_VFN(vf));
80553dde7c95SVishal Kulkarni c.alloc_to_len16 = cpu_to_be32(F_FW_VI_CMD_ALLOC | FW_LEN16(c));
80563dde7c95SVishal Kulkarni c.type_to_viid = cpu_to_be16(V_FW_VI_CMD_TYPE(idstype) |
8057de483253SVishal Kulkarni V_FW_VI_CMD_FUNC(portfunc));
805856b2bdd1SGireesh Nagabhushana c.portid_pkd = V_FW_VI_CMD_PORTID(port);
805956b2bdd1SGireesh Nagabhushana c.nmac = nmac - 1;
80603dde7c95SVishal Kulkarni if(!rss_size)
80613dde7c95SVishal Kulkarni c.norss_rsssize = F_FW_VI_CMD_NORSS;
806256b2bdd1SGireesh Nagabhushana
806356b2bdd1SGireesh Nagabhushana ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
80643dde7c95SVishal Kulkarni if (ret)
80653dde7c95SVishal Kulkarni return ret;
806656b2bdd1SGireesh Nagabhushana
80673dde7c95SVishal Kulkarni if (mac) {
80683dde7c95SVishal Kulkarni memcpy(mac, c.mac, sizeof(c.mac));
806956b2bdd1SGireesh Nagabhushana switch (nmac) {
807056b2bdd1SGireesh Nagabhushana case 5:
80713dde7c95SVishal Kulkarni memcpy(mac + 24, c.nmac3, sizeof(c.nmac3));
807256b2bdd1SGireesh Nagabhushana /* FALLTHRU */
807356b2bdd1SGireesh Nagabhushana case 4:
80743dde7c95SVishal Kulkarni memcpy(mac + 18, c.nmac2, sizeof(c.nmac2));
807556b2bdd1SGireesh Nagabhushana /* FALLTHRU */
807656b2bdd1SGireesh Nagabhushana case 3:
80773dde7c95SVishal Kulkarni memcpy(mac + 12, c.nmac1, sizeof(c.nmac1));
807856b2bdd1SGireesh Nagabhushana /* FALLTHRU */
807956b2bdd1SGireesh Nagabhushana case 2:
80803dde7c95SVishal Kulkarni memcpy(mac + 6, c.nmac0, sizeof(c.nmac0));
808156b2bdd1SGireesh Nagabhushana }
808256b2bdd1SGireesh Nagabhushana }
80833dde7c95SVishal Kulkarni if (rss_size)
80843dde7c95SVishal Kulkarni *rss_size = G_FW_VI_CMD_RSSSIZE(be16_to_cpu(c.norss_rsssize));
80857e6ad469SVishal Kulkarni
80867e6ad469SVishal Kulkarni if (vivld)
80877e6ad469SVishal Kulkarni *vivld = G_FW_VI_CMD_VFVLD(be32_to_cpu(c.alloc_to_len16));
80887e6ad469SVishal Kulkarni
80897e6ad469SVishal Kulkarni if (vin)
80907e6ad469SVishal Kulkarni *vin = G_FW_VI_CMD_VIN(be32_to_cpu(c.alloc_to_len16));
80917e6ad469SVishal Kulkarni
80923dde7c95SVishal Kulkarni return G_FW_VI_CMD_VIID(be16_to_cpu(c.type_to_viid));
8093de483253SVishal Kulkarni }
8094de483253SVishal Kulkarni
80953dde7c95SVishal Kulkarni /**
8096de483253SVishal Kulkarni * t4_alloc_vi - allocate an [Ethernet Function] virtual interface
8097de483253SVishal Kulkarni * @adap: the adapter
8098de483253SVishal Kulkarni * @mbox: mailbox to use for the FW command
8099de483253SVishal Kulkarni * @port: physical port associated with the VI
8100de483253SVishal Kulkarni * @pf: the PF owning the VI
8101de483253SVishal Kulkarni * @vf: the VF owning the VI
8102de483253SVishal Kulkarni * @nmac: number of MAC addresses needed (1 to 5)
8103de483253SVishal Kulkarni * @mac: the MAC addresses of the VI
8104de483253SVishal Kulkarni * @rss_size: size of RSS table slice associated with this VI
8105de483253SVishal Kulkarni *
8106de483253SVishal Kulkarni * backwards compatible and convieniance routine to allocate a Virtual
8107de483253SVishal Kulkarni * Interface with a Ethernet Port Application Function and Intrustion
8108de483253SVishal Kulkarni * Detection System disabled.
8109de483253SVishal Kulkarni */
t4_alloc_vi(struct adapter * adap,unsigned int mbox,unsigned int port,unsigned int pf,unsigned int vf,unsigned int nmac,u8 * mac,unsigned int * rss_size,u8 * vivld,u8 * vin)81103dde7c95SVishal Kulkarni int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
8111de483253SVishal Kulkarni unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
81127e6ad469SVishal Kulkarni unsigned int *rss_size, u8 *vivld, u8 *vin)
8113de483253SVishal Kulkarni {
8114de483253SVishal Kulkarni return t4_alloc_vi_func(adap, mbox, port, pf, vf, nmac, mac, rss_size,
81157e6ad469SVishal Kulkarni vivld, vin, FW_VI_FUNC_ETH, 0);
811656b2bdd1SGireesh Nagabhushana }
811756b2bdd1SGireesh Nagabhushana
81183dde7c95SVishal Kulkarni
81193dde7c95SVishal Kulkarni /**
812056b2bdd1SGireesh Nagabhushana * t4_free_vi - free a virtual interface
812156b2bdd1SGireesh Nagabhushana * @adap: the adapter
812256b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
812356b2bdd1SGireesh Nagabhushana * @pf: the PF owning the VI
812456b2bdd1SGireesh Nagabhushana * @vf: the VF owning the VI
812556b2bdd1SGireesh Nagabhushana * @viid: virtual interface identifiler
812656b2bdd1SGireesh Nagabhushana *
812756b2bdd1SGireesh Nagabhushana * Free a previously allocated virtual interface.
812856b2bdd1SGireesh Nagabhushana */
t4_free_vi(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int viid)81293dde7c95SVishal Kulkarni int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
813056b2bdd1SGireesh Nagabhushana unsigned int vf, unsigned int viid)
813156b2bdd1SGireesh Nagabhushana {
813256b2bdd1SGireesh Nagabhushana struct fw_vi_cmd c;
813356b2bdd1SGireesh Nagabhushana
81343dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
81353dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_VI_CMD) |
813656b2bdd1SGireesh Nagabhushana F_FW_CMD_REQUEST |
813756b2bdd1SGireesh Nagabhushana F_FW_CMD_EXEC |
813856b2bdd1SGireesh Nagabhushana V_FW_VI_CMD_PFN(pf) |
813956b2bdd1SGireesh Nagabhushana V_FW_VI_CMD_VFN(vf));
81403dde7c95SVishal Kulkarni c.alloc_to_len16 = cpu_to_be32(F_FW_VI_CMD_FREE | FW_LEN16(c));
81413dde7c95SVishal Kulkarni c.type_to_viid = cpu_to_be16(V_FW_VI_CMD_VIID(viid));
814256b2bdd1SGireesh Nagabhushana
81433dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
814456b2bdd1SGireesh Nagabhushana }
814556b2bdd1SGireesh Nagabhushana
81463dde7c95SVishal Kulkarni /**
814756b2bdd1SGireesh Nagabhushana * t4_set_rxmode - set Rx properties of a virtual interface
814856b2bdd1SGireesh Nagabhushana * @adap: the adapter
814956b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
815056b2bdd1SGireesh Nagabhushana * @viid: the VI id
815156b2bdd1SGireesh Nagabhushana * @mtu: the new MTU or -1
815256b2bdd1SGireesh Nagabhushana * @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change
815356b2bdd1SGireesh Nagabhushana * @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change
815456b2bdd1SGireesh Nagabhushana * @bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change
81553dde7c95SVishal Kulkarni * @vlanex: 1 to enable HW VLAN extraction, 0 to disable it, -1 no change
815656b2bdd1SGireesh Nagabhushana * @sleep_ok: if true we may sleep while awaiting command completion
815756b2bdd1SGireesh Nagabhushana *
815856b2bdd1SGireesh Nagabhushana * Sets Rx properties of a virtual interface.
815956b2bdd1SGireesh Nagabhushana */
t4_set_rxmode(struct adapter * adap,unsigned int mbox,unsigned int viid,int mtu,int promisc,int all_multi,int bcast,int vlanex,bool sleep_ok)81603dde7c95SVishal Kulkarni int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
81613dde7c95SVishal Kulkarni int mtu, int promisc, int all_multi, int bcast, int vlanex,
81623dde7c95SVishal Kulkarni bool sleep_ok)
816356b2bdd1SGireesh Nagabhushana {
816456b2bdd1SGireesh Nagabhushana struct fw_vi_rxmode_cmd c;
816556b2bdd1SGireesh Nagabhushana
816656b2bdd1SGireesh Nagabhushana /* convert to FW values */
816756b2bdd1SGireesh Nagabhushana if (mtu < 0)
816856b2bdd1SGireesh Nagabhushana mtu = M_FW_VI_RXMODE_CMD_MTU;
816956b2bdd1SGireesh Nagabhushana if (promisc < 0)
817056b2bdd1SGireesh Nagabhushana promisc = M_FW_VI_RXMODE_CMD_PROMISCEN;
817156b2bdd1SGireesh Nagabhushana if (all_multi < 0)
817256b2bdd1SGireesh Nagabhushana all_multi = M_FW_VI_RXMODE_CMD_ALLMULTIEN;
817356b2bdd1SGireesh Nagabhushana if (bcast < 0)
817456b2bdd1SGireesh Nagabhushana bcast = M_FW_VI_RXMODE_CMD_BROADCASTEN;
817556b2bdd1SGireesh Nagabhushana if (vlanex < 0)
817656b2bdd1SGireesh Nagabhushana vlanex = M_FW_VI_RXMODE_CMD_VLANEXEN;
817756b2bdd1SGireesh Nagabhushana
81783dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
81793dde7c95SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_RXMODE_CMD) |
81803dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
81813dde7c95SVishal Kulkarni V_FW_VI_RXMODE_CMD_VIID(viid));
81823dde7c95SVishal Kulkarni c.retval_len16 = cpu_to_be32(FW_LEN16(c));
81833dde7c95SVishal Kulkarni c.mtu_to_vlanexen =
81843dde7c95SVishal Kulkarni cpu_to_be32(V_FW_VI_RXMODE_CMD_MTU(mtu) |
818556b2bdd1SGireesh Nagabhushana V_FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
818656b2bdd1SGireesh Nagabhushana V_FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
818756b2bdd1SGireesh Nagabhushana V_FW_VI_RXMODE_CMD_BROADCASTEN(bcast) |
818856b2bdd1SGireesh Nagabhushana V_FW_VI_RXMODE_CMD_VLANEXEN(vlanex));
81893dde7c95SVishal Kulkarni return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
819056b2bdd1SGireesh Nagabhushana }
819156b2bdd1SGireesh Nagabhushana
81923dde7c95SVishal Kulkarni /**
81937e6ad469SVishal Kulkarni * t4_alloc_encap_mac_filt - Adds a mac entry in mps tcam with VNI support
81947e6ad469SVishal Kulkarni * @adap: the adapter
81957e6ad469SVishal Kulkarni * @viid: the VI id
81967e6ad469SVishal Kulkarni * @mac: the MAC address
81977e6ad469SVishal Kulkarni * @mask: the mask
81987e6ad469SVishal Kulkarni * @vni: the VNI id for the tunnel protocol
81997e6ad469SVishal Kulkarni * @vni_mask: mask for the VNI id
82007e6ad469SVishal Kulkarni * @dip_hit: to enable DIP match for the MPS entry
82017e6ad469SVishal Kulkarni * @lookup_type: MAC address for inner (1) or outer (0) header
82027e6ad469SVishal Kulkarni * @sleep_ok: call is allowed to sleep
82037e6ad469SVishal Kulkarni *
82047e6ad469SVishal Kulkarni * Allocates an MPS entry with specified MAC address and VNI value.
82057e6ad469SVishal Kulkarni *
82067e6ad469SVishal Kulkarni * Returns a negative error number or the allocated index for this mac.
82077e6ad469SVishal Kulkarni */
t4_alloc_encap_mac_filt(struct adapter * adap,unsigned int viid,const u8 * addr,const u8 * mask,unsigned int vni,unsigned int vni_mask,u8 dip_hit,u8 lookup_type,bool sleep_ok)82087e6ad469SVishal Kulkarni int t4_alloc_encap_mac_filt(struct adapter *adap, unsigned int viid,
82097e6ad469SVishal Kulkarni const u8 *addr, const u8 *mask, unsigned int vni,
82107e6ad469SVishal Kulkarni unsigned int vni_mask, u8 dip_hit, u8 lookup_type,
82117e6ad469SVishal Kulkarni bool sleep_ok)
82127e6ad469SVishal Kulkarni {
82137e6ad469SVishal Kulkarni struct fw_vi_mac_cmd c;
82147e6ad469SVishal Kulkarni struct fw_vi_mac_vni *p = c.u.exact_vni;
82157e6ad469SVishal Kulkarni int ret = 0;
82167e6ad469SVishal Kulkarni u32 val;
82177e6ad469SVishal Kulkarni
82187e6ad469SVishal Kulkarni memset(&c, 0, sizeof(c));
82197e6ad469SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
82207e6ad469SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
82217e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_VIID(viid));
82227e6ad469SVishal Kulkarni val = V_FW_CMD_LEN16(1) |
82237e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_EXACTMAC_VNI);
82247e6ad469SVishal Kulkarni c.freemacs_to_len16 = cpu_to_be32(val);
82257e6ad469SVishal Kulkarni p->valid_to_idx = cpu_to_be16(F_FW_VI_MAC_CMD_VALID |
82267e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
82277e6ad469SVishal Kulkarni memcpy(p->macaddr, addr, sizeof(p->macaddr));
82287e6ad469SVishal Kulkarni memcpy(p->macaddr_mask, mask, sizeof(p->macaddr_mask));
82297e6ad469SVishal Kulkarni
82307e6ad469SVishal Kulkarni p->lookup_type_to_vni = cpu_to_be32(V_FW_VI_MAC_CMD_VNI(vni) |
82317e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_DIP_HIT(dip_hit) |
82327e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_LOOKUP_TYPE(lookup_type));
82337e6ad469SVishal Kulkarni p->vni_mask_pkd = cpu_to_be32(V_FW_VI_MAC_CMD_VNI_MASK(vni_mask));
82347e6ad469SVishal Kulkarni
82357e6ad469SVishal Kulkarni ret = t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, sleep_ok);
82367e6ad469SVishal Kulkarni if (ret == 0)
82377e6ad469SVishal Kulkarni ret = G_FW_VI_MAC_CMD_IDX(be16_to_cpu(p->valid_to_idx));
82387e6ad469SVishal Kulkarni return ret;
82397e6ad469SVishal Kulkarni }
82407e6ad469SVishal Kulkarni
82417e6ad469SVishal Kulkarni /**
82423dde7c95SVishal Kulkarni * t4_alloc_raw_mac_filt - Adds a mac entry in mps tcam
82433dde7c95SVishal Kulkarni * @adap: the adapter
82443dde7c95SVishal Kulkarni * @viid: the VI id
82453dde7c95SVishal Kulkarni * @mac: the MAC address
82463dde7c95SVishal Kulkarni * @mask: the mask
82473dde7c95SVishal Kulkarni * @idx: index at which to add this entry
82487e6ad469SVishal Kulkarni * @port_id: the port index
82493dde7c95SVishal Kulkarni * @lookup_type: MAC address for inner (1) or outer (0) header
82503dde7c95SVishal Kulkarni * @sleep_ok: call is allowed to sleep
82513dde7c95SVishal Kulkarni *
82523dde7c95SVishal Kulkarni * Adds the mac entry at the specified index using raw mac interface.
82533dde7c95SVishal Kulkarni *
82543dde7c95SVishal Kulkarni * Returns a negative error number or the allocated index for this mac.
82553dde7c95SVishal Kulkarni */
t4_alloc_raw_mac_filt(struct adapter * adap,unsigned int viid,const u8 * addr,const u8 * mask,unsigned int idx,u8 lookup_type,u8 port_id,bool sleep_ok)82563dde7c95SVishal Kulkarni int t4_alloc_raw_mac_filt(struct adapter *adap, unsigned int viid,
82573dde7c95SVishal Kulkarni const u8 *addr, const u8 *mask, unsigned int idx,
82587e6ad469SVishal Kulkarni u8 lookup_type, u8 port_id, bool sleep_ok)
82593dde7c95SVishal Kulkarni {
82603dde7c95SVishal Kulkarni int ret = 0;
82613dde7c95SVishal Kulkarni struct fw_vi_mac_cmd c;
82623dde7c95SVishal Kulkarni struct fw_vi_mac_raw *p = &c.u.raw;
82633dde7c95SVishal Kulkarni u32 val;
82643dde7c95SVishal Kulkarni
82653dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
82663dde7c95SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
82673dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
82683dde7c95SVishal Kulkarni V_FW_VI_MAC_CMD_VIID(viid));
82693dde7c95SVishal Kulkarni val = V_FW_CMD_LEN16(1) |
82703dde7c95SVishal Kulkarni V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_RAW);
82713dde7c95SVishal Kulkarni c.freemacs_to_len16 = cpu_to_be32(val);
82723dde7c95SVishal Kulkarni
82733dde7c95SVishal Kulkarni /* Specify that this is an inner mac address */
82743dde7c95SVishal Kulkarni p->raw_idx_pkd = cpu_to_be32(V_FW_VI_MAC_CMD_RAW_IDX(idx));
82753dde7c95SVishal Kulkarni
82763dde7c95SVishal Kulkarni /* Lookup Type. Outer header: 0, Inner header: 1 */
82777e6ad469SVishal Kulkarni p->data0_pkd = cpu_to_be32(V_DATALKPTYPE(lookup_type) |
82787e6ad469SVishal Kulkarni V_DATAPORTNUM(port_id));
82797e6ad469SVishal Kulkarni /* Lookup mask and port mask */
82807e6ad469SVishal Kulkarni p->data0m_pkd = cpu_to_be64(V_DATALKPTYPE(M_DATALKPTYPE) |
82817e6ad469SVishal Kulkarni V_DATAPORTNUM(M_DATAPORTNUM));
82823dde7c95SVishal Kulkarni
82833dde7c95SVishal Kulkarni /* Copy the address and the mask */
82843dde7c95SVishal Kulkarni memcpy((u8 *)&p->data1[0] + 2, addr, ETH_ALEN);
82853dde7c95SVishal Kulkarni memcpy((u8 *)&p->data1m[0] + 2, mask, ETH_ALEN);
82863dde7c95SVishal Kulkarni
82873dde7c95SVishal Kulkarni ret = t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, sleep_ok);
82883dde7c95SVishal Kulkarni if (ret == 0) {
82893dde7c95SVishal Kulkarni ret = G_FW_VI_MAC_CMD_RAW_IDX(be32_to_cpu(p->raw_idx_pkd));
82903dde7c95SVishal Kulkarni if (ret != idx)
82913dde7c95SVishal Kulkarni ret = -ENOMEM;
82923dde7c95SVishal Kulkarni }
82933dde7c95SVishal Kulkarni
82943dde7c95SVishal Kulkarni return ret;
82953dde7c95SVishal Kulkarni }
82963dde7c95SVishal Kulkarni
82973dde7c95SVishal Kulkarni /**
829856b2bdd1SGireesh Nagabhushana * t4_alloc_mac_filt - allocates exact-match filters for MAC addresses
829956b2bdd1SGireesh Nagabhushana * @adap: the adapter
830056b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
830156b2bdd1SGireesh Nagabhushana * @viid: the VI id
830256b2bdd1SGireesh Nagabhushana * @free: if true any existing filters for this VI id are first removed
830356b2bdd1SGireesh Nagabhushana * @naddr: the number of MAC addresses to allocate filters for (up to 7)
830456b2bdd1SGireesh Nagabhushana * @addr: the MAC address(es)
830556b2bdd1SGireesh Nagabhushana * @idx: where to store the index of each allocated filter
830656b2bdd1SGireesh Nagabhushana * @hash: pointer to hash address filter bitmap
830756b2bdd1SGireesh Nagabhushana * @sleep_ok: call is allowed to sleep
830856b2bdd1SGireesh Nagabhushana *
830956b2bdd1SGireesh Nagabhushana * Allocates an exact-match filter for each of the supplied addresses and
831056b2bdd1SGireesh Nagabhushana * sets it to the corresponding address. If @idx is not %NULL it should
831156b2bdd1SGireesh Nagabhushana * have at least @naddr entries, each of which will be set to the index of
831256b2bdd1SGireesh Nagabhushana * the filter allocated for the corresponding MAC address. If a filter
831356b2bdd1SGireesh Nagabhushana * could not be allocated for an address its index is set to 0xffff.
831456b2bdd1SGireesh Nagabhushana * If @hash is not %NULL addresses that fail to allocate an exact filter
831556b2bdd1SGireesh Nagabhushana * are hashed and update the hash filter bitmap pointed at by @hash.
831656b2bdd1SGireesh Nagabhushana *
831756b2bdd1SGireesh Nagabhushana * Returns a negative error number or the number of filters allocated.
831856b2bdd1SGireesh Nagabhushana */
t4_alloc_mac_filt(struct adapter * adap,unsigned int mbox,unsigned int viid,bool free,unsigned int naddr,const u8 ** addr,u16 * idx,u64 * hash,bool sleep_ok)83193dde7c95SVishal Kulkarni int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
83203dde7c95SVishal Kulkarni unsigned int viid, bool free, unsigned int naddr,
83213dde7c95SVishal Kulkarni const u8 **addr, u16 *idx, u64 *hash, bool sleep_ok)
832256b2bdd1SGireesh Nagabhushana {
832356b2bdd1SGireesh Nagabhushana int offset, ret = 0;
832456b2bdd1SGireesh Nagabhushana struct fw_vi_mac_cmd c;
832556b2bdd1SGireesh Nagabhushana unsigned int nfilters = 0;
83263dde7c95SVishal Kulkarni unsigned int max_naddr = adap->params.arch.mps_tcam_size;
832756b2bdd1SGireesh Nagabhushana unsigned int rem = naddr;
832856b2bdd1SGireesh Nagabhushana
8329de483253SVishal Kulkarni if (naddr > max_naddr)
83303dde7c95SVishal Kulkarni return -EINVAL;
833156b2bdd1SGireesh Nagabhushana
833256b2bdd1SGireesh Nagabhushana for (offset = 0; offset < naddr ; /**/) {
833356b2bdd1SGireesh Nagabhushana unsigned int fw_naddr = (rem < ARRAY_SIZE(c.u.exact)
83343dde7c95SVishal Kulkarni ? rem
83353dde7c95SVishal Kulkarni : ARRAY_SIZE(c.u.exact));
833656b2bdd1SGireesh Nagabhushana size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
833756b2bdd1SGireesh Nagabhushana u.exact[fw_naddr]), 16);
833856b2bdd1SGireesh Nagabhushana struct fw_vi_mac_exact *p;
833956b2bdd1SGireesh Nagabhushana int i;
834056b2bdd1SGireesh Nagabhushana
83413dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
83423dde7c95SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
834356b2bdd1SGireesh Nagabhushana F_FW_CMD_REQUEST |
834456b2bdd1SGireesh Nagabhushana F_FW_CMD_WRITE |
834556b2bdd1SGireesh Nagabhushana V_FW_CMD_EXEC(free) |
834656b2bdd1SGireesh Nagabhushana V_FW_VI_MAC_CMD_VIID(viid));
83473dde7c95SVishal Kulkarni c.freemacs_to_len16 = cpu_to_be32(V_FW_VI_MAC_CMD_FREEMACS(free) |
834856b2bdd1SGireesh Nagabhushana V_FW_CMD_LEN16(len16));
834956b2bdd1SGireesh Nagabhushana
835056b2bdd1SGireesh Nagabhushana for (i = 0, p = c.u.exact; i < fw_naddr; i++, p++) {
83513dde7c95SVishal Kulkarni p->valid_to_idx =
83523dde7c95SVishal Kulkarni cpu_to_be16(F_FW_VI_MAC_CMD_VALID |
835356b2bdd1SGireesh Nagabhushana V_FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
83543dde7c95SVishal Kulkarni memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
835556b2bdd1SGireesh Nagabhushana }
835656b2bdd1SGireesh Nagabhushana
835756b2bdd1SGireesh Nagabhushana /*
835856b2bdd1SGireesh Nagabhushana * It's okay if we run out of space in our MAC address arena.
835956b2bdd1SGireesh Nagabhushana * Some of the addresses we submit may get stored so we need
836056b2bdd1SGireesh Nagabhushana * to run through the reply to see what the results were ...
836156b2bdd1SGireesh Nagabhushana */
836256b2bdd1SGireesh Nagabhushana ret = t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), &c, sleep_ok);
836356b2bdd1SGireesh Nagabhushana if (ret && ret != -FW_ENOMEM)
836456b2bdd1SGireesh Nagabhushana break;
836556b2bdd1SGireesh Nagabhushana
836656b2bdd1SGireesh Nagabhushana for (i = 0, p = c.u.exact; i < fw_naddr; i++, p++) {
83673dde7c95SVishal Kulkarni u16 index = G_FW_VI_MAC_CMD_IDX(
83683dde7c95SVishal Kulkarni be16_to_cpu(p->valid_to_idx));
836956b2bdd1SGireesh Nagabhushana
83703dde7c95SVishal Kulkarni if (idx)
83713dde7c95SVishal Kulkarni idx[offset+i] = (index >= max_naddr
83723dde7c95SVishal Kulkarni ? 0xffff
83733dde7c95SVishal Kulkarni : index);
8374de483253SVishal Kulkarni if (index < max_naddr)
837556b2bdd1SGireesh Nagabhushana nfilters++;
83763dde7c95SVishal Kulkarni else if (hash)
83773dde7c95SVishal Kulkarni *hash |= (1ULL << hash_mac_addr(addr[offset+i]));
837856b2bdd1SGireesh Nagabhushana }
837956b2bdd1SGireesh Nagabhushana
838056b2bdd1SGireesh Nagabhushana free = false;
838156b2bdd1SGireesh Nagabhushana offset += fw_naddr;
838256b2bdd1SGireesh Nagabhushana rem -= fw_naddr;
838356b2bdd1SGireesh Nagabhushana }
838456b2bdd1SGireesh Nagabhushana
838556b2bdd1SGireesh Nagabhushana if (ret == 0 || ret == -FW_ENOMEM)
838656b2bdd1SGireesh Nagabhushana ret = nfilters;
83873dde7c95SVishal Kulkarni return ret;
838856b2bdd1SGireesh Nagabhushana }
838956b2bdd1SGireesh Nagabhushana
83903dde7c95SVishal Kulkarni /**
83917e6ad469SVishal Kulkarni * t4_free_encap_mac_filt - frees MPS entry at given index
83927e6ad469SVishal Kulkarni * @adap: the adapter
83937e6ad469SVishal Kulkarni * @viid: the VI id
83947e6ad469SVishal Kulkarni * @idx: index of MPS entry to be freed
83957e6ad469SVishal Kulkarni * @sleep_ok: call is allowed to sleep
83967e6ad469SVishal Kulkarni *
83977e6ad469SVishal Kulkarni * Frees the MPS entry at supplied index
83987e6ad469SVishal Kulkarni *
83997e6ad469SVishal Kulkarni * Returns a negative error number or zero on success
84007e6ad469SVishal Kulkarni */
t4_free_encap_mac_filt(struct adapter * adap,unsigned int viid,int idx,bool sleep_ok)84017e6ad469SVishal Kulkarni int t4_free_encap_mac_filt(struct adapter *adap, unsigned int viid,
84027e6ad469SVishal Kulkarni int idx, bool sleep_ok)
84037e6ad469SVishal Kulkarni {
84047e6ad469SVishal Kulkarni struct fw_vi_mac_exact *p;
84057e6ad469SVishal Kulkarni struct fw_vi_mac_cmd c;
84067e6ad469SVishal Kulkarni u8 addr[] = {0,0,0,0,0,0};
84077e6ad469SVishal Kulkarni int ret = 0;
84087e6ad469SVishal Kulkarni u32 exact;
84097e6ad469SVishal Kulkarni
84107e6ad469SVishal Kulkarni memset(&c, 0, sizeof(c));
84117e6ad469SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
84127e6ad469SVishal Kulkarni F_FW_CMD_REQUEST |
84137e6ad469SVishal Kulkarni F_FW_CMD_WRITE |
84147e6ad469SVishal Kulkarni V_FW_CMD_EXEC(0) |
84157e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_VIID(viid));
84167e6ad469SVishal Kulkarni exact = V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_EXACTMAC);
84177e6ad469SVishal Kulkarni c.freemacs_to_len16 = cpu_to_be32(V_FW_VI_MAC_CMD_FREEMACS(0) |
84187e6ad469SVishal Kulkarni exact |
84197e6ad469SVishal Kulkarni V_FW_CMD_LEN16(1));
84207e6ad469SVishal Kulkarni p = c.u.exact;
84217e6ad469SVishal Kulkarni p->valid_to_idx = cpu_to_be16(F_FW_VI_MAC_CMD_VALID |
84227e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_IDX(idx));
84237e6ad469SVishal Kulkarni memcpy(p->macaddr, addr, sizeof(p->macaddr));
84247e6ad469SVishal Kulkarni
84257e6ad469SVishal Kulkarni ret = t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, sleep_ok);
84267e6ad469SVishal Kulkarni return ret;
84277e6ad469SVishal Kulkarni }
84287e6ad469SVishal Kulkarni
84297e6ad469SVishal Kulkarni /**
84307e6ad469SVishal Kulkarni * t4_free_raw_mac_filt - Frees a raw mac entry in mps tcam
84317e6ad469SVishal Kulkarni * @adap: the adapter
84327e6ad469SVishal Kulkarni * @viid: the VI id
84337e6ad469SVishal Kulkarni * @addr: the MAC address
84347e6ad469SVishal Kulkarni * @mask: the mask
84357e6ad469SVishal Kulkarni * @idx: index of the entry in mps tcam
84367e6ad469SVishal Kulkarni * @lookup_type: MAC address for inner (1) or outer (0) header
84377e6ad469SVishal Kulkarni * @port_id: the port index
84387e6ad469SVishal Kulkarni * @sleep_ok: call is allowed to sleep
84397e6ad469SVishal Kulkarni *
84407e6ad469SVishal Kulkarni * Removes the mac entry at the specified index using raw mac interface.
84417e6ad469SVishal Kulkarni *
84427e6ad469SVishal Kulkarni * Returns a negative error number on failure.
84437e6ad469SVishal Kulkarni */
t4_free_raw_mac_filt(struct adapter * adap,unsigned int viid,const u8 * addr,const u8 * mask,unsigned int idx,u8 lookup_type,u8 port_id,bool sleep_ok)84447e6ad469SVishal Kulkarni int t4_free_raw_mac_filt(struct adapter *adap, unsigned int viid,
84457e6ad469SVishal Kulkarni const u8 *addr, const u8 *mask, unsigned int idx,
84467e6ad469SVishal Kulkarni u8 lookup_type, u8 port_id, bool sleep_ok)
84477e6ad469SVishal Kulkarni {
84487e6ad469SVishal Kulkarni struct fw_vi_mac_cmd c;
84497e6ad469SVishal Kulkarni struct fw_vi_mac_raw *p = &c.u.raw;
84507e6ad469SVishal Kulkarni u32 raw;
84517e6ad469SVishal Kulkarni
84527e6ad469SVishal Kulkarni memset(&c, 0, sizeof(c));
84537e6ad469SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
84547e6ad469SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
84557e6ad469SVishal Kulkarni V_FW_CMD_EXEC(0) |
84567e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_VIID(viid));
84577e6ad469SVishal Kulkarni raw = V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_RAW);
84587e6ad469SVishal Kulkarni c.freemacs_to_len16 = cpu_to_be32(V_FW_VI_MAC_CMD_FREEMACS(0) |
84597e6ad469SVishal Kulkarni raw |
84607e6ad469SVishal Kulkarni V_FW_CMD_LEN16(1));
84617e6ad469SVishal Kulkarni
84627e6ad469SVishal Kulkarni p->raw_idx_pkd = cpu_to_be32(V_FW_VI_MAC_CMD_RAW_IDX(idx) |
84637e6ad469SVishal Kulkarni FW_VI_MAC_ID_BASED_FREE);
84647e6ad469SVishal Kulkarni
84657e6ad469SVishal Kulkarni /* Lookup Type. Outer header: 0, Inner header: 1 */
84667e6ad469SVishal Kulkarni p->data0_pkd = cpu_to_be32(V_DATALKPTYPE(lookup_type) |
84677e6ad469SVishal Kulkarni V_DATAPORTNUM(port_id));
84687e6ad469SVishal Kulkarni /* Lookup mask and port mask */
84697e6ad469SVishal Kulkarni p->data0m_pkd = cpu_to_be64(V_DATALKPTYPE(M_DATALKPTYPE) |
84707e6ad469SVishal Kulkarni V_DATAPORTNUM(M_DATAPORTNUM));
84717e6ad469SVishal Kulkarni
84727e6ad469SVishal Kulkarni /* Copy the address and the mask */
84737e6ad469SVishal Kulkarni memcpy((u8 *)&p->data1[0] + 2, addr, ETH_ALEN);
84747e6ad469SVishal Kulkarni memcpy((u8 *)&p->data1m[0] + 2, mask, ETH_ALEN);
84757e6ad469SVishal Kulkarni
84767e6ad469SVishal Kulkarni return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, sleep_ok);
84777e6ad469SVishal Kulkarni }
84787e6ad469SVishal Kulkarni
84797e6ad469SVishal Kulkarni /**
84803dde7c95SVishal Kulkarni * t4_free_mac_filt - frees exact-match filters of given MAC addresses
84813dde7c95SVishal Kulkarni * @adap: the adapter
84823dde7c95SVishal Kulkarni * @mbox: mailbox to use for the FW command
84833dde7c95SVishal Kulkarni * @viid: the VI id
84843dde7c95SVishal Kulkarni * @naddr: the number of MAC addresses to allocate filters for (up to 7)
84853dde7c95SVishal Kulkarni * @addr: the MAC address(es)
84863dde7c95SVishal Kulkarni * @sleep_ok: call is allowed to sleep
84873dde7c95SVishal Kulkarni *
84883dde7c95SVishal Kulkarni * Frees the exact-match filter for each of the supplied addresses
84893dde7c95SVishal Kulkarni *
84903dde7c95SVishal Kulkarni * Returns a negative error number or the number of filters freed.
84913dde7c95SVishal Kulkarni */
t4_free_mac_filt(struct adapter * adap,unsigned int mbox,unsigned int viid,unsigned int naddr,const u8 ** addr,bool sleep_ok)84923dde7c95SVishal Kulkarni int t4_free_mac_filt(struct adapter *adap, unsigned int mbox,
84933dde7c95SVishal Kulkarni unsigned int viid, unsigned int naddr,
84943dde7c95SVishal Kulkarni const u8 **addr, bool sleep_ok)
84953dde7c95SVishal Kulkarni {
84963dde7c95SVishal Kulkarni int offset, ret = 0;
84973dde7c95SVishal Kulkarni struct fw_vi_mac_cmd c;
84983dde7c95SVishal Kulkarni unsigned int nfilters = 0;
84993dde7c95SVishal Kulkarni unsigned int max_naddr = is_t4(adap->params.chip) ?
85003dde7c95SVishal Kulkarni NUM_MPS_CLS_SRAM_L_INSTANCES :
85013dde7c95SVishal Kulkarni NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
85023dde7c95SVishal Kulkarni unsigned int rem = naddr;
85033dde7c95SVishal Kulkarni
85043dde7c95SVishal Kulkarni if (naddr > max_naddr)
85053dde7c95SVishal Kulkarni return -EINVAL;
85063dde7c95SVishal Kulkarni
85073dde7c95SVishal Kulkarni for (offset = 0; offset < (int)naddr ; /**/) {
85083dde7c95SVishal Kulkarni unsigned int fw_naddr = (rem < ARRAY_SIZE(c.u.exact)
85093dde7c95SVishal Kulkarni ? rem
85103dde7c95SVishal Kulkarni : ARRAY_SIZE(c.u.exact));
85113dde7c95SVishal Kulkarni size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
85123dde7c95SVishal Kulkarni u.exact[fw_naddr]), 16);
85133dde7c95SVishal Kulkarni struct fw_vi_mac_exact *p;
85143dde7c95SVishal Kulkarni int i;
85153dde7c95SVishal Kulkarni
85163dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
85173dde7c95SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
85183dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
85193dde7c95SVishal Kulkarni F_FW_CMD_WRITE |
85203dde7c95SVishal Kulkarni V_FW_CMD_EXEC(0) |
85213dde7c95SVishal Kulkarni V_FW_VI_MAC_CMD_VIID(viid));
85223dde7c95SVishal Kulkarni c.freemacs_to_len16 =
85233dde7c95SVishal Kulkarni cpu_to_be32(V_FW_VI_MAC_CMD_FREEMACS(0) |
85243dde7c95SVishal Kulkarni V_FW_CMD_LEN16(len16));
85253dde7c95SVishal Kulkarni
85263dde7c95SVishal Kulkarni for (i = 0, p = c.u.exact; i < (int)fw_naddr; i++, p++) {
85273dde7c95SVishal Kulkarni p->valid_to_idx = cpu_to_be16(
85283dde7c95SVishal Kulkarni F_FW_VI_MAC_CMD_VALID |
85293dde7c95SVishal Kulkarni V_FW_VI_MAC_CMD_IDX(FW_VI_MAC_MAC_BASED_FREE));
85303dde7c95SVishal Kulkarni memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
85313dde7c95SVishal Kulkarni }
85323dde7c95SVishal Kulkarni
85333dde7c95SVishal Kulkarni ret = t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), &c, sleep_ok);
85343dde7c95SVishal Kulkarni if (ret)
85353dde7c95SVishal Kulkarni break;
85363dde7c95SVishal Kulkarni
85373dde7c95SVishal Kulkarni for (i = 0, p = c.u.exact; i < fw_naddr; i++, p++) {
85383dde7c95SVishal Kulkarni u16 index = G_FW_VI_MAC_CMD_IDX(
85393dde7c95SVishal Kulkarni be16_to_cpu(p->valid_to_idx));
85403dde7c95SVishal Kulkarni
85413dde7c95SVishal Kulkarni if (index < max_naddr)
85423dde7c95SVishal Kulkarni nfilters++;
85433dde7c95SVishal Kulkarni }
85443dde7c95SVishal Kulkarni
85453dde7c95SVishal Kulkarni offset += fw_naddr;
85463dde7c95SVishal Kulkarni rem -= fw_naddr;
85473dde7c95SVishal Kulkarni }
85483dde7c95SVishal Kulkarni
85493dde7c95SVishal Kulkarni if (ret == 0)
85503dde7c95SVishal Kulkarni ret = nfilters;
85513dde7c95SVishal Kulkarni return ret;
85523dde7c95SVishal Kulkarni }
85533dde7c95SVishal Kulkarni
85543dde7c95SVishal Kulkarni /**
855556b2bdd1SGireesh Nagabhushana * t4_change_mac - modifies the exact-match filter for a MAC address
855656b2bdd1SGireesh Nagabhushana * @adap: the adapter
855756b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
855856b2bdd1SGireesh Nagabhushana * @viid: the VI id
855956b2bdd1SGireesh Nagabhushana * @idx: index of existing filter for old value of MAC address, or -1
856056b2bdd1SGireesh Nagabhushana * @addr: the new MAC address value
856156b2bdd1SGireesh Nagabhushana * @persist: whether a new MAC allocation should be persistent
856256b2bdd1SGireesh Nagabhushana * @add_smt: if true also add the address to the HW SMT
856356b2bdd1SGireesh Nagabhushana *
856456b2bdd1SGireesh Nagabhushana * Modifies an exact-match filter and sets it to the new MAC address if
856556b2bdd1SGireesh Nagabhushana * @idx >= 0, or adds the MAC address to a new filter if @idx < 0. In the
856656b2bdd1SGireesh Nagabhushana * latter case the address is added persistently if @persist is %true.
856756b2bdd1SGireesh Nagabhushana *
856856b2bdd1SGireesh Nagabhushana * Note that in general it is not possible to modify the value of a given
856956b2bdd1SGireesh Nagabhushana * filter so the generic way to modify an address filter is to free the one
857056b2bdd1SGireesh Nagabhushana * being used by the old address value and allocate a new filter for the
857156b2bdd1SGireesh Nagabhushana * new address value.
857256b2bdd1SGireesh Nagabhushana *
857356b2bdd1SGireesh Nagabhushana * Returns a negative error number or the index of the filter with the new
857456b2bdd1SGireesh Nagabhushana * MAC value. Note that this index may differ from @idx.
857556b2bdd1SGireesh Nagabhushana */
t4_change_mac(struct adapter * adap,unsigned int mbox,unsigned int viid,int idx,const u8 * addr,bool persist,u8 * smt_idx)85763dde7c95SVishal Kulkarni int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
85777e6ad469SVishal Kulkarni int idx, const u8 *addr, bool persist, u8 *smt_idx)
857856b2bdd1SGireesh Nagabhushana {
85797e6ad469SVishal Kulkarni /* This will add this mac address to the destination TCAM region */
85807e6ad469SVishal Kulkarni return t4_add_mac(adap, mbox, viid, idx, addr, persist, smt_idx, 0);
858156b2bdd1SGireesh Nagabhushana }
858256b2bdd1SGireesh Nagabhushana
85833dde7c95SVishal Kulkarni /**
858456b2bdd1SGireesh Nagabhushana * t4_set_addr_hash - program the MAC inexact-match hash filter
858556b2bdd1SGireesh Nagabhushana * @adap: the adapter
858656b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
858756b2bdd1SGireesh Nagabhushana * @viid: the VI id
858856b2bdd1SGireesh Nagabhushana * @ucast: whether the hash filter should also match unicast addresses
858956b2bdd1SGireesh Nagabhushana * @vec: the value to be written to the hash filter
859056b2bdd1SGireesh Nagabhushana * @sleep_ok: call is allowed to sleep
859156b2bdd1SGireesh Nagabhushana *
859256b2bdd1SGireesh Nagabhushana * Sets the 64-bit inexact-match hash filter for a virtual interface.
859356b2bdd1SGireesh Nagabhushana */
t4_set_addr_hash(struct adapter * adap,unsigned int mbox,unsigned int viid,bool ucast,u64 vec,bool sleep_ok)85943dde7c95SVishal Kulkarni int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
859556b2bdd1SGireesh Nagabhushana bool ucast, u64 vec, bool sleep_ok)
859656b2bdd1SGireesh Nagabhushana {
859756b2bdd1SGireesh Nagabhushana struct fw_vi_mac_cmd c;
85983dde7c95SVishal Kulkarni u32 val;
859956b2bdd1SGireesh Nagabhushana
86003dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
86013dde7c95SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
86023dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
86033dde7c95SVishal Kulkarni V_FW_VI_ENABLE_CMD_VIID(viid));
86043dde7c95SVishal Kulkarni val = V_FW_VI_MAC_CMD_ENTRY_TYPE(FW_VI_MAC_TYPE_HASHVEC) |
86053dde7c95SVishal Kulkarni V_FW_VI_MAC_CMD_HASHUNIEN(ucast) | V_FW_CMD_LEN16(1);
86063dde7c95SVishal Kulkarni c.freemacs_to_len16 = cpu_to_be32(val);
860756b2bdd1SGireesh Nagabhushana c.u.hash.hashvec = cpu_to_be64(vec);
86083dde7c95SVishal Kulkarni return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
860956b2bdd1SGireesh Nagabhushana }
861056b2bdd1SGireesh Nagabhushana
86113dde7c95SVishal Kulkarni /**
86123dde7c95SVishal Kulkarni * t4_enable_vi_params - enable/disable a virtual interface
86133dde7c95SVishal Kulkarni * @adap: the adapter
86143dde7c95SVishal Kulkarni * @mbox: mailbox to use for the FW command
86153dde7c95SVishal Kulkarni * @viid: the VI id
86163dde7c95SVishal Kulkarni * @rx_en: 1=enable Rx, 0=disable Rx
86173dde7c95SVishal Kulkarni * @tx_en: 1=enable Tx, 0=disable Tx
86183dde7c95SVishal Kulkarni * @dcb_en: 1=enable delivery of Data Center Bridging messages.
86193dde7c95SVishal Kulkarni *
86203dde7c95SVishal Kulkarni * Enables/disables a virtual interface. Note that setting DCB Enable
86213dde7c95SVishal Kulkarni * only makes sense when enabling a Virtual Interface ...
86223dde7c95SVishal Kulkarni */
t4_enable_vi_params(struct adapter * adap,unsigned int mbox,unsigned int viid,bool rx_en,bool tx_en,bool dcb_en)86233dde7c95SVishal Kulkarni int t4_enable_vi_params(struct adapter *adap, unsigned int mbox,
86243dde7c95SVishal Kulkarni unsigned int viid, bool rx_en, bool tx_en, bool dcb_en)
86253dde7c95SVishal Kulkarni {
86263dde7c95SVishal Kulkarni struct fw_vi_enable_cmd c;
86273dde7c95SVishal Kulkarni
86283dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
86293dde7c95SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_ENABLE_CMD) |
86303dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
86313dde7c95SVishal Kulkarni V_FW_VI_ENABLE_CMD_VIID(viid));
86323dde7c95SVishal Kulkarni c.ien_to_len16 = cpu_to_be32(V_FW_VI_ENABLE_CMD_IEN(rx_en) |
86333dde7c95SVishal Kulkarni V_FW_VI_ENABLE_CMD_EEN(tx_en) |
86343dde7c95SVishal Kulkarni V_FW_VI_ENABLE_CMD_DCB_INFO(dcb_en) |
86353dde7c95SVishal Kulkarni FW_LEN16(c));
86363dde7c95SVishal Kulkarni return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL);
86373dde7c95SVishal Kulkarni }
86383dde7c95SVishal Kulkarni
86393dde7c95SVishal Kulkarni /**
864056b2bdd1SGireesh Nagabhushana * t4_enable_vi - enable/disable a virtual interface
864156b2bdd1SGireesh Nagabhushana * @adap: the adapter
864256b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
864356b2bdd1SGireesh Nagabhushana * @viid: the VI id
864456b2bdd1SGireesh Nagabhushana * @rx_en: 1=enable Rx, 0=disable Rx
864556b2bdd1SGireesh Nagabhushana * @tx_en: 1=enable Tx, 0=disable Tx
864656b2bdd1SGireesh Nagabhushana *
86473dde7c95SVishal Kulkarni * Enables/disables a virtual interface. Note that setting DCB Enable
86483dde7c95SVishal Kulkarni * only makes sense when enabling a Virtual Interface ...
864956b2bdd1SGireesh Nagabhushana */
t4_enable_vi(struct adapter * adap,unsigned int mbox,unsigned int viid,bool rx_en,bool tx_en)86503dde7c95SVishal Kulkarni int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
865156b2bdd1SGireesh Nagabhushana bool rx_en, bool tx_en)
865256b2bdd1SGireesh Nagabhushana {
86533dde7c95SVishal Kulkarni return t4_enable_vi_params(adap, mbox, viid, rx_en, tx_en, 0);
865456b2bdd1SGireesh Nagabhushana }
865556b2bdd1SGireesh Nagabhushana
86563dde7c95SVishal Kulkarni /**
86577e6ad469SVishal Kulkarni * t4_enable_pi_params - enable/disable a Port's Virtual Interface
86587e6ad469SVishal Kulkarni * @adap: the adapter
86597e6ad469SVishal Kulkarni * @mbox: mailbox to use for the FW command
86607e6ad469SVishal Kulkarni * @pi: the Port Information structure
86617e6ad469SVishal Kulkarni * @rx_en: 1=enable Rx, 0=disable Rx
86627e6ad469SVishal Kulkarni * @tx_en: 1=enable Tx, 0=disable Tx
86637e6ad469SVishal Kulkarni * @dcb_en: 1=enable delivery of Data Center Bridging messages.
86647e6ad469SVishal Kulkarni *
86657e6ad469SVishal Kulkarni * Enables/disables a Port's Virtual Interface. Note that setting DCB
86667e6ad469SVishal Kulkarni * Enable only makes sense when enabling a Virtual Interface ...
86677e6ad469SVishal Kulkarni * If the Virtual Interface enable/disable operation is successful,
86687e6ad469SVishal Kulkarni * we notify the OS-specific code of a potential Link Status change
86697e6ad469SVishal Kulkarni * via the OS Contract API t4_os_link_changed().
86707e6ad469SVishal Kulkarni */
t4_enable_pi_params(struct adapter * adap,unsigned int mbox,struct port_info * pi,bool rx_en,bool tx_en,bool dcb_en)86717e6ad469SVishal Kulkarni int t4_enable_pi_params(struct adapter *adap, unsigned int mbox,
86727e6ad469SVishal Kulkarni struct port_info *pi,
86737e6ad469SVishal Kulkarni bool rx_en, bool tx_en, bool dcb_en)
86747e6ad469SVishal Kulkarni {
86757e6ad469SVishal Kulkarni int ret = t4_enable_vi_params(adap, mbox, pi->viid,
86767e6ad469SVishal Kulkarni rx_en, tx_en, dcb_en);
86777e6ad469SVishal Kulkarni if (ret)
86787e6ad469SVishal Kulkarni return ret;
86797e6ad469SVishal Kulkarni t4_os_link_changed(adap, pi->port_id,
86807e6ad469SVishal Kulkarni rx_en && tx_en && pi->link_cfg.link_ok);
86817e6ad469SVishal Kulkarni return 0;
86827e6ad469SVishal Kulkarni }
86837e6ad469SVishal Kulkarni
86847e6ad469SVishal Kulkarni /**
868556b2bdd1SGireesh Nagabhushana * t4_identify_port - identify a VI's port by blinking its LED
868656b2bdd1SGireesh Nagabhushana * @adap: the adapter
868756b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
868856b2bdd1SGireesh Nagabhushana * @viid: the VI id
868956b2bdd1SGireesh Nagabhushana * @nblinks: how many times to blink LED at 2.5 Hz
869056b2bdd1SGireesh Nagabhushana *
869156b2bdd1SGireesh Nagabhushana * Identifies a VI's port by blinking its LED.
869256b2bdd1SGireesh Nagabhushana */
t4_identify_port(struct adapter * adap,unsigned int mbox,unsigned int viid,unsigned int nblinks)86933dde7c95SVishal Kulkarni int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
869456b2bdd1SGireesh Nagabhushana unsigned int nblinks)
869556b2bdd1SGireesh Nagabhushana {
869656b2bdd1SGireesh Nagabhushana struct fw_vi_enable_cmd c;
869756b2bdd1SGireesh Nagabhushana
86983dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
86993dde7c95SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_ENABLE_CMD) |
87003dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
87013dde7c95SVishal Kulkarni V_FW_VI_ENABLE_CMD_VIID(viid));
87023dde7c95SVishal Kulkarni c.ien_to_len16 = cpu_to_be32(F_FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
87033dde7c95SVishal Kulkarni c.blinkdur = cpu_to_be16(nblinks);
87043dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
870556b2bdd1SGireesh Nagabhushana }
870656b2bdd1SGireesh Nagabhushana
87073dde7c95SVishal Kulkarni /**
87083dde7c95SVishal Kulkarni * t4_iq_stop - stop an ingress queue and its FLs
870956b2bdd1SGireesh Nagabhushana * @adap: the adapter
871056b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
871156b2bdd1SGireesh Nagabhushana * @pf: the PF owning the queues
871256b2bdd1SGireesh Nagabhushana * @vf: the VF owning the queues
87133dde7c95SVishal Kulkarni * @iqtype: the ingress queue type (FW_IQ_TYPE_FL_INT_CAP, etc.)
871456b2bdd1SGireesh Nagabhushana * @iqid: ingress queue id
871556b2bdd1SGireesh Nagabhushana * @fl0id: FL0 queue id or 0xffff if no attached FL0
871656b2bdd1SGireesh Nagabhushana * @fl1id: FL1 queue id or 0xffff if no attached FL1
871756b2bdd1SGireesh Nagabhushana *
87183dde7c95SVishal Kulkarni * Stops an ingress queue and its associated FLs, if any. This causes
87193dde7c95SVishal Kulkarni * any current or future data/messages destined for these queues to be
87203dde7c95SVishal Kulkarni * tossed.
872156b2bdd1SGireesh Nagabhushana */
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)87223dde7c95SVishal Kulkarni int t4_iq_stop(struct adapter *adap, unsigned int mbox, unsigned int pf,
87233dde7c95SVishal Kulkarni unsigned int vf, unsigned int iqtype, unsigned int iqid,
87243dde7c95SVishal Kulkarni unsigned int fl0id, unsigned int fl1id)
872556b2bdd1SGireesh Nagabhushana {
872656b2bdd1SGireesh Nagabhushana struct fw_iq_cmd c;
872756b2bdd1SGireesh Nagabhushana
87283dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
87293dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST |
873056b2bdd1SGireesh Nagabhushana F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(pf) |
873156b2bdd1SGireesh Nagabhushana V_FW_IQ_CMD_VFN(vf));
87323dde7c95SVishal Kulkarni c.alloc_to_len16 = cpu_to_be32(F_FW_IQ_CMD_IQSTOP | FW_LEN16(c));
87333dde7c95SVishal Kulkarni c.type_to_iqandstindex = cpu_to_be32(V_FW_IQ_CMD_TYPE(iqtype));
87343dde7c95SVishal Kulkarni c.iqid = cpu_to_be16(iqid);
87353dde7c95SVishal Kulkarni c.fl0id = cpu_to_be16(fl0id);
87363dde7c95SVishal Kulkarni c.fl1id = cpu_to_be16(fl1id);
87373dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
873856b2bdd1SGireesh Nagabhushana }
873956b2bdd1SGireesh Nagabhushana
87403dde7c95SVishal Kulkarni /**
874156b2bdd1SGireesh Nagabhushana * t4_iq_free - free an ingress queue and its FLs
874256b2bdd1SGireesh Nagabhushana * @adap: the adapter
874356b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
874456b2bdd1SGireesh Nagabhushana * @pf: the PF owning the queues
874556b2bdd1SGireesh Nagabhushana * @vf: the VF owning the queues
874656b2bdd1SGireesh Nagabhushana * @iqtype: the ingress queue type (FW_IQ_TYPE_FL_INT_CAP, etc.)
874756b2bdd1SGireesh Nagabhushana * @iqid: ingress queue id
874856b2bdd1SGireesh Nagabhushana * @fl0id: FL0 queue id or 0xffff if no attached FL0
874956b2bdd1SGireesh Nagabhushana * @fl1id: FL1 queue id or 0xffff if no attached FL1
875056b2bdd1SGireesh Nagabhushana *
875156b2bdd1SGireesh Nagabhushana * Frees an ingress queue and its associated FLs, if any.
875256b2bdd1SGireesh Nagabhushana */
t4_iq_free(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int iqtype,unsigned int iqid,unsigned int fl0id,unsigned int fl1id)87533dde7c95SVishal Kulkarni int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
87543dde7c95SVishal Kulkarni unsigned int vf, unsigned int iqtype, unsigned int iqid,
87553dde7c95SVishal Kulkarni unsigned int fl0id, unsigned int fl1id)
875656b2bdd1SGireesh Nagabhushana {
875756b2bdd1SGireesh Nagabhushana struct fw_iq_cmd c;
875856b2bdd1SGireesh Nagabhushana
87593dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
87603dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST |
876156b2bdd1SGireesh Nagabhushana F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(pf) |
876256b2bdd1SGireesh Nagabhushana V_FW_IQ_CMD_VFN(vf));
87633dde7c95SVishal Kulkarni c.alloc_to_len16 = cpu_to_be32(F_FW_IQ_CMD_FREE | FW_LEN16(c));
87643dde7c95SVishal Kulkarni c.type_to_iqandstindex = cpu_to_be32(V_FW_IQ_CMD_TYPE(iqtype));
87653dde7c95SVishal Kulkarni c.iqid = cpu_to_be16(iqid);
87663dde7c95SVishal Kulkarni c.fl0id = cpu_to_be16(fl0id);
87673dde7c95SVishal Kulkarni c.fl1id = cpu_to_be16(fl1id);
87683dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
876956b2bdd1SGireesh Nagabhushana }
877056b2bdd1SGireesh Nagabhushana
87713dde7c95SVishal Kulkarni /**
877256b2bdd1SGireesh Nagabhushana * t4_eth_eq_free - free an Ethernet egress queue
877356b2bdd1SGireesh Nagabhushana * @adap: the adapter
877456b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
877556b2bdd1SGireesh Nagabhushana * @pf: the PF owning the queue
877656b2bdd1SGireesh Nagabhushana * @vf: the VF owning the queue
877756b2bdd1SGireesh Nagabhushana * @eqid: egress queue id
877856b2bdd1SGireesh Nagabhushana *
877956b2bdd1SGireesh Nagabhushana * Frees an Ethernet egress queue.
878056b2bdd1SGireesh Nagabhushana */
t4_eth_eq_free(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int eqid)87813dde7c95SVishal Kulkarni int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
878256b2bdd1SGireesh Nagabhushana unsigned int vf, unsigned int eqid)
878356b2bdd1SGireesh Nagabhushana {
878456b2bdd1SGireesh Nagabhushana struct fw_eq_eth_cmd c;
878556b2bdd1SGireesh Nagabhushana
87863dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
87873dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_EQ_ETH_CMD) |
87883dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
87893dde7c95SVishal Kulkarni V_FW_EQ_ETH_CMD_PFN(pf) |
879056b2bdd1SGireesh Nagabhushana V_FW_EQ_ETH_CMD_VFN(vf));
87913dde7c95SVishal Kulkarni c.alloc_to_len16 = cpu_to_be32(F_FW_EQ_ETH_CMD_FREE | FW_LEN16(c));
87923dde7c95SVishal Kulkarni c.eqid_pkd = cpu_to_be32(V_FW_EQ_ETH_CMD_EQID(eqid));
87933dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
879456b2bdd1SGireesh Nagabhushana }
879556b2bdd1SGireesh Nagabhushana
87963dde7c95SVishal Kulkarni /**
879756b2bdd1SGireesh Nagabhushana * t4_ctrl_eq_free - free a control egress queue
879856b2bdd1SGireesh Nagabhushana * @adap: the adapter
879956b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
880056b2bdd1SGireesh Nagabhushana * @pf: the PF owning the queue
880156b2bdd1SGireesh Nagabhushana * @vf: the VF owning the queue
880256b2bdd1SGireesh Nagabhushana * @eqid: egress queue id
880356b2bdd1SGireesh Nagabhushana *
880456b2bdd1SGireesh Nagabhushana * Frees a control egress queue.
880556b2bdd1SGireesh Nagabhushana */
t4_ctrl_eq_free(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int eqid)88063dde7c95SVishal Kulkarni int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
880756b2bdd1SGireesh Nagabhushana unsigned int vf, unsigned int eqid)
880856b2bdd1SGireesh Nagabhushana {
880956b2bdd1SGireesh Nagabhushana struct fw_eq_ctrl_cmd c;
881056b2bdd1SGireesh Nagabhushana
88113dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
88123dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_EQ_CTRL_CMD) |
88133dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
88143dde7c95SVishal Kulkarni V_FW_EQ_CTRL_CMD_PFN(pf) |
881556b2bdd1SGireesh Nagabhushana V_FW_EQ_CTRL_CMD_VFN(vf));
88163dde7c95SVishal Kulkarni c.alloc_to_len16 = cpu_to_be32(F_FW_EQ_CTRL_CMD_FREE | FW_LEN16(c));
88173dde7c95SVishal Kulkarni c.cmpliqid_eqid = cpu_to_be32(V_FW_EQ_CTRL_CMD_EQID(eqid));
88183dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
881956b2bdd1SGireesh Nagabhushana }
882056b2bdd1SGireesh Nagabhushana
88213dde7c95SVishal Kulkarni /**
882256b2bdd1SGireesh Nagabhushana * t4_ofld_eq_free - free an offload egress queue
882356b2bdd1SGireesh Nagabhushana * @adap: the adapter
882456b2bdd1SGireesh Nagabhushana * @mbox: mailbox to use for the FW command
882556b2bdd1SGireesh Nagabhushana * @pf: the PF owning the queue
882656b2bdd1SGireesh Nagabhushana * @vf: the VF owning the queue
882756b2bdd1SGireesh Nagabhushana * @eqid: egress queue id
882856b2bdd1SGireesh Nagabhushana *
882956b2bdd1SGireesh Nagabhushana * Frees a control egress queue.
883056b2bdd1SGireesh Nagabhushana */
t4_ofld_eq_free(struct adapter * adap,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int eqid)88313dde7c95SVishal Kulkarni int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
883256b2bdd1SGireesh Nagabhushana unsigned int vf, unsigned int eqid)
883356b2bdd1SGireesh Nagabhushana {
883456b2bdd1SGireesh Nagabhushana struct fw_eq_ofld_cmd c;
883556b2bdd1SGireesh Nagabhushana
88363dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
88373dde7c95SVishal Kulkarni c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_EQ_OFLD_CMD) |
88383dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
88393dde7c95SVishal Kulkarni V_FW_EQ_OFLD_CMD_PFN(pf) |
884056b2bdd1SGireesh Nagabhushana V_FW_EQ_OFLD_CMD_VFN(vf));
88413dde7c95SVishal Kulkarni c.alloc_to_len16 = cpu_to_be32(F_FW_EQ_OFLD_CMD_FREE | FW_LEN16(c));
88423dde7c95SVishal Kulkarni c.eqid_pkd = cpu_to_be32(V_FW_EQ_OFLD_CMD_EQID(eqid));
88433dde7c95SVishal Kulkarni return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
884456b2bdd1SGireesh Nagabhushana }
884556b2bdd1SGireesh Nagabhushana
88463dde7c95SVishal Kulkarni /**
88477e6ad469SVishal Kulkarni * Return the highest speed set in the port capabilities, in Mb/s.
88483dde7c95SVishal Kulkarni */
t4_link_fwcap_to_speed(fw_port_cap32_t caps)88496feac2e3SRahul Lakkireddy unsigned int t4_link_fwcap_to_speed(fw_port_cap32_t caps)
88503dde7c95SVishal Kulkarni {
88517e6ad469SVishal Kulkarni #define TEST_SPEED_RETURN(__caps_speed, __speed) \
88527e6ad469SVishal Kulkarni do { \
88537e6ad469SVishal Kulkarni if (caps & FW_PORT_CAP32_SPEED_##__caps_speed) \
88547e6ad469SVishal Kulkarni return __speed; \
88557e6ad469SVishal Kulkarni } while (0)
88567e6ad469SVishal Kulkarni
88577e6ad469SVishal Kulkarni TEST_SPEED_RETURN(400G, 400000);
88587e6ad469SVishal Kulkarni TEST_SPEED_RETURN(200G, 200000);
88597e6ad469SVishal Kulkarni TEST_SPEED_RETURN(100G, 100000);
88607e6ad469SVishal Kulkarni TEST_SPEED_RETURN(50G, 50000);
88617e6ad469SVishal Kulkarni TEST_SPEED_RETURN(40G, 40000);
88627e6ad469SVishal Kulkarni TEST_SPEED_RETURN(25G, 25000);
88637e6ad469SVishal Kulkarni TEST_SPEED_RETURN(10G, 10000);
88647e6ad469SVishal Kulkarni TEST_SPEED_RETURN(1G, 1000);
88657e6ad469SVishal Kulkarni TEST_SPEED_RETURN(100M, 100);
88667e6ad469SVishal Kulkarni
88677e6ad469SVishal Kulkarni #undef TEST_SPEED_RETURN
88687e6ad469SVishal Kulkarni
88693dde7c95SVishal Kulkarni return 0;
88703dde7c95SVishal Kulkarni }
88713dde7c95SVishal Kulkarni
88723dde7c95SVishal Kulkarni /**
88736feac2e3SRahul Lakkireddy * t4_link_fwcap_to_fwspeed - return highest speed in Port Capabilities
88747e6ad469SVishal Kulkarni * @acaps: advertised Port Capabilities
88757e6ad469SVishal Kulkarni *
88767e6ad469SVishal Kulkarni * Get the highest speed for the port from the advertised Port
88777e6ad469SVishal Kulkarni * Capabilities. It will be either the highest speed from the list of
88787e6ad469SVishal Kulkarni * speeds or whatever user has set using ethtool.
88797e6ad469SVishal Kulkarni */
t4_link_fwcap_to_fwspeed(fw_port_cap32_t acaps)8880*ece8d794SRobert Mustacchi fw_port_cap32_t t4_link_fwcap_to_fwspeed(fw_port_cap32_t acaps)
88817e6ad469SVishal Kulkarni {
88827e6ad469SVishal Kulkarni #define TEST_SPEED_RETURN(__caps_speed) \
88837e6ad469SVishal Kulkarni do { \
88847e6ad469SVishal Kulkarni if (acaps & FW_PORT_CAP32_SPEED_##__caps_speed) \
88857e6ad469SVishal Kulkarni return FW_PORT_CAP32_SPEED_##__caps_speed; \
88867e6ad469SVishal Kulkarni } while (0)
88877e6ad469SVishal Kulkarni
88887e6ad469SVishal Kulkarni TEST_SPEED_RETURN(400G);
88897e6ad469SVishal Kulkarni TEST_SPEED_RETURN(200G);
88907e6ad469SVishal Kulkarni TEST_SPEED_RETURN(100G);
88917e6ad469SVishal Kulkarni TEST_SPEED_RETURN(50G);
88927e6ad469SVishal Kulkarni TEST_SPEED_RETURN(40G);
88937e6ad469SVishal Kulkarni TEST_SPEED_RETURN(25G);
88947e6ad469SVishal Kulkarni TEST_SPEED_RETURN(10G);
88957e6ad469SVishal Kulkarni TEST_SPEED_RETURN(1G);
88967e6ad469SVishal Kulkarni TEST_SPEED_RETURN(100M);
88977e6ad469SVishal Kulkarni
88987e6ad469SVishal Kulkarni #undef TEST_SPEED_RETURN
88997e6ad469SVishal Kulkarni
89007e6ad469SVishal Kulkarni return 0;
89017e6ad469SVishal Kulkarni }
89027e6ad469SVishal Kulkarni
89037e6ad469SVishal Kulkarni /**
89046feac2e3SRahul Lakkireddy * fwcaps16_to_caps32 - convert 16-bit Port Capabilities to 32-bits
89056feac2e3SRahul Lakkireddy * @caps16: a 16-bit Port Capabilities value
89066feac2e3SRahul Lakkireddy *
89076feac2e3SRahul Lakkireddy * Returns the equivalent 32-bit Port Capabilities value.
89086feac2e3SRahul Lakkireddy */
fwcaps16_to_caps32(fw_port_cap16_t caps16)89096feac2e3SRahul Lakkireddy static fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16)
89106feac2e3SRahul Lakkireddy {
89116feac2e3SRahul Lakkireddy fw_port_cap32_t caps32 = 0;
89126feac2e3SRahul Lakkireddy
89136feac2e3SRahul Lakkireddy #define CAP16_TO_CAP32(__cap) \
89146feac2e3SRahul Lakkireddy do { \
89156feac2e3SRahul Lakkireddy if (caps16 & FW_PORT_CAP_##__cap) \
89166feac2e3SRahul Lakkireddy caps32 |= FW_PORT_CAP32_##__cap; \
89176feac2e3SRahul Lakkireddy } while (0)
89186feac2e3SRahul Lakkireddy
89196feac2e3SRahul Lakkireddy CAP16_TO_CAP32(SPEED_100M);
89206feac2e3SRahul Lakkireddy CAP16_TO_CAP32(SPEED_1G);
89216feac2e3SRahul Lakkireddy CAP16_TO_CAP32(SPEED_25G);
89226feac2e3SRahul Lakkireddy CAP16_TO_CAP32(SPEED_10G);
89236feac2e3SRahul Lakkireddy CAP16_TO_CAP32(SPEED_40G);
89246feac2e3SRahul Lakkireddy CAP16_TO_CAP32(SPEED_100G);
89256feac2e3SRahul Lakkireddy CAP16_TO_CAP32(FC_RX);
89266feac2e3SRahul Lakkireddy CAP16_TO_CAP32(FC_TX);
89276feac2e3SRahul Lakkireddy CAP16_TO_CAP32(ANEG);
89286feac2e3SRahul Lakkireddy CAP16_TO_CAP32(FORCE_PAUSE);
89296feac2e3SRahul Lakkireddy CAP16_TO_CAP32(MDIAUTO);
89306feac2e3SRahul Lakkireddy CAP16_TO_CAP32(MDISTRAIGHT);
89316feac2e3SRahul Lakkireddy CAP16_TO_CAP32(FEC_RS);
89326feac2e3SRahul Lakkireddy CAP16_TO_CAP32(FEC_BASER_RS);
89336feac2e3SRahul Lakkireddy CAP16_TO_CAP32(802_3_PAUSE);
89346feac2e3SRahul Lakkireddy CAP16_TO_CAP32(802_3_ASM_DIR);
89356feac2e3SRahul Lakkireddy
89366feac2e3SRahul Lakkireddy #undef CAP16_TO_CAP32
89376feac2e3SRahul Lakkireddy
89386feac2e3SRahul Lakkireddy return caps32;
89396feac2e3SRahul Lakkireddy }
89406feac2e3SRahul Lakkireddy
89416feac2e3SRahul Lakkireddy /**
89426feac2e3SRahul Lakkireddy * fwcaps32_to_caps16 - convert 32-bit Port Capabilities to 16-bits
89436feac2e3SRahul Lakkireddy * @caps32: a 32-bit Port Capabilities value
89446feac2e3SRahul Lakkireddy *
89456feac2e3SRahul Lakkireddy * Returns the equivalent 16-bit Port Capabilities value. Note that
89466feac2e3SRahul Lakkireddy * not all 32-bit Port Capabilities can be represented in the 16-bit
89476feac2e3SRahul Lakkireddy * Port Capabilities and some fields/values may not make it.
89486feac2e3SRahul Lakkireddy */
fwcaps32_to_caps16(fw_port_cap32_t caps32)89496feac2e3SRahul Lakkireddy static fw_port_cap16_t fwcaps32_to_caps16(fw_port_cap32_t caps32)
89506feac2e3SRahul Lakkireddy {
89516feac2e3SRahul Lakkireddy fw_port_cap16_t caps16 = 0;
89526feac2e3SRahul Lakkireddy
89536feac2e3SRahul Lakkireddy #define CAP32_TO_CAP16(__cap) \
89546feac2e3SRahul Lakkireddy do { \
89556feac2e3SRahul Lakkireddy if (caps32 & FW_PORT_CAP32_##__cap) \
89566feac2e3SRahul Lakkireddy caps16 |= FW_PORT_CAP_##__cap; \
89576feac2e3SRahul Lakkireddy } while (0)
89586feac2e3SRahul Lakkireddy
89596feac2e3SRahul Lakkireddy CAP32_TO_CAP16(SPEED_100M);
89606feac2e3SRahul Lakkireddy CAP32_TO_CAP16(SPEED_1G);
89616feac2e3SRahul Lakkireddy CAP32_TO_CAP16(SPEED_10G);
89626feac2e3SRahul Lakkireddy CAP32_TO_CAP16(SPEED_25G);
89636feac2e3SRahul Lakkireddy CAP32_TO_CAP16(SPEED_40G);
89646feac2e3SRahul Lakkireddy CAP32_TO_CAP16(SPEED_100G);
89656feac2e3SRahul Lakkireddy CAP32_TO_CAP16(FC_RX);
89666feac2e3SRahul Lakkireddy CAP32_TO_CAP16(FC_TX);
89676feac2e3SRahul Lakkireddy CAP32_TO_CAP16(802_3_PAUSE);
89686feac2e3SRahul Lakkireddy CAP32_TO_CAP16(802_3_ASM_DIR);
89696feac2e3SRahul Lakkireddy CAP32_TO_CAP16(ANEG);
89706feac2e3SRahul Lakkireddy CAP32_TO_CAP16(FORCE_PAUSE);
89716feac2e3SRahul Lakkireddy CAP32_TO_CAP16(MDIAUTO);
89726feac2e3SRahul Lakkireddy CAP32_TO_CAP16(MDISTRAIGHT);
89736feac2e3SRahul Lakkireddy CAP32_TO_CAP16(FEC_RS);
89746feac2e3SRahul Lakkireddy CAP32_TO_CAP16(FEC_BASER_RS);
89756feac2e3SRahul Lakkireddy
89766feac2e3SRahul Lakkireddy #undef CAP32_TO_CAP16
89776feac2e3SRahul Lakkireddy
89786feac2e3SRahul Lakkireddy return caps16;
89796feac2e3SRahul Lakkireddy }
89806feac2e3SRahul Lakkireddy
t4_link_set_autoneg(struct port_info * pi,u8 autoneg,fw_port_cap32_t * new_caps)89816feac2e3SRahul Lakkireddy int t4_link_set_autoneg(struct port_info *pi, u8 autoneg,
89826feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
89836feac2e3SRahul Lakkireddy {
89846feac2e3SRahul Lakkireddy struct link_config *lc = &pi->link_cfg;
89856feac2e3SRahul Lakkireddy fw_port_cap32_t caps = *new_caps;
89866feac2e3SRahul Lakkireddy
89876feac2e3SRahul Lakkireddy if (autoneg) {
89886feac2e3SRahul Lakkireddy if (!(lc->pcaps & FW_PORT_CAP32_ANEG))
89896feac2e3SRahul Lakkireddy return -ENOTSUP;
89906feac2e3SRahul Lakkireddy
89916feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_ANEG;
89926feac2e3SRahul Lakkireddy } else {
89936feac2e3SRahul Lakkireddy caps &= ~FW_PORT_CAP32_ANEG;
89946feac2e3SRahul Lakkireddy }
89956feac2e3SRahul Lakkireddy
89966feac2e3SRahul Lakkireddy caps &= ~V_FW_PORT_CAP32_MDI(M_FW_PORT_CAP32_MDI);
89976feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_MDIAUTO)
89986feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_MDIAUTO;
89996feac2e3SRahul Lakkireddy
90006feac2e3SRahul Lakkireddy *new_caps = caps;
90016feac2e3SRahul Lakkireddy return 0;
90026feac2e3SRahul Lakkireddy }
90036feac2e3SRahul Lakkireddy
t4_link_set_pause(struct port_info * pi,cc_pause_t pause,fw_port_cap32_t * new_caps)90046feac2e3SRahul Lakkireddy int t4_link_set_pause(struct port_info *pi, cc_pause_t pause,
90056feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
90066feac2e3SRahul Lakkireddy {
90076feac2e3SRahul Lakkireddy struct link_config *lc = &pi->link_cfg;
90086feac2e3SRahul Lakkireddy fw_port_cap32_t caps = *new_caps;
90096feac2e3SRahul Lakkireddy
90106feac2e3SRahul Lakkireddy caps &= ~V_FW_PORT_CAP32_FC(M_FW_PORT_CAP32_FC);
90116feac2e3SRahul Lakkireddy caps &= ~V_FW_PORT_CAP32_802_3(M_FW_PORT_CAP32_802_3);
90126feac2e3SRahul Lakkireddy
90136feac2e3SRahul Lakkireddy if ((pause & PAUSE_TX) && (pause & PAUSE_RX)) {
90146feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FC_TX | FW_PORT_CAP32_FC_RX;
90156feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
90166feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_802_3_PAUSE;
90176feac2e3SRahul Lakkireddy } else if (pause & PAUSE_TX) {
90186feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FC_TX;
90196feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
90206feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_802_3_ASM_DIR;
90216feac2e3SRahul Lakkireddy } else if (pause & PAUSE_RX) {
90226feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FC_RX;
90236feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
90246feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_802_3_PAUSE;
90256feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
90266feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_802_3_ASM_DIR;
90276feac2e3SRahul Lakkireddy }
90286feac2e3SRahul Lakkireddy
90296feac2e3SRahul Lakkireddy if (!(pause & PAUSE_AUTONEG))
90306feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FORCE_PAUSE;
90316feac2e3SRahul Lakkireddy
90326feac2e3SRahul Lakkireddy *new_caps = caps;
90336feac2e3SRahul Lakkireddy return 0;
90346feac2e3SRahul Lakkireddy }
90356feac2e3SRahul Lakkireddy
90366feac2e3SRahul Lakkireddy #define T4_LINK_FEC_MASK V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)
90376feac2e3SRahul Lakkireddy
t4_link_supported_speed_to_fec(u32 speed)90386feac2e3SRahul Lakkireddy static fw_port_cap32_t t4_link_supported_speed_to_fec(u32 speed)
90396feac2e3SRahul Lakkireddy {
90406feac2e3SRahul Lakkireddy fw_port_cap32_t caps = 0;
90416feac2e3SRahul Lakkireddy
90426feac2e3SRahul Lakkireddy switch (speed) {
90436feac2e3SRahul Lakkireddy case 100000:
90446feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FEC_RS;
90456feac2e3SRahul Lakkireddy break;
90466feac2e3SRahul Lakkireddy case 50000:
90476feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FEC_BASER_RS;
90486feac2e3SRahul Lakkireddy break;
90496feac2e3SRahul Lakkireddy case 25000:
90506feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FEC_RS |
90516feac2e3SRahul Lakkireddy FW_PORT_CAP32_FEC_BASER_RS;
90526feac2e3SRahul Lakkireddy break;
90536feac2e3SRahul Lakkireddy default:
90546feac2e3SRahul Lakkireddy break;
90556feac2e3SRahul Lakkireddy }
90566feac2e3SRahul Lakkireddy
90576feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FEC_NO_FEC;
90586feac2e3SRahul Lakkireddy return caps;
90596feac2e3SRahul Lakkireddy }
90606feac2e3SRahul Lakkireddy
t4_link_update_fec(struct port_info * pi,u32 max_speed,cc_fec_t fec,fw_port_cap32_t * new_caps)90616feac2e3SRahul Lakkireddy static void t4_link_update_fec(struct port_info *pi, u32 max_speed,
90626feac2e3SRahul Lakkireddy cc_fec_t fec, fw_port_cap32_t *new_caps)
90636feac2e3SRahul Lakkireddy {
90646feac2e3SRahul Lakkireddy fw_port_cap32_t caps = *new_caps;
90656feac2e3SRahul Lakkireddy
90666feac2e3SRahul Lakkireddy caps &= ~T4_LINK_FEC_MASK;
90676feac2e3SRahul Lakkireddy if (fec & FEC_RS) {
90686feac2e3SRahul Lakkireddy switch (max_speed) {
90696feac2e3SRahul Lakkireddy case 100000:
90706feac2e3SRahul Lakkireddy case 25000:
90716feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FEC_RS;
90726feac2e3SRahul Lakkireddy break;
90736feac2e3SRahul Lakkireddy default:
90746feac2e3SRahul Lakkireddy CH_ERR(pi->adapter,
90756feac2e3SRahul Lakkireddy "Ignoring unsupported RS FEC for speed %u\n",
90766feac2e3SRahul Lakkireddy max_speed);
90776feac2e3SRahul Lakkireddy break;
90786feac2e3SRahul Lakkireddy }
90796feac2e3SRahul Lakkireddy }
90806feac2e3SRahul Lakkireddy
90816feac2e3SRahul Lakkireddy if (fec & FEC_BASER_RS) {
90826feac2e3SRahul Lakkireddy switch (max_speed) {
90836feac2e3SRahul Lakkireddy case 50000:
90846feac2e3SRahul Lakkireddy case 25000:
90856feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FEC_BASER_RS;
90866feac2e3SRahul Lakkireddy break;
90876feac2e3SRahul Lakkireddy default:
90886feac2e3SRahul Lakkireddy CH_ERR(pi->adapter,
90896feac2e3SRahul Lakkireddy "Ignoring unsupported BASER FEC for speed %u\n",
90906feac2e3SRahul Lakkireddy max_speed);
90916feac2e3SRahul Lakkireddy break;
90926feac2e3SRahul Lakkireddy }
90936feac2e3SRahul Lakkireddy }
90946feac2e3SRahul Lakkireddy
90956feac2e3SRahul Lakkireddy if (fec & FEC_NONE)
90966feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FEC_NO_FEC;
90976feac2e3SRahul Lakkireddy
90986feac2e3SRahul Lakkireddy if (!(caps & T4_LINK_FEC_MASK)) {
90996feac2e3SRahul Lakkireddy /* No explicit encoding is requested.
91006feac2e3SRahul Lakkireddy * So, default back to AUTO.
91016feac2e3SRahul Lakkireddy */
91026feac2e3SRahul Lakkireddy caps |= t4_link_supported_speed_to_fec(max_speed);
91036feac2e3SRahul Lakkireddy caps &= ~FW_PORT_CAP32_FORCE_FEC;
91046feac2e3SRahul Lakkireddy }
91056feac2e3SRahul Lakkireddy
91066feac2e3SRahul Lakkireddy if (fec & FEC_FORCE)
91076feac2e3SRahul Lakkireddy caps |= FW_PORT_CAP32_FORCE_FEC;
91086feac2e3SRahul Lakkireddy
91096feac2e3SRahul Lakkireddy *new_caps = caps;
91106feac2e3SRahul Lakkireddy }
91116feac2e3SRahul Lakkireddy
t4_link_set_fec(struct port_info * pi,cc_fec_t fec,fw_port_cap32_t * new_caps)91126feac2e3SRahul Lakkireddy int t4_link_set_fec(struct port_info *pi, cc_fec_t fec,
91136feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
91146feac2e3SRahul Lakkireddy {
91156feac2e3SRahul Lakkireddy struct link_config *lc = &pi->link_cfg;
91166feac2e3SRahul Lakkireddy u32 max_speed;
91176feac2e3SRahul Lakkireddy
91186feac2e3SRahul Lakkireddy if (!(lc->pcaps & T4_LINK_FEC_MASK))
91196feac2e3SRahul Lakkireddy return -ENOTSUP;
91206feac2e3SRahul Lakkireddy
91216feac2e3SRahul Lakkireddy max_speed = t4_link_fwcap_to_speed(lc->link_caps);
91226feac2e3SRahul Lakkireddy /* Link might be down. In that case consider the max
91236feac2e3SRahul Lakkireddy * speed advertised
91246feac2e3SRahul Lakkireddy */
91256feac2e3SRahul Lakkireddy if (!max_speed)
91266feac2e3SRahul Lakkireddy max_speed = t4_link_fwcap_to_speed(lc->acaps);
91276feac2e3SRahul Lakkireddy
91286feac2e3SRahul Lakkireddy t4_link_update_fec(pi, max_speed, fec, new_caps);
91296feac2e3SRahul Lakkireddy return 0;
91306feac2e3SRahul Lakkireddy }
91316feac2e3SRahul Lakkireddy
91326feac2e3SRahul Lakkireddy #define T4_LINK_SPEED_MASK V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED)
91336feac2e3SRahul Lakkireddy
t4_link_set_speed(struct port_info * pi,fw_port_cap32_t speed,u8 en,fw_port_cap32_t * new_caps)91346feac2e3SRahul Lakkireddy int t4_link_set_speed(struct port_info *pi, fw_port_cap32_t speed, u8 en,
91356feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
91366feac2e3SRahul Lakkireddy {
91376feac2e3SRahul Lakkireddy fw_port_cap32_t tcaps, caps = *new_caps;
91386feac2e3SRahul Lakkireddy struct link_config *lc = &pi->link_cfg;
91396feac2e3SRahul Lakkireddy
91406feac2e3SRahul Lakkireddy if (((lc->pcaps & T4_LINK_SPEED_MASK) & speed) != speed)
91416feac2e3SRahul Lakkireddy return -ENOTSUP;
91426feac2e3SRahul Lakkireddy
91436feac2e3SRahul Lakkireddy if (en)
91446feac2e3SRahul Lakkireddy caps |= speed;
91456feac2e3SRahul Lakkireddy else
91466feac2e3SRahul Lakkireddy caps &= ~speed;
91476feac2e3SRahul Lakkireddy
91486feac2e3SRahul Lakkireddy /* If no speeds are left, then pick the next highest speed. */
91496feac2e3SRahul Lakkireddy if (!(caps & T4_LINK_SPEED_MASK)) {
91506feac2e3SRahul Lakkireddy tcaps = CAP32_SPEED(lc->pcaps);
91516feac2e3SRahul Lakkireddy tcaps &= ~speed;
91526feac2e3SRahul Lakkireddy tcaps &= (speed - 1);
91536feac2e3SRahul Lakkireddy if (tcaps == 0)
91546feac2e3SRahul Lakkireddy return -EINVAL;
91556feac2e3SRahul Lakkireddy
91566feac2e3SRahul Lakkireddy caps |= t4_link_fwcap_to_fwspeed(tcaps);
91576feac2e3SRahul Lakkireddy }
91586feac2e3SRahul Lakkireddy
91596feac2e3SRahul Lakkireddy *new_caps = caps;
91606feac2e3SRahul Lakkireddy return 0;
91616feac2e3SRahul Lakkireddy }
91626feac2e3SRahul Lakkireddy
t4_link_sanitize_speed_caps(struct link_config * lc,fw_port_cap32_t * new_caps)91636feac2e3SRahul Lakkireddy static void t4_link_sanitize_speed_caps(struct link_config *lc,
91646feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
91656feac2e3SRahul Lakkireddy {
91666feac2e3SRahul Lakkireddy fw_port_cap32_t tcaps, caps = *new_caps;
91676feac2e3SRahul Lakkireddy
91686feac2e3SRahul Lakkireddy /* Sanitize Speeds when AN is disabled */
91696feac2e3SRahul Lakkireddy if (!(caps & FW_PORT_CAP32_ANEG)) {
91706feac2e3SRahul Lakkireddy tcaps = CAP32_SPEED(caps);
91716feac2e3SRahul Lakkireddy caps &= ~T4_LINK_SPEED_MASK;
91726feac2e3SRahul Lakkireddy caps |= t4_link_fwcap_to_fwspeed(tcaps);
91736feac2e3SRahul Lakkireddy }
91746feac2e3SRahul Lakkireddy
91756feac2e3SRahul Lakkireddy *new_caps = caps;
91766feac2e3SRahul Lakkireddy }
91776feac2e3SRahul Lakkireddy
t4_link_sanitize_fec_caps(struct link_config * lc,fw_port_cap32_t * new_caps)91786feac2e3SRahul Lakkireddy static void t4_link_sanitize_fec_caps(struct link_config *lc,
91796feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
91806feac2e3SRahul Lakkireddy {
91816feac2e3SRahul Lakkireddy fw_port_cap32_t tcaps, caps = *new_caps;
91826feac2e3SRahul Lakkireddy u32 max_speed;
91836feac2e3SRahul Lakkireddy
91846feac2e3SRahul Lakkireddy /* Sanitize FECs when supported */
91856feac2e3SRahul Lakkireddy if (CAP32_FEC(lc->pcaps)) {
91866feac2e3SRahul Lakkireddy max_speed = t4_link_fwcap_to_speed(caps);
91876feac2e3SRahul Lakkireddy tcaps = t4_link_supported_speed_to_fec(max_speed);
91886feac2e3SRahul Lakkireddy if (caps & FW_PORT_CAP32_FORCE_FEC) {
91896feac2e3SRahul Lakkireddy /* If the current chosen FEC params are
91906feac2e3SRahul Lakkireddy * completely invalid, then disable FEC.
91916feac2e3SRahul Lakkireddy * Else, pick only the FECs requested
91926feac2e3SRahul Lakkireddy * by user or the defaults supported by
91936feac2e3SRahul Lakkireddy * the speed.
91946feac2e3SRahul Lakkireddy */
91956feac2e3SRahul Lakkireddy if (!(tcaps & CAP32_FEC(caps)))
91966feac2e3SRahul Lakkireddy tcaps = FW_PORT_CAP32_FEC_NO_FEC;
91976feac2e3SRahul Lakkireddy else
91986feac2e3SRahul Lakkireddy tcaps &= CAP32_FEC(caps);
91996feac2e3SRahul Lakkireddy }
92006feac2e3SRahul Lakkireddy } else {
92016feac2e3SRahul Lakkireddy /* Always force NO_FEC when FECs are not supported */
92026feac2e3SRahul Lakkireddy tcaps = FW_PORT_CAP32_FEC_NO_FEC;
92036feac2e3SRahul Lakkireddy }
92046feac2e3SRahul Lakkireddy
92056feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_FORCE_FEC) {
92066feac2e3SRahul Lakkireddy tcaps |= FW_PORT_CAP32_FORCE_FEC;
92076feac2e3SRahul Lakkireddy } else {
92086feac2e3SRahul Lakkireddy /* Older firmware doesn't allow driver to send request
92096feac2e3SRahul Lakkireddy * to try multiple FECs for FEC_AUTO case. So, clear
92106feac2e3SRahul Lakkireddy * the FEC caps for FEC_AUTO case because the older
92116feac2e3SRahul Lakkireddy * firmware will try all supported FECs on its own.
92126feac2e3SRahul Lakkireddy */
92136feac2e3SRahul Lakkireddy caps &= ~FW_PORT_CAP32_FORCE_FEC;
92146feac2e3SRahul Lakkireddy if (tcaps & (tcaps - 1))
92156feac2e3SRahul Lakkireddy tcaps = 0;
92166feac2e3SRahul Lakkireddy }
92176feac2e3SRahul Lakkireddy
92186feac2e3SRahul Lakkireddy caps &= ~T4_LINK_FEC_MASK;
92196feac2e3SRahul Lakkireddy caps |= tcaps;
92206feac2e3SRahul Lakkireddy
92216feac2e3SRahul Lakkireddy *new_caps = caps;
92226feac2e3SRahul Lakkireddy }
92236feac2e3SRahul Lakkireddy
t4_link_sanitize_caps(struct link_config * lc,fw_port_cap32_t * new_caps)92246feac2e3SRahul Lakkireddy static void t4_link_sanitize_caps(struct link_config *lc,
92256feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
92266feac2e3SRahul Lakkireddy {
92276feac2e3SRahul Lakkireddy fw_port_cap32_t caps = *new_caps;
92286feac2e3SRahul Lakkireddy
92296feac2e3SRahul Lakkireddy t4_link_sanitize_speed_caps(lc, &caps);
92306feac2e3SRahul Lakkireddy t4_link_sanitize_fec_caps(lc, &caps);
92316feac2e3SRahul Lakkireddy
92326feac2e3SRahul Lakkireddy /* Remove all unsupported caps */
92336feac2e3SRahul Lakkireddy if ((lc->pcaps | caps) != lc->pcaps)
92346feac2e3SRahul Lakkireddy caps &= lc->pcaps;
92356feac2e3SRahul Lakkireddy
92366feac2e3SRahul Lakkireddy *new_caps = caps;
92376feac2e3SRahul Lakkireddy }
92386feac2e3SRahul Lakkireddy
92396feac2e3SRahul Lakkireddy /**
92406feac2e3SRahul Lakkireddy * t4_link_l1cfg_core - apply link configuration to MAC/PHY
92416feac2e3SRahul Lakkireddy * @adapter: the adapter
92426feac2e3SRahul Lakkireddy * @mbox: the Firmware Mailbox to use
92436feac2e3SRahul Lakkireddy * @port: the Port ID
92446feac2e3SRahul Lakkireddy * @lc: the Port's Link Configuration
92456feac2e3SRahul Lakkireddy * @rcap: new link configuration
92466feac2e3SRahul Lakkireddy * @sleep_ok: if true we may sleep while awaiting command completion
92476feac2e3SRahul Lakkireddy * @timeout: time to wait for command to finish before timing out
92486feac2e3SRahul Lakkireddy * (negative implies @sleep_ok=false)
92496feac2e3SRahul Lakkireddy *
92506feac2e3SRahul Lakkireddy * Set up a port's MAC and PHY according to a desired link configuration.
92516feac2e3SRahul Lakkireddy * - If the PHY can auto-negotiate first decide what to advertise, then
92526feac2e3SRahul Lakkireddy * enable/disable auto-negotiation as desired, and reset.
92536feac2e3SRahul Lakkireddy * - If the PHY does not auto-negotiate just reset it.
92546feac2e3SRahul Lakkireddy * - If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
92556feac2e3SRahul Lakkireddy * otherwise do it later based on the outcome of auto-negotiation.
92566feac2e3SRahul Lakkireddy */
t4_link_l1cfg_core(struct adapter * adapter,unsigned int mbox,unsigned int port,struct link_config * lc,fw_port_cap32_t rcap,bool sleep_ok,int timeout)92576feac2e3SRahul Lakkireddy int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
92586feac2e3SRahul Lakkireddy unsigned int port, struct link_config *lc,
92596feac2e3SRahul Lakkireddy fw_port_cap32_t rcap, bool sleep_ok, int timeout)
92606feac2e3SRahul Lakkireddy {
92616feac2e3SRahul Lakkireddy unsigned int fw_caps = adapter->params.fw_caps_support;
92626feac2e3SRahul Lakkireddy struct fw_port_cmd cmd;
92636feac2e3SRahul Lakkireddy int ret;
92646feac2e3SRahul Lakkireddy
92656feac2e3SRahul Lakkireddy t4_link_sanitize_caps(lc, &rcap);
92666feac2e3SRahul Lakkireddy
92676feac2e3SRahul Lakkireddy memset(&cmd, 0, sizeof(cmd));
92686feac2e3SRahul Lakkireddy cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
92696feac2e3SRahul Lakkireddy F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
92706feac2e3SRahul Lakkireddy V_FW_PORT_CMD_PORTID(port));
92716feac2e3SRahul Lakkireddy cmd.action_to_len16 =
92726feac2e3SRahul Lakkireddy cpu_to_be32(V_FW_PORT_CMD_ACTION(fw_caps == FW_CAPS16
92736feac2e3SRahul Lakkireddy ? FW_PORT_ACTION_L1_CFG
92746feac2e3SRahul Lakkireddy : FW_PORT_ACTION_L1_CFG32) |
92756feac2e3SRahul Lakkireddy FW_LEN16(cmd));
92766feac2e3SRahul Lakkireddy if (fw_caps == FW_CAPS16)
92776feac2e3SRahul Lakkireddy cmd.u.l1cfg.rcap = cpu_to_be32(fwcaps32_to_caps16(rcap));
92786feac2e3SRahul Lakkireddy else
92796feac2e3SRahul Lakkireddy cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap);
92806feac2e3SRahul Lakkireddy ret = t4_wr_mbox_meat_timeout(adapter, mbox, &cmd, sizeof(cmd), NULL,
92816feac2e3SRahul Lakkireddy sleep_ok, timeout);
92826feac2e3SRahul Lakkireddy
92836feac2e3SRahul Lakkireddy /* Unfortunately, even if the Requested Port Capabilities "fit" within
92846feac2e3SRahul Lakkireddy * the Physical Port Capabilities, some combinations of features may
92856feac2e3SRahul Lakkireddy * still not be legal. For example, 40Gb/s and Reed-Solomon Forward
92866feac2e3SRahul Lakkireddy * Error Correction. So if the Firmware rejects the L1 Configure
92876feac2e3SRahul Lakkireddy * request, flag that here.
92886feac2e3SRahul Lakkireddy */
92896feac2e3SRahul Lakkireddy if (ret) {
92906feac2e3SRahul Lakkireddy CH_ERR(adapter,
92916feac2e3SRahul Lakkireddy "Requested Port Capabilities 0x%x rejected, error %d\n",
92926feac2e3SRahul Lakkireddy rcap, -ret);
92936feac2e3SRahul Lakkireddy return ret;
92946feac2e3SRahul Lakkireddy }
92956feac2e3SRahul Lakkireddy
92966feac2e3SRahul Lakkireddy return 0;
92976feac2e3SRahul Lakkireddy }
92986feac2e3SRahul Lakkireddy
92996feac2e3SRahul Lakkireddy /**
93006feac2e3SRahul Lakkireddy * t4_restart_aneg - restart autonegotiation
93016feac2e3SRahul Lakkireddy * @adap: the adapter
93026feac2e3SRahul Lakkireddy * @mbox: mbox to use for the FW command
93036feac2e3SRahul Lakkireddy * @port: the port id
93046feac2e3SRahul Lakkireddy *
93056feac2e3SRahul Lakkireddy * Restarts autonegotiation for the selected port.
93066feac2e3SRahul Lakkireddy */
t4_restart_aneg(struct adapter * adap,unsigned int mbox,unsigned int port)93076feac2e3SRahul Lakkireddy int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
93086feac2e3SRahul Lakkireddy {
93096feac2e3SRahul Lakkireddy unsigned int fw_caps = adap->params.fw_caps_support;
93106feac2e3SRahul Lakkireddy struct fw_port_cmd c;
93116feac2e3SRahul Lakkireddy
93126feac2e3SRahul Lakkireddy memset(&c, 0, sizeof(c));
93136feac2e3SRahul Lakkireddy c.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
93146feac2e3SRahul Lakkireddy F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
93156feac2e3SRahul Lakkireddy V_FW_PORT_CMD_PORTID(port));
93166feac2e3SRahul Lakkireddy c.action_to_len16 =
93176feac2e3SRahul Lakkireddy cpu_to_be32(V_FW_PORT_CMD_ACTION(fw_caps == FW_CAPS16
93186feac2e3SRahul Lakkireddy ? FW_PORT_ACTION_L1_CFG
93196feac2e3SRahul Lakkireddy : FW_PORT_ACTION_L1_CFG32) |
93206feac2e3SRahul Lakkireddy FW_LEN16(c));
93216feac2e3SRahul Lakkireddy if (fw_caps == FW_CAPS16)
93226feac2e3SRahul Lakkireddy c.u.l1cfg.rcap = cpu_to_be32(FW_PORT_CAP_ANEG);
93236feac2e3SRahul Lakkireddy else
93246feac2e3SRahul Lakkireddy c.u.l1cfg32.rcap32 = cpu_to_be32(FW_PORT_CAP32_ANEG);
93256feac2e3SRahul Lakkireddy return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
93266feac2e3SRahul Lakkireddy }
93276feac2e3SRahul Lakkireddy
93286feac2e3SRahul Lakkireddy /**
93296feac2e3SRahul Lakkireddy * t4_init_link_config - initialize a link's SW state
93306feac2e3SRahul Lakkireddy * @pi: the port info
93316feac2e3SRahul Lakkireddy * @pcaps: link Port Capabilities
93326feac2e3SRahul Lakkireddy * @acaps: link current Advertised Port Capabilities
93336feac2e3SRahul Lakkireddy *
93346feac2e3SRahul Lakkireddy * Initializes the SW state maintained for each link, including the link's
93356feac2e3SRahul Lakkireddy * capabilities and default speed/flow-control/autonegotiation settings.
93366feac2e3SRahul Lakkireddy */
t4_init_link_config(struct port_info * pi,fw_port_cap32_t pcaps,fw_port_cap32_t acaps)93376feac2e3SRahul Lakkireddy static void t4_init_link_config(struct port_info *pi, fw_port_cap32_t pcaps,
93386feac2e3SRahul Lakkireddy fw_port_cap32_t acaps)
93396feac2e3SRahul Lakkireddy {
93406feac2e3SRahul Lakkireddy u32 max_speed = t4_link_fwcap_to_speed(acaps);
93416feac2e3SRahul Lakkireddy struct link_config *lc = &pi->link_cfg;
93426feac2e3SRahul Lakkireddy fw_port_cap32_t new_caps = acaps;
93436feac2e3SRahul Lakkireddy
93446feac2e3SRahul Lakkireddy /* If initializing for the first time or if port module changed,
93456feac2e3SRahul Lakkireddy * then overwrite the saved link params with the new port module
93466feac2e3SRahul Lakkireddy * caps.
93476feac2e3SRahul Lakkireddy */
93486feac2e3SRahul Lakkireddy if (lc->admin_caps == 0 || lc->pcaps != pcaps) {
93496feac2e3SRahul Lakkireddy t4_link_update_fec(pi, max_speed, FEC_AUTO, &new_caps);
93506feac2e3SRahul Lakkireddy lc->admin_caps = new_caps;
93516feac2e3SRahul Lakkireddy }
93526feac2e3SRahul Lakkireddy
93536feac2e3SRahul Lakkireddy lc->pcaps = pcaps;
93546feac2e3SRahul Lakkireddy lc->acaps = acaps;
93556feac2e3SRahul Lakkireddy lc->lpacaps = 0;
93566feac2e3SRahul Lakkireddy lc->link_caps = 0;
93576feac2e3SRahul Lakkireddy }
93586feac2e3SRahul Lakkireddy
93596feac2e3SRahul Lakkireddy /**
93606feac2e3SRahul Lakkireddy * t4_link_down_rc_str - return a string for a Link Down Reason Code
93616feac2e3SRahul Lakkireddy * @link_down_rc: Link Down Reason Code
93626feac2e3SRahul Lakkireddy *
93636feac2e3SRahul Lakkireddy * Returns a string representation of the Link Down Reason Code.
93646feac2e3SRahul Lakkireddy */
t4_link_down_rc_str(unsigned char link_down_rc)93656feac2e3SRahul Lakkireddy const char *t4_link_down_rc_str(unsigned char link_down_rc)
93666feac2e3SRahul Lakkireddy {
93676feac2e3SRahul Lakkireddy static const char * const reason[] = {
93686feac2e3SRahul Lakkireddy "Link Down",
93696feac2e3SRahul Lakkireddy "Remote Fault",
93706feac2e3SRahul Lakkireddy "Auto-negotiation Failure",
93716feac2e3SRahul Lakkireddy "Reserved",
93726feac2e3SRahul Lakkireddy "Insufficient Airflow",
93736feac2e3SRahul Lakkireddy "Unable To Determine Reason",
93746feac2e3SRahul Lakkireddy "No RX Signal Detected",
93756feac2e3SRahul Lakkireddy "Reserved",
93766feac2e3SRahul Lakkireddy };
93776feac2e3SRahul Lakkireddy
93786feac2e3SRahul Lakkireddy if (link_down_rc >= ARRAY_SIZE(reason))
93796feac2e3SRahul Lakkireddy return "Bad Reason Code";
93806feac2e3SRahul Lakkireddy
93816feac2e3SRahul Lakkireddy return reason[link_down_rc];
93826feac2e3SRahul Lakkireddy }
93836feac2e3SRahul Lakkireddy
93846feac2e3SRahul Lakkireddy /**
93857e6ad469SVishal Kulkarni * lstatus_to_fwcap - translate old lstatus to 32-bit Port Capabilities
93867e6ad469SVishal Kulkarni * @lstatus: old FW_PORT_ACTION_GET_PORT_INFO lstatus value
93877e6ad469SVishal Kulkarni *
93887e6ad469SVishal Kulkarni * Translates old FW_PORT_ACTION_GET_PORT_INFO lstatus field into new
93897e6ad469SVishal Kulkarni * 32-bit Port Capabilities value.
93907e6ad469SVishal Kulkarni */
lstatus_to_fwcap(u32 lstatus)93917e6ad469SVishal Kulkarni static fw_port_cap32_t lstatus_to_fwcap(u32 lstatus)
93927e6ad469SVishal Kulkarni {
93937e6ad469SVishal Kulkarni fw_port_cap32_t linkattr = 0;
93947e6ad469SVishal Kulkarni
93957e6ad469SVishal Kulkarni /*
93967e6ad469SVishal Kulkarni * Unfortunately the format of the Link Status in the old
93977e6ad469SVishal Kulkarni * 16-bit Port Information message isn't the same as the
93987e6ad469SVishal Kulkarni * 16-bit Port Capabilities bitfield used everywhere else ...
93997e6ad469SVishal Kulkarni */
94007e6ad469SVishal Kulkarni if (lstatus & F_FW_PORT_CMD_RXPAUSE)
94017e6ad469SVishal Kulkarni linkattr |= FW_PORT_CAP32_FC_RX;
94027e6ad469SVishal Kulkarni if (lstatus & F_FW_PORT_CMD_TXPAUSE)
94037e6ad469SVishal Kulkarni linkattr |= FW_PORT_CAP32_FC_TX;
94047e6ad469SVishal Kulkarni if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
94057e6ad469SVishal Kulkarni linkattr |= FW_PORT_CAP32_SPEED_100M;
94067e6ad469SVishal Kulkarni if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
94077e6ad469SVishal Kulkarni linkattr |= FW_PORT_CAP32_SPEED_1G;
94087e6ad469SVishal Kulkarni if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
94097e6ad469SVishal Kulkarni linkattr |= FW_PORT_CAP32_SPEED_10G;
94107e6ad469SVishal Kulkarni if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_25G))
94117e6ad469SVishal Kulkarni linkattr |= FW_PORT_CAP32_SPEED_25G;
94127e6ad469SVishal Kulkarni if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
94137e6ad469SVishal Kulkarni linkattr |= FW_PORT_CAP32_SPEED_40G;
94147e6ad469SVishal Kulkarni if (lstatus & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100G))
94157e6ad469SVishal Kulkarni linkattr |= FW_PORT_CAP32_SPEED_100G;
94167e6ad469SVishal Kulkarni
94177e6ad469SVishal Kulkarni return linkattr;
94187e6ad469SVishal Kulkarni }
94197e6ad469SVishal Kulkarni
94207e6ad469SVishal Kulkarni /**
94213dde7c95SVishal Kulkarni * t4_handle_get_port_info - process a FW reply message
94223dde7c95SVishal Kulkarni * @pi: the port info
94233dde7c95SVishal Kulkarni * @rpl: start of the FW message
94243dde7c95SVishal Kulkarni *
94253dde7c95SVishal Kulkarni * Processes a GET_PORT_INFO FW reply message.
94263dde7c95SVishal Kulkarni */
t4_handle_get_port_info(struct port_info * pi,const __be64 * rpl)94273dde7c95SVishal Kulkarni void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
94283dde7c95SVishal Kulkarni {
94297e6ad469SVishal Kulkarni const struct fw_port_cmd *cmd = (const void *)rpl;
94307e6ad469SVishal Kulkarni int action = G_FW_PORT_CMD_ACTION(be32_to_cpu(cmd->action_to_len16));
94317e6ad469SVishal Kulkarni struct adapter *adapter = pi->adapter;
94327e6ad469SVishal Kulkarni struct link_config *lc = &pi->link_cfg;
94337e6ad469SVishal Kulkarni int link_ok, linkdnrc;
94347e6ad469SVishal Kulkarni enum fw_port_type port_type;
94357e6ad469SVishal Kulkarni enum fw_port_module_type mod_type;
94367e6ad469SVishal Kulkarni fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
94373dde7c95SVishal Kulkarni
943856b2bdd1SGireesh Nagabhushana /*
94397e6ad469SVishal Kulkarni * Extract the various fields from the Port Information message.
94403dde7c95SVishal Kulkarni */
94417e6ad469SVishal Kulkarni switch (action) {
94427e6ad469SVishal Kulkarni case FW_PORT_ACTION_GET_PORT_INFO: {
94437e6ad469SVishal Kulkarni u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
94443dde7c95SVishal Kulkarni
94457e6ad469SVishal Kulkarni link_ok = (lstatus & F_FW_PORT_CMD_LSTATUS) != 0;
94467e6ad469SVishal Kulkarni linkdnrc = G_FW_PORT_CMD_LINKDNRC(lstatus);
94477e6ad469SVishal Kulkarni port_type = G_FW_PORT_CMD_PTYPE(lstatus);
94487e6ad469SVishal Kulkarni mod_type = G_FW_PORT_CMD_MODTYPE(lstatus);
94497e6ad469SVishal Kulkarni pcaps = fwcaps16_to_caps32(be16_to_cpu(cmd->u.info.pcap));
94507e6ad469SVishal Kulkarni acaps = fwcaps16_to_caps32(be16_to_cpu(cmd->u.info.acap));
94517e6ad469SVishal Kulkarni lpacaps = fwcaps16_to_caps32(be16_to_cpu(cmd->u.info.lpacap));
94527e6ad469SVishal Kulkarni linkattr = lstatus_to_fwcap(lstatus);
94537e6ad469SVishal Kulkarni break;
94547e6ad469SVishal Kulkarni }
94553dde7c95SVishal Kulkarni
94567e6ad469SVishal Kulkarni case FW_PORT_ACTION_GET_PORT_INFO32: {
94577e6ad469SVishal Kulkarni u32 lstatus32 = be32_to_cpu(cmd->u.info32.lstatus32_to_cbllen32);
94583dde7c95SVishal Kulkarni
94597e6ad469SVishal Kulkarni link_ok = (lstatus32 & F_FW_PORT_CMD_LSTATUS32) != 0;
94607e6ad469SVishal Kulkarni linkdnrc = G_FW_PORT_CMD_LINKDNRC32(lstatus32);
94617e6ad469SVishal Kulkarni port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
94627e6ad469SVishal Kulkarni mod_type = G_FW_PORT_CMD_MODTYPE32(lstatus32);
94637e6ad469SVishal Kulkarni pcaps = be32_to_cpu(cmd->u.info32.pcaps32);
94647e6ad469SVishal Kulkarni acaps = be32_to_cpu(cmd->u.info32.acaps32);
94657e6ad469SVishal Kulkarni lpacaps = be32_to_cpu(cmd->u.info32.lpacaps32);
94667e6ad469SVishal Kulkarni linkattr = be32_to_cpu(cmd->u.info32.linkattr32);
94677e6ad469SVishal Kulkarni break;
94687e6ad469SVishal Kulkarni }
94693dde7c95SVishal Kulkarni
94707e6ad469SVishal Kulkarni default:
94717e6ad469SVishal Kulkarni CH_ERR(adapter, "Handle Port Information: Bad Command/Action %#x\n",
94727e6ad469SVishal Kulkarni be32_to_cpu(cmd->action_to_len16));
94737e6ad469SVishal Kulkarni return;
94747e6ad469SVishal Kulkarni }
94757e6ad469SVishal Kulkarni
94767e6ad469SVishal Kulkarni /*
94777e6ad469SVishal Kulkarni * Reset state for communicating new Transceiver Module status and
94787e6ad469SVishal Kulkarni * whether the OS-dependent layer wants us to redo the current
94797e6ad469SVishal Kulkarni * "sticky" L1 Configure Link Parameters.
94807e6ad469SVishal Kulkarni */
94817e6ad469SVishal Kulkarni lc->new_module = false;
94827e6ad469SVishal Kulkarni lc->redo_l1cfg = false;
94837e6ad469SVishal Kulkarni
94847e6ad469SVishal Kulkarni if (mod_type != pi->mod_type) {
94857e6ad469SVishal Kulkarni /*
94867e6ad469SVishal Kulkarni * Some versions of the early T6 Firmware "cheated" when
94877e6ad469SVishal Kulkarni * handling different Transceiver Modules by changing the
94887e6ad469SVishal Kulkarni * underlaying Port Type reported to the Host Drivers. As
94897e6ad469SVishal Kulkarni * such we need to capture whatever Port Type the Firmware
94907e6ad469SVishal Kulkarni * sends us and record it in case it's different from what we
94917e6ad469SVishal Kulkarni * were told earlier. Unfortunately, since Firmware is
94927e6ad469SVishal Kulkarni * forever, we'll need to keep this code here forever, but in
94937e6ad469SVishal Kulkarni * later T6 Firmware it should just be an assignment of the
94947e6ad469SVishal Kulkarni * same value already recorded.
94957e6ad469SVishal Kulkarni */
94967e6ad469SVishal Kulkarni pi->port_type = port_type;
94977e6ad469SVishal Kulkarni
94987e6ad469SVishal Kulkarni /*
94997e6ad469SVishal Kulkarni * Record new Module Type information.
95007e6ad469SVishal Kulkarni */
95017e6ad469SVishal Kulkarni pi->mod_type = mod_type;
95027e6ad469SVishal Kulkarni
95037e6ad469SVishal Kulkarni /*
95047e6ad469SVishal Kulkarni * Let the OS-dependent layer know if we have a new
95057e6ad469SVishal Kulkarni * Transceiver Module inserted.
95067e6ad469SVishal Kulkarni */
95077e6ad469SVishal Kulkarni lc->new_module = t4_is_inserted_mod_type(mod_type);
95087e6ad469SVishal Kulkarni
95096feac2e3SRahul Lakkireddy if (lc->new_module)
95106feac2e3SRahul Lakkireddy t4_init_link_config(pi, pcaps, acaps);
95117e6ad469SVishal Kulkarni t4_os_portmod_changed(adapter, pi->port_id);
95123dde7c95SVishal Kulkarni }
95133dde7c95SVishal Kulkarni
95146feac2e3SRahul Lakkireddy if (link_ok != lc->link_ok || acaps != lc->acaps ||
95156feac2e3SRahul Lakkireddy lpacaps != lc->lpacaps || linkattr != lc->link_caps) {
9516592b68f9SPaul Winder /* something changed */
95173dde7c95SVishal Kulkarni if (!link_ok && lc->link_ok) {
95187e6ad469SVishal Kulkarni lc->link_down_rc = linkdnrc;
95197e6ad469SVishal Kulkarni CH_WARN_RATELIMIT(adapter,
95203dde7c95SVishal Kulkarni "Port %d link down, reason: %s\n",
95217e6ad469SVishal Kulkarni pi->tx_chan, t4_link_down_rc_str(linkdnrc));
95223dde7c95SVishal Kulkarni }
95236feac2e3SRahul Lakkireddy
95243dde7c95SVishal Kulkarni lc->link_ok = link_ok;
95256feac2e3SRahul Lakkireddy lc->acaps = acaps;
95267e6ad469SVishal Kulkarni lc->lpacaps = lpacaps;
95276feac2e3SRahul Lakkireddy lc->link_caps = linkattr;
95283dde7c95SVishal Kulkarni
95297e6ad469SVishal Kulkarni t4_os_link_changed(adapter, pi->port_id, link_ok);
95303dde7c95SVishal Kulkarni }
95317e6ad469SVishal Kulkarni
95327e6ad469SVishal Kulkarni /*
95337e6ad469SVishal Kulkarni * If we have a new Transceiver Module and the OS-dependent code has
95347e6ad469SVishal Kulkarni * told us that it wants us to redo whatever "sticky" L1 Configuration
95357e6ad469SVishal Kulkarni * Link Parameters are set, do that now.
95367e6ad469SVishal Kulkarni */
95377e6ad469SVishal Kulkarni if (lc->new_module && lc->redo_l1cfg) {
95387e6ad469SVishal Kulkarni int ret;
95397e6ad469SVishal Kulkarni
95407e6ad469SVishal Kulkarni /*
95417e6ad469SVishal Kulkarni * Save the current L1 Configuration and restore it if an
95427e6ad469SVishal Kulkarni * error occurs. We probably should fix the l1_cfg*()
95437e6ad469SVishal Kulkarni * routines not to change the link_config when an error
95447e6ad469SVishal Kulkarni * occurs ...
95457e6ad469SVishal Kulkarni */
95466feac2e3SRahul Lakkireddy ret = t4_link_l1cfg_ns(adapter, adapter->mbox, pi->lport, lc,
95476feac2e3SRahul Lakkireddy lc->admin_caps);
95487e6ad469SVishal Kulkarni if (ret) {
95497e6ad469SVishal Kulkarni CH_WARN(adapter,
95507e6ad469SVishal Kulkarni "Attempt to update new Transceiver Module settings failed\n");
95517e6ad469SVishal Kulkarni }
95527e6ad469SVishal Kulkarni }
95537e6ad469SVishal Kulkarni lc->new_module = false;
95547e6ad469SVishal Kulkarni lc->redo_l1cfg = false;
95553dde7c95SVishal Kulkarni }
95563dde7c95SVishal Kulkarni
95573dde7c95SVishal Kulkarni /**
95583dde7c95SVishal Kulkarni * t4_update_port_info - retrieve and update port information if changed
95593dde7c95SVishal Kulkarni * @pi: the port_info
95603dde7c95SVishal Kulkarni *
95613dde7c95SVishal Kulkarni * We issue a Get Port Information Command to the Firmware and, if
95623dde7c95SVishal Kulkarni * successful, we check to see if anything is different from what we
95633dde7c95SVishal Kulkarni * last recorded and update things accordingly.
95643dde7c95SVishal Kulkarni */
t4_update_port_info(struct port_info * pi)95653dde7c95SVishal Kulkarni int t4_update_port_info(struct port_info *pi)
95663dde7c95SVishal Kulkarni {
95677e6ad469SVishal Kulkarni unsigned int fw_caps = pi->adapter->params.fw_caps_support;
95683dde7c95SVishal Kulkarni struct fw_port_cmd port_cmd;
95693dde7c95SVishal Kulkarni int ret;
95703dde7c95SVishal Kulkarni
95713dde7c95SVishal Kulkarni memset(&port_cmd, 0, sizeof port_cmd);
95723dde7c95SVishal Kulkarni port_cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
95733dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ |
95747e6ad469SVishal Kulkarni V_FW_PORT_CMD_PORTID(pi->lport));
95753dde7c95SVishal Kulkarni port_cmd.action_to_len16 = cpu_to_be32(
95767e6ad469SVishal Kulkarni V_FW_PORT_CMD_ACTION(fw_caps == FW_CAPS16
95777e6ad469SVishal Kulkarni ? FW_PORT_ACTION_GET_PORT_INFO
95787e6ad469SVishal Kulkarni : FW_PORT_ACTION_GET_PORT_INFO32) |
95793dde7c95SVishal Kulkarni FW_LEN16(port_cmd));
95803dde7c95SVishal Kulkarni ret = t4_wr_mbox(pi->adapter, pi->adapter->mbox,
95813dde7c95SVishal Kulkarni &port_cmd, sizeof(port_cmd), &port_cmd);
95823dde7c95SVishal Kulkarni if (ret)
95833dde7c95SVishal Kulkarni return ret;
95843dde7c95SVishal Kulkarni
95853dde7c95SVishal Kulkarni t4_handle_get_port_info(pi, (__be64 *)&port_cmd);
95863dde7c95SVishal Kulkarni return 0;
95873dde7c95SVishal Kulkarni }
95883dde7c95SVishal Kulkarni
95893dde7c95SVishal Kulkarni /**
95907e6ad469SVishal Kulkarni * t4_get_link_params - retrieve basic link parameters for given port
95917e6ad469SVishal Kulkarni * @pi: the port
95927e6ad469SVishal Kulkarni * @link_okp: value return pointer for link up/down
95937e6ad469SVishal Kulkarni * @speedp: value return pointer for speed (Mb/s)
95947e6ad469SVishal Kulkarni * @mtup: value return pointer for mtu
95957e6ad469SVishal Kulkarni *
95967e6ad469SVishal Kulkarni * Retrieves basic link parameters for a port: link up/down, speed (Mb/s),
95977e6ad469SVishal Kulkarni * and MTU for a specified port. A negative error is returned on
95987e6ad469SVishal Kulkarni * failure; 0 on success.
95997e6ad469SVishal Kulkarni */
t4_get_link_params(struct port_info * pi,unsigned int * link_okp,unsigned int * speedp,unsigned int * mtup)96007e6ad469SVishal Kulkarni int t4_get_link_params(struct port_info *pi, unsigned int *link_okp,
96017e6ad469SVishal Kulkarni unsigned int *speedp, unsigned int *mtup)
96027e6ad469SVishal Kulkarni {
96037e6ad469SVishal Kulkarni unsigned int fw_caps = pi->adapter->params.fw_caps_support;
96047e6ad469SVishal Kulkarni struct fw_port_cmd port_cmd;
96057e6ad469SVishal Kulkarni unsigned int action, link_ok, mtu;
96067e6ad469SVishal Kulkarni fw_port_cap32_t linkattr;
96077e6ad469SVishal Kulkarni int ret;
96087e6ad469SVishal Kulkarni
96097e6ad469SVishal Kulkarni memset(&port_cmd, 0, sizeof port_cmd);
96107e6ad469SVishal Kulkarni port_cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
96117e6ad469SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ |
96127e6ad469SVishal Kulkarni V_FW_PORT_CMD_PORTID(pi->tx_chan));
96137e6ad469SVishal Kulkarni action = (fw_caps == FW_CAPS16
96147e6ad469SVishal Kulkarni ? FW_PORT_ACTION_GET_PORT_INFO
96157e6ad469SVishal Kulkarni : FW_PORT_ACTION_GET_PORT_INFO32);
96167e6ad469SVishal Kulkarni port_cmd.action_to_len16 = cpu_to_be32(
96177e6ad469SVishal Kulkarni V_FW_PORT_CMD_ACTION(action) |
96187e6ad469SVishal Kulkarni FW_LEN16(port_cmd));
96197e6ad469SVishal Kulkarni ret = t4_wr_mbox(pi->adapter, pi->adapter->mbox,
96207e6ad469SVishal Kulkarni &port_cmd, sizeof(port_cmd), &port_cmd);
96217e6ad469SVishal Kulkarni if (ret)
96227e6ad469SVishal Kulkarni return ret;
96237e6ad469SVishal Kulkarni
96247e6ad469SVishal Kulkarni if (action == FW_PORT_ACTION_GET_PORT_INFO) {
96257e6ad469SVishal Kulkarni u32 lstatus = be32_to_cpu(port_cmd.u.info.lstatus_to_modtype);
96267e6ad469SVishal Kulkarni
96277e6ad469SVishal Kulkarni link_ok = !!(lstatus & F_FW_PORT_CMD_LSTATUS);
96287e6ad469SVishal Kulkarni linkattr = lstatus_to_fwcap(lstatus);
96297e6ad469SVishal Kulkarni mtu = be16_to_cpu(port_cmd.u.info.mtu);;
96307e6ad469SVishal Kulkarni } else {
96317e6ad469SVishal Kulkarni u32 lstatus32 = be32_to_cpu(port_cmd.u.info32.lstatus32_to_cbllen32);
96327e6ad469SVishal Kulkarni
96337e6ad469SVishal Kulkarni link_ok = !!(lstatus32 & F_FW_PORT_CMD_LSTATUS32);
96347e6ad469SVishal Kulkarni linkattr = be32_to_cpu(port_cmd.u.info32.linkattr32);
96357e6ad469SVishal Kulkarni mtu = G_FW_PORT_CMD_MTU32(
96367e6ad469SVishal Kulkarni be32_to_cpu(port_cmd.u.info32.auxlinfo32_mtu32));
96377e6ad469SVishal Kulkarni }
96387e6ad469SVishal Kulkarni
96397e6ad469SVishal Kulkarni *link_okp = link_ok;
96406feac2e3SRahul Lakkireddy *speedp = t4_link_fwcap_to_speed(linkattr);
96417e6ad469SVishal Kulkarni *mtup = mtu;
96427e6ad469SVishal Kulkarni
96437e6ad469SVishal Kulkarni return 0;
96447e6ad469SVishal Kulkarni }
96457e6ad469SVishal Kulkarni
96467e6ad469SVishal Kulkarni /**
964756b2bdd1SGireesh Nagabhushana * t4_handle_fw_rpl - process a FW reply message
964856b2bdd1SGireesh Nagabhushana * @adap: the adapter
964956b2bdd1SGireesh Nagabhushana * @rpl: start of the FW message
965056b2bdd1SGireesh Nagabhushana *
965156b2bdd1SGireesh Nagabhushana * Processes a FW message, such as link state change messages.
965256b2bdd1SGireesh Nagabhushana */
t4_handle_fw_rpl(struct adapter * adap,const __be64 * rpl)96533dde7c95SVishal Kulkarni int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
965456b2bdd1SGireesh Nagabhushana {
965556b2bdd1SGireesh Nagabhushana u8 opcode = *(const u8 *)rpl;
965656b2bdd1SGireesh Nagabhushana
96573dde7c95SVishal Kulkarni /*
96583dde7c95SVishal Kulkarni * This might be a port command ... this simplifies the following
96593dde7c95SVishal Kulkarni * conditionals ... We can get away with pre-dereferencing
96603dde7c95SVishal Kulkarni * action_to_len16 because it's in the first 16 bytes and all messages
96613dde7c95SVishal Kulkarni * will be at least that long.
96623dde7c95SVishal Kulkarni */
9663de483253SVishal Kulkarni const struct fw_port_cmd *p = (const void *)rpl;
96643dde7c95SVishal Kulkarni unsigned int action =
96653dde7c95SVishal Kulkarni G_FW_PORT_CMD_ACTION(be32_to_cpu(p->action_to_len16));
9666de483253SVishal Kulkarni
96677e6ad469SVishal Kulkarni if (opcode == FW_PORT_CMD &&
96687e6ad469SVishal Kulkarni (action == FW_PORT_ACTION_GET_PORT_INFO ||
96697e6ad469SVishal Kulkarni action == FW_PORT_ACTION_GET_PORT_INFO32)) {
967056b2bdd1SGireesh Nagabhushana int i;
96713dde7c95SVishal Kulkarni int chan = G_FW_PORT_CMD_PORTID(be32_to_cpu(p->op_to_portid));
967256b2bdd1SGireesh Nagabhushana struct port_info *pi = NULL;
967356b2bdd1SGireesh Nagabhushana
967456b2bdd1SGireesh Nagabhushana for_each_port(adap, i) {
967556b2bdd1SGireesh Nagabhushana pi = adap2pinfo(adap, i);
96767e6ad469SVishal Kulkarni if (pi->lport == chan)
967756b2bdd1SGireesh Nagabhushana break;
967856b2bdd1SGireesh Nagabhushana }
96793dde7c95SVishal Kulkarni
96803dde7c95SVishal Kulkarni t4_handle_get_port_info(pi, rpl);
96813dde7c95SVishal Kulkarni } else {
96823dde7c95SVishal Kulkarni CH_WARN_RATELIMIT(adap, "Unknown firmware reply %d\n", opcode);
9683de483253SVishal Kulkarni return -EINVAL;
9684de483253SVishal Kulkarni }
96853dde7c95SVishal Kulkarni return 0;
968656b2bdd1SGireesh Nagabhushana }
968756b2bdd1SGireesh Nagabhushana
96883dde7c95SVishal Kulkarni /**
968956b2bdd1SGireesh Nagabhushana * get_pci_mode - determine a card's PCI mode
969056b2bdd1SGireesh Nagabhushana * @adapter: the adapter
969156b2bdd1SGireesh Nagabhushana * @p: where to store the PCI settings
969256b2bdd1SGireesh Nagabhushana *
969356b2bdd1SGireesh Nagabhushana * Determines a card's PCI mode and associated parameters, such as speed
969456b2bdd1SGireesh Nagabhushana * and width.
969556b2bdd1SGireesh Nagabhushana */
get_pci_mode(struct adapter * adapter,struct pci_params * p)96963dde7c95SVishal Kulkarni static void get_pci_mode(struct adapter *adapter,
96973dde7c95SVishal Kulkarni struct pci_params *p)
969856b2bdd1SGireesh Nagabhushana {
969956b2bdd1SGireesh Nagabhushana u16 val;
970056b2bdd1SGireesh Nagabhushana u32 pcie_cap;
970156b2bdd1SGireesh Nagabhushana
970256b2bdd1SGireesh Nagabhushana pcie_cap = t4_os_find_pci_capability(adapter, PCI_CAP_ID_EXP);
97033dde7c95SVishal Kulkarni if (pcie_cap) {
970456b2bdd1SGireesh Nagabhushana t4_os_pci_read_cfg2(adapter, pcie_cap + PCI_EXP_LNKSTA, &val);
970556b2bdd1SGireesh Nagabhushana p->speed = val & PCI_EXP_LNKSTA_CLS;
970656b2bdd1SGireesh Nagabhushana p->width = (val & PCI_EXP_LNKSTA_NLW) >> 4;
970756b2bdd1SGireesh Nagabhushana }
970856b2bdd1SGireesh Nagabhushana }
970956b2bdd1SGireesh Nagabhushana
97103dde7c95SVishal Kulkarni /**
97113dde7c95SVishal Kulkarni * t4_wait_dev_ready - wait till to reads of registers work
97123dde7c95SVishal Kulkarni *
97133dde7c95SVishal Kulkarni * Right after the device is RESET is can take a small amount of time
97143dde7c95SVishal Kulkarni * for it to respond to register reads. Until then, all reads will
97153dde7c95SVishal Kulkarni * return either 0xff...ff or 0xee...ee. Return an error if reads
97163dde7c95SVishal Kulkarni * don't work within a reasonable time frame.
97173dde7c95SVishal Kulkarni */
t4_wait_dev_ready(struct adapter * adapter)97183dde7c95SVishal Kulkarni int t4_wait_dev_ready(struct adapter *adapter)
971956b2bdd1SGireesh Nagabhushana {
97203dde7c95SVishal Kulkarni u32 whoami;
972156b2bdd1SGireesh Nagabhushana
97223dde7c95SVishal Kulkarni whoami = t4_read_reg(adapter, A_PL_WHOAMI);
97233dde7c95SVishal Kulkarni if (whoami != 0xffffffff && whoami != X_CIM_PF_NOACCESS)
97243dde7c95SVishal Kulkarni return 0;
972556b2bdd1SGireesh Nagabhushana
97263dde7c95SVishal Kulkarni msleep(500);
97273dde7c95SVishal Kulkarni whoami = t4_read_reg(adapter, A_PL_WHOAMI);
97283dde7c95SVishal Kulkarni if (whoami != 0xffffffff && whoami != X_CIM_PF_NOACCESS)
97293dde7c95SVishal Kulkarni return 0;
97303dde7c95SVishal Kulkarni
97313dde7c95SVishal Kulkarni CH_ERR(adapter, "Device didn't become ready for access, "
97323dde7c95SVishal Kulkarni "whoami = %#x\n", whoami);
97333dde7c95SVishal Kulkarni return -EIO;
973456b2bdd1SGireesh Nagabhushana }
973556b2bdd1SGireesh Nagabhushana
97363dde7c95SVishal Kulkarni struct flash_desc {
97373dde7c95SVishal Kulkarni u32 vendor_and_model_id;
97383dde7c95SVishal Kulkarni u32 size_mb;
97393dde7c95SVishal Kulkarni };
97403dde7c95SVishal Kulkarni
t4_get_flash_params(struct adapter * adapter)97413dde7c95SVishal Kulkarni int t4_get_flash_params(struct adapter *adapter)
97423dde7c95SVishal Kulkarni {
9743fa56a4b4SVishal Kulkarni /*
9744fa56a4b4SVishal Kulkarni * Table for non-standard supported Flash parts. Note, all Flash
9745fa56a4b4SVishal Kulkarni * parts must have 64KB sectors.
97463dde7c95SVishal Kulkarni */
97473dde7c95SVishal Kulkarni static struct flash_desc supported_flash[] = {
97483dde7c95SVishal Kulkarni { 0x00150201, 4 << 20 }, /* Spansion 4MB S25FL032P */
97493dde7c95SVishal Kulkarni };
97503dde7c95SVishal Kulkarni
97513dde7c95SVishal Kulkarni int ret;
97523dde7c95SVishal Kulkarni u32 flashid = 0;
97533dde7c95SVishal Kulkarni unsigned int part, manufacturer;
9754fa56a4b4SVishal Kulkarni unsigned int density, size = 0;
97553dde7c95SVishal Kulkarni
97563dde7c95SVishal Kulkarni
97573dde7c95SVishal Kulkarni /*
97583dde7c95SVishal Kulkarni * Issue a Read ID Command to the Flash part. We decode supported
97593dde7c95SVishal Kulkarni * Flash parts and their sizes from this. There's a newer Query
9760fa56a4b4SVishal Kulkarni * Command which can retrieve detailed geometry information but many
9761fa56a4b4SVishal Kulkarni * Flash parts don't support it.
97623dde7c95SVishal Kulkarni */
97633dde7c95SVishal Kulkarni ret = sf1_write(adapter, 1, 1, 0, SF_RD_ID);
97643dde7c95SVishal Kulkarni if (!ret)
97653dde7c95SVishal Kulkarni ret = sf1_read(adapter, 3, 0, 1, &flashid);
97663dde7c95SVishal Kulkarni t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */
97673dde7c95SVishal Kulkarni if (ret < 0)
97683dde7c95SVishal Kulkarni return ret;
97693dde7c95SVishal Kulkarni
9770fa56a4b4SVishal Kulkarni /*
9771fa56a4b4SVishal Kulkarni * Check to see if it's one of our non-standard supported Flash parts.
9772fa56a4b4SVishal Kulkarni */
97733dde7c95SVishal Kulkarni for (part = 0; part < ARRAY_SIZE(supported_flash); part++)
97743dde7c95SVishal Kulkarni if (supported_flash[part].vendor_and_model_id == flashid) {
97753dde7c95SVishal Kulkarni adapter->params.sf_size =
97763dde7c95SVishal Kulkarni supported_flash[part].size_mb;
97773dde7c95SVishal Kulkarni adapter->params.sf_nsec =
97783dde7c95SVishal Kulkarni adapter->params.sf_size / SF_SEC_SIZE;
97793dde7c95SVishal Kulkarni goto found;
97803dde7c95SVishal Kulkarni }
97813dde7c95SVishal Kulkarni
9782fa56a4b4SVishal Kulkarni /*
97837e6ad469SVishal Kulkarni * Decode Flash part size. The code below looks repetative with
9784fa56a4b4SVishal Kulkarni * common encodings, but that's not guaranteed in the JEDEC
97857e6ad469SVishal Kulkarni * specification for the Read JADEC ID command. The only thing that
97867e6ad469SVishal Kulkarni * we're guaranteed by the JADEC specification is where the
9787fa56a4b4SVishal Kulkarni * Manufacturer ID is in the returned result. After that each
9788fa56a4b4SVishal Kulkarni * Manufacturer ~could~ encode things completely differently.
9789fa56a4b4SVishal Kulkarni * Note, all Flash parts must have 64KB sectors.
9790fa56a4b4SVishal Kulkarni */
97913dde7c95SVishal Kulkarni manufacturer = flashid & 0xff;
97923dde7c95SVishal Kulkarni switch (manufacturer) {
97933dde7c95SVishal Kulkarni case 0x20: { /* Micron/Numonix */
97943dde7c95SVishal Kulkarni /*
97953dde7c95SVishal Kulkarni * This Density -> Size decoding table is taken from Micron
97963dde7c95SVishal Kulkarni * Data Sheets.
97973dde7c95SVishal Kulkarni */
97983dde7c95SVishal Kulkarni density = (flashid >> 16) & 0xff;
97993dde7c95SVishal Kulkarni switch (density) {
98003dde7c95SVishal Kulkarni case 0x14: size = 1 << 20; break; /* 1MB */
98013dde7c95SVishal Kulkarni case 0x15: size = 1 << 21; break; /* 2MB */
98023dde7c95SVishal Kulkarni case 0x16: size = 1 << 22; break; /* 4MB */
98033dde7c95SVishal Kulkarni case 0x17: size = 1 << 23; break; /* 8MB */
98043dde7c95SVishal Kulkarni case 0x18: size = 1 << 24; break; /* 16MB */
98053dde7c95SVishal Kulkarni case 0x19: size = 1 << 25; break; /* 32MB */
98063dde7c95SVishal Kulkarni case 0x20: size = 1 << 26; break; /* 64MB */
98073dde7c95SVishal Kulkarni case 0x21: size = 1 << 27; break; /* 128MB */
98083dde7c95SVishal Kulkarni case 0x22: size = 1 << 28; break; /* 256MB */
98093dde7c95SVishal Kulkarni }
98103dde7c95SVishal Kulkarni break;
98113dde7c95SVishal Kulkarni }
98123dde7c95SVishal Kulkarni
9813fa56a4b4SVishal Kulkarni case 0x9d: { /* ISSI -- Integrated Silicon Solution, Inc. */
9814fa56a4b4SVishal Kulkarni /*
9815fa56a4b4SVishal Kulkarni * This Density -> Size decoding table is taken from ISSI
9816fa56a4b4SVishal Kulkarni * Data Sheets.
9817fa56a4b4SVishal Kulkarni */
9818fa56a4b4SVishal Kulkarni density = (flashid >> 16) & 0xff;
9819fa56a4b4SVishal Kulkarni switch (density) {
9820fa56a4b4SVishal Kulkarni case 0x16: size = 1 << 25; break; /* 32MB */
9821fa56a4b4SVishal Kulkarni case 0x17: size = 1 << 26; break; /* 64MB */
98223dde7c95SVishal Kulkarni }
9823fa56a4b4SVishal Kulkarni break;
9824fa56a4b4SVishal Kulkarni }
9825fa56a4b4SVishal Kulkarni
9826fa56a4b4SVishal Kulkarni case 0xc2: { /* Macronix */
9827fa56a4b4SVishal Kulkarni /*
9828fa56a4b4SVishal Kulkarni * This Density -> Size decoding table is taken from Macronix
9829fa56a4b4SVishal Kulkarni * Data Sheets.
9830fa56a4b4SVishal Kulkarni */
9831fa56a4b4SVishal Kulkarni density = (flashid >> 16) & 0xff;
9832fa56a4b4SVishal Kulkarni switch (density) {
9833fa56a4b4SVishal Kulkarni case 0x17: size = 1 << 23; break; /* 8MB */
9834fa56a4b4SVishal Kulkarni case 0x18: size = 1 << 24; break; /* 16MB */
9835fa56a4b4SVishal Kulkarni }
9836fa56a4b4SVishal Kulkarni break;
9837fa56a4b4SVishal Kulkarni }
9838fa56a4b4SVishal Kulkarni
9839fa56a4b4SVishal Kulkarni case 0xef: { /* Winbond */
9840fa56a4b4SVishal Kulkarni /*
9841fa56a4b4SVishal Kulkarni * This Density -> Size decoding table is taken from Winbond
9842fa56a4b4SVishal Kulkarni * Data Sheets.
9843fa56a4b4SVishal Kulkarni */
9844fa56a4b4SVishal Kulkarni density = (flashid >> 16) & 0xff;
9845fa56a4b4SVishal Kulkarni switch (density) {
9846fa56a4b4SVishal Kulkarni case 0x17: size = 1 << 23; break; /* 8MB */
9847fa56a4b4SVishal Kulkarni case 0x18: size = 1 << 24; break; /* 16MB */
9848fa56a4b4SVishal Kulkarni }
9849fa56a4b4SVishal Kulkarni break;
9850fa56a4b4SVishal Kulkarni }
9851fa56a4b4SVishal Kulkarni }
9852fa56a4b4SVishal Kulkarni
9853fa56a4b4SVishal Kulkarni /*
9854fa56a4b4SVishal Kulkarni * If we didn't recognize the FLASH part, that's no real issue: the
9855fa56a4b4SVishal Kulkarni * Hardware/Software contract says that Hardware will _*ALWAYS*_
9856fa56a4b4SVishal Kulkarni * use a FLASH part which is at least 4MB in size and has 64KB
9857fa56a4b4SVishal Kulkarni * sectors. The unrecognized FLASH part is likely to be much larger
9858fa56a4b4SVishal Kulkarni * than 4MB, but that's all we really need.
9859fa56a4b4SVishal Kulkarni */
9860fa56a4b4SVishal Kulkarni if (size == 0) {
9861fa56a4b4SVishal Kulkarni CH_WARN(adapter, "Unknown Flash Part, ID = %#x, assuming 4MB\n", flashid);
9862fa56a4b4SVishal Kulkarni size = 1 << 22;
9863fa56a4b4SVishal Kulkarni }
9864fa56a4b4SVishal Kulkarni
9865fa56a4b4SVishal Kulkarni /*
9866fa56a4b4SVishal Kulkarni * Store decoded Flash size and fall through into vetting code.
9867fa56a4b4SVishal Kulkarni */
9868fa56a4b4SVishal Kulkarni adapter->params.sf_size = size;
9869fa56a4b4SVishal Kulkarni adapter->params.sf_nsec = size / SF_SEC_SIZE;
98703dde7c95SVishal Kulkarni
98713dde7c95SVishal Kulkarni found:
98723dde7c95SVishal Kulkarni /*
98733dde7c95SVishal Kulkarni * We should ~probably~ reject adapters with FLASHes which are too
98743dde7c95SVishal Kulkarni * small but we have some legacy FPGAs with small FLASHes that we'd
98753dde7c95SVishal Kulkarni * still like to use. So instead we emit a scary message ...
98763dde7c95SVishal Kulkarni */
98773dde7c95SVishal Kulkarni if (adapter->params.sf_size < FLASH_MIN_SIZE)
98783dde7c95SVishal Kulkarni CH_WARN(adapter, "WARNING: Flash Part ID %#x, size %#x < %#x\n",
98793dde7c95SVishal Kulkarni flashid, adapter->params.sf_size, FLASH_MIN_SIZE);
98803dde7c95SVishal Kulkarni
98813dde7c95SVishal Kulkarni return 0;
98823dde7c95SVishal Kulkarni }
98833dde7c95SVishal Kulkarni
set_pcie_completion_timeout(struct adapter * adapter,u8 range)98843dde7c95SVishal Kulkarni static void set_pcie_completion_timeout(struct adapter *adapter,
9885de483253SVishal Kulkarni u8 range)
9886de483253SVishal Kulkarni {
9887de483253SVishal Kulkarni u16 val;
9888de483253SVishal Kulkarni u32 pcie_cap;
9889de483253SVishal Kulkarni
9890de483253SVishal Kulkarni pcie_cap = t4_os_find_pci_capability(adapter, PCI_CAP_ID_EXP);
9891de483253SVishal Kulkarni if (pcie_cap) {
9892de483253SVishal Kulkarni t4_os_pci_read_cfg2(adapter, pcie_cap + PCI_EXP_DEVCTL2, &val);
9893de483253SVishal Kulkarni val &= 0xfff0;
9894de483253SVishal Kulkarni val |= range ;
9895de483253SVishal Kulkarni t4_os_pci_write_cfg2(adapter, pcie_cap + PCI_EXP_DEVCTL2, val);
9896de483253SVishal Kulkarni }
9897de483253SVishal Kulkarni }
9898de483253SVishal Kulkarni
98993dde7c95SVishal Kulkarni /**
99003dde7c95SVishal Kulkarni * t4_get_chip_type - Determine chip type from device ID
99013dde7c95SVishal Kulkarni * @adap: the adapter
99023dde7c95SVishal Kulkarni * @ver: adapter version
990356b2bdd1SGireesh Nagabhushana */
t4_get_chip_type(struct adapter * adap,int ver)99043dde7c95SVishal Kulkarni enum chip_type t4_get_chip_type(struct adapter *adap, int ver)
990556b2bdd1SGireesh Nagabhushana {
99063dde7c95SVishal Kulkarni enum chip_type chip = 0;
99073dde7c95SVishal Kulkarni u32 pl_rev = G_REV(t4_read_reg(adap, A_PL_REV));
990856b2bdd1SGireesh Nagabhushana
99093dde7c95SVishal Kulkarni /* Retrieve adapter's device ID */
9910de483253SVishal Kulkarni switch (ver) {
9911de483253SVishal Kulkarni case CHELSIO_T4_FPGA:
99123dde7c95SVishal Kulkarni chip |= CHELSIO_CHIP_FPGA;
9913de483253SVishal Kulkarni /*FALLTHROUGH*/
9914de483253SVishal Kulkarni case CHELSIO_T4:
99153dde7c95SVishal Kulkarni chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev);
9916de483253SVishal Kulkarni break;
9917de483253SVishal Kulkarni case CHELSIO_T5_FPGA:
99183dde7c95SVishal Kulkarni chip |= CHELSIO_CHIP_FPGA;
9919de483253SVishal Kulkarni /*FALLTHROUGH*/
9920de483253SVishal Kulkarni case CHELSIO_T5:
99213dde7c95SVishal Kulkarni chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev);
99223dde7c95SVishal Kulkarni break;
99233dde7c95SVishal Kulkarni case CHELSIO_T6_FPGA:
99243dde7c95SVishal Kulkarni chip |= CHELSIO_CHIP_FPGA;
99253dde7c95SVishal Kulkarni /*FALLTHROUGH*/
99263dde7c95SVishal Kulkarni case CHELSIO_T6:
99273dde7c95SVishal Kulkarni chip |= CHELSIO_CHIP_CODE(CHELSIO_T6, pl_rev);
9928de483253SVishal Kulkarni break;
9929de483253SVishal Kulkarni default:
99303dde7c95SVishal Kulkarni CH_ERR(adap, "Device %d is not supported\n",
99313dde7c95SVishal Kulkarni adap->params.pci.device_id);
99323dde7c95SVishal Kulkarni return -EINVAL;
993356b2bdd1SGireesh Nagabhushana }
9934de483253SVishal Kulkarni
9935de483253SVishal Kulkarni /* T4A1 chip is no longer supported */
99363dde7c95SVishal Kulkarni if (chip == T4_A1) {
99373dde7c95SVishal Kulkarni CH_ALERT(adap, "T4 rev 1 chip is no longer supported\n");
9938de483253SVishal Kulkarni return -EINVAL;
9939de483253SVishal Kulkarni }
99403dde7c95SVishal Kulkarni return chip;
99413dde7c95SVishal Kulkarni }
994256b2bdd1SGireesh Nagabhushana
99433dde7c95SVishal Kulkarni /**
99443dde7c95SVishal Kulkarni * t4_prep_pf - prepare SW and HW for PF operation
99453dde7c95SVishal Kulkarni * @adapter: the adapter
99463dde7c95SVishal Kulkarni *
99473dde7c95SVishal Kulkarni * Initialize adapter SW state for the various HW modules, set initial
99483dde7c95SVishal Kulkarni * values for some adapter tunables on each PF.
99493dde7c95SVishal Kulkarni */
t4_prep_pf(struct adapter * adapter)99503dde7c95SVishal Kulkarni int t4_prep_pf(struct adapter *adapter)
99513dde7c95SVishal Kulkarni {
99523dde7c95SVishal Kulkarni int ret, ver;
99533dde7c95SVishal Kulkarni
99543dde7c95SVishal Kulkarni ret = t4_wait_dev_ready(adapter);
995556b2bdd1SGireesh Nagabhushana if (ret < 0)
9956de483253SVishal Kulkarni return ret;
995756b2bdd1SGireesh Nagabhushana
99583dde7c95SVishal Kulkarni get_pci_mode(adapter, &adapter->params.pci);
99593dde7c95SVishal Kulkarni
99603dde7c95SVishal Kulkarni
99613dde7c95SVishal Kulkarni /* Retrieve adapter's device ID
99623dde7c95SVishal Kulkarni */
99633dde7c95SVishal Kulkarni t4_os_pci_read_cfg2(adapter, PCI_DEVICE_ID, &adapter->params.pci.device_id);
99643dde7c95SVishal Kulkarni t4_os_pci_read_cfg2(adapter, PCI_VENDOR_ID, &adapter->params.pci.vendor_id);
99653dde7c95SVishal Kulkarni
99663dde7c95SVishal Kulkarni ver = CHELSIO_PCI_ID_VER(adapter->params.pci.device_id);
99673dde7c95SVishal Kulkarni adapter->params.chip = t4_get_chip_type(adapter, ver);
99683dde7c95SVishal Kulkarni if (is_t4(adapter->params.chip)) {
99693dde7c95SVishal Kulkarni adapter->params.arch.sge_fl_db = F_DBPRIO;
99703dde7c95SVishal Kulkarni adapter->params.arch.mps_tcam_size =
99713dde7c95SVishal Kulkarni NUM_MPS_CLS_SRAM_L_INSTANCES;
99723dde7c95SVishal Kulkarni adapter->params.arch.mps_rplc_size = 128;
99733dde7c95SVishal Kulkarni adapter->params.arch.nchan = NCHAN;
99743dde7c95SVishal Kulkarni adapter->params.arch.pm_stats_cnt = PM_NSTATS;
99753dde7c95SVishal Kulkarni adapter->params.arch.vfcount = 128;
99763dde7c95SVishal Kulkarni /* Congestion map is for 4 channels so that
99773dde7c95SVishal Kulkarni * MPS can have 4 priority per port.
99783dde7c95SVishal Kulkarni */
99793dde7c95SVishal Kulkarni adapter->params.arch.cng_ch_bits_log = 2;
99803dde7c95SVishal Kulkarni } else if (is_t5(adapter->params.chip)) {
99813dde7c95SVishal Kulkarni adapter->params.arch.sge_fl_db = F_DBPRIO | F_DBTYPE;
99823dde7c95SVishal Kulkarni adapter->params.arch.mps_tcam_size =
99833dde7c95SVishal Kulkarni NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
99843dde7c95SVishal Kulkarni adapter->params.arch.mps_rplc_size = 128;
99853dde7c95SVishal Kulkarni adapter->params.arch.nchan = NCHAN;
99863dde7c95SVishal Kulkarni adapter->params.arch.pm_stats_cnt = PM_NSTATS;
99873dde7c95SVishal Kulkarni adapter->params.arch.vfcount = 128;
99883dde7c95SVishal Kulkarni adapter->params.arch.cng_ch_bits_log = 2;
99893dde7c95SVishal Kulkarni } else if (is_t6(adapter->params.chip)) {
99903dde7c95SVishal Kulkarni adapter->params.arch.sge_fl_db = 0;
99913dde7c95SVishal Kulkarni adapter->params.arch.mps_tcam_size =
99923dde7c95SVishal Kulkarni NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
99933dde7c95SVishal Kulkarni adapter->params.arch.mps_rplc_size = 256;
99943dde7c95SVishal Kulkarni adapter->params.arch.nchan = 2;
99953dde7c95SVishal Kulkarni adapter->params.arch.pm_stats_cnt = T6_PM_NSTATS;
99963dde7c95SVishal Kulkarni adapter->params.arch.vfcount = 256;
99973dde7c95SVishal Kulkarni /* Congestion map will be for 2 channels so that
99983dde7c95SVishal Kulkarni * MPS can have 8 priority per port.
99993dde7c95SVishal Kulkarni */
100003dde7c95SVishal Kulkarni adapter->params.arch.cng_ch_bits_log = 3;
100013dde7c95SVishal Kulkarni } else {
100023dde7c95SVishal Kulkarni CH_ERR(adapter, "Device %d is not supported\n",
100033dde7c95SVishal Kulkarni adapter->params.pci.device_id);
100043dde7c95SVishal Kulkarni return -EINVAL;
100053dde7c95SVishal Kulkarni }
100063dde7c95SVishal Kulkarni
100073dde7c95SVishal Kulkarni adapter->params.pci.vpd_cap_addr =
100083dde7c95SVishal Kulkarni t4_os_find_pci_capability(adapter, PCI_CAP_ID_VPD);
100093dde7c95SVishal Kulkarni
10010de483253SVishal Kulkarni if (is_fpga(adapter->params.chip)) {
10011de483253SVishal Kulkarni /* FPGA */
1001256b2bdd1SGireesh Nagabhushana adapter->params.cim_la_size = 2 * CIMLA_SIZE;
10013de483253SVishal Kulkarni } else {
10014de483253SVishal Kulkarni /* ASIC */
1001556b2bdd1SGireesh Nagabhushana adapter->params.cim_la_size = CIMLA_SIZE;
10016de483253SVishal Kulkarni }
1001756b2bdd1SGireesh Nagabhushana
1001856b2bdd1SGireesh Nagabhushana init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
1001956b2bdd1SGireesh Nagabhushana
1002056b2bdd1SGireesh Nagabhushana /*
10021de483253SVishal Kulkarni * Default port and clock for debugging in case we can't reach FW.
1002256b2bdd1SGireesh Nagabhushana */
1002356b2bdd1SGireesh Nagabhushana adapter->params.nports = 1;
1002456b2bdd1SGireesh Nagabhushana adapter->params.portvec = 1;
1002556b2bdd1SGireesh Nagabhushana adapter->params.vpd.cclk = 50000;
1002656b2bdd1SGireesh Nagabhushana
10027de483253SVishal Kulkarni /* Set pci completion timeout value to 4 seconds. */
10028de483253SVishal Kulkarni set_pcie_completion_timeout(adapter, 0xd);
10029de483253SVishal Kulkarni return 0;
1003056b2bdd1SGireesh Nagabhushana }
1003156b2bdd1SGireesh Nagabhushana
100323dde7c95SVishal Kulkarni /**
100333dde7c95SVishal Kulkarni * t4_prep_master_pf - prepare SW for master PF operations
100343dde7c95SVishal Kulkarni * @adapter: the adapter
100353dde7c95SVishal Kulkarni *
100363dde7c95SVishal Kulkarni */
t4_prep_master_pf(struct adapter * adapter)100373dde7c95SVishal Kulkarni int t4_prep_master_pf(struct adapter *adapter)
1003856b2bdd1SGireesh Nagabhushana {
100393dde7c95SVishal Kulkarni int ret;
100403dde7c95SVishal Kulkarni
100413dde7c95SVishal Kulkarni ret = t4_prep_pf(adapter);
100423dde7c95SVishal Kulkarni if (ret < 0)
100433dde7c95SVishal Kulkarni return ret;
100443dde7c95SVishal Kulkarni
100453dde7c95SVishal Kulkarni ret = t4_get_flash_params(adapter);
100463dde7c95SVishal Kulkarni if (ret < 0) {
100473dde7c95SVishal Kulkarni CH_ERR(adapter,
100483dde7c95SVishal Kulkarni "Unable to retrieve Flash parameters ret = %d\n", -ret);
100493dde7c95SVishal Kulkarni return ret;
100503dde7c95SVishal Kulkarni }
100513dde7c95SVishal Kulkarni
100523dde7c95SVishal Kulkarni return 0;
100533dde7c95SVishal Kulkarni }
100543dde7c95SVishal Kulkarni
100553dde7c95SVishal Kulkarni /**
100563dde7c95SVishal Kulkarni * t4_prep_adapter - prepare SW and HW for operation
100573dde7c95SVishal Kulkarni * @adapter: the adapter
100583dde7c95SVishal Kulkarni * @reset: if true perform a HW reset
100593dde7c95SVishal Kulkarni *
100603dde7c95SVishal Kulkarni * Initialize adapter SW state for the various HW modules, set initial
100613dde7c95SVishal Kulkarni * values for some adapter tunables.
100623dde7c95SVishal Kulkarni */
t4_prep_adapter(struct adapter * adapter,bool reset)100633dde7c95SVishal Kulkarni int t4_prep_adapter(struct adapter *adapter, bool reset)
100643dde7c95SVishal Kulkarni {
100653dde7c95SVishal Kulkarni return t4_prep_master_pf(adapter);
100663dde7c95SVishal Kulkarni }
100673dde7c95SVishal Kulkarni
100683dde7c95SVishal Kulkarni /**
100693dde7c95SVishal Kulkarni * t4_shutdown_adapter - shut down adapter, host & wire
100703dde7c95SVishal Kulkarni * @adapter: the adapter
100713dde7c95SVishal Kulkarni *
100723dde7c95SVishal Kulkarni * Perform an emergency shutdown of the adapter and stop it from
100733dde7c95SVishal Kulkarni * continuing any further communication on the ports or DMA to the
100743dde7c95SVishal Kulkarni * host. This is typically used when the adapter and/or firmware
100753dde7c95SVishal Kulkarni * have crashed and we want to prevent any further accidental
100763dde7c95SVishal Kulkarni * communication with the rest of the world. This will also force
100773dde7c95SVishal Kulkarni * the port Link Status to go down -- if register writes work --
100783dde7c95SVishal Kulkarni * which should help our peers figure out that we're down.
100793dde7c95SVishal Kulkarni */
t4_shutdown_adapter(struct adapter * adapter)100803dde7c95SVishal Kulkarni int t4_shutdown_adapter(struct adapter *adapter)
100813dde7c95SVishal Kulkarni {
100823dde7c95SVishal Kulkarni int port;
100833dde7c95SVishal Kulkarni
100843dde7c95SVishal Kulkarni t4_intr_disable(adapter);
100853dde7c95SVishal Kulkarni t4_write_reg(adapter, A_DBG_GPIO_EN, 0);
100863dde7c95SVishal Kulkarni for_each_port(adapter, port) {
100873dde7c95SVishal Kulkarni u32 a_port_cfg = is_t4(adapter->params.chip) ?
100883dde7c95SVishal Kulkarni PORT_REG(port, A_XGMAC_PORT_CFG) :
100893dde7c95SVishal Kulkarni T5_PORT_REG(port, A_MAC_PORT_CFG);
100903dde7c95SVishal Kulkarni
100913dde7c95SVishal Kulkarni t4_write_reg(adapter, a_port_cfg,
100923dde7c95SVishal Kulkarni t4_read_reg(adapter, a_port_cfg)
100933dde7c95SVishal Kulkarni & ~V_SIGNAL_DET(1));
100943dde7c95SVishal Kulkarni }
100953dde7c95SVishal Kulkarni t4_set_reg_field(adapter, A_SGE_CONTROL, F_GLOBALENABLE, 0);
100963dde7c95SVishal Kulkarni
100973dde7c95SVishal Kulkarni return 0;
100983dde7c95SVishal Kulkarni }
100993dde7c95SVishal Kulkarni
101003dde7c95SVishal Kulkarni /**
101013dde7c95SVishal Kulkarni * t4_bar2_sge_qregs - return BAR2 SGE Queue register information
101023dde7c95SVishal Kulkarni * @adapter: the adapter
101033dde7c95SVishal Kulkarni * @qid: the Queue ID
101043dde7c95SVishal Kulkarni * @qtype: the Ingress or Egress type for @qid
101053dde7c95SVishal Kulkarni * @user: true if this request is for a user mode queue
101063dde7c95SVishal Kulkarni * @pbar2_qoffset: BAR2 Queue Offset
101073dde7c95SVishal Kulkarni * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
101083dde7c95SVishal Kulkarni *
101093dde7c95SVishal Kulkarni * Returns the BAR2 SGE Queue Registers information associated with the
101103dde7c95SVishal Kulkarni * indicated Absolute Queue ID. These are passed back in return value
101113dde7c95SVishal Kulkarni * pointers. @qtype should be T4_BAR2_QTYPE_EGRESS for Egress Queue
101123dde7c95SVishal Kulkarni * and T4_BAR2_QTYPE_INGRESS for Ingress Queues.
101133dde7c95SVishal Kulkarni *
101143dde7c95SVishal Kulkarni * This may return an error which indicates that BAR2 SGE Queue
101153dde7c95SVishal Kulkarni * registers aren't available. If an error is not returned, then the
101163dde7c95SVishal Kulkarni * following values are returned:
101173dde7c95SVishal Kulkarni *
101183dde7c95SVishal Kulkarni * *@pbar2_qoffset: the BAR2 Offset of the @qid Registers
101193dde7c95SVishal Kulkarni * *@pbar2_qid: the BAR2 SGE Queue ID or 0 of @qid
101203dde7c95SVishal Kulkarni *
101213dde7c95SVishal Kulkarni * If the returned BAR2 Queue ID is 0, then BAR2 SGE registers which
101223dde7c95SVishal Kulkarni * require the "Inferred Queue ID" ability may be used. E.g. the
101233dde7c95SVishal Kulkarni * Write Combining Doorbell Buffer. If the BAR2 Queue ID is not 0,
101243dde7c95SVishal Kulkarni * then these "Inferred Queue ID" register may not be used.
101253dde7c95SVishal Kulkarni */
t4_bar2_sge_qregs(struct adapter * adapter,unsigned int qid,enum t4_bar2_qtype qtype,int user,u64 * pbar2_qoffset,unsigned int * pbar2_qid)101263dde7c95SVishal Kulkarni int t4_bar2_sge_qregs(struct adapter *adapter,
101273dde7c95SVishal Kulkarni unsigned int qid,
101283dde7c95SVishal Kulkarni enum t4_bar2_qtype qtype,
101293dde7c95SVishal Kulkarni int user,
101303dde7c95SVishal Kulkarni u64 *pbar2_qoffset,
101313dde7c95SVishal Kulkarni unsigned int *pbar2_qid)
101323dde7c95SVishal Kulkarni {
101333dde7c95SVishal Kulkarni unsigned int page_shift, page_size, qpp_shift, qpp_mask;
101343dde7c95SVishal Kulkarni u64 bar2_page_offset, bar2_qoffset;
101353dde7c95SVishal Kulkarni unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred;
101363dde7c95SVishal Kulkarni
101373dde7c95SVishal Kulkarni /* T4 doesn't support BAR2 SGE Queue registers for kernel
101383dde7c95SVishal Kulkarni * mode queues.
101393dde7c95SVishal Kulkarni */
101403dde7c95SVishal Kulkarni if (!user && is_t4(adapter->params.chip))
101413dde7c95SVishal Kulkarni return -EINVAL;
101423dde7c95SVishal Kulkarni
101433dde7c95SVishal Kulkarni /* Get our SGE Page Size parameters.
101443dde7c95SVishal Kulkarni */
101453dde7c95SVishal Kulkarni page_shift = adapter->params.sge.hps + 10;
101463dde7c95SVishal Kulkarni page_size = 1 << page_shift;
101473dde7c95SVishal Kulkarni
101483dde7c95SVishal Kulkarni /* Get the right Queues per Page parameters for our Queue.
101493dde7c95SVishal Kulkarni */
101503dde7c95SVishal Kulkarni qpp_shift = (qtype == T4_BAR2_QTYPE_EGRESS
101513dde7c95SVishal Kulkarni ? adapter->params.sge.eq_qpp
101523dde7c95SVishal Kulkarni : adapter->params.sge.iq_qpp);
101533dde7c95SVishal Kulkarni qpp_mask = (1 << qpp_shift) - 1;
101543dde7c95SVishal Kulkarni
101553dde7c95SVishal Kulkarni /* Calculate the basics of the BAR2 SGE Queue register area:
101563dde7c95SVishal Kulkarni * o The BAR2 page the Queue registers will be in.
101573dde7c95SVishal Kulkarni * o The BAR2 Queue ID.
101583dde7c95SVishal Kulkarni * o The BAR2 Queue ID Offset into the BAR2 page.
101593dde7c95SVishal Kulkarni */
101603dde7c95SVishal Kulkarni bar2_page_offset = ((u64)(qid >> qpp_shift) << page_shift);
101613dde7c95SVishal Kulkarni bar2_qid = qid & qpp_mask;
101623dde7c95SVishal Kulkarni bar2_qid_offset = bar2_qid * SGE_UDB_SIZE;
101633dde7c95SVishal Kulkarni
101643dde7c95SVishal Kulkarni /* If the BAR2 Queue ID Offset is less than the Page Size, then the
101653dde7c95SVishal Kulkarni * hardware will infer the Absolute Queue ID simply from the writes to
101663dde7c95SVishal Kulkarni * the BAR2 Queue ID Offset within the BAR2 Page (and we need to use a
101673dde7c95SVishal Kulkarni * BAR2 Queue ID of 0 for those writes). Otherwise, we'll simply
101683dde7c95SVishal Kulkarni * write to the first BAR2 SGE Queue Area within the BAR2 Page with
101693dde7c95SVishal Kulkarni * the BAR2 Queue ID and the hardware will infer the Absolute Queue ID
101703dde7c95SVishal Kulkarni * from the BAR2 Page and BAR2 Queue ID.
101713dde7c95SVishal Kulkarni *
101723dde7c95SVishal Kulkarni * One important censequence of this is that some BAR2 SGE registers
101733dde7c95SVishal Kulkarni * have a "Queue ID" field and we can write the BAR2 SGE Queue ID
101743dde7c95SVishal Kulkarni * there. But other registers synthesize the SGE Queue ID purely
101753dde7c95SVishal Kulkarni * from the writes to the registers -- the Write Combined Doorbell
101763dde7c95SVishal Kulkarni * Buffer is a good example. These BAR2 SGE Registers are only
101773dde7c95SVishal Kulkarni * available for those BAR2 SGE Register areas where the SGE Absolute
101783dde7c95SVishal Kulkarni * Queue ID can be inferred from simple writes.
101793dde7c95SVishal Kulkarni */
101803dde7c95SVishal Kulkarni bar2_qoffset = bar2_page_offset;
101813dde7c95SVishal Kulkarni bar2_qinferred = (bar2_qid_offset < page_size);
101823dde7c95SVishal Kulkarni if (bar2_qinferred) {
101833dde7c95SVishal Kulkarni bar2_qoffset += bar2_qid_offset;
101843dde7c95SVishal Kulkarni bar2_qid = 0;
101853dde7c95SVishal Kulkarni }
101863dde7c95SVishal Kulkarni
101873dde7c95SVishal Kulkarni *pbar2_qoffset = bar2_qoffset;
101883dde7c95SVishal Kulkarni *pbar2_qid = bar2_qid;
101893dde7c95SVishal Kulkarni return 0;
101903dde7c95SVishal Kulkarni }
101913dde7c95SVishal Kulkarni
101923dde7c95SVishal Kulkarni /**
101933dde7c95SVishal Kulkarni * t4_init_devlog_params - initialize adapter->params.devlog
101943dde7c95SVishal Kulkarni * @adap: the adapter
101953dde7c95SVishal Kulkarni * @fw_attach: whether we can talk to the firmware
101963dde7c95SVishal Kulkarni *
101973dde7c95SVishal Kulkarni * Initialize various fields of the adapter's Firmware Device Log
101983dde7c95SVishal Kulkarni * Parameters structure.
101993dde7c95SVishal Kulkarni */
t4_init_devlog_params(struct adapter * adap,int fw_attach)102003dde7c95SVishal Kulkarni int t4_init_devlog_params(struct adapter *adap, int fw_attach)
102013dde7c95SVishal Kulkarni {
102023dde7c95SVishal Kulkarni struct devlog_params *dparams = &adap->params.devlog;
102033dde7c95SVishal Kulkarni u32 pf_dparams;
102043dde7c95SVishal Kulkarni unsigned int devlog_meminfo;
102053dde7c95SVishal Kulkarni struct fw_devlog_cmd devlog_cmd;
102063dde7c95SVishal Kulkarni int ret;
102073dde7c95SVishal Kulkarni
102083dde7c95SVishal Kulkarni /* If we're dealing with newer firmware, the Device Log Paramerters
102093dde7c95SVishal Kulkarni * are stored in a designated register which allows us to access the
102103dde7c95SVishal Kulkarni * Device Log even if we can't talk to the firmware.
102113dde7c95SVishal Kulkarni */
102123dde7c95SVishal Kulkarni pf_dparams =
102133dde7c95SVishal Kulkarni t4_read_reg(adap, PCIE_FW_REG(A_PCIE_FW_PF, PCIE_FW_PF_DEVLOG));
102143dde7c95SVishal Kulkarni if (pf_dparams) {
102153dde7c95SVishal Kulkarni unsigned int nentries, nentries128;
102163dde7c95SVishal Kulkarni
102173dde7c95SVishal Kulkarni dparams->memtype = G_PCIE_FW_PF_DEVLOG_MEMTYPE(pf_dparams);
102183dde7c95SVishal Kulkarni dparams->start = G_PCIE_FW_PF_DEVLOG_ADDR16(pf_dparams) << 4;
102193dde7c95SVishal Kulkarni
102203dde7c95SVishal Kulkarni nentries128 = G_PCIE_FW_PF_DEVLOG_NENTRIES128(pf_dparams);
102213dde7c95SVishal Kulkarni nentries = (nentries128 + 1) * 128;
102223dde7c95SVishal Kulkarni dparams->size = nentries * sizeof(struct fw_devlog_e);
102233dde7c95SVishal Kulkarni
102243dde7c95SVishal Kulkarni return 0;
102253dde7c95SVishal Kulkarni }
102263dde7c95SVishal Kulkarni
102273dde7c95SVishal Kulkarni /*
102283dde7c95SVishal Kulkarni * For any failing returns ...
102293dde7c95SVishal Kulkarni */
102303dde7c95SVishal Kulkarni memset(dparams, 0, sizeof *dparams);
102313dde7c95SVishal Kulkarni
102323dde7c95SVishal Kulkarni /*
102333dde7c95SVishal Kulkarni * If we can't talk to the firmware, there's really nothing we can do
102343dde7c95SVishal Kulkarni * at this point.
102353dde7c95SVishal Kulkarni */
102363dde7c95SVishal Kulkarni if (!fw_attach)
102373dde7c95SVishal Kulkarni return -ENXIO;
102383dde7c95SVishal Kulkarni
102393dde7c95SVishal Kulkarni /* Otherwise, ask the firmware for it's Device Log Parameters.
102403dde7c95SVishal Kulkarni */
102413dde7c95SVishal Kulkarni memset(&devlog_cmd, 0, sizeof devlog_cmd);
102423dde7c95SVishal Kulkarni devlog_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_DEVLOG_CMD) |
102433dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ);
102443dde7c95SVishal Kulkarni devlog_cmd.retval_len16 = cpu_to_be32(FW_LEN16(devlog_cmd));
102453dde7c95SVishal Kulkarni ret = t4_wr_mbox(adap, adap->mbox, &devlog_cmd, sizeof(devlog_cmd),
102463dde7c95SVishal Kulkarni &devlog_cmd);
102473dde7c95SVishal Kulkarni if (ret)
102483dde7c95SVishal Kulkarni return ret;
102493dde7c95SVishal Kulkarni
102503dde7c95SVishal Kulkarni devlog_meminfo =
102513dde7c95SVishal Kulkarni be32_to_cpu(devlog_cmd.memtype_devlog_memaddr16_devlog);
102523dde7c95SVishal Kulkarni dparams->memtype = G_FW_DEVLOG_CMD_MEMTYPE_DEVLOG(devlog_meminfo);
102533dde7c95SVishal Kulkarni dparams->start = G_FW_DEVLOG_CMD_MEMADDR16_DEVLOG(devlog_meminfo) << 4;
102543dde7c95SVishal Kulkarni dparams->size = be32_to_cpu(devlog_cmd.memsize_devlog);
102553dde7c95SVishal Kulkarni
102563dde7c95SVishal Kulkarni return 0;
102573dde7c95SVishal Kulkarni }
102583dde7c95SVishal Kulkarni
102593dde7c95SVishal Kulkarni /**
102603dde7c95SVishal Kulkarni * t4_init_sge_params - initialize adap->params.sge
102613dde7c95SVishal Kulkarni * @adapter: the adapter
102623dde7c95SVishal Kulkarni *
102633dde7c95SVishal Kulkarni * Initialize various fields of the adapter's SGE Parameters structure.
102643dde7c95SVishal Kulkarni */
t4_init_sge_params(struct adapter * adapter)102653dde7c95SVishal Kulkarni int t4_init_sge_params(struct adapter *adapter)
102663dde7c95SVishal Kulkarni {
102673dde7c95SVishal Kulkarni struct sge_params *sge_params = &adapter->params.sge;
102683dde7c95SVishal Kulkarni u32 hps, qpp;
102693dde7c95SVishal Kulkarni unsigned int s_hps, s_qpp;
102703dde7c95SVishal Kulkarni
102713dde7c95SVishal Kulkarni /* Extract the SGE Page Size for our PF.
102723dde7c95SVishal Kulkarni */
102733dde7c95SVishal Kulkarni hps = t4_read_reg(adapter, A_SGE_HOST_PAGE_SIZE);
102743dde7c95SVishal Kulkarni s_hps = (S_HOSTPAGESIZEPF0 +
102753dde7c95SVishal Kulkarni (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * adapter->pf);
102763dde7c95SVishal Kulkarni sge_params->hps = ((hps >> s_hps) & M_HOSTPAGESIZEPF0);
102773dde7c95SVishal Kulkarni
102783dde7c95SVishal Kulkarni /* Extract the SGE Egress and Ingess Queues Per Page for our PF.
102793dde7c95SVishal Kulkarni */
102803dde7c95SVishal Kulkarni s_qpp = (S_QUEUESPERPAGEPF0 +
102813dde7c95SVishal Kulkarni (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * adapter->pf);
102823dde7c95SVishal Kulkarni qpp = t4_read_reg(adapter, A_SGE_EGRESS_QUEUES_PER_PAGE_PF);
102833dde7c95SVishal Kulkarni sge_params->eq_qpp = ((qpp >> s_qpp) & M_QUEUESPERPAGEPF0);
102843dde7c95SVishal Kulkarni qpp = t4_read_reg(adapter, A_SGE_INGRESS_QUEUES_PER_PAGE_PF);
102853dde7c95SVishal Kulkarni sge_params->iq_qpp = ((qpp >> s_qpp) & M_QUEUESPERPAGEPF0);
102863dde7c95SVishal Kulkarni
102873dde7c95SVishal Kulkarni return 0;
102883dde7c95SVishal Kulkarni }
102893dde7c95SVishal Kulkarni
102903dde7c95SVishal Kulkarni /**
102913dde7c95SVishal Kulkarni * t4_init_tp_params - initialize adap->params.tp
102923dde7c95SVishal Kulkarni * @adap: the adapter
102933dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
102943dde7c95SVishal Kulkarni *
102953dde7c95SVishal Kulkarni * Initialize various fields of the adapter's TP Parameters structure.
102963dde7c95SVishal Kulkarni */
t4_init_tp_params(struct adapter * adap,bool sleep_ok)102973dde7c95SVishal Kulkarni int t4_init_tp_params(struct adapter *adap, bool sleep_ok)
102983dde7c95SVishal Kulkarni {
102997e6ad469SVishal Kulkarni u32 param, val, v;
103007e6ad469SVishal Kulkarni int chan, ret;
103013dde7c95SVishal Kulkarni
103023dde7c95SVishal Kulkarni v = t4_read_reg(adap, A_TP_TIMER_RESOLUTION);
103033dde7c95SVishal Kulkarni adap->params.tp.tre = G_TIMERRESOLUTION(v);
103043dde7c95SVishal Kulkarni adap->params.tp.dack_re = G_DELAYEDACKRESOLUTION(v);
103053dde7c95SVishal Kulkarni
103063dde7c95SVishal Kulkarni /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
103073dde7c95SVishal Kulkarni for (chan = 0; chan < NCHAN; chan++)
103083dde7c95SVishal Kulkarni adap->params.tp.tx_modq[chan] = chan;
103093dde7c95SVishal Kulkarni
103107e6ad469SVishal Kulkarni /* Cache the adapter's Compressed Filter Mode/Mask and global Ingress
103113dde7c95SVishal Kulkarni * Configuration.
103123dde7c95SVishal Kulkarni */
103137e6ad469SVishal Kulkarni
103147e6ad469SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
103157e6ad469SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_FILTER) |
103167e6ad469SVishal Kulkarni V_FW_PARAMS_PARAM_Y(FW_PARAM_DEV_FILTER_MODE_MASK));
103177e6ad469SVishal Kulkarni
103187e6ad469SVishal Kulkarni /* Read current value */
103197e6ad469SVishal Kulkarni ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,
103207e6ad469SVishal Kulkarni ¶m, &val);
103217e6ad469SVishal Kulkarni if (ret == 0) {
103227e6ad469SVishal Kulkarni CH_INFO(adap,
103237e6ad469SVishal Kulkarni "Current filter mode/mask 0x%x:0x%x\n",
103247e6ad469SVishal Kulkarni G_FW_PARAMS_PARAM_FILTER_MODE(val),
103257e6ad469SVishal Kulkarni G_FW_PARAMS_PARAM_FILTER_MASK(val));
103267e6ad469SVishal Kulkarni adap->params.tp.vlan_pri_map = G_FW_PARAMS_PARAM_FILTER_MODE(val);
103277e6ad469SVishal Kulkarni adap->params.tp.filter_mask = G_FW_PARAMS_PARAM_FILTER_MASK(val);
103287e6ad469SVishal Kulkarni } else {
103297e6ad469SVishal Kulkarni CH_WARN(adap,
103307e6ad469SVishal Kulkarni "Reading filter mode/mask not supported via fw api, "
103317e6ad469SVishal Kulkarni "falling back to older indirect-reg-read \n");
103327e6ad469SVishal Kulkarni
103337e6ad469SVishal Kulkarni /* Incase of older-fw (which doesn't expose the api
103347e6ad469SVishal Kulkarni * FW_PARAM_DEV_FILTER_MODE_MASK) and newer-driver (which uses
103357e6ad469SVishal Kulkarni * the fw api) combination, fall-back to older method of reading
103367e6ad469SVishal Kulkarni * the filter mode from indirect-register
103377e6ad469SVishal Kulkarni */
103383dde7c95SVishal Kulkarni t4_tp_pio_read(adap, &adap->params.tp.vlan_pri_map, 1,
103393dde7c95SVishal Kulkarni A_TP_VLAN_PRI_MAP, sleep_ok);
103407e6ad469SVishal Kulkarni
103417e6ad469SVishal Kulkarni /* With the older-fw and newer-driver combination we might run
103427e6ad469SVishal Kulkarni * into an issue when user wants to use hash filter region but
103437e6ad469SVishal Kulkarni * the filter_mask is zero, in this case filter_mask validation
103447e6ad469SVishal Kulkarni * is tough. To avoid that we set the filter_mask same as filter
103457e6ad469SVishal Kulkarni * mode, which will behave exactly as the older way of ignoring
103467e6ad469SVishal Kulkarni * the filter mask validation.
103477e6ad469SVishal Kulkarni */
103487e6ad469SVishal Kulkarni adap->params.tp.filter_mask = adap->params.tp.vlan_pri_map;
103497e6ad469SVishal Kulkarni }
103507e6ad469SVishal Kulkarni
103513dde7c95SVishal Kulkarni t4_tp_pio_read(adap, &adap->params.tp.ingress_config, 1,
103523dde7c95SVishal Kulkarni A_TP_INGRESS_CONFIG, sleep_ok);
103533dde7c95SVishal Kulkarni
103543dde7c95SVishal Kulkarni /* For T6, cache the adapter's compressed error vector
103553dde7c95SVishal Kulkarni * and passing outer header info for encapsulated packets.
103563dde7c95SVishal Kulkarni */
103573dde7c95SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) {
103583dde7c95SVishal Kulkarni v = t4_read_reg(adap, A_TP_OUT_CONFIG);
103593dde7c95SVishal Kulkarni adap->params.tp.rx_pkt_encap = (v & F_CRXPKTENC) ? 1 : 0;
103603dde7c95SVishal Kulkarni }
103613dde7c95SVishal Kulkarni
103623dde7c95SVishal Kulkarni /* Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
103633dde7c95SVishal Kulkarni * shift positions of several elements of the Compressed Filter Tuple
103643dde7c95SVishal Kulkarni * for this adapter which we need frequently ...
103653dde7c95SVishal Kulkarni */
103663dde7c95SVishal Kulkarni adap->params.tp.fcoe_shift = t4_filter_field_shift(adap, F_FCOE);
103673dde7c95SVishal Kulkarni adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
103683dde7c95SVishal Kulkarni adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
103693dde7c95SVishal Kulkarni adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
103703dde7c95SVishal Kulkarni adap->params.tp.tos_shift = t4_filter_field_shift(adap, F_TOS);
103713dde7c95SVishal Kulkarni adap->params.tp.protocol_shift = t4_filter_field_shift(adap, F_PROTOCOL);
103723dde7c95SVishal Kulkarni adap->params.tp.ethertype_shift = t4_filter_field_shift(adap,
103733dde7c95SVishal Kulkarni F_ETHERTYPE);
103743dde7c95SVishal Kulkarni adap->params.tp.macmatch_shift = t4_filter_field_shift(adap,
103753dde7c95SVishal Kulkarni F_MACMATCH);
103763dde7c95SVishal Kulkarni adap->params.tp.matchtype_shift = t4_filter_field_shift(adap,
103773dde7c95SVishal Kulkarni F_MPSHITTYPE);
103783dde7c95SVishal Kulkarni adap->params.tp.frag_shift = t4_filter_field_shift(adap,
103793dde7c95SVishal Kulkarni F_FRAGMENTATION);
103803dde7c95SVishal Kulkarni return 0;
103813dde7c95SVishal Kulkarni }
103823dde7c95SVishal Kulkarni
103833dde7c95SVishal Kulkarni /**
103843dde7c95SVishal Kulkarni * t4_filter_field_shift - calculate filter field shift
103853dde7c95SVishal Kulkarni * @adap: the adapter
103863dde7c95SVishal Kulkarni * @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
103873dde7c95SVishal Kulkarni *
103883dde7c95SVishal Kulkarni * Return the shift position of a filter field within the Compressed
103893dde7c95SVishal Kulkarni * Filter Tuple. The filter field is specified via its selection bit
103903dde7c95SVishal Kulkarni * within TP_VLAN_PRI_MAL (filter mode). E.g. F_VLAN.
103913dde7c95SVishal Kulkarni */
t4_filter_field_shift(const struct adapter * adap,int filter_sel)103923dde7c95SVishal Kulkarni int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
103933dde7c95SVishal Kulkarni {
103943dde7c95SVishal Kulkarni unsigned int filter_mode = adap->params.tp.vlan_pri_map;
103953dde7c95SVishal Kulkarni unsigned int sel;
103963dde7c95SVishal Kulkarni int field_shift;
103973dde7c95SVishal Kulkarni
103983dde7c95SVishal Kulkarni if ((filter_mode & filter_sel) == 0)
103993dde7c95SVishal Kulkarni return -1;
104003dde7c95SVishal Kulkarni
104013dde7c95SVishal Kulkarni for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
104023dde7c95SVishal Kulkarni switch (filter_mode & sel) {
104033dde7c95SVishal Kulkarni case F_FCOE:
104043dde7c95SVishal Kulkarni field_shift += W_FT_FCOE;
104053dde7c95SVishal Kulkarni break;
104063dde7c95SVishal Kulkarni case F_PORT:
104073dde7c95SVishal Kulkarni field_shift += W_FT_PORT;
104083dde7c95SVishal Kulkarni break;
104093dde7c95SVishal Kulkarni case F_VNIC_ID:
104103dde7c95SVishal Kulkarni field_shift += W_FT_VNIC_ID;
104113dde7c95SVishal Kulkarni break;
104123dde7c95SVishal Kulkarni case F_VLAN:
104133dde7c95SVishal Kulkarni field_shift += W_FT_VLAN;
104143dde7c95SVishal Kulkarni break;
104153dde7c95SVishal Kulkarni case F_TOS:
104163dde7c95SVishal Kulkarni field_shift += W_FT_TOS;
104173dde7c95SVishal Kulkarni break;
104183dde7c95SVishal Kulkarni case F_PROTOCOL:
104193dde7c95SVishal Kulkarni field_shift += W_FT_PROTOCOL;
104203dde7c95SVishal Kulkarni break;
104213dde7c95SVishal Kulkarni case F_ETHERTYPE:
104223dde7c95SVishal Kulkarni field_shift += W_FT_ETHERTYPE;
104233dde7c95SVishal Kulkarni break;
104243dde7c95SVishal Kulkarni case F_MACMATCH:
104253dde7c95SVishal Kulkarni field_shift += W_FT_MACMATCH;
104263dde7c95SVishal Kulkarni break;
104273dde7c95SVishal Kulkarni case F_MPSHITTYPE:
104283dde7c95SVishal Kulkarni field_shift += W_FT_MPSHITTYPE;
104293dde7c95SVishal Kulkarni break;
104303dde7c95SVishal Kulkarni case F_FRAGMENTATION:
104313dde7c95SVishal Kulkarni field_shift += W_FT_FRAGMENTATION;
104323dde7c95SVishal Kulkarni break;
104333dde7c95SVishal Kulkarni }
104343dde7c95SVishal Kulkarni }
104353dde7c95SVishal Kulkarni return field_shift;
104363dde7c95SVishal Kulkarni }
104373dde7c95SVishal Kulkarni
104383dde7c95SVishal Kulkarni /**
104393dde7c95SVishal Kulkarni * t4_create_filter_info - return Compressed Filter Value/Mask tuple
104403dde7c95SVishal Kulkarni * @adapter: the adapter
104413dde7c95SVishal Kulkarni * @filter_value: Filter Value return value pointer
104423dde7c95SVishal Kulkarni * @filter_mask: Filter Mask return value pointer
104433dde7c95SVishal Kulkarni * @fcoe: FCoE filter selection
104443dde7c95SVishal Kulkarni * @port: physical port filter selection
104453dde7c95SVishal Kulkarni * @vnic: Virtual NIC ID filter selection
104463dde7c95SVishal Kulkarni * @vlan: VLAN ID filter selection
104473dde7c95SVishal Kulkarni * @vlan_pcp: VLAN Priority Code Point
104483dde7c95SVishal Kulkarni * @vlan_dei: VLAN Drop Eligibility Indicator
104493dde7c95SVishal Kulkarni * @tos: Type Of Server filter selection
104503dde7c95SVishal Kulkarni * @protocol: IP Protocol filter selection
104513dde7c95SVishal Kulkarni * @ethertype: Ethernet Type filter selection
104523dde7c95SVishal Kulkarni * @macmatch: MPS MAC Index filter selection
104533dde7c95SVishal Kulkarni * @matchtype: MPS Hit Type filter selection
104543dde7c95SVishal Kulkarni * @frag: IP Fragmentation filter selection
104553dde7c95SVishal Kulkarni *
104563dde7c95SVishal Kulkarni * Construct a Compressed Filter Value/Mask tuple based on a set of
104573dde7c95SVishal Kulkarni * "filter selection" values. For each passed filter selection value
104583dde7c95SVishal Kulkarni * which is greater than or equal to 0, we put that value into the
104593dde7c95SVishal Kulkarni * constructed Filter Value and the appropriate mask into the Filter
104603dde7c95SVishal Kulkarni * Mask. If a filter selections is specified which is not currently
104613dde7c95SVishal Kulkarni * configured into the hardware, an error will be returned. Otherwise
104623dde7c95SVishal Kulkarni * the constructed FIlter Value/Mask tuple will be returned via the
104633dde7c95SVishal Kulkarni * specified return value pointers and success will be returned.
104643dde7c95SVishal Kulkarni *
104653dde7c95SVishal Kulkarni * All filter selection values and the returned Filter Value/Mask values
104663dde7c95SVishal Kulkarni * are in Host-Endian format.
104673dde7c95SVishal Kulkarni */
t4_create_filter_info(const struct adapter * adapter,u64 * filter_value,u64 * filter_mask,int fcoe,int port,int vnic,int vlan,int vlan_pcp,int vlan_dei,int tos,int protocol,int ethertype,int macmatch,int matchtype,int frag)104683dde7c95SVishal Kulkarni int t4_create_filter_info(const struct adapter *adapter,
104693dde7c95SVishal Kulkarni u64 *filter_value, u64 *filter_mask,
104703dde7c95SVishal Kulkarni int fcoe, int port, int vnic,
104713dde7c95SVishal Kulkarni int vlan, int vlan_pcp, int vlan_dei,
104723dde7c95SVishal Kulkarni int tos, int protocol, int ethertype,
104733dde7c95SVishal Kulkarni int macmatch, int matchtype, int frag)
104743dde7c95SVishal Kulkarni {
104753dde7c95SVishal Kulkarni const struct tp_params *tp = &adapter->params.tp;
104763dde7c95SVishal Kulkarni u64 v, m;
104773dde7c95SVishal Kulkarni
104783dde7c95SVishal Kulkarni /*
104793dde7c95SVishal Kulkarni * If any selected filter field isn't enabled, return an error.
104803dde7c95SVishal Kulkarni */
104813dde7c95SVishal Kulkarni #define BAD_FILTER(__field) \
104823dde7c95SVishal Kulkarni ((__field) >= 0 && tp->__field##_shift < 0)
104833dde7c95SVishal Kulkarni if (BAD_FILTER(fcoe) ||
104843dde7c95SVishal Kulkarni BAD_FILTER(port) ||
104853dde7c95SVishal Kulkarni BAD_FILTER(vnic) ||
104863dde7c95SVishal Kulkarni BAD_FILTER(vlan) ||
104873dde7c95SVishal Kulkarni BAD_FILTER(tos) ||
104883dde7c95SVishal Kulkarni BAD_FILTER(protocol) ||
104893dde7c95SVishal Kulkarni BAD_FILTER(ethertype) ||
104903dde7c95SVishal Kulkarni BAD_FILTER(macmatch) ||
104913dde7c95SVishal Kulkarni BAD_FILTER(matchtype) ||
104923dde7c95SVishal Kulkarni BAD_FILTER(frag))
104933dde7c95SVishal Kulkarni return -EINVAL;
104943dde7c95SVishal Kulkarni #undef BAD_FILTER
104953dde7c95SVishal Kulkarni
104963dde7c95SVishal Kulkarni /*
104973dde7c95SVishal Kulkarni * We have to have VLAN ID selected if we want to also select on
104983dde7c95SVishal Kulkarni * either the Priority Code Point or Drop Eligibility Indicator
104993dde7c95SVishal Kulkarni * fields.
105003dde7c95SVishal Kulkarni */
105013dde7c95SVishal Kulkarni if ((vlan_pcp >= 0 || vlan_dei >= 0) && vlan < 0)
105023dde7c95SVishal Kulkarni return -EINVAL;
105033dde7c95SVishal Kulkarni
105043dde7c95SVishal Kulkarni /*
105053dde7c95SVishal Kulkarni * Construct Filter Value and Mask.
105063dde7c95SVishal Kulkarni */
105073dde7c95SVishal Kulkarni v = m = 0;
105083dde7c95SVishal Kulkarni #define SET_FILTER_FIELD(__field, __width) \
105093dde7c95SVishal Kulkarni do { \
105103dde7c95SVishal Kulkarni if ((__field) >= 0) { \
105113dde7c95SVishal Kulkarni const int shift = tp->__field##_shift; \
105123dde7c95SVishal Kulkarni \
105133dde7c95SVishal Kulkarni v |= (__field) << shift; \
105143dde7c95SVishal Kulkarni m |= ((1ULL << (__width)) - 1) << shift; \
105153dde7c95SVishal Kulkarni } \
105163dde7c95SVishal Kulkarni } while (0)
105173dde7c95SVishal Kulkarni SET_FILTER_FIELD(fcoe, W_FT_FCOE);
105183dde7c95SVishal Kulkarni SET_FILTER_FIELD(port, W_FT_PORT);
105193dde7c95SVishal Kulkarni SET_FILTER_FIELD(tos, W_FT_TOS);
105203dde7c95SVishal Kulkarni SET_FILTER_FIELD(protocol, W_FT_PROTOCOL);
105213dde7c95SVishal Kulkarni SET_FILTER_FIELD(ethertype, W_FT_ETHERTYPE);
105223dde7c95SVishal Kulkarni SET_FILTER_FIELD(macmatch, W_FT_MACMATCH);
105233dde7c95SVishal Kulkarni SET_FILTER_FIELD(matchtype, W_FT_MPSHITTYPE);
105243dde7c95SVishal Kulkarni SET_FILTER_FIELD(frag, W_FT_FRAGMENTATION);
105253dde7c95SVishal Kulkarni #undef SET_FILTER_FIELD
105263dde7c95SVishal Kulkarni
105273dde7c95SVishal Kulkarni /*
105283dde7c95SVishal Kulkarni * We handle VNIC ID and VLANs separately because they're slightly
105293dde7c95SVishal Kulkarni * different than the rest of the fields. Both require that a
105303dde7c95SVishal Kulkarni * corresponding "valid" bit be set in the Filter Value and Mask.
105313dde7c95SVishal Kulkarni * These bits are in the top bit of the field. Additionally, we can
105323dde7c95SVishal Kulkarni * select the Priority Code Point and Drop Eligibility Indicator
105333dde7c95SVishal Kulkarni * fields for VLANs as an option. Remember that the format of a VLAN
105343dde7c95SVishal Kulkarni * Tag is:
105353dde7c95SVishal Kulkarni *
105363dde7c95SVishal Kulkarni * bits: 3 1 12
105373dde7c95SVishal Kulkarni * +---+-+------------+
105383dde7c95SVishal Kulkarni * |PCP|D| VLAN ID |
105393dde7c95SVishal Kulkarni * +---+-+------------+
105403dde7c95SVishal Kulkarni */
105413dde7c95SVishal Kulkarni if (vnic >= 0) {
105423dde7c95SVishal Kulkarni v |= ((1ULL << (W_FT_VNIC_ID-1)) | vnic) << tp->vnic_shift;
105433dde7c95SVishal Kulkarni m |= ((1ULL << W_FT_VNIC_ID) - 1) << tp->vnic_shift;
105443dde7c95SVishal Kulkarni }
105453dde7c95SVishal Kulkarni if (vlan >= 0) {
105463dde7c95SVishal Kulkarni v |= ((1ULL << (W_FT_VLAN-1)) | vlan) << tp->vlan_shift;
105473dde7c95SVishal Kulkarni m |= ((1ULL << (W_FT_VLAN-1)) | 0xfff) << tp->vlan_shift;
105483dde7c95SVishal Kulkarni
105493dde7c95SVishal Kulkarni if (vlan_dei >= 0) {
105503dde7c95SVishal Kulkarni v |= vlan_dei << (tp->vlan_shift + 12);
105513dde7c95SVishal Kulkarni m |= 0x7 << (tp->vlan_shift + 12);
105523dde7c95SVishal Kulkarni }
105533dde7c95SVishal Kulkarni if (vlan_pcp >= 0) {
105543dde7c95SVishal Kulkarni v |= vlan_pcp << (tp->vlan_shift + 13);
105553dde7c95SVishal Kulkarni m |= 0x7 << (tp->vlan_shift + 13);
105563dde7c95SVishal Kulkarni }
105573dde7c95SVishal Kulkarni }
105583dde7c95SVishal Kulkarni
105593dde7c95SVishal Kulkarni /*
105603dde7c95SVishal Kulkarni * Pass back computed Filter Value and Mask; return success.
105613dde7c95SVishal Kulkarni */
105623dde7c95SVishal Kulkarni *filter_value = v;
105633dde7c95SVishal Kulkarni *filter_mask = m;
105643dde7c95SVishal Kulkarni return 0;
105653dde7c95SVishal Kulkarni }
105663dde7c95SVishal Kulkarni
t4_init_rss_mode(struct adapter * adap,int mbox)105673dde7c95SVishal Kulkarni int t4_init_rss_mode(struct adapter *adap, int mbox)
105683dde7c95SVishal Kulkarni {
105693dde7c95SVishal Kulkarni int i, ret;
105703dde7c95SVishal Kulkarni struct fw_rss_vi_config_cmd rvc;
105713dde7c95SVishal Kulkarni
105723dde7c95SVishal Kulkarni memset(&rvc, 0, sizeof(rvc));
105733dde7c95SVishal Kulkarni
105743dde7c95SVishal Kulkarni for_each_port(adap, i) {
105753dde7c95SVishal Kulkarni struct port_info *p = adap2pinfo(adap, i);
105763dde7c95SVishal Kulkarni rvc.op_to_viid =
105773dde7c95SVishal Kulkarni cpu_to_be32(V_FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) |
105783dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ |
105793dde7c95SVishal Kulkarni V_FW_RSS_VI_CONFIG_CMD_VIID(p->viid));
105803dde7c95SVishal Kulkarni rvc.retval_len16 = cpu_to_be32(FW_LEN16(rvc));
105813dde7c95SVishal Kulkarni ret = t4_wr_mbox(adap, mbox, &rvc, sizeof(rvc), &rvc);
105823dde7c95SVishal Kulkarni if (ret)
105833dde7c95SVishal Kulkarni return ret;
105843dde7c95SVishal Kulkarni p->rss_mode = be32_to_cpu(rvc.u.basicvirtual.defaultq_to_udpen);
105853dde7c95SVishal Kulkarni }
105863dde7c95SVishal Kulkarni return 0;
105873dde7c95SVishal Kulkarni }
105883dde7c95SVishal Kulkarni
t4_init_portmirror(struct port_info * pi,int mbox,int port,int pf,int vf)105893dde7c95SVishal Kulkarni static int t4_init_portmirror(struct port_info *pi, int mbox,
105903dde7c95SVishal Kulkarni int port, int pf, int vf)
105913dde7c95SVishal Kulkarni {
105923dde7c95SVishal Kulkarni struct adapter *adapter = pi->adapter;
105933dde7c95SVishal Kulkarni int ret;
105947e6ad469SVishal Kulkarni u8 vivld = 0, vin = 0;
105953dde7c95SVishal Kulkarni
105967e6ad469SVishal Kulkarni ret = t4_alloc_vi(pi->adapter, mbox, port, pf, vf, 1, NULL, NULL,
105977e6ad469SVishal Kulkarni &vivld, &vin);
105983dde7c95SVishal Kulkarni if (ret < 0)
105993dde7c95SVishal Kulkarni return ret;
106003dde7c95SVishal Kulkarni
106013dde7c95SVishal Kulkarni pi->viid_mirror = ret;
106027e6ad469SVishal Kulkarni
106037e6ad469SVishal Kulkarni /* If fw supports returning the VIN as part of FW_VI_CMD,
106047e6ad469SVishal Kulkarni * save the returned values.
106057e6ad469SVishal Kulkarni */
106067e6ad469SVishal Kulkarni if (adapter->params.viid_smt_extn_support) {
106077e6ad469SVishal Kulkarni pi->vivld_mirror = vivld;
106087e6ad469SVishal Kulkarni pi->vin_mirror = vin;
106097e6ad469SVishal Kulkarni } else {
106107e6ad469SVishal Kulkarni /* Retrieve the values from VIID */
106117e6ad469SVishal Kulkarni pi->vivld_mirror = G_FW_VIID_VIVLD(pi->viid_mirror);
106127e6ad469SVishal Kulkarni pi->vin_mirror = G_FW_VIID_VIN(pi->viid_mirror);
106137e6ad469SVishal Kulkarni }
106147e6ad469SVishal Kulkarni
106157e6ad469SVishal Kulkarni CH_INFO(pi->adapter, "Port %d Traffic Mirror PF = %u; VF = %u\n",
106167e6ad469SVishal Kulkarni port, pf, pi->vin_mirror);
106173dde7c95SVishal Kulkarni return 0;
106183dde7c95SVishal Kulkarni }
106193dde7c95SVishal Kulkarni
t4_mirror_init(struct adapter * adap,int mbox,int pf,int vf,bool enable_ringbb)106207e6ad469SVishal Kulkarni int t4_mirror_init(struct adapter *adap, int mbox, int pf, int vf,
106217e6ad469SVishal Kulkarni bool enable_ringbb)
106223dde7c95SVishal Kulkarni {
106233dde7c95SVishal Kulkarni int ret, i, j = 0;
106243dde7c95SVishal Kulkarni
106253dde7c95SVishal Kulkarni for_each_port(adap, i) {
106263dde7c95SVishal Kulkarni struct port_info *pi = adap2pinfo(adap, i);
106273dde7c95SVishal Kulkarni
106287e6ad469SVishal Kulkarni /* We want mirroring only on Port0 for ringbackbone
106297e6ad469SVishal Kulkarni * configuration.
106307e6ad469SVishal Kulkarni */
106317e6ad469SVishal Kulkarni if (enable_ringbb && i)
106327e6ad469SVishal Kulkarni break;
106333dde7c95SVishal Kulkarni while ((adap->params.portvec & (1 << j)) == 0)
106343dde7c95SVishal Kulkarni j++;
106353dde7c95SVishal Kulkarni
106363dde7c95SVishal Kulkarni ret = t4_init_portmirror(pi, mbox, j, pf, vf);
106373dde7c95SVishal Kulkarni if (ret)
106383dde7c95SVishal Kulkarni return ret;
106393dde7c95SVishal Kulkarni j++;
106403dde7c95SVishal Kulkarni }
106413dde7c95SVishal Kulkarni return 0;
106423dde7c95SVishal Kulkarni }
106433dde7c95SVishal Kulkarni
106443dde7c95SVishal Kulkarni /**
106457e6ad469SVishal Kulkarni * t4_init_portinfo_viid - allocate a virtual interface and initialize
106467e6ad469SVishal Kulkarni * port_info
106477e6ad469SVishal Kulkarni * @pi: the port_info
106487e6ad469SVishal Kulkarni * @mbox: mailbox to use for the FW command
106497e6ad469SVishal Kulkarni * @port: physical port associated with the VI
106507e6ad469SVishal Kulkarni * @pf: the PF owning the VI
106517e6ad469SVishal Kulkarni * @vf: the VF owning the VI
106527e6ad469SVishal Kulkarni * @mac: the MAC address of the VI
106537e6ad469SVishal Kulkarni * @alloc_vi: Indicator to alloc VI
106547e6ad469SVishal Kulkarni *
106557e6ad469SVishal Kulkarni * Allocates a virtual interface for the given physical port. If @mac is
106567e6ad469SVishal Kulkarni * not %NULL it contains the MAC address of the VI as assigned by FW.
106577e6ad469SVishal Kulkarni * @mac should be large enough to hold an Ethernet address.
106587e6ad469SVishal Kulkarni * Returns < 0 on error.
106597e6ad469SVishal Kulkarni */
t4_init_portinfo_viid(struct port_info * pi,int mbox,int port,int pf,int vf,u8 mac[],bool alloc_vi)106607e6ad469SVishal Kulkarni int t4_init_portinfo_viid(struct port_info *pi, int mbox,
106617e6ad469SVishal Kulkarni int port, int pf, int vf, u8 mac[], bool alloc_vi)
106627e6ad469SVishal Kulkarni {
106637e6ad469SVishal Kulkarni struct adapter *adapter = pi->adapter;
106647e6ad469SVishal Kulkarni unsigned int fw_caps = adapter->params.fw_caps_support;
106657e6ad469SVishal Kulkarni struct fw_port_cmd cmd;
106667e6ad469SVishal Kulkarni unsigned int rss_size;
106677e6ad469SVishal Kulkarni enum fw_port_type port_type;
106687e6ad469SVishal Kulkarni int mdio_addr;
106697e6ad469SVishal Kulkarni fw_port_cap32_t pcaps, acaps;
106707e6ad469SVishal Kulkarni int ret;
106717e6ad469SVishal Kulkarni
106727e6ad469SVishal Kulkarni /*
106737e6ad469SVishal Kulkarni * If we haven't yet determined whether we're talking to Firmware
106747e6ad469SVishal Kulkarni * which knows the new 32-bit Port Capabilities, it's time to find
106757e6ad469SVishal Kulkarni * out now. This will also tell new Firmware to send us Port Status
106767e6ad469SVishal Kulkarni * Updates using the new 32-bit Port Capabilities version of the
106777e6ad469SVishal Kulkarni * Port Information message.
106787e6ad469SVishal Kulkarni */
106797e6ad469SVishal Kulkarni if (fw_caps == FW_CAPS_UNKNOWN) {
106807e6ad469SVishal Kulkarni u32 param, val;
106817e6ad469SVishal Kulkarni
106827e6ad469SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) |
106837e6ad469SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_PORT_CAPS32));
106847e6ad469SVishal Kulkarni val = 1;
106857e6ad469SVishal Kulkarni ret = t4_set_params(adapter, mbox, pf, vf, 1, ¶m, &val);
106867e6ad469SVishal Kulkarni fw_caps = (ret == 0 ? FW_CAPS32 : FW_CAPS16);
106877e6ad469SVishal Kulkarni adapter->params.fw_caps_support = fw_caps;
106887e6ad469SVishal Kulkarni }
106897e6ad469SVishal Kulkarni
106907e6ad469SVishal Kulkarni memset(&cmd, 0, sizeof(cmd));
106917e6ad469SVishal Kulkarni cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
106927e6ad469SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ |
106937e6ad469SVishal Kulkarni V_FW_PORT_CMD_PORTID(port));
106947e6ad469SVishal Kulkarni cmd.action_to_len16 = cpu_to_be32(
106957e6ad469SVishal Kulkarni V_FW_PORT_CMD_ACTION(fw_caps == FW_CAPS16
106967e6ad469SVishal Kulkarni ? FW_PORT_ACTION_GET_PORT_INFO
106977e6ad469SVishal Kulkarni : FW_PORT_ACTION_GET_PORT_INFO32) |
106987e6ad469SVishal Kulkarni FW_LEN16(cmd));
106997e6ad469SVishal Kulkarni ret = t4_wr_mbox(pi->adapter, mbox, &cmd, sizeof(cmd), &cmd);
107007e6ad469SVishal Kulkarni if (ret)
107017e6ad469SVishal Kulkarni return ret;
107027e6ad469SVishal Kulkarni
107037e6ad469SVishal Kulkarni /*
107047e6ad469SVishal Kulkarni * Extract the various fields from the Port Information message.
107057e6ad469SVishal Kulkarni */
107067e6ad469SVishal Kulkarni if (fw_caps == FW_CAPS16) {
107077e6ad469SVishal Kulkarni u32 lstatus = be32_to_cpu(cmd.u.info.lstatus_to_modtype);
107087e6ad469SVishal Kulkarni
107097e6ad469SVishal Kulkarni port_type = G_FW_PORT_CMD_PTYPE(lstatus);
107107e6ad469SVishal Kulkarni mdio_addr = ((lstatus & F_FW_PORT_CMD_MDIOCAP)
107117e6ad469SVishal Kulkarni ? G_FW_PORT_CMD_MDIOADDR(lstatus)
107127e6ad469SVishal Kulkarni : -1);
107137e6ad469SVishal Kulkarni pcaps = fwcaps16_to_caps32(be16_to_cpu(cmd.u.info.pcap));
107147e6ad469SVishal Kulkarni acaps = fwcaps16_to_caps32(be16_to_cpu(cmd.u.info.acap));
107157e6ad469SVishal Kulkarni } else {
107167e6ad469SVishal Kulkarni u32 lstatus32 = be32_to_cpu(cmd.u.info32.lstatus32_to_cbllen32);
107177e6ad469SVishal Kulkarni
107187e6ad469SVishal Kulkarni port_type = G_FW_PORT_CMD_PORTTYPE32(lstatus32);
107197e6ad469SVishal Kulkarni mdio_addr = ((lstatus32 & F_FW_PORT_CMD_MDIOCAP32)
107207e6ad469SVishal Kulkarni ? G_FW_PORT_CMD_MDIOADDR32(lstatus32)
107217e6ad469SVishal Kulkarni : -1);
107227e6ad469SVishal Kulkarni pcaps = be32_to_cpu(cmd.u.info32.pcaps32);
107237e6ad469SVishal Kulkarni acaps = be32_to_cpu(cmd.u.info32.acaps32);
107247e6ad469SVishal Kulkarni }
107257e6ad469SVishal Kulkarni
107267e6ad469SVishal Kulkarni if (alloc_vi) {
107277e6ad469SVishal Kulkarni u8 vivld = 0, vin = 0;
107287e6ad469SVishal Kulkarni
107297e6ad469SVishal Kulkarni ret = t4_alloc_vi(pi->adapter, mbox, port, pf, vf, 1, mac,
107307e6ad469SVishal Kulkarni &rss_size, &vivld, &vin);
107317e6ad469SVishal Kulkarni if (ret < 0)
107327e6ad469SVishal Kulkarni return ret;
107337e6ad469SVishal Kulkarni
107347e6ad469SVishal Kulkarni pi->viid = ret;
107357e6ad469SVishal Kulkarni pi->rss_size = rss_size;
107367e6ad469SVishal Kulkarni
107377e6ad469SVishal Kulkarni /* If fw supports returning the VIN as part of FW_VI_CMD,
107387e6ad469SVishal Kulkarni * save the returned values.
107397e6ad469SVishal Kulkarni */
107407e6ad469SVishal Kulkarni if (adapter->params.viid_smt_extn_support) {
107417e6ad469SVishal Kulkarni pi->vivld = vivld;
107427e6ad469SVishal Kulkarni pi->vin = vin;
107437e6ad469SVishal Kulkarni } else {
107447e6ad469SVishal Kulkarni /* Retrieve the values from VIID */
107457e6ad469SVishal Kulkarni pi->vivld = G_FW_VIID_VIVLD(pi->viid);
107467e6ad469SVishal Kulkarni pi->vin = G_FW_VIID_VIN(pi->viid);
107477e6ad469SVishal Kulkarni }
107487e6ad469SVishal Kulkarni }
107497e6ad469SVishal Kulkarni
107507e6ad469SVishal Kulkarni pi->tx_chan = port;
107517e6ad469SVishal Kulkarni pi->lport = port;
107527e6ad469SVishal Kulkarni pi->rx_chan = port;
107537e6ad469SVishal Kulkarni pi->rx_cchan = t4_get_tp_e2c_map(pi->adapter, port);
107547e6ad469SVishal Kulkarni
107557e6ad469SVishal Kulkarni pi->port_type = port_type;
107567e6ad469SVishal Kulkarni pi->mdio_addr = mdio_addr;
107577e6ad469SVishal Kulkarni pi->mod_type = FW_PORT_MOD_TYPE_NA;
107587e6ad469SVishal Kulkarni
107596feac2e3SRahul Lakkireddy t4_init_link_config(pi, pcaps, acaps);
107607e6ad469SVishal Kulkarni return 0;
107617e6ad469SVishal Kulkarni }
107627e6ad469SVishal Kulkarni
107637e6ad469SVishal Kulkarni /**
107643dde7c95SVishal Kulkarni * t4_init_portinfo - allocate a virtual interface and initialize port_info
107653dde7c95SVishal Kulkarni * @pi: the port_info
107663dde7c95SVishal Kulkarni * @mbox: mailbox to use for the FW command
107673dde7c95SVishal Kulkarni * @port: physical port associated with the VI
107683dde7c95SVishal Kulkarni * @pf: the PF owning the VI
107693dde7c95SVishal Kulkarni * @vf: the VF owning the VI
107703dde7c95SVishal Kulkarni * @mac: the MAC address of the VI
107713dde7c95SVishal Kulkarni *
107723dde7c95SVishal Kulkarni * Allocates a virtual interface for the given physical port. If @mac is
107733dde7c95SVishal Kulkarni * not %NULL it contains the MAC address of the VI as assigned by FW.
107743dde7c95SVishal Kulkarni * @mac should be large enough to hold an Ethernet address.
107753dde7c95SVishal Kulkarni * Returns < 0 on error.
107763dde7c95SVishal Kulkarni */
t4_init_portinfo(struct port_info * pi,int mbox,int port,int pf,int vf,u8 mac[])107773dde7c95SVishal Kulkarni int t4_init_portinfo(struct port_info *pi, int mbox,
107783dde7c95SVishal Kulkarni int port, int pf, int vf, u8 mac[])
107793dde7c95SVishal Kulkarni {
107807e6ad469SVishal Kulkarni return t4_init_portinfo_viid(pi, mbox, port, pf, vf, mac, true);
1078156b2bdd1SGireesh Nagabhushana }
107823dde7c95SVishal Kulkarni
t4_port_init(struct adapter * adap,int mbox,int pf,int vf)107833dde7c95SVishal Kulkarni int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
107843dde7c95SVishal Kulkarni {
107853dde7c95SVishal Kulkarni u8 addr[6];
107863dde7c95SVishal Kulkarni int ret, i, j = 0;
107873dde7c95SVishal Kulkarni
107883dde7c95SVishal Kulkarni for_each_port(adap, i) {
107893dde7c95SVishal Kulkarni struct port_info *pi = adap2pinfo(adap, i);
107903dde7c95SVishal Kulkarni
107913dde7c95SVishal Kulkarni while ((adap->params.portvec & (1 << j)) == 0)
107923dde7c95SVishal Kulkarni j++;
107933dde7c95SVishal Kulkarni
107943dde7c95SVishal Kulkarni ret = t4_init_portinfo(pi, mbox, j, pf, vf, addr);
107953dde7c95SVishal Kulkarni if (ret)
107963dde7c95SVishal Kulkarni return ret;
107973dde7c95SVishal Kulkarni
107983dde7c95SVishal Kulkarni t4_os_set_hw_addr(adap, i, addr);
107993dde7c95SVishal Kulkarni j++;
108003dde7c95SVishal Kulkarni }
108013dde7c95SVishal Kulkarni return 0;
108023dde7c95SVishal Kulkarni }
108033dde7c95SVishal Kulkarni
108043dde7c95SVishal Kulkarni /**
108053dde7c95SVishal Kulkarni * t4_read_cimq_cfg - read CIM queue configuration
108063dde7c95SVishal Kulkarni * @adap: the adapter
108073dde7c95SVishal Kulkarni * @base: holds the queue base addresses in bytes
108083dde7c95SVishal Kulkarni * @size: holds the queue sizes in bytes
108093dde7c95SVishal Kulkarni * @thres: holds the queue full thresholds in bytes
108103dde7c95SVishal Kulkarni *
108113dde7c95SVishal Kulkarni * Returns the current configuration of the CIM queues, starting with
108123dde7c95SVishal Kulkarni * the IBQs, then the OBQs.
108133dde7c95SVishal Kulkarni */
t4_read_cimq_cfg(struct adapter * adap,u16 * base,u16 * size,u16 * thres)108143dde7c95SVishal Kulkarni void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres)
108153dde7c95SVishal Kulkarni {
108163dde7c95SVishal Kulkarni unsigned int i, v;
108173dde7c95SVishal Kulkarni int cim_num_obq = is_t4(adap->params.chip) ?
108183dde7c95SVishal Kulkarni CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
108193dde7c95SVishal Kulkarni
108203dde7c95SVishal Kulkarni for (i = 0; i < CIM_NUM_IBQ; i++) {
108213dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_IBQSELECT |
108223dde7c95SVishal Kulkarni V_QUENUMSELECT(i));
108233dde7c95SVishal Kulkarni v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
108243dde7c95SVishal Kulkarni /* value is in 256-byte units */
108253dde7c95SVishal Kulkarni *base++ = G_CIMQBASE(v) * 256;
108263dde7c95SVishal Kulkarni *size++ = G_CIMQSIZE(v) * 256;
108273dde7c95SVishal Kulkarni *thres++ = G_QUEFULLTHRSH(v) * 8; /* 8-byte unit */
108283dde7c95SVishal Kulkarni }
108293dde7c95SVishal Kulkarni for (i = 0; i < cim_num_obq; i++) {
108303dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
108313dde7c95SVishal Kulkarni V_QUENUMSELECT(i));
108323dde7c95SVishal Kulkarni v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
108333dde7c95SVishal Kulkarni /* value is in 256-byte units */
108343dde7c95SVishal Kulkarni *base++ = G_CIMQBASE(v) * 256;
108353dde7c95SVishal Kulkarni *size++ = G_CIMQSIZE(v) * 256;
108363dde7c95SVishal Kulkarni }
108373dde7c95SVishal Kulkarni }
108383dde7c95SVishal Kulkarni
108393dde7c95SVishal Kulkarni /**
108403dde7c95SVishal Kulkarni * t4_read_cim_ibq - read the contents of a CIM inbound queue
108413dde7c95SVishal Kulkarni * @adap: the adapter
108423dde7c95SVishal Kulkarni * @qid: the queue index
108433dde7c95SVishal Kulkarni * @data: where to store the queue contents
108443dde7c95SVishal Kulkarni * @n: capacity of @data in 32-bit words
108453dde7c95SVishal Kulkarni *
108463dde7c95SVishal Kulkarni * Reads the contents of the selected CIM queue starting at address 0 up
108473dde7c95SVishal Kulkarni * to the capacity of @data. @n must be a multiple of 4. Returns < 0 on
108483dde7c95SVishal Kulkarni * error and the number of 32-bit words actually read on success.
108493dde7c95SVishal Kulkarni */
t4_read_cim_ibq(struct adapter * adap,unsigned int qid,u32 * data,size_t n)108503dde7c95SVishal Kulkarni int t4_read_cim_ibq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
108513dde7c95SVishal Kulkarni {
108523dde7c95SVishal Kulkarni int i, err, attempts;
108533dde7c95SVishal Kulkarni unsigned int addr;
108543dde7c95SVishal Kulkarni const unsigned int nwords = CIM_IBQ_SIZE * 4;
108553dde7c95SVishal Kulkarni
108563dde7c95SVishal Kulkarni if (qid > 5 || (n & 3))
108573dde7c95SVishal Kulkarni return -EINVAL;
108583dde7c95SVishal Kulkarni
108593dde7c95SVishal Kulkarni addr = qid * nwords;
108603dde7c95SVishal Kulkarni if (n > nwords)
108613dde7c95SVishal Kulkarni n = nwords;
108623dde7c95SVishal Kulkarni
108633dde7c95SVishal Kulkarni /* It might take 3-10ms before the IBQ debug read access is allowed.
108643dde7c95SVishal Kulkarni * Wait for 1 Sec with a delay of 1 usec.
108653dde7c95SVishal Kulkarni */
108663dde7c95SVishal Kulkarni attempts = 1000000;
108673dde7c95SVishal Kulkarni
108683dde7c95SVishal Kulkarni for (i = 0; i < n; i++, addr++) {
108693dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, V_IBQDBGADDR(addr) |
108703dde7c95SVishal Kulkarni F_IBQDBGEN);
108713dde7c95SVishal Kulkarni err = t4_wait_op_done(adap, A_CIM_IBQ_DBG_CFG, F_IBQDBGBUSY, 0,
108723dde7c95SVishal Kulkarni attempts, 1);
108733dde7c95SVishal Kulkarni if (err)
108743dde7c95SVishal Kulkarni return err;
108753dde7c95SVishal Kulkarni *data++ = t4_read_reg(adap, A_CIM_IBQ_DBG_DATA);
108763dde7c95SVishal Kulkarni }
108773dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_IBQ_DBG_CFG, 0);
108783dde7c95SVishal Kulkarni return i;
108793dde7c95SVishal Kulkarni }
108803dde7c95SVishal Kulkarni
108813dde7c95SVishal Kulkarni /**
108823dde7c95SVishal Kulkarni * t4_read_cim_obq - read the contents of a CIM outbound queue
108833dde7c95SVishal Kulkarni * @adap: the adapter
108843dde7c95SVishal Kulkarni * @qid: the queue index
108853dde7c95SVishal Kulkarni * @data: where to store the queue contents
108863dde7c95SVishal Kulkarni * @n: capacity of @data in 32-bit words
108873dde7c95SVishal Kulkarni *
108883dde7c95SVishal Kulkarni * Reads the contents of the selected CIM queue starting at address 0 up
108893dde7c95SVishal Kulkarni * to the capacity of @data. @n must be a multiple of 4. Returns < 0 on
108903dde7c95SVishal Kulkarni * error and the number of 32-bit words actually read on success.
108913dde7c95SVishal Kulkarni */
t4_read_cim_obq(struct adapter * adap,unsigned int qid,u32 * data,size_t n)108923dde7c95SVishal Kulkarni int t4_read_cim_obq(struct adapter *adap, unsigned int qid, u32 *data, size_t n)
108933dde7c95SVishal Kulkarni {
108943dde7c95SVishal Kulkarni int i, err;
108953dde7c95SVishal Kulkarni unsigned int addr, v, nwords;
108963dde7c95SVishal Kulkarni int cim_num_obq = is_t4(adap->params.chip) ?
108973dde7c95SVishal Kulkarni CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
108983dde7c95SVishal Kulkarni
108993dde7c95SVishal Kulkarni if ((qid > (cim_num_obq - 1)) || (n & 3))
109003dde7c95SVishal Kulkarni return -EINVAL;
109013dde7c95SVishal Kulkarni
109023dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_QUEUE_CONFIG_REF, F_OBQSELECT |
109033dde7c95SVishal Kulkarni V_QUENUMSELECT(qid));
109043dde7c95SVishal Kulkarni v = t4_read_reg(adap, A_CIM_QUEUE_CONFIG_CTRL);
109053dde7c95SVishal Kulkarni
109063dde7c95SVishal Kulkarni addr = G_CIMQBASE(v) * 64; /* muliple of 256 -> muliple of 4 */
109073dde7c95SVishal Kulkarni nwords = G_CIMQSIZE(v) * 64; /* same */
109083dde7c95SVishal Kulkarni if (n > nwords)
109093dde7c95SVishal Kulkarni n = nwords;
109103dde7c95SVishal Kulkarni
109113dde7c95SVishal Kulkarni for (i = 0; i < n; i++, addr++) {
109123dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_OBQ_DBG_CFG, V_OBQDBGADDR(addr) |
109133dde7c95SVishal Kulkarni F_OBQDBGEN);
109143dde7c95SVishal Kulkarni err = t4_wait_op_done(adap, A_CIM_OBQ_DBG_CFG, F_OBQDBGBUSY, 0,
109153dde7c95SVishal Kulkarni 2, 1);
109163dde7c95SVishal Kulkarni if (err)
109173dde7c95SVishal Kulkarni return err;
109183dde7c95SVishal Kulkarni *data++ = t4_read_reg(adap, A_CIM_OBQ_DBG_DATA);
109193dde7c95SVishal Kulkarni }
109203dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_OBQ_DBG_CFG, 0);
109213dde7c95SVishal Kulkarni return i;
109223dde7c95SVishal Kulkarni }
109233dde7c95SVishal Kulkarni
109243dde7c95SVishal Kulkarni /**
109253dde7c95SVishal Kulkarni * t4_cim_read - read a block from CIM internal address space
109263dde7c95SVishal Kulkarni * @adap: the adapter
109273dde7c95SVishal Kulkarni * @addr: the start address within the CIM address space
109283dde7c95SVishal Kulkarni * @n: number of words to read
109293dde7c95SVishal Kulkarni * @valp: where to store the result
109303dde7c95SVishal Kulkarni *
109313dde7c95SVishal Kulkarni * Reads a block of 4-byte words from the CIM intenal address space.
109323dde7c95SVishal Kulkarni */
t4_cim_read(struct adapter * adap,unsigned int addr,unsigned int n,unsigned int * valp)109333dde7c95SVishal Kulkarni int t4_cim_read(struct adapter *adap, unsigned int addr, unsigned int n,
109343dde7c95SVishal Kulkarni unsigned int *valp)
109353dde7c95SVishal Kulkarni {
109363dde7c95SVishal Kulkarni int ret = 0;
109373dde7c95SVishal Kulkarni
109383dde7c95SVishal Kulkarni if (t4_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY)
109393dde7c95SVishal Kulkarni return -EBUSY;
109403dde7c95SVishal Kulkarni
109413dde7c95SVishal Kulkarni for ( ; !ret && n--; addr += 4) {
109423dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_HOST_ACC_CTRL, addr);
109433dde7c95SVishal Kulkarni ret = t4_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY,
109443dde7c95SVishal Kulkarni 0, 5, 2);
109453dde7c95SVishal Kulkarni if (!ret)
109463dde7c95SVishal Kulkarni *valp++ = t4_read_reg(adap, A_CIM_HOST_ACC_DATA);
109473dde7c95SVishal Kulkarni }
109483dde7c95SVishal Kulkarni return ret;
109493dde7c95SVishal Kulkarni }
109503dde7c95SVishal Kulkarni
109513dde7c95SVishal Kulkarni /**
109523dde7c95SVishal Kulkarni * t4_cim_write - write a block into CIM internal address space
109533dde7c95SVishal Kulkarni * @adap: the adapter
109543dde7c95SVishal Kulkarni * @addr: the start address within the CIM address space
109553dde7c95SVishal Kulkarni * @n: number of words to write
109563dde7c95SVishal Kulkarni * @valp: set of values to write
109573dde7c95SVishal Kulkarni *
109583dde7c95SVishal Kulkarni * Writes a block of 4-byte words into the CIM intenal address space.
109593dde7c95SVishal Kulkarni */
t4_cim_write(struct adapter * adap,unsigned int addr,unsigned int n,const unsigned int * valp)109603dde7c95SVishal Kulkarni int t4_cim_write(struct adapter *adap, unsigned int addr, unsigned int n,
109613dde7c95SVishal Kulkarni const unsigned int *valp)
109623dde7c95SVishal Kulkarni {
109633dde7c95SVishal Kulkarni int ret = 0;
109643dde7c95SVishal Kulkarni
109653dde7c95SVishal Kulkarni if (t4_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY)
109663dde7c95SVishal Kulkarni return -EBUSY;
109673dde7c95SVishal Kulkarni
109683dde7c95SVishal Kulkarni for ( ; !ret && n--; addr += 4) {
109693dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_HOST_ACC_DATA, *valp++);
109703dde7c95SVishal Kulkarni t4_write_reg(adap, A_CIM_HOST_ACC_CTRL, addr | F_HOSTWRITE);
109713dde7c95SVishal Kulkarni ret = t4_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY,
109723dde7c95SVishal Kulkarni 0, 5, 2);
109733dde7c95SVishal Kulkarni }
109743dde7c95SVishal Kulkarni return ret;
109753dde7c95SVishal Kulkarni }
109763dde7c95SVishal Kulkarni
t4_cim_write1(struct adapter * adap,unsigned int addr,unsigned int val)109773dde7c95SVishal Kulkarni static int t4_cim_write1(struct adapter *adap, unsigned int addr,
109783dde7c95SVishal Kulkarni unsigned int val)
109793dde7c95SVishal Kulkarni {
109803dde7c95SVishal Kulkarni return t4_cim_write(adap, addr, 1, &val);
109813dde7c95SVishal Kulkarni }
109823dde7c95SVishal Kulkarni
109833dde7c95SVishal Kulkarni /**
109843dde7c95SVishal Kulkarni * t4_cim_read_la - read CIM LA capture buffer
109853dde7c95SVishal Kulkarni * @adap: the adapter
109863dde7c95SVishal Kulkarni * @la_buf: where to store the LA data
109873dde7c95SVishal Kulkarni * @wrptr: the HW write pointer within the capture buffer
109883dde7c95SVishal Kulkarni *
109893dde7c95SVishal Kulkarni * Reads the contents of the CIM LA buffer with the most recent entry at
109903dde7c95SVishal Kulkarni * the end of the returned data and with the entry at @wrptr first.
109913dde7c95SVishal Kulkarni * We try to leave the LA in the running state we find it in.
109923dde7c95SVishal Kulkarni */
t4_cim_read_la(struct adapter * adap,u32 * la_buf,unsigned int * wrptr)109933dde7c95SVishal Kulkarni int t4_cim_read_la(struct adapter *adap, u32 *la_buf, unsigned int *wrptr)
109943dde7c95SVishal Kulkarni {
109953dde7c95SVishal Kulkarni int i, ret;
109963dde7c95SVishal Kulkarni unsigned int cfg, val, idx;
109973dde7c95SVishal Kulkarni
109983dde7c95SVishal Kulkarni ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &cfg);
109993dde7c95SVishal Kulkarni if (ret)
110003dde7c95SVishal Kulkarni return ret;
110013dde7c95SVishal Kulkarni
110023dde7c95SVishal Kulkarni if (cfg & F_UPDBGLAEN) { /* LA is running, freeze it */
110033dde7c95SVishal Kulkarni ret = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG, 0);
110043dde7c95SVishal Kulkarni if (ret)
110053dde7c95SVishal Kulkarni return ret;
110063dde7c95SVishal Kulkarni }
110073dde7c95SVishal Kulkarni
110083dde7c95SVishal Kulkarni ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &val);
110093dde7c95SVishal Kulkarni if (ret)
110103dde7c95SVishal Kulkarni goto restart;
110113dde7c95SVishal Kulkarni
110123dde7c95SVishal Kulkarni idx = G_UPDBGLAWRPTR(val);
110133dde7c95SVishal Kulkarni if (wrptr)
110143dde7c95SVishal Kulkarni *wrptr = idx;
110153dde7c95SVishal Kulkarni
110163dde7c95SVishal Kulkarni for (i = 0; i < adap->params.cim_la_size; i++) {
110173dde7c95SVishal Kulkarni ret = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG,
110183dde7c95SVishal Kulkarni V_UPDBGLARDPTR(idx) | F_UPDBGLARDEN);
110193dde7c95SVishal Kulkarni if (ret)
110203dde7c95SVishal Kulkarni break;
110213dde7c95SVishal Kulkarni ret = t4_cim_read(adap, A_UP_UP_DBG_LA_CFG, 1, &val);
110223dde7c95SVishal Kulkarni if (ret)
110233dde7c95SVishal Kulkarni break;
110243dde7c95SVishal Kulkarni if (val & F_UPDBGLARDEN) {
110253dde7c95SVishal Kulkarni ret = -ETIMEDOUT;
110263dde7c95SVishal Kulkarni break;
110273dde7c95SVishal Kulkarni }
110283dde7c95SVishal Kulkarni ret = t4_cim_read(adap, A_UP_UP_DBG_LA_DATA, 1, &la_buf[i]);
110293dde7c95SVishal Kulkarni if (ret)
110303dde7c95SVishal Kulkarni break;
110313dde7c95SVishal Kulkarni
110327e6ad469SVishal Kulkarni /* Bits 0-3 of UpDbgLaRdPtr can be between 0000 to 1001 to
110333dde7c95SVishal Kulkarni * identify the 32-bit portion of the full 312-bit data
110343dde7c95SVishal Kulkarni */
110357e6ad469SVishal Kulkarni if (is_t6(adap->params.chip) && (idx & 0xf) >= 9)
110367e6ad469SVishal Kulkarni idx = (idx & 0xff0) + 0x10;
110377e6ad469SVishal Kulkarni else
110387e6ad469SVishal Kulkarni idx++;
110397e6ad469SVishal Kulkarni /* address can't exceed 0xfff */
110407e6ad469SVishal Kulkarni idx &= M_UPDBGLARDPTR;
110413dde7c95SVishal Kulkarni }
110423dde7c95SVishal Kulkarni restart:
110433dde7c95SVishal Kulkarni if (cfg & F_UPDBGLAEN) {
110443dde7c95SVishal Kulkarni int r = t4_cim_write1(adap, A_UP_UP_DBG_LA_CFG,
110453dde7c95SVishal Kulkarni cfg & ~F_UPDBGLARDEN);
110463dde7c95SVishal Kulkarni if (!ret)
110473dde7c95SVishal Kulkarni ret = r;
110483dde7c95SVishal Kulkarni }
110493dde7c95SVishal Kulkarni return ret;
110503dde7c95SVishal Kulkarni }
110513dde7c95SVishal Kulkarni
110523dde7c95SVishal Kulkarni /**
110533dde7c95SVishal Kulkarni * t4_tp_read_la - read TP LA capture buffer
110543dde7c95SVishal Kulkarni * @adap: the adapter
110553dde7c95SVishal Kulkarni * @la_buf: where to store the LA data
110563dde7c95SVishal Kulkarni * @wrptr: the HW write pointer within the capture buffer
110573dde7c95SVishal Kulkarni *
110583dde7c95SVishal Kulkarni * Reads the contents of the TP LA buffer with the most recent entry at
110593dde7c95SVishal Kulkarni * the end of the returned data and with the entry at @wrptr first.
110603dde7c95SVishal Kulkarni * We leave the LA in the running state we find it in.
110613dde7c95SVishal Kulkarni */
t4_tp_read_la(struct adapter * adap,u64 * la_buf,unsigned int * wrptr)110623dde7c95SVishal Kulkarni void t4_tp_read_la(struct adapter *adap, u64 *la_buf, unsigned int *wrptr)
110633dde7c95SVishal Kulkarni {
110643dde7c95SVishal Kulkarni bool last_incomplete;
110653dde7c95SVishal Kulkarni unsigned int i, cfg, val, idx;
110663dde7c95SVishal Kulkarni
110673dde7c95SVishal Kulkarni cfg = t4_read_reg(adap, A_TP_DBG_LA_CONFIG) & 0xffff;
110683dde7c95SVishal Kulkarni if (cfg & F_DBGLAENABLE) /* freeze LA */
110693dde7c95SVishal Kulkarni t4_write_reg(adap, A_TP_DBG_LA_CONFIG,
110703dde7c95SVishal Kulkarni adap->params.tp.la_mask | (cfg ^ F_DBGLAENABLE));
110713dde7c95SVishal Kulkarni
110723dde7c95SVishal Kulkarni val = t4_read_reg(adap, A_TP_DBG_LA_CONFIG);
110733dde7c95SVishal Kulkarni idx = G_DBGLAWPTR(val);
110743dde7c95SVishal Kulkarni last_incomplete = G_DBGLAMODE(val) >= 2 && (val & F_DBGLAWHLF) == 0;
110753dde7c95SVishal Kulkarni if (last_incomplete)
110763dde7c95SVishal Kulkarni idx = (idx + 1) & M_DBGLARPTR;
110773dde7c95SVishal Kulkarni if (wrptr)
110783dde7c95SVishal Kulkarni *wrptr = idx;
110793dde7c95SVishal Kulkarni
110803dde7c95SVishal Kulkarni val &= 0xffff;
110813dde7c95SVishal Kulkarni val &= ~V_DBGLARPTR(M_DBGLARPTR);
110823dde7c95SVishal Kulkarni val |= adap->params.tp.la_mask;
110833dde7c95SVishal Kulkarni
110843dde7c95SVishal Kulkarni for (i = 0; i < TPLA_SIZE; i++) {
110853dde7c95SVishal Kulkarni t4_write_reg(adap, A_TP_DBG_LA_CONFIG, V_DBGLARPTR(idx) | val);
110863dde7c95SVishal Kulkarni la_buf[i] = t4_read_reg64(adap, A_TP_DBG_LA_DATAL);
110873dde7c95SVishal Kulkarni idx = (idx + 1) & M_DBGLARPTR;
110883dde7c95SVishal Kulkarni }
110893dde7c95SVishal Kulkarni
110903dde7c95SVishal Kulkarni /* Wipe out last entry if it isn't valid */
110913dde7c95SVishal Kulkarni if (last_incomplete)
110923dde7c95SVishal Kulkarni la_buf[TPLA_SIZE - 1] = ~0ULL;
110933dde7c95SVishal Kulkarni
110943dde7c95SVishal Kulkarni if (cfg & F_DBGLAENABLE) /* restore running state */
110953dde7c95SVishal Kulkarni t4_write_reg(adap, A_TP_DBG_LA_CONFIG,
110963dde7c95SVishal Kulkarni cfg | adap->params.tp.la_mask);
110973dde7c95SVishal Kulkarni }
110983dde7c95SVishal Kulkarni
110993dde7c95SVishal Kulkarni /* SGE Hung Ingress DMA Warning Threshold time and Warning Repeat Rate (in
111003dde7c95SVishal Kulkarni * seconds). If we find one of the SGE Ingress DMA State Machines in the same
111013dde7c95SVishal Kulkarni * state for more than the Warning Threshold then we'll issue a warning about
111023dde7c95SVishal Kulkarni * a potential hang. We'll repeat the warning as the SGE Ingress DMA Channel
111033dde7c95SVishal Kulkarni * appears to be hung every Warning Repeat second till the situation clears.
111043dde7c95SVishal Kulkarni * If the situation clears, we'll note that as well.
111053dde7c95SVishal Kulkarni */
111063dde7c95SVishal Kulkarni #define SGE_IDMA_WARN_THRESH 1
111073dde7c95SVishal Kulkarni #define SGE_IDMA_WARN_REPEAT 300
111083dde7c95SVishal Kulkarni
111093dde7c95SVishal Kulkarni /**
111103dde7c95SVishal Kulkarni * t4_idma_monitor_init - initialize SGE Ingress DMA Monitor
111113dde7c95SVishal Kulkarni * @adapter: the adapter
111123dde7c95SVishal Kulkarni * @idma: the adapter IDMA Monitor state
111133dde7c95SVishal Kulkarni *
111143dde7c95SVishal Kulkarni * Initialize the state of an SGE Ingress DMA Monitor.
111153dde7c95SVishal Kulkarni */
t4_idma_monitor_init(struct adapter * adapter,struct sge_idma_monitor_state * idma)111163dde7c95SVishal Kulkarni void t4_idma_monitor_init(struct adapter *adapter,
111173dde7c95SVishal Kulkarni struct sge_idma_monitor_state *idma)
111183dde7c95SVishal Kulkarni {
111193dde7c95SVishal Kulkarni /* Initialize the state variables for detecting an SGE Ingress DMA
111203dde7c95SVishal Kulkarni * hang. The SGE has internal counters which count up on each clock
111213dde7c95SVishal Kulkarni * tick whenever the SGE finds its Ingress DMA State Engines in the
111223dde7c95SVishal Kulkarni * same state they were on the previous clock tick. The clock used is
111233dde7c95SVishal Kulkarni * the Core Clock so we have a limit on the maximum "time" they can
111243dde7c95SVishal Kulkarni * record; typically a very small number of seconds. For instance,
111253dde7c95SVishal Kulkarni * with a 600MHz Core Clock, we can only count up to a bit more than
111263dde7c95SVishal Kulkarni * 7s. So we'll synthesize a larger counter in order to not run the
111273dde7c95SVishal Kulkarni * risk of having the "timers" overflow and give us the flexibility to
111283dde7c95SVishal Kulkarni * maintain a Hung SGE State Machine of our own which operates across
111293dde7c95SVishal Kulkarni * a longer time frame.
111303dde7c95SVishal Kulkarni */
111313dde7c95SVishal Kulkarni idma->idma_1s_thresh = core_ticks_per_usec(adapter) * 1000000; /* 1s */
111323dde7c95SVishal Kulkarni idma->idma_stalled[0] = idma->idma_stalled[1] = 0;
111333dde7c95SVishal Kulkarni }
111343dde7c95SVishal Kulkarni
111353dde7c95SVishal Kulkarni /**
111363dde7c95SVishal Kulkarni * t4_idma_monitor - monitor SGE Ingress DMA state
111373dde7c95SVishal Kulkarni * @adapter: the adapter
111383dde7c95SVishal Kulkarni * @idma: the adapter IDMA Monitor state
111393dde7c95SVishal Kulkarni * @hz: number of ticks/second
111403dde7c95SVishal Kulkarni * @ticks: number of ticks since the last IDMA Monitor call
111413dde7c95SVishal Kulkarni */
t4_idma_monitor(struct adapter * adapter,struct sge_idma_monitor_state * idma,int hz,int ticks)111423dde7c95SVishal Kulkarni void t4_idma_monitor(struct adapter *adapter,
111433dde7c95SVishal Kulkarni struct sge_idma_monitor_state *idma,
111443dde7c95SVishal Kulkarni int hz, int ticks)
111453dde7c95SVishal Kulkarni {
111463dde7c95SVishal Kulkarni int i, idma_same_state_cnt[2];
111473dde7c95SVishal Kulkarni
111483dde7c95SVishal Kulkarni /* Read the SGE Debug Ingress DMA Same State Count registers. These
111493dde7c95SVishal Kulkarni * are counters inside the SGE which count up on each clock when the
111503dde7c95SVishal Kulkarni * SGE finds its Ingress DMA State Engines in the same states they
111513dde7c95SVishal Kulkarni * were in the previous clock. The counters will peg out at
111523dde7c95SVishal Kulkarni * 0xffffffff without wrapping around so once they pass the 1s
111533dde7c95SVishal Kulkarni * threshold they'll stay above that till the IDMA state changes.
111543dde7c95SVishal Kulkarni */
111553dde7c95SVishal Kulkarni t4_write_reg(adapter, A_SGE_DEBUG_INDEX, 13);
111563dde7c95SVishal Kulkarni idma_same_state_cnt[0] = t4_read_reg(adapter, A_SGE_DEBUG_DATA_HIGH);
111573dde7c95SVishal Kulkarni idma_same_state_cnt[1] = t4_read_reg(adapter, A_SGE_DEBUG_DATA_LOW);
111583dde7c95SVishal Kulkarni
111593dde7c95SVishal Kulkarni for (i = 0; i < 2; i++) {
111603dde7c95SVishal Kulkarni u32 debug0, debug11;
111613dde7c95SVishal Kulkarni
111623dde7c95SVishal Kulkarni /* If the Ingress DMA Same State Counter ("timer") is less
111633dde7c95SVishal Kulkarni * than 1s, then we can reset our synthesized Stall Timer and
111643dde7c95SVishal Kulkarni * continue. If we have previously emitted warnings about a
111653dde7c95SVishal Kulkarni * potential stalled Ingress Queue, issue a note indicating
111663dde7c95SVishal Kulkarni * that the Ingress Queue has resumed forward progress.
111673dde7c95SVishal Kulkarni */
111683dde7c95SVishal Kulkarni if (idma_same_state_cnt[i] < idma->idma_1s_thresh) {
111693dde7c95SVishal Kulkarni if (idma->idma_stalled[i] >= SGE_IDMA_WARN_THRESH*hz)
111703dde7c95SVishal Kulkarni CH_WARN(adapter, "SGE idma%d, queue %u, "
111713dde7c95SVishal Kulkarni "resumed after %d seconds\n",
111723dde7c95SVishal Kulkarni i, idma->idma_qid[i],
111733dde7c95SVishal Kulkarni idma->idma_stalled[i]/hz);
111743dde7c95SVishal Kulkarni idma->idma_stalled[i] = 0;
111753dde7c95SVishal Kulkarni continue;
111763dde7c95SVishal Kulkarni }
111773dde7c95SVishal Kulkarni
111783dde7c95SVishal Kulkarni /* Synthesize an SGE Ingress DMA Same State Timer in the Hz
111793dde7c95SVishal Kulkarni * domain. The first time we get here it'll be because we
111803dde7c95SVishal Kulkarni * passed the 1s Threshold; each additional time it'll be
111813dde7c95SVishal Kulkarni * because the RX Timer Callback is being fired on its regular
111823dde7c95SVishal Kulkarni * schedule.
111833dde7c95SVishal Kulkarni *
111843dde7c95SVishal Kulkarni * If the stall is below our Potential Hung Ingress Queue
111853dde7c95SVishal Kulkarni * Warning Threshold, continue.
111863dde7c95SVishal Kulkarni */
111873dde7c95SVishal Kulkarni if (idma->idma_stalled[i] == 0) {
111883dde7c95SVishal Kulkarni idma->idma_stalled[i] = hz;
111893dde7c95SVishal Kulkarni idma->idma_warn[i] = 0;
111903dde7c95SVishal Kulkarni } else {
111913dde7c95SVishal Kulkarni idma->idma_stalled[i] += ticks;
111923dde7c95SVishal Kulkarni idma->idma_warn[i] -= ticks;
111933dde7c95SVishal Kulkarni }
111943dde7c95SVishal Kulkarni
111953dde7c95SVishal Kulkarni if (idma->idma_stalled[i] < SGE_IDMA_WARN_THRESH*hz)
111963dde7c95SVishal Kulkarni continue;
111973dde7c95SVishal Kulkarni
111983dde7c95SVishal Kulkarni /* We'll issue a warning every SGE_IDMA_WARN_REPEAT seconds.
111993dde7c95SVishal Kulkarni */
112003dde7c95SVishal Kulkarni if (idma->idma_warn[i] > 0)
112013dde7c95SVishal Kulkarni continue;
112023dde7c95SVishal Kulkarni idma->idma_warn[i] = SGE_IDMA_WARN_REPEAT*hz;
112033dde7c95SVishal Kulkarni
112043dde7c95SVishal Kulkarni /* Read and save the SGE IDMA State and Queue ID information.
112053dde7c95SVishal Kulkarni * We do this every time in case it changes across time ...
112063dde7c95SVishal Kulkarni * can't be too careful ...
112073dde7c95SVishal Kulkarni */
112083dde7c95SVishal Kulkarni t4_write_reg(adapter, A_SGE_DEBUG_INDEX, 0);
112093dde7c95SVishal Kulkarni debug0 = t4_read_reg(adapter, A_SGE_DEBUG_DATA_LOW);
112103dde7c95SVishal Kulkarni idma->idma_state[i] = (debug0 >> (i * 9)) & 0x3f;
112113dde7c95SVishal Kulkarni
112123dde7c95SVishal Kulkarni t4_write_reg(adapter, A_SGE_DEBUG_INDEX, 11);
112133dde7c95SVishal Kulkarni debug11 = t4_read_reg(adapter, A_SGE_DEBUG_DATA_LOW);
112143dde7c95SVishal Kulkarni idma->idma_qid[i] = (debug11 >> (i * 16)) & 0xffff;
112153dde7c95SVishal Kulkarni
112163dde7c95SVishal Kulkarni CH_WARN(adapter, "SGE idma%u, queue %u, potentially stuck in "
112173dde7c95SVishal Kulkarni " state %u for %d seconds (debug0=%#x, debug11=%#x)\n",
112183dde7c95SVishal Kulkarni i, idma->idma_qid[i], idma->idma_state[i],
112193dde7c95SVishal Kulkarni idma->idma_stalled[i]/hz,
112203dde7c95SVishal Kulkarni debug0, debug11);
112213dde7c95SVishal Kulkarni t4_sge_decode_idma_state(adapter, idma->idma_state[i]);
112223dde7c95SVishal Kulkarni }
112233dde7c95SVishal Kulkarni }
112243dde7c95SVishal Kulkarni
112253dde7c95SVishal Kulkarni /**
112263dde7c95SVishal Kulkarni * t4_set_vf_mac - Set MAC address for the specified VF
112273dde7c95SVishal Kulkarni * @adapter: The adapter
112283dde7c95SVishal Kulkarni * @vf: one of the VFs instantiated by the specified PF
112293dde7c95SVishal Kulkarni * @naddr: the number of MAC addresses
112303dde7c95SVishal Kulkarni * @addr: the MAC address(es) to be set to the specified VF
112313dde7c95SVishal Kulkarni */
t4_set_vf_mac_acl(struct adapter * adapter,unsigned int vf,unsigned int naddr,u8 * addr)112323dde7c95SVishal Kulkarni int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
112333dde7c95SVishal Kulkarni unsigned int naddr, u8 *addr)
112343dde7c95SVishal Kulkarni {
112353dde7c95SVishal Kulkarni struct fw_acl_mac_cmd cmd;
112363dde7c95SVishal Kulkarni
112373dde7c95SVishal Kulkarni memset(&cmd, 0, sizeof(cmd));
112383dde7c95SVishal Kulkarni cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_ACL_MAC_CMD) |
112393dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
112403dde7c95SVishal Kulkarni F_FW_CMD_WRITE |
112413dde7c95SVishal Kulkarni V_FW_ACL_MAC_CMD_PFN(adapter->pf) |
112423dde7c95SVishal Kulkarni V_FW_ACL_MAC_CMD_VFN(vf));
112433dde7c95SVishal Kulkarni
112443dde7c95SVishal Kulkarni /* Note: Do not enable the ACL */
112453dde7c95SVishal Kulkarni cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd));
112463dde7c95SVishal Kulkarni cmd.nmac = naddr;
112473dde7c95SVishal Kulkarni
112483dde7c95SVishal Kulkarni switch (adapter->pf) {
112493dde7c95SVishal Kulkarni case 3:
112503dde7c95SVishal Kulkarni memcpy(cmd.macaddr3, addr, sizeof(cmd.macaddr3));
112513dde7c95SVishal Kulkarni break;
112523dde7c95SVishal Kulkarni case 2:
112533dde7c95SVishal Kulkarni memcpy(cmd.macaddr2, addr, sizeof(cmd.macaddr2));
112543dde7c95SVishal Kulkarni break;
112553dde7c95SVishal Kulkarni case 1:
112563dde7c95SVishal Kulkarni memcpy(cmd.macaddr1, addr, sizeof(cmd.macaddr1));
112573dde7c95SVishal Kulkarni break;
112583dde7c95SVishal Kulkarni case 0:
112593dde7c95SVishal Kulkarni memcpy(cmd.macaddr0, addr, sizeof(cmd.macaddr0));
112603dde7c95SVishal Kulkarni break;
112613dde7c95SVishal Kulkarni }
112623dde7c95SVishal Kulkarni
112633dde7c95SVishal Kulkarni return t4_wr_mbox(adapter, adapter->mbox, &cmd, sizeof(cmd), &cmd);
112643dde7c95SVishal Kulkarni }
112653dde7c95SVishal Kulkarni
112663dde7c95SVishal Kulkarni /* Code which cannot be pushed to kernel.org e.g., cxgbtool ioctl helper
112673dde7c95SVishal Kulkarni * functions
112683dde7c95SVishal Kulkarni */
112693dde7c95SVishal Kulkarni
112703dde7c95SVishal Kulkarni /**
112713dde7c95SVishal Kulkarni * t4_read_pace_tbl - read the pace table
112723dde7c95SVishal Kulkarni * @adap: the adapter
112733dde7c95SVishal Kulkarni * @pace_vals: holds the returned values
112743dde7c95SVishal Kulkarni *
112753dde7c95SVishal Kulkarni * Returns the values of TP's pace table in microseconds.
112763dde7c95SVishal Kulkarni */
t4_read_pace_tbl(struct adapter * adap,unsigned int pace_vals[NTX_SCHED])112773dde7c95SVishal Kulkarni void t4_read_pace_tbl(struct adapter *adap, unsigned int pace_vals[NTX_SCHED])
112783dde7c95SVishal Kulkarni {
112793dde7c95SVishal Kulkarni unsigned int i, v;
112803dde7c95SVishal Kulkarni
112813dde7c95SVishal Kulkarni for (i = 0; i < NTX_SCHED; i++) {
112823dde7c95SVishal Kulkarni t4_write_reg(adap, A_TP_PACE_TABLE, 0xffff0000 + i);
112833dde7c95SVishal Kulkarni v = t4_read_reg(adap, A_TP_PACE_TABLE);
112843dde7c95SVishal Kulkarni pace_vals[i] = dack_ticks_to_usec(adap, v);
112853dde7c95SVishal Kulkarni }
112863dde7c95SVishal Kulkarni }
112873dde7c95SVishal Kulkarni
112883dde7c95SVishal Kulkarni /**
112893dde7c95SVishal Kulkarni * t4_get_tx_sched - get the configuration of a Tx HW traffic scheduler
112903dde7c95SVishal Kulkarni * @adap: the adapter
112913dde7c95SVishal Kulkarni * @sched: the scheduler index
112923dde7c95SVishal Kulkarni * @kbps: the byte rate in Kbps
112933dde7c95SVishal Kulkarni * @ipg: the interpacket delay in tenths of nanoseconds
112943dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
112953dde7c95SVishal Kulkarni *
112963dde7c95SVishal Kulkarni * Return the current configuration of a HW Tx scheduler.
112973dde7c95SVishal Kulkarni */
t4_get_tx_sched(struct adapter * adap,unsigned int sched,unsigned int * kbps,unsigned int * ipg,bool sleep_ok)112983dde7c95SVishal Kulkarni void t4_get_tx_sched(struct adapter *adap, unsigned int sched, unsigned int *kbps,
112993dde7c95SVishal Kulkarni unsigned int *ipg, bool sleep_ok)
113003dde7c95SVishal Kulkarni {
113013dde7c95SVishal Kulkarni unsigned int v, addr, bpt, cpt;
113023dde7c95SVishal Kulkarni
113033dde7c95SVishal Kulkarni if (kbps) {
113043dde7c95SVishal Kulkarni addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2;
113053dde7c95SVishal Kulkarni t4_tp_tm_pio_read(adap, &v, 1, addr, sleep_ok);
113063dde7c95SVishal Kulkarni if (sched & 1)
113073dde7c95SVishal Kulkarni v >>= 16;
113083dde7c95SVishal Kulkarni bpt = (v >> 8) & 0xff;
113093dde7c95SVishal Kulkarni cpt = v & 0xff;
113103dde7c95SVishal Kulkarni if (!cpt)
113113dde7c95SVishal Kulkarni *kbps = 0; /* scheduler disabled */
113123dde7c95SVishal Kulkarni else {
113133dde7c95SVishal Kulkarni v = (adap->params.vpd.cclk * 1000) / cpt; /* ticks/s */
113143dde7c95SVishal Kulkarni *kbps = (v * bpt) / 125;
113153dde7c95SVishal Kulkarni }
113163dde7c95SVishal Kulkarni }
113173dde7c95SVishal Kulkarni if (ipg) {
113183dde7c95SVishal Kulkarni addr = A_TP_TX_MOD_Q1_Q0_TIMER_SEPARATOR - sched / 2;
113193dde7c95SVishal Kulkarni t4_tp_tm_pio_read(adap, &v, 1, addr, sleep_ok);
113203dde7c95SVishal Kulkarni if (sched & 1)
113213dde7c95SVishal Kulkarni v >>= 16;
113223dde7c95SVishal Kulkarni v &= 0xffff;
113233dde7c95SVishal Kulkarni *ipg = (10000 * v) / core_ticks_per_usec(adap);
113243dde7c95SVishal Kulkarni }
113253dde7c95SVishal Kulkarni }
113263dde7c95SVishal Kulkarni
113273dde7c95SVishal Kulkarni /**
113283dde7c95SVishal Kulkarni * t4_load_cfg - download config file
113293dde7c95SVishal Kulkarni * @adap: the adapter
113303dde7c95SVishal Kulkarni * @cfg_data: the cfg text file to write
113313dde7c95SVishal Kulkarni * @size: text file size
113323dde7c95SVishal Kulkarni *
113333dde7c95SVishal Kulkarni * Write the supplied config text file to the card's serial flash.
113343dde7c95SVishal Kulkarni */
t4_load_cfg(struct adapter * adap,const u8 * cfg_data,unsigned int size)113353dde7c95SVishal Kulkarni int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
113363dde7c95SVishal Kulkarni {
113373dde7c95SVishal Kulkarni int ret, i, n, cfg_addr;
113383dde7c95SVishal Kulkarni unsigned int addr;
113393dde7c95SVishal Kulkarni unsigned int flash_cfg_start_sec;
113403dde7c95SVishal Kulkarni unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
113413dde7c95SVishal Kulkarni
113423dde7c95SVishal Kulkarni cfg_addr = t4_flash_cfg_addr(adap);
113433dde7c95SVishal Kulkarni if (cfg_addr < 0)
113443dde7c95SVishal Kulkarni return cfg_addr;
113453dde7c95SVishal Kulkarni
113463dde7c95SVishal Kulkarni addr = cfg_addr;
113473dde7c95SVishal Kulkarni flash_cfg_start_sec = addr / SF_SEC_SIZE;
113483dde7c95SVishal Kulkarni
113493dde7c95SVishal Kulkarni if (size > FLASH_CFG_MAX_SIZE) {
113503dde7c95SVishal Kulkarni CH_ERR(adap, "cfg file too large, max is %u bytes\n",
113513dde7c95SVishal Kulkarni FLASH_CFG_MAX_SIZE);
113523dde7c95SVishal Kulkarni return -EFBIG;
113533dde7c95SVishal Kulkarni }
113543dde7c95SVishal Kulkarni
113553dde7c95SVishal Kulkarni i = DIV_ROUND_UP(FLASH_CFG_MAX_SIZE, /* # of sectors spanned */
113563dde7c95SVishal Kulkarni sf_sec_size);
113573dde7c95SVishal Kulkarni ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec,
113583dde7c95SVishal Kulkarni flash_cfg_start_sec + i - 1);
113593dde7c95SVishal Kulkarni /*
113603dde7c95SVishal Kulkarni * If size == 0 then we're simply erasing the FLASH sectors associated
113613dde7c95SVishal Kulkarni * with the on-adapter Firmware Configuration File.
113623dde7c95SVishal Kulkarni */
113633dde7c95SVishal Kulkarni if (ret || size == 0)
113643dde7c95SVishal Kulkarni goto out;
113653dde7c95SVishal Kulkarni
113663dde7c95SVishal Kulkarni /* this will write to the flash up to SF_PAGE_SIZE at a time */
113673dde7c95SVishal Kulkarni for (i = 0; i< size; i+= SF_PAGE_SIZE) {
113683dde7c95SVishal Kulkarni if ( (size - i) < SF_PAGE_SIZE)
113693dde7c95SVishal Kulkarni n = size - i;
113703dde7c95SVishal Kulkarni else
113713dde7c95SVishal Kulkarni n = SF_PAGE_SIZE;
113723dde7c95SVishal Kulkarni ret = t4_write_flash(adap, addr, n, cfg_data, 1);
113733dde7c95SVishal Kulkarni if (ret)
113743dde7c95SVishal Kulkarni goto out;
113753dde7c95SVishal Kulkarni
113763dde7c95SVishal Kulkarni addr += SF_PAGE_SIZE;
113773dde7c95SVishal Kulkarni cfg_data += SF_PAGE_SIZE;
113783dde7c95SVishal Kulkarni }
113793dde7c95SVishal Kulkarni
113803dde7c95SVishal Kulkarni out:
113813dde7c95SVishal Kulkarni if (ret)
113823dde7c95SVishal Kulkarni CH_ERR(adap, "config file %s failed %d\n",
113833dde7c95SVishal Kulkarni (size == 0 ? "clear" : "download"), ret);
113843dde7c95SVishal Kulkarni return ret;
113853dde7c95SVishal Kulkarni }
113863dde7c95SVishal Kulkarni
113873dde7c95SVishal Kulkarni /**
113883dde7c95SVishal Kulkarni * t5_fw_init_extern_mem - initialize the external memory
113893dde7c95SVishal Kulkarni * @adap: the adapter
113903dde7c95SVishal Kulkarni *
113913dde7c95SVishal Kulkarni * Initializes the external memory on T5.
113923dde7c95SVishal Kulkarni */
t5_fw_init_extern_mem(struct adapter * adap)113933dde7c95SVishal Kulkarni int t5_fw_init_extern_mem(struct adapter *adap)
113943dde7c95SVishal Kulkarni {
113953dde7c95SVishal Kulkarni u32 params[1], val[1];
113963dde7c95SVishal Kulkarni int ret;
113973dde7c95SVishal Kulkarni
113983dde7c95SVishal Kulkarni if (!is_t5(adap->params.chip))
113993dde7c95SVishal Kulkarni return 0;
114003dde7c95SVishal Kulkarni
114013dde7c95SVishal Kulkarni val[0] = 0xff; /* Initialize all MCs */
114023dde7c95SVishal Kulkarni params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
114033dde7c95SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_MCINIT));
114043dde7c95SVishal Kulkarni ret = t4_set_params_timeout(adap, adap->mbox, adap->pf, 0, 1, params, val,
114053dde7c95SVishal Kulkarni FW_CMD_MAX_TIMEOUT);
114063dde7c95SVishal Kulkarni
114073dde7c95SVishal Kulkarni return ret;
114083dde7c95SVishal Kulkarni }
114093dde7c95SVishal Kulkarni
114103dde7c95SVishal Kulkarni /* BIOS boot headers */
114113dde7c95SVishal Kulkarni typedef struct pci_expansion_rom_header {
114123dde7c95SVishal Kulkarni u8 signature[2]; /* ROM Signature. Should be 0xaa55 */
114133dde7c95SVishal Kulkarni u8 reserved[22]; /* Reserved per processor Architecture data */
114143dde7c95SVishal Kulkarni u8 pcir_offset[2]; /* Offset to PCI Data Structure */
114153dde7c95SVishal Kulkarni } pci_exp_rom_header_t; /* PCI_EXPANSION_ROM_HEADER */
114163dde7c95SVishal Kulkarni
114173dde7c95SVishal Kulkarni /* Legacy PCI Expansion ROM Header */
114183dde7c95SVishal Kulkarni typedef struct legacy_pci_expansion_rom_header {
114193dde7c95SVishal Kulkarni u8 signature[2]; /* ROM Signature. Should be 0xaa55 */
114203dde7c95SVishal Kulkarni u8 size512; /* Current Image Size in units of 512 bytes */
114213dde7c95SVishal Kulkarni u8 initentry_point[4];
114223dde7c95SVishal Kulkarni u8 cksum; /* Checksum computed on the entire Image */
114233dde7c95SVishal Kulkarni u8 reserved[16]; /* Reserved */
114243dde7c95SVishal Kulkarni u8 pcir_offset[2]; /* Offset to PCI Data Struture */
114253dde7c95SVishal Kulkarni } legacy_pci_exp_rom_header_t; /* LEGACY_PCI_EXPANSION_ROM_HEADER */
114263dde7c95SVishal Kulkarni
114273dde7c95SVishal Kulkarni /* EFI PCI Expansion ROM Header */
114283dde7c95SVishal Kulkarni typedef struct efi_pci_expansion_rom_header {
114293dde7c95SVishal Kulkarni u8 signature[2]; // ROM signature. The value 0xaa55
114303dde7c95SVishal Kulkarni u8 initialization_size[2]; /* Units 512. Includes this header */
114313dde7c95SVishal Kulkarni u8 efi_signature[4]; /* Signature from EFI image header. 0x0EF1 */
114323dde7c95SVishal Kulkarni u8 efi_subsystem[2]; /* Subsystem value for EFI image header */
114333dde7c95SVishal Kulkarni u8 efi_machine_type[2]; /* Machine type from EFI image header */
114343dde7c95SVishal Kulkarni u8 compression_type[2]; /* Compression type. */
114353dde7c95SVishal Kulkarni /*
114363dde7c95SVishal Kulkarni * Compression type definition
114373dde7c95SVishal Kulkarni * 0x0: uncompressed
114383dde7c95SVishal Kulkarni * 0x1: Compressed
114393dde7c95SVishal Kulkarni * 0x2-0xFFFF: Reserved
114403dde7c95SVishal Kulkarni */
114413dde7c95SVishal Kulkarni u8 reserved[8]; /* Reserved */
114423dde7c95SVishal Kulkarni u8 efi_image_header_offset[2]; /* Offset to EFI Image */
114433dde7c95SVishal Kulkarni u8 pcir_offset[2]; /* Offset to PCI Data Structure */
114443dde7c95SVishal Kulkarni } efi_pci_exp_rom_header_t; /* EFI PCI Expansion ROM Header */
114453dde7c95SVishal Kulkarni
114463dde7c95SVishal Kulkarni /* PCI Data Structure Format */
114473dde7c95SVishal Kulkarni typedef struct pcir_data_structure { /* PCI Data Structure */
114483dde7c95SVishal Kulkarni u8 signature[4]; /* Signature. The string "PCIR" */
114493dde7c95SVishal Kulkarni u8 vendor_id[2]; /* Vendor Identification */
114503dde7c95SVishal Kulkarni u8 device_id[2]; /* Device Identification */
114513dde7c95SVishal Kulkarni u8 vital_product[2]; /* Pointer to Vital Product Data */
114523dde7c95SVishal Kulkarni u8 length[2]; /* PCIR Data Structure Length */
114533dde7c95SVishal Kulkarni u8 revision; /* PCIR Data Structure Revision */
114543dde7c95SVishal Kulkarni u8 class_code[3]; /* Class Code */
114553dde7c95SVishal Kulkarni u8 image_length[2]; /* Image Length. Multiple of 512B */
114563dde7c95SVishal Kulkarni u8 code_revision[2]; /* Revision Level of Code/Data */
114573dde7c95SVishal Kulkarni u8 code_type; /* Code Type. */
114583dde7c95SVishal Kulkarni /*
114593dde7c95SVishal Kulkarni * PCI Expansion ROM Code Types
114603dde7c95SVishal Kulkarni * 0x00: Intel IA-32, PC-AT compatible. Legacy
114613dde7c95SVishal Kulkarni * 0x01: Open Firmware standard for PCI. FCODE
114623dde7c95SVishal Kulkarni * 0x02: Hewlett-Packard PA RISC. HP reserved
114633dde7c95SVishal Kulkarni * 0x03: EFI Image. EFI
114643dde7c95SVishal Kulkarni * 0x04-0xFF: Reserved.
114653dde7c95SVishal Kulkarni */
114663dde7c95SVishal Kulkarni u8 indicator; /* Indicator. Identifies the last image in the ROM */
114673dde7c95SVishal Kulkarni u8 reserved[2]; /* Reserved */
114683dde7c95SVishal Kulkarni } pcir_data_t; /* PCI__DATA_STRUCTURE */
114693dde7c95SVishal Kulkarni
114703dde7c95SVishal Kulkarni /* BOOT constants */
114713dde7c95SVishal Kulkarni enum {
114723dde7c95SVishal Kulkarni BOOT_FLASH_BOOT_ADDR = 0x0,/* start address of boot image in flash */
114733dde7c95SVishal Kulkarni BOOT_SIGNATURE = 0xaa55, /* signature of BIOS boot ROM */
114743dde7c95SVishal Kulkarni BOOT_SIZE_INC = 512, /* image size measured in 512B chunks */
114753dde7c95SVishal Kulkarni BOOT_MIN_SIZE = sizeof(pci_exp_rom_header_t), /* basic header */
114763dde7c95SVishal Kulkarni BOOT_MAX_SIZE = 1024*BOOT_SIZE_INC, /* 1 byte * length increment */
114773dde7c95SVishal Kulkarni VENDOR_ID = 0x1425, /* Vendor ID */
114783dde7c95SVishal Kulkarni PCIR_SIGNATURE = 0x52494350 /* PCIR signature */
114793dde7c95SVishal Kulkarni };
114803dde7c95SVishal Kulkarni
114813dde7c95SVishal Kulkarni /*
114823dde7c95SVishal Kulkarni * modify_device_id - Modifies the device ID of the Boot BIOS image
114833dde7c95SVishal Kulkarni * @adatper: the device ID to write.
114843dde7c95SVishal Kulkarni * @boot_data: the boot image to modify.
114853dde7c95SVishal Kulkarni *
114863dde7c95SVishal Kulkarni * Write the supplied device ID to the boot BIOS image.
114873dde7c95SVishal Kulkarni */
modify_device_id(int device_id,u8 * boot_data)114883dde7c95SVishal Kulkarni static void modify_device_id(int device_id, u8 *boot_data)
114893dde7c95SVishal Kulkarni {
114903dde7c95SVishal Kulkarni legacy_pci_exp_rom_header_t *header;
114913dde7c95SVishal Kulkarni pcir_data_t *pcir_header;
114923dde7c95SVishal Kulkarni u32 cur_header = 0;
114933dde7c95SVishal Kulkarni
114943dde7c95SVishal Kulkarni /*
114953dde7c95SVishal Kulkarni * Loop through all chained images and change the device ID's
114963dde7c95SVishal Kulkarni */
114973dde7c95SVishal Kulkarni while (1) {
114983dde7c95SVishal Kulkarni header = (legacy_pci_exp_rom_header_t *) &boot_data[cur_header];
114993dde7c95SVishal Kulkarni pcir_header = (pcir_data_t *) &boot_data[cur_header +
115003dde7c95SVishal Kulkarni le16_to_cpu(*(u16*)header->pcir_offset)];
115013dde7c95SVishal Kulkarni
115023dde7c95SVishal Kulkarni /*
115033dde7c95SVishal Kulkarni * Only modify the Device ID if code type is Legacy or HP.
115043dde7c95SVishal Kulkarni * 0x00: Okay to modify
115053dde7c95SVishal Kulkarni * 0x01: FCODE. Do not be modify
115063dde7c95SVishal Kulkarni * 0x03: Okay to modify
115073dde7c95SVishal Kulkarni * 0x04-0xFF: Do not modify
115083dde7c95SVishal Kulkarni */
115093dde7c95SVishal Kulkarni if (pcir_header->code_type == 0x00) {
115103dde7c95SVishal Kulkarni u8 csum = 0;
115113dde7c95SVishal Kulkarni int i;
115123dde7c95SVishal Kulkarni
115133dde7c95SVishal Kulkarni /*
115143dde7c95SVishal Kulkarni * Modify Device ID to match current adatper
115153dde7c95SVishal Kulkarni */
115163dde7c95SVishal Kulkarni *(u16*) pcir_header->device_id = device_id;
115173dde7c95SVishal Kulkarni
115183dde7c95SVishal Kulkarni /*
115193dde7c95SVishal Kulkarni * Set checksum temporarily to 0.
115203dde7c95SVishal Kulkarni * We will recalculate it later.
115213dde7c95SVishal Kulkarni */
115223dde7c95SVishal Kulkarni header->cksum = 0x0;
115233dde7c95SVishal Kulkarni
115243dde7c95SVishal Kulkarni /*
115253dde7c95SVishal Kulkarni * Calculate and update checksum
115263dde7c95SVishal Kulkarni */
115273dde7c95SVishal Kulkarni for (i = 0; i < (header->size512 * 512); i++)
115283dde7c95SVishal Kulkarni csum += (u8)boot_data[cur_header + i];
115293dde7c95SVishal Kulkarni
115303dde7c95SVishal Kulkarni /*
115313dde7c95SVishal Kulkarni * Invert summed value to create the checksum
115323dde7c95SVishal Kulkarni * Writing new checksum value directly to the boot data
115333dde7c95SVishal Kulkarni */
115343dde7c95SVishal Kulkarni boot_data[cur_header + 7] = -csum;
115353dde7c95SVishal Kulkarni
115363dde7c95SVishal Kulkarni } else if (pcir_header->code_type == 0x03) {
115373dde7c95SVishal Kulkarni
115383dde7c95SVishal Kulkarni /*
115393dde7c95SVishal Kulkarni * Modify Device ID to match current adatper
115403dde7c95SVishal Kulkarni */
115413dde7c95SVishal Kulkarni *(u16*) pcir_header->device_id = device_id;
115423dde7c95SVishal Kulkarni
115433dde7c95SVishal Kulkarni }
115443dde7c95SVishal Kulkarni
115453dde7c95SVishal Kulkarni
115463dde7c95SVishal Kulkarni /*
115473dde7c95SVishal Kulkarni * Check indicator element to identify if this is the last
115483dde7c95SVishal Kulkarni * image in the ROM.
115493dde7c95SVishal Kulkarni */
115503dde7c95SVishal Kulkarni if (pcir_header->indicator & 0x80)
115513dde7c95SVishal Kulkarni break;
115523dde7c95SVishal Kulkarni
115533dde7c95SVishal Kulkarni /*
115543dde7c95SVishal Kulkarni * Move header pointer up to the next image in the ROM.
115553dde7c95SVishal Kulkarni */
115563dde7c95SVishal Kulkarni cur_header += header->size512 * 512;
115573dde7c95SVishal Kulkarni }
115583dde7c95SVishal Kulkarni }
115593dde7c95SVishal Kulkarni
115603dde7c95SVishal Kulkarni #ifdef CHELSIO_T4_DIAGS
115613dde7c95SVishal Kulkarni /*
115623dde7c95SVishal Kulkarni * t4_earse_sf - Erase entire serial Flash region
115633dde7c95SVishal Kulkarni * @adapter: the adapter
115643dde7c95SVishal Kulkarni *
115653dde7c95SVishal Kulkarni * Clears the entire serial flash region.
115663dde7c95SVishal Kulkarni */
t4_erase_sf(struct adapter * adap)115673dde7c95SVishal Kulkarni int t4_erase_sf(struct adapter *adap)
115683dde7c95SVishal Kulkarni {
115693dde7c95SVishal Kulkarni unsigned int nsectors;
115703dde7c95SVishal Kulkarni int ret;
115713dde7c95SVishal Kulkarni
115723dde7c95SVishal Kulkarni nsectors = FLASH_END_SEC;
115733dde7c95SVishal Kulkarni if (nsectors > adap->params.sf_nsec)
115743dde7c95SVishal Kulkarni nsectors = adap->params.sf_nsec;
115753dde7c95SVishal Kulkarni
115763dde7c95SVishal Kulkarni // Erase all sectors of flash before and including the FW.
115773dde7c95SVishal Kulkarni // Flash layout is in t4_hw.h.
115783dde7c95SVishal Kulkarni ret = t4_flash_erase_sectors(adap, 0, nsectors - 1);
115793dde7c95SVishal Kulkarni if (ret)
115803dde7c95SVishal Kulkarni CH_ERR(adap, "Erasing serial flash failed, error %d\n", ret);
115813dde7c95SVishal Kulkarni return ret;
115823dde7c95SVishal Kulkarni }
115833dde7c95SVishal Kulkarni #endif
115843dde7c95SVishal Kulkarni
115853dde7c95SVishal Kulkarni /*
115863dde7c95SVishal Kulkarni * t4_load_boot - download boot flash
115873dde7c95SVishal Kulkarni * @adapter: the adapter
115883dde7c95SVishal Kulkarni * @boot_data: the boot image to write
115893dde7c95SVishal Kulkarni * @boot_addr: offset in flash to write boot_data
115903dde7c95SVishal Kulkarni * @size: image size
115913dde7c95SVishal Kulkarni *
115923dde7c95SVishal Kulkarni * Write the supplied boot image to the card's serial flash.
115933dde7c95SVishal Kulkarni * The boot image has the following sections: a 28-byte header and the
115943dde7c95SVishal Kulkarni * boot image.
115953dde7c95SVishal Kulkarni */
t4_load_boot(struct adapter * adap,u8 * boot_data,unsigned int boot_addr,unsigned int size)115963dde7c95SVishal Kulkarni int t4_load_boot(struct adapter *adap, u8 *boot_data,
115973dde7c95SVishal Kulkarni unsigned int boot_addr, unsigned int size)
115983dde7c95SVishal Kulkarni {
115993dde7c95SVishal Kulkarni pci_exp_rom_header_t *header;
116003dde7c95SVishal Kulkarni int pcir_offset ;
116013dde7c95SVishal Kulkarni pcir_data_t *pcir_header;
116023dde7c95SVishal Kulkarni int ret, addr;
116033dde7c95SVishal Kulkarni uint16_t device_id;
116043dde7c95SVishal Kulkarni unsigned int i;
116053dde7c95SVishal Kulkarni unsigned int boot_sector = (boot_addr * 1024 );
116063dde7c95SVishal Kulkarni unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
116073dde7c95SVishal Kulkarni
116083dde7c95SVishal Kulkarni /*
116093dde7c95SVishal Kulkarni * Make sure the boot image does not encroach on the firmware region
116103dde7c95SVishal Kulkarni */
116113dde7c95SVishal Kulkarni if ((boot_sector + size) >> 16 > FLASH_FW_START_SEC) {
116123dde7c95SVishal Kulkarni CH_ERR(adap, "boot image encroaching on firmware region\n");
116133dde7c95SVishal Kulkarni return -EFBIG;
116143dde7c95SVishal Kulkarni }
116153dde7c95SVishal Kulkarni
116163dde7c95SVishal Kulkarni /*
116173dde7c95SVishal Kulkarni * The boot sector is comprised of the Expansion-ROM boot, iSCSI boot,
116183dde7c95SVishal Kulkarni * and Boot configuration data sections. These 3 boot sections span
116193dde7c95SVishal Kulkarni * sectors 0 to 7 in flash and live right before the FW image location.
116203dde7c95SVishal Kulkarni */
116213dde7c95SVishal Kulkarni i = DIV_ROUND_UP(size ? size : FLASH_FW_START,
116223dde7c95SVishal Kulkarni sf_sec_size);
116233dde7c95SVishal Kulkarni ret = t4_flash_erase_sectors(adap, boot_sector >> 16,
116243dde7c95SVishal Kulkarni (boot_sector >> 16) + i - 1);
116253dde7c95SVishal Kulkarni
116263dde7c95SVishal Kulkarni /*
116273dde7c95SVishal Kulkarni * If size == 0 then we're simply erasing the FLASH sectors associated
116283dde7c95SVishal Kulkarni * with the on-adapter option ROM file
116293dde7c95SVishal Kulkarni */
116303dde7c95SVishal Kulkarni if (ret || (size == 0))
116313dde7c95SVishal Kulkarni goto out;
116323dde7c95SVishal Kulkarni
116333dde7c95SVishal Kulkarni /* Get boot header */
116343dde7c95SVishal Kulkarni header = (pci_exp_rom_header_t *)boot_data;
116353dde7c95SVishal Kulkarni pcir_offset = le16_to_cpu(*(u16 *)header->pcir_offset);
116363dde7c95SVishal Kulkarni /* PCIR Data Structure */
116373dde7c95SVishal Kulkarni pcir_header = (pcir_data_t *) &boot_data[pcir_offset];
116383dde7c95SVishal Kulkarni
116393dde7c95SVishal Kulkarni /*
116403dde7c95SVishal Kulkarni * Perform some primitive sanity testing to avoid accidentally
116413dde7c95SVishal Kulkarni * writing garbage over the boot sectors. We ought to check for
116423dde7c95SVishal Kulkarni * more but it's not worth it for now ...
116433dde7c95SVishal Kulkarni */
116443dde7c95SVishal Kulkarni if (size < BOOT_MIN_SIZE || size > BOOT_MAX_SIZE) {
116453dde7c95SVishal Kulkarni CH_ERR(adap, "boot image too small/large\n");
116463dde7c95SVishal Kulkarni return -EFBIG;
116473dde7c95SVishal Kulkarni }
116483dde7c95SVishal Kulkarni
116493dde7c95SVishal Kulkarni #ifndef CHELSIO_T4_DIAGS
116503dde7c95SVishal Kulkarni /*
116513dde7c95SVishal Kulkarni * Check BOOT ROM header signature
116523dde7c95SVishal Kulkarni */
116533dde7c95SVishal Kulkarni if (le16_to_cpu(*(u16*)header->signature) != BOOT_SIGNATURE ) {
116543dde7c95SVishal Kulkarni CH_ERR(adap, "Boot image missing signature\n");
116553dde7c95SVishal Kulkarni return -EINVAL;
116563dde7c95SVishal Kulkarni }
116573dde7c95SVishal Kulkarni
116583dde7c95SVishal Kulkarni /*
116593dde7c95SVishal Kulkarni * Check PCI header signature
116603dde7c95SVishal Kulkarni */
116613dde7c95SVishal Kulkarni if (le32_to_cpu(*(u32*)pcir_header->signature) != PCIR_SIGNATURE) {
116623dde7c95SVishal Kulkarni CH_ERR(adap, "PCI header missing signature\n");
116633dde7c95SVishal Kulkarni return -EINVAL;
116643dde7c95SVishal Kulkarni }
116653dde7c95SVishal Kulkarni
116663dde7c95SVishal Kulkarni /*
116673dde7c95SVishal Kulkarni * Check Vendor ID matches Chelsio ID
116683dde7c95SVishal Kulkarni */
116693dde7c95SVishal Kulkarni if (le16_to_cpu(*(u16*)pcir_header->vendor_id) != VENDOR_ID) {
116703dde7c95SVishal Kulkarni CH_ERR(adap, "Vendor ID missing signature\n");
116713dde7c95SVishal Kulkarni return -EINVAL;
116723dde7c95SVishal Kulkarni }
116733dde7c95SVishal Kulkarni #endif
116743dde7c95SVishal Kulkarni
116753dde7c95SVishal Kulkarni /*
116763dde7c95SVishal Kulkarni * Retrieve adapter's device ID
116773dde7c95SVishal Kulkarni */
116783dde7c95SVishal Kulkarni t4_os_pci_read_cfg2(adap, PCI_DEVICE_ID, &device_id);
116793dde7c95SVishal Kulkarni /* Want to deal with PF 0 so I strip off PF 4 indicator */
116803dde7c95SVishal Kulkarni device_id = device_id & 0xf0ff;
116813dde7c95SVishal Kulkarni
116823dde7c95SVishal Kulkarni /*
116833dde7c95SVishal Kulkarni * Check PCIE Device ID
116843dde7c95SVishal Kulkarni */
116853dde7c95SVishal Kulkarni if (le16_to_cpu(*(u16*)pcir_header->device_id) != device_id) {
116863dde7c95SVishal Kulkarni /*
116873dde7c95SVishal Kulkarni * Change the device ID in the Boot BIOS image to match
116883dde7c95SVishal Kulkarni * the Device ID of the current adapter.
116893dde7c95SVishal Kulkarni */
116903dde7c95SVishal Kulkarni modify_device_id(device_id, boot_data);
116913dde7c95SVishal Kulkarni }
116923dde7c95SVishal Kulkarni
116933dde7c95SVishal Kulkarni /*
116943dde7c95SVishal Kulkarni * Skip over the first SF_PAGE_SIZE worth of data and write it after
116953dde7c95SVishal Kulkarni * we finish copying the rest of the boot image. This will ensure
116963dde7c95SVishal Kulkarni * that the BIOS boot header will only be written if the boot image
116973dde7c95SVishal Kulkarni * was written in full.
116983dde7c95SVishal Kulkarni */
116993dde7c95SVishal Kulkarni addr = boot_sector;
117003dde7c95SVishal Kulkarni for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
117013dde7c95SVishal Kulkarni addr += SF_PAGE_SIZE;
117023dde7c95SVishal Kulkarni boot_data += SF_PAGE_SIZE;
117033dde7c95SVishal Kulkarni ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, boot_data, 0);
117043dde7c95SVishal Kulkarni if (ret)
117053dde7c95SVishal Kulkarni goto out;
117063dde7c95SVishal Kulkarni }
117073dde7c95SVishal Kulkarni
117083dde7c95SVishal Kulkarni ret = t4_write_flash(adap, boot_sector, SF_PAGE_SIZE,
117093dde7c95SVishal Kulkarni (const u8 *)header, 0);
117103dde7c95SVishal Kulkarni
117113dde7c95SVishal Kulkarni out:
117123dde7c95SVishal Kulkarni if (ret)
117133dde7c95SVishal Kulkarni CH_ERR(adap, "boot image download failed, error %d\n", ret);
117143dde7c95SVishal Kulkarni return ret;
117153dde7c95SVishal Kulkarni }
117163dde7c95SVishal Kulkarni
117173dde7c95SVishal Kulkarni /*
117183dde7c95SVishal Kulkarni * t4_flash_bootcfg_addr - return the address of the flash optionrom configuration
117193dde7c95SVishal Kulkarni * @adapter: the adapter
117203dde7c95SVishal Kulkarni *
117213dde7c95SVishal Kulkarni * Return the address within the flash where the OptionROM Configuration
117223dde7c95SVishal Kulkarni * is stored, or an error if the device FLASH is too small to contain
117233dde7c95SVishal Kulkarni * a OptionROM Configuration.
117243dde7c95SVishal Kulkarni */
t4_flash_bootcfg_addr(struct adapter * adapter)117253dde7c95SVishal Kulkarni static int t4_flash_bootcfg_addr(struct adapter *adapter)
117263dde7c95SVishal Kulkarni {
117273dde7c95SVishal Kulkarni /*
117283dde7c95SVishal Kulkarni * If the device FLASH isn't large enough to hold a Firmware
117293dde7c95SVishal Kulkarni * Configuration File, return an error.
117303dde7c95SVishal Kulkarni */
117313dde7c95SVishal Kulkarni if (adapter->params.sf_size < FLASH_BOOTCFG_START + FLASH_BOOTCFG_MAX_SIZE)
117323dde7c95SVishal Kulkarni return -ENOSPC;
117333dde7c95SVishal Kulkarni
117343dde7c95SVishal Kulkarni return FLASH_BOOTCFG_START;
117353dde7c95SVishal Kulkarni }
117363dde7c95SVishal Kulkarni
t4_load_bootcfg(struct adapter * adap,const u8 * cfg_data,unsigned int size)117373dde7c95SVishal Kulkarni int t4_load_bootcfg(struct adapter *adap,const u8 *cfg_data, unsigned int size)
117383dde7c95SVishal Kulkarni {
117393dde7c95SVishal Kulkarni int ret, i, n, cfg_addr;
117403dde7c95SVishal Kulkarni unsigned int addr;
117413dde7c95SVishal Kulkarni unsigned int flash_cfg_start_sec;
117423dde7c95SVishal Kulkarni unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
117433dde7c95SVishal Kulkarni
117443dde7c95SVishal Kulkarni cfg_addr = t4_flash_bootcfg_addr(adap);
117453dde7c95SVishal Kulkarni if (cfg_addr < 0)
117463dde7c95SVishal Kulkarni return cfg_addr;
117473dde7c95SVishal Kulkarni
117483dde7c95SVishal Kulkarni addr = cfg_addr;
117493dde7c95SVishal Kulkarni flash_cfg_start_sec = addr / SF_SEC_SIZE;
117503dde7c95SVishal Kulkarni
117513dde7c95SVishal Kulkarni if (size > FLASH_BOOTCFG_MAX_SIZE) {
117523dde7c95SVishal Kulkarni CH_ERR(adap, "bootcfg file too large, max is %u bytes\n",
117533dde7c95SVishal Kulkarni FLASH_BOOTCFG_MAX_SIZE);
117543dde7c95SVishal Kulkarni return -EFBIG;
117553dde7c95SVishal Kulkarni }
117563dde7c95SVishal Kulkarni
117573dde7c95SVishal Kulkarni i = DIV_ROUND_UP(FLASH_BOOTCFG_MAX_SIZE,/* # of sectors spanned */
117583dde7c95SVishal Kulkarni sf_sec_size);
117593dde7c95SVishal Kulkarni ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec,
117603dde7c95SVishal Kulkarni flash_cfg_start_sec + i - 1);
117613dde7c95SVishal Kulkarni
117623dde7c95SVishal Kulkarni /*
117633dde7c95SVishal Kulkarni * If size == 0 then we're simply erasing the FLASH sectors associated
117643dde7c95SVishal Kulkarni * with the on-adapter OptionROM Configuration File.
117653dde7c95SVishal Kulkarni */
117663dde7c95SVishal Kulkarni if (ret || size == 0)
117673dde7c95SVishal Kulkarni goto out;
117683dde7c95SVishal Kulkarni
117693dde7c95SVishal Kulkarni /* this will write to the flash up to SF_PAGE_SIZE at a time */
117703dde7c95SVishal Kulkarni for (i = 0; i< size; i+= SF_PAGE_SIZE) {
117713dde7c95SVishal Kulkarni if ( (size - i) < SF_PAGE_SIZE)
117723dde7c95SVishal Kulkarni n = size - i;
117733dde7c95SVishal Kulkarni else
117743dde7c95SVishal Kulkarni n = SF_PAGE_SIZE;
117753dde7c95SVishal Kulkarni ret = t4_write_flash(adap, addr, n, cfg_data, 0);
117763dde7c95SVishal Kulkarni if (ret)
117773dde7c95SVishal Kulkarni goto out;
117783dde7c95SVishal Kulkarni
117793dde7c95SVishal Kulkarni addr += SF_PAGE_SIZE;
117803dde7c95SVishal Kulkarni cfg_data += SF_PAGE_SIZE;
117813dde7c95SVishal Kulkarni }
117823dde7c95SVishal Kulkarni
117833dde7c95SVishal Kulkarni out:
117843dde7c95SVishal Kulkarni if (ret)
117853dde7c95SVishal Kulkarni CH_ERR(adap, "boot config data %s failed %d\n",
117863dde7c95SVishal Kulkarni (size == 0 ? "clear" : "download"), ret);
117873dde7c95SVishal Kulkarni return ret;
117883dde7c95SVishal Kulkarni }
117893dde7c95SVishal Kulkarni
117903dde7c95SVishal Kulkarni /**
117917e6ad469SVishal Kulkarni * t4_read_bootcfg - read the current (boot)OptionROM configuration from FLASH
117927e6ad469SVishal Kulkarni * @adap: the adapter
117937e6ad469SVishal Kulkarni * @cfg_data: where to store the read OptionROM configuration data
117947e6ad469SVishal Kulkarni *
117957e6ad469SVishal Kulkarni * Read the current OptionROM configuration from FLASH and write to the
117967e6ad469SVishal Kulkarni * buffer @cfg_data supplied.
117977e6ad469SVishal Kulkarni */
t4_read_bootcfg(struct adapter * adap,u8 * cfg_data,unsigned int size)117987e6ad469SVishal Kulkarni int t4_read_bootcfg(struct adapter *adap, u8 *cfg_data, unsigned int size)
117997e6ad469SVishal Kulkarni {
118007e6ad469SVishal Kulkarni u32 *ptr = (u32 *)cfg_data;
118017e6ad469SVishal Kulkarni int i, n, cfg_addr;
118027e6ad469SVishal Kulkarni int ret = 0;
118037e6ad469SVishal Kulkarni
118047e6ad469SVishal Kulkarni if (size > FLASH_BOOTCFG_MAX_SIZE) {
118057e6ad469SVishal Kulkarni CH_ERR(adap, "bootcfg file too big, max is %u bytes\n",
118067e6ad469SVishal Kulkarni FLASH_BOOTCFG_MAX_SIZE);
118077e6ad469SVishal Kulkarni return -EINVAL;
118087e6ad469SVishal Kulkarni }
118097e6ad469SVishal Kulkarni
118107e6ad469SVishal Kulkarni cfg_addr = t4_flash_bootcfg_addr(adap);
118117e6ad469SVishal Kulkarni if (cfg_addr < 0)
118127e6ad469SVishal Kulkarni return cfg_addr;
118137e6ad469SVishal Kulkarni
118147e6ad469SVishal Kulkarni size = size / sizeof (u32);
118157e6ad469SVishal Kulkarni for (i = 0; i < size; i += SF_PAGE_SIZE) {
118167e6ad469SVishal Kulkarni if ( (size - i) < SF_PAGE_SIZE)
118177e6ad469SVishal Kulkarni n = size - i;
118187e6ad469SVishal Kulkarni else
118197e6ad469SVishal Kulkarni n = SF_PAGE_SIZE;
118207e6ad469SVishal Kulkarni
118217e6ad469SVishal Kulkarni ret = t4_read_flash(adap, cfg_addr, n, ptr, 0);
118227e6ad469SVishal Kulkarni if (ret)
118237e6ad469SVishal Kulkarni goto out;
118247e6ad469SVishal Kulkarni
118257e6ad469SVishal Kulkarni cfg_addr += (n*4);
118267e6ad469SVishal Kulkarni ptr += n;
118277e6ad469SVishal Kulkarni }
118287e6ad469SVishal Kulkarni
118297e6ad469SVishal Kulkarni out:
118307e6ad469SVishal Kulkarni return ret;
118317e6ad469SVishal Kulkarni }
118327e6ad469SVishal Kulkarni
118337e6ad469SVishal Kulkarni /**
118343dde7c95SVishal Kulkarni * t4_set_filter_mode - configure the optional components of filter tuples
118353dde7c95SVishal Kulkarni * @adap: the adapter
118363dde7c95SVishal Kulkarni * @mode_map: a bitmap selcting which optional filter components to enable
118373dde7c95SVishal Kulkarni * @sleep_ok: if true we may sleep while awaiting command completion
118383dde7c95SVishal Kulkarni *
118393dde7c95SVishal Kulkarni * Sets the filter mode by selecting the optional components to enable
118403dde7c95SVishal Kulkarni * in filter tuples. Returns 0 on success and a negative error if the
118413dde7c95SVishal Kulkarni * requested mode needs more bits than are available for optional
118423dde7c95SVishal Kulkarni * components.
118433dde7c95SVishal Kulkarni */
t4_set_filter_mode(struct adapter * adap,unsigned int mode_map,bool sleep_ok)118443dde7c95SVishal Kulkarni int t4_set_filter_mode(struct adapter *adap, unsigned int mode_map,
118453dde7c95SVishal Kulkarni bool sleep_ok)
118463dde7c95SVishal Kulkarni {
118473dde7c95SVishal Kulkarni static u8 width[] = { 1, 3, 17, 17, 8, 8, 16, 9, 3, 1 };
118483dde7c95SVishal Kulkarni
118493dde7c95SVishal Kulkarni int i, nbits = 0;
118503dde7c95SVishal Kulkarni
118513dde7c95SVishal Kulkarni for (i = S_FCOE; i <= S_FRAGMENTATION; i++)
118523dde7c95SVishal Kulkarni if (mode_map & (1 << i))
118533dde7c95SVishal Kulkarni nbits += width[i];
118543dde7c95SVishal Kulkarni if (nbits > FILTER_OPT_LEN)
118553dde7c95SVishal Kulkarni return -EINVAL;
118563dde7c95SVishal Kulkarni
118573dde7c95SVishal Kulkarni t4_tp_pio_write(adap, &mode_map, 1, A_TP_VLAN_PRI_MAP, sleep_ok);
118583dde7c95SVishal Kulkarni
118593dde7c95SVishal Kulkarni return 0;
118603dde7c95SVishal Kulkarni }
118613dde7c95SVishal Kulkarni
118623dde7c95SVishal Kulkarni /**
118633dde7c95SVishal Kulkarni * t4_clr_port_stats - clear port statistics
118643dde7c95SVishal Kulkarni * @adap: the adapter
118653dde7c95SVishal Kulkarni * @idx: the port index
118663dde7c95SVishal Kulkarni *
118673dde7c95SVishal Kulkarni * Clear HW statistics for the given port.
118683dde7c95SVishal Kulkarni */
t4_clr_port_stats(struct adapter * adap,int idx)118693dde7c95SVishal Kulkarni void t4_clr_port_stats(struct adapter *adap, int idx)
118703dde7c95SVishal Kulkarni {
118713dde7c95SVishal Kulkarni unsigned int i;
118723dde7c95SVishal Kulkarni u32 bgmap = t4_get_mps_bg_map(adap, idx);
118733dde7c95SVishal Kulkarni u32 port_base_addr;
118743dde7c95SVishal Kulkarni
118753dde7c95SVishal Kulkarni if (is_t4(adap->params.chip))
118763dde7c95SVishal Kulkarni port_base_addr = PORT_BASE(idx);
118773dde7c95SVishal Kulkarni else
118783dde7c95SVishal Kulkarni port_base_addr = T5_PORT_BASE(idx);
118793dde7c95SVishal Kulkarni
118803dde7c95SVishal Kulkarni for (i = A_MPS_PORT_STAT_TX_PORT_BYTES_L;
118813dde7c95SVishal Kulkarni i <= A_MPS_PORT_STAT_TX_PORT_PPP7_H; i += 8)
118823dde7c95SVishal Kulkarni t4_write_reg(adap, port_base_addr + i, 0);
118833dde7c95SVishal Kulkarni for (i = A_MPS_PORT_STAT_RX_PORT_BYTES_L;
118843dde7c95SVishal Kulkarni i <= A_MPS_PORT_STAT_RX_PORT_LESS_64B_H; i += 8)
118853dde7c95SVishal Kulkarni t4_write_reg(adap, port_base_addr + i, 0);
118863dde7c95SVishal Kulkarni for (i = 0; i < 4; i++)
118873dde7c95SVishal Kulkarni if (bgmap & (1 << i)) {
118883dde7c95SVishal Kulkarni t4_write_reg(adap,
118893dde7c95SVishal Kulkarni A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + i * 8, 0);
118903dde7c95SVishal Kulkarni t4_write_reg(adap,
118913dde7c95SVishal Kulkarni A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + i * 8, 0);
118923dde7c95SVishal Kulkarni }
118933dde7c95SVishal Kulkarni }
118943dde7c95SVishal Kulkarni
118953dde7c95SVishal Kulkarni /**
118967e6ad469SVishal Kulkarni * t4_i2c_io - read/write I2C data from adapter
118973dde7c95SVishal Kulkarni * @adap: the adapter
118983dde7c95SVishal Kulkarni * @port: Port number if per-port device; <0 if not
118993dde7c95SVishal Kulkarni * @devid: per-port device ID or absolute device ID
119003dde7c95SVishal Kulkarni * @offset: byte offset into device I2C space
119013dde7c95SVishal Kulkarni * @len: byte length of I2C space data
119027e6ad469SVishal Kulkarni * @buf: buffer in which to return I2C data for read
119037e6ad469SVishal Kulkarni * buffer which holds the I2C data for write
119047e6ad469SVishal Kulkarni * @write: if true, do a write; else do a read
119057e6ad469SVishal Kulkarni * Reads/Writes the I2C data from/to the indicated device and location.
119063dde7c95SVishal Kulkarni */
t4_i2c_io(struct adapter * adap,unsigned int mbox,int port,unsigned int devid,unsigned int offset,unsigned int len,u8 * buf,bool write)119077e6ad469SVishal Kulkarni int t4_i2c_io(struct adapter *adap, unsigned int mbox,
119087e6ad469SVishal Kulkarni int port, unsigned int devid,
119097e6ad469SVishal Kulkarni unsigned int offset, unsigned int len,
119107e6ad469SVishal Kulkarni u8 *buf, bool write)
119117e6ad469SVishal Kulkarni {
119127e6ad469SVishal Kulkarni struct fw_ldst_cmd ldst_cmd, ldst_rpl;
119137e6ad469SVishal Kulkarni unsigned int i2c_max = sizeof(ldst_cmd.u.i2c.data);
119147e6ad469SVishal Kulkarni int ret = 0;
119157e6ad469SVishal Kulkarni
119167e6ad469SVishal Kulkarni if (len > I2C_PAGE_SIZE)
119177e6ad469SVishal Kulkarni return -EINVAL;
119187e6ad469SVishal Kulkarni
119197e6ad469SVishal Kulkarni /* Dont allow reads that spans multiple pages */
119207e6ad469SVishal Kulkarni if (offset < I2C_PAGE_SIZE && offset + len > I2C_PAGE_SIZE)
119217e6ad469SVishal Kulkarni return -EINVAL;
119227e6ad469SVishal Kulkarni
119237e6ad469SVishal Kulkarni memset(&ldst_cmd, 0, sizeof(ldst_cmd));
119247e6ad469SVishal Kulkarni ldst_cmd.op_to_addrspace =
119257e6ad469SVishal Kulkarni cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
119267e6ad469SVishal Kulkarni F_FW_CMD_REQUEST |
119277e6ad469SVishal Kulkarni (write ? F_FW_CMD_WRITE : F_FW_CMD_READ) |
119287e6ad469SVishal Kulkarni V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_I2C));
119297e6ad469SVishal Kulkarni ldst_cmd.cycles_to_len16 = cpu_to_be32(FW_LEN16(ldst_cmd));
119307e6ad469SVishal Kulkarni ldst_cmd.u.i2c.pid = (port < 0 ? 0xff : port);
119317e6ad469SVishal Kulkarni ldst_cmd.u.i2c.did = devid;
119327e6ad469SVishal Kulkarni
119337e6ad469SVishal Kulkarni while (len > 0) {
119347e6ad469SVishal Kulkarni unsigned int i2c_len = (len < i2c_max) ? len : i2c_max;
119357e6ad469SVishal Kulkarni
119367e6ad469SVishal Kulkarni ldst_cmd.u.i2c.boffset = offset;
119377e6ad469SVishal Kulkarni ldst_cmd.u.i2c.blen = i2c_len;
119387e6ad469SVishal Kulkarni
119397e6ad469SVishal Kulkarni if (write)
119407e6ad469SVishal Kulkarni memcpy(ldst_cmd.u.i2c.data, buf, i2c_len);
119417e6ad469SVishal Kulkarni
119427e6ad469SVishal Kulkarni ret = t4_wr_mbox(adap, mbox, &ldst_cmd, sizeof(ldst_cmd),
119437e6ad469SVishal Kulkarni write ? NULL : &ldst_rpl);
119447e6ad469SVishal Kulkarni if (ret)
119457e6ad469SVishal Kulkarni break;
119467e6ad469SVishal Kulkarni
119477e6ad469SVishal Kulkarni if (!write)
119487e6ad469SVishal Kulkarni memcpy(buf, ldst_rpl.u.i2c.data, i2c_len);
119497e6ad469SVishal Kulkarni offset += i2c_len;
119507e6ad469SVishal Kulkarni buf += i2c_len;
119517e6ad469SVishal Kulkarni len -= i2c_len;
119527e6ad469SVishal Kulkarni }
119537e6ad469SVishal Kulkarni
119547e6ad469SVishal Kulkarni return ret;
119557e6ad469SVishal Kulkarni }
119567e6ad469SVishal Kulkarni
t4_i2c_rd(struct adapter * adap,unsigned int mbox,int port,unsigned int devid,unsigned int offset,unsigned int len,u8 * buf)119573dde7c95SVishal Kulkarni int t4_i2c_rd(struct adapter *adap, unsigned int mbox,
119583dde7c95SVishal Kulkarni int port, unsigned int devid,
119593dde7c95SVishal Kulkarni unsigned int offset, unsigned int len,
119603dde7c95SVishal Kulkarni u8 *buf)
119613dde7c95SVishal Kulkarni {
119627e6ad469SVishal Kulkarni return t4_i2c_io(adap, mbox, port, devid, offset, len, buf, false);
119633dde7c95SVishal Kulkarni }
119643dde7c95SVishal Kulkarni
t4_i2c_wr(struct adapter * adap,unsigned int mbox,int port,unsigned int devid,unsigned int offset,unsigned int len,u8 * buf)119653dde7c95SVishal Kulkarni int t4_i2c_wr(struct adapter *adap, unsigned int mbox,
119663dde7c95SVishal Kulkarni int port, unsigned int devid,
119673dde7c95SVishal Kulkarni unsigned int offset, unsigned int len,
119683dde7c95SVishal Kulkarni u8 *buf)
119693dde7c95SVishal Kulkarni {
119707e6ad469SVishal Kulkarni return t4_i2c_io(adap, mbox, port, devid, offset, len, buf, true);
119713dde7c95SVishal Kulkarni }
119723dde7c95SVishal Kulkarni
119733dde7c95SVishal Kulkarni /**
119743dde7c95SVishal Kulkarni * t4_sge_ctxt_rd - read an SGE context through FW
119753dde7c95SVishal Kulkarni * @adap: the adapter
119763dde7c95SVishal Kulkarni * @mbox: mailbox to use for the FW command
119773dde7c95SVishal Kulkarni * @cid: the context id
119783dde7c95SVishal Kulkarni * @ctype: the context type
119793dde7c95SVishal Kulkarni * @data: where to store the context data
119803dde7c95SVishal Kulkarni *
119813dde7c95SVishal Kulkarni * Issues a FW command through the given mailbox to read an SGE context.
119823dde7c95SVishal Kulkarni */
t4_sge_ctxt_rd(struct adapter * adap,unsigned int mbox,unsigned int cid,enum ctxt_type ctype,u32 * data)119833dde7c95SVishal Kulkarni int t4_sge_ctxt_rd(struct adapter *adap, unsigned int mbox, unsigned int cid,
119843dde7c95SVishal Kulkarni enum ctxt_type ctype, u32 *data)
119853dde7c95SVishal Kulkarni {
119863dde7c95SVishal Kulkarni int ret;
119873dde7c95SVishal Kulkarni struct fw_ldst_cmd c;
119883dde7c95SVishal Kulkarni
119893dde7c95SVishal Kulkarni if (ctype == CTXT_EGRESS)
119903dde7c95SVishal Kulkarni ret = FW_LDST_ADDRSPC_SGE_EGRC;
119913dde7c95SVishal Kulkarni else if (ctype == CTXT_INGRESS)
119923dde7c95SVishal Kulkarni ret = FW_LDST_ADDRSPC_SGE_INGC;
119933dde7c95SVishal Kulkarni else if (ctype == CTXT_FLM)
119943dde7c95SVishal Kulkarni ret = FW_LDST_ADDRSPC_SGE_FLMC;
119953dde7c95SVishal Kulkarni else
119963dde7c95SVishal Kulkarni ret = FW_LDST_ADDRSPC_SGE_CONMC;
119973dde7c95SVishal Kulkarni
119983dde7c95SVishal Kulkarni memset(&c, 0, sizeof(c));
119993dde7c95SVishal Kulkarni c.op_to_addrspace = cpu_to_be32(V_FW_CMD_OP(FW_LDST_CMD) |
120003dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ |
120013dde7c95SVishal Kulkarni V_FW_LDST_CMD_ADDRSPACE(ret));
120023dde7c95SVishal Kulkarni c.cycles_to_len16 = cpu_to_be32(FW_LEN16(c));
120033dde7c95SVishal Kulkarni c.u.idctxt.physid = cpu_to_be32(cid);
120043dde7c95SVishal Kulkarni
120053dde7c95SVishal Kulkarni ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
120063dde7c95SVishal Kulkarni if (ret == 0) {
120073dde7c95SVishal Kulkarni data[0] = be32_to_cpu(c.u.idctxt.ctxt_data0);
120083dde7c95SVishal Kulkarni data[1] = be32_to_cpu(c.u.idctxt.ctxt_data1);
120093dde7c95SVishal Kulkarni data[2] = be32_to_cpu(c.u.idctxt.ctxt_data2);
120103dde7c95SVishal Kulkarni data[3] = be32_to_cpu(c.u.idctxt.ctxt_data3);
120113dde7c95SVishal Kulkarni data[4] = be32_to_cpu(c.u.idctxt.ctxt_data4);
120123dde7c95SVishal Kulkarni data[5] = be32_to_cpu(c.u.idctxt.ctxt_data5);
120133dde7c95SVishal Kulkarni }
120143dde7c95SVishal Kulkarni return ret;
120153dde7c95SVishal Kulkarni }
120163dde7c95SVishal Kulkarni
120173dde7c95SVishal Kulkarni /**
120183dde7c95SVishal Kulkarni * t4_sge_ctxt_rd_bd - read an SGE context bypassing FW
120193dde7c95SVishal Kulkarni * @adap: the adapter
120203dde7c95SVishal Kulkarni * @cid: the context id
120213dde7c95SVishal Kulkarni * @ctype: the context type
120223dde7c95SVishal Kulkarni * @data: where to store the context data
120233dde7c95SVishal Kulkarni *
120243dde7c95SVishal Kulkarni * Reads an SGE context directly, bypassing FW. This is only for
120253dde7c95SVishal Kulkarni * debugging when FW is unavailable.
120263dde7c95SVishal Kulkarni */
t4_sge_ctxt_rd_bd(struct adapter * adap,unsigned int cid,enum ctxt_type ctype,u32 * data)120273dde7c95SVishal Kulkarni int t4_sge_ctxt_rd_bd(struct adapter *adap, unsigned int cid, enum ctxt_type ctype,
120283dde7c95SVishal Kulkarni u32 *data)
120293dde7c95SVishal Kulkarni {
120303dde7c95SVishal Kulkarni int i, ret;
120313dde7c95SVishal Kulkarni
120323dde7c95SVishal Kulkarni t4_write_reg(adap, A_SGE_CTXT_CMD, V_CTXTQID(cid) | V_CTXTTYPE(ctype));
120333dde7c95SVishal Kulkarni ret = t4_wait_op_done(adap, A_SGE_CTXT_CMD, F_BUSY, 0, 3, 1);
120343dde7c95SVishal Kulkarni if (!ret)
120353dde7c95SVishal Kulkarni for (i = A_SGE_CTXT_DATA0; i <= A_SGE_CTXT_DATA5; i += 4)
120363dde7c95SVishal Kulkarni *data++ = t4_read_reg(adap, i);
120373dde7c95SVishal Kulkarni return ret;
120383dde7c95SVishal Kulkarni }
120393dde7c95SVishal Kulkarni
t4_sched_config(struct adapter * adapter,int type,int minmaxen)120403dde7c95SVishal Kulkarni int t4_sched_config(struct adapter *adapter, int type, int minmaxen)
120413dde7c95SVishal Kulkarni {
120423dde7c95SVishal Kulkarni struct fw_sched_cmd cmd;
120433dde7c95SVishal Kulkarni
120443dde7c95SVishal Kulkarni memset(&cmd, 0, sizeof(cmd));
120453dde7c95SVishal Kulkarni cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_SCHED_CMD) |
120463dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
120473dde7c95SVishal Kulkarni F_FW_CMD_WRITE);
120483dde7c95SVishal Kulkarni cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
120493dde7c95SVishal Kulkarni
120503dde7c95SVishal Kulkarni cmd.u.config.sc = FW_SCHED_SC_CONFIG;
120513dde7c95SVishal Kulkarni cmd.u.config.type = type;
120523dde7c95SVishal Kulkarni cmd.u.config.minmaxen = minmaxen;
120533dde7c95SVishal Kulkarni
120543dde7c95SVishal Kulkarni return t4_wr_mbox_meat(adapter,adapter->mbox, &cmd, sizeof(cmd),
120553dde7c95SVishal Kulkarni NULL, 1);
120563dde7c95SVishal Kulkarni }
120573dde7c95SVishal Kulkarni
t4_sched_params(struct adapter * adapter,int channel,int cls,int level,int mode,int type,int rateunit,int ratemode,int minrate,int maxrate,int weight,int pktsize,int burstsize)120587e6ad469SVishal Kulkarni int t4_sched_params(struct adapter *adapter,
120597e6ad469SVishal Kulkarni int channel, int cls,
120607e6ad469SVishal Kulkarni int level, int mode, int type,
120617e6ad469SVishal Kulkarni int rateunit, int ratemode,
120627e6ad469SVishal Kulkarni int minrate, int maxrate, int weight,
120637e6ad469SVishal Kulkarni int pktsize, int burstsize)
120643dde7c95SVishal Kulkarni {
120653dde7c95SVishal Kulkarni struct fw_sched_cmd cmd;
120663dde7c95SVishal Kulkarni
120673dde7c95SVishal Kulkarni memset(&cmd, 0, sizeof(cmd));
120683dde7c95SVishal Kulkarni cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_SCHED_CMD) |
120693dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
120703dde7c95SVishal Kulkarni F_FW_CMD_WRITE);
120713dde7c95SVishal Kulkarni cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
120723dde7c95SVishal Kulkarni
120733dde7c95SVishal Kulkarni cmd.u.params.sc = FW_SCHED_SC_PARAMS;
120743dde7c95SVishal Kulkarni cmd.u.params.type = type;
120753dde7c95SVishal Kulkarni cmd.u.params.level = level;
120763dde7c95SVishal Kulkarni cmd.u.params.mode = mode;
120773dde7c95SVishal Kulkarni cmd.u.params.ch = channel;
120787e6ad469SVishal Kulkarni cmd.u.params.cl = cls;
120793dde7c95SVishal Kulkarni cmd.u.params.unit = rateunit;
120803dde7c95SVishal Kulkarni cmd.u.params.rate = ratemode;
120813dde7c95SVishal Kulkarni cmd.u.params.min = cpu_to_be32(minrate);
120823dde7c95SVishal Kulkarni cmd.u.params.max = cpu_to_be32(maxrate);
120833dde7c95SVishal Kulkarni cmd.u.params.weight = cpu_to_be16(weight);
120843dde7c95SVishal Kulkarni cmd.u.params.pktsize = cpu_to_be16(pktsize);
120857e6ad469SVishal Kulkarni cmd.u.params.burstsize = cpu_to_be16(burstsize);
120863dde7c95SVishal Kulkarni
120873dde7c95SVishal Kulkarni return t4_wr_mbox_meat(adapter,adapter->mbox, &cmd, sizeof(cmd),
120883dde7c95SVishal Kulkarni NULL, 1);
120893dde7c95SVishal Kulkarni }
120903dde7c95SVishal Kulkarni
t4_read_sched_params(struct adapter * adapter,int channel,int cls,int * level,int * mode,int * type,int * rateunit,int * ratemode,int * minrate,int * maxrate,int * weight,int * pktsize,int * burstsize)120917e6ad469SVishal Kulkarni int t4_read_sched_params(struct adapter *adapter,
120927e6ad469SVishal Kulkarni int channel, int cls,
120937e6ad469SVishal Kulkarni int *level, int *mode, int *type,
120947e6ad469SVishal Kulkarni int *rateunit, int *ratemode,
120957e6ad469SVishal Kulkarni int *minrate, int *maxrate, int *weight,
120967e6ad469SVishal Kulkarni int *pktsize, int *burstsize)
120977e6ad469SVishal Kulkarni {
120987e6ad469SVishal Kulkarni struct fw_sched_cmd cmd;
120997e6ad469SVishal Kulkarni int ret = 0;
121007e6ad469SVishal Kulkarni
121017e6ad469SVishal Kulkarni memset(&cmd, 0, sizeof(cmd));
121027e6ad469SVishal Kulkarni cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_SCHED_CMD) |
121037e6ad469SVishal Kulkarni F_FW_CMD_REQUEST |
121047e6ad469SVishal Kulkarni F_FW_CMD_READ);
121057e6ad469SVishal Kulkarni cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
121067e6ad469SVishal Kulkarni cmd.u.params.sc = FW_SCHED_SC_PARAMS;
121077e6ad469SVishal Kulkarni cmd.u.params.ch = channel;
121087e6ad469SVishal Kulkarni cmd.u.params.cl = cls;
121097e6ad469SVishal Kulkarni
121107e6ad469SVishal Kulkarni ret = t4_wr_mbox_meat(adapter, adapter->mbox, &cmd, sizeof(cmd),
121117e6ad469SVishal Kulkarni &cmd, 1);
121127e6ad469SVishal Kulkarni if (ret)
121137e6ad469SVishal Kulkarni goto out;
121147e6ad469SVishal Kulkarni
121157e6ad469SVishal Kulkarni *level = cmd.u.params.level;
121167e6ad469SVishal Kulkarni *mode = cmd.u.params.mode;
121177e6ad469SVishal Kulkarni *type = cmd.u.params.type;
121187e6ad469SVishal Kulkarni *rateunit = cmd.u.params.unit;
121197e6ad469SVishal Kulkarni *ratemode = cmd.u.params.rate;
121207e6ad469SVishal Kulkarni *minrate = be32_to_cpu(cmd.u.params.min);
121217e6ad469SVishal Kulkarni *maxrate = be32_to_cpu(cmd.u.params.max);
121227e6ad469SVishal Kulkarni *weight = be16_to_cpu(cmd.u.params.weight);
121237e6ad469SVishal Kulkarni *pktsize = be16_to_cpu(cmd.u.params.pktsize);
121247e6ad469SVishal Kulkarni *burstsize = be16_to_cpu(cmd.u.params.burstsize);
121257e6ad469SVishal Kulkarni
121267e6ad469SVishal Kulkarni out:
121277e6ad469SVishal Kulkarni return ret;
121287e6ad469SVishal Kulkarni }
121297e6ad469SVishal Kulkarni
121303dde7c95SVishal Kulkarni /*
121313dde7c95SVishal Kulkarni * t4_config_watchdog - configure (enable/disable) a watchdog timer
121323dde7c95SVishal Kulkarni * @adapter: the adapter
121333dde7c95SVishal Kulkarni * @mbox: mailbox to use for the FW command
121343dde7c95SVishal Kulkarni * @pf: the PF owning the queue
121353dde7c95SVishal Kulkarni * @vf: the VF owning the queue
121363dde7c95SVishal Kulkarni * @timeout: watchdog timeout in ms
121373dde7c95SVishal Kulkarni * @action: watchdog timer / action
121383dde7c95SVishal Kulkarni *
121393dde7c95SVishal Kulkarni * There are separate watchdog timers for each possible watchdog
121403dde7c95SVishal Kulkarni * action. Configure one of the watchdog timers by setting a non-zero
121413dde7c95SVishal Kulkarni * timeout. Disable a watchdog timer by using a timeout of zero.
121423dde7c95SVishal Kulkarni */
t4_config_watchdog(struct adapter * adapter,unsigned int mbox,unsigned int pf,unsigned int vf,unsigned int timeout,unsigned int action)121433dde7c95SVishal Kulkarni int t4_config_watchdog(struct adapter *adapter, unsigned int mbox,
121443dde7c95SVishal Kulkarni unsigned int pf, unsigned int vf,
121453dde7c95SVishal Kulkarni unsigned int timeout, unsigned int action)
121463dde7c95SVishal Kulkarni {
121473dde7c95SVishal Kulkarni struct fw_watchdog_cmd wdog;
121483dde7c95SVishal Kulkarni unsigned int ticks;
121493dde7c95SVishal Kulkarni
121503dde7c95SVishal Kulkarni /*
121513dde7c95SVishal Kulkarni * The watchdog command expects a timeout in units of 10ms so we need
121523dde7c95SVishal Kulkarni * to convert it here (via rounding) and force a minimum of one 10ms
121533dde7c95SVishal Kulkarni * "tick" if the timeout is non-zero but the convertion results in 0
121543dde7c95SVishal Kulkarni * ticks.
121553dde7c95SVishal Kulkarni */
121563dde7c95SVishal Kulkarni ticks = (timeout + 5)/10;
121573dde7c95SVishal Kulkarni if (timeout && !ticks)
121583dde7c95SVishal Kulkarni ticks = 1;
121593dde7c95SVishal Kulkarni
121603dde7c95SVishal Kulkarni memset(&wdog, 0, sizeof wdog);
121613dde7c95SVishal Kulkarni wdog.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_WATCHDOG_CMD) |
121623dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
121633dde7c95SVishal Kulkarni F_FW_CMD_WRITE |
121643dde7c95SVishal Kulkarni V_FW_PARAMS_CMD_PFN(pf) |
121653dde7c95SVishal Kulkarni V_FW_PARAMS_CMD_VFN(vf));
121663dde7c95SVishal Kulkarni wdog.retval_len16 = cpu_to_be32(FW_LEN16(wdog));
121673dde7c95SVishal Kulkarni wdog.timeout = cpu_to_be32(ticks);
121683dde7c95SVishal Kulkarni wdog.action = cpu_to_be32(action);
121693dde7c95SVishal Kulkarni
121703dde7c95SVishal Kulkarni return t4_wr_mbox(adapter, mbox, &wdog, sizeof wdog, NULL);
121713dde7c95SVishal Kulkarni }
121723dde7c95SVishal Kulkarni
t4_get_devlog_level(struct adapter * adapter,unsigned int * level)121733dde7c95SVishal Kulkarni int t4_get_devlog_level(struct adapter *adapter, unsigned int *level)
121743dde7c95SVishal Kulkarni {
121753dde7c95SVishal Kulkarni struct fw_devlog_cmd devlog_cmd;
121763dde7c95SVishal Kulkarni int ret;
121773dde7c95SVishal Kulkarni
121783dde7c95SVishal Kulkarni memset(&devlog_cmd, 0, sizeof(devlog_cmd));
121793dde7c95SVishal Kulkarni devlog_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_DEVLOG_CMD) |
121803dde7c95SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_READ);
121813dde7c95SVishal Kulkarni devlog_cmd.retval_len16 = cpu_to_be32(FW_LEN16(devlog_cmd));
121823dde7c95SVishal Kulkarni ret = t4_wr_mbox(adapter, adapter->mbox, &devlog_cmd,
121833dde7c95SVishal Kulkarni sizeof(devlog_cmd), &devlog_cmd);
121843dde7c95SVishal Kulkarni if (ret)
121853dde7c95SVishal Kulkarni return ret;
121863dde7c95SVishal Kulkarni
121873dde7c95SVishal Kulkarni *level = devlog_cmd.level;
121883dde7c95SVishal Kulkarni return 0;
121893dde7c95SVishal Kulkarni }
121903dde7c95SVishal Kulkarni
t4_set_devlog_level(struct adapter * adapter,unsigned int level)121913dde7c95SVishal Kulkarni int t4_set_devlog_level(struct adapter *adapter, unsigned int level)
121923dde7c95SVishal Kulkarni {
121933dde7c95SVishal Kulkarni struct fw_devlog_cmd devlog_cmd;
121943dde7c95SVishal Kulkarni
121953dde7c95SVishal Kulkarni memset(&devlog_cmd, 0, sizeof(devlog_cmd));
121963dde7c95SVishal Kulkarni devlog_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_DEVLOG_CMD) |
121973dde7c95SVishal Kulkarni F_FW_CMD_REQUEST |
121983dde7c95SVishal Kulkarni F_FW_CMD_WRITE);
121993dde7c95SVishal Kulkarni devlog_cmd.level = level;
122003dde7c95SVishal Kulkarni devlog_cmd.retval_len16 = cpu_to_be32(FW_LEN16(devlog_cmd));
122013dde7c95SVishal Kulkarni return t4_wr_mbox(adapter, adapter->mbox, &devlog_cmd,
122023dde7c95SVishal Kulkarni sizeof(devlog_cmd), &devlog_cmd);
122033dde7c95SVishal Kulkarni }
122043dde7c95SVishal Kulkarni
t4_configure_add_smac(struct adapter * adap)122057e6ad469SVishal Kulkarni int t4_configure_add_smac(struct adapter *adap)
122067e6ad469SVishal Kulkarni {
122077e6ad469SVishal Kulkarni unsigned int param, val;
122087e6ad469SVishal Kulkarni int ret = 0;
122097e6ad469SVishal Kulkarni
122107e6ad469SVishal Kulkarni adap->params.smac_add_support = 0;
122117e6ad469SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
122127e6ad469SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_ADD_SMAC));
122137e6ad469SVishal Kulkarni /* Query FW to check if FW supports adding source mac address
122147e6ad469SVishal Kulkarni * to TCAM feature or not.
122157e6ad469SVishal Kulkarni * If FW returns 1, driver can use this feature and driver need to send
122167e6ad469SVishal Kulkarni * FW_PARAMS_PARAM_DEV_ADD_SMAC write command with value 1 to
122177e6ad469SVishal Kulkarni * enable adding smac to TCAM.
122187e6ad469SVishal Kulkarni */
122197e6ad469SVishal Kulkarni ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val);
122207e6ad469SVishal Kulkarni if (ret)
122217e6ad469SVishal Kulkarni return ret;
122227e6ad469SVishal Kulkarni
122237e6ad469SVishal Kulkarni if (val == 1) {
122247e6ad469SVishal Kulkarni ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1,
122257e6ad469SVishal Kulkarni ¶m, &val);
122267e6ad469SVishal Kulkarni if (!ret)
122277e6ad469SVishal Kulkarni /* Firmware allows adding explicit TCAM entries.
122287e6ad469SVishal Kulkarni * Save this internally.
122297e6ad469SVishal Kulkarni */
122307e6ad469SVishal Kulkarni adap->params.smac_add_support = 1;
122317e6ad469SVishal Kulkarni }
122327e6ad469SVishal Kulkarni
122337e6ad469SVishal Kulkarni return ret;
122347e6ad469SVishal Kulkarni }
122357e6ad469SVishal Kulkarni
t4_configure_ringbb(struct adapter * adap)122367e6ad469SVishal Kulkarni int t4_configure_ringbb(struct adapter *adap)
122377e6ad469SVishal Kulkarni {
122387e6ad469SVishal Kulkarni unsigned int param, val;
122397e6ad469SVishal Kulkarni int ret = 0;
122407e6ad469SVishal Kulkarni
122417e6ad469SVishal Kulkarni param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
122427e6ad469SVishal Kulkarni V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_RING_BACKBONE));
122437e6ad469SVishal Kulkarni /* Query FW to check if FW supports ring switch feature or not.
122447e6ad469SVishal Kulkarni * If FW returns 1, driver can use this feature and driver need to send
122457e6ad469SVishal Kulkarni * FW_PARAMS_PARAM_DEV_RING_BACKBONE write command with value 1 to
122467e6ad469SVishal Kulkarni * enable the ring backbone configuration.
122477e6ad469SVishal Kulkarni */
122487e6ad469SVishal Kulkarni ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val);
122497e6ad469SVishal Kulkarni if (ret < 0) {
122507e6ad469SVishal Kulkarni CH_ERR(adap, "Querying FW using Ring backbone params command failed, err=%d\n",
122517e6ad469SVishal Kulkarni ret);
122527e6ad469SVishal Kulkarni goto out;
122537e6ad469SVishal Kulkarni }
122547e6ad469SVishal Kulkarni
122557e6ad469SVishal Kulkarni if (val != 1) {
122567e6ad469SVishal Kulkarni CH_ERR(adap, "FW doesnot support ringbackbone features\n");
122577e6ad469SVishal Kulkarni goto out;
122587e6ad469SVishal Kulkarni }
122597e6ad469SVishal Kulkarni
122607e6ad469SVishal Kulkarni ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val);
122617e6ad469SVishal Kulkarni if (ret < 0) {
122627e6ad469SVishal Kulkarni CH_ERR(adap, "Could not set Ringbackbone, err= %d\n",
122637e6ad469SVishal Kulkarni ret);
122647e6ad469SVishal Kulkarni goto out;
122657e6ad469SVishal Kulkarni }
122667e6ad469SVishal Kulkarni
122677e6ad469SVishal Kulkarni out:
122687e6ad469SVishal Kulkarni return ret;
122697e6ad469SVishal Kulkarni }
122707e6ad469SVishal Kulkarni
122717e6ad469SVishal Kulkarni /*
122727e6ad469SVishal Kulkarni * t4_set_vlan_acl - Set a VLAN id for the specified VF
122737e6ad469SVishal Kulkarni * @adapter: the adapter
122747e6ad469SVishal Kulkarni * @mbox: mailbox to use for the FW command
122757e6ad469SVishal Kulkarni * @vf: one of the VFs instantiated by the specified PF
122767e6ad469SVishal Kulkarni * @vlan: The vlanid to be set
122777e6ad469SVishal Kulkarni *
122787e6ad469SVishal Kulkarni */
t4_set_vlan_acl(struct adapter * adap,unsigned int mbox,unsigned int vf,u16 vlan)122797e6ad469SVishal Kulkarni int t4_set_vlan_acl(struct adapter *adap, unsigned int mbox, unsigned int vf,
122807e6ad469SVishal Kulkarni u16 vlan)
122817e6ad469SVishal Kulkarni {
122827e6ad469SVishal Kulkarni struct fw_acl_vlan_cmd vlan_cmd;
122837e6ad469SVishal Kulkarni unsigned int enable;
122847e6ad469SVishal Kulkarni
122857e6ad469SVishal Kulkarni enable = (vlan ? F_FW_ACL_VLAN_CMD_EN : 0);
122867e6ad469SVishal Kulkarni memset(&vlan_cmd, 0, sizeof(vlan_cmd));
122877e6ad469SVishal Kulkarni vlan_cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_ACL_VLAN_CMD) |
122887e6ad469SVishal Kulkarni F_FW_CMD_REQUEST |
122897e6ad469SVishal Kulkarni F_FW_CMD_WRITE |
122907e6ad469SVishal Kulkarni F_FW_CMD_EXEC |
122917e6ad469SVishal Kulkarni V_FW_ACL_VLAN_CMD_PFN(adap->pf) |
122927e6ad469SVishal Kulkarni V_FW_ACL_VLAN_CMD_VFN(vf));
122937e6ad469SVishal Kulkarni vlan_cmd.en_to_len16 = cpu_to_be32(enable | FW_LEN16(vlan_cmd));
122947e6ad469SVishal Kulkarni /* Drop all packets that donot match vlan id */
122957e6ad469SVishal Kulkarni vlan_cmd.dropnovlan_fm = (enable
122967e6ad469SVishal Kulkarni ? (F_FW_ACL_VLAN_CMD_DROPNOVLAN |
122977e6ad469SVishal Kulkarni F_FW_ACL_VLAN_CMD_FM)
122987e6ad469SVishal Kulkarni : 0);
122997e6ad469SVishal Kulkarni if (enable != 0) {
123007e6ad469SVishal Kulkarni vlan_cmd.nvlan = 1;
123017e6ad469SVishal Kulkarni vlan_cmd.vlanid[0] = cpu_to_be16(vlan);
123027e6ad469SVishal Kulkarni }
123037e6ad469SVishal Kulkarni
123047e6ad469SVishal Kulkarni return t4_wr_mbox(adap, adap->mbox, &vlan_cmd, sizeof(vlan_cmd), NULL);
123057e6ad469SVishal Kulkarni }
123067e6ad469SVishal Kulkarni
123077e6ad469SVishal Kulkarni /**
123087e6ad469SVishal Kulkarni * t4_del_mac - Removes the exact-match filter for a MAC address
123097e6ad469SVishal Kulkarni * @adap: the adapter
123107e6ad469SVishal Kulkarni * @mbox: mailbox to use for the FW command
123117e6ad469SVishal Kulkarni * @viid: the VI id
123127e6ad469SVishal Kulkarni * @addr: the MAC address value
123137e6ad469SVishal Kulkarni * @smac: if true, delete from only the smac region of MPS
123147e6ad469SVishal Kulkarni *
123157e6ad469SVishal Kulkarni * Modifies an exact-match filter and sets it to the new MAC address if
123167e6ad469SVishal Kulkarni * @idx >= 0, or adds the MAC address to a new filter if @idx < 0. In the
123177e6ad469SVishal Kulkarni * latter case the address is added persistently if @persist is %true.
123187e6ad469SVishal Kulkarni *
123197e6ad469SVishal Kulkarni * Returns a negative error number or the index of the filter with the new
123207e6ad469SVishal Kulkarni * MAC value. Note that this index may differ from @idx.
123217e6ad469SVishal Kulkarni */
t4_del_mac(struct adapter * adap,unsigned int mbox,unsigned int viid,const u8 * addr,bool smac)123227e6ad469SVishal Kulkarni int t4_del_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
123237e6ad469SVishal Kulkarni const u8 *addr, bool smac)
123247e6ad469SVishal Kulkarni {
123257e6ad469SVishal Kulkarni int ret;
123267e6ad469SVishal Kulkarni struct fw_vi_mac_cmd c;
123277e6ad469SVishal Kulkarni struct fw_vi_mac_exact *p = c.u.exact;
123287e6ad469SVishal Kulkarni unsigned int max_mac_addr = adap->params.arch.mps_tcam_size;
123297e6ad469SVishal Kulkarni
123307e6ad469SVishal Kulkarni memset(&c, 0, sizeof(c));
123317e6ad469SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
123327e6ad469SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
123337e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_VIID(viid));
123347e6ad469SVishal Kulkarni c.freemacs_to_len16 = cpu_to_be32(
123357e6ad469SVishal Kulkarni V_FW_CMD_LEN16(1) |
123367e6ad469SVishal Kulkarni (smac ? F_FW_VI_MAC_CMD_IS_SMAC : 0));
123377e6ad469SVishal Kulkarni
123387e6ad469SVishal Kulkarni memcpy(p->macaddr, addr, sizeof(p->macaddr));
123397e6ad469SVishal Kulkarni p->valid_to_idx = cpu_to_be16(
123407e6ad469SVishal Kulkarni F_FW_VI_MAC_CMD_VALID |
123417e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_IDX(FW_VI_MAC_MAC_BASED_FREE));
123427e6ad469SVishal Kulkarni
123437e6ad469SVishal Kulkarni ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
123447e6ad469SVishal Kulkarni if (ret == 0) {
123457e6ad469SVishal Kulkarni ret = G_FW_VI_MAC_CMD_IDX(be16_to_cpu(p->valid_to_idx));
123467e6ad469SVishal Kulkarni if (ret < max_mac_addr)
123477e6ad469SVishal Kulkarni return -ENOMEM;
123487e6ad469SVishal Kulkarni }
123497e6ad469SVishal Kulkarni
123507e6ad469SVishal Kulkarni return ret;
123517e6ad469SVishal Kulkarni }
123527e6ad469SVishal Kulkarni
123537e6ad469SVishal Kulkarni /**
123547e6ad469SVishal Kulkarni * t4_add_mac - Adds an exact-match filter for a MAC address
123557e6ad469SVishal Kulkarni * @adap: the adapter
123567e6ad469SVishal Kulkarni * @mbox: mailbox to use for the FW command
123577e6ad469SVishal Kulkarni * @viid: the VI id
123587e6ad469SVishal Kulkarni * @idx: index of existing filter for old value of MAC address, or -1
123597e6ad469SVishal Kulkarni * @addr: the new MAC address value
123607e6ad469SVishal Kulkarni * @persist: whether a new MAC allocation should be persistent
123617e6ad469SVishal Kulkarni * @add_smt: if true also add the address to the HW SMT
123627e6ad469SVishal Kulkarni * @smac: if true, update only the smac region of MPS
123637e6ad469SVishal Kulkarni *
123647e6ad469SVishal Kulkarni * Modifies an exact-match filter and sets it to the new MAC address if
123657e6ad469SVishal Kulkarni * @idx >= 0, or adds the MAC address to a new filter if @idx < 0. In the
123667e6ad469SVishal Kulkarni * latter case the address is added persistently if @persist is %true.
123677e6ad469SVishal Kulkarni *
123687e6ad469SVishal Kulkarni * Returns a negative error number or the index of the filter with the new
123697e6ad469SVishal Kulkarni * MAC value. Note that this index may differ from @idx.
123707e6ad469SVishal Kulkarni */
t4_add_mac(struct adapter * adap,unsigned int mbox,unsigned int viid,int idx,const u8 * addr,bool persist,u8 * smt_idx,bool smac)123717e6ad469SVishal Kulkarni int t4_add_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
123727e6ad469SVishal Kulkarni int idx, const u8 *addr, bool persist, u8 *smt_idx, bool smac)
123737e6ad469SVishal Kulkarni {
123747e6ad469SVishal Kulkarni int ret, mode;
123757e6ad469SVishal Kulkarni struct fw_vi_mac_cmd c;
123767e6ad469SVishal Kulkarni struct fw_vi_mac_exact *p = c.u.exact;
123777e6ad469SVishal Kulkarni unsigned int max_mac_addr = adap->params.arch.mps_tcam_size;
123787e6ad469SVishal Kulkarni
123797e6ad469SVishal Kulkarni if (idx < 0) /* new allocation */
123807e6ad469SVishal Kulkarni idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC;
123817e6ad469SVishal Kulkarni mode = smt_idx ? FW_VI_MAC_SMT_AND_MPSTCAM : FW_VI_MAC_MPS_TCAM_ENTRY;
123827e6ad469SVishal Kulkarni
123837e6ad469SVishal Kulkarni memset(&c, 0, sizeof(c));
123847e6ad469SVishal Kulkarni c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) |
123857e6ad469SVishal Kulkarni F_FW_CMD_REQUEST | F_FW_CMD_WRITE |
123867e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_VIID(viid));
123877e6ad469SVishal Kulkarni c.freemacs_to_len16 = cpu_to_be32(
123887e6ad469SVishal Kulkarni V_FW_CMD_LEN16(1) |
123897e6ad469SVishal Kulkarni (smac ? F_FW_VI_MAC_CMD_IS_SMAC : 0));
123907e6ad469SVishal Kulkarni p->valid_to_idx = cpu_to_be16(F_FW_VI_MAC_CMD_VALID |
123917e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_SMAC_RESULT(mode) |
123927e6ad469SVishal Kulkarni V_FW_VI_MAC_CMD_IDX(idx));
123937e6ad469SVishal Kulkarni memcpy(p->macaddr, addr, sizeof(p->macaddr));
123947e6ad469SVishal Kulkarni
123957e6ad469SVishal Kulkarni ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
123967e6ad469SVishal Kulkarni if (ret == 0) {
123977e6ad469SVishal Kulkarni ret = G_FW_VI_MAC_CMD_IDX(be16_to_cpu(p->valid_to_idx));
123987e6ad469SVishal Kulkarni if (ret >= max_mac_addr)
123997e6ad469SVishal Kulkarni return -ENOMEM;
124007e6ad469SVishal Kulkarni if (smt_idx) {
124017e6ad469SVishal Kulkarni /* Does fw supports returning smt_idx? */
124027e6ad469SVishal Kulkarni if (adap->params.viid_smt_extn_support)
124037e6ad469SVishal Kulkarni *smt_idx = G_FW_VI_MAC_CMD_SMTID(be32_to_cpu(c.op_to_viid));
124047e6ad469SVishal Kulkarni else {
124057e6ad469SVishal Kulkarni /* In T4/T5, SMT contains 256 SMAC entries
124067e6ad469SVishal Kulkarni * organized in 128 rows of 2 entries each.
124077e6ad469SVishal Kulkarni * In T6, SMT contains 256 SMAC entries in
124087e6ad469SVishal Kulkarni * 256 rows.
124097e6ad469SVishal Kulkarni */
124107e6ad469SVishal Kulkarni if (CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5)
124117e6ad469SVishal Kulkarni *smt_idx = ((viid & M_FW_VIID_VIN) << 1);
124127e6ad469SVishal Kulkarni else
124137e6ad469SVishal Kulkarni *smt_idx = (viid & M_FW_VIID_VIN);
124147e6ad469SVishal Kulkarni }
124157e6ad469SVishal Kulkarni }
124167e6ad469SVishal Kulkarni }
124177e6ad469SVishal Kulkarni
124187e6ad469SVishal Kulkarni return ret;
124197e6ad469SVishal Kulkarni }
124207e6ad469SVishal Kulkarni
12421