Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/axgbe/if_axgbe_pci.c
Show All 35 Lines | |||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/systm.h> | |||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_media.h> | #include <net/if_media.h> | ||||
#include <dev/mii/mii.h> | #include <dev/mii/mii.h> | ||||
#include <dev/mii/miivar.h> | #include <dev/mii/miivar.h> | ||||
#include <dev/pci/pcireg.h> | #include <dev/pci/pcireg.h> | ||||
#include <dev/pci/pcivar.h> | #include <dev/pci/pcivar.h> | ||||
#include "xgbe.h" | #include "xgbe.h" | ||||
#include "xgbe-common.h" | #include "xgbe-common.h" | ||||
#include "miibus_if.h" | #include "miibus_if.h" | ||||
#include "ifdi_if.h" | #include "ifdi_if.h" | ||||
#include "opt_inet.h" | #include "opt_inet.h" | ||||
#include "opt_inet6.h" | #include "opt_inet6.h" | ||||
MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data"); | MALLOC_DEFINE(M_AXGBE, "axgbe", "axgbe data"); | ||||
extern struct if_txrx axgbe_txrx; | extern struct if_txrx axgbe_txrx; | ||||
static int axgbe_sph_enable; | |||||
/* Function prototypes */ | /* Function prototypes */ | ||||
static void *axgbe_register(device_t); | static void *axgbe_register(device_t); | ||||
static int axgbe_if_attach_pre(if_ctx_t); | static int axgbe_if_attach_pre(if_ctx_t); | ||||
static int axgbe_if_attach_post(if_ctx_t); | static int axgbe_if_attach_post(if_ctx_t); | ||||
static int axgbe_if_detach(if_ctx_t); | static int axgbe_if_detach(if_ctx_t); | ||||
static void axgbe_if_stop(if_ctx_t); | static void axgbe_if_stop(if_ctx_t); | ||||
static void axgbe_if_init(if_ctx_t); | static void axgbe_if_init(if_ctx_t); | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | static struct if_shared_ctx axgbe_sctx_init = { | ||||
.isc_rx_maxsize = MJUM9BYTES, | .isc_rx_maxsize = MJUM9BYTES, | ||||
.isc_rx_maxsegsize = MJUM9BYTES, | .isc_rx_maxsegsize = MJUM9BYTES, | ||||
.isc_rx_nsegments = 1, | .isc_rx_nsegments = 1, | ||||
.isc_admin_intrcnt = 4, | .isc_admin_intrcnt = 4, | ||||
.isc_vendor_info = axgbe_vendor_info_array, | .isc_vendor_info = axgbe_vendor_info_array, | ||||
.isc_driver_version = XGBE_DRV_VERSION, | .isc_driver_version = XGBE_DRV_VERSION, | ||||
.isc_nrxd_min = {XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MIN}, | |||||
.isc_nrxd_default = {XGBE_RX_DESC_CNT_DEFAULT, XGBE_RX_DESC_CNT_DEFAULT}, | |||||
.isc_nrxd_max = {XGBE_RX_DESC_CNT_MAX, XGBE_RX_DESC_CNT_MAX}, | |||||
.isc_ntxd_min = {XGBE_TX_DESC_CNT_MIN}, | .isc_ntxd_min = {XGBE_TX_DESC_CNT_MIN}, | ||||
.isc_ntxd_default = {XGBE_TX_DESC_CNT_DEFAULT}, | .isc_ntxd_default = {XGBE_TX_DESC_CNT_DEFAULT}, | ||||
.isc_ntxd_max = {XGBE_TX_DESC_CNT_MAX}, | .isc_ntxd_max = {XGBE_TX_DESC_CNT_MAX}, | ||||
.isc_nfl = 2, | |||||
.isc_ntxqs = 1, | .isc_ntxqs = 1, | ||||
.isc_nrxqs = 2, | |||||
.isc_flags = IFLIB_TSO_INIT_IP | IFLIB_NEED_SCRATCH | | .isc_flags = IFLIB_TSO_INIT_IP | IFLIB_NEED_SCRATCH | | ||||
IFLIB_NEED_ZERO_CSUM | IFLIB_NEED_ETHER_PAD, | IFLIB_NEED_ZERO_CSUM | IFLIB_NEED_ETHER_PAD, | ||||
}; | }; | ||||
static void * | static void * | ||||
axgbe_register(device_t dev) | axgbe_register(device_t dev) | ||||
{ | { | ||||
int axgbe_nfl; | |||||
int axgbe_nrxqs; | |||||
int error, i; | |||||
char *value = NULL; | |||||
value = kern_getenv("dev.ax.sph_enable"); | |||||
if (value) { | |||||
axgbe_sph_enable = strtol(value, NULL, 10); | |||||
freeenv(value); | |||||
} else { | |||||
/* | |||||
* 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"); | |||||
if (error) { | |||||
printf("Error setting tunable, using default driver values\n"); | |||||
} | |||||
axgbe_sph_enable = 1; | |||||
} | |||||
if (!axgbe_sph_enable) { | |||||
axgbe_nfl = 1; | |||||
axgbe_nrxqs = 1; | |||||
} else { | |||||
axgbe_nfl = 2; | |||||
axgbe_nrxqs = 2; | |||||
} | |||||
axgbe_sctx_init.isc_nfl = axgbe_nfl; | |||||
axgbe_sctx_init.isc_nrxqs = axgbe_nrxqs; | |||||
for (i = 0 ; i < axgbe_nrxqs ; i++) { | |||||
axgbe_sctx_init.isc_nrxd_min[i] = XGBE_RX_DESC_CNT_MIN; | |||||
axgbe_sctx_init.isc_nrxd_default[i] = XGBE_RX_DESC_CNT_DEFAULT; | |||||
axgbe_sctx_init.isc_nrxd_max[i] = XGBE_RX_DESC_CNT_MAX; | |||||
} | |||||
return (&axgbe_sctx_init); | return (&axgbe_sctx_init); | ||||
} | } | ||||
/* MII Interface Functions */ | /* MII Interface Functions */ | ||||
static int | static int | ||||
axgbe_miibus_readreg(device_t dev, int phy, int reg) | axgbe_miibus_readreg(device_t dev, int phy, int reg) | ||||
{ | { | ||||
struct axgbe_if_softc *sc = iflib_get_softc(device_get_softc(dev)); | struct axgbe_if_softc *sc = iflib_get_softc(device_get_softc(dev)); | ||||
struct xgbe_prv_data *pdata = &sc->pdata; | struct xgbe_prv_data *pdata = &sc->pdata; | ||||
int val; | int val; | ||||
vmaffione: This could be made shorter and more readable with something like:
````
for (i = 0; i <… | |||||
axgbe_printf(3, "%s: phy %d reg %d\n", __func__, phy, reg); | axgbe_printf(3, "%s: phy %d reg %d\n", __func__, phy, reg); | ||||
val = xgbe_phy_mii_read(pdata, phy, reg); | val = xgbe_phy_mii_read(pdata, phy, reg); | ||||
axgbe_printf(2, "%s: val 0x%x\n", __func__, val); | axgbe_printf(2, "%s: val 0x%x\n", __func__, val); | ||||
return (val & 0xFFFF); | return (val & 0xFFFF); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 997 Lines • ▼ Show 20 Lines | axgbe_if_attach_post(if_ctx_t ctx) | ||||
struct axgbe_if_softc *sc = iflib_get_softc(ctx); | struct axgbe_if_softc *sc = iflib_get_softc(ctx); | ||||
struct xgbe_prv_data *pdata = &sc->pdata; | struct xgbe_prv_data *pdata = &sc->pdata; | ||||
struct ifnet *ifp = pdata->netdev; | struct ifnet *ifp = pdata->netdev; | ||||
struct xgbe_phy_if *phy_if = &pdata->phy_if; | struct xgbe_phy_if *phy_if = &pdata->phy_if; | ||||
struct xgbe_hw_if *hw_if = &pdata->hw_if; | struct xgbe_hw_if *hw_if = &pdata->hw_if; | ||||
if_softc_ctx_t scctx = sc->scctx; | if_softc_ctx_t scctx = sc->scctx; | ||||
int i, ret; | int i, ret; | ||||
/* set split header support based on tunable */ | |||||
pdata->sph_enable = axgbe_sph_enable; | |||||
/* Initialize ECC timestamps */ | /* Initialize ECC timestamps */ | ||||
pdata->tx_sec_period = ticks; | pdata->tx_sec_period = ticks; | ||||
pdata->tx_ded_period = ticks; | pdata->tx_ded_period = ticks; | ||||
pdata->rx_sec_period = ticks; | pdata->rx_sec_period = ticks; | ||||
pdata->rx_ded_period = ticks; | pdata->rx_ded_period = ticks; | ||||
pdata->desc_sec_period = ticks; | pdata->desc_sec_period = ticks; | ||||
pdata->desc_ded_period = ticks; | pdata->desc_ded_period = ticks; | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | #endif | ||||
DBGPR("mtu %d\n", ifp->if_mtu); | DBGPR("mtu %d\n", ifp->if_mtu); | ||||
scctx->isc_max_frame_size = ifp->if_mtu + 18; | scctx->isc_max_frame_size = ifp->if_mtu + 18; | ||||
scctx->isc_min_frame_size = XGMAC_MIN_PACKET; | scctx->isc_min_frame_size = XGMAC_MIN_PACKET; | ||||
axgbe_setup_sysctl(pdata); | axgbe_setup_sysctl(pdata); | ||||
axgbe_sysctl_init(pdata); | axgbe_sysctl_init(pdata); | ||||
axgbe_pci_init(pdata); | |||||
return (0); | return (0); | ||||
} /* axgbe_if_attach_post */ | } /* axgbe_if_attach_post */ | ||||
static void | static void | ||||
xgbe_free_intr(struct xgbe_prv_data *pdata, struct resource *res, void *tag, | xgbe_free_intr(struct xgbe_prv_data *pdata, struct resource *res, void *tag, | ||||
int rid) | int rid) | ||||
{ | { | ||||
if (tag) | if (tag) | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
} /* axgbe_if_detach */ | } /* axgbe_if_detach */ | ||||
static void | static void | ||||
axgbe_pci_init(struct xgbe_prv_data *pdata) | axgbe_pci_init(struct xgbe_prv_data *pdata) | ||||
{ | { | ||||
struct xgbe_phy_if *phy_if = &pdata->phy_if; | struct xgbe_phy_if *phy_if = &pdata->phy_if; | ||||
struct xgbe_hw_if *hw_if = &pdata->hw_if; | struct xgbe_hw_if *hw_if = &pdata->hw_if; | ||||
int ret = 0; | int ret = 0; | ||||
if (!__predict_false((test_bit(XGBE_DOWN, &pdata->dev_state)))) { | |||||
axgbe_printf(1, "%s: Starting when XGBE_UP\n", __func__); | |||||
return; | |||||
} | |||||
hw_if->init(pdata); | hw_if->init(pdata); | ||||
ret = phy_if->phy_start(pdata); | ret = phy_if->phy_start(pdata); | ||||
if (ret) { | if (ret) { | ||||
axgbe_error("%s: phy start %d\n", __func__, ret); | axgbe_error("%s: phy start %d\n", __func__, ret); | ||||
ret = hw_if->exit(pdata); | ret = hw_if->exit(pdata); | ||||
if (ret) | if (ret) | ||||
axgbe_error("%s: exit error %d\n", __func__, ret); | axgbe_error("%s: exit error %d\n", __func__, ret); | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | axgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *va, uint64_t *pa, int nrxqs, | ||||
struct xgbe_prv_data *pdata = &sc->pdata; | struct xgbe_prv_data *pdata = &sc->pdata; | ||||
if_softc_ctx_t scctx = sc->scctx; | if_softc_ctx_t scctx = sc->scctx; | ||||
struct xgbe_channel *channel; | struct xgbe_channel *channel; | ||||
struct xgbe_ring *rx_ring; | struct xgbe_ring *rx_ring; | ||||
int i, j, k; | int i, j, k; | ||||
MPASS(scctx->isc_nrxqsets > 0); | MPASS(scctx->isc_nrxqsets > 0); | ||||
MPASS(scctx->isc_nrxqsets == nrxqsets); | MPASS(scctx->isc_nrxqsets == nrxqsets); | ||||
if (!pdata->sph_enable) { | |||||
MPASS(nrxqs == 1); | |||||
} else { | |||||
MPASS(nrxqs == 2); | MPASS(nrxqs == 2); | ||||
} | |||||
axgbe_printf(1, "%s: rxqsets %d/%d rxqs %d\n", __func__, | axgbe_printf(1, "%s: rxqsets %d/%d rxqs %d\n", __func__, | ||||
scctx->isc_nrxqsets, nrxqsets, nrxqs); | scctx->isc_nrxqsets, nrxqsets, nrxqs); | ||||
for (i = 0 ; i < nrxqsets; i++) { | for (i = 0 ; i < nrxqsets; i++) { | ||||
channel = pdata->channel[i]; | channel = pdata->channel[i]; | ||||
▲ Show 20 Lines • Show All 249 Lines • ▼ Show 20 Lines | axgbe_if_msix_intr_assign(if_ctx_t ctx, int msix) | ||||
pdata->per_channel_irq = 1; | pdata->per_channel_irq = 1; | ||||
pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL; | pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL; | ||||
rid++; | rid++; | ||||
for (i = 0; i < scctx->isc_nrxqsets; i++, rid++) { | for (i = 0; i < scctx->isc_nrxqsets; i++, rid++) { | ||||
channel = pdata->channel[i]; | channel = pdata->channel[i]; | ||||
snprintf(buf, sizeof(buf), "rxq%d", i); | snprintf(buf, sizeof(buf), "rxq%d", i); | ||||
error = iflib_irq_alloc_generic(ctx, &irq, rid, IFLIB_INTR_RXTX, | error = iflib_irq_alloc_generic(ctx, &irq, rid, IFLIB_INTR_RXTX, | ||||
Done Inline ActionsThis looks correct (because IFLIB_INTR_TX is handled below), but then why was it like that? A simple mistake? vmaffione: This looks correct (because IFLIB_INTR_TX is handled below), but then why was it like that? A… | |||||
Done Inline ActionsRecently, IFLIB_INTR_RX is changed to IFLIB_INTR_RXTX as part of D27683. I verified it doesn't break things. But need to see whether softirq for TX is still needed. If needed will change and submit as separate review. For now, retaining the change from the above review as IFLIB_INTR_RXTX. rajesh1.kumar_amd.com: Recently, IFLIB_INTR_RX is changed to IFLIB_INTR_RXTX as part of [[ https://reviews.freebsd. | |||||
axgbe_msix_que, channel, channel->queue_index, buf); | axgbe_msix_que, channel, channel->queue_index, buf); | ||||
if (error) { | if (error) { | ||||
axgbe_error("Failed to allocated que int %d err: %d\n", | axgbe_error("Failed to allocated que int %d err: %d\n", | ||||
i, error); | i, error); | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 319 Lines • ▼ Show 20 Lines | axgbe_if_media_change(if_ctx_t ctx) | ||||
sx_xunlock(&sc->pdata.an_mutex); | sx_xunlock(&sc->pdata.an_mutex); | ||||
return (-sc->pdata.phy_if.phy_config_aneg(&sc->pdata)); | return (-sc->pdata.phy_if.phy_config_aneg(&sc->pdata)); | ||||
} | } | ||||
static int | static int | ||||
axgbe_if_promisc_set(if_ctx_t ctx, int flags) | axgbe_if_promisc_set(if_ctx_t ctx, int flags) | ||||
{ | { | ||||
struct axgbe_if_softc *sc = iflib_get_softc(ctx); | struct axgbe_if_softc *sc = iflib_get_softc(ctx); | ||||
struct xgbe_prv_data *pdata = &sc->pdata; | |||||
struct ifnet *ifp = pdata->netdev; | |||||
if (XGMAC_IOREAD_BITS(&sc->pdata, MAC_PFR, PR) == 1) | axgbe_printf(1, "%s: MAC_PFR 0x%x drv_flags 0x%x if_flags 0x%x\n", | ||||
__func__, XGMAC_IOREAD(pdata, MAC_PFR), ifp->if_drv_flags, ifp->if_flags); | |||||
if (ifp->if_flags & IFF_PPROMISC) { | |||||
axgbe_printf(1, "User requested to enter promisc mode\n"); | |||||
if (XGMAC_IOREAD_BITS(pdata, MAC_PFR, PR) == 1) { | |||||
axgbe_printf(1, "Already in promisc mode\n"); | |||||
return (0); | return (0); | ||||
} | |||||
XGMAC_IOWRITE_BITS(&sc->pdata, MAC_PFR, PR, 1); | axgbe_printf(1, "Entering promisc mode\n"); | ||||
XGMAC_IOWRITE_BITS(&sc->pdata, MAC_PFR, VTFE, 0); | XGMAC_IOWRITE_BITS(pdata, MAC_PFR, PR, 1); | ||||
XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0); | |||||
} else { | |||||
axgbe_printf(1, "User requested to leave promisc mode\n"); | |||||
if (XGMAC_IOREAD_BITS(pdata, MAC_PFR, PR) == 0) { | |||||
axgbe_printf(1, "Already not in promisc mode\n"); | |||||
return (0); | |||||
} | |||||
axgbe_printf(1, "Leaving promisc mode\n"); | |||||
XGMAC_IOWRITE_BITS(pdata, MAC_PFR, PR, 0); | |||||
XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1); | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
static uint64_t | static uint64_t | ||||
axgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt) | axgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt) | ||||
{ | { | ||||
struct axgbe_if_softc *sc = iflib_get_softc(ctx); | struct axgbe_if_softc *sc = iflib_get_softc(ctx); | ||||
struct ifnet *ifp = iflib_get_ifp(ctx); | struct ifnet *ifp = iflib_get_ifp(ctx); | ||||
struct xgbe_prv_data *pdata = &sc->pdata; | struct xgbe_prv_data *pdata = &sc->pdata; | ||||
▲ Show 20 Lines • Show All 62 Lines • Show Last 20 Lines |
This could be made shorter and more readable with something like: