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