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