int t3_mac_disable(struct cmac *mac, int which) { struct adapter *adap = mac->adapter; if (which & MAC_DIRECTION_TX) { t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); mac->txen = 0; } if (which & MAC_DIRECTION_RX) { int val = F_MAC_RESET_; t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, F_PCS_RESET_, 0); msleep(100); t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); if (is_10G(adap)) val |= F_PCS_RESET_; else if (uses_xaui(adap)) val |= F_PCS_RESET_ | F_XG2G_RESET_; else val |= F_RGMII_RESET_ | F_XG2G_RESET_; t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val); } return 0; }
/** * t3_mac_set_speed_duplex_fc - set MAC speed, duplex and flow control * @mac: the MAC to configure * @speed: the desired speed (10/100/1000/10000) * @duplex: the desired duplex * @fc: desired Tx/Rx PAUSE configuration * * Set the MAC speed, duplex (actually only full-duplex is supported), and * flow control. If a parameter value is negative the corresponding * MAC setting is left at its current value. */ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) { u32 val; adapter_t *adap = mac->adapter; unsigned int oft = mac->offset; if (duplex >= 0 && duplex != DUPLEX_FULL) return -EINVAL; if (mac->multiport) { u32 rx_max_pkt_size = G_RXMAXPKTSIZE(t3_read_reg(adap, A_XGM_RX_MAX_PKT_SIZE + oft)); val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8); t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, F_TXPAUSEEN); return t3_vsc7323_set_speed_fc(adap, speed, fc, mac->ext_port); } if (speed >= 0) { if (speed == SPEED_10) val = V_PORTSPEED(0); else if (speed == SPEED_100) val = V_PORTSPEED(1); else if (speed == SPEED_1000) val = V_PORTSPEED(2); else if (speed == SPEED_10000) val = V_PORTSPEED(3); else return -EINVAL; if (!uses_xaui(adap)) /* T302 */ t3_set_reg_field(adap, A_XGM_PORT_CFG + oft, V_PORTSPEED(M_PORTSPEED), val); else { u32 old = t3_read_reg(adap, A_XGM_PORT_CFG + oft); if ((old & V_PORTSPEED(M_PORTSPEED)) != val) { t3_mac_reset(mac, val); mac->was_reset = 1; } } } val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); if (fc & PAUSE_TX) { u32 rx_max_pkt_size = G_RXMAXPKTSIZE(t3_read_reg(adap, A_XGM_RX_MAX_PKT_SIZE + oft)); val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8); } t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); return 0; }
static int t3b2_mac_reset(struct cmac *mac) { struct adapter *adap = mac->adapter; unsigned int oft = mac->offset; u32 val; if (!macidx(mac)) t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0); else t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ msleep(10); /* Check for xgm Rx fifo empty */ if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, 0x80000000, 1, 5, 2)) { CH_ERR(adap, "MAC %d Rx fifo drain failed\n", macidx(mac)); return -1; } t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ val = F_MAC_RESET_; if (is_10G(adap)) val |= F_PCS_RESET_; else if (uses_xaui(adap)) val |= F_PCS_RESET_ | F_XG2G_RESET_; else val |= F_RGMII_RESET_ | F_XG2G_RESET_; t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ if ((val & F_PCS_RESET_) && adap->params.rev) { msleep(1); t3b_pcs_reset(mac); } t3_write_reg(adap, A_XGM_RX_CFG + oft, F_DISPAUSEFRAMES | F_EN1536BFRAMES | F_RMFCS | F_ENJUMBO | F_ENHASHMCAST); if (!macidx(mac)) t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); else t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); return 0; }
/* * Returns a reasonable A_XGM_RESET_CTRL value for the mac specified. */ static inline int xgm_reset_ctrl(const struct cmac *mac) { adapter_t *adap = mac->adapter; int val = F_MAC_RESET_ | F_XGMAC_STOP_EN; if (is_10G(adap)) { int cfg = t3_read_reg(adap, A_XGM_PORT_CFG + mac->offset); val |= F_PCS_RESET_; if (G_PORTSPEED(cfg) != 3) /* not running at 10G */ val |= F_XG2G_RESET_; } else if (uses_xaui(adap)) val |= F_PCS_RESET_ | F_XG2G_RESET_; else val |= F_RGMII_RESET_ | F_XG2G_RESET_; return (val); }
int t3_mac_reset(struct cmac *mac) { static const struct addr_val_pair mac_reset_avp[] = { {A_XGM_TX_CTRL, 0}, {A_XGM_RX_CTRL, 0}, {A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES | F_RMFCS | F_ENJUMBO | F_ENHASHMCAST}, {A_XGM_RX_HASH_LOW, 0}, {A_XGM_RX_HASH_HIGH, 0}, {A_XGM_RX_EXACT_MATCH_LOW_1, 0}, {A_XGM_RX_EXACT_MATCH_LOW_2, 0}, {A_XGM_RX_EXACT_MATCH_LOW_3, 0}, {A_XGM_RX_EXACT_MATCH_LOW_4, 0}, {A_XGM_RX_EXACT_MATCH_LOW_5, 0}, {A_XGM_RX_EXACT_MATCH_LOW_6, 0}, {A_XGM_RX_EXACT_MATCH_LOW_7, 0}, {A_XGM_RX_EXACT_MATCH_LOW_8, 0}, {A_XGM_STAT_CTRL, F_CLRSTATS} }; u32 val; struct adapter *adap = mac->adapter; unsigned int oft = mac->offset; t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft); t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft, F_RXSTRFRWRD | F_DISERRFRAMES, uses_xaui(adap) ? 0 : F_RXSTRFRWRD); t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0, F_UNDERUNFIX); if (uses_xaui(adap)) { if (adap->params.rev == 0) { t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, F_RXENABLE | F_TXENABLE); if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft, F_CMULOCK, 1, 5, 2)) { CH_ERR(adap, "MAC %d XAUI SERDES CMU lock failed\n", macidx(mac)); return -1; } t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, F_SERDESRESET_); } else xaui_serdes_reset(mac); } t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + oft, V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE), V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER); val = F_MAC_RESET_ | F_XGMAC_STOP_EN; if (is_10G(adap)) val |= F_PCS_RESET_; else if (uses_xaui(adap)) val |= F_PCS_RESET_ | F_XG2G_RESET_; else val |= F_RGMII_RESET_ | F_XG2G_RESET_; t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ if ((val & F_PCS_RESET_) && adap->params.rev) { msleep(1); t3b_pcs_reset(mac); } memset(&mac->stats, 0, sizeof(mac->stats)); return 0; }
static int t3b2_mac_reset(struct cmac *mac) { struct adapter *adap = mac->adapter; unsigned int oft = mac->offset, store; int idx = macidx(mac); u32 val; if (!macidx(mac)) t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0); else t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); /* Stop NIC traffic to reduce the number of TXTOGGLES */ t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0); /* Ensure TX drains */ t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0); t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ /* Store A_TP_TX_DROP_CFG_CH0 */ t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx); msleep(10); /* Change DROP_CFG to 0xc0000011 */ t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011); /* Check for xgm Rx fifo empty */ /* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */ if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, 0x80000000, 1, 1000, 2)) { CH_ERR(adap, "MAC %d Rx fifo drain failed\n", macidx(mac)); return -1; } t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ val = F_MAC_RESET_; if (is_10G(adap)) val |= F_PCS_RESET_; else if (uses_xaui(adap)) val |= F_PCS_RESET_ | F_XG2G_RESET_; else val |= F_RGMII_RESET_ | F_XG2G_RESET_; t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ if ((val & F_PCS_RESET_) && adap->params.rev) { msleep(1); t3b_pcs_reset(mac); } t3_write_reg(adap, A_XGM_RX_CFG + oft, F_DISPAUSEFRAMES | F_EN1536BFRAMES | F_RMFCS | F_ENJUMBO | F_ENHASHMCAST); /* Restore the DROP_CFG */ t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); t3_write_reg(adap, A_TP_PIO_DATA, store); if (!idx) t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); else t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); /* re-enable nic traffic */ t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); /* Set: re-enable NIC traffic */ t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); return 0; }