/** * 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; }
int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) { u32 val; struct adapter *adap = mac->adapter; unsigned int oft = mac->offset; if (duplex >= 0 && duplex != DUPLEX_FULL) return -EINVAL; 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; t3_set_reg_field(adap, A_XGM_PORT_CFG + oft, V_PORTSPEED(M_PORTSPEED), val); } 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; }