1 /**************************************************************************
2 SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 Copyright (c) 2007-2009 Chelsio Inc.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
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.
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.
29 ***************************************************************************/
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <cxgb_include.h>
37 #define msleep t3_os_sleep
40 static inline int macidx(const struct cmac *mac)
42 return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR);
46 * Returns a reasonable A_XGM_RESET_CTRL value for the mac specified.
48 static inline int xgm_reset_ctrl(const struct cmac *mac)
50 adapter_t *adap = mac->adapter;
51 int val = F_MAC_RESET_ | F_XGMAC_STOP_EN;
54 int cfg = t3_read_reg(adap, A_XGM_PORT_CFG + mac->offset);
57 if (G_PORTSPEED(cfg) != 3) /* not running at 10G */
59 } else if (uses_xaui(adap))
60 val |= F_PCS_RESET_ | F_XG2G_RESET_;
62 val |= F_RGMII_RESET_ | F_XG2G_RESET_;
67 static void xaui_serdes_reset(struct cmac *mac)
69 static const unsigned int clear[] = {
70 F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1,
71 F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3
75 adapter_t *adap = mac->adapter;
76 u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset;
78 t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] |
79 F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 |
80 F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 |
81 F_RESETPLL23 | F_RESETPLL01);
82 (void)t3_read_reg(adap, ctrl);
85 for (i = 0; i < ARRAY_SIZE(clear); i++) {
86 t3_set_reg_field(adap, ctrl, clear[i], 0);
92 * t3b_pcs_reset - reset the PCS on T3B+ adapters
93 * @mac: the XGMAC handle
95 * Reset the XGMAC PCS block on T3B+ adapters.
97 void t3b_pcs_reset(struct cmac *mac)
99 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
102 /* No delay required */
104 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0,
108 void t3c_pcs_force_los(struct cmac *mac)
110 t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT0 + mac->offset,
111 F_LOWSIGFORCEEN0 | F_LOWSIGFORCEVALUE0,
112 F_LOWSIGFORCEEN0 | F_LOWSIGFORCEVALUE0);
113 t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT1 + mac->offset,
114 F_LOWSIGFORCEEN1 | F_LOWSIGFORCEVALUE1,
115 F_LOWSIGFORCEEN1 | F_LOWSIGFORCEVALUE1);
116 t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT2 + mac->offset,
117 F_LOWSIGFORCEEN2 | F_LOWSIGFORCEVALUE2,
118 F_LOWSIGFORCEEN2 | F_LOWSIGFORCEVALUE2);
119 t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT3 + mac->offset,
120 F_LOWSIGFORCEEN3 | F_LOWSIGFORCEVALUE3,
121 F_LOWSIGFORCEEN3 | F_LOWSIGFORCEVALUE3);
123 /* No delay required */
125 t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT0 + mac->offset,
126 F_LOWSIGFORCEEN0, 0);
127 t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT1 + mac->offset,
128 F_LOWSIGFORCEEN1, 0);
129 t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT2 + mac->offset,
130 F_LOWSIGFORCEEN2, 0);
131 t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT3 + mac->offset,
132 F_LOWSIGFORCEEN3, 0);
136 * t3_mac_init - initialize a MAC
137 * @mac: the MAC to initialize
139 * Initialize the given MAC.
141 int t3_mac_init(struct cmac *mac)
143 static struct addr_val_pair mac_reset_avp[] = {
144 { A_XGM_TX_CTRL, 0 },
145 { A_XGM_RX_CTRL, 0 },
146 { A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES |
147 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST },
148 { A_XGM_RX_HASH_LOW, 0 },
149 { A_XGM_RX_HASH_HIGH, 0 },
150 { A_XGM_RX_EXACT_MATCH_LOW_1, 0 },
151 { A_XGM_RX_EXACT_MATCH_LOW_2, 0 },
152 { A_XGM_RX_EXACT_MATCH_LOW_3, 0 },
153 { A_XGM_RX_EXACT_MATCH_LOW_4, 0 },
154 { A_XGM_RX_EXACT_MATCH_LOW_5, 0 },
155 { A_XGM_RX_EXACT_MATCH_LOW_6, 0 },
156 { A_XGM_RX_EXACT_MATCH_LOW_7, 0 },
157 { A_XGM_RX_EXACT_MATCH_LOW_8, 0 },
158 { A_XGM_STAT_CTRL, F_CLRSTATS }
161 adapter_t *adap = mac->adapter;
162 unsigned int oft = mac->offset;
164 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
165 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
167 t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft);
168 t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft,
169 F_RXSTRFRWRD | F_DISERRFRAMES,
170 uses_xaui(adap) ? 0 : F_RXSTRFRWRD);
171 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX);
173 if (uses_xaui(adap)) {
174 if (adap->params.rev == 0) {
175 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
176 F_RXENABLE | F_TXENABLE);
177 if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft,
178 F_CMULOCK, 1, 5, 2)) {
180 "MAC %d XAUI SERDES CMU lock failed\n",
184 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
187 xaui_serdes_reset(mac);
191 if (mac->multiport) {
192 t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
193 V_RXMAXPKTSIZE(MAX_FRAME_SIZE - 4));
194 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0,
196 t3_set_reg_field(adap, A_XGM_RX_CFG + oft, 0, F_COPYPREAMBLE |
197 F_ENNON802_3PREAMBLE);
198 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft,
199 V_TXFIFOTHRESH(M_TXFIFOTHRESH),
201 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
202 t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
205 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
206 V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE),
207 V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER);
209 val = xgm_reset_ctrl(mac);
210 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
211 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
212 if ((val & F_PCS_RESET_) && adap->params.rev) {
217 memset(&mac->stats, 0, sizeof(mac->stats));
221 static int t3_mac_reset(struct cmac *mac, int portspeed)
224 adapter_t *adap = mac->adapter;
225 unsigned int oft = mac->offset;
226 int idx = macidx(mac);
229 /* Stop egress traffic to xgm*/
230 store_mps = t3_read_reg(adap, A_MPS_CFG);
232 t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
234 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
236 /* This will reduce the number of TXTOGGLES */
237 /* Clear: to stop the NIC traffic */
238 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0);
239 /* Ensure TX drains */
240 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0);
243 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
244 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
246 /* Store A_TP_TX_DROP_CFG_CH0 */
247 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
248 store = t3_read_reg(adap, A_TP_PIO_DATA);
252 /* Change DROP_CFG to 0xc0000011 */
253 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
254 t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011);
256 /* Check for xgm Rx fifo empty */
257 /* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */
258 if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
259 0x80000000, 1, 1000, 2) && portspeed < 0) {
260 CH_ERR(adap, "MAC %d Rx fifo drain failed\n", idx);
264 if (portspeed >= 0) {
265 u32 intr = t3_read_reg(adap, A_XGM_INT_ENABLE + oft);
268 * safespeedchange: wipes out pretty much all XGMAC registers.
271 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
272 V_PORTSPEED(M_PORTSPEED) | F_SAFESPEEDCHANGE,
273 portspeed | F_SAFESPEEDCHANGE);
274 (void) t3_read_reg(adap, A_XGM_PORT_CFG + oft);
275 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
276 F_SAFESPEEDCHANGE, 0);
277 (void) t3_read_reg(adap, A_XGM_PORT_CFG + oft);
280 t3_write_reg(adap, A_XGM_INT_ENABLE + oft, intr);
283 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); /*MAC in reset*/
284 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
286 val = xgm_reset_ctrl(mac);
287 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
288 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
289 if ((val & F_PCS_RESET_) && adap->params.rev) {
293 t3_write_reg(adap, A_XGM_RX_CFG + oft,
294 F_DISPAUSEFRAMES | F_EN1536BFRAMES |
295 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST );
298 /* Restore the DROP_CFG */
299 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
300 t3_write_reg(adap, A_TP_PIO_DATA, store);
302 /* Resume egress traffic to xgm */
303 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE | F_PORT0ACTIVE,
306 /* Set: re-enable NIC traffic */
307 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, F_ENFORCEPKT);
313 * Set the exact match register 'idx' to recognize the given Ethernet address.
315 static void set_addr_filter(struct cmac *mac, int idx, const u8 *addr)
317 u32 addr_lo, addr_hi;
318 unsigned int oft = mac->offset + idx * 8;
320 addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
321 addr_hi = (addr[5] << 8) | addr[4];
323 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo);
324 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi);
328 * t3_mac_set_address - set one of the station's unicast MAC addresses
329 * @mac: the MAC handle
330 * @idx: index of the exact address match filter to use
331 * @addr: the Ethernet address
333 * Set one of the station's unicast MAC addresses.
335 int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6])
338 idx = mac->ext_port + idx * mac->adapter->params.nports;
339 if (idx >= mac->nucast)
341 set_addr_filter(mac, idx, addr);
342 if (mac->multiport && idx < mac->adapter->params.nports)
343 t3_vsc7323_set_addr(mac->adapter, addr, idx);
348 * t3_mac_set_num_ucast - set the number of unicast addresses needed
349 * @mac: the MAC handle
350 * @n: number of unicast addresses needed
352 * Specify the number of exact address filters that should be reserved for
353 * unicast addresses. Caller should reload the unicast and multicast
354 * addresses after calling this.
356 * Generally, this is 1 with the first one used for the station address,
357 * and the rest are available for multicast addresses.
359 int t3_mac_set_num_ucast(struct cmac *mac, unsigned char n)
361 if (n > EXACT_ADDR_FILTERS)
367 void t3_mac_disable_exact_filters(struct cmac *mac)
369 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
371 for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
372 u32 v = t3_read_reg(mac->adapter, reg);
373 t3_write_reg(mac->adapter, reg, v);
375 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
378 void t3_mac_enable_exact_filters(struct cmac *mac)
380 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
382 for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
383 u32 v = t3_read_reg(mac->adapter, reg);
384 t3_write_reg(mac->adapter, reg, v);
386 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
389 /* Calculate the RX hash filter index of an Ethernet address */
390 static int hash_hw_addr(const u8 *addr)
392 int hash = 0, octet, bit, i = 0, c;
394 for (octet = 0; octet < 6; ++octet)
395 for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) {
396 hash ^= (c & 1) << i;
404 * t3_mac_set_rx_mode - set the Rx mode and address filters
405 * @mac: the MAC to configure
406 * @rm: structure containing the Rx mode and MAC addresses needed
408 * Configures the MAC Rx mode (promiscuity, etc) and exact and hash
411 struct t3_mcaddr_ctx {
413 u32 hash_lo, hash_hi;
417 t3_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
419 struct t3_mcaddr_ctx *ctx = arg;
422 if (ctx->mac->nucast + cnt < EXACT_ADDR_FILTERS)
423 set_addr_filter(ctx->mac, ctx->mac->nucast + cnt, LLADDR(sdl));
425 hash = hash_hw_addr(LLADDR(sdl));
427 ctx->hash_lo |= (1 << hash);
429 ctx->hash_hi |= (1 << (hash - 32));
434 int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm)
436 struct t3_mcaddr_ctx ctx;
437 adapter_t *adap = mac->adapter;
438 unsigned int oft = mac->offset;
440 if (promisc_rx_mode(rm))
441 mac->promisc_map |= 1 << mac->ext_port;
443 mac->promisc_map &= ~(1 << mac->ext_port);
444 t3_set_reg_field(adap, A_XGM_RX_CFG + oft, F_COPYALLFRAMES,
445 mac->promisc_map ? F_COPYALLFRAMES : 0);
447 if (allmulti_rx_mode(rm) || mac->multiport)
448 ctx.hash_lo = ctx.hash_hi = 0xffffffff;
451 ctx.hash_lo = ctx.hash_hi = 0;
452 if_foreach_llmaddr(rm->port->ifp, t3_hash_maddr, &ctx);
455 t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, ctx.hash_lo);
456 t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, ctx.hash_hi);
460 static int rx_fifo_hwm(int mtu)
464 hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
465 return min(hwm, MAC_RXFIFO_SIZE - 8192);
469 * t3_mac_set_mtu - set the MAC MTU
470 * @mac: the MAC to configure
473 * Sets the MAC MTU and adjusts the FIFO PAUSE watermarks accordingly.
475 int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
479 unsigned int thres, v, reg;
480 adapter_t *adap = mac->adapter;
481 unsigned port_type = adap->params.vpd.port_type[macidx(mac)];
482 unsigned int orig_mtu=mtu;
485 * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max
486 * packet size register includes header, but not FCS.
490 mtu += 8; /* for preamble */
491 if (mtu > MAX_FRAME_SIZE - 4)
494 return t3_vsc7323_set_mtu(adap, mtu - 4, mac->ext_port);
496 /* Modify the TX and RX fifo depth only if the card has a vsc8211 phy */
497 if (port_type == 2) {
498 int err = t3_vsc8211_fifo_depth(adap,orig_mtu,macidx(mac));
504 if (adap->params.rev >= T3_REV_B2 &&
505 (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
506 t3_mac_disable_exact_filters(mac);
507 v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
508 t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
509 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
511 reg = adap->params.rev == T3_REV_B2 ?
512 A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG;
515 if (t3_wait_op_done(adap, reg + mac->offset,
516 F_RXFIFO_EMPTY, 1, 20, 5)) {
517 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
518 t3_mac_enable_exact_filters(mac);
521 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
522 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
523 V_RXMAXPKTSIZE(mtu));
524 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
525 t3_mac_enable_exact_filters(mac);
527 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
528 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
529 V_RXMAXPKTSIZE(mtu));
531 * Adjust the PAUSE frame watermarks. We always set the LWM, and the
532 * HWM only if flow-control is enabled.
534 hwm = rx_fifo_hwm(mtu);
535 lwm = min(3 * (int) mtu, MAC_RXFIFO_SIZE /4);
536 v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
537 v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
538 v |= V_RXFIFOPAUSELWM(lwm / 8);
539 if (G_RXFIFOPAUSEHWM(v))
540 v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
541 V_RXFIFOPAUSEHWM(hwm / 8);
543 t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
545 /* Adjust the TX FIFO threshold based on the MTU */
546 thres = (adap->params.vpd.cclk * 1000) / 15625;
547 thres = (thres * mtu) / 1000;
550 thres = mtu > thres ? (mtu - thres + 7) / 8 : 0;
551 thres = max(thres, 8U); /* need at least 8 */
552 ipg = (port_type == 9 || adap->params.rev != T3_REV_C) ? 1 : 0;
553 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
554 V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
555 V_TXFIFOTHRESH(thres) | V_TXIPG(ipg));
560 * t3_mac_set_speed_duplex_fc - set MAC speed, duplex and flow control
561 * @mac: the MAC to configure
562 * @speed: the desired speed (10/100/1000/10000)
563 * @duplex: the desired duplex
564 * @fc: desired Tx/Rx PAUSE configuration
566 * Set the MAC speed, duplex (actually only full-duplex is supported), and
567 * flow control. If a parameter value is negative the corresponding
568 * MAC setting is left at its current value.
570 int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
573 adapter_t *adap = mac->adapter;
574 unsigned int oft = mac->offset;
575 unsigned int pause_bits;
577 if (duplex >= 0 && duplex != DUPLEX_FULL)
580 pause_bits = MAC_RXFIFO_SIZE * 4 * 8;
581 t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
583 t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
584 (pause_bits >> (adap->params.rev == T3_REV_C ? 10 : 7)));
586 if (mac->multiport) {
587 u32 rx_max_pkt_size =
588 G_RXMAXPKTSIZE(t3_read_reg(adap,
589 A_XGM_RX_MAX_PKT_SIZE + oft));
590 val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
591 val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
592 val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
593 t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
594 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
597 return t3_vsc7323_set_speed_fc(adap, speed, fc, mac->ext_port);
600 if (speed == SPEED_10)
601 val = V_PORTSPEED(0);
602 else if (speed == SPEED_100)
603 val = V_PORTSPEED(1);
604 else if (speed == SPEED_1000)
605 val = V_PORTSPEED(2);
606 else if (speed == SPEED_10000)
607 val = V_PORTSPEED(3);
611 if (!uses_xaui(adap)) /* T302 */
612 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
613 V_PORTSPEED(M_PORTSPEED), val);
615 u32 old = t3_read_reg(adap, A_XGM_PORT_CFG + oft);
617 if ((old & V_PORTSPEED(M_PORTSPEED)) != val) {
618 t3_mac_reset(mac, val);
624 val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
625 val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
627 u32 rx_max_pkt_size =
628 G_RXMAXPKTSIZE(t3_read_reg(adap,
629 A_XGM_RX_MAX_PKT_SIZE + oft));
630 val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
632 t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
634 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
635 (fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
640 * t3_mac_enable - enable the MAC in the given directions
641 * @mac: the MAC to configure
642 * @which: bitmap indicating which directions to enable
644 * Enables the MAC for operation in the given directions.
645 * %MAC_DIRECTION_TX enables the Tx direction, and %MAC_DIRECTION_RX
646 * enables the Rx one.
648 int t3_mac_enable(struct cmac *mac, int which)
650 int idx = macidx(mac);
651 adapter_t *adap = mac->adapter;
652 unsigned int oft = mac->offset;
653 struct mac_stats *s = &mac->stats;
656 return t3_vsc7323_enable(adap, mac->ext_port, which);
658 if (which & MAC_DIRECTION_TX) {
659 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
660 t3_write_reg(adap, A_TP_PIO_DATA,
661 adap->params.rev == T3_REV_C ?
662 0xc4ffff01 : 0xc0ede401);
663 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
664 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx,
665 adap->params.rev == T3_REV_C ?
668 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
670 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
671 mac->tx_mcnt = s->tx_frames;
672 mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
674 mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
675 A_XGM_TX_SPI4_SOP_EOP_CNT +
677 mac->rx_mcnt = s->rx_frames;
678 mac->rx_pause = s->rx_pause;
679 mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
680 A_XGM_RX_SPI4_SOP_EOP_CNT +
682 mac->rx_ocnt = s->rx_fifo_ovfl;
686 if (which & MAC_DIRECTION_RX)
687 t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
692 * t3_mac_disable - disable the MAC in the given directions
693 * @mac: the MAC to configure
694 * @which: bitmap indicating which directions to disable
696 * Disables the MAC in the given directions.
697 * %MAC_DIRECTION_TX disables the Tx direction, and %MAC_DIRECTION_RX
698 * disables the Rx one.
700 int t3_mac_disable(struct cmac *mac, int which)
702 adapter_t *adap = mac->adapter;
705 return t3_vsc7323_disable(adap, mac->ext_port, which);
707 if (which & MAC_DIRECTION_TX) {
708 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
711 if (which & MAC_DIRECTION_RX) {
712 int val = xgm_reset_ctrl(mac);
714 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
717 t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
718 t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
723 int t3b2_mac_watchdog_task(struct cmac *mac)
726 unsigned int tx_tcnt, tx_xcnt;
727 adapter_t *adap = mac->adapter;
728 struct mac_stats *s = &mac->stats;
729 u64 tx_mcnt = s->tx_frames;
732 tx_mcnt = t3_read_reg(adap, A_XGM_STAT_TX_FRAME_LOW);
735 tx_xcnt = 1; /* By default tx_xcnt is making progress*/
736 tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt*/
737 if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) {
738 u32 cfg, active, enforcepkt;
740 tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
741 A_XGM_TX_SPI4_SOP_EOP_CNT +
743 cfg = t3_read_reg(adap, A_MPS_CFG);
744 active = macidx(mac) ? cfg & F_PORT1ACTIVE : cfg & F_PORT0ACTIVE;
745 enforcepkt = cfg & F_ENFORCEPKT;
746 if (active && enforcepkt && (tx_xcnt == 0)) {
747 t3_write_reg(adap, A_TP_PIO_ADDR,
748 A_TP_TX_DROP_CNT_CH0 + macidx(mac));
749 tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
759 if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) {
760 if (mac->toggle_cnt > 4) {
773 mac->tx_tcnt = tx_tcnt;
774 mac->tx_xcnt = tx_xcnt;
775 mac->tx_mcnt = s->tx_frames;
776 mac->rx_pause = s->rx_pause;
778 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
779 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
780 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
781 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
783 } else if (status == 2) {
784 t3_mac_reset(mac, -1);
791 * t3_mac_update_stats - accumulate MAC statistics
792 * @mac: the MAC handle
794 * This function is called periodically to accumulate the current values
795 * of the RMON counters into the port statistics. Since the packet
796 * counters are only 32 bits they can overflow in ~286 secs at 10G, so the
797 * function should be called more frequently than that. The byte counters
798 * are 45-bit wide, they would overflow in ~7.8 hours.
800 const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
802 #define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset)
803 #define RMON_UPDATE(mac, name, reg) \
804 (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg)
805 #define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \
806 (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \
807 ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32)
812 return t3_vsc7323_update_stats(mac);
814 RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH);
815 RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH);
816 RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES);
817 RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES);
818 RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES);
819 RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES);
820 RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES);
821 RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES);
822 RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES);
824 RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES);
826 v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
827 if (mac->adapter->params.rev == T3_REV_B2)
829 mac->stats.rx_too_long += v;
831 RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES);
832 RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES);
833 RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES);
834 RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES);
835 RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES);
836 RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES);
837 RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES);
839 RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH);
840 RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH);
841 RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST);
842 RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST);
843 RMON_UPDATE(mac, tx_pause, TX_PAUSE);
844 /* This counts error frames in general (bad FCS, underrun, etc). */
845 RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES);
847 RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES);
848 RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES);
849 RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES);
850 RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES);
851 RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES);
852 RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES);
853 RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES);
855 /* The next stat isn't clear-on-read. */
856 t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50);
857 v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA);
858 lo = (u32)mac->stats.rx_cong_drops;
859 mac->stats.rx_cong_drops += (u64)(v - lo);