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