1 /**************************************************************************
3 Copyright (c) 2007-2009 Chelsio Inc.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
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.
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.
28 ***************************************************************************/
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <cxgb_include.h>
36 #define msleep t3_os_sleep
39 static inline int macidx(const struct cmac *mac)
41 return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR);
45 * Returns a reasonable A_XGM_RESET_CTRL value for the mac specified.
47 static inline int xgm_reset_ctrl(const struct cmac *mac)
49 adapter_t *adap = mac->adapter;
50 int val = F_MAC_RESET_ | F_XGMAC_STOP_EN;
53 int cfg = t3_read_reg(adap, A_XGM_PORT_CFG + mac->offset);
56 if (G_PORTSPEED(cfg) != 3) /* not running at 10G */
58 } else if (uses_xaui(adap))
59 val |= F_PCS_RESET_ | F_XG2G_RESET_;
61 val |= F_RGMII_RESET_ | F_XG2G_RESET_;
66 static void xaui_serdes_reset(struct cmac *mac)
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
74 adapter_t *adap = mac->adapter;
75 u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset;
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);
84 for (i = 0; i < ARRAY_SIZE(clear); i++) {
85 t3_set_reg_field(adap, ctrl, clear[i], 0);
91 * t3b_pcs_reset - reset the PCS on T3B+ adapters
92 * @mac: the XGMAC handle
94 * Reset the XGMAC PCS block on T3B+ adapters.
96 void t3b_pcs_reset(struct cmac *mac)
98 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
101 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0,
106 * t3_mac_init - initialize a MAC
107 * @mac: the MAC to initialize
109 * Initialize the given MAC.
111 int t3_mac_init(struct cmac *mac)
113 static struct addr_val_pair mac_reset_avp[] = {
114 { A_XGM_TX_CTRL, 0 },
115 { A_XGM_RX_CTRL, 0 },
116 { A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES |
117 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST },
118 { A_XGM_RX_HASH_LOW, 0 },
119 { A_XGM_RX_HASH_HIGH, 0 },
120 { A_XGM_RX_EXACT_MATCH_LOW_1, 0 },
121 { A_XGM_RX_EXACT_MATCH_LOW_2, 0 },
122 { A_XGM_RX_EXACT_MATCH_LOW_3, 0 },
123 { A_XGM_RX_EXACT_MATCH_LOW_4, 0 },
124 { A_XGM_RX_EXACT_MATCH_LOW_5, 0 },
125 { A_XGM_RX_EXACT_MATCH_LOW_6, 0 },
126 { A_XGM_RX_EXACT_MATCH_LOW_7, 0 },
127 { A_XGM_RX_EXACT_MATCH_LOW_8, 0 },
128 { A_XGM_STAT_CTRL, F_CLRSTATS }
131 adapter_t *adap = mac->adapter;
132 unsigned int oft = mac->offset;
134 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
135 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
137 t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft);
138 t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft,
139 F_RXSTRFRWRD | F_DISERRFRAMES,
140 uses_xaui(adap) ? 0 : F_RXSTRFRWRD);
141 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX);
143 if (uses_xaui(adap)) {
144 if (adap->params.rev == 0) {
145 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
146 F_RXENABLE | F_TXENABLE);
147 if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft,
148 F_CMULOCK, 1, 5, 2)) {
150 "MAC %d XAUI SERDES CMU lock failed\n",
154 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
157 xaui_serdes_reset(mac);
161 if (mac->multiport) {
162 t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
163 V_RXMAXPKTSIZE(MAX_FRAME_SIZE - 4));
164 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0,
166 t3_set_reg_field(adap, A_XGM_RX_CFG + oft, 0, F_COPYPREAMBLE |
167 F_ENNON802_3PREAMBLE);
168 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft,
169 V_TXFIFOTHRESH(M_TXFIFOTHRESH),
171 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
172 t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
175 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
176 V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE),
177 V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER);
179 val = xgm_reset_ctrl(mac);
180 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
181 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
182 if ((val & F_PCS_RESET_) && adap->params.rev) {
187 memset(&mac->stats, 0, sizeof(mac->stats));
191 static int t3_mac_reset(struct cmac *mac, int portspeed)
194 adapter_t *adap = mac->adapter;
195 unsigned int oft = mac->offset;
196 int idx = macidx(mac);
199 /* Stop egress traffic to xgm*/
200 store_mps = t3_read_reg(adap, A_MPS_CFG);
202 t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
204 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
206 /* This will reduce the number of TXTOGGLES */
207 /* Clear: to stop the NIC traffic */
208 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0);
209 /* Ensure TX drains */
210 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0);
213 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
214 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
216 /* Store A_TP_TX_DROP_CFG_CH0 */
217 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
218 store = t3_read_reg(adap, A_TP_PIO_DATA);
222 /* Change DROP_CFG to 0xc0000011 */
223 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
224 t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011);
226 /* Check for xgm Rx fifo empty */
227 /* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */
228 if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
229 0x80000000, 1, 1000, 2) && portspeed < 0) {
230 CH_ERR(adap, "MAC %d Rx fifo drain failed\n", idx);
234 if (portspeed >= 0) {
235 u32 intr = t3_read_reg(adap, A_XGM_INT_ENABLE + oft);
238 * safespeedchange: wipes out pretty much all XGMAC registers.
241 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
242 V_PORTSPEED(M_PORTSPEED) | F_SAFESPEEDCHANGE,
243 portspeed | F_SAFESPEEDCHANGE);
244 (void) t3_read_reg(adap, A_XGM_PORT_CFG + oft);
245 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
246 F_SAFESPEEDCHANGE, 0);
247 (void) t3_read_reg(adap, A_XGM_PORT_CFG + oft);
250 t3_write_reg(adap, A_XGM_INT_ENABLE + oft, intr);
253 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); /*MAC in reset*/
254 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
256 val = xgm_reset_ctrl(mac);
257 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
258 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
259 if ((val & F_PCS_RESET_) && adap->params.rev) {
263 t3_write_reg(adap, A_XGM_RX_CFG + oft,
264 F_DISPAUSEFRAMES | F_EN1536BFRAMES |
265 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST );
268 /* Restore the DROP_CFG */
269 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
270 t3_write_reg(adap, A_TP_PIO_DATA, store);
272 /* Resume egress traffic to xgm */
273 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE | F_PORT0ACTIVE,
276 /* Set: re-enable NIC traffic */
277 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, F_ENFORCEPKT);
283 * Set the exact match register 'idx' to recognize the given Ethernet address.
285 static void set_addr_filter(struct cmac *mac, int idx, const u8 *addr)
287 u32 addr_lo, addr_hi;
288 unsigned int oft = mac->offset + idx * 8;
290 addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
291 addr_hi = (addr[5] << 8) | addr[4];
293 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo);
294 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi);
298 * t3_mac_set_address - set one of the station's unicast MAC addresses
299 * @mac: the MAC handle
300 * @idx: index of the exact address match filter to use
301 * @addr: the Ethernet address
303 * Set one of the station's unicast MAC addresses.
305 int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6])
308 idx = mac->ext_port + idx * mac->adapter->params.nports;
309 if (idx >= mac->nucast)
311 set_addr_filter(mac, idx, addr);
312 if (mac->multiport && idx < mac->adapter->params.nports)
313 t3_vsc7323_set_addr(mac->adapter, addr, idx);
318 * t3_mac_set_num_ucast - set the number of unicast addresses needed
319 * @mac: the MAC handle
320 * @n: number of unicast addresses needed
322 * Specify the number of exact address filters that should be reserved for
323 * unicast addresses. Caller should reload the unicast and multicast
324 * addresses after calling this.
326 * Generally, this is 1 with the first one used for the station address,
327 * and the rest are available for multicast addresses.
329 int t3_mac_set_num_ucast(struct cmac *mac, unsigned char n)
331 if (n > EXACT_ADDR_FILTERS)
337 void t3_mac_disable_exact_filters(struct cmac *mac)
339 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
341 for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
342 u32 v = t3_read_reg(mac->adapter, reg);
343 t3_write_reg(mac->adapter, reg, v);
345 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
348 void t3_mac_enable_exact_filters(struct cmac *mac)
350 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
352 for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
353 u32 v = t3_read_reg(mac->adapter, reg);
354 t3_write_reg(mac->adapter, reg, v);
356 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
359 /* Calculate the RX hash filter index of an Ethernet address */
360 static int hash_hw_addr(const u8 *addr)
362 int hash = 0, octet, bit, i = 0, c;
364 for (octet = 0; octet < 6; ++octet)
365 for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) {
366 hash ^= (c & 1) << i;
374 * t3_mac_set_rx_mode - set the Rx mode and address filters
375 * @mac: the MAC to configure
376 * @rm: structure containing the Rx mode and MAC addresses needed
378 * Configures the MAC Rx mode (promiscuity, etc) and exact and hash
381 int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm)
383 u32 hash_lo, hash_hi;
384 adapter_t *adap = mac->adapter;
385 unsigned int oft = mac->offset;
387 if (promisc_rx_mode(rm))
388 mac->promisc_map |= 1 << mac->ext_port;
390 mac->promisc_map &= ~(1 << mac->ext_port);
391 t3_set_reg_field(adap, A_XGM_RX_CFG + oft, F_COPYALLFRAMES,
392 mac->promisc_map ? F_COPYALLFRAMES : 0);
394 if (allmulti_rx_mode(rm) || mac->multiport)
395 hash_lo = hash_hi = 0xffffffff;
398 int exact_addr_idx = mac->nucast;
400 hash_lo = hash_hi = 0;
401 while ((addr = t3_get_next_mcaddr(rm)))
402 if (exact_addr_idx < EXACT_ADDR_FILTERS)
403 set_addr_filter(mac, exact_addr_idx++, addr);
405 int hash = hash_hw_addr(addr);
408 hash_lo |= (1 << hash);
410 hash_hi |= (1 << (hash - 32));
414 t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo);
415 t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi);
419 static int rx_fifo_hwm(int mtu)
423 hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
424 return min(hwm, MAC_RXFIFO_SIZE - 8192);
428 * t3_mac_set_mtu - set the MAC MTU
429 * @mac: the MAC to configure
432 * Sets the MAC MTU and adjusts the FIFO PAUSE watermarks accordingly.
434 int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
436 int hwm, lwm, divisor;
438 unsigned int thres, v, reg;
439 adapter_t *adap = mac->adapter;
440 unsigned port_type = adap->params.vpd.port_type[macidx(mac)];
441 unsigned int orig_mtu=mtu;
444 * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max
445 * packet size register includes header, but not FCS.
449 mtu += 8; /* for preamble */
450 if (mtu > MAX_FRAME_SIZE - 4)
453 return t3_vsc7323_set_mtu(adap, mtu - 4, mac->ext_port);
455 /* Modify the TX and RX fifo depth only if the card has a vsc8211 phy */
456 if (port_type == 2) {
457 int err = t3_vsc8211_fifo_depth(adap,orig_mtu,macidx(mac));
463 if (adap->params.rev >= T3_REV_B2 &&
464 (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
465 t3_mac_disable_exact_filters(mac);
466 v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
467 t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
468 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
470 reg = adap->params.rev == T3_REV_B2 ?
471 A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG;
474 if (t3_wait_op_done(adap, reg + mac->offset,
475 F_RXFIFO_EMPTY, 1, 20, 5)) {
476 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
477 t3_mac_enable_exact_filters(mac);
480 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
481 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
482 V_RXMAXPKTSIZE(mtu));
483 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
484 t3_mac_enable_exact_filters(mac);
486 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
487 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
488 V_RXMAXPKTSIZE(mtu));
490 * Adjust the PAUSE frame watermarks. We always set the LWM, and the
491 * HWM only if flow-control is enabled.
493 hwm = rx_fifo_hwm(mtu);
494 lwm = min(3 * (int) mtu, MAC_RXFIFO_SIZE /4);
495 v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
496 v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
497 v |= V_RXFIFOPAUSELWM(lwm / 8);
498 if (G_RXFIFOPAUSEHWM(v))
499 v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
500 V_RXFIFOPAUSEHWM(hwm / 8);
502 t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
504 /* Adjust the TX FIFO threshold based on the MTU */
505 thres = (adap->params.vpd.cclk * 1000) / 15625;
506 thres = (thres * mtu) / 1000;
509 thres = mtu > thres ? (mtu - thres + 7) / 8 : 0;
510 thres = max(thres, 8U); /* need at least 8 */
511 ipg = (port_type == 9 || adap->params.rev != T3_REV_C) ? 1 : 0;
512 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
513 V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
514 V_TXFIFOTHRESH(thres) | V_TXIPG(ipg));
516 /* Assuming a minimum drain rate of 2.5Gbps...
518 if (adap->params.rev > 0) {
519 divisor = (adap->params.rev == T3_REV_C) ? 64 : 8;
520 t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
521 (hwm - lwm) * 4 / divisor);
523 t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
524 MAC_RXFIFO_SIZE * 4 * 8 / 512);
529 * t3_mac_set_speed_duplex_fc - set MAC speed, duplex and flow control
530 * @mac: the MAC to configure
531 * @speed: the desired speed (10/100/1000/10000)
532 * @duplex: the desired duplex
533 * @fc: desired Tx/Rx PAUSE configuration
535 * Set the MAC speed, duplex (actually only full-duplex is supported), and
536 * flow control. If a parameter value is negative the corresponding
537 * MAC setting is left at its current value.
539 int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
542 adapter_t *adap = mac->adapter;
543 unsigned int oft = mac->offset;
545 if (duplex >= 0 && duplex != DUPLEX_FULL)
547 if (mac->multiport) {
548 u32 rx_max_pkt_size =
549 G_RXMAXPKTSIZE(t3_read_reg(adap,
550 A_XGM_RX_MAX_PKT_SIZE + oft));
551 val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
552 val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
553 val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
554 t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
556 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
558 return t3_vsc7323_set_speed_fc(adap, speed, fc, mac->ext_port);
561 if (speed == SPEED_10)
562 val = V_PORTSPEED(0);
563 else if (speed == SPEED_100)
564 val = V_PORTSPEED(1);
565 else if (speed == SPEED_1000)
566 val = V_PORTSPEED(2);
567 else if (speed == SPEED_10000)
568 val = V_PORTSPEED(3);
572 if (!uses_xaui(adap)) /* T302 */
573 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
574 V_PORTSPEED(M_PORTSPEED), val);
576 u32 old = t3_read_reg(adap, A_XGM_PORT_CFG + oft);
578 if ((old & V_PORTSPEED(M_PORTSPEED)) != val) {
579 t3_mac_reset(mac, val);
585 val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
586 val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
588 u32 rx_max_pkt_size =
589 G_RXMAXPKTSIZE(t3_read_reg(adap,
590 A_XGM_RX_MAX_PKT_SIZE + oft));
591 val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
593 t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
595 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
596 (fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
601 * t3_mac_enable - enable the MAC in the given directions
602 * @mac: the MAC to configure
603 * @which: bitmap indicating which directions to enable
605 * Enables the MAC for operation in the given directions.
606 * %MAC_DIRECTION_TX enables the Tx direction, and %MAC_DIRECTION_RX
607 * enables the Rx one.
609 int t3_mac_enable(struct cmac *mac, int which)
611 int idx = macidx(mac);
612 adapter_t *adap = mac->adapter;
613 unsigned int oft = mac->offset;
614 struct mac_stats *s = &mac->stats;
617 return t3_vsc7323_enable(adap, mac->ext_port, which);
619 if (which & MAC_DIRECTION_TX) {
620 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
621 t3_write_reg(adap, A_TP_PIO_DATA,
622 adap->params.rev == T3_REV_C ?
623 0xc4ffff01 : 0xc0ede401);
624 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
625 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx,
626 adap->params.rev == T3_REV_C ?
629 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
631 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
632 mac->tx_mcnt = s->tx_frames;
633 mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
635 mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
636 A_XGM_TX_SPI4_SOP_EOP_CNT +
638 mac->rx_mcnt = s->rx_frames;
639 mac->rx_pause = s->rx_pause;
640 mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
641 A_XGM_RX_SPI4_SOP_EOP_CNT +
643 mac->rx_ocnt = s->rx_fifo_ovfl;
647 if (which & MAC_DIRECTION_RX)
648 t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
653 * t3_mac_disable - disable the MAC in the given directions
654 * @mac: the MAC to configure
655 * @which: bitmap indicating which directions to disable
657 * Disables the MAC in the given directions.
658 * %MAC_DIRECTION_TX disables the Tx direction, and %MAC_DIRECTION_RX
659 * disables the Rx one.
661 int t3_mac_disable(struct cmac *mac, int which)
663 adapter_t *adap = mac->adapter;
666 return t3_vsc7323_disable(adap, mac->ext_port, which);
668 if (which & MAC_DIRECTION_TX) {
669 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
672 if (which & MAC_DIRECTION_RX) {
673 int val = xgm_reset_ctrl(mac);
675 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
678 t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
679 t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
684 int t3b2_mac_watchdog_task(struct cmac *mac)
687 unsigned int tx_tcnt, tx_xcnt;
688 adapter_t *adap = mac->adapter;
689 struct mac_stats *s = &mac->stats;
690 u64 tx_mcnt = s->tx_frames;
693 tx_mcnt = t3_read_reg(adap, A_XGM_STAT_TX_FRAME_LOW);
696 tx_xcnt = 1; /* By default tx_xcnt is making progress*/
697 tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt*/
698 if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) {
699 u32 cfg, active, enforcepkt;
701 tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
702 A_XGM_TX_SPI4_SOP_EOP_CNT +
704 cfg = t3_read_reg(adap, A_MPS_CFG);
705 active = macidx(mac) ? cfg & F_PORT1ACTIVE : cfg & F_PORT0ACTIVE;
706 enforcepkt = cfg & F_ENFORCEPKT;
707 if (active && enforcepkt && (tx_xcnt == 0)) {
708 t3_write_reg(adap, A_TP_PIO_ADDR,
709 A_TP_TX_DROP_CNT_CH0 + macidx(mac));
710 tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
720 if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) {
721 if (mac->toggle_cnt > 4) {
734 mac->tx_tcnt = tx_tcnt;
735 mac->tx_xcnt = tx_xcnt;
736 mac->tx_mcnt = s->tx_frames;
737 mac->rx_pause = s->rx_pause;
739 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
740 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
741 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
742 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
744 } else if (status == 2) {
745 t3_mac_reset(mac, -1);
752 * t3_mac_update_stats - accumulate MAC statistics
753 * @mac: the MAC handle
755 * This function is called periodically to accumulate the current values
756 * of the RMON counters into the port statistics. Since the packet
757 * counters are only 32 bits they can overflow in ~286 secs at 10G, so the
758 * function should be called more frequently than that. The byte counters
759 * are 45-bit wide, they would overflow in ~7.8 hours.
761 const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
763 #define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset)
764 #define RMON_UPDATE(mac, name, reg) \
765 (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg)
766 #define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \
767 (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \
768 ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32)
773 return t3_vsc7323_update_stats(mac);
775 RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH);
776 RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH);
777 RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES);
778 RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES);
779 RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES);
780 RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES);
781 RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES);
782 RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES);
783 RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES);
785 RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES);
787 v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
788 if (mac->adapter->params.rev == T3_REV_B2)
790 mac->stats.rx_too_long += v;
792 RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES);
793 RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES);
794 RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES);
795 RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES);
796 RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES);
797 RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES);
798 RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES);
800 RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH);
801 RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH);
802 RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST);
803 RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST);
804 RMON_UPDATE(mac, tx_pause, TX_PAUSE);
805 /* This counts error frames in general (bad FCS, underrun, etc). */
806 RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES);
808 RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES);
809 RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES);
810 RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES);
811 RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES);
812 RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES);
813 RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES);
814 RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES);
816 /* The next stat isn't clear-on-read. */
817 t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50);
818 v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA);
819 lo = (u32)mac->stats.rx_cong_drops;
820 mac->stats.rx_cong_drops += (u64)(v - lo);