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