0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include "common.h"
0033 #include "regs.h"
0034
0035
0036
0037
0038
0039 #define EXACT_ADDR_FILTERS 8
0040
0041 static inline int macidx(const struct cmac *mac)
0042 {
0043 return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR);
0044 }
0045
0046 static void xaui_serdes_reset(struct cmac *mac)
0047 {
0048 static const unsigned int clear[] = {
0049 F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1,
0050 F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3
0051 };
0052
0053 int i;
0054 struct adapter *adap = mac->adapter;
0055 u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset;
0056
0057 t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] |
0058 F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 |
0059 F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 |
0060 F_RESETPLL23 | F_RESETPLL01);
0061 t3_read_reg(adap, ctrl);
0062 udelay(15);
0063
0064 for (i = 0; i < ARRAY_SIZE(clear); i++) {
0065 t3_set_reg_field(adap, ctrl, clear[i], 0);
0066 udelay(15);
0067 }
0068 }
0069
0070 void t3b_pcs_reset(struct cmac *mac)
0071 {
0072 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
0073 F_PCS_RESET_, 0);
0074 udelay(20);
0075 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0,
0076 F_PCS_RESET_);
0077 }
0078
0079 int t3_mac_reset(struct cmac *mac)
0080 {
0081 static const struct addr_val_pair mac_reset_avp[] = {
0082 {A_XGM_TX_CTRL, 0},
0083 {A_XGM_RX_CTRL, 0},
0084 {A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES |
0085 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST},
0086 {A_XGM_RX_HASH_LOW, 0},
0087 {A_XGM_RX_HASH_HIGH, 0},
0088 {A_XGM_RX_EXACT_MATCH_LOW_1, 0},
0089 {A_XGM_RX_EXACT_MATCH_LOW_2, 0},
0090 {A_XGM_RX_EXACT_MATCH_LOW_3, 0},
0091 {A_XGM_RX_EXACT_MATCH_LOW_4, 0},
0092 {A_XGM_RX_EXACT_MATCH_LOW_5, 0},
0093 {A_XGM_RX_EXACT_MATCH_LOW_6, 0},
0094 {A_XGM_RX_EXACT_MATCH_LOW_7, 0},
0095 {A_XGM_RX_EXACT_MATCH_LOW_8, 0},
0096 {A_XGM_STAT_CTRL, F_CLRSTATS}
0097 };
0098 u32 val;
0099 struct adapter *adap = mac->adapter;
0100 unsigned int oft = mac->offset;
0101
0102 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
0103 t3_read_reg(adap, A_XGM_RESET_CTRL + oft);
0104
0105 t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft);
0106 t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft,
0107 F_RXSTRFRWRD | F_DISERRFRAMES,
0108 uses_xaui(adap) ? 0 : F_RXSTRFRWRD);
0109 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX);
0110
0111 if (uses_xaui(adap)) {
0112 if (adap->params.rev == 0) {
0113 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
0114 F_RXENABLE | F_TXENABLE);
0115 if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft,
0116 F_CMULOCK, 1, 5, 2)) {
0117 CH_ERR(adap,
0118 "MAC %d XAUI SERDES CMU lock failed\n",
0119 macidx(mac));
0120 return -1;
0121 }
0122 t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0,
0123 F_SERDESRESET_);
0124 } else
0125 xaui_serdes_reset(mac);
0126 }
0127
0128 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
0129 V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE),
0130 V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER);
0131 val = F_MAC_RESET_ | F_XGMAC_STOP_EN;
0132
0133 if (is_10G(adap))
0134 val |= F_PCS_RESET_;
0135 else if (uses_xaui(adap))
0136 val |= F_PCS_RESET_ | F_XG2G_RESET_;
0137 else
0138 val |= F_RGMII_RESET_ | F_XG2G_RESET_;
0139 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
0140 t3_read_reg(adap, A_XGM_RESET_CTRL + oft);
0141 if ((val & F_PCS_RESET_) && adap->params.rev) {
0142 msleep(1);
0143 t3b_pcs_reset(mac);
0144 }
0145
0146 memset(&mac->stats, 0, sizeof(mac->stats));
0147 return 0;
0148 }
0149
0150 static int t3b2_mac_reset(struct cmac *mac)
0151 {
0152 struct adapter *adap = mac->adapter;
0153 unsigned int oft = mac->offset, store;
0154 int idx = macidx(mac);
0155 u32 val;
0156
0157 if (!macidx(mac))
0158 t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
0159 else
0160 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
0161
0162
0163 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0);
0164
0165 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0);
0166
0167 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
0168 t3_read_reg(adap, A_XGM_RESET_CTRL + oft);
0169
0170
0171 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
0172 store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx);
0173
0174 msleep(10);
0175
0176
0177 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
0178 t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011);
0179
0180
0181
0182 if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
0183 0x80000000, 1, 1000, 2)) {
0184 CH_ERR(adap, "MAC %d Rx fifo drain failed\n",
0185 macidx(mac));
0186 return -1;
0187 }
0188
0189 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0);
0190 t3_read_reg(adap, A_XGM_RESET_CTRL + oft);
0191
0192 val = F_MAC_RESET_;
0193 if (is_10G(adap))
0194 val |= F_PCS_RESET_;
0195 else if (uses_xaui(adap))
0196 val |= F_PCS_RESET_ | F_XG2G_RESET_;
0197 else
0198 val |= F_RGMII_RESET_ | F_XG2G_RESET_;
0199 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
0200 t3_read_reg(adap, A_XGM_RESET_CTRL + oft);
0201 if ((val & F_PCS_RESET_) && adap->params.rev) {
0202 msleep(1);
0203 t3b_pcs_reset(mac);
0204 }
0205 t3_write_reg(adap, A_XGM_RX_CFG + oft,
0206 F_DISPAUSEFRAMES | F_EN1536BFRAMES |
0207 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST);
0208
0209
0210 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
0211 t3_write_reg(adap, A_TP_PIO_DATA, store);
0212
0213 if (!idx)
0214 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE);
0215 else
0216 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE);
0217
0218
0219 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
0220
0221
0222 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
0223
0224 return 0;
0225 }
0226
0227
0228
0229
0230 static void set_addr_filter(struct cmac *mac, int idx, const u8 * addr)
0231 {
0232 u32 addr_lo, addr_hi;
0233 unsigned int oft = mac->offset + idx * 8;
0234
0235 addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
0236 addr_hi = (addr[5] << 8) | addr[4];
0237
0238 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo);
0239 t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi);
0240 }
0241
0242
0243 int t3_mac_set_address(struct cmac *mac, unsigned int idx, const u8 addr[6])
0244 {
0245 if (idx >= mac->nucast)
0246 return -EINVAL;
0247 set_addr_filter(mac, idx, addr);
0248 return 0;
0249 }
0250
0251
0252
0253
0254
0255
0256 int t3_mac_set_num_ucast(struct cmac *mac, int n)
0257 {
0258 if (n > EXACT_ADDR_FILTERS)
0259 return -EINVAL;
0260 mac->nucast = n;
0261 return 0;
0262 }
0263
0264 void t3_mac_disable_exact_filters(struct cmac *mac)
0265 {
0266 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
0267
0268 for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
0269 u32 v = t3_read_reg(mac->adapter, reg);
0270 t3_write_reg(mac->adapter, reg, v);
0271 }
0272 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1);
0273 }
0274
0275 void t3_mac_enable_exact_filters(struct cmac *mac)
0276 {
0277 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
0278
0279 for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
0280 u32 v = t3_read_reg(mac->adapter, reg);
0281 t3_write_reg(mac->adapter, reg, v);
0282 }
0283 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1);
0284 }
0285
0286
0287 static int hash_hw_addr(const u8 * addr)
0288 {
0289 int hash = 0, octet, bit, i = 0, c;
0290
0291 for (octet = 0; octet < 6; ++octet)
0292 for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) {
0293 hash ^= (c & 1) << i;
0294 if (++i == 6)
0295 i = 0;
0296 }
0297 return hash;
0298 }
0299
0300 int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev)
0301 {
0302 u32 val, hash_lo, hash_hi;
0303 struct adapter *adap = mac->adapter;
0304 unsigned int oft = mac->offset;
0305
0306 val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES;
0307 if (dev->flags & IFF_PROMISC)
0308 val |= F_COPYALLFRAMES;
0309 t3_write_reg(adap, A_XGM_RX_CFG + oft, val);
0310
0311 if (dev->flags & IFF_ALLMULTI)
0312 hash_lo = hash_hi = 0xffffffff;
0313 else {
0314 struct netdev_hw_addr *ha;
0315 int exact_addr_idx = mac->nucast;
0316
0317 hash_lo = hash_hi = 0;
0318 netdev_for_each_mc_addr(ha, dev)
0319 if (exact_addr_idx < EXACT_ADDR_FILTERS)
0320 set_addr_filter(mac, exact_addr_idx++,
0321 ha->addr);
0322 else {
0323 int hash = hash_hw_addr(ha->addr);
0324
0325 if (hash < 32)
0326 hash_lo |= (1 << hash);
0327 else
0328 hash_hi |= (1 << (hash - 32));
0329 }
0330 }
0331
0332 t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo);
0333 t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi);
0334 return 0;
0335 }
0336
0337 static int rx_fifo_hwm(int mtu)
0338 {
0339 int hwm;
0340
0341 hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
0342 return min(hwm, MAC_RXFIFO_SIZE - 8192);
0343 }
0344
0345 int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
0346 {
0347 int hwm, lwm, divisor;
0348 int ipg;
0349 unsigned int thres, v, reg;
0350 struct adapter *adap = mac->adapter;
0351
0352
0353
0354
0355
0356 mtu += 14;
0357 if (mtu > 1536)
0358 mtu += 4;
0359
0360 if (mtu > MAX_FRAME_SIZE - 4)
0361 return -EINVAL;
0362 t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
0363
0364 if (adap->params.rev >= T3_REV_B2 &&
0365 (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
0366 t3_mac_disable_exact_filters(mac);
0367 v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
0368 t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
0369 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
0370
0371 reg = adap->params.rev == T3_REV_B2 ?
0372 A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG;
0373
0374
0375 if (t3_wait_op_done(adap, reg + mac->offset,
0376 F_RXFIFO_EMPTY, 1, 20, 5)) {
0377 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
0378 t3_mac_enable_exact_filters(mac);
0379 return -EIO;
0380 }
0381 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
0382 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
0383 V_RXMAXPKTSIZE(mtu));
0384 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
0385 t3_mac_enable_exact_filters(mac);
0386 } else
0387 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
0388 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
0389 V_RXMAXPKTSIZE(mtu));
0390
0391
0392
0393
0394
0395 hwm = rx_fifo_hwm(mtu);
0396 lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
0397 v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
0398 v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
0399 v |= V_RXFIFOPAUSELWM(lwm / 8);
0400 if (G_RXFIFOPAUSEHWM(v))
0401 v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
0402 V_RXFIFOPAUSEHWM(hwm / 8);
0403
0404 t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
0405
0406
0407 thres = (adap->params.vpd.cclk * 1000) / 15625;
0408 thres = (thres * mtu) / 1000;
0409 if (is_10G(adap))
0410 thres /= 10;
0411 thres = mtu > thres ? (mtu - thres + 7) / 8 : 0;
0412 thres = max(thres, 8U);
0413 ipg = (adap->params.rev == T3_REV_C) ? 0 : 1;
0414 t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
0415 V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
0416 V_TXFIFOTHRESH(thres) | V_TXIPG(ipg));
0417
0418 if (adap->params.rev > 0) {
0419 divisor = (adap->params.rev == T3_REV_C) ? 64 : 8;
0420 t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
0421 (hwm - lwm) * 4 / divisor);
0422 }
0423 t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
0424 MAC_RXFIFO_SIZE * 4 * 8 / 512);
0425 return 0;
0426 }
0427
0428 int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
0429 {
0430 u32 val;
0431 struct adapter *adap = mac->adapter;
0432 unsigned int oft = mac->offset;
0433
0434 if (duplex >= 0 && duplex != DUPLEX_FULL)
0435 return -EINVAL;
0436 if (speed >= 0) {
0437 if (speed == SPEED_10)
0438 val = V_PORTSPEED(0);
0439 else if (speed == SPEED_100)
0440 val = V_PORTSPEED(1);
0441 else if (speed == SPEED_1000)
0442 val = V_PORTSPEED(2);
0443 else if (speed == SPEED_10000)
0444 val = V_PORTSPEED(3);
0445 else
0446 return -EINVAL;
0447
0448 t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
0449 V_PORTSPEED(M_PORTSPEED), val);
0450 }
0451
0452 val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
0453 val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
0454 if (fc & PAUSE_TX) {
0455 u32 rx_max_pkt_size =
0456 G_RXMAXPKTSIZE(t3_read_reg(adap,
0457 A_XGM_RX_MAX_PKT_SIZE + oft));
0458 val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
0459 }
0460 t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
0461
0462 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
0463 (fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
0464 return 0;
0465 }
0466
0467 int t3_mac_enable(struct cmac *mac, int which)
0468 {
0469 int idx = macidx(mac);
0470 struct adapter *adap = mac->adapter;
0471 unsigned int oft = mac->offset;
0472 struct mac_stats *s = &mac->stats;
0473
0474 if (which & MAC_DIRECTION_TX) {
0475 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
0476 t3_write_reg(adap, A_TP_PIO_DATA,
0477 adap->params.rev == T3_REV_C ?
0478 0xc4ffff01 : 0xc0ede401);
0479 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
0480 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx,
0481 adap->params.rev == T3_REV_C ? 0 : 1 << idx);
0482
0483 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
0484
0485 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
0486 mac->tx_mcnt = s->tx_frames;
0487 mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
0488 A_TP_PIO_DATA)));
0489 mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
0490 A_XGM_TX_SPI4_SOP_EOP_CNT +
0491 oft)));
0492 mac->rx_mcnt = s->rx_frames;
0493 mac->rx_pause = s->rx_pause;
0494 mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
0495 A_XGM_RX_SPI4_SOP_EOP_CNT +
0496 oft)));
0497 mac->rx_ocnt = s->rx_fifo_ovfl;
0498 mac->txen = F_TXEN;
0499 mac->toggle_cnt = 0;
0500 }
0501 if (which & MAC_DIRECTION_RX)
0502 t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
0503 return 0;
0504 }
0505
0506 int t3_mac_disable(struct cmac *mac, int which)
0507 {
0508 struct adapter *adap = mac->adapter;
0509
0510 if (which & MAC_DIRECTION_TX) {
0511 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
0512 mac->txen = 0;
0513 }
0514 if (which & MAC_DIRECTION_RX) {
0515 int val = F_MAC_RESET_;
0516
0517 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
0518 F_PCS_RESET_, 0);
0519 msleep(100);
0520 t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
0521 if (is_10G(adap))
0522 val |= F_PCS_RESET_;
0523 else if (uses_xaui(adap))
0524 val |= F_PCS_RESET_ | F_XG2G_RESET_;
0525 else
0526 val |= F_RGMII_RESET_ | F_XG2G_RESET_;
0527 t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
0528 }
0529 return 0;
0530 }
0531
0532 int t3b2_mac_watchdog_task(struct cmac *mac)
0533 {
0534 struct adapter *adap = mac->adapter;
0535 struct mac_stats *s = &mac->stats;
0536 unsigned int tx_tcnt, tx_xcnt;
0537 u64 tx_mcnt = s->tx_frames;
0538 int status;
0539
0540 status = 0;
0541 tx_xcnt = 1;
0542 tx_tcnt = mac->tx_tcnt;
0543 if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) {
0544 tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
0545 A_XGM_TX_SPI4_SOP_EOP_CNT +
0546 mac->offset)));
0547 if (tx_xcnt == 0) {
0548 t3_write_reg(adap, A_TP_PIO_ADDR,
0549 A_TP_TX_DROP_CNT_CH0 + macidx(mac));
0550 tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
0551 A_TP_PIO_DATA)));
0552 } else {
0553 goto out;
0554 }
0555 } else {
0556 mac->toggle_cnt = 0;
0557 goto out;
0558 }
0559
0560 if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) {
0561 if (mac->toggle_cnt > 4) {
0562 status = 2;
0563 goto out;
0564 } else {
0565 status = 1;
0566 goto out;
0567 }
0568 } else {
0569 mac->toggle_cnt = 0;
0570 goto out;
0571 }
0572
0573 out:
0574 mac->tx_tcnt = tx_tcnt;
0575 mac->tx_xcnt = tx_xcnt;
0576 mac->tx_mcnt = s->tx_frames;
0577 mac->rx_pause = s->rx_pause;
0578 if (status == 1) {
0579 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
0580 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);
0581 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
0582 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);
0583 mac->toggle_cnt++;
0584 } else if (status == 2) {
0585 t3b2_mac_reset(mac);
0586 mac->toggle_cnt = 0;
0587 }
0588 return status;
0589 }
0590
0591
0592
0593
0594
0595
0596
0597
0598 const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
0599 {
0600 #define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset)
0601 #define RMON_UPDATE(mac, name, reg) \
0602 (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg)
0603 #define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \
0604 (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \
0605 ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32)
0606
0607 u32 v, lo;
0608
0609 RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH);
0610 RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH);
0611 RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES);
0612 RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES);
0613 RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES);
0614 RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES);
0615 RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES);
0616 RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES);
0617 RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES);
0618
0619 RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES);
0620
0621 v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
0622 if (mac->adapter->params.rev == T3_REV_B2)
0623 v &= 0x7fffffff;
0624 mac->stats.rx_too_long += v;
0625
0626 RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES);
0627 RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES);
0628 RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES);
0629 RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES);
0630 RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES);
0631 RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES);
0632 RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES);
0633
0634 RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH);
0635 RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH);
0636 RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST);
0637 RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST);
0638 RMON_UPDATE(mac, tx_pause, TX_PAUSE);
0639
0640 RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES);
0641
0642 RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES);
0643 RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES);
0644 RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES);
0645 RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES);
0646 RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES);
0647 RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES);
0648 RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES);
0649
0650
0651 t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50);
0652 v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA);
0653 lo = (u32) mac->stats.rx_cong_drops;
0654 mac->stats.rx_cong_drops += (u64) (v - lo);
0655
0656 return &mac->stats;
0657 }