Skip to content

Commit

Permalink
axgbe: Various stability improvements
Browse files Browse the repository at this point in the history
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: freebsd#1103
  • Loading branch information
swhite2 authored and bsdimp committed Apr 29, 2024
1 parent 05e8ab6 commit 2b8df53
Show file tree
Hide file tree
Showing 8 changed files with 298 additions and 42 deletions.
98 changes: 73 additions & 25 deletions sys/dev/axgbe/if_axgbe_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@
#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");

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down
16 changes: 16 additions & 0 deletions sys/dev/axgbe/xgbe-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
9 changes: 8 additions & 1 deletion sys/dev/axgbe/xgbe-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 0 additions & 2 deletions sys/dev/axgbe/xgbe-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,6 @@ xgbe_i2c_isr(void *data)
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)
Expand Down
Loading

0 comments on commit 2b8df53

Please sign in to comment.