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