diff --git a/sys/dev/axgbe/if_axgbe_pci.c b/sys/dev/axgbe/if_axgbe_pci.c --- a/sys/dev/axgbe/if_axgbe_pci.c +++ b/sys/dev/axgbe/if_axgbe_pci.c @@ -57,6 +57,14 @@ #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"); @@ -104,6 +112,7 @@ #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); @@ -278,11 +287,11 @@ * 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) { @@ -390,6 +399,7 @@ 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; int ret; @@ -432,8 +442,15 @@ 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); @@ -715,6 +732,47 @@ 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) { @@ -1337,11 +1395,9 @@ pdata->tx_sf_mode = MTL_TSF_ENABLE; pdata->tx_threshold = MTL_TX_THRESHOLD_64; pdata->tx_osp_mode = DMA_OSP_ENABLE; - pdata->rx_sf_mode = MTL_RSF_DISABLE; + pdata->rx_sf_mode = MTL_RSF_ENABLE; 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; @@ -1356,7 +1412,7 @@ 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; @@ -1374,6 +1430,8 @@ if (ret) axgbe_error("%s: exit error %d\n", __func__, ret); + axgbe_sysctl_init(pdata); + /* Configure the defaults */ xgbe_default_config(pdata); @@ -1409,15 +1467,7 @@ 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; @@ -1453,11 +1503,6 @@ 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, @@ -1469,8 +1514,6 @@ scctx->isc_max_frame_size = if_getmtu(ifp) + 18; scctx->isc_min_frame_size = XGMAC_MIN_PACKET; - axgbe_sysctl_init(pdata); - axgbe_pci_init(pdata); return (0); @@ -1535,6 +1578,7 @@ mac_res[0] = pdata->xgmac_res; mac_res[1] = pdata->xpcs_res; + phy_if->phy_stop(pdata); phy_if->phy_exit(pdata); /* Free Interrupts */ @@ -1606,7 +1650,6 @@ { struct axgbe_if_softc *sc = iflib_get_softc(ctx); struct xgbe_prv_data *pdata = &sc->pdata; - struct xgbe_phy_if *phy_if = &pdata->phy_if; struct xgbe_hw_if *hw_if = &pdata->hw_if; int ret; @@ -1621,8 +1664,6 @@ hw_if->disable_tx(pdata); hw_if->disable_rx(pdata); - phy_if->phy_stop(pdata); - ret = hw_if->exit(pdata); if (ret) axgbe_error("%s: exit error %d\n", __func__, ret); diff --git a/sys/dev/axgbe/xgbe-common.h b/sys/dev/axgbe/xgbe-common.h --- a/sys/dev/axgbe/xgbe-common.h +++ b/sys/dev/axgbe/xgbe-common.h @@ -479,6 +479,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 @@ -1319,10 +1321,18 @@ #define MDIO_PMA_10GBR_FECCTRL 0x00ab #endif +#ifndef MDIO_PMA_RX_CTRL1 +#define MDIO_PMA_RX_CTRL1 0x8051 +#endif + #ifndef MDIO_PCS_DIG_CTRL #define MDIO_PCS_DIG_CTRL 0x8000 #endif +#ifndef MDIO_PCS_DIGITAL_STAT +#define MDIO_PCS_DIGITAL_STAT 0x8010 +#endif + #ifndef MDIO_AN_XNP #define MDIO_AN_XNP 0x0016 #endif @@ -1363,6 +1373,10 @@ #define MDIO_VEND2_PMA_CDR_CONTROL 0x8056 #endif +#ifndef MDIO_VEND2_PMA_MISC_CTRL0 +#define MDIO_VEND2_PMA_MISC_CTRL0 0x8090 +#endif + #ifndef MDIO_CTRL1_SPEED1G #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) #endif @@ -1398,6 +1412,8 @@ #define XGBE_KR_TRAINING_ENABLE BIT(1) #define XGBE_PCS_CL37_BP BIT(12) +#define XGBE_PCS_PSEQ_STATE_MASK 0x1c +#define XGBE_PCS_PSEQ_STATE_POWER_GOOD 0x10 #define XGBE_AN_CL37_INT_CMPLT BIT(0) #define XGBE_AN_CL37_INT_MASK 0x01 @@ -1415,6 +1431,14 @@ #define XGBE_PMA_CDR_TRACK_EN_OFF 0x00 #define XGBE_PMA_CDR_TRACK_EN_ON 0x01 +#define XGBE_PMA_RX_RST_0_MASK BIT(4) +#define XGBE_PMA_RX_RST_0_RESET_ON 0x10 +#define XGBE_PMA_RX_RST_0_RESET_OFF 0x00 + +#define XGBE_PMA_PLL_CTRL_MASK BIT(15) +#define XGBE_PMA_PLL_CTRL_ENABLE BIT(15) +#define XGBE_PMA_PLL_CTRL_DISABLE 0x0000 + /* Bit setting and getting macros * The get macro will extract the current bit field value from within * the variable diff --git a/sys/dev/axgbe/xgbe-dev.c b/sys/dev/axgbe/xgbe-dev.c --- a/sys/dev/axgbe/xgbe-dev.c +++ b/sys/dev/axgbe/xgbe-dev.c @@ -1451,7 +1451,8 @@ 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, @@ -2029,6 +2030,12 @@ { xgbe_set_mac_address(pdata, if_getlladdr(pdata->netdev)); + /* + * Promisc mode does not work as intended. Multicast traffic + * is triggering the filter, so enable Receive All. + */ + 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-i2c.c b/sys/dev/axgbe/xgbe-i2c.c --- a/sys/dev/axgbe/xgbe-i2c.c +++ b/sys/dev/axgbe/xgbe-i2c.c @@ -327,8 +327,6 @@ if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET)) pdata->i2c_complete = true; - return; - reissue_check: /* Reissue interrupt if status is not clear */ if (pdata->vdata->irq_reissue_support) @@ -442,7 +440,7 @@ ret, state->tx_abort_source); if (ret) { - axgbe_error("%s: i2c xfer ret %d abrt_source 0x%x \n", __func__, + axgbe_printf(1, "%s: i2c xfer ret %d abrt_source 0x%x \n", __func__, ret, state->tx_abort_source); if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK) ret = -ENOTCONN; diff --git a/sys/dev/axgbe/xgbe-mdio.c b/sys/dev/axgbe/xgbe-mdio.c --- a/sys/dev/axgbe/xgbe-mdio.c +++ b/sys/dev/axgbe/xgbe-mdio.c @@ -734,11 +734,6 @@ if (pdata->an_int & XGBE_AN_CL37_INT_CMPLT) { pdata->an_state = XGBE_AN_COMPLETE; pdata->an_int &= ~XGBE_AN_CL37_INT_CMPLT; - - /* If SGMII is enabled, check the link status */ - if ((pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) && - !(pdata->an_status & XGBE_SGMII_AN_LINK_STATUS)) - pdata->an_state = XGBE_AN_NO_LINK; } axgbe_printf(2, "%s: CL37 AN %s\n", __func__, @@ -1364,6 +1359,7 @@ if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) { axgbe_error("%s: LINK_ERR\n", __func__); pdata->phy.link = 0; + clear_bit(XGBE_LINK_ERR, &pdata->dev_state); goto adjust_link; } @@ -1443,7 +1439,10 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata) { - int ret; + int ret = 0; + + if (pdata->phy_started) + return (ret); DBGPR("-->xgbe_phy_start\n"); @@ -1588,6 +1587,7 @@ pdata->phy.duplex = DUPLEX_FULL; } + pdata->phy_started = 0; pdata->phy.link = 0; pdata->phy.pause_autoneg = pdata->pause_autoneg; diff --git a/sys/dev/axgbe/xgbe-phy-v2.c b/sys/dev/axgbe/xgbe-phy-v2.c --- a/sys/dev/axgbe/xgbe-phy-v2.c +++ b/sys/dev/axgbe/xgbe-phy-v2.c @@ -150,6 +150,9 @@ /* RRC frequency during link status check */ #define XGBE_RRC_FREQUENCY 10 +/* SFP port max PHY probe retries */ +#define XGBE_SFP_PHY_RETRY_MAX 5 + enum xgbe_port_mode { XGBE_PORT_MODE_RSVD = 0, XGBE_PORT_MODE_BACKPLANE, @@ -186,10 +189,16 @@ enum xgbe_sfp_base { XGBE_SFP_BASE_UNKNOWN = 0, + XGBE_SFP_BASE_PX, + XGBE_SFP_BASE_BX10, + XGBE_SFP_BASE_100_FX, + XGBE_SFP_BASE_100_LX10, + XGBE_SFP_BASE_100_BX, XGBE_SFP_BASE_1000_T, 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, @@ -199,9 +208,11 @@ enum xgbe_sfp_speed { XGBE_SFP_SPEED_UNKNOWN = 0, + XGBE_SFP_SPEED_100, XGBE_SFP_SPEED_100_1000, XGBE_SFP_SPEED_1000, XGBE_SFP_SPEED_10000, + XGBE_SFP_SPEED_25000, }; /* SFP Serial ID Base ID values relative to an offset of 0 */ @@ -225,16 +236,31 @@ #define XGBE_SFP_BASE_1GBE_CC_LX BIT(1) #define XGBE_SFP_BASE_1GBE_CC_CX BIT(2) #define XGBE_SFP_BASE_1GBE_CC_T BIT(3) +#define XGBE_SFP_BASE_100M_CC_LX10 BIT(4) +#define XGBE_SFP_BASE_100M_CC_FX BIT(5) +#define XGBE_SFP_BASE_CC_BX10 BIT(6) +#define XGBE_SFP_BASE_CC_PX BIT(7) #define XGBE_SFP_BASE_CABLE 8 #define XGBE_SFP_BASE_CABLE_PASSIVE BIT(2) #define XGBE_SFP_BASE_CABLE_ACTIVE BIT(3) #define XGBE_SFP_BASE_BR 12 +#define XGBE_SFP_BASE_BR_100M_MIN 0x1 +#define XGBE_SFP_BASE_BR_100M_MAX 0x2 #define XGBE_SFP_BASE_BR_1GBE_MIN 0x0a #define XGBE_SFP_BASE_BR_1GBE_MAX 0x0d #define XGBE_SFP_BASE_BR_10GBE_MIN 0x64 #define XGBE_SFP_BASE_BR_10GBE_MAX 0x68 +#define XGBE_SFP_BASE_BR_25GBE 0xFF + +/* 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 @@ -245,6 +271,16 @@ #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 */ @@ -342,6 +378,9 @@ unsigned int sfp_gpio_address; unsigned int sfp_gpio_mask; unsigned int sfp_gpio_inputs; + unsigned int sfp_gpio_outputs; + unsigned int sfp_gpio_polarity; + unsigned int sfp_gpio_configuration; unsigned int sfp_gpio_rx_los; unsigned int sfp_gpio_tx_fault; unsigned int sfp_gpio_mod_absent; @@ -365,6 +404,7 @@ enum xgbe_mdio_reset mdio_reset; unsigned int mdio_reset_addr; unsigned int mdio_reset_gpio; + int sfp_phy_retries; /* Re-driver support */ unsigned int redrv; @@ -382,6 +422,8 @@ static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata); static int xgbe_phy_reset(struct xgbe_prv_data *pdata); +static int axgbe_ifmedia_upd(struct ifnet *ifp); +static void axgbe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); static int xgbe_phy_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *i2c_op) @@ -756,6 +798,14 @@ } switch (phy_data->sfp_base) { + case XGBE_SFP_BASE_100_FX: + case XGBE_SFP_BASE_100_LX10: + case XGBE_SFP_BASE_100_BX: + pdata->phy.speed = SPEED_100; + pdata->phy.duplex = DUPLEX_FULL; + pdata->phy.autoneg = AUTONEG_DISABLE; + pdata->phy.pause_autoneg = AUTONEG_DISABLE; + break; case XGBE_SFP_BASE_1000_T: case XGBE_SFP_BASE_1000_SX: case XGBE_SFP_BASE_1000_LX: @@ -777,6 +827,13 @@ XGBE_SET_SUP(&pdata->phy, 1000baseX_Full); } break; + case XGBE_SFP_BASE_1000_BX: + case XGBE_SFP_BASE_PX: + pdata->phy.speed = SPEED_1000; + pdata->phy.duplex = DUPLEX_FULL; + pdata->phy.autoneg = AUTONEG_DISABLE; + pdata->phy.pause_autoneg = AUTONEG_DISABLE; + break; case XGBE_SFP_BASE_10000_SR: case XGBE_SFP_BASE_10000_LR: case XGBE_SFP_BASE_10000_LRM: @@ -844,6 +901,10 @@ sfp_base = sfp_eeprom->base; switch (sfp_speed) { + case XGBE_SFP_SPEED_100: + min = XGBE_SFP_BASE_BR_100M_MIN; + max = XGBE_SFP_BASE_BR_100M_MAX; + break; case XGBE_SFP_SPEED_1000: min = XGBE_SFP_BASE_BR_1GBE_MIN; max = XGBE_SFP_BASE_BR_1GBE_MAX; @@ -852,6 +913,10 @@ min = XGBE_SFP_BASE_BR_10GBE_MIN; max = XGBE_SFP_BASE_BR_10GBE_MAX; break; + case XGBE_SFP_SPEED_25000: + min = XGBE_SFP_BASE_BR_25GBE; + max = XGBE_SFP_BASE_BR_25GBE; + break; default: return (false); } @@ -867,6 +932,11 @@ if (phy_data->phydev) phy_data->phydev = 0; + + if (pdata->axgbe_miibus != NULL) { + device_delete_child(pdata->dev, pdata->axgbe_miibus); + pdata->axgbe_miibus = NULL; + } } static bool @@ -1009,49 +1079,6 @@ return (0); } -static int -xgbe_phy_start_aneg(struct xgbe_prv_data *pdata) -{ - uint16_t ctl = 0; - int changed = 0; - int ret; - - if (AUTONEG_ENABLE != pdata->phy.autoneg) { - if (SPEED_1000 == pdata->phy.speed) - ctl |= BMCR_SPEED1; - else if (SPEED_100 == pdata->phy.speed) - ctl |= BMCR_SPEED100; - - if (DUPLEX_FULL == pdata->phy.duplex) - ctl |= BMCR_FDX; - - ret = xgbe_phy_mii_read(pdata, pdata->mdio_addr, MII_BMCR); - if (ret) - return (ret); - - ret = xgbe_phy_mii_write(pdata, pdata->mdio_addr, MII_BMCR, - (ret & ~(~(BMCR_LOOP | BMCR_ISO | BMCR_PDOWN))) | ctl); - } - - ctl = xgbe_phy_mii_read(pdata, pdata->mdio_addr, MII_BMCR); - if (ctl < 0) - return (ctl); - - if (!(ctl & BMCR_AUTOEN) || (ctl & BMCR_ISO)) - changed = 1; - - if (changed > 0) { - ret = xgbe_phy_mii_read(pdata, pdata->mdio_addr, MII_BMCR); - if (ret) - return (ret); - - ret = xgbe_phy_mii_write(pdata, pdata->mdio_addr, MII_BMCR, - (ret & ~(BMCR_ISO)) | (BMCR_AUTOEN | BMCR_STARTNEG)); - } - - return (0); -} - static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata) { @@ -1102,7 +1129,6 @@ phy_data->phydev = 1; xgbe_phy_external_phy_quirks(pdata); - xgbe_phy_start_aneg(pdata); return (0); } @@ -1115,7 +1141,8 @@ axgbe_printf(3, "%s: sfp_changed: 0x%x\n", __func__, phy_data->sfp_changed); - if (!phy_data->sfp_changed) + + if (!phy_data->sfp_phy_retries && !phy_data->sfp_changed) return; phy_data->sfp_phy_avail = 0; @@ -1126,13 +1153,28 @@ /* Check access to the PHY by reading CTRL1 */ ret = xgbe_phy_i2c_mii_read(pdata, MII_BMCR); if (ret < 0) { - axgbe_error("%s: ext phy fail %d\n", __func__, ret); + phy_data->sfp_phy_retries++; + if (phy_data->sfp_phy_retries == XGBE_SFP_PHY_RETRY_MAX) + phy_data->sfp_phy_retries = 0; + else + axgbe_printf(1, "%s: ext phy fail %d. retry %d\n", + __func__, ret, phy_data->sfp_phy_retries); return; } /* Successfully accessed the PHY */ phy_data->sfp_phy_avail = 1; axgbe_printf(3, "Successfully accessed External PHY\n"); + + /* Attach external PHY to the miibus */ + ret = mii_attach(pdata->dev, &pdata->axgbe_miibus, pdata->netdev, + (ifm_change_cb_t)axgbe_ifmedia_upd, + (ifm_stat_cb_t)axgbe_ifmedia_sts, BMSR_DEFCAPMASK, + pdata->mdio_addr, MII_OFFSET_ANY, MIIF_FORCEANEG); + + if (ret) { + axgbe_error("mii attach failed with err=(%d)\n", ret); + } } static bool @@ -1187,6 +1229,7 @@ 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; @@ -1211,14 +1254,19 @@ } 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 * 1G, we first check if it is a DAC and the bitrate is 10G. + * If it's greater than 10G, we assume the DAC is capable + * of multiple bitrates, set the MAC to 10G. */ if (((sfp_base[XGBE_SFP_BASE_CV] & XGBE_SFP_BASE_CV_CP) || - (phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE)) && - xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000)) + (phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE)) && + (xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000) || + xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_25000))) phy_data->sfp_base = XGBE_SFP_BASE_10000_CR; else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR) phy_data->sfp_base = XGBE_SFP_BASE_10000_SR; @@ -1236,14 +1284,45 @@ 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 (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_100M_CC_LX10) + phy_data->sfp_base = XGBE_SFP_BASE_100_LX10; + else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_100M_CC_FX) + phy_data->sfp_base = XGBE_SFP_BASE_100_FX; + else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_CC_BX10) { + /* BX10 can be either 100 or 1000 */ + if (xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_100)) { + phy_data->sfp_base = XGBE_SFP_BASE_100_BX; + } else { + /* default to 1000 */ + phy_data->sfp_base = XGBE_SFP_BASE_1000_BX; + } + } + else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_CC_PX) + phy_data->sfp_base = XGBE_SFP_BASE_PX; + 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; + else if (xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_100) + && (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_100_BX; switch (phy_data->sfp_base) { + case XGBE_SFP_BASE_100_FX: + case XGBE_SFP_BASE_100_LX10: + case XGBE_SFP_BASE_100_BX: + phy_data->sfp_speed = XGBE_SFP_SPEED_100; case XGBE_SFP_BASE_1000_T: phy_data->sfp_speed = XGBE_SFP_SPEED_100_1000; break; + case XGBE_SFP_BASE_PX: 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: @@ -1269,29 +1348,29 @@ 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); } @@ -1337,14 +1416,15 @@ &eeprom_addr, sizeof(eeprom_addr), &sfp_eeprom, sizeof(sfp_eeprom)); - eeprom = &sfp_eeprom; - base = eeprom->base; - dump_sfp_eeprom(pdata, base); if (ret) { axgbe_error("I2C error reading SFP EEPROM\n"); goto put; } + eeprom = &sfp_eeprom; + base = eeprom->base; + dump_sfp_eeprom(pdata, base); + /* Validate the contents read */ if (!xgbe_phy_sfp_verify_eeprom(sfp_eeprom.base[XGBE_SFP_BASE_CC], sfp_eeprom.base, sizeof(sfp_eeprom.base) - 1)) { @@ -1390,13 +1470,19 @@ 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]; @@ -1410,6 +1496,136 @@ 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 int +xgbe_read_gpio_expander(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + uint8_t gpio_reg, gpio_ports[2]; + int ret = 0; + + ret = xgbe_phy_sfp_get_mux(pdata); + if (ret) { + axgbe_error("I2C error setting SFP MUX\n"); + return (ret); + } + + gpio_reg = 2; + for (int i = 0; i < 3; i++) { + 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 GPIO expander register: %d\n", + __func__, gpio_reg); + goto put_mux; + } + + if (gpio_reg == 2) + phy_data->sfp_gpio_outputs = (gpio_ports[1] << 8) | gpio_ports[0]; + else if (gpio_reg == 4) + phy_data->sfp_gpio_polarity = (gpio_ports[1] << 8) | gpio_ports[0]; + else if (gpio_reg == 6) + phy_data->sfp_gpio_configuration = (gpio_ports[1] << 8) | gpio_ports[0]; + + memset(gpio_ports, 0, sizeof(gpio_ports)); + gpio_reg += 2; + } + +put_mux: + xgbe_phy_sfp_put_mux(pdata); + + return (ret); +} + +static void +xgbe_log_gpio_expander(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + + axgbe_printf(1, "Input port registers: 0x%x\n", phy_data->sfp_gpio_inputs); + axgbe_printf(1, "Output port registers: 0x%x\n", phy_data->sfp_gpio_outputs); + axgbe_printf(1, "Polarity port registers: 0x%x\n", phy_data->sfp_gpio_polarity); + axgbe_printf(1, "Configuration port registers: 0x%x\n", phy_data->sfp_gpio_configuration); +} + +static int +xgbe_phy_validate_gpio_expander(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + uint8_t gpio_data[3] = {0}; + int shift = GPIO_MASK_WIDTH * (3 - phy_data->port_id); + int rx_los_pos = (1 << phy_data->sfp_gpio_rx_los); + int tx_fault_pos = (1 << phy_data->sfp_gpio_tx_fault); + int mod_abs_pos = (1 << phy_data->sfp_gpio_mod_absent); + int port_sfp_pins = (mod_abs_pos | rx_los_pos | tx_fault_pos); + uint16_t config = 0; + int ret = 0; + + ret = xgbe_phy_get_comm_ownership(pdata); + if (ret) + return (ret); + + ret = xgbe_read_gpio_expander(pdata); + if (ret) + goto put; + + ret = xgbe_phy_sfp_get_mux(pdata); + if (ret) { + axgbe_error("I2C error setting SFP MUX\n"); + goto put; + } + + if (phy_data->sfp_gpio_polarity) { + axgbe_printf(0, "GPIO polarity inverted, resetting\n"); + + xgbe_log_gpio_expander(pdata); + gpio_data[0] = 4; /* polarity register */ + + ret = xgbe_phy_i2c_write(pdata, phy_data->sfp_gpio_address, + gpio_data, sizeof(gpio_data)); + + if (ret) { + axgbe_error("%s: I2C error writing to GPIO polarity register\n", + __func__); + goto put_mux; + } + } + + config = phy_data->sfp_gpio_configuration; + if ((config & port_sfp_pins) != port_sfp_pins) { + xgbe_log_gpio_expander(pdata); + + /* Write the I/O states to the configuration register */ + axgbe_error("Invalid GPIO configuration, resetting\n"); + gpio_data[0] = 6; /* configuration register */ + config = config & ~(0xF << shift); /* clear port id bits */ + config |= port_sfp_pins; + gpio_data[1] = config & 0xff; + gpio_data[2] = (config >> 8); + + ret = xgbe_phy_i2c_write(pdata, phy_data->sfp_gpio_address, + gpio_data, sizeof(gpio_data)); + if (ret) { + axgbe_error("%s: I2C error writing to GPIO configuration register\n", + __func__); + goto put_mux; + } + } else { + axgbe_printf(0, "GPIO configuration valid\n"); + } + +put_mux: + xgbe_phy_sfp_put_mux(pdata); + +put: + xgbe_phy_put_comm_ownership(pdata); + + return (ret); } static void @@ -1441,9 +1657,6 @@ 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; @@ -1461,6 +1674,11 @@ if (ret) { /* Treat any error as if there isn't an SFP plugged in */ axgbe_error("%s: eeprom read failed\n", __func__); + ret = xgbe_read_gpio_expander(pdata); + + if (!ret) + xgbe_log_gpio_expander(pdata); + xgbe_phy_sfp_reset(phy_data); xgbe_phy_sfp_mod_absent(pdata); goto put; @@ -1610,17 +1828,17 @@ } break; case XGBE_SGMII_AN_LINK_SPEED_1000: + default: + /* Default to 1000 */ if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) { XGBE_SET_LP_ADV(&pdata->phy, 1000baseT_Full); mode = XGBE_MODE_SGMII_1000; } else { /* Half-duplex not supported */ XGBE_SET_LP_ADV(&pdata->phy, 1000baseT_Half); - mode = XGBE_MODE_UNKNOWN; + mode = XGBE_MODE_SGMII_1000; } break; - default: - mode = XGBE_MODE_UNKNOWN; } return (mode); @@ -1913,7 +2131,6 @@ if (!phy_data->phydev) return (0); - ret = xgbe_phy_start_aneg(pdata); return (ret); } @@ -2022,6 +2239,39 @@ xgbe_phy_put_comm_ownership(pdata); } +static void +xgbe_phy_rx_reset(struct xgbe_prv_data *pdata) +{ + int reg; + + reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT, + XGBE_PCS_PSEQ_STATE_MASK); + + if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) { + /* Mailbox command timed out, reset of RX block is required. + * This can be done by asserting the reset bit and waiting + * for its completion. + */ + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, + XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON); + DELAY(20); + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, + XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF); + DELAY(50); + axgbe_printf(0, "%s: firmware mailbox reset performed\n", __func__); + } +} + +static void +xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable) +{ + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0, + XGBE_PMA_PLL_CTRL_MASK, + enable ? XGBE_PMA_PLL_CTRL_ENABLE + : XGBE_PMA_PLL_CTRL_DISABLE); + DELAY(200); +} + static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, unsigned int cmd, unsigned int sub_cmd) @@ -2029,9 +2279,13 @@ unsigned int s0 = 0; unsigned int wait; + xgbe_phy_pll_ctrl(pdata, false); + /* Log if a previous command did not complete */ - if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) + if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { axgbe_error("firmware mailbox not ready for command\n"); + xgbe_phy_rx_reset(pdata); + } /* Construct the command */ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd); @@ -2047,13 +2301,19 @@ while (wait--) { if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { axgbe_printf(3, "%s: Rate change done\n", __func__); - return; + goto reenable_pll; } DELAY(2000); } axgbe_printf(3, "firmware mailbox command did not complete\n"); + + /* Reset on error */ + xgbe_phy_rx_reset(pdata); + +reenable_pll: + xgbe_phy_pll_ctrl(pdata, true); } static void @@ -2436,7 +2696,7 @@ if(phy_data->port_mode == XGBE_PORT_MODE_NBASE_T) ifmr->ifm_active |= IFM_100_T; else if(phy_data->port_mode == XGBE_PORT_MODE_SFP) - ifmr->ifm_active |= IFM_1000_SGMII; + ifmr->ifm_active |= IFM_100_SGMII; else ifmr->ifm_active |= IFM_OTHER; break; @@ -2631,7 +2891,8 @@ switch (speed) { case SPEED_100: - return (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000); + return ((phy_data->sfp_speed == XGBE_SFP_SPEED_100) || + (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000)); case SPEED_1000: return ((phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000) || (phy_data->sfp_speed == XGBE_SFP_SPEED_1000)); @@ -2698,6 +2959,7 @@ axgbe_printf(2, "%s: Link %d\n", __func__, pdata->phy.link); reg = xgbe_phy_mii_read(pdata, pdata->mdio_addr, MII_BMSR); + reg = xgbe_phy_mii_read(pdata, pdata->mdio_addr, MII_BMSR); if (reg < 0) return (reg); @@ -2823,6 +3085,25 @@ return (0); } +static void +xgbe_rrc(struct xgbe_prv_data *pdata) +{ + struct xgbe_phy_data *phy_data = pdata->phy_data; + int ret; + + if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) { + axgbe_printf(1, "ENTERED RRC: rrc_count: %d\n", + phy_data->rrc_count); + phy_data->rrc_count = 0; + if (pdata->link_workaround) { + ret = xgbe_phy_reset(pdata); + if (ret) + axgbe_error("Error resetting phy\n"); + } else + xgbe_phy_rrc(pdata); + } +} + static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) { @@ -2848,16 +3129,28 @@ axgbe_printf(1, "%s: SFP absent 0x%x & sfp_rx_los 0x%x\n", __func__, phy_data->sfp_mod_absent, phy_data->sfp_rx_los); + + if (!phy_data->sfp_mod_absent) { + xgbe_rrc(pdata); + } + return (0); } - } else { + } + + if (phy_data->phydev || phy_data->port_mode != XGBE_PORT_MODE_SFP) { + if (pdata->axgbe_miibus == NULL) { + axgbe_printf(1, "%s: miibus not initialized", __func__); + goto mdio_read; + } + mii = device_get_softc(pdata->axgbe_miibus); mii_tick(mii); - + ret = xgbe_phy_read_status(pdata); if (ret) { - axgbe_printf(2, "Link: Read status returned %d\n", ret); - return (ret); + axgbe_error("Link: Read status returned %d\n", ret); + return (0); } axgbe_printf(2, "%s: link speed %#x duplex %#x media %#x " @@ -2869,9 +3162,14 @@ if ((pdata->phy.autoneg == AUTONEG_ENABLE) && !ret) return (0); - return (pdata->phy.link); + if (pdata->phy.link) + return (1); + + xgbe_rrc(pdata); } +mdio_read: + /* Link status is latched low, so read once to clear * and then read again to get current state */ @@ -2882,17 +3180,7 @@ return (1); /* No link, attempt a receiver reset cycle */ - if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) { - axgbe_printf(1, "ENTERED RRC: rrc_count: %d\n", - phy_data->rrc_count); - phy_data->rrc_count = 0; - if (pdata->link_workaround) { - ret = xgbe_phy_reset(pdata); - if (ret) - axgbe_error("Error resetting phy\n"); - } else - xgbe_phy_rrc(pdata); - } + xgbe_rrc(pdata); return (0); } @@ -3354,6 +3642,15 @@ switch (phy_data->port_mode) { case XGBE_PORT_MODE_SFP: axgbe_printf(3, "%s: calling phy detect\n", __func__); + + /* + * Validate the configuration of the GPIO expander before + * we interpret the SFP signals. + */ + axgbe_printf(1, "Checking GPIO expander validity\n"); + xgbe_phy_validate_gpio_expander(pdata); + + phy_data->sfp_phy_retries = 0; xgbe_phy_sfp_detect(pdata); break; default: diff --git a/sys/dev/axgbe/xgbe-sysctl.c b/sys/dev/axgbe/xgbe-sysctl.c --- a/sys/dev/axgbe/xgbe-sysctl.c +++ b/sys/dev/axgbe/xgbe-sysctl.c @@ -1608,6 +1608,10 @@ pdata->sysctl_xgmac_reg = 0; pdata->sysctl_xpcs_mmd = 1; pdata->sysctl_xpcs_reg = 0; + pdata->link_workaround = 1; + pdata->tx_pause = 1; + pdata->rx_pause = 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"); @@ -1620,6 +1624,18 @@ 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, pdata, 0, sysctl_xgmac_reg_addr_handler, "IU", diff --git a/sys/dev/axgbe/xgbe-txrx.c b/sys/dev/axgbe/xgbe-txrx.c --- a/sys/dev/axgbe/xgbe-txrx.c +++ b/sys/dev/axgbe/xgbe-txrx.c @@ -702,7 +702,7 @@ 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__, @@ -767,11 +767,9 @@ 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); } @@ -788,9 +786,6 @@ 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.h b/sys/dev/axgbe/xgbe.h --- a/sys/dev/axgbe/xgbe.h +++ b/sys/dev/axgbe/xgbe.h @@ -180,9 +180,9 @@ #define XGBE_DMA_SYS_AWCR 0x30303030 /* DMA cache settings - PCI device */ -#define XGBE_DMA_PCI_ARCR 0x00000003 -#define XGBE_DMA_PCI_AWCR 0x13131313 -#define XGBE_DMA_PCI_AWARCR 0x00000313 +#define XGBE_DMA_PCI_ARCR 0x000f0f0f +#define XGBE_DMA_PCI_AWCR 0x0f0f0f0f +#define XGBE_DMA_PCI_AWARCR 0x00000f0f /* DMA channel interrupt modes */ #define XGBE_IRQ_MODE_EDGE 0