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