1f7917c00SJeff Kirsher /*
2f7917c00SJeff Kirsher  * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
3f7917c00SJeff Kirsher  *
4f7917c00SJeff Kirsher  * This software is available to you under a choice of one of two
5f7917c00SJeff Kirsher  * licenses.  You may choose to be licensed under the terms of the GNU
6f7917c00SJeff Kirsher  * General Public License (GPL) Version 2, available from the file
7f7917c00SJeff Kirsher  * COPYING in the main directory of this source tree, or the
8f7917c00SJeff Kirsher  * OpenIB.org BSD license below:
9f7917c00SJeff Kirsher  *
10f7917c00SJeff Kirsher  *     Redistribution and use in source and binary forms, with or
11f7917c00SJeff Kirsher  *     without modification, are permitted provided that the following
12f7917c00SJeff Kirsher  *     conditions are met:
13f7917c00SJeff Kirsher  *
14f7917c00SJeff Kirsher  *      - Redistributions of source code must retain the above
15f7917c00SJeff Kirsher  *        copyright notice, this list of conditions and the following
16f7917c00SJeff Kirsher  *        disclaimer.
17f7917c00SJeff Kirsher  *
18f7917c00SJeff Kirsher  *      - Redistributions in binary form must reproduce the above
19f7917c00SJeff Kirsher  *        copyright notice, this list of conditions and the following
20f7917c00SJeff Kirsher  *        disclaimer in the documentation and/or other materials
21f7917c00SJeff Kirsher  *        provided with the distribution.
22f7917c00SJeff Kirsher  *
23f7917c00SJeff Kirsher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24f7917c00SJeff Kirsher  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25f7917c00SJeff Kirsher  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26f7917c00SJeff Kirsher  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27f7917c00SJeff Kirsher  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28f7917c00SJeff Kirsher  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29f7917c00SJeff Kirsher  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30f7917c00SJeff Kirsher  * SOFTWARE.
31f7917c00SJeff Kirsher  */
3247d71f45SJakub Kicinski #include <linux/etherdevice.h>
33f7917c00SJeff Kirsher #include "common.h"
34f7917c00SJeff Kirsher #include "regs.h"
35f7917c00SJeff Kirsher #include "sge_defs.h"
36f7917c00SJeff Kirsher #include "firmware_exports.h"
37f7917c00SJeff Kirsher 
38f7917c00SJeff Kirsher static void t3_port_intr_clear(struct adapter *adapter, int idx);
39f7917c00SJeff Kirsher 
40f7917c00SJeff Kirsher /**
41f7917c00SJeff Kirsher  *	t3_wait_op_done_val - wait until an operation is completed
42f7917c00SJeff Kirsher  *	@adapter: the adapter performing the operation
43f7917c00SJeff Kirsher  *	@reg: the register to check for completion
44f7917c00SJeff Kirsher  *	@mask: a single-bit field within @reg that indicates completion
45f7917c00SJeff Kirsher  *	@polarity: the value of the field when the operation is completed
46f7917c00SJeff Kirsher  *	@attempts: number of check iterations
47f7917c00SJeff Kirsher  *	@delay: delay in usecs between iterations
48f7917c00SJeff Kirsher  *	@valp: where to store the value of the register at completion time
49f7917c00SJeff Kirsher  *
50f7917c00SJeff Kirsher  *	Wait until an operation is completed by checking a bit in a register
51f7917c00SJeff Kirsher  *	up to @attempts times.  If @valp is not NULL the value of the register
52f7917c00SJeff Kirsher  *	at the time it indicated completion is stored there.  Returns 0 if the
53f7917c00SJeff Kirsher  *	operation completes and -EAGAIN otherwise.
54f7917c00SJeff Kirsher  */
55f7917c00SJeff Kirsher 
t3_wait_op_done_val(struct adapter * adapter,int reg,u32 mask,int polarity,int attempts,int delay,u32 * valp)56f7917c00SJeff Kirsher int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
57f7917c00SJeff Kirsher 			int polarity, int attempts, int delay, u32 *valp)
58f7917c00SJeff Kirsher {
59f7917c00SJeff Kirsher 	while (1) {
60f7917c00SJeff Kirsher 		u32 val = t3_read_reg(adapter, reg);
61f7917c00SJeff Kirsher 
62f7917c00SJeff Kirsher 		if (!!(val & mask) == polarity) {
63f7917c00SJeff Kirsher 			if (valp)
64f7917c00SJeff Kirsher 				*valp = val;
65f7917c00SJeff Kirsher 			return 0;
66f7917c00SJeff Kirsher 		}
67f7917c00SJeff Kirsher 		if (--attempts == 0)
68f7917c00SJeff Kirsher 			return -EAGAIN;
69f7917c00SJeff Kirsher 		if (delay)
70f7917c00SJeff Kirsher 			udelay(delay);
71f7917c00SJeff Kirsher 	}
72f7917c00SJeff Kirsher }
73f7917c00SJeff Kirsher 
74f7917c00SJeff Kirsher /**
75f7917c00SJeff Kirsher  *	t3_write_regs - write a bunch of registers
76f7917c00SJeff Kirsher  *	@adapter: the adapter to program
77f7917c00SJeff Kirsher  *	@p: an array of register address/register value pairs
78f7917c00SJeff Kirsher  *	@n: the number of address/value pairs
79f7917c00SJeff Kirsher  *	@offset: register address offset
80f7917c00SJeff Kirsher  *
81f7917c00SJeff Kirsher  *	Takes an array of register address/register value pairs and writes each
82f7917c00SJeff Kirsher  *	value to the corresponding register.  Register addresses are adjusted
83f7917c00SJeff Kirsher  *	by the supplied offset.
84f7917c00SJeff Kirsher  */
t3_write_regs(struct adapter * adapter,const struct addr_val_pair * p,int n,unsigned int offset)85f7917c00SJeff Kirsher void t3_write_regs(struct adapter *adapter, const struct addr_val_pair *p,
86f7917c00SJeff Kirsher 		   int n, unsigned int offset)
87f7917c00SJeff Kirsher {
88f7917c00SJeff Kirsher 	while (n--) {
89f7917c00SJeff Kirsher 		t3_write_reg(adapter, p->reg_addr + offset, p->val);
90f7917c00SJeff Kirsher 		p++;
91f7917c00SJeff Kirsher 	}
92f7917c00SJeff Kirsher }
93f7917c00SJeff Kirsher 
94f7917c00SJeff Kirsher /**
95f7917c00SJeff Kirsher  *	t3_set_reg_field - set a register field to a value
96f7917c00SJeff Kirsher  *	@adapter: the adapter to program
97f7917c00SJeff Kirsher  *	@addr: the register address
98f7917c00SJeff Kirsher  *	@mask: specifies the portion of the register to modify
99f7917c00SJeff Kirsher  *	@val: the new value for the register field
100f7917c00SJeff Kirsher  *
101f7917c00SJeff Kirsher  *	Sets a register field specified by the supplied mask to the
102f7917c00SJeff Kirsher  *	given value.
103f7917c00SJeff Kirsher  */
t3_set_reg_field(struct adapter * adapter,unsigned int addr,u32 mask,u32 val)104f7917c00SJeff Kirsher void t3_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask,
105f7917c00SJeff Kirsher 		      u32 val)
106f7917c00SJeff Kirsher {
107f7917c00SJeff Kirsher 	u32 v = t3_read_reg(adapter, addr) & ~mask;
108f7917c00SJeff Kirsher 
109f7917c00SJeff Kirsher 	t3_write_reg(adapter, addr, v | val);
110f7917c00SJeff Kirsher 	t3_read_reg(adapter, addr);	/* flush */
111f7917c00SJeff Kirsher }
112f7917c00SJeff Kirsher 
113f7917c00SJeff Kirsher /**
114f7917c00SJeff Kirsher  *	t3_read_indirect - read indirectly addressed registers
115f7917c00SJeff Kirsher  *	@adap: the adapter
116f7917c00SJeff Kirsher  *	@addr_reg: register holding the indirect address
117f7917c00SJeff Kirsher  *	@data_reg: register holding the value of the indirect register
118f7917c00SJeff Kirsher  *	@vals: where the read register values are stored
119f7917c00SJeff Kirsher  *	@start_idx: index of first indirect register to read
120f7917c00SJeff Kirsher  *	@nregs: how many indirect registers to read
121f7917c00SJeff Kirsher  *
122f7917c00SJeff Kirsher  *	Reads registers that are accessed indirectly through an address/data
123f7917c00SJeff Kirsher  *	register pair.
124f7917c00SJeff Kirsher  */
t3_read_indirect(struct adapter * adap,unsigned int addr_reg,unsigned int data_reg,u32 * vals,unsigned int nregs,unsigned int start_idx)125f7917c00SJeff Kirsher static void t3_read_indirect(struct adapter *adap, unsigned int addr_reg,
126f7917c00SJeff Kirsher 			     unsigned int data_reg, u32 *vals,
127f7917c00SJeff Kirsher 			     unsigned int nregs, unsigned int start_idx)
128f7917c00SJeff Kirsher {
129f7917c00SJeff Kirsher 	while (nregs--) {
130f7917c00SJeff Kirsher 		t3_write_reg(adap, addr_reg, start_idx);
131f7917c00SJeff Kirsher 		*vals++ = t3_read_reg(adap, data_reg);
132f7917c00SJeff Kirsher 		start_idx++;
133f7917c00SJeff Kirsher 	}
134f7917c00SJeff Kirsher }
135f7917c00SJeff Kirsher 
136f7917c00SJeff Kirsher /**
137f7917c00SJeff Kirsher  *	t3_mc7_bd_read - read from MC7 through backdoor accesses
138f7917c00SJeff Kirsher  *	@mc7: identifies MC7 to read from
139f7917c00SJeff Kirsher  *	@start: index of first 64-bit word to read
140f7917c00SJeff Kirsher  *	@n: number of 64-bit words to read
141f7917c00SJeff Kirsher  *	@buf: where to store the read result
142f7917c00SJeff Kirsher  *
143f7917c00SJeff Kirsher  *	Read n 64-bit words from MC7 starting at word start, using backdoor
144f7917c00SJeff Kirsher  *	accesses.
145f7917c00SJeff Kirsher  */
t3_mc7_bd_read(struct mc7 * mc7,unsigned int start,unsigned int n,u64 * buf)146f7917c00SJeff Kirsher int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
147f7917c00SJeff Kirsher 		   u64 *buf)
148f7917c00SJeff Kirsher {
149f7917c00SJeff Kirsher 	static const int shift[] = { 0, 0, 16, 24 };
150f7917c00SJeff Kirsher 	static const int step[] = { 0, 32, 16, 8 };
151f7917c00SJeff Kirsher 
152f7917c00SJeff Kirsher 	unsigned int size64 = mc7->size / 8;	/* # of 64-bit words */
153f7917c00SJeff Kirsher 	struct adapter *adap = mc7->adapter;
154f7917c00SJeff Kirsher 
155f7917c00SJeff Kirsher 	if (start >= size64 || start + n > size64)
156f7917c00SJeff Kirsher 		return -EINVAL;
157f7917c00SJeff Kirsher 
158f7917c00SJeff Kirsher 	start *= (8 << mc7->width);
159f7917c00SJeff Kirsher 	while (n--) {
160f7917c00SJeff Kirsher 		int i;
161f7917c00SJeff Kirsher 		u64 val64 = 0;
162f7917c00SJeff Kirsher 
163f7917c00SJeff Kirsher 		for (i = (1 << mc7->width) - 1; i >= 0; --i) {
164f7917c00SJeff Kirsher 			int attempts = 10;
165f7917c00SJeff Kirsher 			u32 val;
166f7917c00SJeff Kirsher 
167f7917c00SJeff Kirsher 			t3_write_reg(adap, mc7->offset + A_MC7_BD_ADDR, start);
168f7917c00SJeff Kirsher 			t3_write_reg(adap, mc7->offset + A_MC7_BD_OP, 0);
169f7917c00SJeff Kirsher 			val = t3_read_reg(adap, mc7->offset + A_MC7_BD_OP);
170f7917c00SJeff Kirsher 			while ((val & F_BUSY) && attempts--)
171f7917c00SJeff Kirsher 				val = t3_read_reg(adap,
172f7917c00SJeff Kirsher 						  mc7->offset + A_MC7_BD_OP);
173f7917c00SJeff Kirsher 			if (val & F_BUSY)
174f7917c00SJeff Kirsher 				return -EIO;
175f7917c00SJeff Kirsher 
176f7917c00SJeff Kirsher 			val = t3_read_reg(adap, mc7->offset + A_MC7_BD_DATA1);
177f7917c00SJeff Kirsher 			if (mc7->width == 0) {
178f7917c00SJeff Kirsher 				val64 = t3_read_reg(adap,
179f7917c00SJeff Kirsher 						    mc7->offset +
180f7917c00SJeff Kirsher 						    A_MC7_BD_DATA0);
181f7917c00SJeff Kirsher 				val64 |= (u64) val << 32;
182f7917c00SJeff Kirsher 			} else {
183f7917c00SJeff Kirsher 				if (mc7->width > 1)
184f7917c00SJeff Kirsher 					val >>= shift[mc7->width];
185f7917c00SJeff Kirsher 				val64 |= (u64) val << (step[mc7->width] * i);
186f7917c00SJeff Kirsher 			}
187f7917c00SJeff Kirsher 			start += 8;
188f7917c00SJeff Kirsher 		}
189f7917c00SJeff Kirsher 		*buf++ = val64;
190f7917c00SJeff Kirsher 	}
191f7917c00SJeff Kirsher 	return 0;
192f7917c00SJeff Kirsher }
193f7917c00SJeff Kirsher 
194f7917c00SJeff Kirsher /*
195f7917c00SJeff Kirsher  * Initialize MI1.
196f7917c00SJeff Kirsher  */
mi1_init(struct adapter * adap,const struct adapter_info * ai)197f7917c00SJeff Kirsher static void mi1_init(struct adapter *adap, const struct adapter_info *ai)
198f7917c00SJeff Kirsher {
199f7917c00SJeff Kirsher 	u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1;
200f7917c00SJeff Kirsher 	u32 val = F_PREEN | V_CLKDIV(clkdiv);
201f7917c00SJeff Kirsher 
202f7917c00SJeff Kirsher 	t3_write_reg(adap, A_MI1_CFG, val);
203f7917c00SJeff Kirsher }
204f7917c00SJeff Kirsher 
205f7917c00SJeff Kirsher #define MDIO_ATTEMPTS 20
206f7917c00SJeff Kirsher 
207f7917c00SJeff Kirsher /*
208f7917c00SJeff Kirsher  * MI1 read/write operations for clause 22 PHYs.
209f7917c00SJeff Kirsher  */
t3_mi1_read(struct net_device * dev,int phy_addr,int mmd_addr,u16 reg_addr)210f7917c00SJeff Kirsher static int t3_mi1_read(struct net_device *dev, int phy_addr, int mmd_addr,
211f7917c00SJeff Kirsher 		       u16 reg_addr)
212f7917c00SJeff Kirsher {
213f7917c00SJeff Kirsher 	struct port_info *pi = netdev_priv(dev);
214f7917c00SJeff Kirsher 	struct adapter *adapter = pi->adapter;
215f7917c00SJeff Kirsher 	int ret;
216f7917c00SJeff Kirsher 	u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);
217f7917c00SJeff Kirsher 
218f7917c00SJeff Kirsher 	mutex_lock(&adapter->mdio_lock);
219f7917c00SJeff Kirsher 	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
220f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MI1_ADDR, addr);
221f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2));
222f7917c00SJeff Kirsher 	ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
223f7917c00SJeff Kirsher 	if (!ret)
224f7917c00SJeff Kirsher 		ret = t3_read_reg(adapter, A_MI1_DATA);
225f7917c00SJeff Kirsher 	mutex_unlock(&adapter->mdio_lock);
226f7917c00SJeff Kirsher 	return ret;
227f7917c00SJeff Kirsher }
228f7917c00SJeff Kirsher 
t3_mi1_write(struct net_device * dev,int phy_addr,int mmd_addr,u16 reg_addr,u16 val)229f7917c00SJeff Kirsher static int t3_mi1_write(struct net_device *dev, int phy_addr, int mmd_addr,
230f7917c00SJeff Kirsher 			u16 reg_addr, u16 val)
231f7917c00SJeff Kirsher {
232f7917c00SJeff Kirsher 	struct port_info *pi = netdev_priv(dev);
233f7917c00SJeff Kirsher 	struct adapter *adapter = pi->adapter;
234f7917c00SJeff Kirsher 	int ret;
235f7917c00SJeff Kirsher 	u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr);
236f7917c00SJeff Kirsher 
237f7917c00SJeff Kirsher 	mutex_lock(&adapter->mdio_lock);
238f7917c00SJeff Kirsher 	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1));
239f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MI1_ADDR, addr);
240f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MI1_DATA, val);
241f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1));
242f7917c00SJeff Kirsher 	ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
243f7917c00SJeff Kirsher 	mutex_unlock(&adapter->mdio_lock);
244f7917c00SJeff Kirsher 	return ret;
245f7917c00SJeff Kirsher }
246f7917c00SJeff Kirsher 
247f7917c00SJeff Kirsher static const struct mdio_ops mi1_mdio_ops = {
248f7917c00SJeff Kirsher 	.read = t3_mi1_read,
249f7917c00SJeff Kirsher 	.write = t3_mi1_write,
250f7917c00SJeff Kirsher 	.mode_support = MDIO_SUPPORTS_C22
251f7917c00SJeff Kirsher };
252f7917c00SJeff Kirsher 
253f7917c00SJeff Kirsher /*
254f7917c00SJeff Kirsher  * Performs the address cycle for clause 45 PHYs.
255f7917c00SJeff Kirsher  * Must be called with the MDIO_LOCK held.
256f7917c00SJeff Kirsher  */
mi1_wr_addr(struct adapter * adapter,int phy_addr,int mmd_addr,int reg_addr)257f7917c00SJeff Kirsher static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr,
258f7917c00SJeff Kirsher 		       int reg_addr)
259f7917c00SJeff Kirsher {
260f7917c00SJeff Kirsher 	u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr);
261f7917c00SJeff Kirsher 
262f7917c00SJeff Kirsher 	t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), 0);
263f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MI1_ADDR, addr);
264f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MI1_DATA, reg_addr);
265f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0));
266f7917c00SJeff Kirsher 	return t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
267f7917c00SJeff Kirsher 			       MDIO_ATTEMPTS, 10);
268f7917c00SJeff Kirsher }
269f7917c00SJeff Kirsher 
270f7917c00SJeff Kirsher /*
271f7917c00SJeff Kirsher  * MI1 read/write operations for indirect-addressed PHYs.
272f7917c00SJeff Kirsher  */
mi1_ext_read(struct net_device * dev,int phy_addr,int mmd_addr,u16 reg_addr)273f7917c00SJeff Kirsher static int mi1_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
274f7917c00SJeff Kirsher 			u16 reg_addr)
275f7917c00SJeff Kirsher {
276f7917c00SJeff Kirsher 	struct port_info *pi = netdev_priv(dev);
277f7917c00SJeff Kirsher 	struct adapter *adapter = pi->adapter;
278f7917c00SJeff Kirsher 	int ret;
279f7917c00SJeff Kirsher 
280f7917c00SJeff Kirsher 	mutex_lock(&adapter->mdio_lock);
281f7917c00SJeff Kirsher 	ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr);
282f7917c00SJeff Kirsher 	if (!ret) {
283f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3));
284f7917c00SJeff Kirsher 		ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
285f7917c00SJeff Kirsher 				      MDIO_ATTEMPTS, 10);
286f7917c00SJeff Kirsher 		if (!ret)
287f7917c00SJeff Kirsher 			ret = t3_read_reg(adapter, A_MI1_DATA);
288f7917c00SJeff Kirsher 	}
289f7917c00SJeff Kirsher 	mutex_unlock(&adapter->mdio_lock);
290f7917c00SJeff Kirsher 	return ret;
291f7917c00SJeff Kirsher }
292f7917c00SJeff Kirsher 
mi1_ext_write(struct net_device * dev,int phy_addr,int mmd_addr,u16 reg_addr,u16 val)293f7917c00SJeff Kirsher static int mi1_ext_write(struct net_device *dev, int phy_addr, int mmd_addr,
294f7917c00SJeff Kirsher 			 u16 reg_addr, u16 val)
295f7917c00SJeff Kirsher {
296f7917c00SJeff Kirsher 	struct port_info *pi = netdev_priv(dev);
297f7917c00SJeff Kirsher 	struct adapter *adapter = pi->adapter;
298f7917c00SJeff Kirsher 	int ret;
299f7917c00SJeff Kirsher 
300f7917c00SJeff Kirsher 	mutex_lock(&adapter->mdio_lock);
301f7917c00SJeff Kirsher 	ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr);
302f7917c00SJeff Kirsher 	if (!ret) {
303f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_MI1_DATA, val);
304f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1));
305f7917c00SJeff Kirsher 		ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
306f7917c00SJeff Kirsher 				      MDIO_ATTEMPTS, 10);
307f7917c00SJeff Kirsher 	}
308f7917c00SJeff Kirsher 	mutex_unlock(&adapter->mdio_lock);
309f7917c00SJeff Kirsher 	return ret;
310f7917c00SJeff Kirsher }
311f7917c00SJeff Kirsher 
312f7917c00SJeff Kirsher static const struct mdio_ops mi1_mdio_ext_ops = {
313f7917c00SJeff Kirsher 	.read = mi1_ext_read,
314f7917c00SJeff Kirsher 	.write = mi1_ext_write,
315f7917c00SJeff Kirsher 	.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
316f7917c00SJeff Kirsher };
317f7917c00SJeff Kirsher 
318f7917c00SJeff Kirsher /**
319f7917c00SJeff Kirsher  *	t3_mdio_change_bits - modify the value of a PHY register
320f7917c00SJeff Kirsher  *	@phy: the PHY to operate on
321f7917c00SJeff Kirsher  *	@mmd: the device address
322f7917c00SJeff Kirsher  *	@reg: the register address
323f7917c00SJeff Kirsher  *	@clear: what part of the register value to mask off
324f7917c00SJeff Kirsher  *	@set: what part of the register value to set
325f7917c00SJeff Kirsher  *
326f7917c00SJeff Kirsher  *	Changes the value of a PHY register by applying a mask to its current
327f7917c00SJeff Kirsher  *	value and ORing the result with a new value.
328f7917c00SJeff Kirsher  */
t3_mdio_change_bits(struct cphy * phy,int mmd,int reg,unsigned int clear,unsigned int set)329f7917c00SJeff Kirsher int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear,
330f7917c00SJeff Kirsher 			unsigned int set)
331f7917c00SJeff Kirsher {
332f7917c00SJeff Kirsher 	int ret;
333f7917c00SJeff Kirsher 	unsigned int val;
334f7917c00SJeff Kirsher 
335f7917c00SJeff Kirsher 	ret = t3_mdio_read(phy, mmd, reg, &val);
336f7917c00SJeff Kirsher 	if (!ret) {
337f7917c00SJeff Kirsher 		val &= ~clear;
338f7917c00SJeff Kirsher 		ret = t3_mdio_write(phy, mmd, reg, val | set);
339f7917c00SJeff Kirsher 	}
340f7917c00SJeff Kirsher 	return ret;
341f7917c00SJeff Kirsher }
342f7917c00SJeff Kirsher 
343f7917c00SJeff Kirsher /**
344f7917c00SJeff Kirsher  *	t3_phy_reset - reset a PHY block
345f7917c00SJeff Kirsher  *	@phy: the PHY to operate on
346f7917c00SJeff Kirsher  *	@mmd: the device address of the PHY block to reset
347f7917c00SJeff Kirsher  *	@wait: how long to wait for the reset to complete in 1ms increments
348f7917c00SJeff Kirsher  *
349f7917c00SJeff Kirsher  *	Resets a PHY block and optionally waits for the reset to complete.
350f7917c00SJeff Kirsher  *	@mmd should be 0 for 10/100/1000 PHYs and the device address to reset
351f7917c00SJeff Kirsher  *	for 10G PHYs.
352f7917c00SJeff Kirsher  */
t3_phy_reset(struct cphy * phy,int mmd,int wait)353f7917c00SJeff Kirsher int t3_phy_reset(struct cphy *phy, int mmd, int wait)
354f7917c00SJeff Kirsher {
355f7917c00SJeff Kirsher 	int err;
356f7917c00SJeff Kirsher 	unsigned int ctl;
357f7917c00SJeff Kirsher 
358f7917c00SJeff Kirsher 	err = t3_mdio_change_bits(phy, mmd, MDIO_CTRL1, MDIO_CTRL1_LPOWER,
359f7917c00SJeff Kirsher 				  MDIO_CTRL1_RESET);
360f7917c00SJeff Kirsher 	if (err || !wait)
361f7917c00SJeff Kirsher 		return err;
362f7917c00SJeff Kirsher 
363f7917c00SJeff Kirsher 	do {
364f7917c00SJeff Kirsher 		err = t3_mdio_read(phy, mmd, MDIO_CTRL1, &ctl);
365f7917c00SJeff Kirsher 		if (err)
366f7917c00SJeff Kirsher 			return err;
367f7917c00SJeff Kirsher 		ctl &= MDIO_CTRL1_RESET;
368f7917c00SJeff Kirsher 		if (ctl)
369f7917c00SJeff Kirsher 			msleep(1);
370f7917c00SJeff Kirsher 	} while (ctl && --wait);
371f7917c00SJeff Kirsher 
372f7917c00SJeff Kirsher 	return ctl ? -1 : 0;
373f7917c00SJeff Kirsher }
374f7917c00SJeff Kirsher 
375f7917c00SJeff Kirsher /**
376f7917c00SJeff Kirsher  *	t3_phy_advertise - set the PHY advertisement registers for autoneg
377f7917c00SJeff Kirsher  *	@phy: the PHY to operate on
378f7917c00SJeff Kirsher  *	@advert: bitmap of capabilities the PHY should advertise
379f7917c00SJeff Kirsher  *
380f7917c00SJeff Kirsher  *	Sets a 10/100/1000 PHY's advertisement registers to advertise the
381f7917c00SJeff Kirsher  *	requested capabilities.
382f7917c00SJeff Kirsher  */
t3_phy_advertise(struct cphy * phy,unsigned int advert)383f7917c00SJeff Kirsher int t3_phy_advertise(struct cphy *phy, unsigned int advert)
384f7917c00SJeff Kirsher {
385f7917c00SJeff Kirsher 	int err;
386f7917c00SJeff Kirsher 	unsigned int val = 0;
387f7917c00SJeff Kirsher 
388f7917c00SJeff Kirsher 	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_CTRL1000, &val);
389f7917c00SJeff Kirsher 	if (err)
390f7917c00SJeff Kirsher 		return err;
391f7917c00SJeff Kirsher 
392f7917c00SJeff Kirsher 	val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
393f7917c00SJeff Kirsher 	if (advert & ADVERTISED_1000baseT_Half)
394f7917c00SJeff Kirsher 		val |= ADVERTISE_1000HALF;
395f7917c00SJeff Kirsher 	if (advert & ADVERTISED_1000baseT_Full)
396f7917c00SJeff Kirsher 		val |= ADVERTISE_1000FULL;
397f7917c00SJeff Kirsher 
398f7917c00SJeff Kirsher 	err = t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_CTRL1000, val);
399f7917c00SJeff Kirsher 	if (err)
400f7917c00SJeff Kirsher 		return err;
401f7917c00SJeff Kirsher 
402f7917c00SJeff Kirsher 	val = 1;
403f7917c00SJeff Kirsher 	if (advert & ADVERTISED_10baseT_Half)
404f7917c00SJeff Kirsher 		val |= ADVERTISE_10HALF;
405f7917c00SJeff Kirsher 	if (advert & ADVERTISED_10baseT_Full)
406f7917c00SJeff Kirsher 		val |= ADVERTISE_10FULL;
407f7917c00SJeff Kirsher 	if (advert & ADVERTISED_100baseT_Half)
408f7917c00SJeff Kirsher 		val |= ADVERTISE_100HALF;
409f7917c00SJeff Kirsher 	if (advert & ADVERTISED_100baseT_Full)
410f7917c00SJeff Kirsher 		val |= ADVERTISE_100FULL;
411f7917c00SJeff Kirsher 	if (advert & ADVERTISED_Pause)
412f7917c00SJeff Kirsher 		val |= ADVERTISE_PAUSE_CAP;
413f7917c00SJeff Kirsher 	if (advert & ADVERTISED_Asym_Pause)
414f7917c00SJeff Kirsher 		val |= ADVERTISE_PAUSE_ASYM;
415f7917c00SJeff Kirsher 	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val);
416f7917c00SJeff Kirsher }
417f7917c00SJeff Kirsher 
418f7917c00SJeff Kirsher /**
419f7917c00SJeff Kirsher  *	t3_phy_advertise_fiber - set fiber PHY advertisement register
420f7917c00SJeff Kirsher  *	@phy: the PHY to operate on
421f7917c00SJeff Kirsher  *	@advert: bitmap of capabilities the PHY should advertise
422f7917c00SJeff Kirsher  *
423f7917c00SJeff Kirsher  *	Sets a fiber PHY's advertisement register to advertise the
424f7917c00SJeff Kirsher  *	requested capabilities.
425f7917c00SJeff Kirsher  */
t3_phy_advertise_fiber(struct cphy * phy,unsigned int advert)426f7917c00SJeff Kirsher int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert)
427f7917c00SJeff Kirsher {
428f7917c00SJeff Kirsher 	unsigned int val = 0;
429f7917c00SJeff Kirsher 
430f7917c00SJeff Kirsher 	if (advert & ADVERTISED_1000baseT_Half)
431f7917c00SJeff Kirsher 		val |= ADVERTISE_1000XHALF;
432f7917c00SJeff Kirsher 	if (advert & ADVERTISED_1000baseT_Full)
433f7917c00SJeff Kirsher 		val |= ADVERTISE_1000XFULL;
434f7917c00SJeff Kirsher 	if (advert & ADVERTISED_Pause)
435f7917c00SJeff Kirsher 		val |= ADVERTISE_1000XPAUSE;
436f7917c00SJeff Kirsher 	if (advert & ADVERTISED_Asym_Pause)
437f7917c00SJeff Kirsher 		val |= ADVERTISE_1000XPSE_ASYM;
438f7917c00SJeff Kirsher 	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_ADVERTISE, val);
439f7917c00SJeff Kirsher }
440f7917c00SJeff Kirsher 
441f7917c00SJeff Kirsher /**
442f7917c00SJeff Kirsher  *	t3_set_phy_speed_duplex - force PHY speed and duplex
443f7917c00SJeff Kirsher  *	@phy: the PHY to operate on
444f7917c00SJeff Kirsher  *	@speed: requested PHY speed
445f7917c00SJeff Kirsher  *	@duplex: requested PHY duplex
446f7917c00SJeff Kirsher  *
447f7917c00SJeff Kirsher  *	Force a 10/100/1000 PHY's speed and duplex.  This also disables
448f7917c00SJeff Kirsher  *	auto-negotiation except for GigE, where auto-negotiation is mandatory.
449f7917c00SJeff Kirsher  */
t3_set_phy_speed_duplex(struct cphy * phy,int speed,int duplex)450f7917c00SJeff Kirsher int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex)
451f7917c00SJeff Kirsher {
452f7917c00SJeff Kirsher 	int err;
453f7917c00SJeff Kirsher 	unsigned int ctl;
454f7917c00SJeff Kirsher 
455f7917c00SJeff Kirsher 	err = t3_mdio_read(phy, MDIO_DEVAD_NONE, MII_BMCR, &ctl);
456f7917c00SJeff Kirsher 	if (err)
457f7917c00SJeff Kirsher 		return err;
458f7917c00SJeff Kirsher 
459f7917c00SJeff Kirsher 	if (speed >= 0) {
460f7917c00SJeff Kirsher 		ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
461f7917c00SJeff Kirsher 		if (speed == SPEED_100)
462f7917c00SJeff Kirsher 			ctl |= BMCR_SPEED100;
463f7917c00SJeff Kirsher 		else if (speed == SPEED_1000)
464f7917c00SJeff Kirsher 			ctl |= BMCR_SPEED1000;
465f7917c00SJeff Kirsher 	}
466f7917c00SJeff Kirsher 	if (duplex >= 0) {
467f7917c00SJeff Kirsher 		ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE);
468f7917c00SJeff Kirsher 		if (duplex == DUPLEX_FULL)
469f7917c00SJeff Kirsher 			ctl |= BMCR_FULLDPLX;
470f7917c00SJeff Kirsher 	}
471f7917c00SJeff Kirsher 	if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */
472f7917c00SJeff Kirsher 		ctl |= BMCR_ANENABLE;
473f7917c00SJeff Kirsher 	return t3_mdio_write(phy, MDIO_DEVAD_NONE, MII_BMCR, ctl);
474f7917c00SJeff Kirsher }
475f7917c00SJeff Kirsher 
t3_phy_lasi_intr_enable(struct cphy * phy)476f7917c00SJeff Kirsher int t3_phy_lasi_intr_enable(struct cphy *phy)
477f7917c00SJeff Kirsher {
478f7917c00SJeff Kirsher 	return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
479f7917c00SJeff Kirsher 			     MDIO_PMA_LASI_LSALARM);
480f7917c00SJeff Kirsher }
481f7917c00SJeff Kirsher 
t3_phy_lasi_intr_disable(struct cphy * phy)482f7917c00SJeff Kirsher int t3_phy_lasi_intr_disable(struct cphy *phy)
483f7917c00SJeff Kirsher {
484f7917c00SJeff Kirsher 	return t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0);
485f7917c00SJeff Kirsher }
486f7917c00SJeff Kirsher 
t3_phy_lasi_intr_clear(struct cphy * phy)487f7917c00SJeff Kirsher int t3_phy_lasi_intr_clear(struct cphy *phy)
488f7917c00SJeff Kirsher {
489f7917c00SJeff Kirsher 	u32 val;
490f7917c00SJeff Kirsher 
491f7917c00SJeff Kirsher 	return t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val);
492f7917c00SJeff Kirsher }
493f7917c00SJeff Kirsher 
t3_phy_lasi_intr_handler(struct cphy * phy)494f7917c00SJeff Kirsher int t3_phy_lasi_intr_handler(struct cphy *phy)
495f7917c00SJeff Kirsher {
496f7917c00SJeff Kirsher 	unsigned int status;
497f7917c00SJeff Kirsher 	int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT,
498f7917c00SJeff Kirsher 			       &status);
499f7917c00SJeff Kirsher 
500f7917c00SJeff Kirsher 	if (err)
501f7917c00SJeff Kirsher 		return err;
502f7917c00SJeff Kirsher 	return (status & MDIO_PMA_LASI_LSALARM) ? cphy_cause_link_change : 0;
503f7917c00SJeff Kirsher }
504f7917c00SJeff Kirsher 
505f7917c00SJeff Kirsher static const struct adapter_info t3_adap_info[] = {
506f7917c00SJeff Kirsher 	{1, 1, 0,
507f7917c00SJeff Kirsher 	 F_GPIO2_OEN | F_GPIO4_OEN |
508f7917c00SJeff Kirsher 	 F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0,
509f7917c00SJeff Kirsher 	 &mi1_mdio_ops, "Chelsio PE9000"},
510f7917c00SJeff Kirsher 	{1, 1, 0,
511f7917c00SJeff Kirsher 	 F_GPIO2_OEN | F_GPIO4_OEN |
512f7917c00SJeff Kirsher 	 F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0,
513f7917c00SJeff Kirsher 	 &mi1_mdio_ops, "Chelsio T302"},
514f7917c00SJeff Kirsher 	{1, 0, 0,
515f7917c00SJeff Kirsher 	 F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN |
516f7917c00SJeff Kirsher 	 F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
517f7917c00SJeff Kirsher 	 { 0 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
518f7917c00SJeff Kirsher 	 &mi1_mdio_ext_ops, "Chelsio T310"},
519f7917c00SJeff Kirsher 	{1, 1, 0,
520f7917c00SJeff Kirsher 	 F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN |
521f7917c00SJeff Kirsher 	 F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL |
522f7917c00SJeff Kirsher 	 F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
523f7917c00SJeff Kirsher 	 { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
524f7917c00SJeff Kirsher 	 &mi1_mdio_ext_ops, "Chelsio T320"},
525f7917c00SJeff Kirsher 	{},
526f7917c00SJeff Kirsher 	{},
527f7917c00SJeff Kirsher 	{1, 0, 0,
528f7917c00SJeff Kirsher 	 F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
529f7917c00SJeff Kirsher 	 F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
530f7917c00SJeff Kirsher 	 { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
531f7917c00SJeff Kirsher 	 &mi1_mdio_ext_ops, "Chelsio T310" },
532f7917c00SJeff Kirsher 	{1, 0, 0,
533f7917c00SJeff Kirsher 	 F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
534f7917c00SJeff Kirsher 	 F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL,
535f7917c00SJeff Kirsher 	 { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
536f7917c00SJeff Kirsher 	 &mi1_mdio_ext_ops, "Chelsio N320E-G2" },
537f7917c00SJeff Kirsher };
538f7917c00SJeff Kirsher 
539f7917c00SJeff Kirsher /*
540f7917c00SJeff Kirsher  * Return the adapter_info structure with a given index.  Out-of-range indices
541f7917c00SJeff Kirsher  * return NULL.
542f7917c00SJeff Kirsher  */
t3_get_adapter_info(unsigned int id)543f7917c00SJeff Kirsher const struct adapter_info *t3_get_adapter_info(unsigned int id)
544f7917c00SJeff Kirsher {
545f7917c00SJeff Kirsher 	return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL;
546f7917c00SJeff Kirsher }
547f7917c00SJeff Kirsher 
548f7917c00SJeff Kirsher struct port_type_info {
549f7917c00SJeff Kirsher 	int (*phy_prep)(struct cphy *phy, struct adapter *adapter,
550f7917c00SJeff Kirsher 			int phy_addr, const struct mdio_ops *ops);
551f7917c00SJeff Kirsher };
552f7917c00SJeff Kirsher 
553f7917c00SJeff Kirsher static const struct port_type_info port_types[] = {
554f7917c00SJeff Kirsher 	{ NULL },
555f7917c00SJeff Kirsher 	{ t3_ael1002_phy_prep },
556f7917c00SJeff Kirsher 	{ t3_vsc8211_phy_prep },
557f7917c00SJeff Kirsher 	{ NULL},
558f7917c00SJeff Kirsher 	{ t3_xaui_direct_phy_prep },
559f7917c00SJeff Kirsher 	{ t3_ael2005_phy_prep },
560f7917c00SJeff Kirsher 	{ t3_qt2045_phy_prep },
561f7917c00SJeff Kirsher 	{ t3_ael1006_phy_prep },
562f7917c00SJeff Kirsher 	{ NULL },
563f7917c00SJeff Kirsher 	{ t3_aq100x_phy_prep },
564f7917c00SJeff Kirsher 	{ t3_ael2020_phy_prep },
565f7917c00SJeff Kirsher };
566f7917c00SJeff Kirsher 
567f7917c00SJeff Kirsher #define VPD_ENTRY(name, len) \
568f7917c00SJeff Kirsher 	u8 name##_kword[2]; u8 name##_len; u8 name##_data[len]
569f7917c00SJeff Kirsher 
570f7917c00SJeff Kirsher /*
571f7917c00SJeff Kirsher  * Partial EEPROM Vital Product Data structure.  Includes only the ID and
572f7917c00SJeff Kirsher  * VPD-R sections.
573f7917c00SJeff Kirsher  */
574f7917c00SJeff Kirsher struct t3_vpd {
575f7917c00SJeff Kirsher 	u8 id_tag;
576f7917c00SJeff Kirsher 	u8 id_len[2];
577f7917c00SJeff Kirsher 	u8 id_data[16];
578f7917c00SJeff Kirsher 	u8 vpdr_tag;
579f7917c00SJeff Kirsher 	u8 vpdr_len[2];
580f7917c00SJeff Kirsher 	VPD_ENTRY(pn, 16);	/* part number */
581f7917c00SJeff Kirsher 	VPD_ENTRY(ec, 16);	/* EC level */
582f7917c00SJeff Kirsher 	VPD_ENTRY(sn, SERNUM_LEN); /* serial number */
583f7917c00SJeff Kirsher 	VPD_ENTRY(na, 12);	/* MAC address base */
584f7917c00SJeff Kirsher 	VPD_ENTRY(cclk, 6);	/* core clock */
585f7917c00SJeff Kirsher 	VPD_ENTRY(mclk, 6);	/* mem clock */
586f7917c00SJeff Kirsher 	VPD_ENTRY(uclk, 6);	/* uP clk */
587f7917c00SJeff Kirsher 	VPD_ENTRY(mdc, 6);	/* MDIO clk */
588f7917c00SJeff Kirsher 	VPD_ENTRY(mt, 2);	/* mem timing */
589f7917c00SJeff Kirsher 	VPD_ENTRY(xaui0cfg, 6);	/* XAUI0 config */
590f7917c00SJeff Kirsher 	VPD_ENTRY(xaui1cfg, 6);	/* XAUI1 config */
591f7917c00SJeff Kirsher 	VPD_ENTRY(port0, 2);	/* PHY0 complex */
592f7917c00SJeff Kirsher 	VPD_ENTRY(port1, 2);	/* PHY1 complex */
593f7917c00SJeff Kirsher 	VPD_ENTRY(port2, 2);	/* PHY2 complex */
594f7917c00SJeff Kirsher 	VPD_ENTRY(port3, 2);	/* PHY3 complex */
595f7917c00SJeff Kirsher 	VPD_ENTRY(rv, 1);	/* csum */
596f7917c00SJeff Kirsher 	u32 pad;		/* for multiple-of-4 sizing and alignment */
597f7917c00SJeff Kirsher };
598f7917c00SJeff Kirsher 
599f7917c00SJeff Kirsher #define EEPROM_STAT_ADDR  0x4000
600f7917c00SJeff Kirsher #define VPD_BASE          0xc00
601f7917c00SJeff Kirsher 
602f7917c00SJeff Kirsher /**
603f7917c00SJeff Kirsher  *	t3_seeprom_wp - enable/disable EEPROM write protection
604f7917c00SJeff Kirsher  *	@adapter: the adapter
605f7917c00SJeff Kirsher  *	@enable: 1 to enable write protection, 0 to disable it
606f7917c00SJeff Kirsher  *
607f7917c00SJeff Kirsher  *	Enables or disables write protection on the serial EEPROM.
608f7917c00SJeff Kirsher  */
t3_seeprom_wp(struct adapter * adapter,int enable)609f7917c00SJeff Kirsher int t3_seeprom_wp(struct adapter *adapter, int enable)
610f7917c00SJeff Kirsher {
61143f3b61eSHeiner Kallweit 	u32 data = enable ? 0xc : 0;
61243f3b61eSHeiner Kallweit 	int ret;
61343f3b61eSHeiner Kallweit 
61443f3b61eSHeiner Kallweit 	/* EEPROM_STAT_ADDR is outside VPD area, use pci_write_vpd_any() */
61543f3b61eSHeiner Kallweit 	ret = pci_write_vpd_any(adapter->pdev, EEPROM_STAT_ADDR, sizeof(u32),
61643f3b61eSHeiner Kallweit 				&data);
61743f3b61eSHeiner Kallweit 
61843f3b61eSHeiner Kallweit 	return ret < 0 ? ret : 0;
619f7917c00SJeff Kirsher }
620f7917c00SJeff Kirsher 
vpdstrtouint(char * s,u8 len,unsigned int base,unsigned int * val)621c33b3b9fSGustavo A. R. Silva static int vpdstrtouint(char *s, u8 len, unsigned int base, unsigned int *val)
6221003e19cSSteve Wise {
623c33b3b9fSGustavo A. R. Silva 	char tok[256];
6241003e19cSSteve Wise 
6251003e19cSSteve Wise 	memcpy(tok, s, len);
6261003e19cSSteve Wise 	tok[len] = 0;
6271003e19cSSteve Wise 	return kstrtouint(strim(tok), base, val);
6281003e19cSSteve Wise }
6291003e19cSSteve Wise 
vpdstrtou16(char * s,u8 len,unsigned int base,u16 * val)630c33b3b9fSGustavo A. R. Silva static int vpdstrtou16(char *s, u8 len, unsigned int base, u16 *val)
6311003e19cSSteve Wise {
632c33b3b9fSGustavo A. R. Silva 	char tok[256];
6331003e19cSSteve Wise 
6341003e19cSSteve Wise 	memcpy(tok, s, len);
6351003e19cSSteve Wise 	tok[len] = 0;
6361003e19cSSteve Wise 	return kstrtou16(strim(tok), base, val);
6371003e19cSSteve Wise }
6381003e19cSSteve Wise 
639f7917c00SJeff Kirsher /**
640f7917c00SJeff Kirsher  *	get_vpd_params - read VPD parameters from VPD EEPROM
641f7917c00SJeff Kirsher  *	@adapter: adapter to read
642f7917c00SJeff Kirsher  *	@p: where to store the parameters
643f7917c00SJeff Kirsher  *
644f7917c00SJeff Kirsher  *	Reads card parameters stored in VPD EEPROM.
645f7917c00SJeff Kirsher  */
get_vpd_params(struct adapter * adapter,struct vpd_params * p)646f7917c00SJeff Kirsher static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
647f7917c00SJeff Kirsher {
648f7917c00SJeff Kirsher 	struct t3_vpd vpd;
64948225f18SHeiner Kallweit 	u8 base_val = 0;
65048225f18SHeiner Kallweit 	int addr, ret;
651f7917c00SJeff Kirsher 
652f7917c00SJeff Kirsher 	/*
653f7917c00SJeff Kirsher 	 * Card information is normally at VPD_BASE but some early cards had
654f7917c00SJeff Kirsher 	 * it at 0.
655f7917c00SJeff Kirsher 	 */
65648225f18SHeiner Kallweit 	ret = pci_read_vpd(adapter->pdev, VPD_BASE, 1, &base_val);
65748225f18SHeiner Kallweit 	if (ret < 0)
658f7917c00SJeff Kirsher 		return ret;
65948225f18SHeiner Kallweit 	addr = base_val == PCI_VPD_LRDT_ID_STRING ? VPD_BASE : 0;
660f7917c00SJeff Kirsher 
66148225f18SHeiner Kallweit 	ret = pci_read_vpd(adapter->pdev, addr, sizeof(vpd), &vpd);
66248225f18SHeiner Kallweit 	if (ret < 0)
663f7917c00SJeff Kirsher 		return ret;
664f7917c00SJeff Kirsher 
6651003e19cSSteve Wise 	ret = vpdstrtouint(vpd.cclk_data, vpd.cclk_len, 10, &p->cclk);
666e72c932dSLABBE Corentin 	if (ret)
667e72c932dSLABBE Corentin 		return ret;
6681003e19cSSteve Wise 	ret = vpdstrtouint(vpd.mclk_data, vpd.mclk_len, 10, &p->mclk);
669e72c932dSLABBE Corentin 	if (ret)
670e72c932dSLABBE Corentin 		return ret;
6711003e19cSSteve Wise 	ret = vpdstrtouint(vpd.uclk_data, vpd.uclk_len, 10, &p->uclk);
672e72c932dSLABBE Corentin 	if (ret)
673e72c932dSLABBE Corentin 		return ret;
6741003e19cSSteve Wise 	ret = vpdstrtouint(vpd.mdc_data, vpd.mdc_len, 10, &p->mdc);
675e72c932dSLABBE Corentin 	if (ret)
676e72c932dSLABBE Corentin 		return ret;
6771003e19cSSteve Wise 	ret = vpdstrtouint(vpd.mt_data, vpd.mt_len, 10, &p->mem_timing);
678e72c932dSLABBE Corentin 	if (ret)
679e72c932dSLABBE Corentin 		return ret;
680f7917c00SJeff Kirsher 	memcpy(p->sn, vpd.sn_data, SERNUM_LEN);
681f7917c00SJeff Kirsher 
682f7917c00SJeff Kirsher 	/* Old eeproms didn't have port information */
683f7917c00SJeff Kirsher 	if (adapter->params.rev == 0 && !vpd.port0_data[0]) {
684f7917c00SJeff Kirsher 		p->port_type[0] = uses_xaui(adapter) ? 1 : 2;
685f7917c00SJeff Kirsher 		p->port_type[1] = uses_xaui(adapter) ? 6 : 2;
686f7917c00SJeff Kirsher 	} else {
687f7917c00SJeff Kirsher 		p->port_type[0] = hex_to_bin(vpd.port0_data[0]);
688f7917c00SJeff Kirsher 		p->port_type[1] = hex_to_bin(vpd.port1_data[0]);
6891003e19cSSteve Wise 		ret = vpdstrtou16(vpd.xaui0cfg_data, vpd.xaui0cfg_len, 16,
6901003e19cSSteve Wise 				  &p->xauicfg[0]);
691e72c932dSLABBE Corentin 		if (ret)
692e72c932dSLABBE Corentin 			return ret;
6931003e19cSSteve Wise 		ret = vpdstrtou16(vpd.xaui1cfg_data, vpd.xaui1cfg_len, 16,
6941003e19cSSteve Wise 				  &p->xauicfg[1]);
695e72c932dSLABBE Corentin 		if (ret)
696e72c932dSLABBE Corentin 			return ret;
697f7917c00SJeff Kirsher 	}
698f7917c00SJeff Kirsher 
6997aee42c6SAndy Shevchenko 	ret = hex2bin(p->eth_base, vpd.na_data, 6);
7007aee42c6SAndy Shevchenko 	if (ret < 0)
7017aee42c6SAndy Shevchenko 		return -EINVAL;
702f7917c00SJeff Kirsher 	return 0;
703f7917c00SJeff Kirsher }
704f7917c00SJeff Kirsher 
705f7917c00SJeff Kirsher /* serial flash and firmware constants */
706f7917c00SJeff Kirsher enum {
707f7917c00SJeff Kirsher 	SF_ATTEMPTS = 5,	/* max retries for SF1 operations */
708f7917c00SJeff Kirsher 	SF_SEC_SIZE = 64 * 1024,	/* serial flash sector size */
709f7917c00SJeff Kirsher 	SF_SIZE = SF_SEC_SIZE * 8,	/* serial flash size */
710f7917c00SJeff Kirsher 
711f7917c00SJeff Kirsher 	/* flash command opcodes */
712f7917c00SJeff Kirsher 	SF_PROG_PAGE = 2,	/* program page */
713f7917c00SJeff Kirsher 	SF_WR_DISABLE = 4,	/* disable writes */
714f7917c00SJeff Kirsher 	SF_RD_STATUS = 5,	/* read status register */
715f7917c00SJeff Kirsher 	SF_WR_ENABLE = 6,	/* enable writes */
716f7917c00SJeff Kirsher 	SF_RD_DATA_FAST = 0xb,	/* read flash */
717f7917c00SJeff Kirsher 	SF_ERASE_SECTOR = 0xd8,	/* erase sector */
718f7917c00SJeff Kirsher 
719f7917c00SJeff Kirsher 	FW_FLASH_BOOT_ADDR = 0x70000,	/* start address of FW in flash */
720f7917c00SJeff Kirsher 	FW_VERS_ADDR = 0x7fffc,    /* flash address holding FW version */
721f7917c00SJeff Kirsher 	FW_MIN_SIZE = 8            /* at least version and csum */
722f7917c00SJeff Kirsher };
723f7917c00SJeff Kirsher 
724f7917c00SJeff Kirsher /**
725f7917c00SJeff Kirsher  *	sf1_read - read data from the serial flash
726f7917c00SJeff Kirsher  *	@adapter: the adapter
727f7917c00SJeff Kirsher  *	@byte_cnt: number of bytes to read
728f7917c00SJeff Kirsher  *	@cont: whether another operation will be chained
729f7917c00SJeff Kirsher  *	@valp: where to store the read data
730f7917c00SJeff Kirsher  *
731f7917c00SJeff Kirsher  *	Reads up to 4 bytes of data from the serial flash.  The location of
732f7917c00SJeff Kirsher  *	the read needs to be specified prior to calling this by issuing the
733f7917c00SJeff Kirsher  *	appropriate commands to the serial flash.
734f7917c00SJeff Kirsher  */
sf1_read(struct adapter * adapter,unsigned int byte_cnt,int cont,u32 * valp)735f7917c00SJeff Kirsher static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont,
736f7917c00SJeff Kirsher 		    u32 *valp)
737f7917c00SJeff Kirsher {
738f7917c00SJeff Kirsher 	int ret;
739f7917c00SJeff Kirsher 
740f7917c00SJeff Kirsher 	if (!byte_cnt || byte_cnt > 4)
741f7917c00SJeff Kirsher 		return -EINVAL;
742f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SF_OP) & F_BUSY)
743f7917c00SJeff Kirsher 		return -EBUSY;
744f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SF_OP, V_CONT(cont) | V_BYTECNT(byte_cnt - 1));
745f7917c00SJeff Kirsher 	ret = t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10);
746f7917c00SJeff Kirsher 	if (!ret)
747f7917c00SJeff Kirsher 		*valp = t3_read_reg(adapter, A_SF_DATA);
748f7917c00SJeff Kirsher 	return ret;
749f7917c00SJeff Kirsher }
750f7917c00SJeff Kirsher 
751f7917c00SJeff Kirsher /**
752f7917c00SJeff Kirsher  *	sf1_write - write data to the serial flash
753f7917c00SJeff Kirsher  *	@adapter: the adapter
754f7917c00SJeff Kirsher  *	@byte_cnt: number of bytes to write
755f7917c00SJeff Kirsher  *	@cont: whether another operation will be chained
756f7917c00SJeff Kirsher  *	@val: value to write
757f7917c00SJeff Kirsher  *
758f7917c00SJeff Kirsher  *	Writes up to 4 bytes of data to the serial flash.  The location of
759f7917c00SJeff Kirsher  *	the write needs to be specified prior to calling this by issuing the
760f7917c00SJeff Kirsher  *	appropriate commands to the serial flash.
761f7917c00SJeff Kirsher  */
sf1_write(struct adapter * adapter,unsigned int byte_cnt,int cont,u32 val)762f7917c00SJeff Kirsher static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont,
763f7917c00SJeff Kirsher 		     u32 val)
764f7917c00SJeff Kirsher {
765f7917c00SJeff Kirsher 	if (!byte_cnt || byte_cnt > 4)
766f7917c00SJeff Kirsher 		return -EINVAL;
767f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SF_OP) & F_BUSY)
768f7917c00SJeff Kirsher 		return -EBUSY;
769f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SF_DATA, val);
770f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SF_OP,
771f7917c00SJeff Kirsher 		     V_CONT(cont) | V_BYTECNT(byte_cnt - 1) | V_OP(1));
772f7917c00SJeff Kirsher 	return t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10);
773f7917c00SJeff Kirsher }
774f7917c00SJeff Kirsher 
775f7917c00SJeff Kirsher /**
776f7917c00SJeff Kirsher  *	flash_wait_op - wait for a flash operation to complete
777f7917c00SJeff Kirsher  *	@adapter: the adapter
778f7917c00SJeff Kirsher  *	@attempts: max number of polls of the status register
779f7917c00SJeff Kirsher  *	@delay: delay between polls in ms
780f7917c00SJeff Kirsher  *
781f7917c00SJeff Kirsher  *	Wait for a flash operation to complete by polling the status register.
782f7917c00SJeff Kirsher  */
flash_wait_op(struct adapter * adapter,int attempts,int delay)783f7917c00SJeff Kirsher static int flash_wait_op(struct adapter *adapter, int attempts, int delay)
784f7917c00SJeff Kirsher {
785f7917c00SJeff Kirsher 	int ret;
786f7917c00SJeff Kirsher 	u32 status;
787f7917c00SJeff Kirsher 
788f7917c00SJeff Kirsher 	while (1) {
789f7917c00SJeff Kirsher 		if ((ret = sf1_write(adapter, 1, 1, SF_RD_STATUS)) != 0 ||
790f7917c00SJeff Kirsher 		    (ret = sf1_read(adapter, 1, 0, &status)) != 0)
791f7917c00SJeff Kirsher 			return ret;
792f7917c00SJeff Kirsher 		if (!(status & 1))
793f7917c00SJeff Kirsher 			return 0;
794f7917c00SJeff Kirsher 		if (--attempts == 0)
795f7917c00SJeff Kirsher 			return -EAGAIN;
796f7917c00SJeff Kirsher 		if (delay)
797f7917c00SJeff Kirsher 			msleep(delay);
798f7917c00SJeff Kirsher 	}
799f7917c00SJeff Kirsher }
800f7917c00SJeff Kirsher 
801f7917c00SJeff Kirsher /**
802f7917c00SJeff Kirsher  *	t3_read_flash - read words from serial flash
803f7917c00SJeff Kirsher  *	@adapter: the adapter
804f7917c00SJeff Kirsher  *	@addr: the start address for the read
805f7917c00SJeff Kirsher  *	@nwords: how many 32-bit words to read
806f7917c00SJeff Kirsher  *	@data: where to store the read data
807f7917c00SJeff Kirsher  *	@byte_oriented: whether to store data as bytes or as words
808f7917c00SJeff Kirsher  *
809f7917c00SJeff Kirsher  *	Read the specified number of 32-bit words from the serial flash.
810f7917c00SJeff Kirsher  *	If @byte_oriented is set the read data is stored as a byte array
811f7917c00SJeff Kirsher  *	(i.e., big-endian), otherwise as 32-bit words in the platform's
812dbedd44eSJoe Perches  *	natural endianness.
813f7917c00SJeff Kirsher  */
t3_read_flash(struct adapter * adapter,unsigned int addr,unsigned int nwords,u32 * data,int byte_oriented)814f7917c00SJeff Kirsher static int t3_read_flash(struct adapter *adapter, unsigned int addr,
815f7917c00SJeff Kirsher 			 unsigned int nwords, u32 *data, int byte_oriented)
816f7917c00SJeff Kirsher {
817f7917c00SJeff Kirsher 	int ret;
818f7917c00SJeff Kirsher 
819f7917c00SJeff Kirsher 	if (addr + nwords * sizeof(u32) > SF_SIZE || (addr & 3))
820f7917c00SJeff Kirsher 		return -EINVAL;
821f7917c00SJeff Kirsher 
822f7917c00SJeff Kirsher 	addr = swab32(addr) | SF_RD_DATA_FAST;
823f7917c00SJeff Kirsher 
824f7917c00SJeff Kirsher 	if ((ret = sf1_write(adapter, 4, 1, addr)) != 0 ||
825f7917c00SJeff Kirsher 	    (ret = sf1_read(adapter, 1, 1, data)) != 0)
826f7917c00SJeff Kirsher 		return ret;
827f7917c00SJeff Kirsher 
828f7917c00SJeff Kirsher 	for (; nwords; nwords--, data++) {
829f7917c00SJeff Kirsher 		ret = sf1_read(adapter, 4, nwords > 1, data);
830f7917c00SJeff Kirsher 		if (ret)
831f7917c00SJeff Kirsher 			return ret;
832f7917c00SJeff Kirsher 		if (byte_oriented)
833f7917c00SJeff Kirsher 			*data = htonl(*data);
834f7917c00SJeff Kirsher 	}
835f7917c00SJeff Kirsher 	return 0;
836f7917c00SJeff Kirsher }
837f7917c00SJeff Kirsher 
838f7917c00SJeff Kirsher /**
839f7917c00SJeff Kirsher  *	t3_write_flash - write up to a page of data to the serial flash
840f7917c00SJeff Kirsher  *	@adapter: the adapter
841f7917c00SJeff Kirsher  *	@addr: the start address to write
842f7917c00SJeff Kirsher  *	@n: length of data to write
843f7917c00SJeff Kirsher  *	@data: the data to write
844f7917c00SJeff Kirsher  *
845f7917c00SJeff Kirsher  *	Writes up to a page of data (256 bytes) to the serial flash starting
846f7917c00SJeff Kirsher  *	at the given address.
847f7917c00SJeff Kirsher  */
t3_write_flash(struct adapter * adapter,unsigned int addr,unsigned int n,const u8 * data)848f7917c00SJeff Kirsher static int t3_write_flash(struct adapter *adapter, unsigned int addr,
849f7917c00SJeff Kirsher 			  unsigned int n, const u8 *data)
850f7917c00SJeff Kirsher {
851f7917c00SJeff Kirsher 	int ret;
852f7917c00SJeff Kirsher 	u32 buf[64];
853f7917c00SJeff Kirsher 	unsigned int i, c, left, val, offset = addr & 0xff;
854f7917c00SJeff Kirsher 
855f7917c00SJeff Kirsher 	if (addr + n > SF_SIZE || offset + n > 256)
856f7917c00SJeff Kirsher 		return -EINVAL;
857f7917c00SJeff Kirsher 
858f7917c00SJeff Kirsher 	val = swab32(addr) | SF_PROG_PAGE;
859f7917c00SJeff Kirsher 
860f7917c00SJeff Kirsher 	if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 ||
861f7917c00SJeff Kirsher 	    (ret = sf1_write(adapter, 4, 1, val)) != 0)
862f7917c00SJeff Kirsher 		return ret;
863f7917c00SJeff Kirsher 
864f7917c00SJeff Kirsher 	for (left = n; left; left -= c) {
865f7917c00SJeff Kirsher 		c = min(left, 4U);
866f7917c00SJeff Kirsher 		for (val = 0, i = 0; i < c; ++i)
867f7917c00SJeff Kirsher 			val = (val << 8) + *data++;
868f7917c00SJeff Kirsher 
869f7917c00SJeff Kirsher 		ret = sf1_write(adapter, c, c != left, val);
870f7917c00SJeff Kirsher 		if (ret)
871f7917c00SJeff Kirsher 			return ret;
872f7917c00SJeff Kirsher 	}
873f7917c00SJeff Kirsher 	if ((ret = flash_wait_op(adapter, 5, 1)) != 0)
874f7917c00SJeff Kirsher 		return ret;
875f7917c00SJeff Kirsher 
876f7917c00SJeff Kirsher 	/* Read the page to verify the write succeeded */
877f7917c00SJeff Kirsher 	ret = t3_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, 1);
878f7917c00SJeff Kirsher 	if (ret)
879f7917c00SJeff Kirsher 		return ret;
880f7917c00SJeff Kirsher 
881f7917c00SJeff Kirsher 	if (memcmp(data - n, (u8 *) buf + offset, n))
882f7917c00SJeff Kirsher 		return -EIO;
883f7917c00SJeff Kirsher 	return 0;
884f7917c00SJeff Kirsher }
885f7917c00SJeff Kirsher 
886f7917c00SJeff Kirsher /**
887f7917c00SJeff Kirsher  *	t3_get_tp_version - read the tp sram version
888f7917c00SJeff Kirsher  *	@adapter: the adapter
889f7917c00SJeff Kirsher  *	@vers: where to place the version
890f7917c00SJeff Kirsher  *
891f7917c00SJeff Kirsher  *	Reads the protocol sram version from sram.
892f7917c00SJeff Kirsher  */
t3_get_tp_version(struct adapter * adapter,u32 * vers)893f7917c00SJeff Kirsher int t3_get_tp_version(struct adapter *adapter, u32 *vers)
894f7917c00SJeff Kirsher {
895f7917c00SJeff Kirsher 	int ret;
896f7917c00SJeff Kirsher 
897f7917c00SJeff Kirsher 	/* Get version loaded in SRAM */
898f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
899f7917c00SJeff Kirsher 	ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
900f7917c00SJeff Kirsher 			      1, 1, 5, 1);
901f7917c00SJeff Kirsher 	if (ret)
902f7917c00SJeff Kirsher 		return ret;
903f7917c00SJeff Kirsher 
904f7917c00SJeff Kirsher 	*vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
905f7917c00SJeff Kirsher 
906f7917c00SJeff Kirsher 	return 0;
907f7917c00SJeff Kirsher }
908f7917c00SJeff Kirsher 
909f7917c00SJeff Kirsher /**
910f7917c00SJeff Kirsher  *	t3_check_tpsram_version - read the tp sram version
911f7917c00SJeff Kirsher  *	@adapter: the adapter
912f7917c00SJeff Kirsher  *
913f7917c00SJeff Kirsher  *	Reads the protocol sram version from flash.
914f7917c00SJeff Kirsher  */
t3_check_tpsram_version(struct adapter * adapter)915f7917c00SJeff Kirsher int t3_check_tpsram_version(struct adapter *adapter)
916f7917c00SJeff Kirsher {
917f7917c00SJeff Kirsher 	int ret;
918f7917c00SJeff Kirsher 	u32 vers;
919f7917c00SJeff Kirsher 	unsigned int major, minor;
920f7917c00SJeff Kirsher 
921f7917c00SJeff Kirsher 	if (adapter->params.rev == T3_REV_A)
922f7917c00SJeff Kirsher 		return 0;
923f7917c00SJeff Kirsher 
924f7917c00SJeff Kirsher 
925f7917c00SJeff Kirsher 	ret = t3_get_tp_version(adapter, &vers);
926f7917c00SJeff Kirsher 	if (ret)
927f7917c00SJeff Kirsher 		return ret;
928f7917c00SJeff Kirsher 
929f7917c00SJeff Kirsher 	major = G_TP_VERSION_MAJOR(vers);
930f7917c00SJeff Kirsher 	minor = G_TP_VERSION_MINOR(vers);
931f7917c00SJeff Kirsher 
932f7917c00SJeff Kirsher 	if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
933f7917c00SJeff Kirsher 		return 0;
934f7917c00SJeff Kirsher 	else {
935f7917c00SJeff Kirsher 		CH_ERR(adapter, "found wrong TP version (%u.%u), "
936f7917c00SJeff Kirsher 		       "driver compiled for version %d.%d\n", major, minor,
937f7917c00SJeff Kirsher 		       TP_VERSION_MAJOR, TP_VERSION_MINOR);
938f7917c00SJeff Kirsher 	}
939f7917c00SJeff Kirsher 	return -EINVAL;
940f7917c00SJeff Kirsher }
941f7917c00SJeff Kirsher 
942f7917c00SJeff Kirsher /**
943f7917c00SJeff Kirsher  *	t3_check_tpsram - check if provided protocol SRAM
944f7917c00SJeff Kirsher  *			  is compatible with this driver
945f7917c00SJeff Kirsher  *	@adapter: the adapter
946f7917c00SJeff Kirsher  *	@tp_sram: the firmware image to write
947f7917c00SJeff Kirsher  *	@size: image size
948f7917c00SJeff Kirsher  *
949f7917c00SJeff Kirsher  *	Checks if an adapter's tp sram is compatible with the driver.
950f7917c00SJeff Kirsher  *	Returns 0 if the versions are compatible, a negative error otherwise.
951f7917c00SJeff Kirsher  */
t3_check_tpsram(struct adapter * adapter,const u8 * tp_sram,unsigned int size)952f7917c00SJeff Kirsher int t3_check_tpsram(struct adapter *adapter, const u8 *tp_sram,
953f7917c00SJeff Kirsher 		    unsigned int size)
954f7917c00SJeff Kirsher {
955f7917c00SJeff Kirsher 	u32 csum;
956f7917c00SJeff Kirsher 	unsigned int i;
957f7917c00SJeff Kirsher 	const __be32 *p = (const __be32 *)tp_sram;
958f7917c00SJeff Kirsher 
959f7917c00SJeff Kirsher 	/* Verify checksum */
960f7917c00SJeff Kirsher 	for (csum = 0, i = 0; i < size / sizeof(csum); i++)
961f7917c00SJeff Kirsher 		csum += ntohl(p[i]);
962f7917c00SJeff Kirsher 	if (csum != 0xffffffff) {
963f7917c00SJeff Kirsher 		CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
964f7917c00SJeff Kirsher 		       csum);
965f7917c00SJeff Kirsher 		return -EINVAL;
966f7917c00SJeff Kirsher 	}
967f7917c00SJeff Kirsher 
968f7917c00SJeff Kirsher 	return 0;
969f7917c00SJeff Kirsher }
970f7917c00SJeff Kirsher 
971f7917c00SJeff Kirsher enum fw_version_type {
972f7917c00SJeff Kirsher 	FW_VERSION_N3,
973f7917c00SJeff Kirsher 	FW_VERSION_T3
974f7917c00SJeff Kirsher };
975f7917c00SJeff Kirsher 
976f7917c00SJeff Kirsher /**
977f7917c00SJeff Kirsher  *	t3_get_fw_version - read the firmware version
978f7917c00SJeff Kirsher  *	@adapter: the adapter
979f7917c00SJeff Kirsher  *	@vers: where to place the version
980f7917c00SJeff Kirsher  *
981f7917c00SJeff Kirsher  *	Reads the FW version from flash.
982f7917c00SJeff Kirsher  */
t3_get_fw_version(struct adapter * adapter,u32 * vers)983f7917c00SJeff Kirsher int t3_get_fw_version(struct adapter *adapter, u32 *vers)
984f7917c00SJeff Kirsher {
985f7917c00SJeff Kirsher 	return t3_read_flash(adapter, FW_VERS_ADDR, 1, vers, 0);
986f7917c00SJeff Kirsher }
987f7917c00SJeff Kirsher 
988f7917c00SJeff Kirsher /**
989f7917c00SJeff Kirsher  *	t3_check_fw_version - check if the FW is compatible with this driver
990f7917c00SJeff Kirsher  *	@adapter: the adapter
991f7917c00SJeff Kirsher  *
992f7917c00SJeff Kirsher  *	Checks if an adapter's FW is compatible with the driver.  Returns 0
993f7917c00SJeff Kirsher  *	if the versions are compatible, a negative error otherwise.
994f7917c00SJeff Kirsher  */
t3_check_fw_version(struct adapter * adapter)995f7917c00SJeff Kirsher int t3_check_fw_version(struct adapter *adapter)
996f7917c00SJeff Kirsher {
997f7917c00SJeff Kirsher 	int ret;
998f7917c00SJeff Kirsher 	u32 vers;
999f7917c00SJeff Kirsher 	unsigned int type, major, minor;
1000f7917c00SJeff Kirsher 
1001f7917c00SJeff Kirsher 	ret = t3_get_fw_version(adapter, &vers);
1002f7917c00SJeff Kirsher 	if (ret)
1003f7917c00SJeff Kirsher 		return ret;
1004f7917c00SJeff Kirsher 
1005f7917c00SJeff Kirsher 	type = G_FW_VERSION_TYPE(vers);
1006f7917c00SJeff Kirsher 	major = G_FW_VERSION_MAJOR(vers);
1007f7917c00SJeff Kirsher 	minor = G_FW_VERSION_MINOR(vers);
1008f7917c00SJeff Kirsher 
1009f7917c00SJeff Kirsher 	if (type == FW_VERSION_T3 && major == FW_VERSION_MAJOR &&
1010f7917c00SJeff Kirsher 	    minor == FW_VERSION_MINOR)
1011f7917c00SJeff Kirsher 		return 0;
1012f7917c00SJeff Kirsher 	else if (major != FW_VERSION_MAJOR || minor < FW_VERSION_MINOR)
1013f7917c00SJeff Kirsher 		CH_WARN(adapter, "found old FW minor version(%u.%u), "
1014f7917c00SJeff Kirsher 		        "driver compiled for version %u.%u\n", major, minor,
1015f7917c00SJeff Kirsher 			FW_VERSION_MAJOR, FW_VERSION_MINOR);
1016f7917c00SJeff Kirsher 	else {
1017f7917c00SJeff Kirsher 		CH_WARN(adapter, "found newer FW version(%u.%u), "
1018f7917c00SJeff Kirsher 		        "driver compiled for version %u.%u\n", major, minor,
1019f7917c00SJeff Kirsher 			FW_VERSION_MAJOR, FW_VERSION_MINOR);
1020f7917c00SJeff Kirsher 		return 0;
1021f7917c00SJeff Kirsher 	}
1022f7917c00SJeff Kirsher 	return -EINVAL;
1023f7917c00SJeff Kirsher }
1024f7917c00SJeff Kirsher 
1025f7917c00SJeff Kirsher /**
1026f7917c00SJeff Kirsher  *	t3_flash_erase_sectors - erase a range of flash sectors
1027f7917c00SJeff Kirsher  *	@adapter: the adapter
1028f7917c00SJeff Kirsher  *	@start: the first sector to erase
1029f7917c00SJeff Kirsher  *	@end: the last sector to erase
1030f7917c00SJeff Kirsher  *
1031f7917c00SJeff Kirsher  *	Erases the sectors in the given range.
1032f7917c00SJeff Kirsher  */
t3_flash_erase_sectors(struct adapter * adapter,int start,int end)1033f7917c00SJeff Kirsher static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end)
1034f7917c00SJeff Kirsher {
1035f7917c00SJeff Kirsher 	while (start <= end) {
1036f7917c00SJeff Kirsher 		int ret;
1037f7917c00SJeff Kirsher 
1038f7917c00SJeff Kirsher 		if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 ||
1039f7917c00SJeff Kirsher 		    (ret = sf1_write(adapter, 4, 0,
1040f7917c00SJeff Kirsher 				     SF_ERASE_SECTOR | (start << 8))) != 0 ||
1041f7917c00SJeff Kirsher 		    (ret = flash_wait_op(adapter, 5, 500)) != 0)
1042f7917c00SJeff Kirsher 			return ret;
1043f7917c00SJeff Kirsher 		start++;
1044f7917c00SJeff Kirsher 	}
1045f7917c00SJeff Kirsher 	return 0;
1046f7917c00SJeff Kirsher }
1047f7917c00SJeff Kirsher 
104849ce9c2cSBen Hutchings /**
1049f7917c00SJeff Kirsher  *	t3_load_fw - download firmware
1050f7917c00SJeff Kirsher  *	@adapter: the adapter
1051f7917c00SJeff Kirsher  *	@fw_data: the firmware image to write
1052f7917c00SJeff Kirsher  *	@size: image size
1053f7917c00SJeff Kirsher  *
1054f7917c00SJeff Kirsher  *	Write the supplied firmware image to the card's serial flash.
1055f7917c00SJeff Kirsher  *	The FW image has the following sections: @size - 8 bytes of code and
1056f7917c00SJeff Kirsher  *	data, followed by 4 bytes of FW version, followed by the 32-bit
1057f7917c00SJeff Kirsher  *	1's complement checksum of the whole image.
1058f7917c00SJeff Kirsher  */
t3_load_fw(struct adapter * adapter,const u8 * fw_data,unsigned int size)1059f7917c00SJeff Kirsher int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size)
1060f7917c00SJeff Kirsher {
1061f7917c00SJeff Kirsher 	u32 csum;
1062f7917c00SJeff Kirsher 	unsigned int i;
1063f7917c00SJeff Kirsher 	const __be32 *p = (const __be32 *)fw_data;
1064f7917c00SJeff Kirsher 	int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
1065f7917c00SJeff Kirsher 
1066f7917c00SJeff Kirsher 	if ((size & 3) || size < FW_MIN_SIZE)
1067f7917c00SJeff Kirsher 		return -EINVAL;
1068f7917c00SJeff Kirsher 	if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR)
1069f7917c00SJeff Kirsher 		return -EFBIG;
1070f7917c00SJeff Kirsher 
1071f7917c00SJeff Kirsher 	for (csum = 0, i = 0; i < size / sizeof(csum); i++)
1072f7917c00SJeff Kirsher 		csum += ntohl(p[i]);
1073f7917c00SJeff Kirsher 	if (csum != 0xffffffff) {
1074f7917c00SJeff Kirsher 		CH_ERR(adapter, "corrupted firmware image, checksum %u\n",
1075f7917c00SJeff Kirsher 		       csum);
1076f7917c00SJeff Kirsher 		return -EINVAL;
1077f7917c00SJeff Kirsher 	}
1078f7917c00SJeff Kirsher 
1079f7917c00SJeff Kirsher 	ret = t3_flash_erase_sectors(adapter, fw_sector, fw_sector);
1080f7917c00SJeff Kirsher 	if (ret)
1081f7917c00SJeff Kirsher 		goto out;
1082f7917c00SJeff Kirsher 
1083f7917c00SJeff Kirsher 	size -= 8;		/* trim off version and checksum */
1084f7917c00SJeff Kirsher 	for (addr = FW_FLASH_BOOT_ADDR; size;) {
1085f7917c00SJeff Kirsher 		unsigned int chunk_size = min(size, 256U);
1086f7917c00SJeff Kirsher 
1087f7917c00SJeff Kirsher 		ret = t3_write_flash(adapter, addr, chunk_size, fw_data);
1088f7917c00SJeff Kirsher 		if (ret)
1089f7917c00SJeff Kirsher 			goto out;
1090f7917c00SJeff Kirsher 
1091f7917c00SJeff Kirsher 		addr += chunk_size;
1092f7917c00SJeff Kirsher 		fw_data += chunk_size;
1093f7917c00SJeff Kirsher 		size -= chunk_size;
1094f7917c00SJeff Kirsher 	}
1095f7917c00SJeff Kirsher 
1096f7917c00SJeff Kirsher 	ret = t3_write_flash(adapter, FW_VERS_ADDR, 4, fw_data);
1097f7917c00SJeff Kirsher out:
1098f7917c00SJeff Kirsher 	if (ret)
1099f7917c00SJeff Kirsher 		CH_ERR(adapter, "firmware download failed, error %d\n", ret);
1100f7917c00SJeff Kirsher 	return ret;
1101f7917c00SJeff Kirsher }
1102f7917c00SJeff Kirsher 
1103f7917c00SJeff Kirsher #define CIM_CTL_BASE 0x2000
1104f7917c00SJeff Kirsher 
1105f7917c00SJeff Kirsher /**
1106f7917c00SJeff Kirsher  *      t3_cim_ctl_blk_read - read a block from CIM control region
1107f7917c00SJeff Kirsher  *
1108f7917c00SJeff Kirsher  *      @adap: the adapter
1109f7917c00SJeff Kirsher  *      @addr: the start address within the CIM control region
1110f7917c00SJeff Kirsher  *      @n: number of words to read
1111f7917c00SJeff Kirsher  *      @valp: where to store the result
1112f7917c00SJeff Kirsher  *
1113f7917c00SJeff Kirsher  *      Reads a block of 4-byte words from the CIM control region.
1114f7917c00SJeff Kirsher  */
t3_cim_ctl_blk_read(struct adapter * adap,unsigned int addr,unsigned int n,unsigned int * valp)1115f7917c00SJeff Kirsher int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr,
1116f7917c00SJeff Kirsher 			unsigned int n, unsigned int *valp)
1117f7917c00SJeff Kirsher {
1118f7917c00SJeff Kirsher 	int ret = 0;
1119f7917c00SJeff Kirsher 
1120f7917c00SJeff Kirsher 	if (t3_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY)
1121f7917c00SJeff Kirsher 		return -EBUSY;
1122f7917c00SJeff Kirsher 
1123f7917c00SJeff Kirsher 	for ( ; !ret && n--; addr += 4) {
1124f7917c00SJeff Kirsher 		t3_write_reg(adap, A_CIM_HOST_ACC_CTRL, CIM_CTL_BASE + addr);
1125f7917c00SJeff Kirsher 		ret = t3_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY,
1126f7917c00SJeff Kirsher 				      0, 5, 2);
1127f7917c00SJeff Kirsher 		if (!ret)
1128f7917c00SJeff Kirsher 			*valp++ = t3_read_reg(adap, A_CIM_HOST_ACC_DATA);
1129f7917c00SJeff Kirsher 	}
1130f7917c00SJeff Kirsher 	return ret;
1131f7917c00SJeff Kirsher }
1132f7917c00SJeff Kirsher 
t3_gate_rx_traffic(struct cmac * mac,u32 * rx_cfg,u32 * rx_hash_high,u32 * rx_hash_low)1133f7917c00SJeff Kirsher static void t3_gate_rx_traffic(struct cmac *mac, u32 *rx_cfg,
1134f7917c00SJeff Kirsher 			       u32 *rx_hash_high, u32 *rx_hash_low)
1135f7917c00SJeff Kirsher {
1136f7917c00SJeff Kirsher 	/* stop Rx unicast traffic */
1137f7917c00SJeff Kirsher 	t3_mac_disable_exact_filters(mac);
1138f7917c00SJeff Kirsher 
1139f7917c00SJeff Kirsher 	/* stop broadcast, multicast, promiscuous mode traffic */
1140f7917c00SJeff Kirsher 	*rx_cfg = t3_read_reg(mac->adapter, A_XGM_RX_CFG);
1141f7917c00SJeff Kirsher 	t3_set_reg_field(mac->adapter, A_XGM_RX_CFG,
1142f7917c00SJeff Kirsher 			 F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES,
1143f7917c00SJeff Kirsher 			 F_DISBCAST);
1144f7917c00SJeff Kirsher 
1145f7917c00SJeff Kirsher 	*rx_hash_high = t3_read_reg(mac->adapter, A_XGM_RX_HASH_HIGH);
1146f7917c00SJeff Kirsher 	t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, 0);
1147f7917c00SJeff Kirsher 
1148f7917c00SJeff Kirsher 	*rx_hash_low = t3_read_reg(mac->adapter, A_XGM_RX_HASH_LOW);
1149f7917c00SJeff Kirsher 	t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, 0);
1150f7917c00SJeff Kirsher 
1151f7917c00SJeff Kirsher 	/* Leave time to drain max RX fifo */
1152f7917c00SJeff Kirsher 	msleep(1);
1153f7917c00SJeff Kirsher }
1154f7917c00SJeff Kirsher 
t3_open_rx_traffic(struct cmac * mac,u32 rx_cfg,u32 rx_hash_high,u32 rx_hash_low)1155f7917c00SJeff Kirsher static void t3_open_rx_traffic(struct cmac *mac, u32 rx_cfg,
1156f7917c00SJeff Kirsher 			       u32 rx_hash_high, u32 rx_hash_low)
1157f7917c00SJeff Kirsher {
1158f7917c00SJeff Kirsher 	t3_mac_enable_exact_filters(mac);
1159f7917c00SJeff Kirsher 	t3_set_reg_field(mac->adapter, A_XGM_RX_CFG,
1160f7917c00SJeff Kirsher 			 F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES,
1161f7917c00SJeff Kirsher 			 rx_cfg);
1162f7917c00SJeff Kirsher 	t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, rx_hash_high);
1163f7917c00SJeff Kirsher 	t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, rx_hash_low);
1164f7917c00SJeff Kirsher }
1165f7917c00SJeff Kirsher 
1166f7917c00SJeff Kirsher /**
1167f7917c00SJeff Kirsher  *	t3_link_changed - handle interface link changes
1168f7917c00SJeff Kirsher  *	@adapter: the adapter
1169f7917c00SJeff Kirsher  *	@port_id: the port index that changed link state
1170f7917c00SJeff Kirsher  *
1171f7917c00SJeff Kirsher  *	Called when a port's link settings change to propagate the new values
1172f7917c00SJeff Kirsher  *	to the associated PHY and MAC.  After performing the common tasks it
1173f7917c00SJeff Kirsher  *	invokes an OS-specific handler.
1174f7917c00SJeff Kirsher  */
t3_link_changed(struct adapter * adapter,int port_id)1175f7917c00SJeff Kirsher void t3_link_changed(struct adapter *adapter, int port_id)
1176f7917c00SJeff Kirsher {
1177f7917c00SJeff Kirsher 	int link_ok, speed, duplex, fc;
1178f7917c00SJeff Kirsher 	struct port_info *pi = adap2pinfo(adapter, port_id);
1179f7917c00SJeff Kirsher 	struct cphy *phy = &pi->phy;
1180f7917c00SJeff Kirsher 	struct cmac *mac = &pi->mac;
1181f7917c00SJeff Kirsher 	struct link_config *lc = &pi->link_config;
1182f7917c00SJeff Kirsher 
1183f7917c00SJeff Kirsher 	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
1184f7917c00SJeff Kirsher 
1185f7917c00SJeff Kirsher 	if (!lc->link_ok && link_ok) {
1186f7917c00SJeff Kirsher 		u32 rx_cfg, rx_hash_high, rx_hash_low;
1187f7917c00SJeff Kirsher 		u32 status;
1188f7917c00SJeff Kirsher 
1189f7917c00SJeff Kirsher 		t3_xgm_intr_enable(adapter, port_id);
1190f7917c00SJeff Kirsher 		t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low);
1191f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0);
1192f7917c00SJeff Kirsher 		t3_mac_enable(mac, MAC_DIRECTION_RX);
1193f7917c00SJeff Kirsher 
1194f7917c00SJeff Kirsher 		status = t3_read_reg(adapter, A_XGM_INT_STATUS + mac->offset);
1195f7917c00SJeff Kirsher 		if (status & F_LINKFAULTCHANGE) {
1196f7917c00SJeff Kirsher 			mac->stats.link_faults++;
1197f7917c00SJeff Kirsher 			pi->link_fault = 1;
1198f7917c00SJeff Kirsher 		}
1199f7917c00SJeff Kirsher 		t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low);
1200f7917c00SJeff Kirsher 	}
1201f7917c00SJeff Kirsher 
1202f7917c00SJeff Kirsher 	if (lc->requested_fc & PAUSE_AUTONEG)
1203f7917c00SJeff Kirsher 		fc &= lc->requested_fc;
1204f7917c00SJeff Kirsher 	else
1205f7917c00SJeff Kirsher 		fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
1206f7917c00SJeff Kirsher 
1207f7917c00SJeff Kirsher 	if (link_ok == lc->link_ok && speed == lc->speed &&
1208f7917c00SJeff Kirsher 	    duplex == lc->duplex && fc == lc->fc)
1209f7917c00SJeff Kirsher 		return;                            /* nothing changed */
1210f7917c00SJeff Kirsher 
1211f7917c00SJeff Kirsher 	if (link_ok != lc->link_ok && adapter->params.rev > 0 &&
1212f7917c00SJeff Kirsher 	    uses_xaui(adapter)) {
1213f7917c00SJeff Kirsher 		if (link_ok)
1214f7917c00SJeff Kirsher 			t3b_pcs_reset(mac);
1215f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset,
1216f7917c00SJeff Kirsher 			     link_ok ? F_TXACTENABLE | F_RXEN : 0);
1217f7917c00SJeff Kirsher 	}
1218f7917c00SJeff Kirsher 	lc->link_ok = link_ok;
1219f7917c00SJeff Kirsher 	lc->speed = speed < 0 ? SPEED_INVALID : speed;
1220f7917c00SJeff Kirsher 	lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
1221f7917c00SJeff Kirsher 
1222f7917c00SJeff Kirsher 	if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
1223f7917c00SJeff Kirsher 		/* Set MAC speed, duplex, and flow control to match PHY. */
1224f7917c00SJeff Kirsher 		t3_mac_set_speed_duplex_fc(mac, speed, duplex, fc);
1225f7917c00SJeff Kirsher 		lc->fc = fc;
1226f7917c00SJeff Kirsher 	}
1227f7917c00SJeff Kirsher 
1228f7917c00SJeff Kirsher 	t3_os_link_changed(adapter, port_id, link_ok && !pi->link_fault,
1229f7917c00SJeff Kirsher 			   speed, duplex, fc);
1230f7917c00SJeff Kirsher }
1231f7917c00SJeff Kirsher 
t3_link_fault(struct adapter * adapter,int port_id)1232f7917c00SJeff Kirsher void t3_link_fault(struct adapter *adapter, int port_id)
1233f7917c00SJeff Kirsher {
1234f7917c00SJeff Kirsher 	struct port_info *pi = adap2pinfo(adapter, port_id);
1235f7917c00SJeff Kirsher 	struct cmac *mac = &pi->mac;
1236f7917c00SJeff Kirsher 	struct cphy *phy = &pi->phy;
1237f7917c00SJeff Kirsher 	struct link_config *lc = &pi->link_config;
1238f7917c00SJeff Kirsher 	int link_ok, speed, duplex, fc, link_fault;
1239f7917c00SJeff Kirsher 	u32 rx_cfg, rx_hash_high, rx_hash_low;
1240f7917c00SJeff Kirsher 
1241f7917c00SJeff Kirsher 	t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low);
1242f7917c00SJeff Kirsher 
1243f7917c00SJeff Kirsher 	if (adapter->params.rev > 0 && uses_xaui(adapter))
1244f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, 0);
1245f7917c00SJeff Kirsher 
1246f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0);
1247f7917c00SJeff Kirsher 	t3_mac_enable(mac, MAC_DIRECTION_RX);
1248f7917c00SJeff Kirsher 
1249f7917c00SJeff Kirsher 	t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low);
1250f7917c00SJeff Kirsher 
1251f7917c00SJeff Kirsher 	link_fault = t3_read_reg(adapter,
1252f7917c00SJeff Kirsher 				 A_XGM_INT_STATUS + mac->offset);
1253f7917c00SJeff Kirsher 	link_fault &= F_LINKFAULTCHANGE;
1254f7917c00SJeff Kirsher 
1255f7917c00SJeff Kirsher 	link_ok = lc->link_ok;
1256f7917c00SJeff Kirsher 	speed = lc->speed;
1257f7917c00SJeff Kirsher 	duplex = lc->duplex;
1258f7917c00SJeff Kirsher 	fc = lc->fc;
1259f7917c00SJeff Kirsher 
1260f7917c00SJeff Kirsher 	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
1261f7917c00SJeff Kirsher 
1262f7917c00SJeff Kirsher 	if (link_fault) {
1263f7917c00SJeff Kirsher 		lc->link_ok = 0;
1264f7917c00SJeff Kirsher 		lc->speed = SPEED_INVALID;
1265f7917c00SJeff Kirsher 		lc->duplex = DUPLEX_INVALID;
1266f7917c00SJeff Kirsher 
1267f7917c00SJeff Kirsher 		t3_os_link_fault(adapter, port_id, 0);
1268f7917c00SJeff Kirsher 
1269f7917c00SJeff Kirsher 		/* Account link faults only when the phy reports a link up */
1270f7917c00SJeff Kirsher 		if (link_ok)
1271f7917c00SJeff Kirsher 			mac->stats.link_faults++;
1272f7917c00SJeff Kirsher 	} else {
1273f7917c00SJeff Kirsher 		if (link_ok)
1274f7917c00SJeff Kirsher 			t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset,
1275f7917c00SJeff Kirsher 				     F_TXACTENABLE | F_RXEN);
1276f7917c00SJeff Kirsher 
1277f7917c00SJeff Kirsher 		pi->link_fault = 0;
1278f7917c00SJeff Kirsher 		lc->link_ok = (unsigned char)link_ok;
1279f7917c00SJeff Kirsher 		lc->speed = speed < 0 ? SPEED_INVALID : speed;
1280f7917c00SJeff Kirsher 		lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
1281f7917c00SJeff Kirsher 		t3_os_link_fault(adapter, port_id, link_ok);
1282f7917c00SJeff Kirsher 	}
1283f7917c00SJeff Kirsher }
1284f7917c00SJeff Kirsher 
1285f7917c00SJeff Kirsher /**
1286f7917c00SJeff Kirsher  *	t3_link_start - apply link configuration to MAC/PHY
1287f7917c00SJeff Kirsher  *	@phy: the PHY to setup
1288f7917c00SJeff Kirsher  *	@mac: the MAC to setup
1289f7917c00SJeff Kirsher  *	@lc: the requested link configuration
1290f7917c00SJeff Kirsher  *
1291f7917c00SJeff Kirsher  *	Set up a port's MAC and PHY according to a desired link configuration.
1292f7917c00SJeff Kirsher  *	- If the PHY can auto-negotiate first decide what to advertise, then
1293f7917c00SJeff Kirsher  *	  enable/disable auto-negotiation as desired, and reset.
1294f7917c00SJeff Kirsher  *	- If the PHY does not auto-negotiate just reset it.
1295f7917c00SJeff Kirsher  *	- If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
1296f7917c00SJeff Kirsher  *	  otherwise do it later based on the outcome of auto-negotiation.
1297f7917c00SJeff Kirsher  */
t3_link_start(struct cphy * phy,struct cmac * mac,struct link_config * lc)1298f7917c00SJeff Kirsher int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
1299f7917c00SJeff Kirsher {
1300f7917c00SJeff Kirsher 	unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
1301f7917c00SJeff Kirsher 
1302f7917c00SJeff Kirsher 	lc->link_ok = 0;
1303f7917c00SJeff Kirsher 	if (lc->supported & SUPPORTED_Autoneg) {
1304f7917c00SJeff Kirsher 		lc->advertising &= ~(ADVERTISED_Asym_Pause | ADVERTISED_Pause);
1305f7917c00SJeff Kirsher 		if (fc) {
1306f7917c00SJeff Kirsher 			lc->advertising |= ADVERTISED_Asym_Pause;
1307f7917c00SJeff Kirsher 			if (fc & PAUSE_RX)
1308f7917c00SJeff Kirsher 				lc->advertising |= ADVERTISED_Pause;
1309f7917c00SJeff Kirsher 		}
1310f7917c00SJeff Kirsher 		phy->ops->advertise(phy, lc->advertising);
1311f7917c00SJeff Kirsher 
1312f7917c00SJeff Kirsher 		if (lc->autoneg == AUTONEG_DISABLE) {
1313f7917c00SJeff Kirsher 			lc->speed = lc->requested_speed;
1314f7917c00SJeff Kirsher 			lc->duplex = lc->requested_duplex;
1315f7917c00SJeff Kirsher 			lc->fc = (unsigned char)fc;
1316f7917c00SJeff Kirsher 			t3_mac_set_speed_duplex_fc(mac, lc->speed, lc->duplex,
1317f7917c00SJeff Kirsher 						   fc);
1318f7917c00SJeff Kirsher 			/* Also disables autoneg */
1319f7917c00SJeff Kirsher 			phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
1320f7917c00SJeff Kirsher 		} else
1321f7917c00SJeff Kirsher 			phy->ops->autoneg_enable(phy);
1322f7917c00SJeff Kirsher 	} else {
1323f7917c00SJeff Kirsher 		t3_mac_set_speed_duplex_fc(mac, -1, -1, fc);
1324f7917c00SJeff Kirsher 		lc->fc = (unsigned char)fc;
1325f7917c00SJeff Kirsher 		phy->ops->reset(phy, 0);
1326f7917c00SJeff Kirsher 	}
1327f7917c00SJeff Kirsher 	return 0;
1328f7917c00SJeff Kirsher }
1329f7917c00SJeff Kirsher 
1330f7917c00SJeff Kirsher /**
1331f7917c00SJeff Kirsher  *	t3_set_vlan_accel - control HW VLAN extraction
1332f7917c00SJeff Kirsher  *	@adapter: the adapter
1333f7917c00SJeff Kirsher  *	@ports: bitmap of adapter ports to operate on
1334f7917c00SJeff Kirsher  *	@on: enable (1) or disable (0) HW VLAN extraction
1335f7917c00SJeff Kirsher  *
1336f7917c00SJeff Kirsher  *	Enables or disables HW extraction of VLAN tags for the given port.
1337f7917c00SJeff Kirsher  */
t3_set_vlan_accel(struct adapter * adapter,unsigned int ports,int on)1338f7917c00SJeff Kirsher void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on)
1339f7917c00SJeff Kirsher {
1340f7917c00SJeff Kirsher 	t3_set_reg_field(adapter, A_TP_OUT_CONFIG,
1341f7917c00SJeff Kirsher 			 ports << S_VLANEXTRACTIONENABLE,
1342f7917c00SJeff Kirsher 			 on ? (ports << S_VLANEXTRACTIONENABLE) : 0);
1343f7917c00SJeff Kirsher }
1344f7917c00SJeff Kirsher 
1345f7917c00SJeff Kirsher struct intr_info {
1346f7917c00SJeff Kirsher 	unsigned int mask;	/* bits to check in interrupt status */
1347f7917c00SJeff Kirsher 	const char *msg;	/* message to print or NULL */
1348f7917c00SJeff Kirsher 	short stat_idx;		/* stat counter to increment or -1 */
1349f7917c00SJeff Kirsher 	unsigned short fatal;	/* whether the condition reported is fatal */
1350f7917c00SJeff Kirsher };
1351f7917c00SJeff Kirsher 
1352f7917c00SJeff Kirsher /**
1353f7917c00SJeff Kirsher  *	t3_handle_intr_status - table driven interrupt handler
1354f7917c00SJeff Kirsher  *	@adapter: the adapter that generated the interrupt
1355f7917c00SJeff Kirsher  *	@reg: the interrupt status register to process
1356f7917c00SJeff Kirsher  *	@mask: a mask to apply to the interrupt status
1357f7917c00SJeff Kirsher  *	@acts: table of interrupt actions
1358f7917c00SJeff Kirsher  *	@stats: statistics counters tracking interrupt occurrences
1359f7917c00SJeff Kirsher  *
1360f7917c00SJeff Kirsher  *	A table driven interrupt handler that applies a set of masks to an
1361f7917c00SJeff Kirsher  *	interrupt status word and performs the corresponding actions if the
1362f7917c00SJeff Kirsher  *	interrupts described by the mask have occurred.  The actions include
1363f7917c00SJeff Kirsher  *	optionally printing a warning or alert message, and optionally
1364f7917c00SJeff Kirsher  *	incrementing a stat counter.  The table is terminated by an entry
1365f7917c00SJeff Kirsher  *	specifying mask 0.  Returns the number of fatal interrupt conditions.
1366f7917c00SJeff Kirsher  */
t3_handle_intr_status(struct adapter * adapter,unsigned int reg,unsigned int mask,const struct intr_info * acts,unsigned long * stats)1367f7917c00SJeff Kirsher static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
1368f7917c00SJeff Kirsher 				 unsigned int mask,
1369f7917c00SJeff Kirsher 				 const struct intr_info *acts,
1370f7917c00SJeff Kirsher 				 unsigned long *stats)
1371f7917c00SJeff Kirsher {
1372f7917c00SJeff Kirsher 	int fatal = 0;
1373f7917c00SJeff Kirsher 	unsigned int status = t3_read_reg(adapter, reg) & mask;
1374f7917c00SJeff Kirsher 
1375f7917c00SJeff Kirsher 	for (; acts->mask; ++acts) {
1376f7917c00SJeff Kirsher 		if (!(status & acts->mask))
1377f7917c00SJeff Kirsher 			continue;
1378f7917c00SJeff Kirsher 		if (acts->fatal) {
1379f7917c00SJeff Kirsher 			fatal++;
1380f7917c00SJeff Kirsher 			CH_ALERT(adapter, "%s (0x%x)\n",
1381f7917c00SJeff Kirsher 				 acts->msg, status & acts->mask);
1382f7917c00SJeff Kirsher 			status &= ~acts->mask;
1383f7917c00SJeff Kirsher 		} else if (acts->msg)
1384f7917c00SJeff Kirsher 			CH_WARN(adapter, "%s (0x%x)\n",
1385f7917c00SJeff Kirsher 				acts->msg, status & acts->mask);
1386f7917c00SJeff Kirsher 		if (acts->stat_idx >= 0)
1387f7917c00SJeff Kirsher 			stats[acts->stat_idx]++;
1388f7917c00SJeff Kirsher 	}
1389f7917c00SJeff Kirsher 	if (status)		/* clear processed interrupts */
1390f7917c00SJeff Kirsher 		t3_write_reg(adapter, reg, status);
1391f7917c00SJeff Kirsher 	return fatal;
1392f7917c00SJeff Kirsher }
1393f7917c00SJeff Kirsher 
1394f7917c00SJeff Kirsher #define SGE_INTR_MASK (F_RSPQDISABLED | \
1395f7917c00SJeff Kirsher 		       F_UC_REQ_FRAMINGERROR | F_R_REQ_FRAMINGERROR | \
1396f7917c00SJeff Kirsher 		       F_CPPARITYERROR | F_OCPARITYERROR | F_RCPARITYERROR | \
1397f7917c00SJeff Kirsher 		       F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
1398f7917c00SJeff Kirsher 		       V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
1399f7917c00SJeff Kirsher 		       F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
1400f7917c00SJeff Kirsher 		       F_HIRCQPARITYERROR | F_LOPRIORITYDBFULL | \
1401f7917c00SJeff Kirsher 		       F_HIPRIORITYDBFULL | F_LOPRIORITYDBEMPTY | \
1402f7917c00SJeff Kirsher 		       F_HIPRIORITYDBEMPTY | F_HIPIODRBDROPERR | \
1403f7917c00SJeff Kirsher 		       F_LOPIODRBDROPERR)
1404f7917c00SJeff Kirsher #define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \
1405f7917c00SJeff Kirsher 		       F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \
1406f7917c00SJeff Kirsher 		       F_NFASRCHFAIL)
1407f7917c00SJeff Kirsher #define MC7_INTR_MASK (F_AE | F_UE | F_CE | V_PE(M_PE))
1408f7917c00SJeff Kirsher #define XGM_INTR_MASK (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \
1409f7917c00SJeff Kirsher 		       V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR) | \
1410f7917c00SJeff Kirsher 		       F_TXFIFO_UNDERRUN)
1411f7917c00SJeff Kirsher #define PCIX_INTR_MASK (F_MSTDETPARERR | F_SIGTARABT | F_RCVTARABT | \
1412f7917c00SJeff Kirsher 			F_RCVMSTABT | F_SIGSYSERR | F_DETPARERR | \
1413f7917c00SJeff Kirsher 			F_SPLCMPDIS | F_UNXSPLCMP | F_RCVSPLCMPERR | \
1414f7917c00SJeff Kirsher 			F_DETCORECCERR | F_DETUNCECCERR | F_PIOPARERR | \
1415f7917c00SJeff Kirsher 			V_WFPARERR(M_WFPARERR) | V_RFPARERR(M_RFPARERR) | \
1416f7917c00SJeff Kirsher 			V_CFPARERR(M_CFPARERR) /* | V_MSIXPARERR(M_MSIXPARERR) */)
1417f7917c00SJeff Kirsher #define PCIE_INTR_MASK (F_UNXSPLCPLERRR | F_UNXSPLCPLERRC | F_PCIE_PIOPARERR |\
1418f7917c00SJeff Kirsher 			F_PCIE_WFPARERR | F_PCIE_RFPARERR | F_PCIE_CFPARERR | \
1419f7917c00SJeff Kirsher 			/* V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR) | */ \
1420f7917c00SJeff Kirsher 			F_RETRYBUFPARERR | F_RETRYLUTPARERR | F_RXPARERR | \
1421f7917c00SJeff Kirsher 			F_TXPARERR | V_BISTERR(M_BISTERR))
1422f7917c00SJeff Kirsher #define ULPRX_INTR_MASK (F_PARERRDATA | F_PARERRPCMD | F_ARBPF1PERR | \
1423f7917c00SJeff Kirsher 			 F_ARBPF0PERR | F_ARBFPERR | F_PCMDMUXPERR | \
1424f7917c00SJeff Kirsher 			 F_DATASELFRAMEERR1 | F_DATASELFRAMEERR0)
1425f7917c00SJeff Kirsher #define ULPTX_INTR_MASK 0xfc
1426f7917c00SJeff Kirsher #define CPLSW_INTR_MASK (F_CIM_OP_MAP_PERR | F_TP_FRAMING_ERROR | \
1427f7917c00SJeff Kirsher 			 F_SGE_FRAMING_ERROR | F_CIM_FRAMING_ERROR | \
1428f7917c00SJeff Kirsher 			 F_ZERO_SWITCH_ERROR)
1429f7917c00SJeff Kirsher #define CIM_INTR_MASK (F_BLKWRPLINT | F_BLKRDPLINT | F_BLKWRCTLINT | \
1430f7917c00SJeff Kirsher 		       F_BLKRDCTLINT | F_BLKWRFLASHINT | F_BLKRDFLASHINT | \
1431f7917c00SJeff Kirsher 		       F_SGLWRFLASHINT | F_WRBLKFLASHINT | F_BLKWRBOOTINT | \
1432f7917c00SJeff Kirsher 	 	       F_FLASHRANGEINT | F_SDRAMRANGEINT | F_RSVDSPACEINT | \
1433f7917c00SJeff Kirsher 		       F_DRAMPARERR | F_ICACHEPARERR | F_DCACHEPARERR | \
1434f7917c00SJeff Kirsher 		       F_OBQSGEPARERR | F_OBQULPHIPARERR | F_OBQULPLOPARERR | \
1435f7917c00SJeff Kirsher 		       F_IBQSGELOPARERR | F_IBQSGEHIPARERR | F_IBQULPPARERR | \
1436f7917c00SJeff Kirsher 		       F_IBQTPPARERR | F_ITAGPARERR | F_DTAGPARERR)
1437f7917c00SJeff Kirsher #define PMTX_INTR_MASK (F_ZERO_C_CMD_ERROR | ICSPI_FRM_ERR | OESPI_FRM_ERR | \
1438f7917c00SJeff Kirsher 			V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR) | \
1439f7917c00SJeff Kirsher 			V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR))
1440f7917c00SJeff Kirsher #define PMRX_INTR_MASK (F_ZERO_E_CMD_ERROR | IESPI_FRM_ERR | OCSPI_FRM_ERR | \
1441f7917c00SJeff Kirsher 			V_IESPI_PAR_ERROR(M_IESPI_PAR_ERROR) | \
1442f7917c00SJeff Kirsher 			V_OCSPI_PAR_ERROR(M_OCSPI_PAR_ERROR))
1443f7917c00SJeff Kirsher #define MPS_INTR_MASK (V_TX0TPPARERRENB(M_TX0TPPARERRENB) | \
1444f7917c00SJeff Kirsher 		       V_TX1TPPARERRENB(M_TX1TPPARERRENB) | \
1445f7917c00SJeff Kirsher 		       V_RXTPPARERRENB(M_RXTPPARERRENB) | \
1446f7917c00SJeff Kirsher 		       V_MCAPARERRENB(M_MCAPARERRENB))
1447f7917c00SJeff Kirsher #define XGM_EXTRA_INTR_MASK (F_LINKFAULTCHANGE)
1448f7917c00SJeff Kirsher #define PL_INTR_MASK (F_T3DBG | F_XGMAC0_0 | F_XGMAC0_1 | F_MC5A | F_PM1_TX | \
1449f7917c00SJeff Kirsher 		      F_PM1_RX | F_ULP2_TX | F_ULP2_RX | F_TP1 | F_CIM | \
1450f7917c00SJeff Kirsher 		      F_MC7_CM | F_MC7_PMTX | F_MC7_PMRX | F_SGE3 | F_PCIM0 | \
1451f7917c00SJeff Kirsher 		      F_MPS0 | F_CPL_SWITCH)
1452f7917c00SJeff Kirsher /*
1453f7917c00SJeff Kirsher  * Interrupt handler for the PCIX1 module.
1454f7917c00SJeff Kirsher  */
pci_intr_handler(struct adapter * adapter)1455f7917c00SJeff Kirsher static void pci_intr_handler(struct adapter *adapter)
1456f7917c00SJeff Kirsher {
1457f7917c00SJeff Kirsher 	static const struct intr_info pcix1_intr_info[] = {
1458f7917c00SJeff Kirsher 		{F_MSTDETPARERR, "PCI master detected parity error", -1, 1},
1459f7917c00SJeff Kirsher 		{F_SIGTARABT, "PCI signaled target abort", -1, 1},
1460f7917c00SJeff Kirsher 		{F_RCVTARABT, "PCI received target abort", -1, 1},
1461f7917c00SJeff Kirsher 		{F_RCVMSTABT, "PCI received master abort", -1, 1},
1462f7917c00SJeff Kirsher 		{F_SIGSYSERR, "PCI signaled system error", -1, 1},
1463f7917c00SJeff Kirsher 		{F_DETPARERR, "PCI detected parity error", -1, 1},
1464f7917c00SJeff Kirsher 		{F_SPLCMPDIS, "PCI split completion discarded", -1, 1},
1465f7917c00SJeff Kirsher 		{F_UNXSPLCMP, "PCI unexpected split completion error", -1, 1},
1466f7917c00SJeff Kirsher 		{F_RCVSPLCMPERR, "PCI received split completion error", -1,
1467f7917c00SJeff Kirsher 		 1},
1468f7917c00SJeff Kirsher 		{F_DETCORECCERR, "PCI correctable ECC error",
1469f7917c00SJeff Kirsher 		 STAT_PCI_CORR_ECC, 0},
1470f7917c00SJeff Kirsher 		{F_DETUNCECCERR, "PCI uncorrectable ECC error", -1, 1},
1471f7917c00SJeff Kirsher 		{F_PIOPARERR, "PCI PIO FIFO parity error", -1, 1},
1472f7917c00SJeff Kirsher 		{V_WFPARERR(M_WFPARERR), "PCI write FIFO parity error", -1,
1473f7917c00SJeff Kirsher 		 1},
1474f7917c00SJeff Kirsher 		{V_RFPARERR(M_RFPARERR), "PCI read FIFO parity error", -1,
1475f7917c00SJeff Kirsher 		 1},
1476f7917c00SJeff Kirsher 		{V_CFPARERR(M_CFPARERR), "PCI command FIFO parity error", -1,
1477f7917c00SJeff Kirsher 		 1},
1478f7917c00SJeff Kirsher 		{V_MSIXPARERR(M_MSIXPARERR), "PCI MSI-X table/PBA parity "
1479f7917c00SJeff Kirsher 		 "error", -1, 1},
1480f7917c00SJeff Kirsher 		{0}
1481f7917c00SJeff Kirsher 	};
1482f7917c00SJeff Kirsher 
1483f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_PCIX_INT_CAUSE, PCIX_INTR_MASK,
1484f7917c00SJeff Kirsher 				  pcix1_intr_info, adapter->irq_stats))
1485f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1486f7917c00SJeff Kirsher }
1487f7917c00SJeff Kirsher 
1488f7917c00SJeff Kirsher /*
1489f7917c00SJeff Kirsher  * Interrupt handler for the PCIE module.
1490f7917c00SJeff Kirsher  */
pcie_intr_handler(struct adapter * adapter)1491f7917c00SJeff Kirsher static void pcie_intr_handler(struct adapter *adapter)
1492f7917c00SJeff Kirsher {
1493f7917c00SJeff Kirsher 	static const struct intr_info pcie_intr_info[] = {
1494f7917c00SJeff Kirsher 		{F_PEXERR, "PCI PEX error", -1, 1},
1495f7917c00SJeff Kirsher 		{F_UNXSPLCPLERRR,
1496f7917c00SJeff Kirsher 		 "PCI unexpected split completion DMA read error", -1, 1},
1497f7917c00SJeff Kirsher 		{F_UNXSPLCPLERRC,
1498f7917c00SJeff Kirsher 		 "PCI unexpected split completion DMA command error", -1, 1},
1499f7917c00SJeff Kirsher 		{F_PCIE_PIOPARERR, "PCI PIO FIFO parity error", -1, 1},
1500f7917c00SJeff Kirsher 		{F_PCIE_WFPARERR, "PCI write FIFO parity error", -1, 1},
1501f7917c00SJeff Kirsher 		{F_PCIE_RFPARERR, "PCI read FIFO parity error", -1, 1},
1502f7917c00SJeff Kirsher 		{F_PCIE_CFPARERR, "PCI command FIFO parity error", -1, 1},
1503f7917c00SJeff Kirsher 		{V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR),
1504f7917c00SJeff Kirsher 		 "PCI MSI-X table/PBA parity error", -1, 1},
1505f7917c00SJeff Kirsher 		{F_RETRYBUFPARERR, "PCI retry buffer parity error", -1, 1},
1506f7917c00SJeff Kirsher 		{F_RETRYLUTPARERR, "PCI retry LUT parity error", -1, 1},
1507f7917c00SJeff Kirsher 		{F_RXPARERR, "PCI Rx parity error", -1, 1},
1508f7917c00SJeff Kirsher 		{F_TXPARERR, "PCI Tx parity error", -1, 1},
1509f7917c00SJeff Kirsher 		{V_BISTERR(M_BISTERR), "PCI BIST error", -1, 1},
1510f7917c00SJeff Kirsher 		{0}
1511f7917c00SJeff Kirsher 	};
1512f7917c00SJeff Kirsher 
1513f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_PCIE_INT_CAUSE) & F_PEXERR)
1514f7917c00SJeff Kirsher 		CH_ALERT(adapter, "PEX error code 0x%x\n",
1515f7917c00SJeff Kirsher 			 t3_read_reg(adapter, A_PCIE_PEX_ERR));
1516f7917c00SJeff Kirsher 
1517f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_PCIE_INT_CAUSE, PCIE_INTR_MASK,
1518f7917c00SJeff Kirsher 				  pcie_intr_info, adapter->irq_stats))
1519f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1520f7917c00SJeff Kirsher }
1521f7917c00SJeff Kirsher 
1522f7917c00SJeff Kirsher /*
1523f7917c00SJeff Kirsher  * TP interrupt handler.
1524f7917c00SJeff Kirsher  */
tp_intr_handler(struct adapter * adapter)1525f7917c00SJeff Kirsher static void tp_intr_handler(struct adapter *adapter)
1526f7917c00SJeff Kirsher {
1527f7917c00SJeff Kirsher 	static const struct intr_info tp_intr_info[] = {
1528f7917c00SJeff Kirsher 		{0xffffff, "TP parity error", -1, 1},
1529f7917c00SJeff Kirsher 		{0x1000000, "TP out of Rx pages", -1, 1},
1530f7917c00SJeff Kirsher 		{0x2000000, "TP out of Tx pages", -1, 1},
1531f7917c00SJeff Kirsher 		{0}
1532f7917c00SJeff Kirsher 	};
1533f7917c00SJeff Kirsher 
1534f7917c00SJeff Kirsher 	static const struct intr_info tp_intr_info_t3c[] = {
1535f7917c00SJeff Kirsher 		{0x1fffffff, "TP parity error", -1, 1},
1536f7917c00SJeff Kirsher 		{F_FLMRXFLSTEMPTY, "TP out of Rx pages", -1, 1},
1537f7917c00SJeff Kirsher 		{F_FLMTXFLSTEMPTY, "TP out of Tx pages", -1, 1},
1538f7917c00SJeff Kirsher 		{0}
1539f7917c00SJeff Kirsher 	};
1540f7917c00SJeff Kirsher 
1541f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_TP_INT_CAUSE, 0xffffffff,
1542f7917c00SJeff Kirsher 				  adapter->params.rev < T3_REV_C ?
1543f7917c00SJeff Kirsher 				  tp_intr_info : tp_intr_info_t3c, NULL))
1544f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1545f7917c00SJeff Kirsher }
1546f7917c00SJeff Kirsher 
1547f7917c00SJeff Kirsher /*
1548f7917c00SJeff Kirsher  * CIM interrupt handler.
1549f7917c00SJeff Kirsher  */
cim_intr_handler(struct adapter * adapter)1550f7917c00SJeff Kirsher static void cim_intr_handler(struct adapter *adapter)
1551f7917c00SJeff Kirsher {
1552f7917c00SJeff Kirsher 	static const struct intr_info cim_intr_info[] = {
1553f7917c00SJeff Kirsher 		{F_RSVDSPACEINT, "CIM reserved space write", -1, 1},
1554f7917c00SJeff Kirsher 		{F_SDRAMRANGEINT, "CIM SDRAM address out of range", -1, 1},
1555f7917c00SJeff Kirsher 		{F_FLASHRANGEINT, "CIM flash address out of range", -1, 1},
1556f7917c00SJeff Kirsher 		{F_BLKWRBOOTINT, "CIM block write to boot space", -1, 1},
1557f7917c00SJeff Kirsher 		{F_WRBLKFLASHINT, "CIM write to cached flash space", -1, 1},
1558f7917c00SJeff Kirsher 		{F_SGLWRFLASHINT, "CIM single write to flash space", -1, 1},
1559f7917c00SJeff Kirsher 		{F_BLKRDFLASHINT, "CIM block read from flash space", -1, 1},
1560f7917c00SJeff Kirsher 		{F_BLKWRFLASHINT, "CIM block write to flash space", -1, 1},
1561f7917c00SJeff Kirsher 		{F_BLKRDCTLINT, "CIM block read from CTL space", -1, 1},
1562f7917c00SJeff Kirsher 		{F_BLKWRCTLINT, "CIM block write to CTL space", -1, 1},
1563f7917c00SJeff Kirsher 		{F_BLKRDPLINT, "CIM block read from PL space", -1, 1},
1564f7917c00SJeff Kirsher 		{F_BLKWRPLINT, "CIM block write to PL space", -1, 1},
1565f7917c00SJeff Kirsher 		{F_DRAMPARERR, "CIM DRAM parity error", -1, 1},
1566f7917c00SJeff Kirsher 		{F_ICACHEPARERR, "CIM icache parity error", -1, 1},
1567f7917c00SJeff Kirsher 		{F_DCACHEPARERR, "CIM dcache parity error", -1, 1},
1568f7917c00SJeff Kirsher 		{F_OBQSGEPARERR, "CIM OBQ SGE parity error", -1, 1},
1569f7917c00SJeff Kirsher 		{F_OBQULPHIPARERR, "CIM OBQ ULPHI parity error", -1, 1},
1570f7917c00SJeff Kirsher 		{F_OBQULPLOPARERR, "CIM OBQ ULPLO parity error", -1, 1},
1571f7917c00SJeff Kirsher 		{F_IBQSGELOPARERR, "CIM IBQ SGELO parity error", -1, 1},
1572f7917c00SJeff Kirsher 		{F_IBQSGEHIPARERR, "CIM IBQ SGEHI parity error", -1, 1},
1573f7917c00SJeff Kirsher 		{F_IBQULPPARERR, "CIM IBQ ULP parity error", -1, 1},
1574f7917c00SJeff Kirsher 		{F_IBQTPPARERR, "CIM IBQ TP parity error", -1, 1},
1575f7917c00SJeff Kirsher 		{F_ITAGPARERR, "CIM itag parity error", -1, 1},
1576f7917c00SJeff Kirsher 		{F_DTAGPARERR, "CIM dtag parity error", -1, 1},
1577f7917c00SJeff Kirsher 		{0}
1578f7917c00SJeff Kirsher 	};
1579f7917c00SJeff Kirsher 
1580f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_CIM_HOST_INT_CAUSE, 0xffffffff,
1581f7917c00SJeff Kirsher 				  cim_intr_info, NULL))
1582f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1583f7917c00SJeff Kirsher }
1584f7917c00SJeff Kirsher 
1585f7917c00SJeff Kirsher /*
1586f7917c00SJeff Kirsher  * ULP RX interrupt handler.
1587f7917c00SJeff Kirsher  */
ulprx_intr_handler(struct adapter * adapter)1588f7917c00SJeff Kirsher static void ulprx_intr_handler(struct adapter *adapter)
1589f7917c00SJeff Kirsher {
1590f7917c00SJeff Kirsher 	static const struct intr_info ulprx_intr_info[] = {
1591f7917c00SJeff Kirsher 		{F_PARERRDATA, "ULP RX data parity error", -1, 1},
1592f7917c00SJeff Kirsher 		{F_PARERRPCMD, "ULP RX command parity error", -1, 1},
1593f7917c00SJeff Kirsher 		{F_ARBPF1PERR, "ULP RX ArbPF1 parity error", -1, 1},
1594f7917c00SJeff Kirsher 		{F_ARBPF0PERR, "ULP RX ArbPF0 parity error", -1, 1},
1595f7917c00SJeff Kirsher 		{F_ARBFPERR, "ULP RX ArbF parity error", -1, 1},
1596f7917c00SJeff Kirsher 		{F_PCMDMUXPERR, "ULP RX PCMDMUX parity error", -1, 1},
1597f7917c00SJeff Kirsher 		{F_DATASELFRAMEERR1, "ULP RX frame error", -1, 1},
1598f7917c00SJeff Kirsher 		{F_DATASELFRAMEERR0, "ULP RX frame error", -1, 1},
1599f7917c00SJeff Kirsher 		{0}
1600f7917c00SJeff Kirsher 	};
1601f7917c00SJeff Kirsher 
1602f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_ULPRX_INT_CAUSE, 0xffffffff,
1603f7917c00SJeff Kirsher 				  ulprx_intr_info, NULL))
1604f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1605f7917c00SJeff Kirsher }
1606f7917c00SJeff Kirsher 
1607f7917c00SJeff Kirsher /*
1608f7917c00SJeff Kirsher  * ULP TX interrupt handler.
1609f7917c00SJeff Kirsher  */
ulptx_intr_handler(struct adapter * adapter)1610f7917c00SJeff Kirsher static void ulptx_intr_handler(struct adapter *adapter)
1611f7917c00SJeff Kirsher {
1612f7917c00SJeff Kirsher 	static const struct intr_info ulptx_intr_info[] = {
1613f7917c00SJeff Kirsher 		{F_PBL_BOUND_ERR_CH0, "ULP TX channel 0 PBL out of bounds",
1614f7917c00SJeff Kirsher 		 STAT_ULP_CH0_PBL_OOB, 0},
1615f7917c00SJeff Kirsher 		{F_PBL_BOUND_ERR_CH1, "ULP TX channel 1 PBL out of bounds",
1616f7917c00SJeff Kirsher 		 STAT_ULP_CH1_PBL_OOB, 0},
1617f7917c00SJeff Kirsher 		{0xfc, "ULP TX parity error", -1, 1},
1618f7917c00SJeff Kirsher 		{0}
1619f7917c00SJeff Kirsher 	};
1620f7917c00SJeff Kirsher 
1621f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_ULPTX_INT_CAUSE, 0xffffffff,
1622f7917c00SJeff Kirsher 				  ulptx_intr_info, adapter->irq_stats))
1623f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1624f7917c00SJeff Kirsher }
1625f7917c00SJeff Kirsher 
1626f7917c00SJeff Kirsher #define ICSPI_FRM_ERR (F_ICSPI0_FIFO2X_RX_FRAMING_ERROR | \
1627f7917c00SJeff Kirsher 	F_ICSPI1_FIFO2X_RX_FRAMING_ERROR | F_ICSPI0_RX_FRAMING_ERROR | \
1628f7917c00SJeff Kirsher 	F_ICSPI1_RX_FRAMING_ERROR | F_ICSPI0_TX_FRAMING_ERROR | \
1629f7917c00SJeff Kirsher 	F_ICSPI1_TX_FRAMING_ERROR)
1630f7917c00SJeff Kirsher #define OESPI_FRM_ERR (F_OESPI0_RX_FRAMING_ERROR | \
1631f7917c00SJeff Kirsher 	F_OESPI1_RX_FRAMING_ERROR | F_OESPI0_TX_FRAMING_ERROR | \
1632f7917c00SJeff Kirsher 	F_OESPI1_TX_FRAMING_ERROR | F_OESPI0_OFIFO2X_TX_FRAMING_ERROR | \
1633f7917c00SJeff Kirsher 	F_OESPI1_OFIFO2X_TX_FRAMING_ERROR)
1634f7917c00SJeff Kirsher 
1635f7917c00SJeff Kirsher /*
1636f7917c00SJeff Kirsher  * PM TX interrupt handler.
1637f7917c00SJeff Kirsher  */
pmtx_intr_handler(struct adapter * adapter)1638f7917c00SJeff Kirsher static void pmtx_intr_handler(struct adapter *adapter)
1639f7917c00SJeff Kirsher {
1640f7917c00SJeff Kirsher 	static const struct intr_info pmtx_intr_info[] = {
1641f7917c00SJeff Kirsher 		{F_ZERO_C_CMD_ERROR, "PMTX 0-length pcmd", -1, 1},
1642f7917c00SJeff Kirsher 		{ICSPI_FRM_ERR, "PMTX ispi framing error", -1, 1},
1643f7917c00SJeff Kirsher 		{OESPI_FRM_ERR, "PMTX ospi framing error", -1, 1},
1644f7917c00SJeff Kirsher 		{V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR),
1645f7917c00SJeff Kirsher 		 "PMTX ispi parity error", -1, 1},
1646f7917c00SJeff Kirsher 		{V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR),
1647f7917c00SJeff Kirsher 		 "PMTX ospi parity error", -1, 1},
1648f7917c00SJeff Kirsher 		{0}
1649f7917c00SJeff Kirsher 	};
1650f7917c00SJeff Kirsher 
1651f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_PM1_TX_INT_CAUSE, 0xffffffff,
1652f7917c00SJeff Kirsher 				  pmtx_intr_info, NULL))
1653f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1654f7917c00SJeff Kirsher }
1655f7917c00SJeff Kirsher 
1656f7917c00SJeff Kirsher #define IESPI_FRM_ERR (F_IESPI0_FIFO2X_RX_FRAMING_ERROR | \
1657f7917c00SJeff Kirsher 	F_IESPI1_FIFO2X_RX_FRAMING_ERROR | F_IESPI0_RX_FRAMING_ERROR | \
1658f7917c00SJeff Kirsher 	F_IESPI1_RX_FRAMING_ERROR | F_IESPI0_TX_FRAMING_ERROR | \
1659f7917c00SJeff Kirsher 	F_IESPI1_TX_FRAMING_ERROR)
1660f7917c00SJeff Kirsher #define OCSPI_FRM_ERR (F_OCSPI0_RX_FRAMING_ERROR | \
1661f7917c00SJeff Kirsher 	F_OCSPI1_RX_FRAMING_ERROR | F_OCSPI0_TX_FRAMING_ERROR | \
1662f7917c00SJeff Kirsher 	F_OCSPI1_TX_FRAMING_ERROR | F_OCSPI0_OFIFO2X_TX_FRAMING_ERROR | \
1663f7917c00SJeff Kirsher 	F_OCSPI1_OFIFO2X_TX_FRAMING_ERROR)
1664f7917c00SJeff Kirsher 
1665f7917c00SJeff Kirsher /*
1666f7917c00SJeff Kirsher  * PM RX interrupt handler.
1667f7917c00SJeff Kirsher  */
pmrx_intr_handler(struct adapter * adapter)1668f7917c00SJeff Kirsher static void pmrx_intr_handler(struct adapter *adapter)
1669f7917c00SJeff Kirsher {
1670f7917c00SJeff Kirsher 	static const struct intr_info pmrx_intr_info[] = {
1671f7917c00SJeff Kirsher 		{F_ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1},
1672f7917c00SJeff Kirsher 		{IESPI_FRM_ERR, "PMRX ispi framing error", -1, 1},
1673f7917c00SJeff Kirsher 		{OCSPI_FRM_ERR, "PMRX ospi framing error", -1, 1},
1674f7917c00SJeff Kirsher 		{V_IESPI_PAR_ERROR(M_IESPI_PAR_ERROR),
1675f7917c00SJeff Kirsher 		 "PMRX ispi parity error", -1, 1},
1676f7917c00SJeff Kirsher 		{V_OCSPI_PAR_ERROR(M_OCSPI_PAR_ERROR),
1677f7917c00SJeff Kirsher 		 "PMRX ospi parity error", -1, 1},
1678f7917c00SJeff Kirsher 		{0}
1679f7917c00SJeff Kirsher 	};
1680f7917c00SJeff Kirsher 
1681f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_PM1_RX_INT_CAUSE, 0xffffffff,
1682f7917c00SJeff Kirsher 				  pmrx_intr_info, NULL))
1683f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1684f7917c00SJeff Kirsher }
1685f7917c00SJeff Kirsher 
1686f7917c00SJeff Kirsher /*
1687f7917c00SJeff Kirsher  * CPL switch interrupt handler.
1688f7917c00SJeff Kirsher  */
cplsw_intr_handler(struct adapter * adapter)1689f7917c00SJeff Kirsher static void cplsw_intr_handler(struct adapter *adapter)
1690f7917c00SJeff Kirsher {
1691f7917c00SJeff Kirsher 	static const struct intr_info cplsw_intr_info[] = {
1692f7917c00SJeff Kirsher 		{F_CIM_OP_MAP_PERR, "CPL switch CIM parity error", -1, 1},
1693f7917c00SJeff Kirsher 		{F_CIM_OVFL_ERROR, "CPL switch CIM overflow", -1, 1},
1694f7917c00SJeff Kirsher 		{F_TP_FRAMING_ERROR, "CPL switch TP framing error", -1, 1},
1695f7917c00SJeff Kirsher 		{F_SGE_FRAMING_ERROR, "CPL switch SGE framing error", -1, 1},
1696f7917c00SJeff Kirsher 		{F_CIM_FRAMING_ERROR, "CPL switch CIM framing error", -1, 1},
1697f7917c00SJeff Kirsher 		{F_ZERO_SWITCH_ERROR, "CPL switch no-switch error", -1, 1},
1698f7917c00SJeff Kirsher 		{0}
1699f7917c00SJeff Kirsher 	};
1700f7917c00SJeff Kirsher 
1701f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_CPL_INTR_CAUSE, 0xffffffff,
1702f7917c00SJeff Kirsher 				  cplsw_intr_info, NULL))
1703f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1704f7917c00SJeff Kirsher }
1705f7917c00SJeff Kirsher 
1706f7917c00SJeff Kirsher /*
1707f7917c00SJeff Kirsher  * MPS interrupt handler.
1708f7917c00SJeff Kirsher  */
mps_intr_handler(struct adapter * adapter)1709f7917c00SJeff Kirsher static void mps_intr_handler(struct adapter *adapter)
1710f7917c00SJeff Kirsher {
1711f7917c00SJeff Kirsher 	static const struct intr_info mps_intr_info[] = {
1712f7917c00SJeff Kirsher 		{0x1ff, "MPS parity error", -1, 1},
1713f7917c00SJeff Kirsher 		{0}
1714f7917c00SJeff Kirsher 	};
1715f7917c00SJeff Kirsher 
1716f7917c00SJeff Kirsher 	if (t3_handle_intr_status(adapter, A_MPS_INT_CAUSE, 0xffffffff,
1717f7917c00SJeff Kirsher 				  mps_intr_info, NULL))
1718f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1719f7917c00SJeff Kirsher }
1720f7917c00SJeff Kirsher 
1721f7917c00SJeff Kirsher #define MC7_INTR_FATAL (F_UE | V_PE(M_PE) | F_AE)
1722f7917c00SJeff Kirsher 
1723f7917c00SJeff Kirsher /*
1724f7917c00SJeff Kirsher  * MC7 interrupt handler.
1725f7917c00SJeff Kirsher  */
mc7_intr_handler(struct mc7 * mc7)1726f7917c00SJeff Kirsher static void mc7_intr_handler(struct mc7 *mc7)
1727f7917c00SJeff Kirsher {
1728f7917c00SJeff Kirsher 	struct adapter *adapter = mc7->adapter;
1729f7917c00SJeff Kirsher 	u32 cause = t3_read_reg(adapter, mc7->offset + A_MC7_INT_CAUSE);
1730f7917c00SJeff Kirsher 
1731f7917c00SJeff Kirsher 	if (cause & F_CE) {
1732f7917c00SJeff Kirsher 		mc7->stats.corr_err++;
1733f7917c00SJeff Kirsher 		CH_WARN(adapter, "%s MC7 correctable error at addr 0x%x, "
1734f7917c00SJeff Kirsher 			"data 0x%x 0x%x 0x%x\n", mc7->name,
1735f7917c00SJeff Kirsher 			t3_read_reg(adapter, mc7->offset + A_MC7_CE_ADDR),
1736f7917c00SJeff Kirsher 			t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA0),
1737f7917c00SJeff Kirsher 			t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA1),
1738f7917c00SJeff Kirsher 			t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA2));
1739f7917c00SJeff Kirsher 	}
1740f7917c00SJeff Kirsher 
1741f7917c00SJeff Kirsher 	if (cause & F_UE) {
1742f7917c00SJeff Kirsher 		mc7->stats.uncorr_err++;
1743f7917c00SJeff Kirsher 		CH_ALERT(adapter, "%s MC7 uncorrectable error at addr 0x%x, "
1744f7917c00SJeff Kirsher 			 "data 0x%x 0x%x 0x%x\n", mc7->name,
1745f7917c00SJeff Kirsher 			 t3_read_reg(adapter, mc7->offset + A_MC7_UE_ADDR),
1746f7917c00SJeff Kirsher 			 t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA0),
1747f7917c00SJeff Kirsher 			 t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA1),
1748f7917c00SJeff Kirsher 			 t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA2));
1749f7917c00SJeff Kirsher 	}
1750f7917c00SJeff Kirsher 
1751f7917c00SJeff Kirsher 	if (G_PE(cause)) {
1752f7917c00SJeff Kirsher 		mc7->stats.parity_err++;
1753f7917c00SJeff Kirsher 		CH_ALERT(adapter, "%s MC7 parity error 0x%x\n",
1754f7917c00SJeff Kirsher 			 mc7->name, G_PE(cause));
1755f7917c00SJeff Kirsher 	}
1756f7917c00SJeff Kirsher 
1757f7917c00SJeff Kirsher 	if (cause & F_AE) {
1758f7917c00SJeff Kirsher 		u32 addr = 0;
1759f7917c00SJeff Kirsher 
1760f7917c00SJeff Kirsher 		if (adapter->params.rev > 0)
1761f7917c00SJeff Kirsher 			addr = t3_read_reg(adapter,
1762f7917c00SJeff Kirsher 					   mc7->offset + A_MC7_ERR_ADDR);
1763f7917c00SJeff Kirsher 		mc7->stats.addr_err++;
1764f7917c00SJeff Kirsher 		CH_ALERT(adapter, "%s MC7 address error: 0x%x\n",
1765f7917c00SJeff Kirsher 			 mc7->name, addr);
1766f7917c00SJeff Kirsher 	}
1767f7917c00SJeff Kirsher 
1768f7917c00SJeff Kirsher 	if (cause & MC7_INTR_FATAL)
1769f7917c00SJeff Kirsher 		t3_fatal_err(adapter);
1770f7917c00SJeff Kirsher 
1771f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_INT_CAUSE, cause);
1772f7917c00SJeff Kirsher }
1773f7917c00SJeff Kirsher 
1774f7917c00SJeff Kirsher #define XGM_INTR_FATAL (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \
1775f7917c00SJeff Kirsher 			V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR))
1776f7917c00SJeff Kirsher /*
1777f7917c00SJeff Kirsher  * XGMAC interrupt handler.
1778f7917c00SJeff Kirsher  */
mac_intr_handler(struct adapter * adap,unsigned int idx)1779f7917c00SJeff Kirsher static int mac_intr_handler(struct adapter *adap, unsigned int idx)
1780f7917c00SJeff Kirsher {
1781f7917c00SJeff Kirsher 	struct cmac *mac = &adap2pinfo(adap, idx)->mac;
1782f7917c00SJeff Kirsher 	/*
1783f7917c00SJeff Kirsher 	 * We mask out interrupt causes for which we're not taking interrupts.
1784f7917c00SJeff Kirsher 	 * This allows us to use polling logic to monitor some of the other
1785f7917c00SJeff Kirsher 	 * conditions when taking interrupts would impose too much load on the
1786f7917c00SJeff Kirsher 	 * system.
1787f7917c00SJeff Kirsher 	 */
1788f7917c00SJeff Kirsher 	u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset) &
1789f7917c00SJeff Kirsher 		    ~F_RXFIFO_OVERFLOW;
1790f7917c00SJeff Kirsher 
1791f7917c00SJeff Kirsher 	if (cause & V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR)) {
1792f7917c00SJeff Kirsher 		mac->stats.tx_fifo_parity_err++;
1793f7917c00SJeff Kirsher 		CH_ALERT(adap, "port%d: MAC TX FIFO parity error\n", idx);
1794f7917c00SJeff Kirsher 	}
1795f7917c00SJeff Kirsher 	if (cause & V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR)) {
1796f7917c00SJeff Kirsher 		mac->stats.rx_fifo_parity_err++;
1797f7917c00SJeff Kirsher 		CH_ALERT(adap, "port%d: MAC RX FIFO parity error\n", idx);
1798f7917c00SJeff Kirsher 	}
1799f7917c00SJeff Kirsher 	if (cause & F_TXFIFO_UNDERRUN)
1800f7917c00SJeff Kirsher 		mac->stats.tx_fifo_urun++;
1801f7917c00SJeff Kirsher 	if (cause & F_RXFIFO_OVERFLOW)
1802f7917c00SJeff Kirsher 		mac->stats.rx_fifo_ovfl++;
1803f7917c00SJeff Kirsher 	if (cause & V_SERDES_LOS(M_SERDES_LOS))
1804f7917c00SJeff Kirsher 		mac->stats.serdes_signal_loss++;
1805f7917c00SJeff Kirsher 	if (cause & F_XAUIPCSCTCERR)
1806f7917c00SJeff Kirsher 		mac->stats.xaui_pcs_ctc_err++;
1807f7917c00SJeff Kirsher 	if (cause & F_XAUIPCSALIGNCHANGE)
1808f7917c00SJeff Kirsher 		mac->stats.xaui_pcs_align_change++;
1809f7917c00SJeff Kirsher 	if (cause & F_XGM_INT) {
1810f7917c00SJeff Kirsher 		t3_set_reg_field(adap,
1811f7917c00SJeff Kirsher 				 A_XGM_INT_ENABLE + mac->offset,
1812f7917c00SJeff Kirsher 				 F_XGM_INT, 0);
1813f7917c00SJeff Kirsher 		mac->stats.link_faults++;
1814f7917c00SJeff Kirsher 
1815f7917c00SJeff Kirsher 		t3_os_link_fault_handler(adap, idx);
1816f7917c00SJeff Kirsher 	}
1817f7917c00SJeff Kirsher 
1818f7917c00SJeff Kirsher 	if (cause & XGM_INTR_FATAL)
1819f7917c00SJeff Kirsher 		t3_fatal_err(adap);
1820f7917c00SJeff Kirsher 
1821f7917c00SJeff Kirsher 	t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause);
1822f7917c00SJeff Kirsher 	return cause != 0;
1823f7917c00SJeff Kirsher }
1824f7917c00SJeff Kirsher 
1825f7917c00SJeff Kirsher /*
1826f7917c00SJeff Kirsher  * Interrupt handler for PHY events.
1827f7917c00SJeff Kirsher  */
t3_phy_intr_handler(struct adapter * adapter)1828f7917c00SJeff Kirsher int t3_phy_intr_handler(struct adapter *adapter)
1829f7917c00SJeff Kirsher {
1830f7917c00SJeff Kirsher 	u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE);
1831f7917c00SJeff Kirsher 
1832f7917c00SJeff Kirsher 	for_each_port(adapter, i) {
1833f7917c00SJeff Kirsher 		struct port_info *p = adap2pinfo(adapter, i);
1834f7917c00SJeff Kirsher 
1835f7917c00SJeff Kirsher 		if (!(p->phy.caps & SUPPORTED_IRQ))
1836f7917c00SJeff Kirsher 			continue;
1837f7917c00SJeff Kirsher 
1838f7917c00SJeff Kirsher 		if (cause & (1 << adapter_info(adapter)->gpio_intr[i])) {
1839f7917c00SJeff Kirsher 			int phy_cause = p->phy.ops->intr_handler(&p->phy);
1840f7917c00SJeff Kirsher 
1841f7917c00SJeff Kirsher 			if (phy_cause & cphy_cause_link_change)
1842f7917c00SJeff Kirsher 				t3_link_changed(adapter, i);
1843f7917c00SJeff Kirsher 			if (phy_cause & cphy_cause_fifo_error)
1844f7917c00SJeff Kirsher 				p->phy.fifo_errors++;
1845f7917c00SJeff Kirsher 			if (phy_cause & cphy_cause_module_change)
1846f7917c00SJeff Kirsher 				t3_os_phymod_changed(adapter, i);
1847f7917c00SJeff Kirsher 		}
1848f7917c00SJeff Kirsher 	}
1849f7917c00SJeff Kirsher 
1850f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_T3DBG_INT_CAUSE, cause);
1851f7917c00SJeff Kirsher 	return 0;
1852f7917c00SJeff Kirsher }
1853f7917c00SJeff Kirsher 
1854f7917c00SJeff Kirsher /*
1855f7917c00SJeff Kirsher  * T3 slow path (non-data) interrupt handler.
1856f7917c00SJeff Kirsher  */
t3_slow_intr_handler(struct adapter * adapter)1857f7917c00SJeff Kirsher int t3_slow_intr_handler(struct adapter *adapter)
1858f7917c00SJeff Kirsher {
1859f7917c00SJeff Kirsher 	u32 cause = t3_read_reg(adapter, A_PL_INT_CAUSE0);
1860f7917c00SJeff Kirsher 
1861f7917c00SJeff Kirsher 	cause &= adapter->slow_intr_mask;
1862f7917c00SJeff Kirsher 	if (!cause)
1863f7917c00SJeff Kirsher 		return 0;
1864f7917c00SJeff Kirsher 	if (cause & F_PCIM0) {
1865f7917c00SJeff Kirsher 		if (is_pcie(adapter))
1866f7917c00SJeff Kirsher 			pcie_intr_handler(adapter);
1867f7917c00SJeff Kirsher 		else
1868f7917c00SJeff Kirsher 			pci_intr_handler(adapter);
1869f7917c00SJeff Kirsher 	}
1870f7917c00SJeff Kirsher 	if (cause & F_SGE3)
1871f7917c00SJeff Kirsher 		t3_sge_err_intr_handler(adapter);
1872f7917c00SJeff Kirsher 	if (cause & F_MC7_PMRX)
1873f7917c00SJeff Kirsher 		mc7_intr_handler(&adapter->pmrx);
1874f7917c00SJeff Kirsher 	if (cause & F_MC7_PMTX)
1875f7917c00SJeff Kirsher 		mc7_intr_handler(&adapter->pmtx);
1876f7917c00SJeff Kirsher 	if (cause & F_MC7_CM)
1877f7917c00SJeff Kirsher 		mc7_intr_handler(&adapter->cm);
1878f7917c00SJeff Kirsher 	if (cause & F_CIM)
1879f7917c00SJeff Kirsher 		cim_intr_handler(adapter);
1880f7917c00SJeff Kirsher 	if (cause & F_TP1)
1881f7917c00SJeff Kirsher 		tp_intr_handler(adapter);
1882f7917c00SJeff Kirsher 	if (cause & F_ULP2_RX)
1883f7917c00SJeff Kirsher 		ulprx_intr_handler(adapter);
1884f7917c00SJeff Kirsher 	if (cause & F_ULP2_TX)
1885f7917c00SJeff Kirsher 		ulptx_intr_handler(adapter);
1886f7917c00SJeff Kirsher 	if (cause & F_PM1_RX)
1887f7917c00SJeff Kirsher 		pmrx_intr_handler(adapter);
1888f7917c00SJeff Kirsher 	if (cause & F_PM1_TX)
1889f7917c00SJeff Kirsher 		pmtx_intr_handler(adapter);
1890f7917c00SJeff Kirsher 	if (cause & F_CPL_SWITCH)
1891f7917c00SJeff Kirsher 		cplsw_intr_handler(adapter);
1892f7917c00SJeff Kirsher 	if (cause & F_MPS0)
1893f7917c00SJeff Kirsher 		mps_intr_handler(adapter);
1894f7917c00SJeff Kirsher 	if (cause & F_MC5A)
1895f7917c00SJeff Kirsher 		t3_mc5_intr_handler(&adapter->mc5);
1896f7917c00SJeff Kirsher 	if (cause & F_XGMAC0_0)
1897f7917c00SJeff Kirsher 		mac_intr_handler(adapter, 0);
1898f7917c00SJeff Kirsher 	if (cause & F_XGMAC0_1)
1899f7917c00SJeff Kirsher 		mac_intr_handler(adapter, 1);
1900f7917c00SJeff Kirsher 	if (cause & F_T3DBG)
1901f7917c00SJeff Kirsher 		t3_os_ext_intr_handler(adapter);
1902f7917c00SJeff Kirsher 
1903f7917c00SJeff Kirsher 	/* Clear the interrupts just processed. */
1904f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_PL_INT_CAUSE0, cause);
1905f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_PL_INT_CAUSE0);	/* flush */
1906f7917c00SJeff Kirsher 	return 1;
1907f7917c00SJeff Kirsher }
1908f7917c00SJeff Kirsher 
calc_gpio_intr(struct adapter * adap)1909f7917c00SJeff Kirsher static unsigned int calc_gpio_intr(struct adapter *adap)
1910f7917c00SJeff Kirsher {
1911f7917c00SJeff Kirsher 	unsigned int i, gpi_intr = 0;
1912f7917c00SJeff Kirsher 
1913f7917c00SJeff Kirsher 	for_each_port(adap, i)
1914f7917c00SJeff Kirsher 		if ((adap2pinfo(adap, i)->phy.caps & SUPPORTED_IRQ) &&
1915f7917c00SJeff Kirsher 		    adapter_info(adap)->gpio_intr[i])
1916f7917c00SJeff Kirsher 			gpi_intr |= 1 << adapter_info(adap)->gpio_intr[i];
1917f7917c00SJeff Kirsher 	return gpi_intr;
1918f7917c00SJeff Kirsher }
1919f7917c00SJeff Kirsher 
1920f7917c00SJeff Kirsher /**
1921f7917c00SJeff Kirsher  *	t3_intr_enable - enable interrupts
1922f7917c00SJeff Kirsher  *	@adapter: the adapter whose interrupts should be enabled
1923f7917c00SJeff Kirsher  *
1924f7917c00SJeff Kirsher  *	Enable interrupts by setting the interrupt enable registers of the
1925f7917c00SJeff Kirsher  *	various HW modules and then enabling the top-level interrupt
1926f7917c00SJeff Kirsher  *	concentrator.
1927f7917c00SJeff Kirsher  */
t3_intr_enable(struct adapter * adapter)1928f7917c00SJeff Kirsher void t3_intr_enable(struct adapter *adapter)
1929f7917c00SJeff Kirsher {
1930f7917c00SJeff Kirsher 	static const struct addr_val_pair intr_en_avp[] = {
1931f7917c00SJeff Kirsher 		{A_SG_INT_ENABLE, SGE_INTR_MASK},
1932f7917c00SJeff Kirsher 		{A_MC7_INT_ENABLE, MC7_INTR_MASK},
1933f7917c00SJeff Kirsher 		{A_MC7_INT_ENABLE - MC7_PMRX_BASE_ADDR + MC7_PMTX_BASE_ADDR,
1934f7917c00SJeff Kirsher 		 MC7_INTR_MASK},
1935f7917c00SJeff Kirsher 		{A_MC7_INT_ENABLE - MC7_PMRX_BASE_ADDR + MC7_CM_BASE_ADDR,
1936f7917c00SJeff Kirsher 		 MC7_INTR_MASK},
1937f7917c00SJeff Kirsher 		{A_MC5_DB_INT_ENABLE, MC5_INTR_MASK},
1938f7917c00SJeff Kirsher 		{A_ULPRX_INT_ENABLE, ULPRX_INTR_MASK},
1939f7917c00SJeff Kirsher 		{A_PM1_TX_INT_ENABLE, PMTX_INTR_MASK},
1940f7917c00SJeff Kirsher 		{A_PM1_RX_INT_ENABLE, PMRX_INTR_MASK},
1941f7917c00SJeff Kirsher 		{A_CIM_HOST_INT_ENABLE, CIM_INTR_MASK},
1942f7917c00SJeff Kirsher 		{A_MPS_INT_ENABLE, MPS_INTR_MASK},
1943f7917c00SJeff Kirsher 	};
1944f7917c00SJeff Kirsher 
1945f7917c00SJeff Kirsher 	adapter->slow_intr_mask = PL_INTR_MASK;
1946f7917c00SJeff Kirsher 
1947f7917c00SJeff Kirsher 	t3_write_regs(adapter, intr_en_avp, ARRAY_SIZE(intr_en_avp), 0);
1948f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_TP_INT_ENABLE,
1949f7917c00SJeff Kirsher 		     adapter->params.rev >= T3_REV_C ? 0x2bfffff : 0x3bfffff);
1950f7917c00SJeff Kirsher 
1951f7917c00SJeff Kirsher 	if (adapter->params.rev > 0) {
1952f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_CPL_INTR_ENABLE,
1953f7917c00SJeff Kirsher 			     CPLSW_INTR_MASK | F_CIM_OVFL_ERROR);
1954f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_ULPTX_INT_ENABLE,
1955f7917c00SJeff Kirsher 			     ULPTX_INTR_MASK | F_PBL_BOUND_ERR_CH0 |
1956f7917c00SJeff Kirsher 			     F_PBL_BOUND_ERR_CH1);
1957f7917c00SJeff Kirsher 	} else {
1958f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_CPL_INTR_ENABLE, CPLSW_INTR_MASK);
1959f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK);
1960f7917c00SJeff Kirsher 	}
1961f7917c00SJeff Kirsher 
1962f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_T3DBG_INT_ENABLE, calc_gpio_intr(adapter));
1963f7917c00SJeff Kirsher 
1964f7917c00SJeff Kirsher 	if (is_pcie(adapter))
1965f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK);
1966f7917c00SJeff Kirsher 	else
1967f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_PCIX_INT_ENABLE, PCIX_INTR_MASK);
1968f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_PL_INT_ENABLE0, adapter->slow_intr_mask);
1969f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_PL_INT_ENABLE0);	/* flush */
1970f7917c00SJeff Kirsher }
1971f7917c00SJeff Kirsher 
1972f7917c00SJeff Kirsher /**
1973f7917c00SJeff Kirsher  *	t3_intr_disable - disable a card's interrupts
1974f7917c00SJeff Kirsher  *	@adapter: the adapter whose interrupts should be disabled
1975f7917c00SJeff Kirsher  *
1976f7917c00SJeff Kirsher  *	Disable interrupts.  We only disable the top-level interrupt
1977f7917c00SJeff Kirsher  *	concentrator and the SGE data interrupts.
1978f7917c00SJeff Kirsher  */
t3_intr_disable(struct adapter * adapter)1979f7917c00SJeff Kirsher void t3_intr_disable(struct adapter *adapter)
1980f7917c00SJeff Kirsher {
1981f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_PL_INT_ENABLE0, 0);
1982f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_PL_INT_ENABLE0);	/* flush */
1983f7917c00SJeff Kirsher 	adapter->slow_intr_mask = 0;
1984f7917c00SJeff Kirsher }
1985f7917c00SJeff Kirsher 
1986f7917c00SJeff Kirsher /**
1987f7917c00SJeff Kirsher  *	t3_intr_clear - clear all interrupts
1988f7917c00SJeff Kirsher  *	@adapter: the adapter whose interrupts should be cleared
1989f7917c00SJeff Kirsher  *
1990f7917c00SJeff Kirsher  *	Clears all interrupts.
1991f7917c00SJeff Kirsher  */
t3_intr_clear(struct adapter * adapter)1992f7917c00SJeff Kirsher void t3_intr_clear(struct adapter *adapter)
1993f7917c00SJeff Kirsher {
1994f7917c00SJeff Kirsher 	static const unsigned int cause_reg_addr[] = {
1995f7917c00SJeff Kirsher 		A_SG_INT_CAUSE,
1996f7917c00SJeff Kirsher 		A_SG_RSPQ_FL_STATUS,
1997f7917c00SJeff Kirsher 		A_PCIX_INT_CAUSE,
1998f7917c00SJeff Kirsher 		A_MC7_INT_CAUSE,
1999f7917c00SJeff Kirsher 		A_MC7_INT_CAUSE - MC7_PMRX_BASE_ADDR + MC7_PMTX_BASE_ADDR,
2000f7917c00SJeff Kirsher 		A_MC7_INT_CAUSE - MC7_PMRX_BASE_ADDR + MC7_CM_BASE_ADDR,
2001f7917c00SJeff Kirsher 		A_CIM_HOST_INT_CAUSE,
2002f7917c00SJeff Kirsher 		A_TP_INT_CAUSE,
2003f7917c00SJeff Kirsher 		A_MC5_DB_INT_CAUSE,
2004f7917c00SJeff Kirsher 		A_ULPRX_INT_CAUSE,
2005f7917c00SJeff Kirsher 		A_ULPTX_INT_CAUSE,
2006f7917c00SJeff Kirsher 		A_CPL_INTR_CAUSE,
2007f7917c00SJeff Kirsher 		A_PM1_TX_INT_CAUSE,
2008f7917c00SJeff Kirsher 		A_PM1_RX_INT_CAUSE,
2009f7917c00SJeff Kirsher 		A_MPS_INT_CAUSE,
2010f7917c00SJeff Kirsher 		A_T3DBG_INT_CAUSE,
2011f7917c00SJeff Kirsher 	};
2012f7917c00SJeff Kirsher 	unsigned int i;
2013f7917c00SJeff Kirsher 
2014f7917c00SJeff Kirsher 	/* Clear PHY and MAC interrupts for each port. */
2015f7917c00SJeff Kirsher 	for_each_port(adapter, i)
2016f7917c00SJeff Kirsher 	    t3_port_intr_clear(adapter, i);
2017f7917c00SJeff Kirsher 
2018f7917c00SJeff Kirsher 	for (i = 0; i < ARRAY_SIZE(cause_reg_addr); ++i)
2019f7917c00SJeff Kirsher 		t3_write_reg(adapter, cause_reg_addr[i], 0xffffffff);
2020f7917c00SJeff Kirsher 
2021f7917c00SJeff Kirsher 	if (is_pcie(adapter))
2022f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_PCIE_PEX_ERR, 0xffffffff);
2023f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_PL_INT_CAUSE0, 0xffffffff);
2024f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_PL_INT_CAUSE0);	/* flush */
2025f7917c00SJeff Kirsher }
2026f7917c00SJeff Kirsher 
t3_xgm_intr_enable(struct adapter * adapter,int idx)2027f7917c00SJeff Kirsher void t3_xgm_intr_enable(struct adapter *adapter, int idx)
2028f7917c00SJeff Kirsher {
2029f7917c00SJeff Kirsher 	struct port_info *pi = adap2pinfo(adapter, idx);
2030f7917c00SJeff Kirsher 
2031f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_XGM_XGM_INT_ENABLE + pi->mac.offset,
2032f7917c00SJeff Kirsher 		     XGM_EXTRA_INTR_MASK);
2033f7917c00SJeff Kirsher }
2034f7917c00SJeff Kirsher 
t3_xgm_intr_disable(struct adapter * adapter,int idx)2035f7917c00SJeff Kirsher void t3_xgm_intr_disable(struct adapter *adapter, int idx)
2036f7917c00SJeff Kirsher {
2037f7917c00SJeff Kirsher 	struct port_info *pi = adap2pinfo(adapter, idx);
2038f7917c00SJeff Kirsher 
2039f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_XGM_XGM_INT_DISABLE + pi->mac.offset,
2040f7917c00SJeff Kirsher 		     0x7ff);
2041f7917c00SJeff Kirsher }
2042f7917c00SJeff Kirsher 
2043f7917c00SJeff Kirsher /**
2044f7917c00SJeff Kirsher  *	t3_port_intr_enable - enable port-specific interrupts
2045f7917c00SJeff Kirsher  *	@adapter: associated adapter
2046f7917c00SJeff Kirsher  *	@idx: index of port whose interrupts should be enabled
2047f7917c00SJeff Kirsher  *
2048f7917c00SJeff Kirsher  *	Enable port-specific (i.e., MAC and PHY) interrupts for the given
2049f7917c00SJeff Kirsher  *	adapter port.
2050f7917c00SJeff Kirsher  */
t3_port_intr_enable(struct adapter * adapter,int idx)2051f7917c00SJeff Kirsher void t3_port_intr_enable(struct adapter *adapter, int idx)
2052f7917c00SJeff Kirsher {
2053f7917c00SJeff Kirsher 	struct cphy *phy = &adap2pinfo(adapter, idx)->phy;
2054f7917c00SJeff Kirsher 
2055f7917c00SJeff Kirsher 	t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), XGM_INTR_MASK);
2056f7917c00SJeff Kirsher 	t3_read_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx)); /* flush */
2057f7917c00SJeff Kirsher 	phy->ops->intr_enable(phy);
2058f7917c00SJeff Kirsher }
2059f7917c00SJeff Kirsher 
2060f7917c00SJeff Kirsher /**
2061f7917c00SJeff Kirsher  *	t3_port_intr_disable - disable port-specific interrupts
2062f7917c00SJeff Kirsher  *	@adapter: associated adapter
2063f7917c00SJeff Kirsher  *	@idx: index of port whose interrupts should be disabled
2064f7917c00SJeff Kirsher  *
2065f7917c00SJeff Kirsher  *	Disable port-specific (i.e., MAC and PHY) interrupts for the given
2066f7917c00SJeff Kirsher  *	adapter port.
2067f7917c00SJeff Kirsher  */
t3_port_intr_disable(struct adapter * adapter,int idx)2068f7917c00SJeff Kirsher void t3_port_intr_disable(struct adapter *adapter, int idx)
2069f7917c00SJeff Kirsher {
2070f7917c00SJeff Kirsher 	struct cphy *phy = &adap2pinfo(adapter, idx)->phy;
2071f7917c00SJeff Kirsher 
2072f7917c00SJeff Kirsher 	t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), 0);
2073f7917c00SJeff Kirsher 	t3_read_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx)); /* flush */
2074f7917c00SJeff Kirsher 	phy->ops->intr_disable(phy);
2075f7917c00SJeff Kirsher }
2076f7917c00SJeff Kirsher 
2077f7917c00SJeff Kirsher /**
2078f7917c00SJeff Kirsher  *	t3_port_intr_clear - clear port-specific interrupts
2079f7917c00SJeff Kirsher  *	@adapter: associated adapter
2080f7917c00SJeff Kirsher  *	@idx: index of port whose interrupts to clear
2081f7917c00SJeff Kirsher  *
2082f7917c00SJeff Kirsher  *	Clear port-specific (i.e., MAC and PHY) interrupts for the given
2083f7917c00SJeff Kirsher  *	adapter port.
2084f7917c00SJeff Kirsher  */
t3_port_intr_clear(struct adapter * adapter,int idx)2085f7917c00SJeff Kirsher static void t3_port_intr_clear(struct adapter *adapter, int idx)
2086f7917c00SJeff Kirsher {
2087f7917c00SJeff Kirsher 	struct cphy *phy = &adap2pinfo(adapter, idx)->phy;
2088f7917c00SJeff Kirsher 
2089f7917c00SJeff Kirsher 	t3_write_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx), 0xffffffff);
2090f7917c00SJeff Kirsher 	t3_read_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx)); /* flush */
2091f7917c00SJeff Kirsher 	phy->ops->intr_clear(phy);
2092f7917c00SJeff Kirsher }
2093f7917c00SJeff Kirsher 
2094f7917c00SJeff Kirsher #define SG_CONTEXT_CMD_ATTEMPTS 100
2095f7917c00SJeff Kirsher 
2096f7917c00SJeff Kirsher /**
2097f7917c00SJeff Kirsher  * 	t3_sge_write_context - write an SGE context
2098f7917c00SJeff Kirsher  * 	@adapter: the adapter
2099f7917c00SJeff Kirsher  * 	@id: the context id
2100f7917c00SJeff Kirsher  * 	@type: the context type
2101f7917c00SJeff Kirsher  *
2102f7917c00SJeff Kirsher  * 	Program an SGE context with the values already loaded in the
2103f7917c00SJeff Kirsher  * 	CONTEXT_DATA? registers.
2104f7917c00SJeff Kirsher  */
t3_sge_write_context(struct adapter * adapter,unsigned int id,unsigned int type)2105f7917c00SJeff Kirsher static int t3_sge_write_context(struct adapter *adapter, unsigned int id,
2106f7917c00SJeff Kirsher 				unsigned int type)
2107f7917c00SJeff Kirsher {
2108f7917c00SJeff Kirsher 	if (type == F_RESPONSEQ) {
2109f7917c00SJeff Kirsher 		/*
2110f7917c00SJeff Kirsher 		 * Can't write the Response Queue Context bits for
2111f7917c00SJeff Kirsher 		 * Interrupt Armed or the Reserve bits after the chip
2112f7917c00SJeff Kirsher 		 * has been initialized out of reset.  Writing to these
2113f7917c00SJeff Kirsher 		 * bits can confuse the hardware.
2114f7917c00SJeff Kirsher 		 */
2115f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff);
2116f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff);
2117f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0x17ffffff);
2118f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff);
2119f7917c00SJeff Kirsher 	} else {
2120f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff);
2121f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff);
2122f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0xffffffff);
2123f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff);
2124f7917c00SJeff Kirsher 	}
2125f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
2126f7917c00SJeff Kirsher 		     V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id));
2127f7917c00SJeff Kirsher 	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
2128f7917c00SJeff Kirsher 			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
2129f7917c00SJeff Kirsher }
2130f7917c00SJeff Kirsher 
2131f7917c00SJeff Kirsher /**
2132f7917c00SJeff Kirsher  *	clear_sge_ctxt - completely clear an SGE context
213345677bc6SWang Hai  *	@adap: the adapter
2134f7917c00SJeff Kirsher  *	@id: the context id
2135f7917c00SJeff Kirsher  *	@type: the context type
2136f7917c00SJeff Kirsher  *
2137f7917c00SJeff Kirsher  *	Completely clear an SGE context.  Used predominantly at post-reset
2138f7917c00SJeff Kirsher  *	initialization.  Note in particular that we don't skip writing to any
2139f7917c00SJeff Kirsher  *	"sensitive bits" in the contexts the way that t3_sge_write_context()
2140f7917c00SJeff Kirsher  *	does ...
2141f7917c00SJeff Kirsher  */
clear_sge_ctxt(struct adapter * adap,unsigned int id,unsigned int type)2142f7917c00SJeff Kirsher static int clear_sge_ctxt(struct adapter *adap, unsigned int id,
2143f7917c00SJeff Kirsher 			  unsigned int type)
2144f7917c00SJeff Kirsher {
2145f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_DATA0, 0);
2146f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_DATA1, 0);
2147f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_DATA2, 0);
2148f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_DATA3, 0);
2149f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_MASK0, 0xffffffff);
2150f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_MASK1, 0xffffffff);
2151f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_MASK2, 0xffffffff);
2152f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_MASK3, 0xffffffff);
2153f7917c00SJeff Kirsher 	t3_write_reg(adap, A_SG_CONTEXT_CMD,
2154f7917c00SJeff Kirsher 		     V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id));
2155f7917c00SJeff Kirsher 	return t3_wait_op_done(adap, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
2156f7917c00SJeff Kirsher 			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
2157f7917c00SJeff Kirsher }
2158f7917c00SJeff Kirsher 
2159f7917c00SJeff Kirsher /**
2160f7917c00SJeff Kirsher  *	t3_sge_init_ecntxt - initialize an SGE egress context
2161f7917c00SJeff Kirsher  *	@adapter: the adapter to configure
2162f7917c00SJeff Kirsher  *	@id: the context id
2163f7917c00SJeff Kirsher  *	@gts_enable: whether to enable GTS for the context
2164f7917c00SJeff Kirsher  *	@type: the egress context type
2165f7917c00SJeff Kirsher  *	@respq: associated response queue
2166f7917c00SJeff Kirsher  *	@base_addr: base address of queue
2167f7917c00SJeff Kirsher  *	@size: number of queue entries
2168f7917c00SJeff Kirsher  *	@token: uP token
2169f7917c00SJeff Kirsher  *	@gen: initial generation value for the context
2170f7917c00SJeff Kirsher  *	@cidx: consumer pointer
2171f7917c00SJeff Kirsher  *
2172f7917c00SJeff Kirsher  *	Initialize an SGE egress context and make it ready for use.  If the
2173f7917c00SJeff Kirsher  *	platform allows concurrent context operations, the caller is
2174f7917c00SJeff Kirsher  *	responsible for appropriate locking.
2175f7917c00SJeff Kirsher  */
t3_sge_init_ecntxt(struct adapter * adapter,unsigned int id,int gts_enable,enum sge_context_type type,int respq,u64 base_addr,unsigned int size,unsigned int token,int gen,unsigned int cidx)2176f7917c00SJeff Kirsher int t3_sge_init_ecntxt(struct adapter *adapter, unsigned int id, int gts_enable,
2177f7917c00SJeff Kirsher 		       enum sge_context_type type, int respq, u64 base_addr,
2178f7917c00SJeff Kirsher 		       unsigned int size, unsigned int token, int gen,
2179f7917c00SJeff Kirsher 		       unsigned int cidx)
2180f7917c00SJeff Kirsher {
2181f7917c00SJeff Kirsher 	unsigned int credits = type == SGE_CNTXT_OFLD ? 0 : FW_WR_NUM;
2182f7917c00SJeff Kirsher 
2183f7917c00SJeff Kirsher 	if (base_addr & 0xfff)	/* must be 4K aligned */
2184f7917c00SJeff Kirsher 		return -EINVAL;
2185f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2186f7917c00SJeff Kirsher 		return -EBUSY;
2187f7917c00SJeff Kirsher 
2188f7917c00SJeff Kirsher 	base_addr >>= 12;
2189f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_EC_INDEX(cidx) |
2190f7917c00SJeff Kirsher 		     V_EC_CREDITS(credits) | V_EC_GTS(gts_enable));
2191f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA1, V_EC_SIZE(size) |
2192f7917c00SJeff Kirsher 		     V_EC_BASE_LO(base_addr & 0xffff));
2193f7917c00SJeff Kirsher 	base_addr >>= 16;
2194f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA2, base_addr);
2195f7917c00SJeff Kirsher 	base_addr >>= 32;
2196f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA3,
2197f7917c00SJeff Kirsher 		     V_EC_BASE_HI(base_addr & 0xf) | V_EC_RESPQ(respq) |
2198f7917c00SJeff Kirsher 		     V_EC_TYPE(type) | V_EC_GEN(gen) | V_EC_UP_TOKEN(token) |
2199f7917c00SJeff Kirsher 		     F_EC_VALID);
2200f7917c00SJeff Kirsher 	return t3_sge_write_context(adapter, id, F_EGRESS);
2201f7917c00SJeff Kirsher }
2202f7917c00SJeff Kirsher 
2203f7917c00SJeff Kirsher /**
2204f7917c00SJeff Kirsher  *	t3_sge_init_flcntxt - initialize an SGE free-buffer list context
2205f7917c00SJeff Kirsher  *	@adapter: the adapter to configure
2206f7917c00SJeff Kirsher  *	@id: the context id
2207f7917c00SJeff Kirsher  *	@gts_enable: whether to enable GTS for the context
2208f7917c00SJeff Kirsher  *	@base_addr: base address of queue
2209f7917c00SJeff Kirsher  *	@size: number of queue entries
2210f7917c00SJeff Kirsher  *	@bsize: size of each buffer for this queue
2211f7917c00SJeff Kirsher  *	@cong_thres: threshold to signal congestion to upstream producers
2212f7917c00SJeff Kirsher  *	@gen: initial generation value for the context
2213f7917c00SJeff Kirsher  *	@cidx: consumer pointer
2214f7917c00SJeff Kirsher  *
2215f7917c00SJeff Kirsher  *	Initialize an SGE free list context and make it ready for use.  The
2216f7917c00SJeff Kirsher  *	caller is responsible for ensuring only one context operation occurs
2217f7917c00SJeff Kirsher  *	at a time.
2218f7917c00SJeff Kirsher  */
t3_sge_init_flcntxt(struct adapter * adapter,unsigned int id,int gts_enable,u64 base_addr,unsigned int size,unsigned int bsize,unsigned int cong_thres,int gen,unsigned int cidx)2219f7917c00SJeff Kirsher int t3_sge_init_flcntxt(struct adapter *adapter, unsigned int id,
2220f7917c00SJeff Kirsher 			int gts_enable, u64 base_addr, unsigned int size,
2221f7917c00SJeff Kirsher 			unsigned int bsize, unsigned int cong_thres, int gen,
2222f7917c00SJeff Kirsher 			unsigned int cidx)
2223f7917c00SJeff Kirsher {
2224f7917c00SJeff Kirsher 	if (base_addr & 0xfff)	/* must be 4K aligned */
2225f7917c00SJeff Kirsher 		return -EINVAL;
2226f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2227f7917c00SJeff Kirsher 		return -EBUSY;
2228f7917c00SJeff Kirsher 
2229f7917c00SJeff Kirsher 	base_addr >>= 12;
2230f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, base_addr);
2231f7917c00SJeff Kirsher 	base_addr >>= 32;
2232f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA1,
2233f7917c00SJeff Kirsher 		     V_FL_BASE_HI((u32) base_addr) |
2234f7917c00SJeff Kirsher 		     V_FL_INDEX_LO(cidx & M_FL_INDEX_LO));
2235f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA2, V_FL_SIZE(size) |
2236f7917c00SJeff Kirsher 		     V_FL_GEN(gen) | V_FL_INDEX_HI(cidx >> 12) |
2237f7917c00SJeff Kirsher 		     V_FL_ENTRY_SIZE_LO(bsize & M_FL_ENTRY_SIZE_LO));
2238f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA3,
2239f7917c00SJeff Kirsher 		     V_FL_ENTRY_SIZE_HI(bsize >> (32 - S_FL_ENTRY_SIZE_LO)) |
2240f7917c00SJeff Kirsher 		     V_FL_CONG_THRES(cong_thres) | V_FL_GTS(gts_enable));
2241f7917c00SJeff Kirsher 	return t3_sge_write_context(adapter, id, F_FREELIST);
2242f7917c00SJeff Kirsher }
2243f7917c00SJeff Kirsher 
2244f7917c00SJeff Kirsher /**
2245f7917c00SJeff Kirsher  *	t3_sge_init_rspcntxt - initialize an SGE response queue context
2246f7917c00SJeff Kirsher  *	@adapter: the adapter to configure
2247f7917c00SJeff Kirsher  *	@id: the context id
2248f7917c00SJeff Kirsher  *	@irq_vec_idx: MSI-X interrupt vector index, 0 if no MSI-X, -1 if no IRQ
2249f7917c00SJeff Kirsher  *	@base_addr: base address of queue
2250f7917c00SJeff Kirsher  *	@size: number of queue entries
2251f7917c00SJeff Kirsher  *	@fl_thres: threshold for selecting the normal or jumbo free list
2252f7917c00SJeff Kirsher  *	@gen: initial generation value for the context
2253f7917c00SJeff Kirsher  *	@cidx: consumer pointer
2254f7917c00SJeff Kirsher  *
2255f7917c00SJeff Kirsher  *	Initialize an SGE response queue context and make it ready for use.
2256f7917c00SJeff Kirsher  *	The caller is responsible for ensuring only one context operation
2257f7917c00SJeff Kirsher  *	occurs at a time.
2258f7917c00SJeff Kirsher  */
t3_sge_init_rspcntxt(struct adapter * adapter,unsigned int id,int irq_vec_idx,u64 base_addr,unsigned int size,unsigned int fl_thres,int gen,unsigned int cidx)2259f7917c00SJeff Kirsher int t3_sge_init_rspcntxt(struct adapter *adapter, unsigned int id,
2260f7917c00SJeff Kirsher 			 int irq_vec_idx, u64 base_addr, unsigned int size,
2261f7917c00SJeff Kirsher 			 unsigned int fl_thres, int gen, unsigned int cidx)
2262f7917c00SJeff Kirsher {
2263f7917c00SJeff Kirsher 	unsigned int intr = 0;
2264f7917c00SJeff Kirsher 
2265f7917c00SJeff Kirsher 	if (base_addr & 0xfff)	/* must be 4K aligned */
2266f7917c00SJeff Kirsher 		return -EINVAL;
2267f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2268f7917c00SJeff Kirsher 		return -EBUSY;
2269f7917c00SJeff Kirsher 
2270f7917c00SJeff Kirsher 	base_addr >>= 12;
2271f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_CQ_SIZE(size) |
2272f7917c00SJeff Kirsher 		     V_CQ_INDEX(cidx));
2273f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA1, base_addr);
2274f7917c00SJeff Kirsher 	base_addr >>= 32;
2275f7917c00SJeff Kirsher 	if (irq_vec_idx >= 0)
2276f7917c00SJeff Kirsher 		intr = V_RQ_MSI_VEC(irq_vec_idx) | F_RQ_INTR_EN;
2277f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA2,
2278f7917c00SJeff Kirsher 		     V_CQ_BASE_HI((u32) base_addr) | intr | V_RQ_GEN(gen));
2279f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA3, fl_thres);
2280f7917c00SJeff Kirsher 	return t3_sge_write_context(adapter, id, F_RESPONSEQ);
2281f7917c00SJeff Kirsher }
2282f7917c00SJeff Kirsher 
2283f7917c00SJeff Kirsher /**
2284f7917c00SJeff Kirsher  *	t3_sge_init_cqcntxt - initialize an SGE completion queue context
2285f7917c00SJeff Kirsher  *	@adapter: the adapter to configure
2286f7917c00SJeff Kirsher  *	@id: the context id
2287f7917c00SJeff Kirsher  *	@base_addr: base address of queue
2288f7917c00SJeff Kirsher  *	@size: number of queue entries
2289f7917c00SJeff Kirsher  *	@rspq: response queue for async notifications
2290f7917c00SJeff Kirsher  *	@ovfl_mode: CQ overflow mode
2291f7917c00SJeff Kirsher  *	@credits: completion queue credits
2292f7917c00SJeff Kirsher  *	@credit_thres: the credit threshold
2293f7917c00SJeff Kirsher  *
2294f7917c00SJeff Kirsher  *	Initialize an SGE completion queue context and make it ready for use.
2295f7917c00SJeff Kirsher  *	The caller is responsible for ensuring only one context operation
2296f7917c00SJeff Kirsher  *	occurs at a time.
2297f7917c00SJeff Kirsher  */
t3_sge_init_cqcntxt(struct adapter * adapter,unsigned int id,u64 base_addr,unsigned int size,int rspq,int ovfl_mode,unsigned int credits,unsigned int credit_thres)2298f7917c00SJeff Kirsher int t3_sge_init_cqcntxt(struct adapter *adapter, unsigned int id, u64 base_addr,
2299f7917c00SJeff Kirsher 			unsigned int size, int rspq, int ovfl_mode,
2300f7917c00SJeff Kirsher 			unsigned int credits, unsigned int credit_thres)
2301f7917c00SJeff Kirsher {
2302f7917c00SJeff Kirsher 	if (base_addr & 0xfff)	/* must be 4K aligned */
2303f7917c00SJeff Kirsher 		return -EINVAL;
2304f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2305f7917c00SJeff Kirsher 		return -EBUSY;
2306f7917c00SJeff Kirsher 
2307f7917c00SJeff Kirsher 	base_addr >>= 12;
2308f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_CQ_SIZE(size));
2309f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA1, base_addr);
2310f7917c00SJeff Kirsher 	base_addr >>= 32;
2311f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA2,
2312f7917c00SJeff Kirsher 		     V_CQ_BASE_HI((u32) base_addr) | V_CQ_RSPQ(rspq) |
2313f7917c00SJeff Kirsher 		     V_CQ_GEN(1) | V_CQ_OVERFLOW_MODE(ovfl_mode) |
2314f7917c00SJeff Kirsher 		     V_CQ_ERR(ovfl_mode));
2315f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_CQ_CREDITS(credits) |
2316f7917c00SJeff Kirsher 		     V_CQ_CREDIT_THRES(credit_thres));
2317f7917c00SJeff Kirsher 	return t3_sge_write_context(adapter, id, F_CQ);
2318f7917c00SJeff Kirsher }
2319f7917c00SJeff Kirsher 
2320f7917c00SJeff Kirsher /**
2321f7917c00SJeff Kirsher  *	t3_sge_enable_ecntxt - enable/disable an SGE egress context
2322f7917c00SJeff Kirsher  *	@adapter: the adapter
2323f7917c00SJeff Kirsher  *	@id: the egress context id
2324f7917c00SJeff Kirsher  *	@enable: enable (1) or disable (0) the context
2325f7917c00SJeff Kirsher  *
2326f7917c00SJeff Kirsher  *	Enable or disable an SGE egress context.  The caller is responsible for
2327f7917c00SJeff Kirsher  *	ensuring only one context operation occurs at a time.
2328f7917c00SJeff Kirsher  */
t3_sge_enable_ecntxt(struct adapter * adapter,unsigned int id,int enable)2329f7917c00SJeff Kirsher int t3_sge_enable_ecntxt(struct adapter *adapter, unsigned int id, int enable)
2330f7917c00SJeff Kirsher {
2331f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2332f7917c00SJeff Kirsher 		return -EBUSY;
2333f7917c00SJeff Kirsher 
2334f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0);
2335f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0);
2336f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0);
2337f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK3, F_EC_VALID);
2338f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_EC_VALID(enable));
2339f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
2340f7917c00SJeff Kirsher 		     V_CONTEXT_CMD_OPCODE(1) | F_EGRESS | V_CONTEXT(id));
2341f7917c00SJeff Kirsher 	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
2342f7917c00SJeff Kirsher 			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
2343f7917c00SJeff Kirsher }
2344f7917c00SJeff Kirsher 
2345f7917c00SJeff Kirsher /**
2346f7917c00SJeff Kirsher  *	t3_sge_disable_fl - disable an SGE free-buffer list
2347f7917c00SJeff Kirsher  *	@adapter: the adapter
2348f7917c00SJeff Kirsher  *	@id: the free list context id
2349f7917c00SJeff Kirsher  *
2350f7917c00SJeff Kirsher  *	Disable an SGE free-buffer list.  The caller is responsible for
2351f7917c00SJeff Kirsher  *	ensuring only one context operation occurs at a time.
2352f7917c00SJeff Kirsher  */
t3_sge_disable_fl(struct adapter * adapter,unsigned int id)2353f7917c00SJeff Kirsher int t3_sge_disable_fl(struct adapter *adapter, unsigned int id)
2354f7917c00SJeff Kirsher {
2355f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2356f7917c00SJeff Kirsher 		return -EBUSY;
2357f7917c00SJeff Kirsher 
2358f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0);
2359f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0);
2360f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK2, V_FL_SIZE(M_FL_SIZE));
2361f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0);
2362f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA2, 0);
2363f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
2364f7917c00SJeff Kirsher 		     V_CONTEXT_CMD_OPCODE(1) | F_FREELIST | V_CONTEXT(id));
2365f7917c00SJeff Kirsher 	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
2366f7917c00SJeff Kirsher 			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
2367f7917c00SJeff Kirsher }
2368f7917c00SJeff Kirsher 
2369f7917c00SJeff Kirsher /**
2370f7917c00SJeff Kirsher  *	t3_sge_disable_rspcntxt - disable an SGE response queue
2371f7917c00SJeff Kirsher  *	@adapter: the adapter
2372f7917c00SJeff Kirsher  *	@id: the response queue context id
2373f7917c00SJeff Kirsher  *
2374f7917c00SJeff Kirsher  *	Disable an SGE response queue.  The caller is responsible for
2375f7917c00SJeff Kirsher  *	ensuring only one context operation occurs at a time.
2376f7917c00SJeff Kirsher  */
t3_sge_disable_rspcntxt(struct adapter * adapter,unsigned int id)2377f7917c00SJeff Kirsher int t3_sge_disable_rspcntxt(struct adapter *adapter, unsigned int id)
2378f7917c00SJeff Kirsher {
2379f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2380f7917c00SJeff Kirsher 		return -EBUSY;
2381f7917c00SJeff Kirsher 
2382f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK0, V_CQ_SIZE(M_CQ_SIZE));
2383f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0);
2384f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0);
2385f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0);
2386f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, 0);
2387f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
2388f7917c00SJeff Kirsher 		     V_CONTEXT_CMD_OPCODE(1) | F_RESPONSEQ | V_CONTEXT(id));
2389f7917c00SJeff Kirsher 	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
2390f7917c00SJeff Kirsher 			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
2391f7917c00SJeff Kirsher }
2392f7917c00SJeff Kirsher 
2393f7917c00SJeff Kirsher /**
2394f7917c00SJeff Kirsher  *	t3_sge_disable_cqcntxt - disable an SGE completion queue
2395f7917c00SJeff Kirsher  *	@adapter: the adapter
2396f7917c00SJeff Kirsher  *	@id: the completion queue context id
2397f7917c00SJeff Kirsher  *
2398f7917c00SJeff Kirsher  *	Disable an SGE completion queue.  The caller is responsible for
2399f7917c00SJeff Kirsher  *	ensuring only one context operation occurs at a time.
2400f7917c00SJeff Kirsher  */
t3_sge_disable_cqcntxt(struct adapter * adapter,unsigned int id)2401f7917c00SJeff Kirsher int t3_sge_disable_cqcntxt(struct adapter *adapter, unsigned int id)
2402f7917c00SJeff Kirsher {
2403f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2404f7917c00SJeff Kirsher 		return -EBUSY;
2405f7917c00SJeff Kirsher 
2406f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK0, V_CQ_SIZE(M_CQ_SIZE));
2407f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0);
2408f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0);
2409f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0);
2410f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, 0);
2411f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_CMD,
2412f7917c00SJeff Kirsher 		     V_CONTEXT_CMD_OPCODE(1) | F_CQ | V_CONTEXT(id));
2413f7917c00SJeff Kirsher 	return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
2414f7917c00SJeff Kirsher 			       0, SG_CONTEXT_CMD_ATTEMPTS, 1);
2415f7917c00SJeff Kirsher }
2416f7917c00SJeff Kirsher 
2417f7917c00SJeff Kirsher /**
2418f7917c00SJeff Kirsher  *	t3_sge_cqcntxt_op - perform an operation on a completion queue context
2419f7917c00SJeff Kirsher  *	@adapter: the adapter
2420f7917c00SJeff Kirsher  *	@id: the context id
2421f7917c00SJeff Kirsher  *	@op: the operation to perform
2422d0ea5cbdSJesse Brandeburg  *	@credits: credit value to write
2423f7917c00SJeff Kirsher  *
2424f7917c00SJeff Kirsher  *	Perform the selected operation on an SGE completion queue context.
2425f7917c00SJeff Kirsher  *	The caller is responsible for ensuring only one context operation
2426f7917c00SJeff Kirsher  *	occurs at a time.
2427f7917c00SJeff Kirsher  */
t3_sge_cqcntxt_op(struct adapter * adapter,unsigned int id,unsigned int op,unsigned int credits)2428f7917c00SJeff Kirsher int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op,
2429f7917c00SJeff Kirsher 		      unsigned int credits)
2430f7917c00SJeff Kirsher {
2431f7917c00SJeff Kirsher 	u32 val;
2432f7917c00SJeff Kirsher 
2433f7917c00SJeff Kirsher 	if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
2434f7917c00SJeff Kirsher 		return -EBUSY;
2435f7917c00SJeff Kirsher 
2436f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_DATA0, credits << 16);
2437f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(op) |
2438f7917c00SJeff Kirsher 		     V_CONTEXT(id) | F_CQ);
2439f7917c00SJeff Kirsher 	if (t3_wait_op_done_val(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY,
2440f7917c00SJeff Kirsher 				0, SG_CONTEXT_CMD_ATTEMPTS, 1, &val))
2441f7917c00SJeff Kirsher 		return -EIO;
2442f7917c00SJeff Kirsher 
2443f7917c00SJeff Kirsher 	if (op >= 2 && op < 7) {
2444f7917c00SJeff Kirsher 		if (adapter->params.rev > 0)
2445f7917c00SJeff Kirsher 			return G_CQ_INDEX(val);
2446f7917c00SJeff Kirsher 
2447f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_SG_CONTEXT_CMD,
2448f7917c00SJeff Kirsher 			     V_CONTEXT_CMD_OPCODE(0) | F_CQ | V_CONTEXT(id));
2449f7917c00SJeff Kirsher 		if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD,
2450f7917c00SJeff Kirsher 				    F_CONTEXT_CMD_BUSY, 0,
2451f7917c00SJeff Kirsher 				    SG_CONTEXT_CMD_ATTEMPTS, 1))
2452f7917c00SJeff Kirsher 			return -EIO;
2453f7917c00SJeff Kirsher 		return G_CQ_INDEX(t3_read_reg(adapter, A_SG_CONTEXT_DATA0));
2454f7917c00SJeff Kirsher 	}
2455f7917c00SJeff Kirsher 	return 0;
2456f7917c00SJeff Kirsher }
2457f7917c00SJeff Kirsher 
2458f7917c00SJeff Kirsher /**
2459f7917c00SJeff Kirsher  *	t3_config_rss - configure Rx packet steering
2460f7917c00SJeff Kirsher  *	@adapter: the adapter
2461f7917c00SJeff Kirsher  *	@rss_config: RSS settings (written to TP_RSS_CONFIG)
2462f7917c00SJeff Kirsher  *	@cpus: values for the CPU lookup table (0xff terminated)
2463f7917c00SJeff Kirsher  *	@rspq: values for the response queue lookup table (0xffff terminated)
2464f7917c00SJeff Kirsher  *
2465f7917c00SJeff Kirsher  *	Programs the receive packet steering logic.  @cpus and @rspq provide
2466f7917c00SJeff Kirsher  *	the values for the CPU and response queue lookup tables.  If they
2467f7917c00SJeff Kirsher  *	provide fewer values than the size of the tables the supplied values
2468f7917c00SJeff Kirsher  *	are used repeatedly until the tables are fully populated.
2469f7917c00SJeff Kirsher  */
t3_config_rss(struct adapter * adapter,unsigned int rss_config,const u8 * cpus,const u16 * rspq)2470f7917c00SJeff Kirsher void t3_config_rss(struct adapter *adapter, unsigned int rss_config,
2471f7917c00SJeff Kirsher 		   const u8 * cpus, const u16 *rspq)
2472f7917c00SJeff Kirsher {
2473f7917c00SJeff Kirsher 	int i, j, cpu_idx = 0, q_idx = 0;
2474f7917c00SJeff Kirsher 
2475f7917c00SJeff Kirsher 	if (cpus)
2476f7917c00SJeff Kirsher 		for (i = 0; i < RSS_TABLE_SIZE; ++i) {
2477f7917c00SJeff Kirsher 			u32 val = i << 16;
2478f7917c00SJeff Kirsher 
2479f7917c00SJeff Kirsher 			for (j = 0; j < 2; ++j) {
2480f7917c00SJeff Kirsher 				val |= (cpus[cpu_idx++] & 0x3f) << (8 * j);
2481f7917c00SJeff Kirsher 				if (cpus[cpu_idx] == 0xff)
2482f7917c00SJeff Kirsher 					cpu_idx = 0;
2483f7917c00SJeff Kirsher 			}
2484f7917c00SJeff Kirsher 			t3_write_reg(adapter, A_TP_RSS_LKP_TABLE, val);
2485f7917c00SJeff Kirsher 		}
2486f7917c00SJeff Kirsher 
2487f7917c00SJeff Kirsher 	if (rspq)
2488f7917c00SJeff Kirsher 		for (i = 0; i < RSS_TABLE_SIZE; ++i) {
2489f7917c00SJeff Kirsher 			t3_write_reg(adapter, A_TP_RSS_MAP_TABLE,
2490f7917c00SJeff Kirsher 				     (i << 16) | rspq[q_idx++]);
2491f7917c00SJeff Kirsher 			if (rspq[q_idx] == 0xffff)
2492f7917c00SJeff Kirsher 				q_idx = 0;
2493f7917c00SJeff Kirsher 		}
2494f7917c00SJeff Kirsher 
2495f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_TP_RSS_CONFIG, rss_config);
2496f7917c00SJeff Kirsher }
2497f7917c00SJeff Kirsher 
2498f7917c00SJeff Kirsher /**
2499f7917c00SJeff Kirsher  *	t3_tp_set_offload_mode - put TP in NIC/offload mode
2500f7917c00SJeff Kirsher  *	@adap: the adapter
2501f7917c00SJeff Kirsher  *	@enable: 1 to select offload mode, 0 for regular NIC
2502f7917c00SJeff Kirsher  *
2503f7917c00SJeff Kirsher  *	Switches TP to NIC/offload mode.
2504f7917c00SJeff Kirsher  */
t3_tp_set_offload_mode(struct adapter * adap,int enable)2505f7917c00SJeff Kirsher void t3_tp_set_offload_mode(struct adapter *adap, int enable)
2506f7917c00SJeff Kirsher {
2507f7917c00SJeff Kirsher 	if (is_offload(adap) || !enable)
2508f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_TP_IN_CONFIG, F_NICMODE,
2509f7917c00SJeff Kirsher 				 V_NICMODE(!enable));
2510f7917c00SJeff Kirsher }
2511f7917c00SJeff Kirsher 
2512f7917c00SJeff Kirsher /**
2513f7917c00SJeff Kirsher  *	pm_num_pages - calculate the number of pages of the payload memory
2514f7917c00SJeff Kirsher  *	@mem_size: the size of the payload memory
2515f7917c00SJeff Kirsher  *	@pg_size: the size of each payload memory page
2516f7917c00SJeff Kirsher  *
2517f7917c00SJeff Kirsher  *	Calculate the number of pages, each of the given size, that fit in a
2518f7917c00SJeff Kirsher  *	memory of the specified size, respecting the HW requirement that the
2519f7917c00SJeff Kirsher  *	number of pages must be a multiple of 24.
2520f7917c00SJeff Kirsher  */
pm_num_pages(unsigned int mem_size,unsigned int pg_size)2521f7917c00SJeff Kirsher static inline unsigned int pm_num_pages(unsigned int mem_size,
2522f7917c00SJeff Kirsher 					unsigned int pg_size)
2523f7917c00SJeff Kirsher {
2524f7917c00SJeff Kirsher 	unsigned int n = mem_size / pg_size;
2525f7917c00SJeff Kirsher 
2526f7917c00SJeff Kirsher 	return n - n % 24;
2527f7917c00SJeff Kirsher }
2528f7917c00SJeff Kirsher 
2529f7917c00SJeff Kirsher #define mem_region(adap, start, size, reg) \
2530f7917c00SJeff Kirsher 	t3_write_reg((adap), A_ ## reg, (start)); \
2531f7917c00SJeff Kirsher 	start += size
2532f7917c00SJeff Kirsher 
2533f7917c00SJeff Kirsher /**
2534f7917c00SJeff Kirsher  *	partition_mem - partition memory and configure TP memory settings
2535f7917c00SJeff Kirsher  *	@adap: the adapter
2536f7917c00SJeff Kirsher  *	@p: the TP parameters
2537f7917c00SJeff Kirsher  *
2538f7917c00SJeff Kirsher  *	Partitions context and payload memory and configures TP's memory
2539f7917c00SJeff Kirsher  *	registers.
2540f7917c00SJeff Kirsher  */
partition_mem(struct adapter * adap,const struct tp_params * p)2541f7917c00SJeff Kirsher static void partition_mem(struct adapter *adap, const struct tp_params *p)
2542f7917c00SJeff Kirsher {
2543f7917c00SJeff Kirsher 	unsigned int m, pstructs, tids = t3_mc5_size(&adap->mc5);
2544f7917c00SJeff Kirsher 	unsigned int timers = 0, timers_shift = 22;
2545f7917c00SJeff Kirsher 
2546f7917c00SJeff Kirsher 	if (adap->params.rev > 0) {
2547f7917c00SJeff Kirsher 		if (tids <= 16 * 1024) {
2548f7917c00SJeff Kirsher 			timers = 1;
2549f7917c00SJeff Kirsher 			timers_shift = 16;
2550f7917c00SJeff Kirsher 		} else if (tids <= 64 * 1024) {
2551f7917c00SJeff Kirsher 			timers = 2;
2552f7917c00SJeff Kirsher 			timers_shift = 18;
2553f7917c00SJeff Kirsher 		} else if (tids <= 256 * 1024) {
2554f7917c00SJeff Kirsher 			timers = 3;
2555f7917c00SJeff Kirsher 			timers_shift = 20;
2556f7917c00SJeff Kirsher 		}
2557f7917c00SJeff Kirsher 	}
2558f7917c00SJeff Kirsher 
2559f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PMM_SIZE,
2560f7917c00SJeff Kirsher 		     p->chan_rx_size | (p->chan_tx_size >> 16));
2561f7917c00SJeff Kirsher 
2562f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PMM_TX_BASE, 0);
2563f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PMM_TX_PAGE_SIZE, p->tx_pg_size);
2564f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PMM_TX_MAX_PAGE, p->tx_num_pgs);
2565f7917c00SJeff Kirsher 	t3_set_reg_field(adap, A_TP_PARA_REG3, V_TXDATAACKIDX(M_TXDATAACKIDX),
2566f7917c00SJeff Kirsher 			 V_TXDATAACKIDX(fls(p->tx_pg_size) - 12));
2567f7917c00SJeff Kirsher 
2568f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PMM_RX_BASE, 0);
2569f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PMM_RX_PAGE_SIZE, p->rx_pg_size);
2570f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PMM_RX_MAX_PAGE, p->rx_num_pgs);
2571f7917c00SJeff Kirsher 
2572f7917c00SJeff Kirsher 	pstructs = p->rx_num_pgs + p->tx_num_pgs;
2573f7917c00SJeff Kirsher 	/* Add a bit of headroom and make multiple of 24 */
2574f7917c00SJeff Kirsher 	pstructs += 48;
2575f7917c00SJeff Kirsher 	pstructs -= pstructs % 24;
2576f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_CMM_MM_MAX_PSTRUCT, pstructs);
2577f7917c00SJeff Kirsher 
2578f7917c00SJeff Kirsher 	m = tids * TCB_SIZE;
2579f7917c00SJeff Kirsher 	mem_region(adap, m, (64 << 10) * 64, SG_EGR_CNTX_BADDR);
2580f7917c00SJeff Kirsher 	mem_region(adap, m, (64 << 10) * 64, SG_CQ_CONTEXT_BADDR);
2581f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_CMM_TIMER_BASE, V_CMTIMERMAXNUM(timers) | m);
2582f7917c00SJeff Kirsher 	m += ((p->ntimer_qs - 1) << timers_shift) + (1 << 22);
2583f7917c00SJeff Kirsher 	mem_region(adap, m, pstructs * 64, TP_CMM_MM_BASE);
2584f7917c00SJeff Kirsher 	mem_region(adap, m, 64 * (pstructs / 24), TP_CMM_MM_PS_FLST_BASE);
2585f7917c00SJeff Kirsher 	mem_region(adap, m, 64 * (p->rx_num_pgs / 24), TP_CMM_MM_RX_FLST_BASE);
2586f7917c00SJeff Kirsher 	mem_region(adap, m, 64 * (p->tx_num_pgs / 24), TP_CMM_MM_TX_FLST_BASE);
2587f7917c00SJeff Kirsher 
2588f7917c00SJeff Kirsher 	m = (m + 4095) & ~0xfff;
2589f7917c00SJeff Kirsher 	t3_write_reg(adap, A_CIM_SDRAM_BASE_ADDR, m);
2590f7917c00SJeff Kirsher 	t3_write_reg(adap, A_CIM_SDRAM_ADDR_SIZE, p->cm_size - m);
2591f7917c00SJeff Kirsher 
2592f7917c00SJeff Kirsher 	tids = (p->cm_size - m - (3 << 20)) / 3072 - 32;
2593f7917c00SJeff Kirsher 	m = t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers -
2594f7917c00SJeff Kirsher 	    adap->params.mc5.nfilters - adap->params.mc5.nroutes;
2595f7917c00SJeff Kirsher 	if (tids < m)
2596f7917c00SJeff Kirsher 		adap->params.mc5.nservers += m - tids;
2597f7917c00SJeff Kirsher }
2598f7917c00SJeff Kirsher 
tp_wr_indirect(struct adapter * adap,unsigned int addr,u32 val)2599f7917c00SJeff Kirsher static inline void tp_wr_indirect(struct adapter *adap, unsigned int addr,
2600f7917c00SJeff Kirsher 				  u32 val)
2601f7917c00SJeff Kirsher {
2602f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PIO_ADDR, addr);
2603f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PIO_DATA, val);
2604f7917c00SJeff Kirsher }
2605f7917c00SJeff Kirsher 
tp_config(struct adapter * adap,const struct tp_params * p)2606f7917c00SJeff Kirsher static void tp_config(struct adapter *adap, const struct tp_params *p)
2607f7917c00SJeff Kirsher {
2608f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_GLOBAL_CONFIG, F_TXPACINGENABLE | F_PATHMTU |
2609f7917c00SJeff Kirsher 		     F_IPCHECKSUMOFFLOAD | F_UDPCHECKSUMOFFLOAD |
2610f7917c00SJeff Kirsher 		     F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
2611f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
2612f7917c00SJeff Kirsher 		     F_MTUENABLE | V_WINDOWSCALEMODE(1) |
2613f7917c00SJeff Kirsher 		     V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
2614f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
2615f7917c00SJeff Kirsher 		     V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
2616f7917c00SJeff Kirsher 		     V_BYTETHRESHOLD(26880) | V_MSSTHRESHOLD(2) |
2617f7917c00SJeff Kirsher 		     F_AUTOCAREFUL | F_AUTOENABLE | V_DACK_MODE(1));
2618f7917c00SJeff Kirsher 	t3_set_reg_field(adap, A_TP_IN_CONFIG, F_RXFBARBPRIO | F_TXFBARBPRIO,
2619f7917c00SJeff Kirsher 			 F_IPV6ENABLE | F_NICMODE);
2620f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
2621f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
2622f7917c00SJeff Kirsher 	t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
2623f7917c00SJeff Kirsher 			 adap->params.rev > 0 ? F_ENABLEESND :
2624f7917c00SJeff Kirsher 			 F_T3A_ENABLEESND);
2625f7917c00SJeff Kirsher 
2626f7917c00SJeff Kirsher 	t3_set_reg_field(adap, A_TP_PC_CONFIG,
2627f7917c00SJeff Kirsher 			 F_ENABLEEPCMDAFULL,
2628f7917c00SJeff Kirsher 			 F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
2629f7917c00SJeff Kirsher 			 F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
2630f7917c00SJeff Kirsher 	t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL,
2631f7917c00SJeff Kirsher 			 F_ENABLEIPV6RSS | F_ENABLENONOFDTNLSYN |
2632f7917c00SJeff Kirsher 			 F_ENABLEARPMISS | F_DISBLEDAPARBIT0);
2633f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
2634f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
2635f7917c00SJeff Kirsher 
2636f7917c00SJeff Kirsher 	if (adap->params.rev > 0) {
2637f7917c00SJeff Kirsher 		tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
2638f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
2639f7917c00SJeff Kirsher 				 F_TXPACEAUTO);
2640f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_TP_PC_CONFIG, F_LOCKTID, F_LOCKTID);
2641f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEAUTOSTRICT);
2642f7917c00SJeff Kirsher 	} else
2643f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
2644f7917c00SJeff Kirsher 
2645f7917c00SJeff Kirsher 	if (adap->params.rev == T3_REV_C)
2646f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_TP_PC_CONFIG,
2647f7917c00SJeff Kirsher 				 V_TABLELATENCYDELTA(M_TABLELATENCYDELTA),
2648f7917c00SJeff Kirsher 				 V_TABLELATENCYDELTA(4));
2649f7917c00SJeff Kirsher 
2650f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
2651f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
2652f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
2653f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
2654f7917c00SJeff Kirsher }
2655f7917c00SJeff Kirsher 
2656f7917c00SJeff Kirsher /* Desired TP timer resolution in usec */
2657f7917c00SJeff Kirsher #define TP_TMR_RES 50
2658f7917c00SJeff Kirsher 
2659f7917c00SJeff Kirsher /* TCP timer values in ms */
2660f7917c00SJeff Kirsher #define TP_DACK_TIMER 50
2661f7917c00SJeff Kirsher #define TP_RTO_MIN    250
2662f7917c00SJeff Kirsher 
2663f7917c00SJeff Kirsher /**
2664f7917c00SJeff Kirsher  *	tp_set_timers - set TP timing parameters
2665f7917c00SJeff Kirsher  *	@adap: the adapter to set
2666f7917c00SJeff Kirsher  *	@core_clk: the core clock frequency in Hz
2667f7917c00SJeff Kirsher  *
2668f7917c00SJeff Kirsher  *	Set TP's timing parameters, such as the various timer resolutions and
2669f7917c00SJeff Kirsher  *	the TCP timer values.
2670f7917c00SJeff Kirsher  */
tp_set_timers(struct adapter * adap,unsigned int core_clk)2671f7917c00SJeff Kirsher static void tp_set_timers(struct adapter *adap, unsigned int core_clk)
2672f7917c00SJeff Kirsher {
2673f7917c00SJeff Kirsher 	unsigned int tre = fls(core_clk / (1000000 / TP_TMR_RES)) - 1;
2674f7917c00SJeff Kirsher 	unsigned int dack_re = fls(core_clk / 5000) - 1;	/* 200us */
2675f7917c00SJeff Kirsher 	unsigned int tstamp_re = fls(core_clk / 1000);	/* 1ms, at least */
2676f7917c00SJeff Kirsher 	unsigned int tps = core_clk >> tre;
2677f7917c00SJeff Kirsher 
2678f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TIMER_RESOLUTION, V_TIMERRESOLUTION(tre) |
2679f7917c00SJeff Kirsher 		     V_DELAYEDACKRESOLUTION(dack_re) |
2680f7917c00SJeff Kirsher 		     V_TIMESTAMPRESOLUTION(tstamp_re));
2681f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_DACK_TIMER,
2682f7917c00SJeff Kirsher 		     (core_clk >> dack_re) / (1000 / TP_DACK_TIMER));
2683f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TCP_BACKOFF_REG0, 0x3020100);
2684f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TCP_BACKOFF_REG1, 0x7060504);
2685f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TCP_BACKOFF_REG2, 0xb0a0908);
2686f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TCP_BACKOFF_REG3, 0xf0e0d0c);
2687f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_SHIFT_CNT, V_SYNSHIFTMAX(6) |
2688f7917c00SJeff Kirsher 		     V_RXTSHIFTMAXR1(4) | V_RXTSHIFTMAXR2(15) |
2689f7917c00SJeff Kirsher 		     V_PERSHIFTBACKOFFMAX(8) | V_PERSHIFTMAX(8) |
2690f7917c00SJeff Kirsher 		     V_KEEPALIVEMAX(9));
2691f7917c00SJeff Kirsher 
2692f7917c00SJeff Kirsher #define SECONDS * tps
2693f7917c00SJeff Kirsher 
2694f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_MSL, adap->params.rev > 0 ? 0 : 2 SECONDS);
2695f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_RXT_MIN, tps / (1000 / TP_RTO_MIN));
2696f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_RXT_MAX, 64 SECONDS);
2697f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PERS_MIN, 5 SECONDS);
2698f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PERS_MAX, 64 SECONDS);
2699f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_KEEP_IDLE, 7200 SECONDS);
2700f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_KEEP_INTVL, 75 SECONDS);
2701f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_INIT_SRTT, 3 SECONDS);
2702f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_FINWAIT2_TIMER, 600 SECONDS);
2703f7917c00SJeff Kirsher 
2704f7917c00SJeff Kirsher #undef SECONDS
2705f7917c00SJeff Kirsher }
2706f7917c00SJeff Kirsher 
2707f7917c00SJeff Kirsher /**
2708f7917c00SJeff Kirsher  *	t3_tp_set_coalescing_size - set receive coalescing size
2709f7917c00SJeff Kirsher  *	@adap: the adapter
2710f7917c00SJeff Kirsher  *	@size: the receive coalescing size
2711f7917c00SJeff Kirsher  *	@psh: whether a set PSH bit should deliver coalesced data
2712f7917c00SJeff Kirsher  *
2713f7917c00SJeff Kirsher  *	Set the receive coalescing size and PSH bit handling.
2714f7917c00SJeff Kirsher  */
t3_tp_set_coalescing_size(struct adapter * adap,unsigned int size,int psh)2715f7917c00SJeff Kirsher static int t3_tp_set_coalescing_size(struct adapter *adap,
2716f7917c00SJeff Kirsher 				     unsigned int size, int psh)
2717f7917c00SJeff Kirsher {
2718f7917c00SJeff Kirsher 	u32 val;
2719f7917c00SJeff Kirsher 
2720f7917c00SJeff Kirsher 	if (size > MAX_RX_COALESCING_LEN)
2721f7917c00SJeff Kirsher 		return -EINVAL;
2722f7917c00SJeff Kirsher 
2723f7917c00SJeff Kirsher 	val = t3_read_reg(adap, A_TP_PARA_REG3);
2724f7917c00SJeff Kirsher 	val &= ~(F_RXCOALESCEENABLE | F_RXCOALESCEPSHEN);
2725f7917c00SJeff Kirsher 
2726f7917c00SJeff Kirsher 	if (size) {
2727f7917c00SJeff Kirsher 		val |= F_RXCOALESCEENABLE;
2728f7917c00SJeff Kirsher 		if (psh)
2729f7917c00SJeff Kirsher 			val |= F_RXCOALESCEPSHEN;
2730f7917c00SJeff Kirsher 		size = min(MAX_RX_COALESCING_LEN, size);
2731f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
2732f7917c00SJeff Kirsher 			     V_MAXRXDATA(MAX_RX_COALESCING_LEN));
2733f7917c00SJeff Kirsher 	}
2734f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PARA_REG3, val);
2735f7917c00SJeff Kirsher 	return 0;
2736f7917c00SJeff Kirsher }
2737f7917c00SJeff Kirsher 
2738f7917c00SJeff Kirsher /**
2739f7917c00SJeff Kirsher  *	t3_tp_set_max_rxsize - set the max receive size
2740f7917c00SJeff Kirsher  *	@adap: the adapter
2741f7917c00SJeff Kirsher  *	@size: the max receive size
2742f7917c00SJeff Kirsher  *
2743f7917c00SJeff Kirsher  *	Set TP's max receive size.  This is the limit that applies when
2744f7917c00SJeff Kirsher  *	receive coalescing is disabled.
2745f7917c00SJeff Kirsher  */
t3_tp_set_max_rxsize(struct adapter * adap,unsigned int size)2746f7917c00SJeff Kirsher static void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size)
2747f7917c00SJeff Kirsher {
2748f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_PARA_REG7,
2749f7917c00SJeff Kirsher 		     V_PMMAXXFERLEN0(size) | V_PMMAXXFERLEN1(size));
2750f7917c00SJeff Kirsher }
2751f7917c00SJeff Kirsher 
init_mtus(unsigned short mtus[])2752f7917c00SJeff Kirsher static void init_mtus(unsigned short mtus[])
2753f7917c00SJeff Kirsher {
2754f7917c00SJeff Kirsher 	/*
2755f7917c00SJeff Kirsher 	 * See draft-mathis-plpmtud-00.txt for the values.  The min is 88 so
2756f7917c00SJeff Kirsher 	 * it can accommodate max size TCP/IP headers when SACK and timestamps
2757f7917c00SJeff Kirsher 	 * are enabled and still have at least 8 bytes of payload.
2758f7917c00SJeff Kirsher 	 */
2759f7917c00SJeff Kirsher 	mtus[0] = 88;
2760f7917c00SJeff Kirsher 	mtus[1] = 88;
2761f7917c00SJeff Kirsher 	mtus[2] = 256;
2762f7917c00SJeff Kirsher 	mtus[3] = 512;
2763f7917c00SJeff Kirsher 	mtus[4] = 576;
2764f7917c00SJeff Kirsher 	mtus[5] = 1024;
2765f7917c00SJeff Kirsher 	mtus[6] = 1280;
2766f7917c00SJeff Kirsher 	mtus[7] = 1492;
2767f7917c00SJeff Kirsher 	mtus[8] = 1500;
2768f7917c00SJeff Kirsher 	mtus[9] = 2002;
2769f7917c00SJeff Kirsher 	mtus[10] = 2048;
2770f7917c00SJeff Kirsher 	mtus[11] = 4096;
2771f7917c00SJeff Kirsher 	mtus[12] = 4352;
2772f7917c00SJeff Kirsher 	mtus[13] = 8192;
2773f7917c00SJeff Kirsher 	mtus[14] = 9000;
2774f7917c00SJeff Kirsher 	mtus[15] = 9600;
2775f7917c00SJeff Kirsher }
2776f7917c00SJeff Kirsher 
2777f7917c00SJeff Kirsher /*
2778f7917c00SJeff Kirsher  * Initial congestion control parameters.
2779f7917c00SJeff Kirsher  */
init_cong_ctrl(unsigned short * a,unsigned short * b)2780f7917c00SJeff Kirsher static void init_cong_ctrl(unsigned short *a, unsigned short *b)
2781f7917c00SJeff Kirsher {
2782f7917c00SJeff Kirsher 	a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
2783f7917c00SJeff Kirsher 	a[9] = 2;
2784f7917c00SJeff Kirsher 	a[10] = 3;
2785f7917c00SJeff Kirsher 	a[11] = 4;
2786f7917c00SJeff Kirsher 	a[12] = 5;
2787f7917c00SJeff Kirsher 	a[13] = 6;
2788f7917c00SJeff Kirsher 	a[14] = 7;
2789f7917c00SJeff Kirsher 	a[15] = 8;
2790f7917c00SJeff Kirsher 	a[16] = 9;
2791f7917c00SJeff Kirsher 	a[17] = 10;
2792f7917c00SJeff Kirsher 	a[18] = 14;
2793f7917c00SJeff Kirsher 	a[19] = 17;
2794f7917c00SJeff Kirsher 	a[20] = 21;
2795f7917c00SJeff Kirsher 	a[21] = 25;
2796f7917c00SJeff Kirsher 	a[22] = 30;
2797f7917c00SJeff Kirsher 	a[23] = 35;
2798f7917c00SJeff Kirsher 	a[24] = 45;
2799f7917c00SJeff Kirsher 	a[25] = 60;
2800f7917c00SJeff Kirsher 	a[26] = 80;
2801f7917c00SJeff Kirsher 	a[27] = 100;
2802f7917c00SJeff Kirsher 	a[28] = 200;
2803f7917c00SJeff Kirsher 	a[29] = 300;
2804f7917c00SJeff Kirsher 	a[30] = 400;
2805f7917c00SJeff Kirsher 	a[31] = 500;
2806f7917c00SJeff Kirsher 
2807f7917c00SJeff Kirsher 	b[0] = b[1] = b[2] = b[3] = b[4] = b[5] = b[6] = b[7] = b[8] = 0;
2808f7917c00SJeff Kirsher 	b[9] = b[10] = 1;
2809f7917c00SJeff Kirsher 	b[11] = b[12] = 2;
2810f7917c00SJeff Kirsher 	b[13] = b[14] = b[15] = b[16] = 3;
2811f7917c00SJeff Kirsher 	b[17] = b[18] = b[19] = b[20] = b[21] = 4;
2812f7917c00SJeff Kirsher 	b[22] = b[23] = b[24] = b[25] = b[26] = b[27] = 5;
2813f7917c00SJeff Kirsher 	b[28] = b[29] = 6;
2814f7917c00SJeff Kirsher 	b[30] = b[31] = 7;
2815f7917c00SJeff Kirsher }
2816f7917c00SJeff Kirsher 
2817f7917c00SJeff Kirsher /* The minimum additive increment value for the congestion control table */
2818f7917c00SJeff Kirsher #define CC_MIN_INCR 2U
2819f7917c00SJeff Kirsher 
2820f7917c00SJeff Kirsher /**
2821f7917c00SJeff Kirsher  *	t3_load_mtus - write the MTU and congestion control HW tables
2822f7917c00SJeff Kirsher  *	@adap: the adapter
2823f7917c00SJeff Kirsher  *	@mtus: the unrestricted values for the MTU table
2824d0ea5cbdSJesse Brandeburg  *	@alpha: the values for the congestion control alpha parameter
2825f7917c00SJeff Kirsher  *	@beta: the values for the congestion control beta parameter
2826f7917c00SJeff Kirsher  *	@mtu_cap: the maximum permitted effective MTU
2827f7917c00SJeff Kirsher  *
2828f7917c00SJeff Kirsher  *	Write the MTU table with the supplied MTUs capping each at &mtu_cap.
2829f7917c00SJeff Kirsher  *	Update the high-speed congestion control table with the supplied alpha,
2830f7917c00SJeff Kirsher  * 	beta, and MTUs.
2831f7917c00SJeff Kirsher  */
t3_load_mtus(struct adapter * adap,unsigned short mtus[NMTUS],unsigned short alpha[NCCTRL_WIN],unsigned short beta[NCCTRL_WIN],unsigned short mtu_cap)2832f7917c00SJeff Kirsher void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS],
2833f7917c00SJeff Kirsher 		  unsigned short alpha[NCCTRL_WIN],
2834f7917c00SJeff Kirsher 		  unsigned short beta[NCCTRL_WIN], unsigned short mtu_cap)
2835f7917c00SJeff Kirsher {
2836f7917c00SJeff Kirsher 	static const unsigned int avg_pkts[NCCTRL_WIN] = {
2837f7917c00SJeff Kirsher 		2, 6, 10, 14, 20, 28, 40, 56, 80, 112, 160, 224, 320, 448, 640,
2838f7917c00SJeff Kirsher 		896, 1281, 1792, 2560, 3584, 5120, 7168, 10240, 14336, 20480,
2839f7917c00SJeff Kirsher 		28672, 40960, 57344, 81920, 114688, 163840, 229376
2840f7917c00SJeff Kirsher 	};
2841f7917c00SJeff Kirsher 
2842f7917c00SJeff Kirsher 	unsigned int i, w;
2843f7917c00SJeff Kirsher 
2844f7917c00SJeff Kirsher 	for (i = 0; i < NMTUS; ++i) {
2845f7917c00SJeff Kirsher 		unsigned int mtu = min(mtus[i], mtu_cap);
2846f7917c00SJeff Kirsher 		unsigned int log2 = fls(mtu);
2847f7917c00SJeff Kirsher 
2848f7917c00SJeff Kirsher 		if (!(mtu & ((1 << log2) >> 2)))	/* round */
2849f7917c00SJeff Kirsher 			log2--;
2850f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_MTU_TABLE,
2851f7917c00SJeff Kirsher 			     (i << 24) | (log2 << 16) | mtu);
2852f7917c00SJeff Kirsher 
2853f7917c00SJeff Kirsher 		for (w = 0; w < NCCTRL_WIN; ++w) {
2854f7917c00SJeff Kirsher 			unsigned int inc;
2855f7917c00SJeff Kirsher 
2856f7917c00SJeff Kirsher 			inc = max(((mtu - 40) * alpha[w]) / avg_pkts[w],
2857f7917c00SJeff Kirsher 				  CC_MIN_INCR);
2858f7917c00SJeff Kirsher 
2859f7917c00SJeff Kirsher 			t3_write_reg(adap, A_TP_CCTRL_TABLE, (i << 21) |
2860f7917c00SJeff Kirsher 				     (w << 16) | (beta[w] << 13) | inc);
2861f7917c00SJeff Kirsher 		}
2862f7917c00SJeff Kirsher 	}
2863f7917c00SJeff Kirsher }
2864f7917c00SJeff Kirsher 
2865f7917c00SJeff Kirsher /**
2866f7917c00SJeff Kirsher  *	t3_tp_get_mib_stats - read TP's MIB counters
2867f7917c00SJeff Kirsher  *	@adap: the adapter
2868f7917c00SJeff Kirsher  *	@tps: holds the returned counter values
2869f7917c00SJeff Kirsher  *
2870f7917c00SJeff Kirsher  *	Returns the values of TP's MIB counters.
2871f7917c00SJeff Kirsher  */
t3_tp_get_mib_stats(struct adapter * adap,struct tp_mib_stats * tps)2872f7917c00SJeff Kirsher void t3_tp_get_mib_stats(struct adapter *adap, struct tp_mib_stats *tps)
2873f7917c00SJeff Kirsher {
2874f7917c00SJeff Kirsher 	t3_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_RDATA, (u32 *) tps,
2875f7917c00SJeff Kirsher 			 sizeof(*tps) / sizeof(u32), 0);
2876f7917c00SJeff Kirsher }
2877f7917c00SJeff Kirsher 
2878f7917c00SJeff Kirsher #define ulp_region(adap, name, start, len) \
2879f7917c00SJeff Kirsher 	t3_write_reg((adap), A_ULPRX_ ## name ## _LLIMIT, (start)); \
2880f7917c00SJeff Kirsher 	t3_write_reg((adap), A_ULPRX_ ## name ## _ULIMIT, \
2881f7917c00SJeff Kirsher 		     (start) + (len) - 1); \
2882f7917c00SJeff Kirsher 	start += len
2883f7917c00SJeff Kirsher 
2884f7917c00SJeff Kirsher #define ulptx_region(adap, name, start, len) \
2885f7917c00SJeff Kirsher 	t3_write_reg((adap), A_ULPTX_ ## name ## _LLIMIT, (start)); \
2886f7917c00SJeff Kirsher 	t3_write_reg((adap), A_ULPTX_ ## name ## _ULIMIT, \
2887f7917c00SJeff Kirsher 		     (start) + (len) - 1)
2888f7917c00SJeff Kirsher 
ulp_config(struct adapter * adap,const struct tp_params * p)2889f7917c00SJeff Kirsher static void ulp_config(struct adapter *adap, const struct tp_params *p)
2890f7917c00SJeff Kirsher {
2891f7917c00SJeff Kirsher 	unsigned int m = p->chan_rx_size;
2892f7917c00SJeff Kirsher 
2893f7917c00SJeff Kirsher 	ulp_region(adap, ISCSI, m, p->chan_rx_size / 8);
2894f7917c00SJeff Kirsher 	ulp_region(adap, TDDP, m, p->chan_rx_size / 8);
2895f7917c00SJeff Kirsher 	ulptx_region(adap, TPT, m, p->chan_rx_size / 4);
2896f7917c00SJeff Kirsher 	ulp_region(adap, STAG, m, p->chan_rx_size / 4);
2897f7917c00SJeff Kirsher 	ulp_region(adap, RQ, m, p->chan_rx_size / 4);
2898f7917c00SJeff Kirsher 	ulptx_region(adap, PBL, m, p->chan_rx_size / 4);
2899f7917c00SJeff Kirsher 	ulp_region(adap, PBL, m, p->chan_rx_size / 4);
2900f7917c00SJeff Kirsher 	t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
2901f7917c00SJeff Kirsher }
2902f7917c00SJeff Kirsher 
2903f7917c00SJeff Kirsher /**
2904f7917c00SJeff Kirsher  *	t3_set_proto_sram - set the contents of the protocol sram
290545677bc6SWang Hai  *	@adap: the adapter
2906f7917c00SJeff Kirsher  *	@data: the protocol image
2907f7917c00SJeff Kirsher  *
2908f7917c00SJeff Kirsher  *	Write the contents of the protocol SRAM.
2909f7917c00SJeff Kirsher  */
t3_set_proto_sram(struct adapter * adap,const u8 * data)2910f7917c00SJeff Kirsher int t3_set_proto_sram(struct adapter *adap, const u8 *data)
2911f7917c00SJeff Kirsher {
2912f7917c00SJeff Kirsher 	int i;
2913f7917c00SJeff Kirsher 	const __be32 *buf = (const __be32 *)data;
2914f7917c00SJeff Kirsher 
2915f7917c00SJeff Kirsher 	for (i = 0; i < PROTO_SRAM_LINES; i++) {
2916f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, be32_to_cpu(*buf++));
2917f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, be32_to_cpu(*buf++));
2918f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, be32_to_cpu(*buf++));
2919f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, be32_to_cpu(*buf++));
2920f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, be32_to_cpu(*buf++));
2921f7917c00SJeff Kirsher 
2922f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
2923f7917c00SJeff Kirsher 		if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
2924f7917c00SJeff Kirsher 			return -EIO;
2925f7917c00SJeff Kirsher 	}
2926f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
2927f7917c00SJeff Kirsher 
2928f7917c00SJeff Kirsher 	return 0;
2929f7917c00SJeff Kirsher }
2930f7917c00SJeff Kirsher 
t3_config_trace_filter(struct adapter * adapter,const struct trace_params * tp,int filter_index,int invert,int enable)2931f7917c00SJeff Kirsher void t3_config_trace_filter(struct adapter *adapter,
2932f7917c00SJeff Kirsher 			    const struct trace_params *tp, int filter_index,
2933f7917c00SJeff Kirsher 			    int invert, int enable)
2934f7917c00SJeff Kirsher {
2935f7917c00SJeff Kirsher 	u32 addr, key[4], mask[4];
2936f7917c00SJeff Kirsher 
2937f7917c00SJeff Kirsher 	key[0] = tp->sport | (tp->sip << 16);
2938f7917c00SJeff Kirsher 	key[1] = (tp->sip >> 16) | (tp->dport << 16);
2939f7917c00SJeff Kirsher 	key[2] = tp->dip;
2940f7917c00SJeff Kirsher 	key[3] = tp->proto | (tp->vlan << 8) | (tp->intf << 20);
2941f7917c00SJeff Kirsher 
2942f7917c00SJeff Kirsher 	mask[0] = tp->sport_mask | (tp->sip_mask << 16);
2943f7917c00SJeff Kirsher 	mask[1] = (tp->sip_mask >> 16) | (tp->dport_mask << 16);
2944f7917c00SJeff Kirsher 	mask[2] = tp->dip_mask;
2945f7917c00SJeff Kirsher 	mask[3] = tp->proto_mask | (tp->vlan_mask << 8) | (tp->intf_mask << 20);
2946f7917c00SJeff Kirsher 
2947f7917c00SJeff Kirsher 	if (invert)
2948f7917c00SJeff Kirsher 		key[3] |= (1 << 29);
2949f7917c00SJeff Kirsher 	if (enable)
2950f7917c00SJeff Kirsher 		key[3] |= (1 << 28);
2951f7917c00SJeff Kirsher 
2952f7917c00SJeff Kirsher 	addr = filter_index ? A_TP_RX_TRC_KEY0 : A_TP_TX_TRC_KEY0;
2953f7917c00SJeff Kirsher 	tp_wr_indirect(adapter, addr++, key[0]);
2954f7917c00SJeff Kirsher 	tp_wr_indirect(adapter, addr++, mask[0]);
2955f7917c00SJeff Kirsher 	tp_wr_indirect(adapter, addr++, key[1]);
2956f7917c00SJeff Kirsher 	tp_wr_indirect(adapter, addr++, mask[1]);
2957f7917c00SJeff Kirsher 	tp_wr_indirect(adapter, addr++, key[2]);
2958f7917c00SJeff Kirsher 	tp_wr_indirect(adapter, addr++, mask[2]);
2959f7917c00SJeff Kirsher 	tp_wr_indirect(adapter, addr++, key[3]);
2960f7917c00SJeff Kirsher 	tp_wr_indirect(adapter, addr, mask[3]);
2961f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_TP_PIO_DATA);
2962f7917c00SJeff Kirsher }
2963f7917c00SJeff Kirsher 
2964f7917c00SJeff Kirsher /**
2965f7917c00SJeff Kirsher  *	t3_config_sched - configure a HW traffic scheduler
2966f7917c00SJeff Kirsher  *	@adap: the adapter
2967f7917c00SJeff Kirsher  *	@kbps: target rate in Kbps
2968f7917c00SJeff Kirsher  *	@sched: the scheduler index
2969f7917c00SJeff Kirsher  *
2970f7917c00SJeff Kirsher  *	Configure a HW scheduler for the target rate
2971f7917c00SJeff Kirsher  */
t3_config_sched(struct adapter * adap,unsigned int kbps,int sched)2972f7917c00SJeff Kirsher int t3_config_sched(struct adapter *adap, unsigned int kbps, int sched)
2973f7917c00SJeff Kirsher {
2974f7917c00SJeff Kirsher 	unsigned int v, tps, cpt, bpt, delta, mindelta = ~0;
2975f7917c00SJeff Kirsher 	unsigned int clk = adap->params.vpd.cclk * 1000;
2976f7917c00SJeff Kirsher 	unsigned int selected_cpt = 0, selected_bpt = 0;
2977f7917c00SJeff Kirsher 
2978f7917c00SJeff Kirsher 	if (kbps > 0) {
2979f7917c00SJeff Kirsher 		kbps *= 125;	/* -> bytes */
2980f7917c00SJeff Kirsher 		for (cpt = 1; cpt <= 255; cpt++) {
2981f7917c00SJeff Kirsher 			tps = clk / cpt;
2982f7917c00SJeff Kirsher 			bpt = (kbps + tps / 2) / tps;
2983f7917c00SJeff Kirsher 			if (bpt > 0 && bpt <= 255) {
2984f7917c00SJeff Kirsher 				v = bpt * tps;
2985f7917c00SJeff Kirsher 				delta = v >= kbps ? v - kbps : kbps - v;
2986f7917c00SJeff Kirsher 				if (delta <= mindelta) {
2987f7917c00SJeff Kirsher 					mindelta = delta;
2988f7917c00SJeff Kirsher 					selected_cpt = cpt;
2989f7917c00SJeff Kirsher 					selected_bpt = bpt;
2990f7917c00SJeff Kirsher 				}
2991f7917c00SJeff Kirsher 			} else if (selected_cpt)
2992f7917c00SJeff Kirsher 				break;
2993f7917c00SJeff Kirsher 		}
2994f7917c00SJeff Kirsher 		if (!selected_cpt)
2995f7917c00SJeff Kirsher 			return -EINVAL;
2996f7917c00SJeff Kirsher 	}
2997f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TM_PIO_ADDR,
2998f7917c00SJeff Kirsher 		     A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2);
2999f7917c00SJeff Kirsher 	v = t3_read_reg(adap, A_TP_TM_PIO_DATA);
3000f7917c00SJeff Kirsher 	if (sched & 1)
3001f7917c00SJeff Kirsher 		v = (v & 0xffff) | (selected_cpt << 16) | (selected_bpt << 24);
3002f7917c00SJeff Kirsher 	else
3003f7917c00SJeff Kirsher 		v = (v & 0xffff0000) | selected_cpt | (selected_bpt << 8);
3004f7917c00SJeff Kirsher 	t3_write_reg(adap, A_TP_TM_PIO_DATA, v);
3005f7917c00SJeff Kirsher 	return 0;
3006f7917c00SJeff Kirsher }
3007f7917c00SJeff Kirsher 
tp_init(struct adapter * adap,const struct tp_params * p)3008f7917c00SJeff Kirsher static int tp_init(struct adapter *adap, const struct tp_params *p)
3009f7917c00SJeff Kirsher {
3010f7917c00SJeff Kirsher 	int busy = 0;
3011f7917c00SJeff Kirsher 
3012f7917c00SJeff Kirsher 	tp_config(adap, p);
3013f7917c00SJeff Kirsher 	t3_set_vlan_accel(adap, 3, 0);
3014f7917c00SJeff Kirsher 
3015f7917c00SJeff Kirsher 	if (is_offload(adap)) {
3016f7917c00SJeff Kirsher 		tp_set_timers(adap, adap->params.vpd.cclk * 1000);
3017f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_RESET, F_FLSTINITENABLE);
3018f7917c00SJeff Kirsher 		busy = t3_wait_op_done(adap, A_TP_RESET, F_FLSTINITENABLE,
3019f7917c00SJeff Kirsher 				       0, 1000, 5);
3020f7917c00SJeff Kirsher 		if (busy)
3021f7917c00SJeff Kirsher 			CH_ERR(adap, "TP initialization timed out\n");
3022f7917c00SJeff Kirsher 	}
3023f7917c00SJeff Kirsher 
3024f7917c00SJeff Kirsher 	if (!busy)
3025f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_RESET, F_TPRESET);
3026f7917c00SJeff Kirsher 	return busy;
3027f7917c00SJeff Kirsher }
3028f7917c00SJeff Kirsher 
3029f7917c00SJeff Kirsher /*
3030f7917c00SJeff Kirsher  * Perform the bits of HW initialization that are dependent on the Tx
3031f7917c00SJeff Kirsher  * channels being used.
3032f7917c00SJeff Kirsher  */
chan_init_hw(struct adapter * adap,unsigned int chan_map)3033f7917c00SJeff Kirsher static void chan_init_hw(struct adapter *adap, unsigned int chan_map)
3034f7917c00SJeff Kirsher {
3035f7917c00SJeff Kirsher 	int i;
3036f7917c00SJeff Kirsher 
3037f7917c00SJeff Kirsher 	if (chan_map != 3) {                                 /* one channel */
3038f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_ULPRX_CTL, F_ROUND_ROBIN, 0);
3039f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
3040f7917c00SJeff Kirsher 		t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_ENFORCEPKT |
3041f7917c00SJeff Kirsher 			     (chan_map == 1 ? F_TPTXPORT0EN | F_PORT0ACTIVE :
3042f7917c00SJeff Kirsher 					      F_TPTXPORT1EN | F_PORT1ACTIVE));
3043f7917c00SJeff Kirsher 		t3_write_reg(adap, A_PM1_TX_CFG,
3044f7917c00SJeff Kirsher 			     chan_map == 1 ? 0xffffffff : 0);
3045f7917c00SJeff Kirsher 	} else {                                             /* two channels */
3046f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
3047f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
3048f7917c00SJeff Kirsher 		t3_write_reg(adap, A_ULPTX_DMA_WEIGHT,
3049f7917c00SJeff Kirsher 			     V_D1_WEIGHT(16) | V_D0_WEIGHT(16));
3050f7917c00SJeff Kirsher 		t3_write_reg(adap, A_MPS_CFG, F_TPTXPORT0EN | F_TPTXPORT1EN |
3051f7917c00SJeff Kirsher 			     F_TPRXPORTEN | F_PORT0ACTIVE | F_PORT1ACTIVE |
3052f7917c00SJeff Kirsher 			     F_ENFORCEPKT);
3053f7917c00SJeff Kirsher 		t3_write_reg(adap, A_PM1_TX_CFG, 0x80008000);
3054f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_TP_PC_CONFIG, 0, F_TXTOSQUEUEMAPMODE);
3055f7917c00SJeff Kirsher 		t3_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP,
3056f7917c00SJeff Kirsher 			     V_TX_MOD_QUEUE_REQ_MAP(0xaa));
3057f7917c00SJeff Kirsher 		for (i = 0; i < 16; i++)
3058f7917c00SJeff Kirsher 			t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE,
3059f7917c00SJeff Kirsher 				     (i << 16) | 0x1010);
3060f7917c00SJeff Kirsher 	}
3061f7917c00SJeff Kirsher }
3062f7917c00SJeff Kirsher 
calibrate_xgm(struct adapter * adapter)3063f7917c00SJeff Kirsher static int calibrate_xgm(struct adapter *adapter)
3064f7917c00SJeff Kirsher {
3065f7917c00SJeff Kirsher 	if (uses_xaui(adapter)) {
3066f7917c00SJeff Kirsher 		unsigned int v, i;
3067f7917c00SJeff Kirsher 
3068f7917c00SJeff Kirsher 		for (i = 0; i < 5; ++i) {
3069f7917c00SJeff Kirsher 			t3_write_reg(adapter, A_XGM_XAUI_IMP, 0);
3070f7917c00SJeff Kirsher 			t3_read_reg(adapter, A_XGM_XAUI_IMP);
3071f7917c00SJeff Kirsher 			msleep(1);
3072f7917c00SJeff Kirsher 			v = t3_read_reg(adapter, A_XGM_XAUI_IMP);
3073f7917c00SJeff Kirsher 			if (!(v & (F_XGM_CALFAULT | F_CALBUSY))) {
3074f7917c00SJeff Kirsher 				t3_write_reg(adapter, A_XGM_XAUI_IMP,
3075f7917c00SJeff Kirsher 					     V_XAUIIMP(G_CALIMP(v) >> 2));
3076f7917c00SJeff Kirsher 				return 0;
3077f7917c00SJeff Kirsher 			}
3078f7917c00SJeff Kirsher 		}
3079f7917c00SJeff Kirsher 		CH_ERR(adapter, "MAC calibration failed\n");
3080f7917c00SJeff Kirsher 		return -1;
3081f7917c00SJeff Kirsher 	} else {
3082f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_XGM_RGMII_IMP,
3083f7917c00SJeff Kirsher 			     V_RGMIIIMPPD(2) | V_RGMIIIMPPU(3));
3084f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_XGM_IMPSETUPDATE,
3085f7917c00SJeff Kirsher 				 F_XGM_IMPSETUPDATE);
3086f7917c00SJeff Kirsher 	}
3087f7917c00SJeff Kirsher 	return 0;
3088f7917c00SJeff Kirsher }
3089f7917c00SJeff Kirsher 
calibrate_xgm_t3b(struct adapter * adapter)3090f7917c00SJeff Kirsher static void calibrate_xgm_t3b(struct adapter *adapter)
3091f7917c00SJeff Kirsher {
3092f7917c00SJeff Kirsher 	if (!uses_xaui(adapter)) {
3093f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_XGM_RGMII_IMP, F_CALRESET |
3094f7917c00SJeff Kirsher 			     F_CALUPDATE | V_RGMIIIMPPD(2) | V_RGMIIIMPPU(3));
3095f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_CALRESET, 0);
3096f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, 0,
3097f7917c00SJeff Kirsher 				 F_XGM_IMPSETUPDATE);
3098f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_XGM_IMPSETUPDATE,
3099f7917c00SJeff Kirsher 				 0);
3100f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_CALUPDATE, 0);
3101f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_XGM_RGMII_IMP, 0, F_CALUPDATE);
3102f7917c00SJeff Kirsher 	}
3103f7917c00SJeff Kirsher }
3104f7917c00SJeff Kirsher 
3105f7917c00SJeff Kirsher struct mc7_timing_params {
3106f7917c00SJeff Kirsher 	unsigned char ActToPreDly;
3107f7917c00SJeff Kirsher 	unsigned char ActToRdWrDly;
3108f7917c00SJeff Kirsher 	unsigned char PreCyc;
3109f7917c00SJeff Kirsher 	unsigned char RefCyc[5];
3110f7917c00SJeff Kirsher 	unsigned char BkCyc;
3111f7917c00SJeff Kirsher 	unsigned char WrToRdDly;
3112f7917c00SJeff Kirsher 	unsigned char RdToWrDly;
3113f7917c00SJeff Kirsher };
3114f7917c00SJeff Kirsher 
3115f7917c00SJeff Kirsher /*
3116f7917c00SJeff Kirsher  * Write a value to a register and check that the write completed.  These
3117f7917c00SJeff Kirsher  * writes normally complete in a cycle or two, so one read should suffice.
3118f7917c00SJeff Kirsher  * The very first read exists to flush the posted write to the device.
3119f7917c00SJeff Kirsher  */
wrreg_wait(struct adapter * adapter,unsigned int addr,u32 val)3120f7917c00SJeff Kirsher static int wrreg_wait(struct adapter *adapter, unsigned int addr, u32 val)
3121f7917c00SJeff Kirsher {
3122f7917c00SJeff Kirsher 	t3_write_reg(adapter, addr, val);
3123f7917c00SJeff Kirsher 	t3_read_reg(adapter, addr);	/* flush */
3124f7917c00SJeff Kirsher 	if (!(t3_read_reg(adapter, addr) & F_BUSY))
3125f7917c00SJeff Kirsher 		return 0;
3126f7917c00SJeff Kirsher 	CH_ERR(adapter, "write to MC7 register 0x%x timed out\n", addr);
3127f7917c00SJeff Kirsher 	return -EIO;
3128f7917c00SJeff Kirsher }
3129f7917c00SJeff Kirsher 
mc7_init(struct mc7 * mc7,unsigned int mc7_clock,int mem_type)3130f7917c00SJeff Kirsher static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type)
3131f7917c00SJeff Kirsher {
3132f7917c00SJeff Kirsher 	static const unsigned int mc7_mode[] = {
3133f7917c00SJeff Kirsher 		0x632, 0x642, 0x652, 0x432, 0x442
3134f7917c00SJeff Kirsher 	};
3135f7917c00SJeff Kirsher 	static const struct mc7_timing_params mc7_timings[] = {
3136f7917c00SJeff Kirsher 		{12, 3, 4, {20, 28, 34, 52, 0}, 15, 6, 4},
3137f7917c00SJeff Kirsher 		{12, 4, 5, {20, 28, 34, 52, 0}, 16, 7, 4},
3138f7917c00SJeff Kirsher 		{12, 5, 6, {20, 28, 34, 52, 0}, 17, 8, 4},
3139f7917c00SJeff Kirsher 		{9, 3, 4, {15, 21, 26, 39, 0}, 12, 6, 4},
3140f7917c00SJeff Kirsher 		{9, 4, 5, {15, 21, 26, 39, 0}, 13, 7, 4}
3141f7917c00SJeff Kirsher 	};
3142f7917c00SJeff Kirsher 
3143f7917c00SJeff Kirsher 	u32 val;
3144f7917c00SJeff Kirsher 	unsigned int width, density, slow, attempts;
3145f7917c00SJeff Kirsher 	struct adapter *adapter = mc7->adapter;
3146f7917c00SJeff Kirsher 	const struct mc7_timing_params *p = &mc7_timings[mem_type];
3147f7917c00SJeff Kirsher 
3148f7917c00SJeff Kirsher 	if (!mc7->size)
3149f7917c00SJeff Kirsher 		return 0;
3150f7917c00SJeff Kirsher 
3151f7917c00SJeff Kirsher 	val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
3152f7917c00SJeff Kirsher 	slow = val & F_SLOW;
3153f7917c00SJeff Kirsher 	width = G_WIDTH(val);
3154f7917c00SJeff Kirsher 	density = G_DEN(val);
3155f7917c00SJeff Kirsher 
3156f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_CFG, val | F_IFEN);
3157f7917c00SJeff Kirsher 	val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);	/* flush */
3158f7917c00SJeff Kirsher 	msleep(1);
3159f7917c00SJeff Kirsher 
3160f7917c00SJeff Kirsher 	if (!slow) {
3161f7917c00SJeff Kirsher 		t3_write_reg(adapter, mc7->offset + A_MC7_CAL, F_SGL_CAL_EN);
3162f7917c00SJeff Kirsher 		t3_read_reg(adapter, mc7->offset + A_MC7_CAL);
3163f7917c00SJeff Kirsher 		msleep(1);
3164f7917c00SJeff Kirsher 		if (t3_read_reg(adapter, mc7->offset + A_MC7_CAL) &
3165f7917c00SJeff Kirsher 		    (F_BUSY | F_SGL_CAL_EN | F_CAL_FAULT)) {
3166f7917c00SJeff Kirsher 			CH_ERR(adapter, "%s MC7 calibration timed out\n",
3167f7917c00SJeff Kirsher 			       mc7->name);
3168f7917c00SJeff Kirsher 			goto out_fail;
3169f7917c00SJeff Kirsher 		}
3170f7917c00SJeff Kirsher 	}
3171f7917c00SJeff Kirsher 
3172f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_PARM,
3173f7917c00SJeff Kirsher 		     V_ACTTOPREDLY(p->ActToPreDly) |
3174f7917c00SJeff Kirsher 		     V_ACTTORDWRDLY(p->ActToRdWrDly) | V_PRECYC(p->PreCyc) |
3175f7917c00SJeff Kirsher 		     V_REFCYC(p->RefCyc[density]) | V_BKCYC(p->BkCyc) |
3176f7917c00SJeff Kirsher 		     V_WRTORDDLY(p->WrToRdDly) | V_RDTOWRDLY(p->RdToWrDly));
3177f7917c00SJeff Kirsher 
3178f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_CFG,
3179f7917c00SJeff Kirsher 		     val | F_CLKEN | F_TERM150);
3180f7917c00SJeff Kirsher 	t3_read_reg(adapter, mc7->offset + A_MC7_CFG);	/* flush */
3181f7917c00SJeff Kirsher 
3182f7917c00SJeff Kirsher 	if (!slow)
3183f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, mc7->offset + A_MC7_DLL, F_DLLENB,
3184f7917c00SJeff Kirsher 				 F_DLLENB);
3185f7917c00SJeff Kirsher 	udelay(1);
3186f7917c00SJeff Kirsher 
3187f7917c00SJeff Kirsher 	val = slow ? 3 : 6;
3188f7917c00SJeff Kirsher 	if (wrreg_wait(adapter, mc7->offset + A_MC7_PRE, 0) ||
3189f7917c00SJeff Kirsher 	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE2, 0) ||
3190f7917c00SJeff Kirsher 	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE3, 0) ||
3191f7917c00SJeff Kirsher 	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val))
3192f7917c00SJeff Kirsher 		goto out_fail;
3193f7917c00SJeff Kirsher 
3194f7917c00SJeff Kirsher 	if (!slow) {
3195f7917c00SJeff Kirsher 		t3_write_reg(adapter, mc7->offset + A_MC7_MODE, 0x100);
3196f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, mc7->offset + A_MC7_DLL, F_DLLRST, 0);
3197f7917c00SJeff Kirsher 		udelay(5);
3198f7917c00SJeff Kirsher 	}
3199f7917c00SJeff Kirsher 
3200f7917c00SJeff Kirsher 	if (wrreg_wait(adapter, mc7->offset + A_MC7_PRE, 0) ||
3201f7917c00SJeff Kirsher 	    wrreg_wait(adapter, mc7->offset + A_MC7_REF, 0) ||
3202f7917c00SJeff Kirsher 	    wrreg_wait(adapter, mc7->offset + A_MC7_REF, 0) ||
3203f7917c00SJeff Kirsher 	    wrreg_wait(adapter, mc7->offset + A_MC7_MODE,
3204f7917c00SJeff Kirsher 		       mc7_mode[mem_type]) ||
3205f7917c00SJeff Kirsher 	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val | 0x380) ||
3206f7917c00SJeff Kirsher 	    wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val))
3207f7917c00SJeff Kirsher 		goto out_fail;
3208f7917c00SJeff Kirsher 
3209f7917c00SJeff Kirsher 	/* clock value is in KHz */
3210f7917c00SJeff Kirsher 	mc7_clock = mc7_clock * 7812 + mc7_clock / 2;	/* ns */
3211f7917c00SJeff Kirsher 	mc7_clock /= 1000000;	/* KHz->MHz, ns->us */
3212f7917c00SJeff Kirsher 
3213f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_REF,
3214f7917c00SJeff Kirsher 		     F_PERREFEN | V_PREREFDIV(mc7_clock));
3215f7917c00SJeff Kirsher 	t3_read_reg(adapter, mc7->offset + A_MC7_REF);	/* flush */
3216f7917c00SJeff Kirsher 
3217f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_ECC, F_ECCGENEN | F_ECCCHKEN);
3218f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_BIST_DATA, 0);
3219f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_BIST_ADDR_BEG, 0);
3220f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_BIST_ADDR_END,
3221f7917c00SJeff Kirsher 		     (mc7->size << width) - 1);
3222f7917c00SJeff Kirsher 	t3_write_reg(adapter, mc7->offset + A_MC7_BIST_OP, V_OP(1));
3223f7917c00SJeff Kirsher 	t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP);	/* flush */
3224f7917c00SJeff Kirsher 
3225f7917c00SJeff Kirsher 	attempts = 50;
3226f7917c00SJeff Kirsher 	do {
3227f7917c00SJeff Kirsher 		msleep(250);
3228f7917c00SJeff Kirsher 		val = t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP);
3229f7917c00SJeff Kirsher 	} while ((val & F_BUSY) && --attempts);
3230f7917c00SJeff Kirsher 	if (val & F_BUSY) {
3231f7917c00SJeff Kirsher 		CH_ERR(adapter, "%s MC7 BIST timed out\n", mc7->name);
3232f7917c00SJeff Kirsher 		goto out_fail;
3233f7917c00SJeff Kirsher 	}
3234f7917c00SJeff Kirsher 
3235f7917c00SJeff Kirsher 	/* Enable normal memory accesses. */
3236f7917c00SJeff Kirsher 	t3_set_reg_field(adapter, mc7->offset + A_MC7_CFG, 0, F_RDY);
3237f7917c00SJeff Kirsher 	return 0;
3238f7917c00SJeff Kirsher 
3239f7917c00SJeff Kirsher out_fail:
3240f7917c00SJeff Kirsher 	return -1;
3241f7917c00SJeff Kirsher }
3242f7917c00SJeff Kirsher 
config_pcie(struct adapter * adap)3243f7917c00SJeff Kirsher static void config_pcie(struct adapter *adap)
3244f7917c00SJeff Kirsher {
3245f7917c00SJeff Kirsher 	static const u16 ack_lat[4][6] = {
3246f7917c00SJeff Kirsher 		{237, 416, 559, 1071, 2095, 4143},
3247f7917c00SJeff Kirsher 		{128, 217, 289, 545, 1057, 2081},
3248f7917c00SJeff Kirsher 		{73, 118, 154, 282, 538, 1050},
3249f7917c00SJeff Kirsher 		{67, 107, 86, 150, 278, 534}
3250f7917c00SJeff Kirsher 	};
3251f7917c00SJeff Kirsher 	static const u16 rpl_tmr[4][6] = {
3252f7917c00SJeff Kirsher 		{711, 1248, 1677, 3213, 6285, 12429},
3253f7917c00SJeff Kirsher 		{384, 651, 867, 1635, 3171, 6243},
3254f7917c00SJeff Kirsher 		{219, 354, 462, 846, 1614, 3150},
3255f7917c00SJeff Kirsher 		{201, 321, 258, 450, 834, 1602}
3256f7917c00SJeff Kirsher 	};
3257f7917c00SJeff Kirsher 
3258f7917c00SJeff Kirsher 	u16 val, devid;
3259f7917c00SJeff Kirsher 	unsigned int log2_width, pldsize;
3260f7917c00SJeff Kirsher 	unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt;
3261f7917c00SJeff Kirsher 
3262c772b44eSJiang Liu 	pcie_capability_read_word(adap->pdev, PCI_EXP_DEVCTL, &val);
3263f7917c00SJeff Kirsher 	pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
3264f7917c00SJeff Kirsher 
3265f7917c00SJeff Kirsher 	pci_read_config_word(adap->pdev, 0x2, &devid);
3266f7917c00SJeff Kirsher 	if (devid == 0x37) {
3267c772b44eSJiang Liu 		pcie_capability_write_word(adap->pdev, PCI_EXP_DEVCTL,
3268f7917c00SJeff Kirsher 					   val & ~PCI_EXP_DEVCTL_READRQ &
3269f7917c00SJeff Kirsher 					   ~PCI_EXP_DEVCTL_PAYLOAD);
3270f7917c00SJeff Kirsher 		pldsize = 0;
3271f7917c00SJeff Kirsher 	}
3272f7917c00SJeff Kirsher 
3273c772b44eSJiang Liu 	pcie_capability_read_word(adap->pdev, PCI_EXP_LNKCTL, &val);
3274f7917c00SJeff Kirsher 
3275f7917c00SJeff Kirsher 	fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0));
3276f7917c00SJeff Kirsher 	fst_trn_rx = adap->params.rev == 0 ? fst_trn_tx :
3277f7917c00SJeff Kirsher 	    G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE));
3278f7917c00SJeff Kirsher 	log2_width = fls(adap->params.pci.width) - 1;
3279f7917c00SJeff Kirsher 	acklat = ack_lat[log2_width][pldsize];
3280f2692bd9SBjorn Helgaas 	if (val & PCI_EXP_LNKCTL_ASPM_L0S)	/* check LOsEnable */
3281f7917c00SJeff Kirsher 		acklat += fst_trn_tx * 4;
3282f7917c00SJeff Kirsher 	rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4;
3283f7917c00SJeff Kirsher 
3284f7917c00SJeff Kirsher 	if (adap->params.rev == 0)
3285f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_PCIE_PEX_CTRL1,
3286f7917c00SJeff Kirsher 				 V_T3A_ACKLAT(M_T3A_ACKLAT),
3287f7917c00SJeff Kirsher 				 V_T3A_ACKLAT(acklat));
3288f7917c00SJeff Kirsher 	else
3289f7917c00SJeff Kirsher 		t3_set_reg_field(adap, A_PCIE_PEX_CTRL1, V_ACKLAT(M_ACKLAT),
3290f7917c00SJeff Kirsher 				 V_ACKLAT(acklat));
3291f7917c00SJeff Kirsher 
3292f7917c00SJeff Kirsher 	t3_set_reg_field(adap, A_PCIE_PEX_CTRL0, V_REPLAYLMT(M_REPLAYLMT),
3293f7917c00SJeff Kirsher 			 V_REPLAYLMT(rpllmt));
3294f7917c00SJeff Kirsher 
3295f7917c00SJeff Kirsher 	t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff);
3296f7917c00SJeff Kirsher 	t3_set_reg_field(adap, A_PCIE_CFG, 0,
3297f7917c00SJeff Kirsher 			 F_ENABLELINKDWNDRST | F_ENABLELINKDOWNRST |
3298f7917c00SJeff Kirsher 			 F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN);
3299f7917c00SJeff Kirsher }
3300f7917c00SJeff Kirsher 
3301f7917c00SJeff Kirsher /*
3302f7917c00SJeff Kirsher  * Initialize and configure T3 HW modules.  This performs the
3303f7917c00SJeff Kirsher  * initialization steps that need to be done once after a card is reset.
3304f7917c00SJeff Kirsher  * MAC and PHY initialization is handled separarely whenever a port is enabled.
3305f7917c00SJeff Kirsher  *
3306f7917c00SJeff Kirsher  * fw_params are passed to FW and their value is platform dependent.  Only the
3307f7917c00SJeff Kirsher  * top 8 bits are available for use, the rest must be 0.
3308f7917c00SJeff Kirsher  */
t3_init_hw(struct adapter * adapter,u32 fw_params)3309f7917c00SJeff Kirsher int t3_init_hw(struct adapter *adapter, u32 fw_params)
3310f7917c00SJeff Kirsher {
3311f7917c00SJeff Kirsher 	int err = -EIO, attempts, i;
3312f7917c00SJeff Kirsher 	const struct vpd_params *vpd = &adapter->params.vpd;
3313f7917c00SJeff Kirsher 
3314f7917c00SJeff Kirsher 	if (adapter->params.rev > 0)
3315f7917c00SJeff Kirsher 		calibrate_xgm_t3b(adapter);
3316f7917c00SJeff Kirsher 	else if (calibrate_xgm(adapter))
3317f7917c00SJeff Kirsher 		goto out_err;
3318f7917c00SJeff Kirsher 
3319f7917c00SJeff Kirsher 	if (vpd->mclk) {
3320f7917c00SJeff Kirsher 		partition_mem(adapter, &adapter->params.tp);
3321f7917c00SJeff Kirsher 
3322f7917c00SJeff Kirsher 		if (mc7_init(&adapter->pmrx, vpd->mclk, vpd->mem_timing) ||
3323f7917c00SJeff Kirsher 		    mc7_init(&adapter->pmtx, vpd->mclk, vpd->mem_timing) ||
3324f7917c00SJeff Kirsher 		    mc7_init(&adapter->cm, vpd->mclk, vpd->mem_timing) ||
3325f7917c00SJeff Kirsher 		    t3_mc5_init(&adapter->mc5, adapter->params.mc5.nservers,
3326f7917c00SJeff Kirsher 				adapter->params.mc5.nfilters,
3327f7917c00SJeff Kirsher 				adapter->params.mc5.nroutes))
3328f7917c00SJeff Kirsher 			goto out_err;
3329f7917c00SJeff Kirsher 
3330f7917c00SJeff Kirsher 		for (i = 0; i < 32; i++)
3331f7917c00SJeff Kirsher 			if (clear_sge_ctxt(adapter, i, F_CQ))
3332f7917c00SJeff Kirsher 				goto out_err;
3333f7917c00SJeff Kirsher 	}
3334f7917c00SJeff Kirsher 
3335f7917c00SJeff Kirsher 	if (tp_init(adapter, &adapter->params.tp))
3336f7917c00SJeff Kirsher 		goto out_err;
3337f7917c00SJeff Kirsher 
3338f7917c00SJeff Kirsher 	t3_tp_set_coalescing_size(adapter,
3339f7917c00SJeff Kirsher 				  min(adapter->params.sge.max_pkt_size,
3340f7917c00SJeff Kirsher 				      MAX_RX_COALESCING_LEN), 1);
3341f7917c00SJeff Kirsher 	t3_tp_set_max_rxsize(adapter,
3342f7917c00SJeff Kirsher 			     min(adapter->params.sge.max_pkt_size, 16384U));
3343f7917c00SJeff Kirsher 	ulp_config(adapter, &adapter->params.tp);
3344f7917c00SJeff Kirsher 
3345f7917c00SJeff Kirsher 	if (is_pcie(adapter))
3346f7917c00SJeff Kirsher 		config_pcie(adapter);
3347f7917c00SJeff Kirsher 	else
3348f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_PCIX_CFG, 0,
3349f7917c00SJeff Kirsher 				 F_DMASTOPEN | F_CLIDECEN);
3350f7917c00SJeff Kirsher 
3351f7917c00SJeff Kirsher 	if (adapter->params.rev == T3_REV_C)
3352f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_ULPTX_CONFIG, 0,
3353f7917c00SJeff Kirsher 				 F_CFG_CQE_SOP_MASK);
3354f7917c00SJeff Kirsher 
3355f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
3356f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_PM1_RX_MODE, 0);
3357f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_PM1_TX_MODE, 0);
3358f7917c00SJeff Kirsher 	chan_init_hw(adapter, adapter->params.chan_map);
3359f7917c00SJeff Kirsher 	t3_sge_init(adapter, &adapter->params.sge);
3360f7917c00SJeff Kirsher 	t3_set_reg_field(adapter, A_PL_RST, 0, F_FATALPERREN);
3361f7917c00SJeff Kirsher 
3362f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter));
3363f7917c00SJeff Kirsher 
3364f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params);
3365f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_CIM_BOOT_CFG,
3366f7917c00SJeff Kirsher 		     V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2));
3367f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_CIM_BOOT_CFG);	/* flush */
3368f7917c00SJeff Kirsher 
3369f7917c00SJeff Kirsher 	attempts = 100;
3370f7917c00SJeff Kirsher 	do {			/* wait for uP to initialize */
3371f7917c00SJeff Kirsher 		msleep(20);
3372f7917c00SJeff Kirsher 	} while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts);
3373f7917c00SJeff Kirsher 	if (!attempts) {
3374f7917c00SJeff Kirsher 		CH_ERR(adapter, "uP initialization timed out\n");
3375f7917c00SJeff Kirsher 		goto out_err;
3376f7917c00SJeff Kirsher 	}
3377f7917c00SJeff Kirsher 
3378f7917c00SJeff Kirsher 	err = 0;
3379f7917c00SJeff Kirsher out_err:
3380f7917c00SJeff Kirsher 	return err;
3381f7917c00SJeff Kirsher }
3382f7917c00SJeff Kirsher 
3383f7917c00SJeff Kirsher /**
3384f7917c00SJeff Kirsher  *	get_pci_mode - determine a card's PCI mode
3385f7917c00SJeff Kirsher  *	@adapter: the adapter
3386f7917c00SJeff Kirsher  *	@p: where to store the PCI settings
3387f7917c00SJeff Kirsher  *
3388f7917c00SJeff Kirsher  *	Determines a card's PCI mode and associated parameters, such as speed
3389f7917c00SJeff Kirsher  *	and width.
3390f7917c00SJeff Kirsher  */
get_pci_mode(struct adapter * adapter,struct pci_params * p)3391f7917c00SJeff Kirsher static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
3392f7917c00SJeff Kirsher {
3393f7917c00SJeff Kirsher 	static unsigned short speed_map[] = { 33, 66, 100, 133 };
3394c772b44eSJiang Liu 	u32 pci_mode;
3395f7917c00SJeff Kirsher 
3396c772b44eSJiang Liu 	if (pci_is_pcie(adapter->pdev)) {
3397f7917c00SJeff Kirsher 		u16 val;
3398f7917c00SJeff Kirsher 
3399f7917c00SJeff Kirsher 		p->variant = PCI_VARIANT_PCIE;
3400c772b44eSJiang Liu 		pcie_capability_read_word(adapter->pdev, PCI_EXP_LNKSTA, &val);
3401f7917c00SJeff Kirsher 		p->width = (val >> 4) & 0x3f;
3402f7917c00SJeff Kirsher 		return;
3403f7917c00SJeff Kirsher 	}
3404f7917c00SJeff Kirsher 
3405f7917c00SJeff Kirsher 	pci_mode = t3_read_reg(adapter, A_PCIX_MODE);
3406f7917c00SJeff Kirsher 	p->speed = speed_map[G_PCLKRANGE(pci_mode)];
3407f7917c00SJeff Kirsher 	p->width = (pci_mode & F_64BIT) ? 64 : 32;
3408f7917c00SJeff Kirsher 	pci_mode = G_PCIXINITPAT(pci_mode);
3409f7917c00SJeff Kirsher 	if (pci_mode == 0)
3410f7917c00SJeff Kirsher 		p->variant = PCI_VARIANT_PCI;
3411f7917c00SJeff Kirsher 	else if (pci_mode < 4)
3412f7917c00SJeff Kirsher 		p->variant = PCI_VARIANT_PCIX_MODE1_PARITY;
3413f7917c00SJeff Kirsher 	else if (pci_mode < 8)
3414f7917c00SJeff Kirsher 		p->variant = PCI_VARIANT_PCIX_MODE1_ECC;
3415f7917c00SJeff Kirsher 	else
3416f7917c00SJeff Kirsher 		p->variant = PCI_VARIANT_PCIX_266_MODE2;
3417f7917c00SJeff Kirsher }
3418f7917c00SJeff Kirsher 
3419f7917c00SJeff Kirsher /**
3420f7917c00SJeff Kirsher  *	init_link_config - initialize a link's SW state
3421f7917c00SJeff Kirsher  *	@lc: structure holding the link state
3422d0ea5cbdSJesse Brandeburg  *	@caps: information about the current card
3423f7917c00SJeff Kirsher  *
3424f7917c00SJeff Kirsher  *	Initializes the SW state maintained for each link, including the link's
3425f7917c00SJeff Kirsher  *	capabilities and default speed/duplex/flow-control/autonegotiation
3426f7917c00SJeff Kirsher  *	settings.
3427f7917c00SJeff Kirsher  */
init_link_config(struct link_config * lc,unsigned int caps)3428f7917c00SJeff Kirsher static void init_link_config(struct link_config *lc, unsigned int caps)
3429f7917c00SJeff Kirsher {
3430f7917c00SJeff Kirsher 	lc->supported = caps;
3431f7917c00SJeff Kirsher 	lc->requested_speed = lc->speed = SPEED_INVALID;
3432f7917c00SJeff Kirsher 	lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
3433f7917c00SJeff Kirsher 	lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
3434f7917c00SJeff Kirsher 	if (lc->supported & SUPPORTED_Autoneg) {
3435f7917c00SJeff Kirsher 		lc->advertising = lc->supported;
3436f7917c00SJeff Kirsher 		lc->autoneg = AUTONEG_ENABLE;
3437f7917c00SJeff Kirsher 		lc->requested_fc |= PAUSE_AUTONEG;
3438f7917c00SJeff Kirsher 	} else {
3439f7917c00SJeff Kirsher 		lc->advertising = 0;
3440f7917c00SJeff Kirsher 		lc->autoneg = AUTONEG_DISABLE;
3441f7917c00SJeff Kirsher 	}
3442f7917c00SJeff Kirsher }
3443f7917c00SJeff Kirsher 
3444f7917c00SJeff Kirsher /**
3445f7917c00SJeff Kirsher  *	mc7_calc_size - calculate MC7 memory size
3446f7917c00SJeff Kirsher  *	@cfg: the MC7 configuration
3447f7917c00SJeff Kirsher  *
3448f7917c00SJeff Kirsher  *	Calculates the size of an MC7 memory in bytes from the value of its
3449f7917c00SJeff Kirsher  *	configuration register.
3450f7917c00SJeff Kirsher  */
mc7_calc_size(u32 cfg)3451f7917c00SJeff Kirsher static unsigned int mc7_calc_size(u32 cfg)
3452f7917c00SJeff Kirsher {
3453f7917c00SJeff Kirsher 	unsigned int width = G_WIDTH(cfg);
3454f7917c00SJeff Kirsher 	unsigned int banks = !!(cfg & F_BKS) + 1;
3455f7917c00SJeff Kirsher 	unsigned int org = !!(cfg & F_ORG) + 1;
3456f7917c00SJeff Kirsher 	unsigned int density = G_DEN(cfg);
3457f7917c00SJeff Kirsher 	unsigned int MBs = ((256 << density) * banks) / (org << width);
3458f7917c00SJeff Kirsher 
3459f7917c00SJeff Kirsher 	return MBs << 20;
3460f7917c00SJeff Kirsher }
3461f7917c00SJeff Kirsher 
mc7_prep(struct adapter * adapter,struct mc7 * mc7,unsigned int base_addr,const char * name)3462f7917c00SJeff Kirsher static void mc7_prep(struct adapter *adapter, struct mc7 *mc7,
3463f7917c00SJeff Kirsher 		     unsigned int base_addr, const char *name)
3464f7917c00SJeff Kirsher {
3465f7917c00SJeff Kirsher 	u32 cfg;
3466f7917c00SJeff Kirsher 
3467f7917c00SJeff Kirsher 	mc7->adapter = adapter;
3468f7917c00SJeff Kirsher 	mc7->name = name;
3469f7917c00SJeff Kirsher 	mc7->offset = base_addr - MC7_PMRX_BASE_ADDR;
3470f7917c00SJeff Kirsher 	cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
3471f7917c00SJeff Kirsher 	mc7->size = G_DEN(cfg) == M_DEN ? 0 : mc7_calc_size(cfg);
3472f7917c00SJeff Kirsher 	mc7->width = G_WIDTH(cfg);
3473f7917c00SJeff Kirsher }
3474f7917c00SJeff Kirsher 
mac_prep(struct cmac * mac,struct adapter * adapter,int index)3475f7917c00SJeff Kirsher static void mac_prep(struct cmac *mac, struct adapter *adapter, int index)
3476f7917c00SJeff Kirsher {
3477f7917c00SJeff Kirsher 	u16 devid;
3478f7917c00SJeff Kirsher 
3479f7917c00SJeff Kirsher 	mac->adapter = adapter;
3480f7917c00SJeff Kirsher 	pci_read_config_word(adapter->pdev, 0x2, &devid);
3481f7917c00SJeff Kirsher 
3482f7917c00SJeff Kirsher 	if (devid == 0x37 && !adapter->params.vpd.xauicfg[1])
3483f7917c00SJeff Kirsher 		index = 0;
3484f7917c00SJeff Kirsher 	mac->offset = (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR) * index;
3485f7917c00SJeff Kirsher 	mac->nucast = 1;
3486f7917c00SJeff Kirsher 
3487f7917c00SJeff Kirsher 	if (adapter->params.rev == 0 && uses_xaui(adapter)) {
3488f7917c00SJeff Kirsher 		t3_write_reg(adapter, A_XGM_SERDES_CTRL + mac->offset,
3489f7917c00SJeff Kirsher 			     is_10G(adapter) ? 0x2901c04 : 0x2301c04);
3490f7917c00SJeff Kirsher 		t3_set_reg_field(adapter, A_XGM_PORT_CFG + mac->offset,
3491f7917c00SJeff Kirsher 				 F_ENRGMII, 0);
3492f7917c00SJeff Kirsher 	}
3493f7917c00SJeff Kirsher }
3494f7917c00SJeff Kirsher 
early_hw_init(struct adapter * adapter,const struct adapter_info * ai)3495f7917c00SJeff Kirsher static void early_hw_init(struct adapter *adapter,
3496f7917c00SJeff Kirsher 			  const struct adapter_info *ai)
3497f7917c00SJeff Kirsher {
3498f7917c00SJeff Kirsher 	u32 val = V_PORTSPEED(is_10G(adapter) ? 3 : 2);
3499f7917c00SJeff Kirsher 
3500f7917c00SJeff Kirsher 	mi1_init(adapter, ai);
3501f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_I2C_CFG,	/* set for 80KHz */
3502f7917c00SJeff Kirsher 		     V_I2C_CLKDIV(adapter->params.vpd.cclk / 80 - 1));
3503f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_T3DBG_GPIO_EN,
3504f7917c00SJeff Kirsher 		     ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL);
3505f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0);
3506f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_SG_OCO_BASE, V_BASE1(0xfff));
3507f7917c00SJeff Kirsher 
3508f7917c00SJeff Kirsher 	if (adapter->params.rev == 0 || !uses_xaui(adapter))
3509f7917c00SJeff Kirsher 		val |= F_ENRGMII;
3510f7917c00SJeff Kirsher 
3511f7917c00SJeff Kirsher 	/* Enable MAC clocks so we can access the registers */
3512f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_XGM_PORT_CFG, val);
3513f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_XGM_PORT_CFG);
3514f7917c00SJeff Kirsher 
3515f7917c00SJeff Kirsher 	val |= F_CLKDIVRESET_;
3516f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_XGM_PORT_CFG, val);
3517f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_XGM_PORT_CFG);
3518f7917c00SJeff Kirsher 	t3_write_reg(adapter, XGM_REG(A_XGM_PORT_CFG, 1), val);
3519f7917c00SJeff Kirsher 	t3_read_reg(adapter, A_XGM_PORT_CFG);
3520f7917c00SJeff Kirsher }
3521f7917c00SJeff Kirsher 
3522f7917c00SJeff Kirsher /*
3523f7917c00SJeff Kirsher  * Reset the adapter.
3524f7917c00SJeff Kirsher  * Older PCIe cards lose their config space during reset, PCI-X
3525f7917c00SJeff Kirsher  * ones don't.
3526f7917c00SJeff Kirsher  */
t3_reset_adapter(struct adapter * adapter)3527f7917c00SJeff Kirsher int t3_reset_adapter(struct adapter *adapter)
3528f7917c00SJeff Kirsher {
3529f7917c00SJeff Kirsher 	int i, save_and_restore_pcie =
3530f7917c00SJeff Kirsher 	    adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
3531f7917c00SJeff Kirsher 	uint16_t devid = 0;
3532f7917c00SJeff Kirsher 
3533f7917c00SJeff Kirsher 	if (save_and_restore_pcie)
3534f7917c00SJeff Kirsher 		pci_save_state(adapter->pdev);
3535f7917c00SJeff Kirsher 	t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE);
3536f7917c00SJeff Kirsher 
3537f7917c00SJeff Kirsher 	/*
3538f7917c00SJeff Kirsher 	 * Delay. Give Some time to device to reset fully.
3539f7917c00SJeff Kirsher 	 * XXX The delay time should be modified.
3540f7917c00SJeff Kirsher 	 */
3541f7917c00SJeff Kirsher 	for (i = 0; i < 10; i++) {
3542f7917c00SJeff Kirsher 		msleep(50);
3543f7917c00SJeff Kirsher 		pci_read_config_word(adapter->pdev, 0x00, &devid);
3544f7917c00SJeff Kirsher 		if (devid == 0x1425)
3545f7917c00SJeff Kirsher 			break;
3546f7917c00SJeff Kirsher 	}
3547f7917c00SJeff Kirsher 
3548f7917c00SJeff Kirsher 	if (devid != 0x1425)
3549f7917c00SJeff Kirsher 		return -1;
3550f7917c00SJeff Kirsher 
3551f7917c00SJeff Kirsher 	if (save_and_restore_pcie)
3552f7917c00SJeff Kirsher 		pci_restore_state(adapter->pdev);
3553f7917c00SJeff Kirsher 	return 0;
3554f7917c00SJeff Kirsher }
3555f7917c00SJeff Kirsher 
init_parity(struct adapter * adap)3556f7917c00SJeff Kirsher static int init_parity(struct adapter *adap)
3557f7917c00SJeff Kirsher {
3558f7917c00SJeff Kirsher 	int i, err, addr;
3559f7917c00SJeff Kirsher 
3560f7917c00SJeff Kirsher 	if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
3561f7917c00SJeff Kirsher 		return -EBUSY;
3562f7917c00SJeff Kirsher 
3563f7917c00SJeff Kirsher 	for (err = i = 0; !err && i < 16; i++)
3564f7917c00SJeff Kirsher 		err = clear_sge_ctxt(adap, i, F_EGRESS);
3565f7917c00SJeff Kirsher 	for (i = 0xfff0; !err && i <= 0xffff; i++)
3566f7917c00SJeff Kirsher 		err = clear_sge_ctxt(adap, i, F_EGRESS);
3567f7917c00SJeff Kirsher 	for (i = 0; !err && i < SGE_QSETS; i++)
3568f7917c00SJeff Kirsher 		err = clear_sge_ctxt(adap, i, F_RESPONSEQ);
3569f7917c00SJeff Kirsher 	if (err)
3570f7917c00SJeff Kirsher 		return err;
3571f7917c00SJeff Kirsher 
3572f7917c00SJeff Kirsher 	t3_write_reg(adap, A_CIM_IBQ_DBG_DATA, 0);
3573f7917c00SJeff Kirsher 	for (i = 0; i < 4; i++)
3574f7917c00SJeff Kirsher 		for (addr = 0; addr <= M_IBQDBGADDR; addr++) {
3575f7917c00SJeff Kirsher 			t3_write_reg(adap, A_CIM_IBQ_DBG_CFG, F_IBQDBGEN |
3576f7917c00SJeff Kirsher 				     F_IBQDBGWR | V_IBQDBGQID(i) |
3577f7917c00SJeff Kirsher 				     V_IBQDBGADDR(addr));
3578f7917c00SJeff Kirsher 			err = t3_wait_op_done(adap, A_CIM_IBQ_DBG_CFG,
3579f7917c00SJeff Kirsher 					      F_IBQDBGBUSY, 0, 2, 1);
3580f7917c00SJeff Kirsher 			if (err)
3581f7917c00SJeff Kirsher 				return err;
3582f7917c00SJeff Kirsher 		}
3583f7917c00SJeff Kirsher 	return 0;
3584f7917c00SJeff Kirsher }
3585f7917c00SJeff Kirsher 
3586f7917c00SJeff Kirsher /*
3587f7917c00SJeff Kirsher  * Initialize adapter SW state for the various HW modules, set initial values
3588f7917c00SJeff Kirsher  * for some adapter tunables, take PHYs out of reset, and initialize the MDIO
3589f7917c00SJeff Kirsher  * interface.
3590f7917c00SJeff Kirsher  */
t3_prep_adapter(struct adapter * adapter,const struct adapter_info * ai,int reset)3591f7917c00SJeff Kirsher int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
3592f7917c00SJeff Kirsher 		    int reset)
3593f7917c00SJeff Kirsher {
3594f7917c00SJeff Kirsher 	int ret;
3595f7917c00SJeff Kirsher 	unsigned int i, j = -1;
3596f7917c00SJeff Kirsher 
3597f7917c00SJeff Kirsher 	get_pci_mode(adapter, &adapter->params.pci);
3598f7917c00SJeff Kirsher 
3599f7917c00SJeff Kirsher 	adapter->params.info = ai;
3600f7917c00SJeff Kirsher 	adapter->params.nports = ai->nports0 + ai->nports1;
3601f7917c00SJeff Kirsher 	adapter->params.chan_map = (!!ai->nports0) | (!!ai->nports1 << 1);
3602f7917c00SJeff Kirsher 	adapter->params.rev = t3_read_reg(adapter, A_PL_REV);
3603f7917c00SJeff Kirsher 	/*
3604f7917c00SJeff Kirsher 	 * We used to only run the "adapter check task" once a second if
3605f7917c00SJeff Kirsher 	 * we had PHYs which didn't support interrupts (we would check
3606f7917c00SJeff Kirsher 	 * their link status once a second).  Now we check other conditions
3607f7917c00SJeff Kirsher 	 * in that routine which could potentially impose a very high
3608f7917c00SJeff Kirsher 	 * interrupt load on the system.  As such, we now always scan the
3609f7917c00SJeff Kirsher 	 * adapter state once a second ...
3610f7917c00SJeff Kirsher 	 */
3611f7917c00SJeff Kirsher 	adapter->params.linkpoll_period = 10;
3612f7917c00SJeff Kirsher 	adapter->params.stats_update_period = is_10G(adapter) ?
3613f7917c00SJeff Kirsher 	    MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10);
3614f7917c00SJeff Kirsher 	adapter->params.pci.vpd_cap_addr =
3615f7917c00SJeff Kirsher 	    pci_find_capability(adapter->pdev, PCI_CAP_ID_VPD);
3616*767b9825SJia-Ju Bai 	if (!adapter->params.pci.vpd_cap_addr)
3617*767b9825SJia-Ju Bai 		return -ENODEV;
3618f7917c00SJeff Kirsher 	ret = get_vpd_params(adapter, &adapter->params.vpd);
3619f7917c00SJeff Kirsher 	if (ret < 0)
3620f7917c00SJeff Kirsher 		return ret;
3621f7917c00SJeff Kirsher 
3622f7917c00SJeff Kirsher 	if (reset && t3_reset_adapter(adapter))
3623f7917c00SJeff Kirsher 		return -1;
3624f7917c00SJeff Kirsher 
3625f7917c00SJeff Kirsher 	t3_sge_prep(adapter, &adapter->params.sge);
3626f7917c00SJeff Kirsher 
3627f7917c00SJeff Kirsher 	if (adapter->params.vpd.mclk) {
3628f7917c00SJeff Kirsher 		struct tp_params *p = &adapter->params.tp;
3629f7917c00SJeff Kirsher 
3630f7917c00SJeff Kirsher 		mc7_prep(adapter, &adapter->pmrx, MC7_PMRX_BASE_ADDR, "PMRX");
3631f7917c00SJeff Kirsher 		mc7_prep(adapter, &adapter->pmtx, MC7_PMTX_BASE_ADDR, "PMTX");
3632f7917c00SJeff Kirsher 		mc7_prep(adapter, &adapter->cm, MC7_CM_BASE_ADDR, "CM");
3633f7917c00SJeff Kirsher 
3634f7917c00SJeff Kirsher 		p->nchan = adapter->params.chan_map == 3 ? 2 : 1;
3635f7917c00SJeff Kirsher 		p->pmrx_size = t3_mc7_size(&adapter->pmrx);
3636f7917c00SJeff Kirsher 		p->pmtx_size = t3_mc7_size(&adapter->pmtx);
3637f7917c00SJeff Kirsher 		p->cm_size = t3_mc7_size(&adapter->cm);
3638f7917c00SJeff Kirsher 		p->chan_rx_size = p->pmrx_size / 2;	/* only 1 Rx channel */
3639f7917c00SJeff Kirsher 		p->chan_tx_size = p->pmtx_size / p->nchan;
3640f7917c00SJeff Kirsher 		p->rx_pg_size = 64 * 1024;
3641f7917c00SJeff Kirsher 		p->tx_pg_size = is_10G(adapter) ? 64 * 1024 : 16 * 1024;
3642f7917c00SJeff Kirsher 		p->rx_num_pgs = pm_num_pages(p->chan_rx_size, p->rx_pg_size);
3643f7917c00SJeff Kirsher 		p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size);
3644f7917c00SJeff Kirsher 		p->ntimer_qs = p->cm_size >= (128 << 20) ||
3645f7917c00SJeff Kirsher 		    adapter->params.rev > 0 ? 12 : 6;
3646f7917c00SJeff Kirsher 	}
3647f7917c00SJeff Kirsher 
3648f7917c00SJeff Kirsher 	adapter->params.offload = t3_mc7_size(&adapter->pmrx) &&
3649f7917c00SJeff Kirsher 				  t3_mc7_size(&adapter->pmtx) &&
3650f7917c00SJeff Kirsher 				  t3_mc7_size(&adapter->cm);
3651f7917c00SJeff Kirsher 
3652f7917c00SJeff Kirsher 	if (is_offload(adapter)) {
3653f7917c00SJeff Kirsher 		adapter->params.mc5.nservers = DEFAULT_NSERVERS;
3654f7917c00SJeff Kirsher 		adapter->params.mc5.nfilters = adapter->params.rev > 0 ?
3655f7917c00SJeff Kirsher 		    DEFAULT_NFILTERS : 0;
3656f7917c00SJeff Kirsher 		adapter->params.mc5.nroutes = 0;
3657f7917c00SJeff Kirsher 		t3_mc5_prep(adapter, &adapter->mc5, MC5_MODE_144_BIT);
3658f7917c00SJeff Kirsher 
3659f7917c00SJeff Kirsher 		init_mtus(adapter->params.mtus);
3660f7917c00SJeff Kirsher 		init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
3661f7917c00SJeff Kirsher 	}
3662f7917c00SJeff Kirsher 
3663f7917c00SJeff Kirsher 	early_hw_init(adapter, ai);
3664f7917c00SJeff Kirsher 	ret = init_parity(adapter);
3665f7917c00SJeff Kirsher 	if (ret)
3666f7917c00SJeff Kirsher 		return ret;
3667f7917c00SJeff Kirsher 
3668f7917c00SJeff Kirsher 	for_each_port(adapter, i) {
3669f7917c00SJeff Kirsher 		u8 hw_addr[6];
3670f7917c00SJeff Kirsher 		const struct port_type_info *pti;
3671f7917c00SJeff Kirsher 		struct port_info *p = adap2pinfo(adapter, i);
3672f7917c00SJeff Kirsher 
3673f7917c00SJeff Kirsher 		while (!adapter->params.vpd.port_type[++j])
3674f7917c00SJeff Kirsher 			;
3675f7917c00SJeff Kirsher 
3676f7917c00SJeff Kirsher 		pti = &port_types[adapter->params.vpd.port_type[j]];
3677f7917c00SJeff Kirsher 		if (!pti->phy_prep) {
3678f7917c00SJeff Kirsher 			CH_ALERT(adapter, "Invalid port type index %d\n",
3679f7917c00SJeff Kirsher 				 adapter->params.vpd.port_type[j]);
3680f7917c00SJeff Kirsher 			return -EINVAL;
3681f7917c00SJeff Kirsher 		}
3682f7917c00SJeff Kirsher 
3683f7917c00SJeff Kirsher 		p->phy.mdio.dev = adapter->port[i];
3684f7917c00SJeff Kirsher 		ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
3685f7917c00SJeff Kirsher 				    ai->mdio_ops);
3686f7917c00SJeff Kirsher 		if (ret)
3687f7917c00SJeff Kirsher 			return ret;
3688f7917c00SJeff Kirsher 		mac_prep(&p->mac, adapter, j);
3689f7917c00SJeff Kirsher 
3690f7917c00SJeff Kirsher 		/*
3691f7917c00SJeff Kirsher 		 * The VPD EEPROM stores the base Ethernet address for the
3692f7917c00SJeff Kirsher 		 * card.  A port's address is derived from the base by adding
3693f7917c00SJeff Kirsher 		 * the port's index to the base's low octet.
3694f7917c00SJeff Kirsher 		 */
3695f7917c00SJeff Kirsher 		memcpy(hw_addr, adapter->params.vpd.eth_base, 5);
3696f7917c00SJeff Kirsher 		hw_addr[5] = adapter->params.vpd.eth_base[5] + i;
3697f7917c00SJeff Kirsher 
369847d71f45SJakub Kicinski 		eth_hw_addr_set(adapter->port[i], hw_addr);
3699f7917c00SJeff Kirsher 		init_link_config(&p->link_config, p->phy.caps);
3700f7917c00SJeff Kirsher 		p->phy.ops->power_down(&p->phy, 1);
3701f7917c00SJeff Kirsher 
3702f7917c00SJeff Kirsher 		/*
3703f7917c00SJeff Kirsher 		 * If the PHY doesn't support interrupts for link status
3704f7917c00SJeff Kirsher 		 * changes, schedule a scan of the adapter links at least
3705f7917c00SJeff Kirsher 		 * once a second.
3706f7917c00SJeff Kirsher 		 */
3707f7917c00SJeff Kirsher 		if (!(p->phy.caps & SUPPORTED_IRQ) &&
3708f7917c00SJeff Kirsher 		    adapter->params.linkpoll_period > 10)
3709f7917c00SJeff Kirsher 			adapter->params.linkpoll_period = 10;
3710f7917c00SJeff Kirsher 	}
3711f7917c00SJeff Kirsher 
3712f7917c00SJeff Kirsher 	return 0;
3713f7917c00SJeff Kirsher }
3714f7917c00SJeff Kirsher 
t3_led_ready(struct adapter * adapter)3715f7917c00SJeff Kirsher void t3_led_ready(struct adapter *adapter)
3716f7917c00SJeff Kirsher {
3717f7917c00SJeff Kirsher 	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL,
3718f7917c00SJeff Kirsher 			 F_GPIO0_OUT_VAL);
3719f7917c00SJeff Kirsher }
3720f7917c00SJeff Kirsher 
t3_replay_prep_adapter(struct adapter * adapter)3721f7917c00SJeff Kirsher int t3_replay_prep_adapter(struct adapter *adapter)
3722f7917c00SJeff Kirsher {
3723f7917c00SJeff Kirsher 	const struct adapter_info *ai = adapter->params.info;
3724f7917c00SJeff Kirsher 	unsigned int i, j = -1;
3725f7917c00SJeff Kirsher 	int ret;
3726f7917c00SJeff Kirsher 
3727f7917c00SJeff Kirsher 	early_hw_init(adapter, ai);
3728f7917c00SJeff Kirsher 	ret = init_parity(adapter);
3729f7917c00SJeff Kirsher 	if (ret)
3730f7917c00SJeff Kirsher 		return ret;
3731f7917c00SJeff Kirsher 
3732f7917c00SJeff Kirsher 	for_each_port(adapter, i) {
3733f7917c00SJeff Kirsher 		const struct port_type_info *pti;
3734f7917c00SJeff Kirsher 		struct port_info *p = adap2pinfo(adapter, i);
3735f7917c00SJeff Kirsher 
3736f7917c00SJeff Kirsher 		while (!adapter->params.vpd.port_type[++j])
3737f7917c00SJeff Kirsher 			;
3738f7917c00SJeff Kirsher 
3739f7917c00SJeff Kirsher 		pti = &port_types[adapter->params.vpd.port_type[j]];
3740f7917c00SJeff Kirsher 		ret = pti->phy_prep(&p->phy, adapter, p->phy.mdio.prtad, NULL);
3741f7917c00SJeff Kirsher 		if (ret)
3742f7917c00SJeff Kirsher 			return ret;
3743f7917c00SJeff Kirsher 		p->phy.ops->power_down(&p->phy, 1);
3744f7917c00SJeff Kirsher 	}
3745f7917c00SJeff Kirsher 
3746f7917c00SJeff Kirsher 	return 0;
3747f7917c00SJeff Kirsher }
3748f7917c00SJeff Kirsher 
3749