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