1/* 2 * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32#include "common.h" 33#include "regs.h" 34 35/* 36 * # of exact address filters. The first one is used for the station address, 37 * the rest are available for multicast addresses. 38 */ 39#define EXACT_ADDR_FILTERS 8 40 41static inline int macidx(const struct cmac *mac) 42{ 43 return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR); 44} 45 46static void xaui_serdes_reset(struct cmac *mac) 47{ 48 static const unsigned int clear[] = { 49 F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1, 50 F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3 51 }; 52 53 int i; 54 struct adapter *adap = mac->adapter; 55 u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset; 56 57 t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] | 58 F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 | 59 F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 | 60 F_RESETPLL23 | F_RESETPLL01); 61 t3_read_reg(adap, ctrl); 62 udelay(15); 63 64 for (i = 0; i < ARRAY_SIZE(clear); i++) { 65 t3_set_reg_field(adap, ctrl, clear[i], 0); 66 udelay(15); 67 } 68} 69 70void t3b_pcs_reset(struct cmac *mac) 71{ 72 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 73 F_PCS_RESET_, 0); 74 udelay(20); 75 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0, 76 F_PCS_RESET_); 77} 78 79int t3_mac_reset(struct cmac *mac) 80{ 81 static const struct addr_val_pair mac_reset_avp[] = { 82 {A_XGM_TX_CTRL, 0}, 83 {A_XGM_RX_CTRL, 0}, 84 {A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES | 85 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST}, 86 {A_XGM_RX_HASH_LOW, 0}, 87 {A_XGM_RX_HASH_HIGH, 0}, 88 {A_XGM_RX_EXACT_MATCH_LOW_1, 0}, 89 {A_XGM_RX_EXACT_MATCH_LOW_2, 0}, 90 {A_XGM_RX_EXACT_MATCH_LOW_3, 0}, 91 {A_XGM_RX_EXACT_MATCH_LOW_4, 0}, 92 {A_XGM_RX_EXACT_MATCH_LOW_5, 0}, 93 {A_XGM_RX_EXACT_MATCH_LOW_6, 0}, 94 {A_XGM_RX_EXACT_MATCH_LOW_7, 0}, 95 {A_XGM_RX_EXACT_MATCH_LOW_8, 0}, 96 {A_XGM_STAT_CTRL, F_CLRSTATS} 97 }; 98 u32 val; 99 struct adapter *adap = mac->adapter; 100 unsigned int oft = mac->offset; 101 102 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); 103 t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 104 105 t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft); 106 t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft, 107 F_RXSTRFRWRD | F_DISERRFRAMES, 108 uses_xaui(adap) ? 0 : F_RXSTRFRWRD); 109 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX); 110 111 if (uses_xaui(adap)) { 112 if (adap->params.rev == 0) { 113 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, 114 F_RXENABLE | F_TXENABLE); 115 if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft, 116 F_CMULOCK, 1, 5, 2)) { 117 CH_ERR(adap, 118 "MAC %d XAUI SERDES CMU lock failed\n", 119 macidx(mac)); 120 return -1; 121 } 122 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, 123 F_SERDESRESET_); 124 } else 125 xaui_serdes_reset(mac); 126 } 127 128 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft, 129 V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE), 130 V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER); 131 val = F_MAC_RESET_ | F_XGMAC_STOP_EN; 132 133 if (is_10G(adap)) 134 val |= F_PCS_RESET_; 135 else if (uses_xaui(adap)) 136 val |= F_PCS_RESET_ | F_XG2G_RESET_; 137 else 138 val |= F_RGMII_RESET_ | F_XG2G_RESET_; 139 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); 140 t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 141 if ((val & F_PCS_RESET_) && adap->params.rev) { 142 msleep(1); 143 t3b_pcs_reset(mac); 144 } 145 146 memset(&mac->stats, 0, sizeof(mac->stats)); 147 return 0; 148} 149 150static int t3b2_mac_reset(struct cmac *mac) 151{ 152 struct adapter *adap = mac->adapter; 153 unsigned int oft = mac->offset, store; 154 int idx = macidx(mac); 155 u32 val; 156 157 if (!macidx(mac)) 158 t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0); 159 else 160 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); 161 162 /* Stop NIC traffic to reduce the number of TXTOGGLES */ 163 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0); 164 /* Ensure TX drains */ 165 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0); 166 167 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); 168 t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 169 170 /* Store A_TP_TX_DROP_CFG_CH0 */ 171 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 172 store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx); 173 174 msleep(10); 175 176 /* Change DROP_CFG to 0xc0000011 */ 177 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 178 t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011); 179 180 /* Check for xgm Rx fifo empty */ 181 /* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */ 182 if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, 183 0x80000000, 1, 1000, 2)) { 184 CH_ERR(adap, "MAC %d Rx fifo drain failed\n", 185 macidx(mac)); 186 return -1; 187 } 188 189 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); 190 t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 191 192 val = F_MAC_RESET_; 193 if (is_10G(adap)) 194 val |= F_PCS_RESET_; 195 else if (uses_xaui(adap)) 196 val |= F_PCS_RESET_ | F_XG2G_RESET_; 197 else 198 val |= F_RGMII_RESET_ | F_XG2G_RESET_; 199 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); 200 t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 201 if ((val & F_PCS_RESET_) && adap->params.rev) { 202 msleep(1); 203 t3b_pcs_reset(mac); 204 } 205 t3_write_reg(adap, A_XGM_RX_CFG + oft, 206 F_DISPAUSEFRAMES | F_EN1536BFRAMES | 207 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST); 208 209 /* Restore the DROP_CFG */ 210 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 211 t3_write_reg(adap, A_TP_PIO_DATA, store); 212 213 if (!idx) 214 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); 215 else 216 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); 217 218 /* re-enable nic traffic */ 219 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); 220 221 /* Set: re-enable NIC traffic */ 222 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); 223 224 return 0; 225} 226 227/* 228 * Set the exact match register 'idx' to recognize the given Ethernet address. 229 */ 230static void set_addr_filter(struct cmac *mac, int idx, const u8 * addr) 231{ 232 u32 addr_lo, addr_hi; 233 unsigned int oft = mac->offset + idx * 8; 234 235 addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; 236 addr_hi = (addr[5] << 8) | addr[4]; 237 238 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo); 239 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi); 240} 241 242/* Set one of the station's unicast MAC addresses. */ 243int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]) 244{ 245 if (idx >= mac->nucast) 246 return -EINVAL; 247 set_addr_filter(mac, idx, addr); 248 return 0; 249} 250 251/* 252 * Specify the number of exact address filters that should be reserved for 253 * unicast addresses. Caller should reload the unicast and multicast addresses 254 * after calling this. 255 */ 256int t3_mac_set_num_ucast(struct cmac *mac, int n) 257{ 258 if (n > EXACT_ADDR_FILTERS) 259 return -EINVAL; 260 mac->nucast = n; 261 return 0; 262} 263 264void t3_mac_disable_exact_filters(struct cmac *mac) 265{ 266 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1; 267 268 for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) { 269 u32 v = t3_read_reg(mac->adapter, reg); 270 t3_write_reg(mac->adapter, reg, v); 271 } 272 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */ 273} 274 275void t3_mac_enable_exact_filters(struct cmac *mac) 276{ 277 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1; 278 279 for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) { 280 u32 v = t3_read_reg(mac->adapter, reg); 281 t3_write_reg(mac->adapter, reg, v); 282 } 283 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */ 284} 285 286/* Calculate the RX hash filter index of an Ethernet address */ 287static int hash_hw_addr(const u8 * addr) 288{ 289 int hash = 0, octet, bit, i = 0, c; 290 291 for (octet = 0; octet < 6; ++octet) 292 for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) { 293 hash ^= (c & 1) << i; 294 if (++i == 6) 295 i = 0; 296 } 297 return hash; 298} 299 300int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev) 301{ 302 u32 val, hash_lo, hash_hi; 303 struct adapter *adap = mac->adapter; 304 unsigned int oft = mac->offset; 305 306 val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES; 307 if (dev->flags & IFF_PROMISC) 308 val |= F_COPYALLFRAMES; 309 t3_write_reg(adap, A_XGM_RX_CFG + oft, val); 310 311 if (dev->flags & IFF_ALLMULTI) 312 hash_lo = hash_hi = 0xffffffff; 313 else { 314 struct netdev_hw_addr *ha; 315 int exact_addr_idx = mac->nucast; 316 317 hash_lo = hash_hi = 0; 318 netdev_for_each_mc_addr(ha, dev) 319 if (exact_addr_idx < EXACT_ADDR_FILTERS) 320 set_addr_filter(mac, exact_addr_idx++, 321 ha->addr); 322 else { 323 int hash = hash_hw_addr(ha->addr); 324 325 if (hash < 32) 326 hash_lo |= (1 << hash); 327 else 328 hash_hi |= (1 << (hash - 32)); 329 } 330 } 331 332 t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo); 333 t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi); 334 return 0; 335} 336 337static int rx_fifo_hwm(int mtu) 338{ 339 int hwm; 340 341 hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100); 342 return min(hwm, MAC_RXFIFO_SIZE - 8192); 343} 344 345int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) 346{ 347 int hwm, lwm, divisor; 348 int ipg; 349 unsigned int thres, v, reg; 350 struct adapter *adap = mac->adapter; 351 352 /* 353 * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max 354 * packet size register includes header, but not FCS. 355 */ 356 mtu += 14; 357 if (mtu > 1536) 358 mtu += 4; 359 360 if (mtu > MAX_FRAME_SIZE - 4) 361 return -EINVAL; 362 t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); 363 364 if (adap->params.rev >= T3_REV_B2 && 365 (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { 366 t3_mac_disable_exact_filters(mac); 367 v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset); 368 t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset, 369 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST); 370 371 reg = adap->params.rev == T3_REV_B2 ? 372 A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG; 373 374 /* drain RX FIFO */ 375 if (t3_wait_op_done(adap, reg + mac->offset, 376 F_RXFIFO_EMPTY, 1, 20, 5)) { 377 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); 378 t3_mac_enable_exact_filters(mac); 379 return -EIO; 380 } 381 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, 382 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), 383 V_RXMAXPKTSIZE(mtu)); 384 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); 385 t3_mac_enable_exact_filters(mac); 386 } else 387 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, 388 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), 389 V_RXMAXPKTSIZE(mtu)); 390 391 /* 392 * Adjust the PAUSE frame watermarks. We always set the LWM, and the 393 * HWM only if flow-control is enabled. 394 */ 395 hwm = rx_fifo_hwm(mtu); 396 lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4); 397 v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset); 398 v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM); 399 v |= V_RXFIFOPAUSELWM(lwm / 8); 400 if (G_RXFIFOPAUSEHWM(v)) 401 v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) | 402 V_RXFIFOPAUSEHWM(hwm / 8); 403 404 t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v); 405 406 /* Adjust the TX FIFO threshold based on the MTU */ 407 thres = (adap->params.vpd.cclk * 1000) / 15625; 408 thres = (thres * mtu) / 1000; 409 if (is_10G(adap)) 410 thres /= 10; 411 thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; 412 thres = max(thres, 8U); /* need at least 8 */ 413 ipg = (adap->params.rev == T3_REV_C) ? 0 : 1; 414 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, 415 V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG), 416 V_TXFIFOTHRESH(thres) | V_TXIPG(ipg)); 417 418 if (adap->params.rev > 0) { 419 divisor = (adap->params.rev == T3_REV_C) ? 64 : 8; 420 t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset, 421 (hwm - lwm) * 4 / divisor); 422 } 423 t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset, 424 MAC_RXFIFO_SIZE * 4 * 8 / 512); 425 return 0; 426} 427 428int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) 429{ 430 u32 val; 431 struct adapter *adap = mac->adapter; 432 unsigned int oft = mac->offset; 433 434 if (duplex >= 0 && duplex != DUPLEX_FULL) 435 return -EINVAL; 436 if (speed >= 0) { 437 if (speed == SPEED_10) 438 val = V_PORTSPEED(0); 439 else if (speed == SPEED_100) 440 val = V_PORTSPEED(1); 441 else if (speed == SPEED_1000) 442 val = V_PORTSPEED(2); 443 else if (speed == SPEED_10000) 444 val = V_PORTSPEED(3); 445 else 446 return -EINVAL; 447 448 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft, 449 V_PORTSPEED(M_PORTSPEED), val); 450 } 451 452 val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); 453 val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); 454 if (fc & PAUSE_TX) { 455 u32 rx_max_pkt_size = 456 G_RXMAXPKTSIZE(t3_read_reg(adap, 457 A_XGM_RX_MAX_PKT_SIZE + oft)); 458 val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8); 459 } 460 t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); 461 462 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 463 (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); 464 return 0; 465} 466 467int t3_mac_enable(struct cmac *mac, int which) 468{ 469 int idx = macidx(mac); 470 struct adapter *adap = mac->adapter; 471 unsigned int oft = mac->offset; 472 struct mac_stats *s = &mac->stats; 473 474 if (which & MAC_DIRECTION_TX) { 475 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 476 t3_write_reg(adap, A_TP_PIO_DATA, 477 adap->params.rev == T3_REV_C ? 478 0xc4ffff01 : 0xc0ede401); 479 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); 480 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 481 adap->params.rev == T3_REV_C ? 0 : 1 << idx); 482 483 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); 484 485 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx); 486 mac->tx_mcnt = s->tx_frames; 487 mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, 488 A_TP_PIO_DATA))); 489 mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 490 A_XGM_TX_SPI4_SOP_EOP_CNT + 491 oft))); 492 mac->rx_mcnt = s->rx_frames; 493 mac->rx_pause = s->rx_pause; 494 mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 495 A_XGM_RX_SPI4_SOP_EOP_CNT + 496 oft))); 497 mac->rx_ocnt = s->rx_fifo_ovfl; 498 mac->txen = F_TXEN; 499 mac->toggle_cnt = 0; 500 } 501 if (which & MAC_DIRECTION_RX) 502 t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN); 503 return 0; 504} 505 506int t3_mac_disable(struct cmac *mac, int which) 507{ 508 struct adapter *adap = mac->adapter; 509 510 if (which & MAC_DIRECTION_TX) { 511 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 512 mac->txen = 0; 513 } 514 if (which & MAC_DIRECTION_RX) { 515 int val = F_MAC_RESET_; 516 517 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 518 F_PCS_RESET_, 0); 519 msleep(100); 520 t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); 521 if (is_10G(adap)) 522 val |= F_PCS_RESET_; 523 else if (uses_xaui(adap)) 524 val |= F_PCS_RESET_ | F_XG2G_RESET_; 525 else 526 val |= F_RGMII_RESET_ | F_XG2G_RESET_; 527 t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val); 528 } 529 return 0; 530} 531 532int t3b2_mac_watchdog_task(struct cmac *mac) 533{ 534 struct adapter *adap = mac->adapter; 535 struct mac_stats *s = &mac->stats; 536 unsigned int tx_tcnt, tx_xcnt; 537 u64 tx_mcnt = s->tx_frames; 538 int status; 539 540 status = 0; 541 tx_xcnt = 1; /* By default tx_xcnt is making progress */ 542 tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt */ 543 if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) { 544 tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 545 A_XGM_TX_SPI4_SOP_EOP_CNT + 546 mac->offset))); 547 if (tx_xcnt == 0) { 548 t3_write_reg(adap, A_TP_PIO_ADDR, 549 A_TP_TX_DROP_CNT_CH0 + macidx(mac)); 550 tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, 551 A_TP_PIO_DATA))); 552 } else { 553 goto out; 554 } 555 } else { 556 mac->toggle_cnt = 0; 557 goto out; 558 } 559 560 if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) { 561 if (mac->toggle_cnt > 4) { 562 status = 2; 563 goto out; 564 } else { 565 status = 1; 566 goto out; 567 } 568 } else { 569 mac->toggle_cnt = 0; 570 goto out; 571 } 572 573out: 574 mac->tx_tcnt = tx_tcnt; 575 mac->tx_xcnt = tx_xcnt; 576 mac->tx_mcnt = s->tx_frames; 577 mac->rx_pause = s->rx_pause; 578 if (status == 1) { 579 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 580 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ 581 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen); 582 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ 583 mac->toggle_cnt++; 584 } else if (status == 2) { 585 t3b2_mac_reset(mac); 586 mac->toggle_cnt = 0; 587 } 588 return status; 589} 590 591/* 592 * This function is called periodically to accumulate the current values of the 593 * RMON counters into the port statistics. Since the packet counters are only 594 * 32 bits they can overflow in ~286 secs at 10G, so the function should be 595 * called more frequently than that. The byte counters are 45-bit wide, they 596 * would overflow in ~7.8 hours. 597 */ 598const struct mac_stats *t3_mac_update_stats(struct cmac *mac) 599{ 600#define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset) 601#define RMON_UPDATE(mac, name, reg) \ 602 (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg) 603#define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \ 604 (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \ 605 ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32) 606 607 u32 v, lo; 608 609 RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH); 610 RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH); 611 RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES); 612 RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES); 613 RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES); 614 RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES); 615 RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES); 616 RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES); 617 RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES); 618 619 RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES); 620 621 v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); 622 if (mac->adapter->params.rev == T3_REV_B2) 623 v &= 0x7fffffff; 624 mac->stats.rx_too_long += v; 625 626 RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES); 627 RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES); 628 RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES); 629 RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES); 630 RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES); 631 RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES); 632 RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES); 633 634 RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH); 635 RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH); 636 RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST); 637 RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST); 638 RMON_UPDATE(mac, tx_pause, TX_PAUSE); 639 /* This counts error frames in general (bad FCS, underrun, etc). */ 640 RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES); 641 642 RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES); 643 RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES); 644 RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES); 645 RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES); 646 RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES); 647 RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES); 648 RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES); 649 650 /* The next stat isn't clear-on-read. */ 651 t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50); 652 v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA); 653 lo = (u32) mac->stats.rx_cong_drops; 654 mac->stats.rx_cong_drops += (u64) (v - lo); 655 656 return &mac->stats; 657} 658