Page MenuHomeFreeBSD

D40725.diff
No OneTemporary

D40725.diff

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 <net/rss_config.h>
+#include <netinet/in_rss.h>
+
+#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

File Metadata

Mime Type
text/plain
Expires
Mon, Jan 27, 7:56 PM (7 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16208930
Default Alt Text
D40725.diff (36 KB)

Event Timeline