14d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 2a02d44a02bd2b3f3848f30e335adc3c076b3f905Divy Le Ray * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. 34d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 41d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * This software is available to you under a choice of one of two 51d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * licenses. You may choose to be licensed under the terms of the GNU 61d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * General Public License (GPL) Version 2, available from the file 71d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * COPYING in the main directory of this source tree, or the 81d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * OpenIB.org BSD license below: 94d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 101d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * Redistribution and use in source and binary forms, with or 111d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * without modification, are permitted provided that the following 121d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * conditions are met: 131d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * 141d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * - Redistributions of source code must retain the above 151d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * copyright notice, this list of conditions and the following 161d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * disclaimer. 171d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * 181d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * - Redistributions in binary form must reproduce the above 191d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * copyright notice, this list of conditions and the following 201d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * disclaimer in the documentation and/or other materials 211d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * provided with the distribution. 221d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * 231d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 241d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 251d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 261d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 271d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 281d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 291d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 301d68e93d65d63814388d1a0b3de028de6dc27ae0Divy Le Ray * SOFTWARE. 314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "common.h" 334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "regs.h" 344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * # of exact address filters. The first one is used for the station address, 374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * the rest are available for multicast addresses. 384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#define EXACT_ADDR_FILTERS 8 404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline int macidx(const struct cmac *mac) 424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR); 444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic void xaui_serdes_reset(struct cmac *mac) 474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray static const unsigned int clear[] = { 494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1, 504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3 514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray }; 524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray int i; 544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct adapter *adap = mac->adapter; 554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset; 564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] | 584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 | 594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 | 604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_RESETPLL23 | F_RESETPLL01); 614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_read_reg(adap, ctrl); 624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray udelay(15); 634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (i = 0; i < ARRAY_SIZE(clear); i++) { 654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(adap, ctrl, clear[i], 0); 664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray udelay(15); 674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid t3b_pcs_reset(struct cmac *mac) 714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_PCS_RESET_, 0); 744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray udelay(20); 754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0, 764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_PCS_RESET_); 774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint t3_mac_reset(struct cmac *mac) 804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray static const struct addr_val_pair mac_reset_avp[] = { 824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_TX_CTRL, 0}, 834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_CTRL, 0}, 844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES | 854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_RMFCS | F_ENJUMBO | F_ENHASHMCAST}, 864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_HASH_LOW, 0}, 874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_HASH_HIGH, 0}, 884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_EXACT_MATCH_LOW_1, 0}, 894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_EXACT_MATCH_LOW_2, 0}, 904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_EXACT_MATCH_LOW_3, 0}, 914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_EXACT_MATCH_LOW_4, 0}, 924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_EXACT_MATCH_LOW_5, 0}, 934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_EXACT_MATCH_LOW_6, 0}, 944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_EXACT_MATCH_LOW_7, 0}, 954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_RX_EXACT_MATCH_LOW_8, 0}, 964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray {A_XGM_STAT_CTRL, F_CLRSTATS} 974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray }; 984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray u32 val; 994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct adapter *adap = mac->adapter; 1004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray unsigned int oft = mac->offset; 1014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); 1034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 1044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft); 1064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft, 1074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_RXSTRFRWRD | F_DISERRFRAMES, 1084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray uses_xaui(adap) ? 0 : F_RXSTRFRWRD); 10975758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX); 1104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (uses_xaui(adap)) { 1124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (adap->params.rev == 0) { 1134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, 1144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_RXENABLE | F_TXENABLE); 1154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft, 1164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_CMULOCK, 1, 5, 2)) { 1174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray CH_ERR(adap, 1184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray "MAC %d XAUI SERDES CMU lock failed\n", 1194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray macidx(mac)); 1204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return -1; 1214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, 1234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray F_SERDESRESET_); 1244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } else 1254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray xaui_serdes_reset(mac); 1264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 12875758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft, 12975758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE), 13075758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER); 13175758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray val = F_MAC_RESET_ | F_XGMAC_STOP_EN; 13275758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray 1334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (is_10G(adap)) 1344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val |= F_PCS_RESET_; 1354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else if (uses_xaui(adap)) 1364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val |= F_PCS_RESET_ | F_XG2G_RESET_; 1374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else 1384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val |= F_RGMII_RESET_ | F_XG2G_RESET_; 1394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); 1404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 1414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if ((val & F_PCS_RESET_) && adap->params.rev) { 1424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray msleep(1); 1434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3b_pcs_reset(mac); 1444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 1454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray memset(&mac->stats, 0, sizeof(mac->stats)); 1474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 1484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 1494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 1509265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemmingerstatic int t3b2_mac_reset(struct cmac *mac) 151fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray{ 152fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray struct adapter *adap = mac->adapter; 153cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray unsigned int oft = mac->offset, store; 154cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray int idx = macidx(mac); 155fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray u32 val; 156fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 1572eab17ab880ad8d570d27517e6c9d9fe74adc214Jeff Garzik if (!macidx(mac)) 158fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0); 159fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray else 160fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); 161fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 162cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray /* Stop NIC traffic to reduce the number of TXTOGGLES */ 163cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0); 164cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray /* Ensure TX drains */ 165cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0); 166cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray 167fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); 168fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 169fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 170cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray /* Store A_TP_TX_DROP_CFG_CH0 */ 171cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 172cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx); 173cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray 174fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray msleep(10); 175fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 176cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray /* Change DROP_CFG to 0xc0000011 */ 177cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 178cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011); 179cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray 180fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray /* Check for xgm Rx fifo empty */ 181cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray /* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */ 182fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, 183cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray 0x80000000, 1, 1000, 2)) { 184fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray CH_ERR(adap, "MAC %d Rx fifo drain failed\n", 185fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray macidx(mac)); 186fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray return -1; 187fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray } 188fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 189fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); 190fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 191fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 192fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray val = F_MAC_RESET_; 193fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray if (is_10G(adap)) 194fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray val |= F_PCS_RESET_; 195fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray else if (uses_xaui(adap)) 196fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray val |= F_PCS_RESET_ | F_XG2G_RESET_; 197fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray else 198fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray val |= F_RGMII_RESET_ | F_XG2G_RESET_; 199fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); 200fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 201fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray if ((val & F_PCS_RESET_) && adap->params.rev) { 202fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray msleep(1); 203fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3b_pcs_reset(mac); 204fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray } 2052eab17ab880ad8d570d27517e6c9d9fe74adc214Jeff Garzik t3_write_reg(adap, A_XGM_RX_CFG + oft, 206fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray F_DISPAUSEFRAMES | F_EN1536BFRAMES | 207fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray F_RMFCS | F_ENJUMBO | F_ENHASHMCAST); 208fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 209cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray /* Restore the DROP_CFG */ 210cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 211cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_write_reg(adap, A_TP_PIO_DATA, store); 212cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray 213cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray if (!idx) 214fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); 215fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray else 216fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); 217fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 218cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray /* re-enable nic traffic */ 219cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); 220cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray 221bf792094ef830117312b3990b63474320ec864c0Divy Le Ray /* Set: re-enable NIC traffic */ 222bf792094ef830117312b3990b63474320ec864c0Divy Le Ray t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); 223bf792094ef830117312b3990b63474320ec864c0Divy Le Ray 224fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray return 0; 225fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray} 226fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 2274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 2284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Set the exact match register 'idx' to recognize the given Ethernet address. 2294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 2304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic void set_addr_filter(struct cmac *mac, int idx, const u8 * addr) 2314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 2324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray u32 addr_lo, addr_hi; 2334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray unsigned int oft = mac->offset + idx * 8; 2344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; 2364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray addr_hi = (addr[5] << 8) | addr[4]; 2374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo); 2394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi); 2404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 2414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* Set one of the station's unicast MAC addresses. */ 2434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]) 2444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 2454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (idx >= mac->nucast) 2464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return -EINVAL; 2474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray set_addr_filter(mac, idx, addr); 2484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 2494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 2504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 2524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Specify the number of exact address filters that should be reserved for 2534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * unicast addresses. Caller should reload the unicast and multicast addresses 2544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * after calling this. 2554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 2564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint t3_mac_set_num_ucast(struct cmac *mac, int n) 2574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 2584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (n > EXACT_ADDR_FILTERS) 2594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return -EINVAL; 2604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray mac->nucast = n; 2614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 2624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 2634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 264bf792094ef830117312b3990b63474320ec864c0Divy Le Rayvoid t3_mac_disable_exact_filters(struct cmac *mac) 2657b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray{ 2667b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1; 2677b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 2687b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) { 2697b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray u32 v = t3_read_reg(mac->adapter, reg); 2707b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray t3_write_reg(mac->adapter, reg, v); 2717b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray } 2727b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */ 2737b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray} 2747b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 275bf792094ef830117312b3990b63474320ec864c0Divy Le Rayvoid t3_mac_enable_exact_filters(struct cmac *mac) 2767b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray{ 2777b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1; 2787b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 2797b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) { 2807b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray u32 v = t3_read_reg(mac->adapter, reg); 2817b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray t3_write_reg(mac->adapter, reg, v); 2827b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray } 2837b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */ 2847b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray} 2857b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 2864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* Calculate the RX hash filter index of an Ethernet address */ 2874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int hash_hw_addr(const u8 * addr) 2884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 2894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray int hash = 0, octet, bit, i = 0, c; 2904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 2914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (octet = 0; octet < 6; ++octet) 2924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) { 2934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray hash ^= (c & 1) << i; 2944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (++i == 6) 2954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray i = 0; 2964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 2974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return hash; 2984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 2994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3000988d26978561d568efed45cc5576d85ea7b609dJiri Pirkoint t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev) 3014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 3024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray u32 val, hash_lo, hash_hi; 3034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct adapter *adap = mac->adapter; 3044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray unsigned int oft = mac->offset; 3054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES; 3070988d26978561d568efed45cc5576d85ea7b609dJiri Pirko if (dev->flags & IFF_PROMISC) 3084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val |= F_COPYALLFRAMES; 3094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RX_CFG + oft, val); 3104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3110988d26978561d568efed45cc5576d85ea7b609dJiri Pirko if (dev->flags & IFF_ALLMULTI) 3124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray hash_lo = hash_hi = 0xffffffff; 3134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else { 31422bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 3154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray int exact_addr_idx = mac->nucast; 3164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray hash_lo = hash_hi = 0; 31822bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, dev) 3194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (exact_addr_idx < EXACT_ADDR_FILTERS) 3200988d26978561d568efed45cc5576d85ea7b609dJiri Pirko set_addr_filter(mac, exact_addr_idx++, 32122bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko ha->addr); 3224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else { 32322bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko int hash = hash_hw_addr(ha->addr); 3244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (hash < 32) 3264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray hash_lo |= (1 << hash); 3274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else 3284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray hash_hi |= (1 << (hash - 32)); 3294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 3304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 3314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo); 3334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi); 3344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 3354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 3364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3377b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Raystatic int rx_fifo_hwm(int mtu) 3387b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray{ 3397b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray int hwm; 3407b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 3417b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100); 3427b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray return min(hwm, MAC_RXFIFO_SIZE - 8192); 3437b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray} 3447b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 3454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) 3464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 34775758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray int hwm, lwm, divisor; 34875758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray int ipg; 34975758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray unsigned int thres, v, reg; 3504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct adapter *adap = mac->adapter; 3514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 3524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* 3534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max 3544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * packet size register includes header, but not FCS. 3554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 3564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray mtu += 14; 35738a8fc0fcf86f131f8bddf3787f9dfa7325bd981Divy Le Ray if (mtu > 1536) 35838a8fc0fcf86f131f8bddf3787f9dfa7325bd981Divy Le Ray mtu += 4; 35938a8fc0fcf86f131f8bddf3787f9dfa7325bd981Divy Le Ray 3604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (mtu > MAX_FRAME_SIZE - 4) 3614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return -EINVAL; 3624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); 3634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 36475758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray if (adap->params.rev >= T3_REV_B2 && 3657b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { 366bf792094ef830117312b3990b63474320ec864c0Divy Le Ray t3_mac_disable_exact_filters(mac); 367549f8009830177fe8897fd098a999b647990f30dDivy Le Ray v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset); 368549f8009830177fe8897fd098a999b647990f30dDivy Le Ray t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset, 3697b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST); 3707b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 37175758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray reg = adap->params.rev == T3_REV_B2 ? 37275758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG; 37375758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray 37475758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray /* drain RX FIFO */ 37575758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray if (t3_wait_op_done(adap, reg + mac->offset, 37675758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray F_RXFIFO_EMPTY, 1, 20, 5)) { 377549f8009830177fe8897fd098a999b647990f30dDivy Le Ray t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); 378bf792094ef830117312b3990b63474320ec864c0Divy Le Ray t3_mac_enable_exact_filters(mac); 3797b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray return -EIO; 3807b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray } 38175758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, 38275758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), 38375758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray V_RXMAXPKTSIZE(mtu)); 384549f8009830177fe8897fd098a999b647990f30dDivy Le Ray t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); 385bf792094ef830117312b3990b63474320ec864c0Divy Le Ray t3_mac_enable_exact_filters(mac); 3867b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray } else 38775758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, 38875758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), 38975758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray V_RXMAXPKTSIZE(mtu)); 3907b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 3917b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray /* 3927b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray * Adjust the PAUSE frame watermarks. We always set the LWM, and the 3937b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray * HWM only if flow-control is enabled. 3947b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray */ 3957b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray hwm = rx_fifo_hwm(mtu); 3967b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4); 397549f8009830177fe8897fd098a999b647990f30dDivy Le Ray v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset); 3984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM); 3994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray v |= V_RXFIFOPAUSELWM(lwm / 8); 4004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (G_RXFIFOPAUSEHWM(v)) 4014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) | 4024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray V_RXFIFOPAUSEHWM(hwm / 8); 4037b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 4044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v); 4054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* Adjust the TX FIFO threshold based on the MTU */ 4074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray thres = (adap->params.vpd.cclk * 1000) / 15625; 4084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray thres = (thres * mtu) / 1000; 4094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (is_10G(adap)) 4104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray thres /= 10; 4114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; 4124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray thres = max(thres, 8U); /* need at least 8 */ 41375758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray ipg = (adap->params.rev == T3_REV_C) ? 0 : 1; 4144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, 415fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG), 41675758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray V_TXFIFOTHRESH(thres) | V_TXIPG(ipg)); 417fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 41875758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray if (adap->params.rev > 0) { 41975758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray divisor = (adap->params.rev == T3_REV_C) ? 64 : 8; 420fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset, 42175758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray (hwm - lwm) * 4 / divisor); 42275758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray } 423fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset, 424fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray MAC_RXFIFO_SIZE * 4 * 8 / 512); 4254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 4264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 4274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) 4294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 4304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray u32 val; 4314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct adapter *adap = mac->adapter; 4324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray unsigned int oft = mac->offset; 4334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (duplex >= 0 && duplex != DUPLEX_FULL) 4354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return -EINVAL; 4364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (speed >= 0) { 4374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (speed == SPEED_10) 4384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val = V_PORTSPEED(0); 4394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else if (speed == SPEED_100) 4404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val = V_PORTSPEED(1); 4414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else if (speed == SPEED_1000) 4424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val = V_PORTSPEED(2); 4434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else if (speed == SPEED_10000) 4444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray val = V_PORTSPEED(3); 4454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray else 4464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return -EINVAL; 4474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(adap, A_XGM_PORT_CFG + oft, 4494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray V_PORTSPEED(M_PORTSPEED), val); 4504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 4514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4527b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); 4537b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); 454cfe2462c6af309ee70e4aeefa55cae976071b9e2Divy Le Ray if (fc & PAUSE_TX) { 455cfe2462c6af309ee70e4aeefa55cae976071b9e2Divy Le Ray u32 rx_max_pkt_size = 456cfe2462c6af309ee70e4aeefa55cae976071b9e2Divy Le Ray G_RXMAXPKTSIZE(t3_read_reg(adap, 457cfe2462c6af309ee70e4aeefa55cae976071b9e2Divy Le Ray A_XGM_RX_MAX_PKT_SIZE + oft)); 458cfe2462c6af309ee70e4aeefa55cae976071b9e2Divy Le Ray val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8); 459cfe2462c6af309ee70e4aeefa55cae976071b9e2Divy Le Ray } 4607b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); 4617b581a0fa85464f7f765b9a66f612e7ec4ab17f9Divy Le Ray 4624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 4634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); 4644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 4654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 4664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 4674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint t3_mac_enable(struct cmac *mac, int which) 4684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 4694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray int idx = macidx(mac); 4704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct adapter *adap = mac->adapter; 4714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray unsigned int oft = mac->offset; 47259cf81076a85e1df273155298c462574b49cc0feDivy Le Ray struct mac_stats *s = &mac->stats; 4732eab17ab880ad8d570d27517e6c9d9fe74adc214Jeff Garzik 4744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (which & MAC_DIRECTION_TX) { 4754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 476cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_write_reg(adap, A_TP_PIO_DATA, 477cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray adap->params.rev == T3_REV_C ? 478cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray 0xc4ffff01 : 0xc0ede401); 4794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); 480cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 481cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray adap->params.rev == T3_REV_C ? 0 : 1 << idx); 482fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 483b1c9e0f7806d1f627f534fd0f83f235087496f7aDivy Le Ray t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); 484b1c9e0f7806d1f627f534fd0f83f235087496f7aDivy Le Ray 485fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx); 48659cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->tx_mcnt = s->tx_frames; 48759cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, 48859cf81076a85e1df273155298c462574b49cc0feDivy Le Ray A_TP_PIO_DATA))); 48959cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 49059cf81076a85e1df273155298c462574b49cc0feDivy Le Ray A_XGM_TX_SPI4_SOP_EOP_CNT + 49159cf81076a85e1df273155298c462574b49cc0feDivy Le Ray oft))); 49259cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->rx_mcnt = s->rx_frames; 493b4687ff753c2c5c330989efed7cdf1a6bc6b512eDivy Le Ray mac->rx_pause = s->rx_pause; 49459cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 49559cf81076a85e1df273155298c462574b49cc0feDivy Le Ray A_XGM_RX_SPI4_SOP_EOP_CNT + 49659cf81076a85e1df273155298c462574b49cc0feDivy Le Ray oft))); 497b1c9e0f7806d1f627f534fd0f83f235087496f7aDivy Le Ray mac->rx_ocnt = s->rx_fifo_ovfl; 498fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray mac->txen = F_TXEN; 499fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray mac->toggle_cnt = 0; 5004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 5014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (which & MAC_DIRECTION_RX) 5024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN); 5034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 5044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 5054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 5064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint t3_mac_disable(struct cmac *mac, int which) 5074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 5084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray struct adapter *adap = mac->adapter; 5094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 5104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray if (which & MAC_DIRECTION_TX) { 5114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 512fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray mac->txen = 0; 5134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray } 51459cf81076a85e1df273155298c462574b49cc0feDivy Le Ray if (which & MAC_DIRECTION_RX) { 515b1c9e0f7806d1f627f534fd0f83f235087496f7aDivy Le Ray int val = F_MAC_RESET_; 516b1c9e0f7806d1f627f534fd0f83f235087496f7aDivy Le Ray 51759cf81076a85e1df273155298c462574b49cc0feDivy Le Ray t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 51859cf81076a85e1df273155298c462574b49cc0feDivy Le Ray F_PCS_RESET_, 0); 51959cf81076a85e1df273155298c462574b49cc0feDivy Le Ray msleep(100); 5204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); 52159cf81076a85e1df273155298c462574b49cc0feDivy Le Ray if (is_10G(adap)) 52259cf81076a85e1df273155298c462574b49cc0feDivy Le Ray val |= F_PCS_RESET_; 52359cf81076a85e1df273155298c462574b49cc0feDivy Le Ray else if (uses_xaui(adap)) 52459cf81076a85e1df273155298c462574b49cc0feDivy Le Ray val |= F_PCS_RESET_ | F_XG2G_RESET_; 52559cf81076a85e1df273155298c462574b49cc0feDivy Le Ray else 52659cf81076a85e1df273155298c462574b49cc0feDivy Le Ray val |= F_RGMII_RESET_ | F_XG2G_RESET_; 52759cf81076a85e1df273155298c462574b49cc0feDivy Le Ray t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val); 52859cf81076a85e1df273155298c462574b49cc0feDivy Le Ray } 5294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return 0; 5304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 5314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 532fc90664e3438c990d280f179ccb0642711d5c553Divy Le Rayint t3b2_mac_watchdog_task(struct cmac *mac) 533fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray{ 534fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray struct adapter *adap = mac->adapter; 53559cf81076a85e1df273155298c462574b49cc0feDivy Le Ray struct mac_stats *s = &mac->stats; 53659cf81076a85e1df273155298c462574b49cc0feDivy Le Ray unsigned int tx_tcnt, tx_xcnt; 537cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray u64 tx_mcnt = s->tx_frames; 538fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray int status; 539fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 5402090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray status = 0; 5412090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray tx_xcnt = 1; /* By default tx_xcnt is making progress */ 5422090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt */ 543b4687ff753c2c5c330989efed7cdf1a6bc6b512eDivy Le Ray if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) { 54459cf81076a85e1df273155298c462574b49cc0feDivy Le Ray tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 54559cf81076a85e1df273155298c462574b49cc0feDivy Le Ray A_XGM_TX_SPI4_SOP_EOP_CNT + 54659cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->offset))); 54759cf81076a85e1df273155298c462574b49cc0feDivy Le Ray if (tx_xcnt == 0) { 54859cf81076a85e1df273155298c462574b49cc0feDivy Le Ray t3_write_reg(adap, A_TP_PIO_ADDR, 54959cf81076a85e1df273155298c462574b49cc0feDivy Le Ray A_TP_TX_DROP_CNT_CH0 + macidx(mac)); 55059cf81076a85e1df273155298c462574b49cc0feDivy Le Ray tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, 55159cf81076a85e1df273155298c462574b49cc0feDivy Le Ray A_TP_PIO_DATA))); 55259cf81076a85e1df273155298c462574b49cc0feDivy Le Ray } else { 553cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray goto out; 55459cf81076a85e1df273155298c462574b49cc0feDivy Le Ray } 55559cf81076a85e1df273155298c462574b49cc0feDivy Le Ray } else { 55659cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->toggle_cnt = 0; 557cd40658a616050df0a50d0a3ded06e3ebcc0a04aDivy Le Ray goto out; 55859cf81076a85e1df273155298c462574b49cc0feDivy Le Ray } 55959cf81076a85e1df273155298c462574b49cc0feDivy Le Ray 56075758e8aa4b7d5c651261ce653dd8d0b716e1edaDivy Le Ray if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) { 5612090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray if (mac->toggle_cnt > 4) { 562fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray status = 2; 5632090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray goto out; 5642090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray } else { 565fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray status = 1; 5662090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray goto out; 5672090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray } 568fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray } else { 569fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray mac->toggle_cnt = 0; 5702090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray goto out; 5712090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray } 5722090dee420911045258d50239dc2c527e4b1dd06Divy Le Ray 5732090dee420911045258d50239dc2c527e4b1dd06Divy Le Rayout: 57459cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->tx_tcnt = tx_tcnt; 57559cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->tx_xcnt = tx_xcnt; 57659cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->tx_mcnt = s->tx_frames; 577b4687ff753c2c5c330989efed7cdf1a6bc6b512eDivy Le Ray mac->rx_pause = s->rx_pause; 57859cf81076a85e1df273155298c462574b49cc0feDivy Le Ray if (status == 1) { 57959cf81076a85e1df273155298c462574b49cc0feDivy Le Ray t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 58059cf81076a85e1df273155298c462574b49cc0feDivy Le Ray t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ 58159cf81076a85e1df273155298c462574b49cc0feDivy Le Ray t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen); 58259cf81076a85e1df273155298c462574b49cc0feDivy Le Ray t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */ 58359cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->toggle_cnt++; 58459cf81076a85e1df273155298c462574b49cc0feDivy Le Ray } else if (status == 2) { 58559cf81076a85e1df273155298c462574b49cc0feDivy Le Ray t3b2_mac_reset(mac); 58659cf81076a85e1df273155298c462574b49cc0feDivy Le Ray mac->toggle_cnt = 0; 58759cf81076a85e1df273155298c462574b49cc0feDivy Le Ray } 588fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray return status; 589fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray} 590fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 5914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* 5924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * This function is called periodically to accumulate the current values of the 5934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * RMON counters into the port statistics. Since the packet counters are only 5944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * 32 bits they can overflow in ~286 secs at 10G, so the function should be 5954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * called more frequently than that. The byte counters are 45-bit wide, they 5964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * would overflow in ~7.8 hours. 5974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */ 5984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayconst struct mac_stats *t3_mac_update_stats(struct cmac *mac) 5994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{ 6004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset) 6014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#define RMON_UPDATE(mac, name, reg) \ 6024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg) 6034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \ 6044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \ 6054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32) 6064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 6074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray u32 v, lo; 6084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 6094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH); 6104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH); 6114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES); 6124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES); 6134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES); 6144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES); 6154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES); 6164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES); 6174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES); 6184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 6194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES); 6204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 621fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); 622fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray if (mac->adapter->params.rev == T3_REV_B2) 623fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray v &= 0x7fffffff; 624fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray mac->stats.rx_too_long += v; 625fc90664e3438c990d280f179ccb0642711d5c553Divy Le Ray 6264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES); 6274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES); 6284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES); 6294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES); 6304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES); 6314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES); 6324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES); 6334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 6344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH); 6354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH); 6364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST); 6374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST); 6384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_pause, TX_PAUSE); 6394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* This counts error frames in general (bad FCS, underrun, etc). */ 6404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES); 6414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 6424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES); 6434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES); 6444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES); 6454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES); 6464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES); 6474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES); 6484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES); 6494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 6504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray /* The next stat isn't clear-on-read. */ 6514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50); 6524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA); 6534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray lo = (u32) mac->stats.rx_cong_drops; 6544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray mac->stats.rx_cong_drops += (u64) (v - lo); 6554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray 6564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray return &mac->stats; 6574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray} 658