diff --git a/sys/dev/axgbe/if_axgbe_pci.c b/sys/dev/axgbe/if_axgbe_pci.c index fe42aaac656..2e4f74303a3 100644 --- a/sys/dev/axgbe/if_axgbe_pci.c +++ b/sys/dev/axgbe/if_axgbe_pci.c @@ -59,6 +59,14 @@ __FBSDID("$FreeBSD$"); #include "ifdi_if.h" #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_rss.h" + +#ifdef RSS + +#include +#include + +#endif MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data"); @@ -105,6 +113,7 @@ static bool axgbe_if_needs_restart(if_ctx_t, enum iflib_restart_event); #endif static void axgbe_set_counts(if_ctx_t); static void axgbe_init_iflib_softc_ctx(struct axgbe_if_softc *); +static void axgbe_initialize_rss_mapping(struct xgbe_prv_data *); /* MII interface registered functions */ static int axgbe_miibus_readreg(device_t, int, int); @@ -280,11 +289,11 @@ axgbe_register(device_t dev) * No tunable found, generate one with default values * Note: only a reboot will reveal the new kenv */ - error = kern_setenv("dev.ax.sph_enable", "1"); + error = kern_setenv("dev.ax.sph_enable", "0"); if (error) { printf("Error setting tunable, using default driver values\n"); } - axgbe_sph_enable = 1; + axgbe_sph_enable = 0; } if (!axgbe_sph_enable) { @@ -392,6 +401,7 @@ axgbe_if_attach_pre(if_ctx_t ctx) if_softc_ctx_t scctx; if_shared_ctx_t sctx; device_t dev; + device_t rdev; unsigned int ma_lo, ma_hi; unsigned int reg; @@ -430,8 +440,15 @@ axgbe_if_attach_pre(if_ctx_t ctx) sc->pdata.xpcs_res = mac_res[1]; /* Set the PCS indirect addressing definition registers*/ - pdata->xpcs_window_def_reg = PCS_V2_WINDOW_DEF; - pdata->xpcs_window_sel_reg = PCS_V2_WINDOW_SELECT; + rdev = pci_find_dbsf(0, 0, 0, 0); + if (rdev && pci_get_device(rdev) == 0x15d0 + && pci_get_vendor(rdev) == 0x1022) { + pdata->xpcs_window_def_reg = PCS_V2_RV_WINDOW_DEF; + pdata->xpcs_window_sel_reg = PCS_V2_RV_WINDOW_SELECT; + } else { + pdata->xpcs_window_def_reg = PCS_V2_WINDOW_DEF; + pdata->xpcs_window_sel_reg = PCS_V2_WINDOW_SELECT; + } /* Configure the PCS indirect addressing support */ reg = XPCS32_IOREAD(pdata, pdata->xpcs_window_def_reg); @@ -687,6 +704,47 @@ axgbe_init_iflib_softc_ctx(struct axgbe_if_softc *sc) scctx->isc_txrx = &axgbe_txrx; } +static void +axgbe_initialize_rss_mapping(struct xgbe_prv_data *pdata) +{ + int i; + + /* Get RSS key */ +#ifdef RSS + int qid; + uint32_t rss_hash_config = 0; + + rss_getkey((uint8_t *)&pdata->rss_key); + + rss_hash_config = rss_gethashconfig(); + + if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1); + if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1); + if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); +#else + arc4rand(&pdata->rss_key, ARRAY_SIZE(pdata->rss_key), 0); + + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1); + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1); + XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); +#endif + + /* Setup RSS lookup table */ + for (i = 0; i < XGBE_RSS_MAX_TABLE_SIZE; i++) { +#ifdef RSS + qid = rss_get_indirection_to_bucket(i) % pdata->rx_ring_count; + XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, qid); +#else + XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, + i % pdata->rx_ring_count); +#endif + } + +} + static int axgbe_alloc_channels(if_ctx_t ctx) { @@ -1297,11 +1355,8 @@ xgbe_default_config(struct xgbe_prv_data *pdata) pdata->rx_sf_mode = MTL_RSF_DISABLE; pdata->rx_threshold = MTL_RX_THRESHOLD_64; pdata->pause_autoneg = 1; - pdata->tx_pause = 1; - pdata->rx_pause = 1; pdata->phy_speed = SPEED_UNKNOWN; pdata->power_down = 0; - pdata->enable_rss = 1; } static void @@ -1325,7 +1380,7 @@ axgbe_if_attach_post(if_ctx_t ctx) struct xgbe_phy_if *phy_if = &pdata->phy_if; struct xgbe_hw_if *hw_if = &pdata->hw_if; if_softc_ctx_t scctx = sc->scctx; - int i, ret; + int ret; /* set split header support based on tunable */ pdata->sph_enable = axgbe_sph_enable; @@ -1343,6 +1398,10 @@ axgbe_if_attach_post(if_ctx_t ctx) if (ret) axgbe_error("%s: exit error %d\n", __func__, ret); + axgbe_setup_sysctl(pdata); + + axgbe_sysctl_init(pdata); + /* Configure the defaults */ xgbe_default_config(pdata); @@ -1378,15 +1437,7 @@ axgbe_if_attach_post(if_ctx_t ctx) scctx->isc_nrxqsets); DBGPR("Channel count set to: %u\n", pdata->channel_count); - /* Get RSS key */ -#ifdef RSS - rss_getkey((uint8_t *)pdata->rss_key); -#else - arc4rand(&pdata->rss_key, ARRAY_SIZE(pdata->rss_key), 0); -#endif - XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, IP2TE, 1); - XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1); - XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); + axgbe_initialize_rss_mapping(pdata); /* Initialize the PHY device */ pdata->sysctl_an_cdr_workaround = pdata->vdata->an_cdr_workaround; @@ -1422,11 +1473,6 @@ axgbe_if_attach_post(if_ctx_t ctx) pdata->rx_buf_size = ret; DBGPR("%s: rx_buf_size %d\n", __func__, ret); - /* Setup RSS lookup table */ - for (i = 0; i < XGBE_RSS_MAX_TABLE_SIZE; i++) - XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, - i % pdata->rx_ring_count); - /* * Mark the device down until it is initialized, which happens * when the device is accessed first (for configuring the iface, @@ -1438,10 +1484,6 @@ axgbe_if_attach_post(if_ctx_t ctx) scctx->isc_max_frame_size = ifp->if_mtu + 18; scctx->isc_min_frame_size = XGMAC_MIN_PACKET; - axgbe_setup_sysctl(pdata); - - axgbe_sysctl_init(pdata); - axgbe_pci_init(pdata); return (0); diff --git a/sys/dev/axgbe/xgbe-common.h b/sys/dev/axgbe/xgbe-common.h index dc13310dd4a..2c2dc0287f4 100644 --- a/sys/dev/axgbe/xgbe-common.h +++ b/sys/dev/axgbe/xgbe-common.h @@ -481,6 +481,8 @@ #define MAC_PFR_VTFE_WIDTH 1 #define MAC_PFR_VUCC_INDEX 22 #define MAC_PFR_VUCC_WIDTH 1 +#define MAC_PFR_RA_INDEX 31 +#define MAC_PFR_RA_WIDTH 1 #define MAC_PMTCSR_MGKPKTEN_INDEX 1 #define MAC_PMTCSR_MGKPKTEN_WIDTH 1 #define MAC_PMTCSR_PWRDWN_INDEX 0 diff --git a/sys/dev/axgbe/xgbe-dev.c b/sys/dev/axgbe/xgbe-dev.c index 95161802ed8..08b7681afc2 100644 --- a/sys/dev/axgbe/xgbe-dev.c +++ b/sys/dev/axgbe/xgbe-dev.c @@ -1453,7 +1453,8 @@ xgbe_dev_read(struct xgbe_channel *channel) if (!err || !etlt) { /* No error if err is 0 or etlt is 0 */ - if (etlt == 0x09) { + if (etlt == 0x09 && + (if_getcapenable(pdata->netdev) & IFCAP_VLAN_HWTAGGING)) { XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, VLAN_CTAG, 1); packet->vlan_ctag = XGMAC_GET_BITS_LE(rdesc->desc0, @@ -2031,6 +2032,13 @@ xgbe_config_mac_address(struct xgbe_prv_data *pdata) { xgbe_set_mac_address(pdata, IF_LLADDR(pdata->netdev)); + /* + * Promisc mode does not work as intended. When receiving CARP + * packets, the filter still seems to kick in. As a workaround, + * enable the "Receive All" mode on the card during init. + */ + XGMAC_IOWRITE_BITS(pdata, MAC_PFR, RA, 1); + /* Filtering is done using perfect filtering and hash filtering */ if (pdata->hw_feat.hash_table_size) { XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HPF, 1); diff --git a/sys/dev/axgbe/xgbe-phy-v2.c b/sys/dev/axgbe/xgbe-phy-v2.c index df8a75a145b..72ea89eac46 100644 --- a/sys/dev/axgbe/xgbe-phy-v2.c +++ b/sys/dev/axgbe/xgbe-phy-v2.c @@ -192,6 +192,7 @@ enum xgbe_sfp_base { XGBE_SFP_BASE_1000_SX, XGBE_SFP_BASE_1000_LX, XGBE_SFP_BASE_1000_CX, + XGBE_SFP_BASE_1000_BX, XGBE_SFP_BASE_10000_SR, XGBE_SFP_BASE_10000_LR, XGBE_SFP_BASE_10000_LRM, @@ -238,6 +239,14 @@ enum xgbe_sfp_speed { #define XGBE_SFP_BASE_BR_10GBE_MIN 0x64 #define XGBE_SFP_BASE_BR_10GBE_MAX 0x68 +/* Single mode, length of fiber in units of km */ +#define XGBE_SFP_BASE_SM_LEN_KM 14 +#define XGBE_SFP_BASE_SM_LEN_KM_MIN 0x0A + +/* Single mode, length of fiber in units of 100m */ +#define XGBE_SFP_BASE_SM_LEN_100M 15 +#define XGBE_SFP_BASE_SM_LEN_100M_MIN 0x64 + #define XGBE_SFP_BASE_CU_CABLE_LEN 18 #define XGBE_SFP_BASE_VENDOR_NAME 20 @@ -247,6 +256,16 @@ enum xgbe_sfp_speed { #define XGBE_SFP_BASE_VENDOR_REV 56 #define XGBE_SFP_BASE_VENDOR_REV_LEN 4 +/* + * Optical specification compliance - denotes wavelength + * for optical tranceivers + */ +#define XGBE_SFP_BASE_OSC 60 +#define XGBE_SFP_BASE_OSC_LEN 2 +#define XGBE_SFP_BASE_OSC_1310 0x051E +#define XGBE_SFP_BASE_OSC_1439 0x05D2 +#define XGBE_SFP_BASE_OSC_1550 0x060E + #define XGBE_SFP_BASE_CC 63 /* SFP Serial ID Extended ID values relative to an offset of 64 */ @@ -779,6 +798,13 @@ xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) XGBE_SET_SUP(&pdata->phy, 1000baseX_Full); } break; + case XGBE_SFP_BASE_1000_BX: + pdata->phy.speed = SPEED_1000; + pdata->phy.duplex = DUPLEX_FULL; + pdata->phy.autoneg = AUTONEG_DISABLE; + pdata->phy.pause_autoneg = AUTONEG_DISABLE; + XGBE_SET_SUP(&pdata->phy, 1000baseBX_Full); + break; case XGBE_SFP_BASE_10000_SR: case XGBE_SFP_BASE_10000_LR: case XGBE_SFP_BASE_10000_LRM: @@ -1189,6 +1215,7 @@ xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) struct xgbe_phy_data *phy_data = pdata->phy_data; struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; uint8_t *sfp_base; + uint16_t wavelen = 0; sfp_base = sfp_eeprom->base; @@ -1213,6 +1240,8 @@ xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) } else phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE; + wavelen = (sfp_base[XGBE_SFP_BASE_OSC] << 8) | sfp_base[XGBE_SFP_BASE_OSC + 1]; + /* * Determine the type of SFP. Certain 10G SFP+ modules read as * 1000BASE-CX. To prevent 10G DAC cables to be recognized as @@ -1238,7 +1267,12 @@ xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) phy_data->sfp_base = XGBE_SFP_BASE_1000_CX; else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_T) phy_data->sfp_base = XGBE_SFP_BASE_1000_T; - + else if (xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_1000) + && (sfp_base[XGBE_SFP_BASE_SM_LEN_KM] >= XGBE_SFP_BASE_SM_LEN_KM_MIN + || sfp_base[XGBE_SFP_BASE_SM_LEN_100M] >= XGBE_SFP_BASE_SM_LEN_100M_MIN) + && wavelen >= XGBE_SFP_BASE_OSC_1310) + phy_data->sfp_base = XGBE_SFP_BASE_1000_BX; + switch (phy_data->sfp_base) { case XGBE_SFP_BASE_1000_T: phy_data->sfp_speed = XGBE_SFP_SPEED_100_1000; @@ -1246,6 +1280,7 @@ xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) case XGBE_SFP_BASE_1000_SX: case XGBE_SFP_BASE_1000_LX: case XGBE_SFP_BASE_1000_CX: + case XGBE_SFP_BASE_1000_BX: phy_data->sfp_speed = XGBE_SFP_SPEED_1000; break; case XGBE_SFP_BASE_10000_SR: @@ -1271,29 +1306,29 @@ xgbe_phy_sfp_eeprom_info(struct xgbe_prv_data *pdata, struct xgbe_sfp_ascii sfp_ascii; char *sfp_data = (char *)&sfp_ascii; - axgbe_printf(3, "SFP detected:\n"); + axgbe_printf(0, "SFP detected:\n"); memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME], XGBE_SFP_BASE_VENDOR_NAME_LEN); sfp_data[XGBE_SFP_BASE_VENDOR_NAME_LEN] = '\0'; - axgbe_printf(3, " vendor: %s\n", + axgbe_printf(0, " vendor: %s\n", sfp_data); memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN], XGBE_SFP_BASE_VENDOR_PN_LEN); sfp_data[XGBE_SFP_BASE_VENDOR_PN_LEN] = '\0'; - axgbe_printf(3, " part number: %s\n", + axgbe_printf(0, " part number: %s\n", sfp_data); memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_REV], XGBE_SFP_BASE_VENDOR_REV_LEN); sfp_data[XGBE_SFP_BASE_VENDOR_REV_LEN] = '\0'; - axgbe_printf(3, " revision level: %s\n", + axgbe_printf(0, " revision level: %s\n", sfp_data); memcpy(sfp_data, &sfp_eeprom->extd[XGBE_SFP_BASE_VENDOR_SN], XGBE_SFP_BASE_VENDOR_SN_LEN); sfp_data[XGBE_SFP_BASE_VENDOR_SN_LEN] = '\0'; - axgbe_printf(3, " serial number: %s\n", + axgbe_printf(0, " serial number: %s\n", sfp_data); } @@ -1392,13 +1427,19 @@ xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata) axgbe_printf(3, "%s: befor sfp_mod:%d sfp_gpio_address:0x%x\n", __func__, phy_data->sfp_mod_absent, phy_data->sfp_gpio_address); + ret = xgbe_phy_sfp_get_mux(pdata); + if (ret) { + axgbe_error("I2C error setting SFP MUX\n"); + return; + } + gpio_reg = 0; ret = xgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address, &gpio_reg, sizeof(gpio_reg), gpio_ports, sizeof(gpio_ports)); if (ret) { axgbe_error("%s: I2C error reading SFP GPIO addr:0x%x\n", __func__, phy_data->sfp_gpio_address); - return; + goto put_mux; } phy_data->sfp_gpio_inputs = (gpio_ports[1] << 8) | gpio_ports[0]; @@ -1412,6 +1453,9 @@ xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata) axgbe_printf(3, "%s: after sfp_mod:%d sfp_gpio_inputs:0x%x\n", __func__, phy_data->sfp_mod_absent, phy_data->sfp_gpio_inputs); + +put_mux: + xgbe_phy_sfp_put_mux(pdata); } static void @@ -1443,9 +1487,6 @@ xgbe_phy_sfp_detect(struct xgbe_prv_data *pdata) struct xgbe_phy_data *phy_data = pdata->phy_data; int ret, prev_sfp_state = phy_data->sfp_mod_absent; - /* Reset the SFP signals and info */ - xgbe_phy_sfp_reset(phy_data); - ret = xgbe_phy_get_comm_ownership(pdata); if (ret) return; diff --git a/sys/dev/axgbe/xgbe-sysctl.c b/sys/dev/axgbe/xgbe-sysctl.c index f7998b943b1..0b78d599750 100644 --- a/sys/dev/axgbe/xgbe-sysctl.c +++ b/sys/dev/axgbe/xgbe-sysctl.c @@ -1610,6 +1610,8 @@ axgbe_sysctl_init(struct xgbe_prv_data *pdata) pdata->sysctl_xgmac_reg = 0; pdata->sysctl_xpcs_mmd = 1; pdata->sysctl_xpcs_reg = 0; + pdata->link_workaround = 1; + pdata->enable_rss = 1; SYSCTL_ADD_UINT(clist, top, OID_AUTO, "axgbe_debug_level", CTLFLAG_RWTUN, &pdata->debug_level, 0, "axgbe log level -- higher is verbose"); @@ -1621,6 +1623,18 @@ axgbe_sysctl_init(struct xgbe_prv_data *pdata) SYSCTL_ADD_UINT(clist, top, OID_AUTO, "link_workaround", CTLFLAG_RWTUN, &pdata->link_workaround, 0, "enable the workaround for link issue in coming up"); + + SYSCTL_ADD_UINT(clist, top, OID_AUTO, "rss_enabled", + CTLFLAG_RDTUN, &pdata->enable_rss, 1, + "shows the RSS feature state (1 - enable, 0 - disable)"); + + SYSCTL_ADD_UINT(clist, top, OID_AUTO, "tx_pause", + CTLFLAG_RDTUN, &pdata->tx_pause, 1, + "shows the Flow Control TX pause feature state (1 - enable, 0 - disable)"); + + SYSCTL_ADD_UINT(clist, top, OID_AUTO, "rx_pause", + CTLFLAG_RDTUN, &pdata->rx_pause, 1, + "shows the Flow Control RX pause feature state (1 - enable, 0 - disable)"); SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xgmac_register", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, diff --git a/sys/dev/axgbe/xgbe-txrx.c b/sys/dev/axgbe/xgbe-txrx.c index e798bfa3733..508fb2275e3 100644 --- a/sys/dev/axgbe/xgbe-txrx.c +++ b/sys/dev/axgbe/xgbe-txrx.c @@ -704,7 +704,7 @@ axgbe_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri) struct xgbe_packet_data *packet = &ring->packet_data; struct xgbe_ring_data *rdata; unsigned int last, context_next, context; - unsigned int buf1_len, buf2_len, max_len, len = 0, prev_cur; + unsigned int buf1_len, buf2_len, len = 0, prev_cur; int i = 0; axgbe_printf(2, "%s: rxq %d cidx %d cur %d dirty %d\n", __func__, @@ -769,11 +769,9 @@ read_again: axgbe_printf(2, "%s: csum flags 0x%x\n", __func__, ri->iri_csum_flags); } - max_len = if_getmtu(pdata->netdev) + ETH_HLEN; if (XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, VLAN_CTAG)) { ri->iri_flags |= M_VLANTAG; ri->iri_vtag = packet->vlan_ctag; - max_len += VLAN_HLEN; axgbe_printf(2, "%s: iri_flags 0x%x vtag 0x%x\n", __func__, ri->iri_flags, ri->iri_vtag); } @@ -790,9 +788,6 @@ read_again: if (__predict_false(len == 0)) axgbe_printf(1, "%s: Discarding Zero len packet\n", __func__); - if (__predict_false(len > max_len)) - axgbe_error("%s: Big packet %d/%d\n", __func__, len, max_len); - if (__predict_false(packet->errors)) axgbe_printf(1, "<-- %s: rxq: %d len: %d frags: %d cidx %d cur: %d " "dirty: %d error 0x%x\n", __func__, ri->iri_qsidx, len, i, diff --git a/sys/dev/axgbe/xgbe_osdep.h b/sys/dev/axgbe/xgbe_osdep.h index b9863bbd756..c85eb7b7043 100644 --- a/sys/dev/axgbe/xgbe_osdep.h +++ b/sys/dev/axgbe/xgbe_osdep.h @@ -128,6 +128,7 @@ do { \ #define SUPPORTED_10000baseCR_Full (1 << 19) #define SUPPORTED_100baseT_Half (1 << 20) #define SUPPORTED_1000baseT_Half (1 << 21) +#define SUPPORTED_1000baseBX_Full (1 << 22) #define LPA_PAUSE_ASYM 0x0800