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