From nobody Mon Apr 29 02:41:38 2024 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4VSSJg0xtdz5J267; Mon, 29 Apr 2024 02:41:39 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4VSSJg0mKkz4pDn; Mon, 29 Apr 2024 02:41:39 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1714358499; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=VyVrr/4eOtioSE/YtCWrVUo0E3fAc5M23rGh6NGARpk=; b=BAc9XM5LiiRN1u7jHcjfjzVSl7A3ZY++lhAxtd39Q5wC0xJwPctsgCIDxx3zISly1jIzwQ 59YoSg7mD0OFrITMZ8g4XmgXkKLjS3isBa2YnksXL8X4/NPPkcJ95pOC+iLCGyoByRzJUm us7ZdjOTzRQb8EMa6qrx2zyMN7fpQIM8mybLwI8LVSahsowAJkD1wt2ZTTZbWnHFufEJ/a yvNqDqrkJD5OzL+MPYcmxq6FEgU40xdaIVIRWQhl+ixD4rPoFDTRZ0aHQ6dNhsDmCIY9cf pkOn3vgZWn7xaYa8QEE2nT/5U8GydRaTnj0koxeDwf3F1ulca1yHSH7oxza2Ng== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1714358499; a=rsa-sha256; cv=none; b=Qr4bYeGEFU1YP1hrtPumPznoApSauzY1R32/wyr7tFAZ/rtJjz6zQLvMSVDOMuPzyF7cMD 5/V9Y91aGBM4ShquZuPNh7eO04ch0TEkOJn4/8rsY2jMEihjq1Pi0/+lza29zTtOHcNpK3 jcK9eXUadNIGCmtbCNpvRpQE0VuMyxnQoZPP+efT7nPxvFNbZCd8PK+x2M3d+XARmaMn1k c40VL3ULglFOYpjIdRy3nNK+yHwLac8rx/It8FJ5oZn5XTBS8D8XEy1AU+CcM17SJB9pzu 1wQ/oUMJD31omg7rw3BArBLkh3MRri0arJshphvtKGtNbnRqHkc/dpDqCOpWEA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1714358499; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=VyVrr/4eOtioSE/YtCWrVUo0E3fAc5M23rGh6NGARpk=; b=Y3TTOYWvg0JOwrCsf6wAWqYpSSwYkMm44t0xLLuwmAi80wYnnhy6b53xbCrqrMWo3sirkv WgeLtB6FgfTurioaADsYw3mLFoDGAntqd9zgduRk93vzv+Te6WZ64e55qb5FUVoWY6cRT8 lKurPHFKQbtvPGhWpzg/Uay8mQp2rT5Mdz2c/SAcvRghp668WZdrnlTBDzXF+VKU+4jTxM BXbNzTXhBTznu5eXwJf/9IChK4gmKnXYhRJmfEbgNGT7i1FZc156dDg9vaocIOPG0b2Pfh HTonZEFTkfg3PaUO1MZpahpzHsWGLe+j539UVIMrtMmyRsuPpCaBeh/MCNQA4A== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4VSSJg0MZtzrfC; Mon, 29 Apr 2024 02:41:39 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 43T2fcdG072223; Mon, 29 Apr 2024 02:41:38 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 43T2fckp072220; Mon, 29 Apr 2024 02:41:38 GMT (envelope-from git) Date: Mon, 29 Apr 2024 02:41:38 GMT Message-Id: <202404290241.43T2fckp072220@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Warner Losh Subject: git: 2b8df536a681 - main - axgbe: Various stability improvements List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 2b8df536a68169953a9fa470b78a021156d997aa Auto-Submitted: auto-generated The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=2b8df536a68169953a9fa470b78a021156d997aa commit 2b8df536a68169953a9fa470b78a021156d997aa Author: Stephan de Wit AuthorDate: 2024-04-29 01:57:26 +0000 Commit: Warner Losh CommitDate: 2024-04-29 01:57:51 +0000 axgbe: Various stability improvements Hook in RSS glue. Default to "off" for the split header feature to ensure netmap compatibility. Change the PCS indirection register values based on hardware type (ported from Linux). Move tunable settings to sysctl_init() and set the defaults there. Ensure it's called at the right time by moving it back. Reset PHY RX data path when mailbox command times out (Ported from Linux). Check if VLAN HW tagging is enabled before assuming a VLAN tag is present in a descriptor. Disable the hardware filter since multicast traffic is dropped in promisc mode. Remove unnecessary return statement. Missing sfp_get_mux, causing a race between ports to read SFP(+) sideband signals. Validate and fix incorrectly initialized polarity/configuration registers. Remove unnecessary SFP reset. axgbe_isc_rxd_pkt_get has no error state, remove unnecessary big packet check. Enable RSF to prevent zero-length packets while in Netmap mode. DMA cache coherency update (ported from Linux). Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/1103 --- sys/dev/axgbe/if_axgbe_pci.c | 98 +++++++++++++++++------ sys/dev/axgbe/xgbe-common.h | 16 ++++ sys/dev/axgbe/xgbe-dev.c | 9 ++- sys/dev/axgbe/xgbe-i2c.c | 2 - sys/dev/axgbe/xgbe-phy-v2.c | 186 +++++++++++++++++++++++++++++++++++++++++-- sys/dev/axgbe/xgbe-sysctl.c | 16 ++++ sys/dev/axgbe/xgbe-txrx.c | 7 +- sys/dev/axgbe/xgbe.h | 6 +- 8 files changed, 298 insertions(+), 42 deletions(-) diff --git a/sys/dev/axgbe/if_axgbe_pci.c b/sys/dev/axgbe/if_axgbe_pci.c index beb4ff338dc7..3e68525067fb 100644 --- a/sys/dev/axgbe/if_axgbe_pci.c +++ b/sys/dev/axgbe/if_axgbe_pci.c @@ -56,6 +56,12 @@ #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"); @@ -103,6 +109,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); @@ -277,11 +284,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) { @@ -389,6 +396,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; int ret; @@ -430,9 +438,23 @@ axgbe_if_attach_pre(if_ctx_t ctx) sc->pdata.xgmac_res = mac_res[0]; 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; + /* + * Set the PCS indirect addressing definition registers. + * A newer version of the hardware is using the same PCI ids + * for the network device but has altered register definitions + * for determining the window settings for the indirect PCS access. + * This code checks hardware usage and uses the register values + * accordingly. + */ + 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); @@ -714,6 +736,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) { @@ -1336,11 +1399,9 @@ xgbe_default_config(struct xgbe_prv_data *pdata) 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; @@ -1355,7 +1416,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; @@ -1373,6 +1434,8 @@ axgbe_if_attach_post(if_ctx_t ctx) if (ret) axgbe_error("%s: exit error %d\n", __func__, ret); + axgbe_sysctl_init(pdata); + /* Configure the defaults */ xgbe_default_config(pdata); @@ -1408,15 +1471,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; @@ -1452,11 +1507,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, @@ -1468,8 +1518,6 @@ axgbe_if_attach_post(if_ctx_t ctx) 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); diff --git a/sys/dev/axgbe/xgbe-common.h b/sys/dev/axgbe/xgbe-common.h index 4d504682d1af..e2096463703b 100644 --- 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 @@ -1402,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 @@ -1423,6 +1435,10 @@ #define XGBE_PMA_PLL_CTRL_ENABLE BIT(15) #define XGBE_PMA_PLL_CTRL_DISABLE 0x0000 +#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 + /* 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 index 786e04930780..39d0dab144a2 100644 --- a/sys/dev/axgbe/xgbe-dev.c +++ b/sys/dev/axgbe/xgbe-dev.c @@ -1451,7 +1451,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, @@ -2029,6 +2030,12 @@ xgbe_config_mac_address(struct xgbe_prv_data *pdata) { 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 index 5883e96ed37e..fe9184aa1dd5 100644 --- a/sys/dev/axgbe/xgbe-i2c.c +++ b/sys/dev/axgbe/xgbe-i2c.c @@ -327,8 +327,6 @@ out: 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) diff --git a/sys/dev/axgbe/xgbe-phy-v2.c b/sys/dev/axgbe/xgbe-phy-v2.c index d8c372cac642..d08ed118a8a8 100644 --- a/sys/dev/axgbe/xgbe-phy-v2.c +++ b/sys/dev/axgbe/xgbe-phy-v2.c @@ -376,6 +376,9 @@ struct xgbe_phy_data { 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; @@ -1461,13 +1464,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]; @@ -1481,6 +1490,136 @@ 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 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 @@ -1512,9 +1651,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; @@ -1532,6 +1668,11 @@ xgbe_phy_sfp_detect(struct xgbe_prv_data *pdata) 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; @@ -2102,6 +2243,30 @@ xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable) DELAY(200); } +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_perform_ratechange(struct xgbe_prv_data *pdata, unsigned int cmd, unsigned int sub_cmd) @@ -2112,8 +2277,10 @@ xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, unsigned int cmd, 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); @@ -3467,6 +3634,15 @@ xgbe_phy_start(struct xgbe_prv_data *pdata) 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 index d5ddfbbd0bd6..16523381e1a3 100644 --- a/sys/dev/axgbe/xgbe-sysctl.c +++ b/sys/dev/axgbe/xgbe-sysctl.c @@ -1607,6 +1607,10 @@ 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->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"); @@ -1619,6 +1623,18 @@ axgbe_sysctl_init(struct xgbe_prv_data *pdata) 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 index 52274dba4352..fd3d821e2e53 100644 --- a/sys/dev/axgbe/xgbe-txrx.c +++ b/sys/dev/axgbe/xgbe-txrx.c @@ -702,7 +702,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__, @@ -767,11 +767,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); } @@ -788,9 +786,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.h b/sys/dev/axgbe/xgbe.h index 4719b16f47d6..5e4cc40bb2c9 100644 --- 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