xref: /freebsd/sys/dev/cxgb/common/cxgb_xgmac.c (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
1 /**************************************************************************
2 SPDX-License-Identifier: BSD-2-Clause
3 
4 Copyright (c) 2007-2009 Chelsio Inc.
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10  1. Redistributions of source code must retain the above copyright notice,
11     this list of conditions and the following disclaimer.
12 
13  2. Neither the name of the Chelsio Corporation nor the names of its
14     contributors may be used to endorse or promote products derived from
15     this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
28 
29 ***************************************************************************/
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include <cxgb_include.h>
35 
36 #undef msleep
37 #define msleep t3_os_sleep
38 
39 
40 static inline int macidx(const struct cmac *mac)
41 {
42 	return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR);
43 }
44 
45 /*
46  * Returns a reasonable A_XGM_RESET_CTRL value for the mac specified.
47  */
48 static inline int xgm_reset_ctrl(const struct cmac *mac)
49 {
50 	adapter_t *adap = mac->adapter;
51 	int val = F_MAC_RESET_ | F_XGMAC_STOP_EN;
52 
53 	if (is_10G(adap)) {
54 		int cfg = t3_read_reg(adap, A_XGM_PORT_CFG + mac->offset);
55 
56 		val |= F_PCS_RESET_;
57 		if (G_PORTSPEED(cfg) != 3)	/* not running at 10G */
58 			val |= F_XG2G_RESET_;
59 	} else if (uses_xaui(adap))
60 		val |= F_PCS_RESET_ | F_XG2G_RESET_;
61 	else
62 		val |= F_RGMII_RESET_ | F_XG2G_RESET_;
63 
64 	return (val);
65 }
66 
67 static void xaui_serdes_reset(struct cmac *mac)
68 {
69 	static const unsigned int clear[] = {
70 		F_PWRDN0 | F_PWRDN1,    F_RESETPLL01,    F_RESET0 | F_RESET1,
71 	     	F_PWRDN2 | F_PWRDN3,    F_RESETPLL23,    F_RESET2 | F_RESET3
72 	};
73 
74 	int i;
75 	adapter_t *adap = mac->adapter;
76 	u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset;
77 
78 	t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] |
79 		     F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 |
80 		     F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 |
81 		     F_RESETPLL23 | F_RESETPLL01);
82 	(void)t3_read_reg(adap, ctrl);
83 	udelay(15);
84 
85 	for (i = 0; i < ARRAY_SIZE(clear); i++) {
86 		t3_set_reg_field(adap, ctrl, clear[i], 0);
87 		udelay(15);
88 	}
89 }
90 
91 /**
92  *	t3b_pcs_reset - reset the PCS on T3B+ adapters
93  *	@mac: the XGMAC handle
94  *
95  *	Reset the XGMAC PCS block on T3B+ adapters.
96  */
97 void t3b_pcs_reset(struct cmac *mac)
98 {
99 	t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
100 			 F_PCS_RESET_, 0);
101 
102 	/* No delay required */
103 
104 	t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0,
105 			 F_PCS_RESET_);
106 }
107 
108 void t3c_pcs_force_los(struct cmac *mac)
109 {
110 	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT0 + mac->offset,
111 	    F_LOWSIGFORCEEN0 | F_LOWSIGFORCEVALUE0,
112 	    F_LOWSIGFORCEEN0 | F_LOWSIGFORCEVALUE0);
113 	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT1 + mac->offset,
114 	    F_LOWSIGFORCEEN1 | F_LOWSIGFORCEVALUE1,
115 	    F_LOWSIGFORCEEN1 | F_LOWSIGFORCEVALUE1);
116 	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT2 + mac->offset,
117 	    F_LOWSIGFORCEEN2 | F_LOWSIGFORCEVALUE2,
118 	    F_LOWSIGFORCEEN2 | F_LOWSIGFORCEVALUE2);
119 	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT3 + mac->offset,
120 	    F_LOWSIGFORCEEN3 | F_LOWSIGFORCEVALUE3,
121 	    F_LOWSIGFORCEEN3 | F_LOWSIGFORCEVALUE3);
122 
123 	/* No delay required */
124 
125 	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT0 + mac->offset,
126 	    F_LOWSIGFORCEEN0, 0);
127 	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT1 + mac->offset,
128 	    F_LOWSIGFORCEEN1, 0);
129 	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT2 + mac->offset,
130 	    F_LOWSIGFORCEEN2, 0);
131 	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT3 + mac->offset,
132 	    F_LOWSIGFORCEEN3, 0);
133 }
134 
135 /**
136  *	t3_mac_init - initialize a MAC
137  *	@mac: the MAC to initialize
138  *
139  *	Initialize the given MAC.
140  */
141 int t3_mac_init(struct cmac *mac)
142 {
143 	static struct addr_val_pair mac_reset_avp[] = {
144 		{ A_XGM_TX_CTRL, 0 },
145 		{ A_XGM_RX_CTRL, 0 },
146 		{ A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES |
147 		                F_RMFCS | F_ENJUMBO | F_ENHASHMCAST },
148 		{ A_XGM_RX_HASH_LOW, 0 },
149 		{ A_XGM_RX_HASH_HIGH, 0 },
150 		{ A_XGM_RX_EXACT_MATCH_LOW_1, 0 },
151 		{ A_XGM_RX_EXACT_MATCH_LOW_2, 0 },
152 		{ A_XGM_RX_EXACT_MATCH_LOW_3, 0 },
153 		{ A_XGM_RX_EXACT_MATCH_LOW_4, 0 },
154 		{ A_XGM_RX_EXACT_MATCH_LOW_5, 0 },
155 		{ A_XGM_RX_EXACT_MATCH_LOW_6, 0 },
156 		{ A_XGM_RX_EXACT_MATCH_LOW_7, 0 },
157 		{ A_XGM_RX_EXACT_MATCH_LOW_8, 0 },
158 		{ A_XGM_STAT_CTRL, F_CLRSTATS }
159 	};
160 	u32 val;
161 	adapter_t *adap = mac->adapter;
162 	unsigned int oft = mac->offset;
163 
164 	t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
165 	(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft);    /* flush */
166 
167 	t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft);
168 	t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft,
169 			 F_RXSTRFRWRD | F_DISERRFRAMES,
170 			 uses_xaui(adap) ? 0 : F_RXSTRFRWRD);
171 	t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX);
172 
173 	if (uses_xaui(adap)) {
174 		if (adap->params.rev == 0) {
175 			t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
176 					 F_RXENABLE | F_TXENABLE);
177 			if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft,
178 					    F_CMULOCK, 1, 5, 2)) {
179 				CH_ERR(adap,
180 				       "MAC %d XAUI SERDES CMU lock failed\n",
181 				       macidx(mac));
182 				return -1;
183 			}
184 			t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
185 					 F_SERDESRESET_);
186 		} else
187 			xaui_serdes_reset(mac);
188 	}
189 
190 
191 	if (mac->multiport) {
192 		t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
193 			     V_RXMAXPKTSIZE(MAX_FRAME_SIZE - 4));
194 		t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0,
195 				 F_DISPREAMBLE);
196 		t3_set_reg_field(adap, A_XGM_RX_CFG + oft, 0, F_COPYPREAMBLE |
197 				 F_ENNON802_3PREAMBLE);
198 		t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft,
199 				 V_TXFIFOTHRESH(M_TXFIFOTHRESH),
200 				 V_TXFIFOTHRESH(64));
201 		t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
202 		t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
203 	}
204 
205 	t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
206 			 V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE),
207 			 V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER);
208 
209 	val = xgm_reset_ctrl(mac);
210 	t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
211 	(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft);  /* flush */
212 	if ((val & F_PCS_RESET_) && adap->params.rev) {
213 		msleep(1);
214 		t3b_pcs_reset(mac);
215 	}
216 
217 	memset(&mac->stats, 0, sizeof(mac->stats));
218 	return 0;
219 }
220 
221 static int t3_mac_reset(struct cmac *mac, int portspeed)
222 {
223 	u32 val, store_mps;
224 	adapter_t *adap = mac->adapter;
225 	unsigned int oft = mac->offset;
226 	int idx = macidx(mac);
227 	unsigned int store;
228 
229 	/* Stop egress traffic to xgm*/
230 	store_mps = t3_read_reg(adap, A_MPS_CFG);
231 	if (!idx)
232 		t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
233 	else
234 		t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
235 
236 	/* This will reduce the number of TXTOGGLES */
237 	/* Clear: to stop the NIC traffic */
238 	t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0);
239 	/* Ensure TX drains */
240 	t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0);
241 
242 	/* PCS in reset */
243 	t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
244 	(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft);    /* flush */
245 
246 	/* Store A_TP_TX_DROP_CFG_CH0 */
247 	t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
248 	store = t3_read_reg(adap, A_TP_PIO_DATA);
249 
250 	msleep(10);
251 
252 	/* Change DROP_CFG to 0xc0000011 */
253 	t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
254 	t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011);
255 
256 	/* Check for xgm Rx fifo empty */
257 	/* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */
258 	if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
259 			    0x80000000, 1, 1000, 2) && portspeed < 0) {
260 		CH_ERR(adap, "MAC %d Rx fifo drain failed\n", idx);
261 		return -1;
262 	}
263 
264 	if (portspeed >= 0) {
265 		u32 intr = t3_read_reg(adap, A_XGM_INT_ENABLE + oft);
266 
267 		/*
268 		 * safespeedchange: wipes out pretty much all XGMAC registers.
269 		 */
270 
271 		t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
272 		    V_PORTSPEED(M_PORTSPEED) | F_SAFESPEEDCHANGE,
273 		    portspeed | F_SAFESPEEDCHANGE);
274 		(void) t3_read_reg(adap, A_XGM_PORT_CFG + oft);
275 		t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
276 		    F_SAFESPEEDCHANGE, 0);
277 		(void) t3_read_reg(adap, A_XGM_PORT_CFG + oft);
278 		t3_mac_init(mac);
279 
280 		t3_write_reg(adap, A_XGM_INT_ENABLE + oft, intr);
281 	} else {
282 
283 		t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); /*MAC in reset*/
284 		(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft);    /* flush */
285 
286 		val = xgm_reset_ctrl(mac);
287 		t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
288 		(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft);  /* flush */
289 		if ((val & F_PCS_RESET_) && adap->params.rev) {
290 			msleep(1);
291 			t3b_pcs_reset(mac);
292 		}
293 		t3_write_reg(adap, A_XGM_RX_CFG + oft,
294 			 F_DISPAUSEFRAMES | F_EN1536BFRAMES |
295 					F_RMFCS | F_ENJUMBO | F_ENHASHMCAST );
296 	}
297 
298 	/* Restore the DROP_CFG */
299 	t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
300 	t3_write_reg(adap, A_TP_PIO_DATA, store);
301 
302 	/* Resume egress traffic to xgm */
303 	t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE | F_PORT0ACTIVE,
304 			 store_mps);
305 
306 	/*  Set: re-enable NIC traffic */
307 	t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, F_ENFORCEPKT);
308 
309 	return 0;
310 }
311 
312 /*
313  * Set the exact match register 'idx' to recognize the given Ethernet address.
314  */
315 static void set_addr_filter(struct cmac *mac, int idx, const u8 *addr)
316 {
317 	u32 addr_lo, addr_hi;
318 	unsigned int oft = mac->offset + idx * 8;
319 
320 	addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
321 	addr_hi = (addr[5] << 8) | addr[4];
322 
323 	t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo);
324 	t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi);
325 }
326 
327 /**
328  *	t3_mac_set_address - set one of the station's unicast MAC addresses
329  *	@mac: the MAC handle
330  *	@idx: index of the exact address match filter to use
331  *	@addr: the Ethernet address
332  *
333  *	Set one of the station's unicast MAC addresses.
334  */
335 int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6])
336 {
337 	if (mac->multiport)
338 		idx = mac->ext_port + idx * mac->adapter->params.nports;
339 	if (idx >= mac->nucast)
340 		return -EINVAL;
341 	set_addr_filter(mac, idx, addr);
342 	if (mac->multiport && idx < mac->adapter->params.nports)
343 		t3_vsc7323_set_addr(mac->adapter, addr, idx);
344 	return 0;
345 }
346 
347 /**
348  *	t3_mac_set_num_ucast - set the number of unicast addresses needed
349  *	@mac: the MAC handle
350  *	@n: number of unicast addresses needed
351  *
352  *	Specify the number of exact address filters that should be reserved for
353  *	unicast addresses.  Caller should reload the unicast and multicast
354  *	addresses after calling this.
355  *
356  *	Generally, this is 1 with the first one used for the station address,
357  *	and the rest are available for multicast addresses.
358  */
359 int t3_mac_set_num_ucast(struct cmac *mac, unsigned char n)
360 {
361 	if (n > EXACT_ADDR_FILTERS)
362 		return -EINVAL;
363 	mac->nucast = n;
364 	return 0;
365 }
366 
367 void t3_mac_disable_exact_filters(struct cmac *mac)
368 {
369 	unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
370 
371 	for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
372 		u32 v = t3_read_reg(mac->adapter, reg);
373 		t3_write_reg(mac->adapter, reg, v);
374 	}
375 	t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
376 }
377 
378 void t3_mac_enable_exact_filters(struct cmac *mac)
379 {
380 	unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
381 
382 	for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
383 		u32 v = t3_read_reg(mac->adapter, reg);
384 		t3_write_reg(mac->adapter, reg, v);
385 	}
386 	t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
387 }
388 
389 /* Calculate the RX hash filter index of an Ethernet address */
390 static int hash_hw_addr(const u8 *addr)
391 {
392 	int hash = 0, octet, bit, i = 0, c;
393 
394 	for (octet = 0; octet < 6; ++octet)
395 		for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) {
396 			hash ^= (c & 1) << i;
397 			if (++i == 6)
398 				i = 0;
399 		}
400 	return hash;
401 }
402 
403 /**
404  *	t3_mac_set_rx_mode - set the Rx mode and address filters
405  *	@mac: the MAC to configure
406  *	@rm: structure containing the Rx mode and MAC addresses needed
407  *
408  *	Configures the MAC Rx mode (promiscuity, etc) and exact and hash
409  *	address filters.
410  */
411 struct t3_mcaddr_ctx {
412 	struct cmac *mac;
413 	u32 hash_lo, hash_hi;
414 };
415 
416 static u_int
417 t3_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
418 {
419 	struct t3_mcaddr_ctx *ctx = arg;
420 	int hash;
421 
422 	if (ctx->mac->nucast + cnt < EXACT_ADDR_FILTERS)
423 		set_addr_filter(ctx->mac, ctx->mac->nucast + cnt, LLADDR(sdl));
424 	else {
425 		hash = hash_hw_addr(LLADDR(sdl));
426 		if (hash < 32)
427 			ctx->hash_lo |= (1 << hash);
428 		else
429 			ctx->hash_hi |= (1 << (hash - 32));
430 	}
431 	return (1);
432 }
433 
434 int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm)
435 {
436 	struct t3_mcaddr_ctx ctx;
437 	adapter_t *adap = mac->adapter;
438 	unsigned int oft = mac->offset;
439 
440 	if (promisc_rx_mode(rm))
441 		mac->promisc_map |= 1 << mac->ext_port;
442 	else
443 		mac->promisc_map &= ~(1 << mac->ext_port);
444 	t3_set_reg_field(adap, A_XGM_RX_CFG + oft, F_COPYALLFRAMES,
445 			 mac->promisc_map ? F_COPYALLFRAMES : 0);
446 
447 	if (allmulti_rx_mode(rm) || mac->multiport)
448 		ctx.hash_lo = ctx.hash_hi = 0xffffffff;
449 	else {
450 		ctx.mac = mac;
451 		ctx.hash_lo = ctx.hash_hi = 0;
452 		if_foreach_llmaddr(rm->port->ifp, t3_hash_maddr, &ctx);
453 	}
454 
455 	t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, ctx.hash_lo);
456 	t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, ctx.hash_hi);
457 	return 0;
458 }
459 
460 static int rx_fifo_hwm(int mtu)
461 {
462 	int hwm;
463 
464 	hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
465 	return min(hwm, MAC_RXFIFO_SIZE - 8192);
466 }
467 
468 /**
469  *	t3_mac_set_mtu - set the MAC MTU
470  *	@mac: the MAC to configure
471  *	@mtu: the MTU
472  *
473  *	Sets the MAC MTU and adjusts the FIFO PAUSE watermarks accordingly.
474  */
475 int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
476 {
477 	int hwm, lwm;
478 	int ipg;
479 	unsigned int thres, v, reg;
480 	adapter_t *adap = mac->adapter;
481 	unsigned port_type = adap->params.vpd.port_type[macidx(mac)];
482 	unsigned int orig_mtu=mtu;
483 
484 	/*
485 	 * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't.  The HW max
486 	 * packet size register includes header, but not FCS.
487 	 */
488 	mtu += 14;
489 	if (mac->multiport)
490 		mtu += 8;                             /* for preamble */
491 	if (mtu > MAX_FRAME_SIZE - 4)
492 		return -EINVAL;
493 	if (mac->multiport)
494 		return t3_vsc7323_set_mtu(adap, mtu - 4, mac->ext_port);
495 
496 	/* Modify the TX and RX fifo depth only if the card has a vsc8211 phy */
497 	if (port_type == 2) {
498 		int err = t3_vsc8211_fifo_depth(adap,orig_mtu,macidx(mac));
499 
500 		if (err)
501 			return err;
502 	}
503 
504 	if (adap->params.rev >= T3_REV_B2 &&
505 	    (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
506 		t3_mac_disable_exact_filters(mac);
507 		v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
508 		t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
509 				 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
510 
511 		reg = adap->params.rev == T3_REV_B2 ?
512 			A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG;
513 
514 		/* drain RX FIFO */
515 		if (t3_wait_op_done(adap, reg + mac->offset,
516 				    F_RXFIFO_EMPTY, 1, 20, 5)) {
517 			t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
518 			t3_mac_enable_exact_filters(mac);
519 			return -EIO;
520 		}
521 		t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
522 				 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
523 				 V_RXMAXPKTSIZE(mtu));
524 		t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
525 		t3_mac_enable_exact_filters(mac);
526 	} else
527 		t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
528 				 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
529 				 V_RXMAXPKTSIZE(mtu));
530 	/*
531 	 * Adjust the PAUSE frame watermarks.  We always set the LWM, and the
532 	 * HWM only if flow-control is enabled.
533 	 */
534 	hwm = rx_fifo_hwm(mtu);
535 	lwm = min(3 * (int) mtu, MAC_RXFIFO_SIZE /4);
536 	v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
537 	v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
538 	v |= V_RXFIFOPAUSELWM(lwm / 8);
539 	if (G_RXFIFOPAUSEHWM(v))
540 		v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
541 		    V_RXFIFOPAUSEHWM(hwm / 8);
542 
543 	t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
544 
545 	/* Adjust the TX FIFO threshold based on the MTU */
546 	thres = (adap->params.vpd.cclk * 1000) / 15625;
547 	thres = (thres * mtu) / 1000;
548 	if (is_10G(adap))
549 		thres /= 10;
550 	thres = mtu > thres ? (mtu - thres + 7) / 8 : 0;
551 	thres = max(thres, 8U);                          /* need at least 8 */
552 	ipg = (port_type == 9 || adap->params.rev != T3_REV_C) ? 1 : 0;
553 	t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
554 			 V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
555 			 V_TXFIFOTHRESH(thres) | V_TXIPG(ipg));
556 	return 0;
557 }
558 
559 /**
560  *	t3_mac_set_speed_duplex_fc - set MAC speed, duplex and flow control
561  *	@mac: the MAC to configure
562  *	@speed: the desired speed (10/100/1000/10000)
563  *	@duplex: the desired duplex
564  *	@fc: desired Tx/Rx PAUSE configuration
565  *
566  *	Set the MAC speed, duplex (actually only full-duplex is supported), and
567  *	flow control.  If a parameter value is negative the corresponding
568  *	MAC setting is left at its current value.
569  */
570 int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
571 {
572 	u32 val;
573 	adapter_t *adap = mac->adapter;
574 	unsigned int oft = mac->offset;
575 	unsigned int pause_bits;
576 
577 	if (duplex >= 0 && duplex != DUPLEX_FULL)
578 		return -EINVAL;
579 
580 	pause_bits = MAC_RXFIFO_SIZE * 4 * 8;
581 	t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
582 		     pause_bits / 512);
583 	t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
584 		     (pause_bits >> (adap->params.rev == T3_REV_C ? 10 : 7)));
585 
586 	if (mac->multiport) {
587 		u32 rx_max_pkt_size =
588 		    G_RXMAXPKTSIZE(t3_read_reg(adap,
589 					       A_XGM_RX_MAX_PKT_SIZE + oft));
590 		val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
591 		val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
592 		val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
593 		t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
594 		t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
595 			  		F_TXPAUSEEN);
596 
597 		return t3_vsc7323_set_speed_fc(adap, speed, fc, mac->ext_port);
598 	}
599 	if (speed >= 0) {
600 		if (speed == SPEED_10)
601 			val = V_PORTSPEED(0);
602 		else if (speed == SPEED_100)
603 			val = V_PORTSPEED(1);
604 		else if (speed == SPEED_1000)
605 			val = V_PORTSPEED(2);
606 		else if (speed == SPEED_10000)
607 			val = V_PORTSPEED(3);
608 		else
609 			return -EINVAL;
610 
611 		if (!uses_xaui(adap)) /* T302 */
612 			t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
613 			    V_PORTSPEED(M_PORTSPEED), val);
614 		else {
615 			u32 old = t3_read_reg(adap, A_XGM_PORT_CFG + oft);
616 
617 			if ((old & V_PORTSPEED(M_PORTSPEED)) != val) {
618 				t3_mac_reset(mac, val);
619 				mac->was_reset = 1;
620 			}
621 		}
622 	}
623 
624 	val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
625 	val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
626 	if (fc & PAUSE_TX) {
627 		u32 rx_max_pkt_size =
628 		    G_RXMAXPKTSIZE(t3_read_reg(adap,
629 					       A_XGM_RX_MAX_PKT_SIZE + oft));
630 		val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
631 	}
632 	t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
633 
634 	t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
635 			(fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
636 	return 0;
637 }
638 
639 /**
640  *	t3_mac_enable - enable the MAC in the given directions
641  *	@mac: the MAC to configure
642  *	@which: bitmap indicating which directions to enable
643  *
644  *	Enables the MAC for operation in the given directions.
645  *	%MAC_DIRECTION_TX enables the Tx direction, and %MAC_DIRECTION_RX
646  *	enables the Rx one.
647  */
648 int t3_mac_enable(struct cmac *mac, int which)
649 {
650 	int idx = macidx(mac);
651 	adapter_t *adap = mac->adapter;
652 	unsigned int oft = mac->offset;
653 	struct mac_stats *s = &mac->stats;
654 
655 	if (mac->multiport)
656 		return t3_vsc7323_enable(adap, mac->ext_port, which);
657 
658 	if (which & MAC_DIRECTION_TX) {
659 		t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
660 		t3_write_reg(adap, A_TP_PIO_DATA,
661 			     adap->params.rev == T3_REV_C ?
662 			     0xc4ffff01 : 0xc0ede401);
663 		t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
664 		t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx,
665 				 adap->params.rev == T3_REV_C ?
666 				 0 : 1 << idx);
667 
668 		t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
669 
670 		t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
671 		mac->tx_mcnt = s->tx_frames;
672 		mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
673 							       A_TP_PIO_DATA)));
674 		mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
675 						A_XGM_TX_SPI4_SOP_EOP_CNT +
676 						oft)));
677 		mac->rx_mcnt = s->rx_frames;
678 		mac->rx_pause = s->rx_pause;
679 		mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
680 						A_XGM_RX_SPI4_SOP_EOP_CNT +
681 						oft)));
682 		mac->rx_ocnt = s->rx_fifo_ovfl;
683 		mac->txen = F_TXEN;
684 		mac->toggle_cnt = 0;
685 	}
686 	if (which & MAC_DIRECTION_RX)
687 		t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
688 	return 0;
689 }
690 
691 /**
692  *	t3_mac_disable - disable the MAC in the given directions
693  *	@mac: the MAC to configure
694  *	@which: bitmap indicating which directions to disable
695  *
696  *	Disables the MAC in the given directions.
697  *	%MAC_DIRECTION_TX disables the Tx direction, and %MAC_DIRECTION_RX
698  *	disables the Rx one.
699  */
700 int t3_mac_disable(struct cmac *mac, int which)
701 {
702 	adapter_t *adap = mac->adapter;
703 
704 	if (mac->multiport)
705 		return t3_vsc7323_disable(adap, mac->ext_port, which);
706 
707 	if (which & MAC_DIRECTION_TX) {
708 		t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
709 		mac->txen = 0;
710 	}
711 	if (which & MAC_DIRECTION_RX) {
712 		int val = xgm_reset_ctrl(mac);
713 
714 		t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
715 				 F_PCS_RESET_, 0);
716 		msleep(100);
717 		t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
718 		t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
719 	}
720 	return 0;
721 }
722 
723 int t3b2_mac_watchdog_task(struct cmac *mac)
724 {
725 	int status;
726 	unsigned int tx_tcnt, tx_xcnt;
727 	adapter_t *adap = mac->adapter;
728 	struct mac_stats *s = &mac->stats;
729 	u64 tx_mcnt = s->tx_frames;
730 
731 	if (mac->multiport)
732 		tx_mcnt = t3_read_reg(adap, A_XGM_STAT_TX_FRAME_LOW);
733 
734 	status = 0;
735 	tx_xcnt = 1; /* By default tx_xcnt is making progress*/
736 	tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt*/
737 	if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) {
738 		u32 cfg, active, enforcepkt;
739 
740 		tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
741 						      A_XGM_TX_SPI4_SOP_EOP_CNT +
742 						      mac->offset)));
743 		cfg = t3_read_reg(adap, A_MPS_CFG);
744 		active = macidx(mac) ? cfg & F_PORT1ACTIVE : cfg & F_PORT0ACTIVE;
745 		enforcepkt = cfg & F_ENFORCEPKT;
746 		if (active && enforcepkt && (tx_xcnt == 0)) {
747 			t3_write_reg(adap, A_TP_PIO_ADDR,
748 			     	A_TP_TX_DROP_CNT_CH0 + macidx(mac));
749 			tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
750 			      	A_TP_PIO_DATA)));
751 		} else
752 			goto out;
753 
754 	} else {
755 		mac->toggle_cnt = 0;
756 		goto out;
757 	}
758 
759 	if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) {
760 		if (mac->toggle_cnt > 4) {
761 			status = 2;
762 			goto out;
763 		} else {
764 			status = 1;
765 			goto out;
766 		}
767 	} else {
768 		mac->toggle_cnt = 0;
769 		goto out;
770 	}
771 
772 out:
773 	mac->tx_tcnt = tx_tcnt;
774 	mac->tx_xcnt = tx_xcnt;
775 	mac->tx_mcnt = s->tx_frames;
776 	mac->rx_pause = s->rx_pause;
777 	if (status == 1) {
778 		t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
779 		t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);  /* flush */
780 		t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
781 		t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);  /* flush */
782 		mac->toggle_cnt++;
783 	} else if (status == 2) {
784 		t3_mac_reset(mac, -1);
785 		mac->toggle_cnt = 0;
786 	}
787 	return status;
788 }
789 
790 /**
791  *	t3_mac_update_stats - accumulate MAC statistics
792  *	@mac: the MAC handle
793  *
794  *	This function is called periodically to accumulate the current values
795  *	of the RMON counters into the port statistics.  Since the packet
796  *	counters are only 32 bits they can overflow in ~286 secs at 10G, so the
797  *	function should be called more frequently than that.  The byte counters
798  *	are 45-bit wide, they would overflow in ~7.8 hours.
799  */
800 const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
801 {
802 #define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset)
803 #define RMON_UPDATE(mac, name, reg) \
804 	(mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg)
805 #define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \
806 	(mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \
807 			     ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32)
808 
809 	u32 v, lo;
810 
811 	if (mac->multiport)
812 		return t3_vsc7323_update_stats(mac);
813 
814 	RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH);
815 	RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH);
816 	RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES);
817 	RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES);
818 	RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES);
819 	RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES);
820 	RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES);
821 	RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES);
822 	RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES);
823 
824 	RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES);
825 
826 	v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
827 	if (mac->adapter->params.rev == T3_REV_B2)
828 		v &= 0x7fffffff;
829 	mac->stats.rx_too_long += v;
830 
831 	RMON_UPDATE(mac, rx_frames_64,        RX_64B_FRAMES);
832 	RMON_UPDATE(mac, rx_frames_65_127,    RX_65_127B_FRAMES);
833 	RMON_UPDATE(mac, rx_frames_128_255,   RX_128_255B_FRAMES);
834 	RMON_UPDATE(mac, rx_frames_256_511,   RX_256_511B_FRAMES);
835 	RMON_UPDATE(mac, rx_frames_512_1023,  RX_512_1023B_FRAMES);
836 	RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES);
837 	RMON_UPDATE(mac, rx_frames_1519_max,  RX_1519_MAXB_FRAMES);
838 
839 	RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH);
840 	RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH);
841 	RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST);
842 	RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST);
843 	RMON_UPDATE(mac, tx_pause, TX_PAUSE);
844 	/* This counts error frames in general (bad FCS, underrun, etc). */
845 	RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES);
846 
847 	RMON_UPDATE(mac, tx_frames_64,        TX_64B_FRAMES);
848 	RMON_UPDATE(mac, tx_frames_65_127,    TX_65_127B_FRAMES);
849 	RMON_UPDATE(mac, tx_frames_128_255,   TX_128_255B_FRAMES);
850 	RMON_UPDATE(mac, tx_frames_256_511,   TX_256_511B_FRAMES);
851 	RMON_UPDATE(mac, tx_frames_512_1023,  TX_512_1023B_FRAMES);
852 	RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES);
853 	RMON_UPDATE(mac, tx_frames_1519_max,  TX_1519_MAXB_FRAMES);
854 
855 	/* The next stat isn't clear-on-read. */
856 	t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50);
857 	v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA);
858 	lo = (u32)mac->stats.rx_cong_drops;
859 	mac->stats.rx_cong_drops += (u64)(v - lo);
860 
861 	return &mac->stats;
862 }
863