xref: /illumos-gate/usr/src/uts/common/io/cxgbe/common/t4_hw.c (revision ece8d79431327a5ada7d885f1e001273dff26c72)
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 			      &param, &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 			      &param, &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 				    &param, &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, &param, &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, &param, &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 			      &param, &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, &param, &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, &param, &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 				    &param, &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, &param, &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, &param, &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