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