diff options
Diffstat (limited to 'sys/dev/cxgb/common/cxgb_xgmac.c')
-rw-r--r-- | sys/dev/cxgb/common/cxgb_xgmac.c | 143 |
1 files changed, 115 insertions, 28 deletions
diff --git a/sys/dev/cxgb/common/cxgb_xgmac.c b/sys/dev/cxgb/common/cxgb_xgmac.c index ca8801f602a81..745cc4b4dd5e2 100644 --- a/sys/dev/cxgb/common/cxgb_xgmac.c +++ b/sys/dev/cxgb/common/cxgb_xgmac.c @@ -75,6 +75,12 @@ static void xaui_serdes_reset(struct cmac *mac) } } +/** + * t3b_pcs_reset - reset the PCS on T3B+ adapters + * @mac: the XGMAC handle + * + * Reset the XGMAC PCS block on T3B+ adapters. + */ void t3b_pcs_reset(struct cmac *mac) { t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, @@ -84,6 +90,12 @@ void t3b_pcs_reset(struct cmac *mac) F_PCS_RESET_); } +/** + * t3_mac_reset - reset a MAC + * @mac: the MAC to reset + * + * Reset the given MAC. + */ int t3_mac_reset(struct cmac *mac) { static struct addr_val_pair mac_reset_avp[] = { @@ -114,6 +126,7 @@ int t3_mac_reset(struct cmac *mac) 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) { @@ -146,8 +159,10 @@ int t3_mac_reset(struct cmac *mac) t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN); } - - val = F_MAC_RESET_; + 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) || mac->multiport) val |= F_PCS_RESET_; else if (uses_xaui(adap)) @@ -236,7 +251,14 @@ static void set_addr_filter(struct cmac *mac, int idx, const u8 *addr) t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi); } -/* Set one of the station's unicast MAC addresses. */ +/** + * t3_mac_set_address - set one of the station's unicast MAC addresses + * @mac: the MAC handle + * @idx: index of the exact address match filter to use + * @addr: the Ethernet address + * + * Set one of the station's unicast MAC addresses. + */ int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]) { if (mac->multiport) @@ -249,10 +271,14 @@ int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]) return 0; } -/* - * Specify the number of exact address filters that should be reserved for - * unicast addresses. Caller should reload the unicast and multicast addresses - * after calling this. +/** + * t3_mac_set_num_ucast - set the number of unicast addresses needed + * @mac: the MAC handle + * @n: number of unicast addresses needed + * + * Specify the number of exact address filters that should be reserved for + * unicast addresses. Caller should reload the unicast and multicast + * addresses after calling this. */ int t3_mac_set_num_ucast(struct cmac *mac, unsigned char n) { @@ -298,6 +324,14 @@ static int hash_hw_addr(const u8 *addr) return hash; } +/** + * t3_mac_set_rx_mode - set the Rx mode and address filters + * @mac: the MAC to configure + * @rm: structure containing the Rx mode and MAC addresses needed + * + * Configures the MAC Rx mode (promiscuity, etc) and exact and hash + * address filters. + */ int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm) { u32 hash_lo, hash_hi; @@ -344,10 +378,18 @@ static int rx_fifo_hwm(int mtu) return min(hwm, MAC_RXFIFO_SIZE - 8192); } +/** + * t3_mac_set_mtu - set the MAC MTU + * @mac: the MAC to configure + * @mtu: the MTU + * + * Sets the MAC MTU and adjusts the FIFO PAUSE watermarks accordingly. + */ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) { - int hwm, lwm; - unsigned int thres, v; + int hwm, lwm, divisor; + int ipg; + unsigned int thres, v, reg; adapter_t *adap = mac->adapter; /* @@ -362,27 +404,33 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) if (mac->multiport) return t3_vsc7323_set_mtu(adap, mtu - 4, mac->ext_port); - if (adap->params.rev == T3_REV_B2 && + if (adap->params.rev >= T3_REV_B2 && (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { disable_exact_filters(mac); v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset); t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset, F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST); - /* drain rx FIFO */ - if (t3_wait_op_done(adap, - A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + mac->offset, - 1 << 31, 1, 20, 5)) { + reg = adap->params.rev == T3_REV_B2 ? + A_XGM_RX_MAX_PKT_SIZE_ERR_CNT : A_XGM_RXFIFO_CFG; + + /* drain RX FIFO */ + if (t3_wait_op_done(adap, reg + mac->offset, + F_RXFIFO_EMPTY, 1, 20, 5)) { t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); enable_exact_filters(mac); return -EIO; } - t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); + t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, + V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), + V_RXMAXPKTSIZE(mtu)); t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); enable_exact_filters(mac); } else - t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); - + t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, + V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), + V_RXMAXPKTSIZE(mtu)); + /* * Adjust the PAUSE frame watermarks. We always set the LWM, and the * HWM only if flow-control is enabled. @@ -405,20 +453,34 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) thres /= 10; thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; thres = max(thres, 8U); /* need at least 8 */ + ipg = (adap->params.rev == T3_REV_C) ? 0 : 1; t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG), - V_TXFIFOTHRESH(thres) | V_TXIPG(1)); + V_TXFIFOTHRESH(thres) | V_TXIPG(ipg)); /* Assuming a minimum drain rate of 2.5Gbps... */ - if (adap->params.rev > 0) + if (adap->params.rev > 0) { + divisor = (adap->params.rev == T3_REV_C) ? 64 : 8; t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset, - (hwm - lwm) * 4 / 8); + (hwm - lwm) * 4 / divisor); + } t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset, MAC_RXFIFO_SIZE * 4 * 8 / 512); 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; @@ -466,6 +528,15 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) return 0; } +/** + * t3_mac_enable - enable the MAC in the given directions + * @mac: the MAC to configure + * @which: bitmap indicating which directions to enable + * + * Enables the MAC for operation in the given directions. + * %MAC_DIRECTION_TX enables the Tx direction, and %MAC_DIRECTION_RX + * enables the Rx one. + */ int t3_mac_enable(struct cmac *mac, int which) { int idx = macidx(mac); @@ -478,9 +549,13 @@ int t3_mac_enable(struct cmac *mac, int which) if (which & MAC_DIRECTION_TX) { t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); - t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401); + t3_write_reg(adap, A_TP_PIO_DATA, + adap->params.rev == T3_REV_C ? + 0xc4ffff01 : 0xc0ede401); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); - t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); + t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, + adap->params.rev == T3_REV_C ? + 0 : 1 << idx); t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); @@ -505,6 +580,15 @@ int t3_mac_enable(struct cmac *mac, int which) return 0; } +/** + * t3_mac_disable - disable the MAC in the given directions + * @mac: the MAC to configure + * @which: bitmap indicating which directions to disable + * + * Disables the MAC in the given directions. + * %MAC_DIRECTION_TX disables the Tx direction, and %MAC_DIRECTION_RX + * disables the Rx one. + */ int t3_mac_disable(struct cmac *mac, int which) { adapter_t *adap = mac->adapter; @@ -621,12 +705,15 @@ out: return status; } -/* - * This function is called periodically to accumulate the current values of the - * RMON counters into the port statistics. Since the packet counters are only - * 32 bits they can overflow in ~286 secs at 10G, so the function should be - * called more frequently than that. The byte counters are 45-bit wide, they - * would overflow in ~7.8 hours. +/** + * t3_mac_update_stats - accumulate MAC statistics + * @mac: the MAC handle + * + * This function is called periodically to accumulate the current values + * of the RMON counters into the port statistics. Since the packet + * counters are only 32 bits they can overflow in ~286 secs at 10G, so the + * function should be called more frequently than that. The byte counters + * are 45-bit wide, they would overflow in ~7.8 hours. */ const struct mac_stats *t3_mac_update_stats(struct cmac *mac) { |