1 /************************************************************************** 2 3 Copyright (c) 2007, 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. Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 16 3. Neither the name of the Chelsio Corporation nor the names of its 17 contributors may be used to endorse or promote products derived from 18 this software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 POSSIBILITY OF SUCH DAMAGE. 31 32 ***************************************************************************/ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <dev/cxgb/common/cxgb_common.h> 38 #include <dev/cxgb/common/cxgb_regs.h> 39 40 /* 41 * # of exact address filters. The first one is used for the station address, 42 * the rest are available for multicast addresses. 43 */ 44 #define EXACT_ADDR_FILTERS 8 45 46 static inline int macidx(const struct cmac *mac) 47 { 48 return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR); 49 } 50 51 static void xaui_serdes_reset(struct cmac *mac) 52 { 53 static const unsigned int clear[] = { 54 F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1, 55 F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3 56 }; 57 58 int i; 59 adapter_t *adap = mac->adapter; 60 u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset; 61 62 t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] | 63 F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 | 64 F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 | 65 F_RESETPLL23 | F_RESETPLL01); 66 (void)t3_read_reg(adap, ctrl); 67 udelay(15); 68 69 for (i = 0; i < ARRAY_SIZE(clear); i++) { 70 t3_set_reg_field(adap, ctrl, clear[i], 0); 71 udelay(15); 72 } 73 } 74 75 void t3b_pcs_reset(struct cmac *mac) 76 { 77 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 78 F_PCS_RESET_, 0); 79 udelay(20); 80 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0, 81 F_PCS_RESET_); 82 } 83 84 int t3_mac_reset(struct cmac *mac) 85 { 86 static struct addr_val_pair mac_reset_avp[] = { 87 { A_XGM_TX_CTRL, 0 }, 88 { A_XGM_RX_CTRL, 0 }, 89 { A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES | 90 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST }, 91 { A_XGM_RX_HASH_LOW, 0 }, 92 { A_XGM_RX_HASH_HIGH, 0 }, 93 { A_XGM_RX_EXACT_MATCH_LOW_1, 0 }, 94 { A_XGM_RX_EXACT_MATCH_LOW_2, 0 }, 95 { A_XGM_RX_EXACT_MATCH_LOW_3, 0 }, 96 { A_XGM_RX_EXACT_MATCH_LOW_4, 0 }, 97 { A_XGM_RX_EXACT_MATCH_LOW_5, 0 }, 98 { A_XGM_RX_EXACT_MATCH_LOW_6, 0 }, 99 { A_XGM_RX_EXACT_MATCH_LOW_7, 0 }, 100 { A_XGM_RX_EXACT_MATCH_LOW_8, 0 }, 101 { A_XGM_STAT_CTRL, F_CLRSTATS } 102 }; 103 u32 val; 104 adapter_t *adap = mac->adapter; 105 unsigned int oft = mac->offset; 106 107 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); 108 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 109 110 t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft); 111 t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft, 112 F_RXSTRFRWRD | F_DISERRFRAMES, 113 uses_xaui(adap) ? 0 : F_RXSTRFRWRD); 114 115 if (uses_xaui(adap)) { 116 if (adap->params.rev == 0) { 117 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, 118 F_RXENABLE | F_TXENABLE); 119 if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft, 120 F_CMULOCK, 1, 5, 2)) { 121 CH_ERR(adap, 122 "MAC %d XAUI SERDES CMU lock failed\n", 123 macidx(mac)); 124 return -1; 125 } 126 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, 127 F_SERDESRESET_); 128 } else 129 xaui_serdes_reset(mac); 130 } 131 132 val = F_MAC_RESET_; 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 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 141 if ((val & F_PCS_RESET_) && adap->params.rev) { 142 t3_os_sleep(1); 143 t3b_pcs_reset(mac); 144 } 145 146 memset(&mac->stats, 0, sizeof(mac->stats)); 147 return 0; 148 } 149 150 static int t3b2_mac_reset(struct cmac *mac) 151 { 152 u32 val; 153 adapter_t *adap = mac->adapter; 154 unsigned int oft = mac->offset; 155 156 157 /* Stop egress traffic to xgm*/ 158 if (!macidx(mac)) 159 t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0); 160 else 161 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); 162 163 /* PCS in reset */ 164 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); 165 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 166 167 t3_os_sleep(10); 168 169 /* Check for xgm Rx fifo empty */ 170 if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, 171 0x80000000, 1, 5, 2)) { 172 CH_ERR(adap, "MAC %d Rx fifo drain failed\n", 173 macidx(mac)); 174 return -1; 175 } 176 177 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); /*MAC in reset*/ 178 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 179 180 val = F_MAC_RESET_; 181 if (is_10G(adap)) 182 val |= F_PCS_RESET_; 183 else if (uses_xaui(adap)) 184 val |= F_PCS_RESET_ | F_XG2G_RESET_; 185 else 186 val |= F_RGMII_RESET_ | F_XG2G_RESET_; 187 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); 188 (void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 189 if ((val & F_PCS_RESET_) && adap->params.rev) { 190 t3_os_sleep(1); 191 t3b_pcs_reset(mac); 192 } 193 t3_write_reg(adap, A_XGM_RX_CFG + oft, 194 F_DISPAUSEFRAMES | F_EN1536BFRAMES | 195 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST ); 196 197 /*Resume egress traffic to xgm*/ 198 if (!macidx(mac)) 199 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); 200 else 201 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); 202 203 return 0; 204 } 205 206 /* 207 * Set the exact match register 'idx' to recognize the given Ethernet address. 208 */ 209 static void set_addr_filter(struct cmac *mac, int idx, const u8 *addr) 210 { 211 u32 addr_lo, addr_hi; 212 unsigned int oft = mac->offset + idx * 8; 213 214 addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; 215 addr_hi = (addr[5] << 8) | addr[4]; 216 217 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo); 218 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi); 219 } 220 221 /* Set one of the station's unicast MAC addresses. */ 222 int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]) 223 { 224 if (idx >= mac->nucast) 225 return -EINVAL; 226 set_addr_filter(mac, idx, addr); 227 return 0; 228 } 229 230 /* 231 * Specify the number of exact address filters that should be reserved for 232 * unicast addresses. Caller should reload the unicast and multicast addresses 233 * after calling this. 234 */ 235 int t3_mac_set_num_ucast(struct cmac *mac, int n) 236 { 237 if (n > EXACT_ADDR_FILTERS) 238 return -EINVAL; 239 mac->nucast = n; 240 return 0; 241 } 242 243 /* Calculate the RX hash filter index of an Ethernet address */ 244 static int hash_hw_addr(const u8 *addr) 245 { 246 int hash = 0, octet, bit, i = 0, c; 247 248 for (octet = 0; octet < 6; ++octet) 249 for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) { 250 hash ^= (c & 1) << i; 251 if (++i == 6) 252 i = 0; 253 } 254 return hash; 255 } 256 257 int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm) 258 { 259 u32 val, hash_lo, hash_hi; 260 adapter_t *adap = mac->adapter; 261 unsigned int oft = mac->offset; 262 263 val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES; 264 if (promisc_rx_mode(rm)) 265 val |= F_COPYALLFRAMES; 266 t3_write_reg(adap, A_XGM_RX_CFG + oft, val); 267 268 if (allmulti_rx_mode(rm)) 269 hash_lo = hash_hi = 0xffffffff; 270 else { 271 u8 *addr; 272 int exact_addr_idx = mac->nucast; 273 274 hash_lo = hash_hi = 0; 275 while ((addr = t3_get_next_mcaddr(rm))) 276 if (exact_addr_idx < EXACT_ADDR_FILTERS) 277 set_addr_filter(mac, exact_addr_idx++, addr); 278 else { 279 int hash = hash_hw_addr(addr); 280 281 if (hash < 32) 282 hash_lo |= (1 << hash); 283 else 284 hash_hi |= (1 << (hash - 32)); 285 } 286 } 287 288 t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo); 289 t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi); 290 return 0; 291 } 292 293 int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) 294 { 295 int hwm, lwm; 296 unsigned int thres, v; 297 adapter_t *adap = mac->adapter; 298 299 /* 300 * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max 301 * packet size register includes header, but not FCS. 302 */ 303 mtu += 14; 304 if (mtu > MAX_FRAME_SIZE - 4) 305 return -EINVAL; 306 t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); 307 308 /* 309 * Adjust the PAUSE frame watermarks. We always set the LWM, and the 310 * HWM only if flow-control is enabled. 311 */ 312 hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu, 313 MAC_RXFIFO_SIZE * 38 / 100); 314 hwm = min(hwm, MAC_RXFIFO_SIZE - 8192); 315 lwm = min(3 * (int) mtu, MAC_RXFIFO_SIZE /4); 316 v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset); 317 v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM); 318 v |= V_RXFIFOPAUSELWM(lwm / 8); 319 if (G_RXFIFOPAUSEHWM(v)) 320 v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) | 321 V_RXFIFOPAUSEHWM(hwm / 8); 322 t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v); 323 324 /* Adjust the TX FIFO threshold based on the MTU */ 325 thres = (adap->params.vpd.cclk * 1000) / 15625; 326 thres = (thres * mtu) / 1000; 327 if (is_10G(adap)) 328 thres /= 10; 329 thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; 330 thres = max(thres, 8U); /* need at least 8 */ 331 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, 332 V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG), 333 V_TXFIFOTHRESH(thres) | V_TXIPG(1)); 334 335 /* Assuming a minimum drain rate of 2.5Gbps... 336 */ 337 if (adap->params.rev > 0) 338 t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset, 339 (hwm-lwm) * 4 / 8); 340 t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset, 341 MAC_RXFIFO_SIZE * 4 * 8 / 512); 342 return 0; 343 } 344 345 int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) 346 { 347 u32 val; 348 adapter_t *adap = mac->adapter; 349 unsigned int oft = mac->offset; 350 351 if (duplex >= 0 && duplex != DUPLEX_FULL) 352 return -EINVAL; 353 if (speed >= 0) { 354 if (speed == SPEED_10) 355 val = V_PORTSPEED(0); 356 else if (speed == SPEED_100) 357 val = V_PORTSPEED(1); 358 else if (speed == SPEED_1000) 359 val = V_PORTSPEED(2); 360 else if (speed == SPEED_10000) 361 val = V_PORTSPEED(3); 362 else 363 return -EINVAL; 364 365 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft, 366 V_PORTSPEED(M_PORTSPEED), val); 367 } 368 #if 0 369 val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); 370 val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); 371 if (fc & PAUSE_TX) 372 val |= V_RXFIFOPAUSEHWM(G_RXFIFOPAUSELWM(val) + 128); /* +1KB */ 373 t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); 374 #endif 375 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 376 (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); 377 return 0; 378 } 379 380 int t3_mac_enable(struct cmac *mac, int which) 381 { 382 int idx = macidx(mac); 383 adapter_t *adap = mac->adapter; 384 unsigned int oft = mac->offset; 385 386 if (which & MAC_DIRECTION_TX) { 387 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); 388 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 389 t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401); 390 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); 391 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); 392 393 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx); 394 mac->tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA))); 395 mac->xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_TX_SPI4_SOP_EOP_CNT))); 396 mac->txen = F_TXEN; 397 mac->toggle_cnt = 0; 398 } 399 if (which & MAC_DIRECTION_RX) 400 t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN); 401 return 0; 402 } 403 404 int t3_mac_disable(struct cmac *mac, int which) 405 { 406 int idx = macidx(mac); 407 adapter_t *adap = mac->adapter; 408 409 if (which & MAC_DIRECTION_TX) { 410 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 411 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 412 t3_write_reg(adap, A_TP_PIO_DATA, 0xc000001f); 413 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); 414 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); 415 mac->txen = 0; 416 } 417 if (which & MAC_DIRECTION_RX) 418 t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); 419 return 0; 420 } 421 422 int t3b2_mac_watchdog_task(struct cmac *mac) 423 { 424 int status; 425 unsigned int tcnt, xcnt; 426 adapter_t *adap = mac->adapter; 427 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + macidx(mac)); 428 tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA))); 429 xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_TX_SPI4_SOP_EOP_CNT + mac->offset))); 430 431 if ((tcnt != mac->tcnt) && (xcnt == 0) && (mac->xcnt == 0)) { 432 if (mac->toggle_cnt > 4) { 433 t3b2_mac_reset(mac); 434 mac->toggle_cnt = 0; 435 status = 2; 436 } else { 437 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 438 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ 439 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen); 440 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ 441 mac->toggle_cnt++; 442 status = 1; 443 } 444 } else { 445 mac->toggle_cnt = 0; 446 status = 0; 447 } 448 mac->tcnt = tcnt; 449 mac->xcnt = xcnt; 450 return status; 451 } 452 453 /* 454 * This function is called periodically to accumulate the current values of the 455 * RMON counters into the port statistics. Since the packet counters are only 456 * 32 bits they can overflow in ~286 secs at 10G, so the function should be 457 * called more frequently than that. The byte counters are 45-bit wide, they 458 * would overflow in ~7.8 hours. 459 */ 460 const struct mac_stats *t3_mac_update_stats(struct cmac *mac) 461 { 462 #define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset) 463 #define RMON_UPDATE(mac, name, reg) \ 464 (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg) 465 #define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \ 466 (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \ 467 ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32) 468 469 u32 v, lo; 470 471 RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH); 472 RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH); 473 RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES); 474 RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES); 475 RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES); 476 RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES); 477 RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES); 478 RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES); 479 RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES); 480 481 RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES); 482 483 v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); 484 if (mac->adapter->params.rev == T3_REV_B2) 485 v &= 0x7fffffff; 486 mac->stats.rx_too_long += v; 487 488 RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES); 489 RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES); 490 RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES); 491 RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES); 492 RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES); 493 RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES); 494 RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES); 495 496 RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH); 497 RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH); 498 RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST); 499 RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST); 500 RMON_UPDATE(mac, tx_pause, TX_PAUSE); 501 /* This counts error frames in general (bad FCS, underrun, etc). */ 502 RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES); 503 504 RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES); 505 RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES); 506 RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES); 507 RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES); 508 RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES); 509 RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES); 510 RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES); 511 512 /* The next stat isn't clear-on-read. */ 513 t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50); 514 v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA); 515 lo = (u32)mac->stats.rx_cong_drops; 516 mac->stats.rx_cong_drops += (u64)(v - lo); 517 518 return &mac->stats; 519 } 520