Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108603884
D40725.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
36 KB
Referenced Files
None
Subscribers
None
D40725.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D40725: axgbe: Assorted stability improvements
Attached
Detach File
Event Timeline
Log In to Comment