version 1.645.2.10, 2020/11/16 18:21:45 |
version 1.645.2.11, 2021/10/21 14:30:10 |
Line 107 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 107 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/pcq.h> |
#include <sys/pcq.h> |
#include <sys/sysctl.h> |
#include <sys/sysctl.h> |
#include <sys/workqueue.h> |
#include <sys/workqueue.h> |
|
#include <sys/atomic.h> |
|
|
#include <sys/rndsource.h> |
#include <sys/rndsource.h> |
|
|
Line 157 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 158 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define WM_DEBUG_NVM __BIT(5) |
#define WM_DEBUG_NVM __BIT(5) |
#define WM_DEBUG_INIT __BIT(6) |
#define WM_DEBUG_INIT __BIT(6) |
#define WM_DEBUG_LOCK __BIT(7) |
#define WM_DEBUG_LOCK __BIT(7) |
int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | WM_DEBUG_GMII |
|
| WM_DEBUG_MANAGE | WM_DEBUG_NVM | WM_DEBUG_INIT | WM_DEBUG_LOCK; |
#if 0 |
#define DPRINTF(x, y) do { if (wm_debug & (x)) printf y; } while (0) |
#define WM_DEBUG_DEFAULT WM_DEBUG_TX | WM_DEBUG_RX | WM_DEBUG_LINK | \ |
|
WM_DEBUG_GMII | WM_DEBUG_MANAGE | WM_DEBUG_NVM | WM_DEBUG_INIT | \ |
|
WM_DEBUG_LOCK |
|
#endif |
|
|
|
#define DPRINTF(sc, x, y) \ |
|
do { \ |
|
if ((sc)->sc_debug & (x)) \ |
|
printf y; \ |
|
} while (0) |
#else |
#else |
#define DPRINTF(x, y) __nothing |
#define DPRINTF(sc, x, y) __nothing |
#endif /* WM_DEBUG */ |
#endif /* WM_DEBUG */ |
|
|
#ifdef NET_MPSAFE |
#ifdef NET_MPSAFE |
Line 261 typedef union txdescs { |
|
Line 271 typedef union txdescs { |
|
|
|
typedef union rxdescs { |
typedef union rxdescs { |
wiseman_rxdesc_t sctxu_rxdescs[WM_NRXDESC]; |
wiseman_rxdesc_t sctxu_rxdescs[WM_NRXDESC]; |
ext_rxdesc_t sctxu_ext_rxdescs[WM_NRXDESC]; /* 82574 only */ |
ext_rxdesc_t sctxu_ext_rxdescs[WM_NRXDESC]; /* 82574 only */ |
nq_rxdesc_t sctxu_nq_rxdescs[WM_NRXDESC]; /* 82575 and newer */ |
nq_rxdesc_t sctxu_nq_rxdescs[WM_NRXDESC]; /* 82575 and newer */ |
} rxdescs_t; |
} rxdescs_t; |
|
|
Line 304 static const uint32_t wm_82580_rxpbs_tab |
|
Line 314 static const uint32_t wm_82580_rxpbs_tab |
|
|
|
struct wm_softc; |
struct wm_softc; |
|
|
|
#if defined(_LP64) && !defined(WM_DISABLE_EVENT_COUNTERS) |
|
#if !defined(WM_EVENT_COUNTERS) |
|
#define WM_EVENT_COUNTERS 1 |
|
#endif |
|
#endif |
|
|
#ifdef WM_EVENT_COUNTERS |
#ifdef WM_EVENT_COUNTERS |
#define WM_Q_EVCNT_DEFINE(qname, evname) \ |
#define WM_Q_EVCNT_DEFINE(qname, evname) \ |
char qname##_##evname##_evcnt_name[sizeof("qname##XX##evname")]; \ |
char qname##_##evname##_evcnt_name[sizeof("qname##XX##evname")]; \ |
Line 384 struct wm_txqueue { |
|
Line 400 struct wm_txqueue { |
|
time_t txq_lastsent; |
time_t txq_lastsent; |
|
|
/* Checksum flags used for previous packet */ |
/* Checksum flags used for previous packet */ |
uint32_t txq_last_hw_cmd; |
uint32_t txq_last_hw_cmd; |
uint8_t txq_last_hw_fields; |
uint8_t txq_last_hw_fields; |
uint16_t txq_last_hw_ipcs; |
uint16_t txq_last_hw_ipcs; |
uint16_t txq_last_hw_tucs; |
uint16_t txq_last_hw_tucs; |
|
|
Line 472 struct wm_queue { |
|
Line 488 struct wm_queue { |
|
|
|
struct wm_txqueue wmq_txq; |
struct wm_txqueue wmq_txq; |
struct wm_rxqueue wmq_rxq; |
struct wm_rxqueue wmq_rxq; |
|
char sysctlname[32]; /* Name for sysctl */ |
|
|
bool wmq_txrx_use_workqueue; |
bool wmq_txrx_use_workqueue; |
struct work wmq_cookie; |
struct work wmq_cookie; |
Line 624 struct wm_softc { |
|
Line 641 struct wm_softc { |
|
|
|
struct wm_phyop phy; |
struct wm_phyop phy; |
struct wm_nvmop nvm; |
struct wm_nvmop nvm; |
|
#ifdef WM_DEBUG |
|
uint32_t sc_debug; |
|
#endif |
}; |
}; |
|
|
#define WM_CORE_LOCK(_sc) \ |
#define WM_CORE_LOCK(_sc) \ |
|
|
} while (/*CONSTCOND*/0) |
} while (/*CONSTCOND*/0) |
|
|
#ifdef WM_EVENT_COUNTERS |
#ifdef WM_EVENT_COUNTERS |
#define WM_EVCNT_INCR(ev) (ev)->ev_count++ |
#ifdef __HAVE_ATOMIC64_LOADSTORE |
#define WM_EVCNT_ADD(ev, val) (ev)->ev_count += (val) |
#define WM_EVCNT_INCR(ev) \ |
|
atomic_store_relaxed(&((ev)->ev_count), \ |
|
atomic_load_relaxed(&(ev)->ev_count) + 1) |
|
#define WM_EVCNT_ADD(ev, val) \ |
|
atomic_store_relaxed(&((ev)->ev_count), \ |
|
atomic_load_relaxed(&(ev)->ev_count) + (val)) |
|
#else |
|
#define WM_EVCNT_INCR(ev) \ |
|
((ev)->ev_count)++ |
|
#define WM_EVCNT_ADD(ev, val) \ |
|
(ev)->ev_count += (val) |
|
#endif |
|
|
#define WM_Q_EVCNT_INCR(qname, evname) \ |
#define WM_Q_EVCNT_INCR(qname, evname) \ |
WM_EVCNT_INCR(&(qname)->qname##_ev_##evname) |
WM_EVCNT_INCR(&(qname)->qname##_ev_##evname) |
Line 1036 static bool wm_phy_need_linkdown_discard |
|
Line 1067 static bool wm_phy_need_linkdown_discard |
|
static void wm_set_linkdown_discard(struct wm_softc *); |
static void wm_set_linkdown_discard(struct wm_softc *); |
static void wm_clear_linkdown_discard(struct wm_softc *); |
static void wm_clear_linkdown_discard(struct wm_softc *); |
|
|
|
#ifdef WM_DEBUG |
|
static int wm_sysctl_debug(SYSCTLFN_PROTO); |
|
#endif |
|
|
CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc), |
CFATTACH_DECL3_NEW(wm, sizeof(struct wm_softc), |
wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); |
wm_match, wm_attach, wm_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); |
|
|
Line 1563 static const struct wm_product { |
|
Line 1598 static const struct wm_product { |
|
"I219 LM Ethernet Connection", |
"I219 LM Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM2, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM2, |
"I219 LM Ethernet Connection", |
"I219 LM (2) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM3, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM3, |
"I219 LM Ethernet Connection", |
"I219 LM (3) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM4, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM4, |
"I219 LM Ethernet Connection", |
"I219 LM (4) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM5, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM5, |
"I219 LM Ethernet Connection", |
"I219 LM (5) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM6, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM6, |
"I219 LM Ethernet Connection", |
"I219 LM (6) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM7, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM7, |
"I219 LM Ethernet Connection", |
"I219 LM (7) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM8, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM8, |
"I219 LM Ethernet Connection", |
"I219 LM (8) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM9, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM9, |
"I219 LM Ethernet Connection", |
"I219 LM (9) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM10, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM10, |
"I219 LM Ethernet Connection", |
"I219 LM (10) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM11, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM11, |
"I219 LM Ethernet Connection", |
"I219 LM (11) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM12, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM12, |
"I219 LM Ethernet Connection", |
"I219 LM (12) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM13, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM13, |
"I219 LM Ethernet Connection", |
"I219 LM (13) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM14, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM14, |
"I219 LM Ethernet Connection", |
"I219 LM (14) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM15, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM15, |
"I219 LM Ethernet Connection", |
"I219 LM (15) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM16, |
|
"I219 LM (16) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM17, |
|
"I219 LM (17) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM18, |
|
"I219 LM (18) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_LM19, |
|
"I219 LM (19) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V, |
"I219 V Ethernet Connection", |
"I219 V Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V2, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V2, |
"I219 V Ethernet Connection", |
"I219 V (2) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V4, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V4, |
"I219 V Ethernet Connection", |
"I219 V (4) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V5, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V5, |
"I219 V Ethernet Connection", |
"I219 V (5) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V6, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V6, |
"I219 V Ethernet Connection", |
"I219 V (6) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V7, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V7, |
"I219 V Ethernet Connection", |
"I219 V (7) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V8, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V8, |
"I219 V Ethernet Connection", |
"I219 V (8) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V9, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V9, |
"I219 V Ethernet Connection", |
"I219 V (9) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V10, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V10, |
"I219 V Ethernet Connection", |
"I219 V (10) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V11, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V11, |
"I219 V Ethernet Connection", |
"I219 V (11) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V12, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V12, |
"I219 V Ethernet Connection", |
"I219 V (12) Ethernet Connection", |
WM_T_PCH_SPT, WMP_F_COPPER }, |
WM_T_PCH_SPT, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V13, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V13, |
"I219 V Ethernet Connection", |
"I219 V (13) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V14, |
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V14, |
"I219 V Ethernet Connection", |
"I219 V (14) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V15, |
|
"I219 V (15) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V16, |
|
"I219 V (16) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V17, |
|
"I219 V (17) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V18, |
|
"I219 V (18) Ethernet Connection", |
|
WM_T_PCH_CNP, WMP_F_COPPER }, |
|
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I219_V19, |
|
"I219 V (19) Ethernet Connection", |
WM_T_PCH_CNP, WMP_F_COPPER }, |
WM_T_PCH_CNP, WMP_F_COPPER }, |
{ 0, 0, |
{ 0, 0, |
NULL, |
NULL, |
Line 1847 wm_attach(device_t parent, device_t self |
|
Line 1909 wm_attach(device_t parent, device_t self |
|
uint32_t link_mode; |
uint32_t link_mode; |
uint32_t reg; |
uint32_t reg; |
|
|
|
#if defined(WM_DEBUG) && defined(WM_DEBUG_DEFAULT) |
|
sc->sc_debug = WM_DEBUG_DEFAULT; |
|
#endif |
sc->sc_dev = self; |
sc->sc_dev = self; |
callout_init(&sc->sc_tick_ch, WM_CALLOUT_FLAGS); |
callout_init(&sc->sc_tick_ch, WM_CALLOUT_FLAGS); |
sc->sc_core_stopping = false; |
sc->sc_core_stopping = false; |
Line 1949 wm_attach(device_t parent, device_t self |
|
Line 2014 wm_attach(device_t parent, device_t self |
|
* this driver) to use it for normal operation, though it is |
* this driver) to use it for normal operation, though it is |
* required to work around bugs in some chip versions. |
* required to work around bugs in some chip versions. |
*/ |
*/ |
if (sc->sc_type >= WM_T_82544) { |
switch (sc->sc_type) { |
|
case WM_T_82544: |
|
case WM_T_82541: |
|
case WM_T_82541_2: |
|
case WM_T_82547: |
|
case WM_T_82547_2: |
/* First we have to find the I/O BAR. */ |
/* First we have to find the I/O BAR. */ |
for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) { |
for (i = PCI_MAPREG_START; i < PCI_MAPREG_END; i += 4) { |
memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, i); |
memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, i); |
Line 1982 wm_attach(device_t parent, device_t self |
|
Line 2052 wm_attach(device_t parent, device_t self |
|
aprint_error_dev(sc->sc_dev, |
aprint_error_dev(sc->sc_dev, |
"WARNING: unable to map I/O space\n"); |
"WARNING: unable to map I/O space\n"); |
} |
} |
|
break; |
|
default: |
|
break; |
} |
} |
|
|
/* Enable bus mastering. Disable MWI on the i82542 2.0. */ |
/* Enable bus mastering. Disable MWI on the i82542 2.0. */ |
Line 3220 wm_resume(device_t self, const pmf_qual_ |
|
Line 3292 wm_resume(device_t self, const pmf_qual_ |
|
if (sc->sc_type >= WM_T_PCH2) |
if (sc->sc_type >= WM_T_PCH2) |
wm_resume_workarounds_pchlan(sc); |
wm_resume_workarounds_pchlan(sc); |
if ((ifp->if_flags & IFF_UP) == 0) { |
if ((ifp->if_flags & IFF_UP) == 0) { |
|
/* >= PCH_SPT hardware workaround before reset. */ |
|
if (sc->sc_type >= WM_T_PCH_SPT) |
|
wm_flush_desc_rings(sc); |
|
|
wm_reset(sc); |
wm_reset(sc); |
/* Non-AMT based hardware can now take control from firmware */ |
/* Non-AMT based hardware can now take control from firmware */ |
if ((sc->sc_flags & WM_F_HAS_AMT) == 0) |
if ((sc->sc_flags & WM_F_HAS_AMT) == 0) |
Line 3420 wm_ifflags_cb(struct ethercom *ec) |
|
Line 3496 wm_ifflags_cb(struct ethercom *ec) |
|
bool needreset = false; |
bool needreset = false; |
int rc = 0; |
int rc = 0; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
WM_CORE_LOCK(sc); |
WM_CORE_LOCK(sc); |
|
|
wm_phy_need_linkdown_discard(struct wm_softc *sc) |
wm_phy_need_linkdown_discard(struct wm_softc *sc) |
{ |
{ |
|
|
switch(sc->sc_phytype) { |
switch (sc->sc_phytype) { |
case WMPHY_82577: /* ihphy */ |
case WMPHY_82577: /* ihphy */ |
case WMPHY_82578: /* atphy */ |
case WMPHY_82578: /* atphy */ |
case WMPHY_82579: /* ihphy */ |
case WMPHY_82579: /* ihphy */ |
Line 3519 wm_ioctl(struct ifnet *ifp, u_long cmd, |
|
Line 3595 wm_ioctl(struct ifnet *ifp, u_long cmd, |
|
struct sockaddr_dl *sdl; |
struct sockaddr_dl *sdl; |
int s, error; |
int s, error; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
#ifndef WM_MPSAFE |
#ifndef WM_MPSAFE |
Line 3869 wm_set_filter(struct wm_softc *sc) |
|
Line 3945 wm_set_filter(struct wm_softc *sc) |
|
uint32_t hash, reg, bit; |
uint32_t hash, reg, bit; |
int i, size, ralmax, rv; |
int i, size, ralmax, rv; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->sc_type >= WM_T_82544) |
if (sc->sc_type >= WM_T_82544) |
|
|
wm_set_vlan(struct wm_softc *sc) |
wm_set_vlan(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* Deal with VLAN enables. */ |
/* Deal with VLAN enables. */ |
Line 4099 wm_lan_init_done(struct wm_softc *sc) |
|
Line 4175 wm_lan_init_done(struct wm_softc *sc) |
|
uint32_t reg = 0; |
uint32_t reg = 0; |
int i; |
int i; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* Wait for eeprom to reload */ |
/* Wait for eeprom to reload */ |
Line 4138 wm_get_cfg_done(struct wm_softc *sc) |
|
Line 4214 wm_get_cfg_done(struct wm_softc *sc) |
|
uint32_t reg; |
uint32_t reg; |
int i; |
int i; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* Wait for eeprom to reload */ |
/* Wait for eeprom to reload */ |
Line 4185 wm_get_cfg_done(struct wm_softc *sc) |
|
Line 4261 wm_get_cfg_done(struct wm_softc *sc) |
|
delay(1000); |
delay(1000); |
} |
} |
if (i >= WM_PHY_CFG_TIMEOUT) |
if (i >= WM_PHY_CFG_TIMEOUT) |
DPRINTF(WM_DEBUG_GMII, ("%s: %s failed\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: %s failed\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
break; |
break; |
case WM_T_ICH8: |
case WM_T_ICH8: |
Line 4282 wm_write_smbus_addr(struct wm_softc *sc) |
|
Line 4358 wm_write_smbus_addr(struct wm_softc *sc) |
|
uint16_t phy_data; |
uint16_t phy_data; |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
KASSERT(CSR_READ(sc, WMREG_EXTCNFCTR) & EXTCNFCTR_MDIO_SW_OWNERSHIP); |
KASSERT(CSR_READ(sc, WMREG_EXTCNFCTR) & EXTCNFCTR_MDIO_SW_OWNERSHIP); |
|
|
Line 4307 wm_write_smbus_addr(struct wm_softc *sc) |
|
Line 4383 wm_write_smbus_addr(struct wm_softc *sc) |
|
phy_data |= __SHIFTIN((freq & 0x02) != 0, |
phy_data |= __SHIFTIN((freq & 0x02) != 0, |
HV_SMB_ADDR_FREQ_HIGH); |
HV_SMB_ADDR_FREQ_HIGH); |
} else |
} else |
DPRINTF(WM_DEBUG_INIT, |
DPRINTF(sc, WM_DEBUG_INIT, |
("%s: %s Unsupported SMB frequency in PHY\n", |
("%s: %s Unsupported SMB frequency in PHY\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
} |
} |
Line 4323 wm_init_lcd_from_nvm(struct wm_softc *sc |
|
Line 4399 wm_init_lcd_from_nvm(struct wm_softc *sc |
|
uint16_t phy_page = 0; |
uint16_t phy_page = 0; |
int rv = 0; |
int rv = 0; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
switch (sc->sc_type) { |
switch (sc->sc_type) { |
Line 4365 wm_init_lcd_from_nvm(struct wm_softc *sc |
|
Line 4441 wm_init_lcd_from_nvm(struct wm_softc *sc |
|
&& ((extcnfctr & EXTCNFCTR_PCIE_WRITE_ENABLE) != 0)) |
&& ((extcnfctr & EXTCNFCTR_PCIE_WRITE_ENABLE) != 0)) |
goto release; |
goto release; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s: Configure LCD by software\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s: Configure LCD by software\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
/* word_addr is in DWORD */ |
/* word_addr is in DWORD */ |
word_addr = __SHIFTOUT(extcnfctr, EXTCNFCTR_EXT_CNF_POINTER) << 1; |
word_addr = __SHIFTOUT(extcnfctr, EXTCNFCTR_EXT_CNF_POINTER) << 1; |
Line 4383 wm_init_lcd_from_nvm(struct wm_softc *sc |
|
Line 4459 wm_init_lcd_from_nvm(struct wm_softc *sc |
|
* LCD Write Enable bits are set in the NVM. When both NVM bits |
* LCD Write Enable bits are set in the NVM. When both NVM bits |
* are cleared, SW will configure them instead. |
* are cleared, SW will configure them instead. |
*/ |
*/ |
DPRINTF(WM_DEBUG_INIT, ("%s: %s: Configure SMBus and LED\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s: Configure SMBus and LED\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
if ((rv = wm_write_smbus_addr(sc)) != 0) |
if ((rv = wm_write_smbus_addr(sc)) != 0) |
goto release; |
goto release; |
Line 4494 wm_initialize_hardware_bits(struct wm_so |
|
Line 4570 wm_initialize_hardware_bits(struct wm_so |
|
{ |
{ |
uint32_t tarc0, tarc1, reg; |
uint32_t tarc0, tarc1, reg; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* For 82571 variant, 80003 and ICHs */ |
/* For 82571 variant, 80003 and ICHs */ |
Line 4755 wm_reset_phy(struct wm_softc *sc) |
|
Line 4831 wm_reset_phy(struct wm_softc *sc) |
|
{ |
{ |
uint32_t reg; |
uint32_t reg; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
if (wm_phy_resetisblocked(sc)) |
if (wm_phy_resetisblocked(sc)) |
return -1; |
return -1; |
Line 4782 wm_reset_phy(struct wm_softc *sc) |
|
Line 4858 wm_reset_phy(struct wm_softc *sc) |
|
} |
} |
|
|
/* |
/* |
* Only used by WM_T_PCH_SPT which does not use multiqueue, |
* wm_flush_desc_rings - remove all descriptors from the descriptor rings. |
* so it is enough to check sc->sc_queue[0] only. |
* |
|
* In i219, the descriptor rings must be emptied before resetting the HW |
|
* or before changing the device state to D3 during runtime (runtime PM). |
|
* |
|
* Failure to do this will cause the HW to enter a unit hang state which can |
|
* only be released by PCI reset on the device. |
|
* |
|
* I219 does not use multiqueue, so it is enough to check sc->sc_queue[0] only. |
*/ |
*/ |
static void |
static void |
wm_flush_desc_rings(struct wm_softc *sc) |
wm_flush_desc_rings(struct wm_softc *sc) |
Line 4805 wm_flush_desc_rings(struct wm_softc *sc) |
|
Line 4888 wm_flush_desc_rings(struct wm_softc *sc) |
|
if (((preg & DESCRING_STATUS_FLUSH_REQ) == 0) || (reg == 0)) |
if (((preg & DESCRING_STATUS_FLUSH_REQ) == 0) || (reg == 0)) |
return; |
return; |
|
|
/* TX */ |
/* |
device_printf(sc->sc_dev, "Need TX flush (reg = %08x, len = %u)\n", |
* Remove all descriptors from the tx_ring. |
preg, reg); |
* |
|
* We want to clear all pending descriptors from the TX ring. Zeroing |
|
* happens when the HW reads the regs. We assign the ring itself as |
|
* the data of the next descriptor. We don't care about the data we are |
|
* about to reset the HW. |
|
*/ |
|
#ifdef WM_DEBUG |
|
device_printf(sc->sc_dev, "Need TX flush (reg = %08x)\n", preg); |
|
#endif |
reg = CSR_READ(sc, WMREG_TCTL); |
reg = CSR_READ(sc, WMREG_TCTL); |
CSR_WRITE(sc, WMREG_TCTL, reg | TCTL_EN); |
CSR_WRITE(sc, WMREG_TCTL, reg | TCTL_EN); |
|
|
txq = &sc->sc_queue[0].wmq_txq; |
txq = &sc->sc_queue[0].wmq_txq; |
nexttx = txq->txq_next; |
nexttx = txq->txq_next; |
txd = &txq->txq_descs[nexttx]; |
txd = &txq->txq_descs[nexttx]; |
wm_set_dma_addr(&txd->wtx_addr, WM_CDTXADDR(txq, nexttx)); |
wm_set_dma_addr(&txd->wtx_addr, txq->txq_desc_dma); |
txd->wtx_cmdlen = htole32(WTX_CMD_IFCS | 512); |
txd->wtx_cmdlen = htole32(WTX_CMD_IFCS | 512); |
txd->wtx_fields.wtxu_status = 0; |
txd->wtx_fields.wtxu_status = 0; |
txd->wtx_fields.wtxu_options = 0; |
txd->wtx_fields.wtxu_options = 0; |
Line 4833 wm_flush_desc_rings(struct wm_softc *sc) |
|
Line 4924 wm_flush_desc_rings(struct wm_softc *sc) |
|
if ((preg & DESCRING_STATUS_FLUSH_REQ) == 0) |
if ((preg & DESCRING_STATUS_FLUSH_REQ) == 0) |
return; |
return; |
|
|
/* RX */ |
/* |
|
* Mark all descriptors in the RX ring as consumed and disable the |
|
* rx ring. |
|
*/ |
|
#ifdef WM_DEBUG |
device_printf(sc->sc_dev, "Need RX flush (reg = %08x)\n", preg); |
device_printf(sc->sc_dev, "Need RX flush (reg = %08x)\n", preg); |
|
#endif |
rctl = CSR_READ(sc, WMREG_RCTL); |
rctl = CSR_READ(sc, WMREG_RCTL); |
CSR_WRITE(sc, WMREG_RCTL, rctl & ~RCTL_EN); |
CSR_WRITE(sc, WMREG_RCTL, rctl & ~RCTL_EN); |
CSR_WRITE_FLUSH(sc); |
CSR_WRITE_FLUSH(sc); |
Line 4872 wm_reset(struct wm_softc *sc) |
|
Line 4968 wm_reset(struct wm_softc *sc) |
|
uint16_t kmreg; |
uint16_t kmreg; |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
KASSERT(sc->sc_type != 0); |
KASSERT(sc->sc_type != 0); |
|
|
|
|
wm_init_sysctls(struct wm_softc *sc) |
wm_init_sysctls(struct wm_softc *sc) |
{ |
{ |
struct sysctllog **log; |
struct sysctllog **log; |
const struct sysctlnode *rnode, *cnode; |
const struct sysctlnode *rnode, *qnode, *cnode; |
int rv; |
int i, rv; |
const char *dvname; |
const char *dvname; |
|
|
log = &sc->sc_sysctllog; |
log = &sc->sc_sysctllog; |
Line 5884 wm_init_sysctls(struct wm_softc *sc) |
|
Line 5980 wm_init_sysctls(struct wm_softc *sc) |
|
if (rv != 0) |
if (rv != 0) |
goto teardown; |
goto teardown; |
|
|
|
for (i = 0; i < sc->sc_nqueues; i++) { |
|
struct wm_queue *wmq = &sc->sc_queue[i]; |
|
struct wm_txqueue *txq = &wmq->wmq_txq; |
|
struct wm_rxqueue *rxq = &wmq->wmq_rxq; |
|
|
|
snprintf(sc->sc_queue[i].sysctlname, |
|
sizeof(sc->sc_queue[i].sysctlname), "q%d", i); |
|
|
|
if (sysctl_createv(log, 0, &rnode, &qnode, |
|
0, CTLTYPE_NODE, |
|
sc->sc_queue[i].sysctlname, SYSCTL_DESCR("Queue Name"), |
|
NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL) != 0) |
|
break; |
|
if (sysctl_createv(log, 0, &qnode, &cnode, |
|
CTLFLAG_READONLY, CTLTYPE_INT, |
|
"txq_free", SYSCTL_DESCR("TX queue free"), |
|
NULL, 0, &txq->txq_free, |
|
0, CTL_CREATE, CTL_EOL) != 0) |
|
break; |
|
if (sysctl_createv(log, 0, &qnode, &cnode, |
|
CTLFLAG_READONLY, CTLTYPE_INT, |
|
"txq_next", SYSCTL_DESCR("TX queue next"), |
|
NULL, 0, &txq->txq_next, |
|
0, CTL_CREATE, CTL_EOL) != 0) |
|
break; |
|
|
|
if (sysctl_createv(log, 0, &qnode, &cnode, |
|
CTLFLAG_READONLY, CTLTYPE_INT, |
|
"rxq_ptr", SYSCTL_DESCR("RX queue pointer"), |
|
NULL, 0, &rxq->rxq_ptr, |
|
0, CTL_CREATE, CTL_EOL) != 0) |
|
break; |
|
} |
|
|
|
#ifdef WM_DEBUG |
|
rv = sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE, |
|
CTLTYPE_INT, "debug_flags", |
|
SYSCTL_DESCR( |
|
"Debug flags:\n" \ |
|
"\t0x01 LINK\n" \ |
|
"\t0x02 TX\n" \ |
|
"\t0x04 RX\n" \ |
|
"\t0x08 GMII\n" \ |
|
"\t0x10 MANAGE\n" \ |
|
"\t0x20 NVM\n" \ |
|
"\t0x40 INIT\n" \ |
|
"\t0x80 LOCK"), |
|
wm_sysctl_debug, 0, (void *)sc, 0, CTL_CREATE, CTL_EOL); |
|
if (rv != 0) |
|
goto teardown; |
|
#endif |
|
|
return; |
return; |
|
|
teardown: |
teardown: |
Line 5920 wm_init_locked(struct ifnet *ifp) |
|
Line 6068 wm_init_locked(struct ifnet *ifp) |
|
int i, j, trynum, error = 0; |
int i, j, trynum, error = 0; |
uint32_t reg, sfp_mask = 0; |
uint32_t reg, sfp_mask = 0; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
KASSERT(WM_CORE_LOCKED(sc)); |
KASSERT(WM_CORE_LOCKED(sc)); |
|
|
Line 5951 wm_init_locked(struct ifnet *ifp) |
|
Line 6099 wm_init_locked(struct ifnet *ifp) |
|
ifp->if_collisions += CSR_READ(sc, WMREG_COLC); |
ifp->if_collisions += CSR_READ(sc, WMREG_COLC); |
ifp->if_ierrors += CSR_READ(sc, WMREG_RXERRC); |
ifp->if_ierrors += CSR_READ(sc, WMREG_RXERRC); |
|
|
/* PCH_SPT hardware workaround */ |
/* >= PCH_SPT hardware workaround before reset. */ |
if (sc->sc_type == WM_T_PCH_SPT) |
if (sc->sc_type >= WM_T_PCH_SPT) |
wm_flush_desc_rings(sc); |
wm_flush_desc_rings(sc); |
|
|
/* Reset the chip to a known state. */ |
/* Reset the chip to a known state. */ |
Line 6523 wm_stop_locked(struct ifnet *ifp, int di |
|
Line 6671 wm_stop_locked(struct ifnet *ifp, int di |
|
struct wm_txsoft *txs; |
struct wm_txsoft *txs; |
int i, qidx; |
int i, qidx; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
KASSERT(WM_CORE_LOCKED(sc)); |
KASSERT(WM_CORE_LOCKED(sc)); |
|
|
Line 6571 wm_stop_locked(struct ifnet *ifp, int di |
|
Line 6719 wm_stop_locked(struct ifnet *ifp, int di |
|
for (qidx = 0; qidx < sc->sc_nqueues; qidx++) { |
for (qidx = 0; qidx < sc->sc_nqueues; qidx++) { |
struct wm_queue *wmq = &sc->sc_queue[qidx]; |
struct wm_queue *wmq = &sc->sc_queue[qidx]; |
struct wm_txqueue *txq = &wmq->wmq_txq; |
struct wm_txqueue *txq = &wmq->wmq_txq; |
|
struct mbuf *m; |
|
|
mutex_enter(txq->txq_lock); |
mutex_enter(txq->txq_lock); |
txq->txq_sending = false; /* Ensure watchdog disabled */ |
txq->txq_sending = false; /* Ensure watchdog disabled */ |
for (i = 0; i < WM_TXQUEUELEN(txq); i++) { |
for (i = 0; i < WM_TXQUEUELEN(txq); i++) { |
Line 6581 wm_stop_locked(struct ifnet *ifp, int di |
|
Line 6731 wm_stop_locked(struct ifnet *ifp, int di |
|
txs->txs_mbuf = NULL; |
txs->txs_mbuf = NULL; |
} |
} |
} |
} |
|
/* Drain txq_interq */ |
|
while ((m = pcq_get(txq->txq_interq)) != NULL) |
|
m_freem(m); |
mutex_exit(txq->txq_lock); |
mutex_exit(txq->txq_lock); |
} |
} |
|
|
Line 7198 wm_init_tx_regs(struct wm_softc *sc, str |
|
Line 7351 wm_init_tx_regs(struct wm_softc *sc, str |
|
struct wm_txqueue *txq) |
struct wm_txqueue *txq) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
KASSERT(mutex_owned(txq->txq_lock)); |
KASSERT(mutex_owned(txq->txq_lock)); |
|
|
Line 7407 wm_init_txrx_queues(struct wm_softc *sc) |
|
Line 7560 wm_init_txrx_queues(struct wm_softc *sc) |
|
{ |
{ |
int i, error = 0; |
int i, error = 0; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
for (i = 0; i < sc->sc_nqueues; i++) { |
for (i = 0; i < sc->sc_nqueues; i++) { |
Line 7478 wm_tx_offload(struct wm_softc *sc, struc |
|
Line 7631 wm_tx_offload(struct wm_softc *sc, struc |
|
|
|
default: |
default: |
/* Don't support this protocol or encapsulation. */ |
/* Don't support this protocol or encapsulation. */ |
txq->txq_last_hw_cmd = txq->txq_last_hw_fields = 0; |
txq->txq_last_hw_cmd = txq->txq_last_hw_fields = 0; |
txq->txq_last_hw_ipcs = 0; |
txq->txq_last_hw_ipcs = 0; |
txq->txq_last_hw_tucs = 0; |
txq->txq_last_hw_tucs = 0; |
*fieldsp = 0; |
*fieldsp = 0; |
*cmdp = 0; |
*cmdp = 0; |
return; |
return; |
Line 7636 wm_tx_offload(struct wm_softc *sc, struc |
|
Line 7789 wm_tx_offload(struct wm_softc *sc, struc |
|
*/ |
*/ |
if (sc->sc_nqueues < 2) { |
if (sc->sc_nqueues < 2) { |
/* |
/* |
* |
* Setting up new checksum offload context for every |
* Setting up new checksum offload context for every |
|
* frames takes a lot of processing time for hardware. |
* frames takes a lot of processing time for hardware. |
* This also reduces performance a lot for small sized |
* This also reduces performance a lot for small sized |
* frames so avoid it if driver can use previously |
* frames so avoid it if driver can use previously |
Line 7647 wm_tx_offload(struct wm_softc *sc, struc |
|
Line 7799 wm_tx_offload(struct wm_softc *sc, struc |
|
* checking whether a frame has the same IP/TCP structure is |
* checking whether a frame has the same IP/TCP structure is |
* hard thing so just ignore that and always restablish a |
* hard thing so just ignore that and always restablish a |
* new TSO context. |
* new TSO context. |
*/ |
*/ |
if ((m0->m_pkthdr.csum_flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6)) |
if ((m0->m_pkthdr.csum_flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6)) |
== 0) { |
== 0) { |
if (txq->txq_last_hw_cmd == cmd && |
if (txq->txq_last_hw_cmd == cmd && |
Line 7659 wm_tx_offload(struct wm_softc *sc, struc |
|
Line 7811 wm_tx_offload(struct wm_softc *sc, struc |
|
} |
} |
} |
} |
|
|
txq->txq_last_hw_cmd = cmd; |
txq->txq_last_hw_cmd = cmd; |
txq->txq_last_hw_fields = fields; |
txq->txq_last_hw_fields = fields; |
txq->txq_last_hw_ipcs = (ipcs & 0xffff); |
txq->txq_last_hw_ipcs = (ipcs & 0xffff); |
txq->txq_last_hw_tucs = (tucs & 0xffff); |
txq->txq_last_hw_tucs = (tucs & 0xffff); |
} |
} |
|
|
Line 7828 wm_send_common_locked(struct ifnet *ifp, |
|
Line 7980 wm_send_common_locked(struct ifnet *ifp, |
|
if (txq->txq_sfree < WM_TXQUEUE_GC(txq)) { |
if (txq->txq_sfree < WM_TXQUEUE_GC(txq)) { |
wm_txeof(txq, UINT_MAX); |
wm_txeof(txq, UINT_MAX); |
if (txq->txq_sfree == 0) { |
if (txq->txq_sfree == 0) { |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: no free job descriptors\n", |
("%s: TX: no free job descriptors\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
WM_Q_EVCNT_INCR(txq, txsstall); |
WM_Q_EVCNT_INCR(txq, txsstall); |
Line 7844 wm_send_common_locked(struct ifnet *ifp, |
|
Line 7996 wm_send_common_locked(struct ifnet *ifp, |
|
if (m0 == NULL) |
if (m0 == NULL) |
break; |
break; |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: have packet to transmit: %p\n", |
("%s: TX: have packet to transmit: %p\n", |
device_xname(sc->sc_dev), m0)); |
device_xname(sc->sc_dev), m0)); |
|
|
|
|
continue; |
continue; |
} |
} |
/* Short on resources, just stop for now. */ |
/* Short on resources, just stop for now. */ |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: dmamap load failed: %d\n", |
("%s: TX: dmamap load failed: %d\n", |
device_xname(sc->sc_dev), error)); |
device_xname(sc->sc_dev), error)); |
break; |
break; |
|
|
* pack on the queue, and punt. Notify the upper |
* pack on the queue, and punt. Notify the upper |
* layer that there are no more slots left. |
* layer that there are no more slots left. |
*/ |
*/ |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: need %d (%d) descriptors, have %d\n", |
("%s: TX: need %d (%d) descriptors, have %d\n", |
device_xname(sc->sc_dev), dmamap->dm_nsegs, |
device_xname(sc->sc_dev), dmamap->dm_nsegs, |
segs_needed, txq->txq_free - 1)); |
segs_needed, txq->txq_free - 1)); |
|
|
*/ |
*/ |
if (sc->sc_type == WM_T_82547 && |
if (sc->sc_type == WM_T_82547 && |
wm_82547_txfifo_bugchk(sc, m0)) { |
wm_82547_txfifo_bugchk(sc, m0)) { |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: 82547 Tx FIFO bug detected\n", |
("%s: TX: 82547 Tx FIFO bug detected\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
if (!is_transmit) |
if (!is_transmit) |
|
|
|
|
/* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. */ |
/* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. */ |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: packet has %d (%d) DMA segments\n", |
("%s: TX: packet has %d (%d) DMA segments\n", |
device_xname(sc->sc_dev), dmamap->dm_nsegs, segs_needed)); |
device_xname(sc->sc_dev), dmamap->dm_nsegs, segs_needed)); |
|
|
|
|
M_CSUM_TCPv6 | M_CSUM_UDPv6)) { |
M_CSUM_TCPv6 | M_CSUM_UDPv6)) { |
wm_tx_offload(sc, txq, txs, &cksumcmd, &cksumfields); |
wm_tx_offload(sc, txq, txs, &cksumcmd, &cksumfields); |
} else { |
} else { |
txq->txq_last_hw_cmd = txq->txq_last_hw_fields = 0; |
txq->txq_last_hw_cmd = txq->txq_last_hw_fields = 0; |
txq->txq_last_hw_ipcs = txq->txq_last_hw_tucs = 0; |
txq->txq_last_hw_ipcs = txq->txq_last_hw_tucs = 0; |
cksumcmd = 0; |
cksumcmd = 0; |
cksumfields = 0; |
cksumfields = 0; |
} |
} |
|
|
txq->txq_descs[nexttx].wtx_fields.wtxu_vlan =0; |
txq->txq_descs[nexttx].wtx_fields.wtxu_vlan =0; |
lasttx = nexttx; |
lasttx = nexttx; |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: desc %d: low %#" PRIx64 ", " |
("%s: TX: desc %d: low %#" PRIx64 ", " |
"len %#04zx\n", |
"len %#04zx\n", |
device_xname(sc->sc_dev), nexttx, |
device_xname(sc->sc_dev), nexttx, |
|
|
|
|
txs->txs_lastdesc = lasttx; |
txs->txs_lastdesc = lasttx; |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: desc %d: cmdlen 0x%08x\n", |
("%s: TX: desc %d: cmdlen 0x%08x\n", |
device_xname(sc->sc_dev), |
device_xname(sc->sc_dev), |
lasttx, le32toh(txq->txq_descs[lasttx].wtx_cmdlen))); |
lasttx, le32toh(txq->txq_descs[lasttx].wtx_cmdlen))); |
|
|
/* Give the packet to the chip. */ |
/* Give the packet to the chip. */ |
CSR_WRITE(sc, txq->txq_tdt_reg, nexttx); |
CSR_WRITE(sc, txq->txq_tdt_reg, nexttx); |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: TDT -> %d\n", device_xname(sc->sc_dev), nexttx)); |
("%s: TX: TDT -> %d\n", device_xname(sc->sc_dev), nexttx)); |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: finished transmitting packet, job %d\n", |
("%s: TX: finished transmitting packet, job %d\n", |
device_xname(sc->sc_dev), txq->txq_snext)); |
device_xname(sc->sc_dev), txq->txq_snext)); |
|
|
|
|
ifp->if_flags |= IFF_OACTIVE; |
ifp->if_flags |= IFF_OACTIVE; |
txq->txq_flags |= WM_TXQ_NO_SPACE; |
txq->txq_flags |= WM_TXQ_NO_SPACE; |
WM_Q_EVCNT_INCR(txq, descdrop); |
WM_Q_EVCNT_INCR(txq, descdrop); |
DPRINTF(WM_DEBUG_TX, ("%s: TX: error after IFQ_DEQUEUE\n", |
DPRINTF(sc, WM_DEBUG_TX, ("%s: TX: error after IFQ_DEQUEUE\n", |
__func__)); |
__func__)); |
m_freem(m0); |
m_freem(m0); |
} |
} |
Line 8312 wm_nq_tx_offload(struct wm_softc *sc, st |
|
Line 8464 wm_nq_tx_offload(struct wm_softc *sc, st |
|
txq->txq_nq_descs[txq->txq_next].nqrx_ctx.nqtxc_mssidx = |
txq->txq_nq_descs[txq->txq_next].nqrx_ctx.nqtxc_mssidx = |
htole32(mssidx); |
htole32(mssidx); |
wm_cdtxsync(txq, txq->txq_next, 1, BUS_DMASYNC_PREWRITE); |
wm_cdtxsync(txq, txq->txq_next, 1, BUS_DMASYNC_PREWRITE); |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: context desc %d 0x%08x%08x\n", device_xname(sc->sc_dev), |
("%s: TX: context desc %d 0x%08x%08x\n", device_xname(sc->sc_dev), |
txq->txq_next, 0, vl_len)); |
txq->txq_next, 0, vl_len)); |
DPRINTF(WM_DEBUG_TX, ("\t0x%08x%08x\n", mssidx, cmdc)); |
DPRINTF(sc, WM_DEBUG_TX, ("\t0x%08x%08x\n", mssidx, cmdc)); |
txq->txq_next = WM_NEXTTX(txq, txq->txq_next); |
txq->txq_next = WM_NEXTTX(txq, txq->txq_next); |
txs->txs_ndesc++; |
txs->txs_ndesc++; |
} |
} |
Line 8453 wm_nq_send_common_locked(struct ifnet *i |
|
Line 8605 wm_nq_send_common_locked(struct ifnet *i |
|
if (txq->txq_sfree < WM_TXQUEUE_GC(txq)) { |
if (txq->txq_sfree < WM_TXQUEUE_GC(txq)) { |
wm_txeof(txq, UINT_MAX); |
wm_txeof(txq, UINT_MAX); |
if (txq->txq_sfree == 0) { |
if (txq->txq_sfree == 0) { |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: no free job descriptors\n", |
("%s: TX: no free job descriptors\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
WM_Q_EVCNT_INCR(txq, txsstall); |
WM_Q_EVCNT_INCR(txq, txsstall); |
Line 8469 wm_nq_send_common_locked(struct ifnet *i |
|
Line 8621 wm_nq_send_common_locked(struct ifnet *i |
|
if (m0 == NULL) |
if (m0 == NULL) |
break; |
break; |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: have packet to transmit: %p\n", |
("%s: TX: have packet to transmit: %p\n", |
device_xname(sc->sc_dev), m0)); |
device_xname(sc->sc_dev), m0)); |
|
|
|
|
continue; |
continue; |
} |
} |
/* Short on resources, just stop for now. */ |
/* Short on resources, just stop for now. */ |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: dmamap load failed: %d\n", |
("%s: TX: dmamap load failed: %d\n", |
device_xname(sc->sc_dev), error)); |
device_xname(sc->sc_dev), error)); |
break; |
break; |
|
|
* pack on the queue, and punt. Notify the upper |
* pack on the queue, and punt. Notify the upper |
* layer that there are no more slots left. |
* layer that there are no more slots left. |
*/ |
*/ |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: need %d (%d) descriptors, have %d\n", |
("%s: TX: need %d (%d) descriptors, have %d\n", |
device_xname(sc->sc_dev), dmamap->dm_nsegs, |
device_xname(sc->sc_dev), dmamap->dm_nsegs, |
segs_needed, txq->txq_free - 1)); |
segs_needed, txq->txq_free - 1)); |
|
|
|
|
/* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. */ |
/* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. */ |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: packet has %d (%d) DMA segments\n", |
("%s: TX: packet has %d (%d) DMA segments\n", |
device_xname(sc->sc_dev), dmamap->dm_nsegs, segs_needed)); |
device_xname(sc->sc_dev), dmamap->dm_nsegs, segs_needed)); |
|
|
|
|
htole32(dmamap->dm_segs[0].ds_len | cmdlen); |
htole32(dmamap->dm_segs[0].ds_len | cmdlen); |
txq->txq_nq_descs[nexttx].nqtx_data.nqtxd_fields = |
txq->txq_nq_descs[nexttx].nqtx_data.nqtxd_fields = |
htole32(fields); |
htole32(fields); |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: adv data desc %d 0x%" PRIx64 "\n", |
("%s: TX: adv data desc %d 0x%" PRIx64 "\n", |
device_xname(sc->sc_dev), nexttx, |
device_xname(sc->sc_dev), nexttx, |
(uint64_t)dmamap->dm_segs[0].ds_addr)); |
(uint64_t)dmamap->dm_segs[0].ds_addr)); |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("\t 0x%08x%08x\n", fields, |
("\t 0x%08x%08x\n", fields, |
(uint32_t)dmamap->dm_segs[0].ds_len | cmdlen)); |
(uint32_t)dmamap->dm_segs[0].ds_len | cmdlen)); |
dcmdlen = NQTX_DTYP_D | NQTX_CMD_DEXT; |
dcmdlen = NQTX_DTYP_D | NQTX_CMD_DEXT; |
|
|
txq->txq_nq_descs[nexttx].nqtx_data.nqtxd_fields = 0; |
txq->txq_nq_descs[nexttx].nqtx_data.nqtxd_fields = 0; |
lasttx = nexttx; |
lasttx = nexttx; |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: desc %d: %#" PRIx64 ", len %#04zx\n", |
("%s: TX: desc %d: %#" PRIx64 ", len %#04zx\n", |
device_xname(sc->sc_dev), nexttx, |
device_xname(sc->sc_dev), nexttx, |
(uint64_t)dmamap->dm_segs[seg].ds_addr, |
(uint64_t)dmamap->dm_segs[seg].ds_addr, |
|
|
|
|
txs->txs_lastdesc = lasttx; |
txs->txs_lastdesc = lasttx; |
|
|
DPRINTF(WM_DEBUG_TX, ("%s: TX: desc %d: cmdlen 0x%08x\n", |
DPRINTF(sc, WM_DEBUG_TX, ("%s: TX: desc %d: cmdlen 0x%08x\n", |
device_xname(sc->sc_dev), |
device_xname(sc->sc_dev), |
lasttx, le32toh(txq->txq_descs[lasttx].wtx_cmdlen))); |
lasttx, le32toh(txq->txq_descs[lasttx].wtx_cmdlen))); |
|
|
|
|
CSR_WRITE(sc, txq->txq_tdt_reg, nexttx); |
CSR_WRITE(sc, txq->txq_tdt_reg, nexttx); |
sent = true; |
sent = true; |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: TDT -> %d\n", device_xname(sc->sc_dev), nexttx)); |
("%s: TX: TDT -> %d\n", device_xname(sc->sc_dev), nexttx)); |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: finished transmitting packet, job %d\n", |
("%s: TX: finished transmitting packet, job %d\n", |
device_xname(sc->sc_dev), txq->txq_snext)); |
device_xname(sc->sc_dev), txq->txq_snext)); |
|
|
|
|
ifp->if_flags |= IFF_OACTIVE; |
ifp->if_flags |= IFF_OACTIVE; |
txq->txq_flags |= WM_TXQ_NO_SPACE; |
txq->txq_flags |= WM_TXQ_NO_SPACE; |
WM_Q_EVCNT_INCR(txq, descdrop); |
WM_Q_EVCNT_INCR(txq, descdrop); |
DPRINTF(WM_DEBUG_TX, ("%s: TX: error after IFQ_DEQUEUE\n", |
DPRINTF(sc, WM_DEBUG_TX, ("%s: TX: error after IFQ_DEQUEUE\n", |
__func__)); |
__func__)); |
m_freem(m0); |
m_freem(m0); |
} |
} |
Line 8777 wm_txeof(struct wm_txqueue *txq, u_int l |
|
Line 8929 wm_txeof(struct wm_txqueue *txq, u_int l |
|
i = WM_NEXTTXS(txq, i), txq->txq_sfree++) { |
i = WM_NEXTTXS(txq, i), txq->txq_sfree++) { |
if (limit-- == 0) { |
if (limit-- == 0) { |
more = true; |
more = true; |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: loop limited, job %d is not processed\n", |
("%s: TX: loop limited, job %d is not processed\n", |
device_xname(sc->sc_dev), i)); |
device_xname(sc->sc_dev), i)); |
break; |
break; |
Line 8785 wm_txeof(struct wm_txqueue *txq, u_int l |
|
Line 8937 wm_txeof(struct wm_txqueue *txq, u_int l |
|
|
|
txs = &txq->txq_soft[i]; |
txs = &txq->txq_soft[i]; |
|
|
DPRINTF(WM_DEBUG_TX, ("%s: TX: checking job %d\n", |
DPRINTF(sc, WM_DEBUG_TX, ("%s: TX: checking job %d\n", |
device_xname(sc->sc_dev), i)); |
device_xname(sc->sc_dev), i)); |
|
|
wm_cdtxsync(txq, txs->txs_firstdesc, txs->txs_ndesc, |
wm_cdtxsync(txq, txs->txs_firstdesc, txs->txs_ndesc, |
Line 8800 wm_txeof(struct wm_txqueue *txq, u_int l |
|
Line 8952 wm_txeof(struct wm_txqueue *txq, u_int l |
|
} |
} |
|
|
count++; |
count++; |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: job %d done: descs %d..%d\n", |
("%s: TX: job %d done: descs %d..%d\n", |
device_xname(sc->sc_dev), i, txs->txs_firstdesc, |
device_xname(sc->sc_dev), i, txs->txs_firstdesc, |
txs->txs_lastdesc)); |
txs->txs_lastdesc)); |
Line 8856 wm_txeof(struct wm_txqueue *txq, u_int l |
|
Line 9008 wm_txeof(struct wm_txqueue *txq, u_int l |
|
|
|
/* Update the dirty transmit buffer pointer. */ |
/* Update the dirty transmit buffer pointer. */ |
txq->txq_sdirty = i; |
txq->txq_sdirty = i; |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: txsdirty -> %d\n", device_xname(sc->sc_dev), i)); |
("%s: TX: txsdirty -> %d\n", device_xname(sc->sc_dev), i)); |
|
|
/* |
/* |
Line 9102 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9254 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
|
|
for (i = rxq->rxq_ptr;; i = WM_NEXTRX(i)) { |
for (i = rxq->rxq_ptr;; i = WM_NEXTRX(i)) { |
if (limit-- == 0) { |
if (limit-- == 0) { |
rxq->rxq_ptr = i; |
|
more = true; |
more = true; |
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: loop limited, descriptor %d is not processed\n", |
("%s: RX: loop limited, descriptor %d is not processed\n", |
device_xname(sc->sc_dev), i)); |
device_xname(sc->sc_dev), i)); |
break; |
break; |
Line 9112 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9263 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
|
|
rxs = &rxq->rxq_soft[i]; |
rxs = &rxq->rxq_soft[i]; |
|
|
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: checking descriptor %d\n", |
("%s: RX: checking descriptor %d\n", |
device_xname(sc->sc_dev), i)); |
device_xname(sc->sc_dev), i)); |
wm_cdrxsync(rxq, i, |
wm_cdrxsync(rxq, i, |
Line 9128 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9279 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
#endif |
#endif |
|
|
if (!wm_rxdesc_dd(rxq, i, status)) { |
if (!wm_rxdesc_dd(rxq, i, status)) { |
/* |
|
* Update the receive pointer holding rxq_lock |
|
* consistent with increment counter. |
|
*/ |
|
rxq->rxq_ptr = i; |
|
break; |
break; |
} |
} |
|
|
count++; |
count++; |
if (__predict_false(rxq->rxq_discard)) { |
if (__predict_false(rxq->rxq_discard)) { |
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: discarding contents of descriptor %d\n", |
("%s: RX: discarding contents of descriptor %d\n", |
device_xname(sc->sc_dev), i)); |
device_xname(sc->sc_dev), i)); |
wm_init_rxdesc(rxq, i); |
wm_init_rxdesc(rxq, i); |
if (wm_rxdesc_is_eop(rxq, status)) { |
if (wm_rxdesc_is_eop(rxq, status)) { |
/* Reset our state. */ |
/* Reset our state. */ |
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: resetting rxdiscard -> 0\n", |
("%s: RX: resetting rxdiscard -> 0\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
rxq->rxq_discard = 0; |
rxq->rxq_discard = 0; |
Line 9176 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9322 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
if (rxq->rxq_head != NULL) |
if (rxq->rxq_head != NULL) |
m_freem(rxq->rxq_head); |
m_freem(rxq->rxq_head); |
WM_RXCHAIN_RESET(rxq); |
WM_RXCHAIN_RESET(rxq); |
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: Rx buffer allocation failed, " |
("%s: RX: Rx buffer allocation failed, " |
"dropping packet%s\n", device_xname(sc->sc_dev), |
"dropping packet%s\n", device_xname(sc->sc_dev), |
rxq->rxq_discard ? " (discard)" : "")); |
rxq->rxq_discard ? " (discard)" : "")); |
Line 9185 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9331 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
|
|
m->m_len = len; |
m->m_len = len; |
rxq->rxq_len += len; |
rxq->rxq_len += len; |
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: buffer at %p len %d\n", |
("%s: RX: buffer at %p len %d\n", |
device_xname(sc->sc_dev), m->m_data, len)); |
device_xname(sc->sc_dev), m->m_data, len)); |
|
|
/* If this is not the end of the packet, keep looking. */ |
/* If this is not the end of the packet, keep looking. */ |
if (!wm_rxdesc_is_eop(rxq, status)) { |
if (!wm_rxdesc_is_eop(rxq, status)) { |
WM_RXCHAIN_LINK(rxq, m); |
WM_RXCHAIN_LINK(rxq, m); |
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: not yet EOP, rxlen -> %d\n", |
("%s: RX: not yet EOP, rxlen -> %d\n", |
device_xname(sc->sc_dev), rxq->rxq_len)); |
device_xname(sc->sc_dev), rxq->rxq_len)); |
continue; |
continue; |
Line 9200 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9346 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
|
|
/* |
/* |
* Okay, we have the entire packet now. The chip is |
* Okay, we have the entire packet now. The chip is |
* configured to include the FCS except I35[05], I21[01]. |
* configured to include the FCS except I35[04], I21[01]. |
* (not all chips can be configured to strip it), so we need |
* (not all chips can be configured to strip it), so we need |
* to trim it. Those chips have an eratta, the RCTL_SECRC bit |
* to trim it. Those chips have an eratta, the RCTL_SECRC bit |
* in RCTL register is always set, so we don't trim it. |
* in RCTL register is always set, so we don't trim it. |
Line 9227 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9373 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
|
|
WM_RXCHAIN_RESET(rxq); |
WM_RXCHAIN_RESET(rxq); |
|
|
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: have entire packet, len -> %d\n", |
("%s: RX: have entire packet, len -> %d\n", |
device_xname(sc->sc_dev), len)); |
device_xname(sc->sc_dev), len)); |
|
|
Line 9244 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9390 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
* TODO |
* TODO |
* should be save rsshash and rsstype to this mbuf. |
* should be save rsshash and rsstype to this mbuf. |
*/ |
*/ |
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: RSS type=%" PRIu8 ", RSS hash=%" PRIu32 "\n", |
("%s: RX: RSS type=%" PRIu8 ", RSS hash=%" PRIu32 "\n", |
device_xname(sc->sc_dev), rsstype, rsshash)); |
device_xname(sc->sc_dev), rsstype, rsshash)); |
|
|
Line 9257 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
Line 9403 wm_rxeof(struct wm_rxqueue *rxq, u_int l |
|
|
|
/* Set up checksum info for this packet. */ |
/* Set up checksum info for this packet. */ |
wm_rxdesc_ensure_checksum(rxq, status, errors, m); |
wm_rxdesc_ensure_checksum(rxq, status, errors, m); |
/* |
|
* Update the receive pointer holding rxq_lock consistent with |
|
* increment counter. |
|
*/ |
|
rxq->rxq_ptr = i; |
|
rxq->rxq_packets++; |
rxq->rxq_packets++; |
rxq->rxq_bytes += len; |
rxq->rxq_bytes += len; |
mutex_exit(rxq->rxq_lock); |
|
|
|
/* Pass it on. */ |
/* Pass it on. */ |
if_percpuq_enqueue(sc->sc_ipq, m); |
if_percpuq_enqueue(sc->sc_ipq, m); |
|
|
mutex_enter(rxq->rxq_lock); |
|
|
|
if (rxq->rxq_stopping) |
if (rxq->rxq_stopping) |
break; |
break; |
} |
} |
|
rxq->rxq_ptr = i; |
|
|
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: rxptr -> %d\n", device_xname(sc->sc_dev), i)); |
("%s: RX: rxptr -> %d\n", device_xname(sc->sc_dev), i)); |
|
|
return more; |
return more; |
Line 9296 wm_linkintr_gmii(struct wm_softc *sc, ui |
|
Line 9435 wm_linkintr_gmii(struct wm_softc *sc, ui |
|
|
|
KASSERT(WM_CORE_LOCKED(sc)); |
KASSERT(WM_CORE_LOCKED(sc)); |
|
|
DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(dev), |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s:\n", device_xname(dev), |
__func__)); |
__func__)); |
|
|
if ((icr & ICR_LSC) == 0) { |
if ((icr & ICR_LSC) == 0) { |
if (icr & ICR_RXSEQ) |
if (icr & ICR_RXSEQ) |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: LINK Receive sequence error\n", |
("%s: LINK Receive sequence error\n", |
device_xname(dev))); |
device_xname(dev))); |
return; |
return; |
Line 9311 wm_linkintr_gmii(struct wm_softc *sc, ui |
|
Line 9450 wm_linkintr_gmii(struct wm_softc *sc, ui |
|
status = CSR_READ(sc, WMREG_STATUS); |
status = CSR_READ(sc, WMREG_STATUS); |
link = status & STATUS_LU; |
link = status & STATUS_LU; |
if (link) { |
if (link) { |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n", |
device_xname(dev), |
device_xname(dev), |
(status & STATUS_FD) ? "FDX" : "HDX")); |
(status & STATUS_FD) ? "FDX" : "HDX")); |
if (wm_phy_need_linkdown_discard(sc)) |
if (wm_phy_need_linkdown_discard(sc)) |
Line 9319 wm_linkintr_gmii(struct wm_softc *sc, ui |
|
Line 9458 wm_linkintr_gmii(struct wm_softc *sc, ui |
|
} else { |
} else { |
if (wm_phy_need_linkdown_discard(sc)) |
if (wm_phy_need_linkdown_discard(sc)) |
wm_set_linkdown_discard(sc); |
wm_set_linkdown_discard(sc); |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n", |
device_xname(dev))); |
device_xname(dev))); |
} |
} |
if ((sc->sc_type == WM_T_ICH8) && (link == false)) |
if ((sc->sc_type == WM_T_ICH8) && (link == false)) |
Line 9329 wm_linkintr_gmii(struct wm_softc *sc, ui |
|
Line 9468 wm_linkintr_gmii(struct wm_softc *sc, ui |
|
&& (sc->sc_phytype == WMPHY_IGP_3)) { |
&& (sc->sc_phytype == WMPHY_IGP_3)) { |
wm_kmrn_lock_loss_workaround_ich8lan(sc); |
wm_kmrn_lock_loss_workaround_ich8lan(sc); |
} |
} |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> mii_pollstat\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: LSC -> mii_pollstat\n", |
device_xname(dev))); |
device_xname(dev))); |
mii_pollstat(&sc->sc_mii); |
mii_pollstat(&sc->sc_mii); |
if (sc->sc_type == WM_T_82543) { |
if (sc->sc_type == WM_T_82543) { |
Line 9557 wm_linkintr_tbi(struct wm_softc *sc, uin |
|
Line 9696 wm_linkintr_tbi(struct wm_softc *sc, uin |
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
uint32_t status; |
uint32_t status; |
|
|
DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev), |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev), |
__func__)); |
__func__)); |
|
|
status = CSR_READ(sc, WMREG_STATUS); |
status = CSR_READ(sc, WMREG_STATUS); |
if (icr & ICR_LSC) { |
if (icr & ICR_LSC) { |
wm_check_for_link(sc); |
wm_check_for_link(sc); |
if (status & STATUS_LU) { |
if (status & STATUS_LU) { |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n", |
device_xname(sc->sc_dev), |
device_xname(sc->sc_dev), |
(status & STATUS_FD) ? "FDX" : "HDX")); |
(status & STATUS_FD) ? "FDX" : "HDX")); |
/* |
/* |
Line 9589 wm_linkintr_tbi(struct wm_softc *sc, uin |
|
Line 9728 wm_linkintr_tbi(struct wm_softc *sc, uin |
|
sc->sc_tbi_linkup = 1; |
sc->sc_tbi_linkup = 1; |
if_link_state_change(ifp, LINK_STATE_UP); |
if_link_state_change(ifp, LINK_STATE_UP); |
} else { |
} else { |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
sc->sc_tbi_linkup = 0; |
sc->sc_tbi_linkup = 0; |
if_link_state_change(ifp, LINK_STATE_DOWN); |
if_link_state_change(ifp, LINK_STATE_DOWN); |
Line 9597 wm_linkintr_tbi(struct wm_softc *sc, uin |
|
Line 9736 wm_linkintr_tbi(struct wm_softc *sc, uin |
|
/* Update LED */ |
/* Update LED */ |
wm_tbi_serdes_set_linkled(sc); |
wm_tbi_serdes_set_linkled(sc); |
} else if (icr & ICR_RXSEQ) |
} else if (icr & ICR_RXSEQ) |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: Receive sequence error\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: Receive sequence error\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
} |
} |
|
|
Line 9614 wm_linkintr_serdes(struct wm_softc *sc, |
|
Line 9753 wm_linkintr_serdes(struct wm_softc *sc, |
|
struct ifmedia_entry *ife = mii->mii_media.ifm_cur; |
struct ifmedia_entry *ife = mii->mii_media.ifm_cur; |
uint32_t pcs_adv, pcs_lpab, reg; |
uint32_t pcs_adv, pcs_lpab, reg; |
|
|
DPRINTF(WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev), |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s:\n", device_xname(sc->sc_dev), |
__func__)); |
__func__)); |
|
|
if (icr & ICR_LSC) { |
if (icr & ICR_LSC) { |
/* Check PCS */ |
/* Check PCS */ |
reg = CSR_READ(sc, WMREG_PCS_LSTS); |
reg = CSR_READ(sc, WMREG_PCS_LSTS); |
if ((reg & PCS_LSTS_LINKOK) != 0) { |
if ((reg & PCS_LSTS_LINKOK) != 0) { |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> up\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: LSC -> up\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
mii->mii_media_status |= IFM_ACTIVE; |
mii->mii_media_status |= IFM_ACTIVE; |
sc->sc_tbi_linkup = 1; |
sc->sc_tbi_linkup = 1; |
if_link_state_change(ifp, LINK_STATE_UP); |
if_link_state_change(ifp, LINK_STATE_UP); |
} else { |
} else { |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
mii->mii_media_status |= IFM_NONE; |
mii->mii_media_status |= IFM_NONE; |
sc->sc_tbi_linkup = 0; |
sc->sc_tbi_linkup = 0; |
Line 9644 wm_linkintr_serdes(struct wm_softc *sc, |
|
Line 9783 wm_linkintr_serdes(struct wm_softc *sc, |
|
/* Check flow */ |
/* Check flow */ |
reg = CSR_READ(sc, WMREG_PCS_LSTS); |
reg = CSR_READ(sc, WMREG_PCS_LSTS); |
if ((reg & PCS_LSTS_AN_COMP) == 0) { |
if ((reg & PCS_LSTS_AN_COMP) == 0) { |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("XXX LINKOK but not ACOMP\n")); |
("XXX LINKOK but not ACOMP\n")); |
return; |
return; |
} |
} |
pcs_adv = CSR_READ(sc, WMREG_PCS_ANADV); |
pcs_adv = CSR_READ(sc, WMREG_PCS_ANADV); |
pcs_lpab = CSR_READ(sc, WMREG_PCS_LPAB); |
pcs_lpab = CSR_READ(sc, WMREG_PCS_LPAB); |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("XXX AN result %08x, %08x\n", pcs_adv, pcs_lpab)); |
("XXX AN result %08x, %08x\n", pcs_adv, pcs_lpab)); |
if ((pcs_adv & TXCW_SYM_PAUSE) |
if ((pcs_adv & TXCW_SYM_PAUSE) |
&& (pcs_lpab & TXCW_SYM_PAUSE)) { |
&& (pcs_lpab & TXCW_SYM_PAUSE)) { |
Line 9672 wm_linkintr_serdes(struct wm_softc *sc, |
|
Line 9811 wm_linkintr_serdes(struct wm_softc *sc, |
|
/* Update LED */ |
/* Update LED */ |
wm_tbi_serdes_set_linkled(sc); |
wm_tbi_serdes_set_linkled(sc); |
} else |
} else |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: Receive sequence error\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: Receive sequence error\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
} |
} |
|
|
Line 9707 wm_sched_handle_queue(struct wm_softc *s |
|
Line 9846 wm_sched_handle_queue(struct wm_softc *s |
|
softint_schedule(wmq->wmq_si); |
softint_schedule(wmq->wmq_si); |
} |
} |
|
|
|
static inline void |
|
wm_legacy_intr_disable(struct wm_softc *sc) |
|
{ |
|
|
|
CSR_WRITE(sc, WMREG_IMC, 0xffffffffU); |
|
} |
|
|
|
static inline void |
|
wm_legacy_intr_enable(struct wm_softc *sc) |
|
{ |
|
|
|
CSR_WRITE(sc, WMREG_IMS, sc->sc_icr); |
|
} |
|
|
/* |
/* |
* wm_intr_legacy: |
* wm_intr_legacy: |
* |
* |
|
|
wm_intr_legacy(void *arg) |
wm_intr_legacy(void *arg) |
{ |
{ |
struct wm_softc *sc = arg; |
struct wm_softc *sc = arg; |
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
struct wm_queue *wmq = &sc->sc_queue[0]; |
struct wm_queue *wmq = &sc->sc_queue[0]; |
struct wm_txqueue *txq = &wmq->wmq_txq; |
struct wm_txqueue *txq = &wmq->wmq_txq; |
struct wm_rxqueue *rxq = &wmq->wmq_rxq; |
struct wm_rxqueue *rxq = &wmq->wmq_rxq; |
|
u_int txlimit = sc->sc_tx_intr_process_limit; |
|
u_int rxlimit = sc->sc_rx_intr_process_limit; |
uint32_t icr, rndval = 0; |
uint32_t icr, rndval = 0; |
int handled = 0; |
bool more = false; |
|
|
while (1 /* CONSTCOND */) { |
icr = CSR_READ(sc, WMREG_ICR); |
icr = CSR_READ(sc, WMREG_ICR); |
if ((icr & sc->sc_icr) == 0) |
if ((icr & sc->sc_icr) == 0) |
return 0; |
break; |
|
if (handled == 0) |
|
DPRINTF(WM_DEBUG_TX, |
|
("%s: INTx: got intr\n",device_xname(sc->sc_dev))); |
|
if (rndval == 0) |
|
rndval = icr; |
|
|
|
mutex_enter(rxq->rxq_lock); |
DPRINTF(sc, WM_DEBUG_TX, |
|
("%s: INTx: got intr\n",device_xname(sc->sc_dev))); |
|
if (rndval == 0) |
|
rndval = icr; |
|
|
if (rxq->rxq_stopping) { |
mutex_enter(rxq->rxq_lock); |
mutex_exit(rxq->rxq_lock); |
|
break; |
|
} |
|
|
|
handled = 1; |
if (rxq->rxq_stopping) { |
|
mutex_exit(rxq->rxq_lock); |
|
return 1; |
|
} |
|
|
#if defined(WM_DEBUG) || defined(WM_EVENT_COUNTERS) |
#if defined(WM_DEBUG) || defined(WM_EVENT_COUNTERS) |
if (icr & (ICR_RXDMT0 | ICR_RXT0)) { |
if (icr & (ICR_RXDMT0 | ICR_RXT0)) { |
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: got Rx intr 0x%08x\n", |
("%s: RX: got Rx intr 0x%08x\n", |
device_xname(sc->sc_dev), |
device_xname(sc->sc_dev), |
icr & (ICR_RXDMT0 | ICR_RXT0))); |
icr & (ICR_RXDMT0 | ICR_RXT0))); |
WM_Q_EVCNT_INCR(rxq, intr); |
WM_Q_EVCNT_INCR(rxq, intr); |
} |
} |
#endif |
#endif |
/* |
/* |
* wm_rxeof() does *not* call upper layer functions directly, |
* wm_rxeof() does *not* call upper layer functions directly, |
* as if_percpuq_enqueue() just call softint_schedule(). |
* as if_percpuq_enqueue() just call softint_schedule(). |
* So, we can call wm_rxeof() in interrupt context. |
* So, we can call wm_rxeof() in interrupt context. |
*/ |
*/ |
wm_rxeof(rxq, UINT_MAX); |
more = wm_rxeof(rxq, rxlimit); |
/* Fill lower bits with RX index. See below for the upper. */ |
/* Fill lower bits with RX index. See below for the upper. */ |
rndval |= rxq->rxq_ptr & WM_NRXDESC_MASK; |
rndval |= rxq->rxq_ptr & WM_NRXDESC_MASK; |
|
|
mutex_exit(rxq->rxq_lock); |
mutex_exit(rxq->rxq_lock); |
mutex_enter(txq->txq_lock); |
mutex_enter(txq->txq_lock); |
|
|
if (txq->txq_stopping) { |
if (txq->txq_stopping) { |
mutex_exit(txq->txq_lock); |
mutex_exit(txq->txq_lock); |
break; |
return 1; |
} |
} |
|
|
#if defined(WM_DEBUG) || defined(WM_EVENT_COUNTERS) |
#if defined(WM_DEBUG) || defined(WM_EVENT_COUNTERS) |
if (icr & ICR_TXDW) { |
if (icr & ICR_TXDW) { |
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: got TXDW interrupt\n", |
("%s: TX: got TXDW interrupt\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
WM_Q_EVCNT_INCR(txq, txdw); |
WM_Q_EVCNT_INCR(txq, txdw); |
} |
} |
#endif |
#endif |
wm_txeof(txq, UINT_MAX); |
more |= wm_txeof(txq, txlimit); |
/* Fill upper bits with TX index. See above for the lower. */ |
if (!IF_IS_EMPTY(&ifp->if_snd)) |
rndval = txq->txq_next * WM_NRXDESC; |
more = true; |
|
/* Fill upper bits with TX index. See above for the lower. */ |
|
rndval = txq->txq_next * WM_NRXDESC; |
|
|
mutex_exit(txq->txq_lock); |
mutex_exit(txq->txq_lock); |
WM_CORE_LOCK(sc); |
WM_CORE_LOCK(sc); |
|
|
if (sc->sc_core_stopping) { |
if (sc->sc_core_stopping) { |
WM_CORE_UNLOCK(sc); |
WM_CORE_UNLOCK(sc); |
break; |
return 1; |
} |
} |
|
|
if (icr & (ICR_LSC | ICR_RXSEQ)) { |
if (icr & (ICR_LSC | ICR_RXSEQ)) { |
WM_EVCNT_INCR(&sc->sc_ev_linkintr); |
WM_EVCNT_INCR(&sc->sc_ev_linkintr); |
wm_linkintr(sc, icr); |
wm_linkintr(sc, icr); |
} |
} |
if ((icr & ICR_GPI(0)) != 0) |
if ((icr & ICR_GPI(0)) != 0) |
device_printf(sc->sc_dev, "got module interrupt\n"); |
device_printf(sc->sc_dev, "got module interrupt\n"); |
|
|
WM_CORE_UNLOCK(sc); |
WM_CORE_UNLOCK(sc); |
|
|
if (icr & ICR_RXO) { |
if (icr & ICR_RXO) { |
#if defined(WM_DEBUG) |
#if defined(WM_DEBUG) |
log(LOG_WARNING, "%s: Receive overrun\n", |
log(LOG_WARNING, "%s: Receive overrun\n", |
device_xname(sc->sc_dev)); |
device_xname(sc->sc_dev)); |
#endif /* defined(WM_DEBUG) */ |
#endif /* defined(WM_DEBUG) */ |
} |
|
} |
} |
|
|
rnd_add_uint32(&sc->sc_queue[0].rnd_source, rndval); |
rnd_add_uint32(&sc->sc_queue[0].rnd_source, rndval); |
|
|
if (handled) { |
if (more) { |
/* Try to get more packets going. */ |
/* Try to get more packets going. */ |
|
wm_legacy_intr_disable(sc); |
wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue; |
wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue; |
wm_sched_handle_queue(sc, wmq); |
wm_sched_handle_queue(sc, wmq); |
} |
} |
|
|
return handled; |
return 1; |
} |
} |
|
|
static inline void |
static inline void |
Line 9820 wm_txrxintr_disable(struct wm_queue *wmq |
|
Line 9975 wm_txrxintr_disable(struct wm_queue *wmq |
|
{ |
{ |
struct wm_softc *sc = wmq->wmq_txq.txq_sc; |
struct wm_softc *sc = wmq->wmq_txq.txq_sc; |
|
|
|
if (__predict_false(!wm_is_using_msix(sc))) { |
|
return wm_legacy_intr_disable(sc); |
|
} |
|
|
if (sc->sc_type == WM_T_82574) |
if (sc->sc_type == WM_T_82574) |
CSR_WRITE(sc, WMREG_IMC, |
CSR_WRITE(sc, WMREG_IMC, |
ICR_TXQ(wmq->wmq_id) | ICR_RXQ(wmq->wmq_id)); |
ICR_TXQ(wmq->wmq_id) | ICR_RXQ(wmq->wmq_id)); |
Line 9837 wm_txrxintr_enable(struct wm_queue *wmq) |
|
Line 9996 wm_txrxintr_enable(struct wm_queue *wmq) |
|
|
|
wm_itrs_calculate(sc, wmq); |
wm_itrs_calculate(sc, wmq); |
|
|
|
if (__predict_false(!wm_is_using_msix(sc))) { |
|
return wm_legacy_intr_enable(sc); |
|
} |
|
|
/* |
/* |
* ICR_OTHER which is disabled in wm_linkintr_msix() is enabled here. |
* ICR_OTHER which is disabled in wm_linkintr_msix() is enabled here. |
* There is no need to care about which of RXQ(0) and RXQ(1) enable |
* There is no need to care about which of RXQ(0) and RXQ(1) enable |
Line 9868 wm_txrxintr_msix(void *arg) |
|
Line 10031 wm_txrxintr_msix(void *arg) |
|
|
|
KASSERT(wmq->wmq_intr_idx == wmq->wmq_id); |
KASSERT(wmq->wmq_intr_idx == wmq->wmq_id); |
|
|
DPRINTF(WM_DEBUG_TX, |
DPRINTF(sc, WM_DEBUG_TX, |
("%s: TX: got Tx intr\n", device_xname(sc->sc_dev))); |
("%s: TX: got Tx intr\n", device_xname(sc->sc_dev))); |
|
|
wm_txrxintr_disable(wmq); |
wm_txrxintr_disable(wmq); |
Line 9877 wm_txrxintr_msix(void *arg) |
|
Line 10040 wm_txrxintr_msix(void *arg) |
|
|
|
if (txq->txq_stopping) { |
if (txq->txq_stopping) { |
mutex_exit(txq->txq_lock); |
mutex_exit(txq->txq_lock); |
return 0; |
return 1; |
} |
} |
|
|
WM_Q_EVCNT_INCR(txq, txdw); |
WM_Q_EVCNT_INCR(txq, txdw); |
Line 9887 wm_txrxintr_msix(void *arg) |
|
Line 10050 wm_txrxintr_msix(void *arg) |
|
/* wm_deferred start() is done in wm_handle_queue(). */ |
/* wm_deferred start() is done in wm_handle_queue(). */ |
mutex_exit(txq->txq_lock); |
mutex_exit(txq->txq_lock); |
|
|
DPRINTF(WM_DEBUG_RX, |
DPRINTF(sc, WM_DEBUG_RX, |
("%s: RX: got Rx intr\n", device_xname(sc->sc_dev))); |
("%s: RX: got Rx intr\n", device_xname(sc->sc_dev))); |
mutex_enter(rxq->rxq_lock); |
mutex_enter(rxq->rxq_lock); |
|
|
if (rxq->rxq_stopping) { |
if (rxq->rxq_stopping) { |
mutex_exit(rxq->rxq_lock); |
mutex_exit(rxq->rxq_lock); |
return 0; |
return 1; |
} |
} |
|
|
WM_Q_EVCNT_INCR(rxq, intr); |
WM_Q_EVCNT_INCR(rxq, intr); |
Line 9983 wm_linkintr_msix(void *arg) |
|
Line 10146 wm_linkintr_msix(void *arg) |
|
|
|
reg = CSR_READ(sc, WMREG_ICR); |
reg = CSR_READ(sc, WMREG_ICR); |
WM_CORE_LOCK(sc); |
WM_CORE_LOCK(sc); |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: LINK: got link intr. ICR = %08x\n", |
("%s: LINK: got link intr. ICR = %08x\n", |
device_xname(sc->sc_dev), reg)); |
device_xname(sc->sc_dev), reg)); |
|
|
Line 10082 wm_gmii_reset(struct wm_softc *sc) |
|
Line 10245 wm_gmii_reset(struct wm_softc *sc) |
|
uint32_t reg; |
uint32_t reg; |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
rv = sc->phy.acquire(sc); |
rv = sc->phy.acquire(sc); |
Line 10269 wm_gmii_setup_phytype(struct wm_softc *s |
|
Line 10432 wm_gmii_setup_phytype(struct wm_softc *s |
|
mii_writereg_t new_writereg; |
mii_writereg_t new_writereg; |
bool dodiag = true; |
bool dodiag = true; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* |
/* |
Line 10567 wm_gmii_mediainit(struct wm_softc *sc, p |
|
Line 10730 wm_gmii_mediainit(struct wm_softc *sc, p |
|
struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
struct mii_data *mii = &sc->sc_mii; |
struct mii_data *mii = &sc->sc_mii; |
|
|
DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* We have GMII. */ |
/* We have GMII. */ |
Line 10717 wm_gmii_mediachange(struct ifnet *ifp) |
|
Line 10880 wm_gmii_mediachange(struct ifnet *ifp) |
|
uint32_t reg; |
uint32_t reg; |
int rc; |
int rc; |
|
|
DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
if ((ifp->if_flags & IFF_UP) == 0) |
if ((ifp->if_flags & IFF_UP) == 0) |
return 0; |
return 0; |
Line 10888 wm_gmii_i82543_readreg(device_t dev, int |
|
Line 11051 wm_gmii_i82543_readreg(device_t dev, int |
|
(MII_COMMAND_READ << 10) | (MII_COMMAND_START << 12), 14); |
(MII_COMMAND_READ << 10) | (MII_COMMAND_START << 12), 14); |
*val = wm_i82543_mii_recvbits(sc) & 0xffff; |
*val = wm_i82543_mii_recvbits(sc) & 0xffff; |
|
|
DPRINTF(WM_DEBUG_GMII, ("%s: GMII: read phy %d reg %d -> 0x%04hx\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: GMII: read phy %d reg %d -> 0x%04hx\n", |
device_xname(dev), phy, reg, *val)); |
device_xname(dev), phy, reg, *val)); |
|
|
return 0; |
return 0; |
Line 10942 wm_gmii_mdic_readreg(device_t dev, int p |
|
Line 11105 wm_gmii_mdic_readreg(device_t dev, int p |
|
} |
} |
|
|
if ((mdic & MDIC_READY) == 0) { |
if ((mdic & MDIC_READY) == 0) { |
DPRINTF(WM_DEBUG_GMII, |
DPRINTF(sc, WM_DEBUG_GMII, |
("%s: MDIC read timed out: phy %d reg %d\n", |
("%s: MDIC read timed out: phy %d reg %d\n", |
device_xname(dev), phy, reg)); |
device_xname(dev), phy, reg)); |
return ETIMEDOUT; |
return ETIMEDOUT; |
} else if (mdic & MDIC_E) { |
} else if (mdic & MDIC_E) { |
/* This is normal if no PHY is present. */ |
/* This is normal if no PHY is present. */ |
DPRINTF(WM_DEBUG_GMII, ("%s: MDIC read error: phy %d reg %d\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: MDIC read error: phy %d reg %d\n", |
device_xname(sc->sc_dev), phy, reg)); |
device_xname(sc->sc_dev), phy, reg)); |
return -1; |
return -1; |
} else |
} else |
Line 10994 wm_gmii_mdic_writereg(device_t dev, int |
|
Line 11157 wm_gmii_mdic_writereg(device_t dev, int |
|
} |
} |
|
|
if ((mdic & MDIC_READY) == 0) { |
if ((mdic & MDIC_READY) == 0) { |
DPRINTF(WM_DEBUG_GMII, |
DPRINTF(sc, WM_DEBUG_GMII, |
("%s: MDIC write timed out: phy %d reg %d\n", |
("%s: MDIC write timed out: phy %d reg %d\n", |
device_xname(dev), phy, reg)); |
device_xname(dev), phy, reg)); |
return ETIMEDOUT; |
return ETIMEDOUT; |
} else if (mdic & MDIC_E) { |
} else if (mdic & MDIC_E) { |
DPRINTF(WM_DEBUG_GMII, |
DPRINTF(sc, WM_DEBUG_GMII, |
("%s: MDIC write error: phy %d reg %d\n", |
("%s: MDIC write error: phy %d reg %d\n", |
device_xname(dev), phy, reg)); |
device_xname(dev), phy, reg)); |
return -1; |
return -1; |
|
|
static int |
static int |
wm_enable_phy_wakeup_reg_access_bm(device_t dev, uint16_t *phy_regp) |
wm_enable_phy_wakeup_reg_access_bm(device_t dev, uint16_t *phy_regp) |
{ |
{ |
|
#ifdef WM_DEBUG |
|
struct wm_softc *sc = device_private(dev); |
|
#endif |
uint16_t temp; |
uint16_t temp; |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
|
|
if (!phy_regp) |
if (!phy_regp) |
Line 11391 wm_enable_phy_wakeup_reg_access_bm(devic |
|
Line 11557 wm_enable_phy_wakeup_reg_access_bm(devic |
|
static int |
static int |
wm_disable_phy_wakeup_reg_access_bm(device_t dev, uint16_t *phy_regp) |
wm_disable_phy_wakeup_reg_access_bm(device_t dev, uint16_t *phy_regp) |
{ |
{ |
|
#ifdef WM_DEBUG |
|
struct wm_softc *sc = device_private(dev); |
|
#endif |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
|
|
if (!phy_regp) |
if (!phy_regp) |
Line 11443 wm_access_phy_wakeup_reg_bm(device_t dev |
|
Line 11612 wm_access_phy_wakeup_reg_bm(device_t dev |
|
uint16_t wuce; |
uint16_t wuce; |
int rv = 0; |
int rv = 0; |
|
|
DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
/* XXX Gig must be disabled for MDIO accesses to page 800 */ |
/* XXX Gig must be disabled for MDIO accesses to page 800 */ |
if ((sc->sc_type == WM_T_PCH) |
if ((sc->sc_type == WM_T_PCH) |
Line 11462 wm_access_phy_wakeup_reg_bm(device_t dev |
|
Line 11631 wm_access_phy_wakeup_reg_bm(device_t dev |
|
return rv; |
return rv; |
} |
} |
} |
} |
DPRINTF(WM_DEBUG_GMII, ("%s: %s: Accessing PHY page %d reg 0x%x\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: %s: Accessing PHY page %d reg 0x%x\n", |
device_xname(sc->sc_dev), __func__, page, regnum)); |
device_xname(sc->sc_dev), __func__, page, regnum)); |
|
|
/* |
/* |
Line 11504 wm_gmii_hv_readreg(device_t dev, int phy |
|
Line 11673 wm_gmii_hv_readreg(device_t dev, int phy |
|
struct wm_softc *sc = device_private(dev); |
struct wm_softc *sc = device_private(dev); |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
if (sc->phy.acquire(sc)) { |
if (sc->phy.acquire(sc)) { |
device_printf(dev, "%s: failed to get semaphore\n", __func__); |
device_printf(dev, "%s: failed to get semaphore\n", __func__); |
Line 11568 wm_gmii_hv_writereg(device_t dev, int ph |
|
Line 11737 wm_gmii_hv_writereg(device_t dev, int ph |
|
struct wm_softc *sc = device_private(dev); |
struct wm_softc *sc = device_private(dev); |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_GMII, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
|
|
if (sc->phy.acquire(sc)) { |
if (sc->phy.acquire(sc)) { |
Line 11806 wm_gmii_statchg(struct ifnet *ifp) |
|
Line 11975 wm_gmii_statchg(struct ifnet *ifp) |
|
} |
} |
|
|
if (mii->mii_media_active & IFM_FDX) { |
if (mii->mii_media_active & IFM_FDX) { |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: LINK: statchg: FDX\n", ifp->if_xname)); |
("%s: LINK: statchg: FDX\n", ifp->if_xname)); |
sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_FDX); |
sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_FDX); |
} else { |
} else { |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: LINK: statchg: HDX\n", ifp->if_xname)); |
("%s: LINK: statchg: HDX\n", ifp->if_xname)); |
sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_HDX); |
sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_HDX); |
} |
} |
Line 12304 wm_tbi_mediachange(struct ifnet *ifp) |
|
Line 12473 wm_tbi_mediachange(struct ifnet *ifp) |
|
if ((sc->sc_mii.mii_media.ifm_media & IFM_FLOW) != 0) |
if ((sc->sc_mii.mii_media.ifm_media & IFM_FLOW) != 0) |
sc->sc_txcw |= TXCW_SYM_PAUSE | TXCW_ASYM_PAUSE; |
sc->sc_txcw |= TXCW_SYM_PAUSE | TXCW_ASYM_PAUSE; |
|
|
DPRINTF(WM_DEBUG_LINK,("%s: sc_txcw = 0x%x after autoneg check\n", |
DPRINTF(sc, WM_DEBUG_LINK,("%s: sc_txcw = 0x%x after autoneg check\n", |
device_xname(sc->sc_dev), sc->sc_txcw)); |
device_xname(sc->sc_dev), sc->sc_txcw)); |
CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw); |
CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw); |
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl); |
Line 12314 wm_tbi_mediachange(struct ifnet *ifp) |
|
Line 12483 wm_tbi_mediachange(struct ifnet *ifp) |
|
ctrl = CSR_READ(sc, WMREG_CTRL); |
ctrl = CSR_READ(sc, WMREG_CTRL); |
signal = wm_tbi_havesignal(sc, ctrl); |
signal = wm_tbi_havesignal(sc, ctrl); |
|
|
DPRINTF(WM_DEBUG_LINK, ("%s: signal = %d\n", device_xname(sc->sc_dev), |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: signal = %d\n", device_xname(sc->sc_dev), |
signal)); |
signal)); |
|
|
if (signal) { |
if (signal) { |
Line 12325 wm_tbi_mediachange(struct ifnet *ifp) |
|
Line 12494 wm_tbi_mediachange(struct ifnet *ifp) |
|
break; |
break; |
} |
} |
|
|
DPRINTF(WM_DEBUG_LINK,("%s: i = %d after waiting for link\n", |
DPRINTF(sc, WM_DEBUG_LINK,("%s: i = %d after waiting for link\n", |
device_xname(sc->sc_dev), i)); |
device_xname(sc->sc_dev), i)); |
|
|
status = CSR_READ(sc, WMREG_STATUS); |
status = CSR_READ(sc, WMREG_STATUS); |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: status after final read = 0x%x, STATUS_LU = 0x%x\n", |
("%s: status after final read = 0x%x, STATUS_LU = 0x%x\n", |
device_xname(sc->sc_dev), status, STATUS_LU)); |
device_xname(sc->sc_dev), status, STATUS_LU)); |
if (status & STATUS_LU) { |
if (status & STATUS_LU) { |
/* Link is up. */ |
/* Link is up. */ |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: LINK: set media -> link up %s\n", |
("%s: LINK: set media -> link up %s\n", |
device_xname(sc->sc_dev), |
device_xname(sc->sc_dev), |
(status & STATUS_FD) ? "FDX" : "HDX")); |
(status & STATUS_FD) ? "FDX" : "HDX")); |
Line 12362 wm_tbi_mediachange(struct ifnet *ifp) |
|
Line 12531 wm_tbi_mediachange(struct ifnet *ifp) |
|
if (i == WM_LINKUP_TIMEOUT) |
if (i == WM_LINKUP_TIMEOUT) |
wm_check_for_link(sc); |
wm_check_for_link(sc); |
/* Link is down. */ |
/* Link is down. */ |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: LINK: set media -> link down\n", |
("%s: LINK: set media -> link down\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
sc->sc_tbi_linkup = 0; |
sc->sc_tbi_linkup = 0; |
} |
} |
} else { |
} else { |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: set media -> no signal\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: set media -> no signal\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
sc->sc_tbi_linkup = 0; |
sc->sc_tbi_linkup = 0; |
} |
} |
Line 12425 wm_check_for_link(struct wm_softc *sc) |
|
Line 12594 wm_check_for_link(struct wm_softc *sc) |
|
uint32_t status; |
uint32_t status; |
bool signal; |
bool signal; |
|
|
DPRINTF(WM_DEBUG_LINK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->sc_mediatype == WM_MEDIATYPE_SERDES) { |
if (sc->sc_mediatype == WM_MEDIATYPE_SERDES) { |
Line 12441 wm_check_for_link(struct wm_softc *sc) |
|
Line 12610 wm_check_for_link(struct wm_softc *sc) |
|
status = CSR_READ(sc, WMREG_STATUS); |
status = CSR_READ(sc, WMREG_STATUS); |
signal = wm_tbi_havesignal(sc, ctrl); |
signal = wm_tbi_havesignal(sc, ctrl); |
|
|
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: %s: signal = %d, status_lu = %d, rxcw_c = %d\n", |
("%s: %s: signal = %d, status_lu = %d, rxcw_c = %d\n", |
device_xname(sc->sc_dev), __func__, signal, |
device_xname(sc->sc_dev), __func__, signal, |
((status & STATUS_LU) != 0), ((rxcw & RXCW_C) != 0))); |
((status & STATUS_LU) != 0), ((rxcw & RXCW_C) != 0))); |
Line 12459 wm_check_for_link(struct wm_softc *sc) |
|
Line 12628 wm_check_for_link(struct wm_softc *sc) |
|
* |
* |
*/ |
*/ |
if (signal && ((status & STATUS_LU) == 0) && ((rxcw & RXCW_C) == 0)) { |
if (signal && ((status & STATUS_LU) == 0) && ((rxcw & RXCW_C) == 0)) { |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("%s: %s: force linkup and fullduplex\n", |
("%s: %s: force linkup and fullduplex\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
sc->sc_tbi_linkup = 0; |
sc->sc_tbi_linkup = 0; |
Line 12478 wm_check_for_link(struct wm_softc *sc) |
|
Line 12647 wm_check_for_link(struct wm_softc *sc) |
|
&& ((rxcw & RXCW_C) != 0) |
&& ((rxcw & RXCW_C) != 0) |
&& (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO)) { |
&& (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO)) { |
sc->sc_tbi_linkup = 1; |
sc->sc_tbi_linkup = 1; |
DPRINTF(WM_DEBUG_LINK, ("%s: %s: go back to autonego\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s: go back to autonego\n", |
device_xname(sc->sc_dev), |
device_xname(sc->sc_dev), |
__func__)); |
__func__)); |
CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw); |
CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw); |
CSR_WRITE(sc, WMREG_CTRL, (ctrl & ~CTRL_SLU)); |
CSR_WRITE(sc, WMREG_CTRL, (ctrl & ~CTRL_SLU)); |
} else if (signal && ((rxcw & RXCW_C) != 0)) { |
} else if (signal && ((rxcw & RXCW_C) != 0)) { |
DPRINTF(WM_DEBUG_LINK, ("%s: %s: /C/", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s: /C/", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
} else { |
} else { |
DPRINTF(WM_DEBUG_LINK, ("%s: %s: linkup %08x,%08x,%08x\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s: linkup %08x,%08x,%08x\n", |
device_xname(sc->sc_dev), __func__, rxcw, ctrl, |
device_xname(sc->sc_dev), __func__, rxcw, ctrl, |
status)); |
status)); |
} |
} |
Line 12518 wm_tbi_tick(struct wm_softc *sc) |
|
Line 12687 wm_tbi_tick(struct wm_softc *sc) |
|
|
|
/* set link status */ |
/* set link status */ |
if ((status & STATUS_LU) == 0) { |
if ((status & STATUS_LU) == 0) { |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: checklink -> down\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: checklink -> down\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
sc->sc_tbi_linkup = 0; |
sc->sc_tbi_linkup = 0; |
} else if (sc->sc_tbi_linkup == 0) { |
} else if (sc->sc_tbi_linkup == 0) { |
DPRINTF(WM_DEBUG_LINK, ("%s: LINK: checklink -> up %s\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: LINK: checklink -> up %s\n", |
device_xname(sc->sc_dev), |
device_xname(sc->sc_dev), |
(status & STATUS_FD) ? "FDX" : "HDX")); |
(status & STATUS_FD) ? "FDX" : "HDX")); |
sc->sc_tbi_linkup = 1; |
sc->sc_tbi_linkup = 1; |
Line 12538 wm_tbi_tick(struct wm_softc *sc) |
|
Line 12707 wm_tbi_tick(struct wm_softc *sc) |
|
if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) |
if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) |
&& (++sc->sc_tbi_serdes_ticks |
&& (++sc->sc_tbi_serdes_ticks |
>= sc->sc_tbi_serdes_anegticks)) { |
>= sc->sc_tbi_serdes_anegticks)) { |
DPRINTF(WM_DEBUG_LINK, ("%s: %s: EXPIRE\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s: EXPIRE\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
sc->sc_tbi_serdes_ticks = 0; |
sc->sc_tbi_serdes_ticks = 0; |
/* |
/* |
Line 12725 wm_serdes_mediastatus(struct ifnet *ifp, |
|
Line 12894 wm_serdes_mediastatus(struct ifnet *ifp, |
|
/* Check flow */ |
/* Check flow */ |
reg = CSR_READ(sc, WMREG_PCS_LSTS); |
reg = CSR_READ(sc, WMREG_PCS_LSTS); |
if ((reg & PCS_LSTS_AN_COMP) == 0) { |
if ((reg & PCS_LSTS_AN_COMP) == 0) { |
DPRINTF(WM_DEBUG_LINK, ("XXX LINKOK but not ACOMP\n")); |
DPRINTF(sc, WM_DEBUG_LINK, ("XXX LINKOK but not ACOMP\n")); |
goto setled; |
goto setled; |
} |
} |
pcs_adv = CSR_READ(sc, WMREG_PCS_ANADV); |
pcs_adv = CSR_READ(sc, WMREG_PCS_ANADV); |
pcs_lpab = CSR_READ(sc, WMREG_PCS_LPAB); |
pcs_lpab = CSR_READ(sc, WMREG_PCS_LPAB); |
DPRINTF(WM_DEBUG_LINK, |
DPRINTF(sc, WM_DEBUG_LINK, |
("XXX AN result(2) %08x, %08x\n", pcs_adv, pcs_lpab)); |
("XXX AN result(2) %08x, %08x\n", pcs_adv, pcs_lpab)); |
if ((pcs_adv & TXCW_SYM_PAUSE) |
if ((pcs_adv & TXCW_SYM_PAUSE) |
&& (pcs_lpab & TXCW_SYM_PAUSE)) { |
&& (pcs_lpab & TXCW_SYM_PAUSE)) { |
Line 12792 wm_serdes_tick(struct wm_softc *sc) |
|
Line 12961 wm_serdes_tick(struct wm_softc *sc) |
|
if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) |
if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) |
&& (++sc->sc_tbi_serdes_ticks |
&& (++sc->sc_tbi_serdes_ticks |
>= sc->sc_tbi_serdes_anegticks)) { |
>= sc->sc_tbi_serdes_anegticks)) { |
DPRINTF(WM_DEBUG_LINK, ("%s: %s: EXPIRE\n", |
DPRINTF(sc, WM_DEBUG_LINK, ("%s: %s: EXPIRE\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
sc->sc_tbi_serdes_ticks = 0; |
sc->sc_tbi_serdes_ticks = 0; |
/* XXX */ |
/* XXX */ |
Line 12973 wm_nvm_read_uwire(struct wm_softc *sc, i |
|
Line 13142 wm_nvm_read_uwire(struct wm_softc *sc, i |
|
uint32_t reg, val; |
uint32_t reg, val; |
int i; |
int i; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->nvm.acquire(sc) != 0) |
if (sc->nvm.acquire(sc) != 0) |
Line 13108 wm_nvm_ready_spi(struct wm_softc *sc) |
|
Line 13277 wm_nvm_ready_spi(struct wm_softc *sc) |
|
uint32_t val; |
uint32_t val; |
int usec; |
int usec; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
for (usec = 0; usec < SPI_MAX_RETRIES; delay(5), usec += 5) { |
for (usec = 0; usec < SPI_MAX_RETRIES; delay(5), usec += 5) { |
Line 13137 wm_nvm_read_spi(struct wm_softc *sc, int |
|
Line 13306 wm_nvm_read_spi(struct wm_softc *sc, int |
|
uint8_t opc; |
uint8_t opc; |
int rv = 0; |
int rv = 0; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->nvm.acquire(sc) != 0) |
if (sc->nvm.acquire(sc) != 0) |
Line 13211 wm_nvm_read_eerd(struct wm_softc *sc, in |
|
Line 13380 wm_nvm_read_eerd(struct wm_softc *sc, in |
|
int i, eerd = 0; |
int i, eerd = 0; |
int rv = 0; |
int rv = 0; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->nvm.acquire(sc) != 0) |
if (sc->nvm.acquire(sc) != 0) |
Line 13303 wm_nvm_valid_bank_detect_ich8lan(struct |
|
Line 13472 wm_nvm_valid_bank_detect_ich8lan(struct |
|
} |
} |
} |
} |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: No valid NVM bank present\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: No valid NVM bank present\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
return -1; |
return -1; |
} |
} |
Line 13623 wm_nvm_read_ich8(struct wm_softc *sc, in |
|
Line 13792 wm_nvm_read_ich8(struct wm_softc *sc, in |
|
uint16_t word = 0; |
uint16_t word = 0; |
uint16_t i = 0; |
uint16_t i = 0; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->nvm.acquire(sc) != 0) |
if (sc->nvm.acquire(sc) != 0) |
Line 13637 wm_nvm_read_ich8(struct wm_softc *sc, in |
|
Line 13806 wm_nvm_read_ich8(struct wm_softc *sc, in |
|
*/ |
*/ |
rv = wm_nvm_valid_bank_detect_ich8lan(sc, &flash_bank); |
rv = wm_nvm_valid_bank_detect_ich8lan(sc, &flash_bank); |
if (rv) { |
if (rv) { |
DPRINTF(WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
flash_bank = 0; |
flash_bank = 0; |
} |
} |
Line 13683 wm_nvm_read_spt(struct wm_softc *sc, int |
|
Line 13852 wm_nvm_read_spt(struct wm_softc *sc, int |
|
uint32_t dword = 0; |
uint32_t dword = 0; |
uint16_t i = 0; |
uint16_t i = 0; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->nvm.acquire(sc) != 0) |
if (sc->nvm.acquire(sc) != 0) |
Line 13697 wm_nvm_read_spt(struct wm_softc *sc, int |
|
Line 13866 wm_nvm_read_spt(struct wm_softc *sc, int |
|
*/ |
*/ |
rv = wm_nvm_valid_bank_detect_ich8lan(sc, &flash_bank); |
rv = wm_nvm_valid_bank_detect_ich8lan(sc, &flash_bank); |
if (rv) { |
if (rv) { |
DPRINTF(WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: failed to detect NVM bank\n", |
device_xname(sc->sc_dev))); |
device_xname(sc->sc_dev))); |
flash_bank = 0; |
flash_bank = 0; |
} |
} |
Line 13739 wm_nvm_read_word_invm(struct wm_softc *s |
|
Line 13908 wm_nvm_read_word_invm(struct wm_softc *s |
|
uint16_t i; |
uint16_t i; |
uint8_t record_type, word_address; |
uint8_t record_type, word_address; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
for (i = 0; i < INVM_SIZE; i++) { |
for (i = 0; i < INVM_SIZE; i++) { |
Line 13771 wm_nvm_read_invm(struct wm_softc *sc, in |
|
Line 13940 wm_nvm_read_invm(struct wm_softc *sc, in |
|
int rv = 0; |
int rv = 0; |
int i; |
int i; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->nvm.acquire(sc) != 0) |
if (sc->nvm.acquire(sc) != 0) |
Line 13831 wm_nvm_read_invm(struct wm_softc *sc, in |
|
Line 14000 wm_nvm_read_invm(struct wm_softc *sc, in |
|
} |
} |
break; |
break; |
default: |
default: |
DPRINTF(WM_DEBUG_NVM, |
DPRINTF(sc, WM_DEBUG_NVM, |
("NVM word 0x%02x is not mapped.\n", offset)); |
("NVM word 0x%02x is not mapped.\n", offset)); |
*data = NVM_RESERVED_WORD; |
*data = NVM_RESERVED_WORD; |
break; |
break; |
Line 13913 wm_nvm_validate_checksum(struct wm_softc |
|
Line 14082 wm_nvm_validate_checksum(struct wm_softc |
|
/* XXX PCH_SPT? */ |
/* XXX PCH_SPT? */ |
wm_nvm_read(sc, csum_wordaddr, 1, &eeprom_data); |
wm_nvm_read(sc, csum_wordaddr, 1, &eeprom_data); |
if ((eeprom_data & valid_checksum) == 0) |
if ((eeprom_data & valid_checksum) == 0) |
DPRINTF(WM_DEBUG_NVM, |
DPRINTF(sc, WM_DEBUG_NVM, |
("%s: NVM need to be updated (%04x != %04x)\n", |
("%s: NVM need to be updated (%04x != %04x)\n", |
device_xname(sc->sc_dev), eeprom_data, |
device_xname(sc->sc_dev), eeprom_data, |
valid_checksum)); |
valid_checksum)); |
} |
} |
|
|
if ((wm_debug & WM_DEBUG_NVM) != 0) { |
if ((sc->sc_debug & WM_DEBUG_NVM) != 0) { |
printf("%s: NVM dump:\n", device_xname(sc->sc_dev)); |
printf("%s: NVM dump:\n", device_xname(sc->sc_dev)); |
for (i = 0; i < NVM_SIZE; i++) { |
for (i = 0; i < NVM_SIZE; i++) { |
if (wm_nvm_read(sc, i, 1, &eeprom_data)) |
if (wm_nvm_read(sc, i, 1, &eeprom_data)) |
Line 14124 wm_nvm_read(struct wm_softc *sc, int wor |
|
Line 14293 wm_nvm_read(struct wm_softc *sc, int wor |
|
{ |
{ |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->sc_flags & WM_F_EEPROM_INVALID) |
if (sc->sc_flags & WM_F_EEPROM_INVALID) |
|
|
wm_get_null(struct wm_softc *sc) |
wm_get_null(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
return 0; |
return 0; |
} |
} |
|
|
wm_put_null(struct wm_softc *sc) |
wm_put_null(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
return; |
return; |
} |
} |
Line 14164 wm_get_eecd(struct wm_softc *sc) |
|
Line 14333 wm_get_eecd(struct wm_softc *sc) |
|
uint32_t reg; |
uint32_t reg; |
int x; |
int x; |
|
|
DPRINTF(WM_DEBUG_LOCK | WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK | WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
reg = CSR_READ(sc, WMREG_EECD); |
reg = CSR_READ(sc, WMREG_EECD); |
Line 14222 wm_put_eecd(struct wm_softc *sc) |
|
Line 14391 wm_put_eecd(struct wm_softc *sc) |
|
{ |
{ |
uint32_t reg; |
uint32_t reg; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* Stop nvm */ |
/* Stop nvm */ |
Line 14256 wm_get_swsm_semaphore(struct wm_softc *s |
|
Line 14425 wm_get_swsm_semaphore(struct wm_softc *s |
|
int32_t timeout; |
int32_t timeout; |
uint32_t swsm; |
uint32_t swsm; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
KASSERT(sc->sc_nvm_wordsize > 0); |
KASSERT(sc->sc_nvm_wordsize > 0); |
|
|
Line 14323 wm_put_swsm_semaphore(struct wm_softc *s |
|
Line 14492 wm_put_swsm_semaphore(struct wm_softc *s |
|
{ |
{ |
uint32_t swsm; |
uint32_t swsm; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
swsm = CSR_READ(sc, WMREG_SWSM); |
swsm = CSR_READ(sc, WMREG_SWSM); |
Line 14343 wm_get_swfw_semaphore(struct wm_softc *s |
|
Line 14512 wm_get_swfw_semaphore(struct wm_softc *s |
|
uint32_t fwmask = mask << SWFW_FIRM_SHIFT; |
uint32_t fwmask = mask << SWFW_FIRM_SHIFT; |
int timeout; |
int timeout; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->sc_type == WM_T_80003) |
if (sc->sc_type == WM_T_80003) |
Line 14380 wm_put_swfw_semaphore(struct wm_softc *s |
|
Line 14549 wm_put_swfw_semaphore(struct wm_softc *s |
|
{ |
{ |
uint32_t swfw_sync; |
uint32_t swfw_sync; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
while (wm_get_swsm_semaphore(sc) != 0) |
while (wm_get_swsm_semaphore(sc) != 0) |
Line 14398 wm_get_nvm_80003(struct wm_softc *sc) |
|
Line 14567 wm_get_nvm_80003(struct wm_softc *sc) |
|
{ |
{ |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_LOCK | WM_DEBUG_NVM, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK | WM_DEBUG_NVM, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if ((rv = wm_get_swfw_semaphore(sc, SWFW_EEP_SM)) != 0) { |
if ((rv = wm_get_swfw_semaphore(sc, SWFW_EEP_SM)) != 0) { |
|
|
wm_put_nvm_80003(struct wm_softc *sc) |
wm_put_nvm_80003(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if ((sc->sc_flags & WM_F_LOCK_EECD) != 0) |
if ((sc->sc_flags & WM_F_LOCK_EECD) != 0) |
Line 14435 wm_get_nvm_82571(struct wm_softc *sc) |
|
Line 14604 wm_get_nvm_82571(struct wm_softc *sc) |
|
{ |
{ |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if ((rv = wm_get_swsm_semaphore(sc)) != 0) |
if ((rv = wm_get_swsm_semaphore(sc)) != 0) |
|
|
wm_put_nvm_82571(struct wm_softc *sc) |
wm_put_nvm_82571(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
switch (sc->sc_type) { |
switch (sc->sc_type) { |
|
|
wm_get_phy_82575(struct wm_softc *sc) |
wm_get_phy_82575(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
return wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); |
return wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); |
} |
} |
|
|
wm_put_phy_82575(struct wm_softc *sc) |
wm_put_phy_82575(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
return wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); |
wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); |
} |
} |
|
|
static int |
static int |
Line 14503 wm_get_swfwhw_semaphore(struct wm_softc |
|
Line 14672 wm_get_swfwhw_semaphore(struct wm_softc |
|
uint32_t ext_ctrl; |
uint32_t ext_ctrl; |
int timeout = 200; |
int timeout = 200; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
mutex_enter(sc->sc_ich_phymtx); /* Use PHY mtx for both PHY and NVM */ |
mutex_enter(sc->sc_ich_phymtx); /* Use PHY mtx for both PHY and NVM */ |
Line 14528 wm_put_swfwhw_semaphore(struct wm_softc |
|
Line 14697 wm_put_swfwhw_semaphore(struct wm_softc |
|
{ |
{ |
uint32_t ext_ctrl; |
uint32_t ext_ctrl; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR); |
ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR); |
Line 14544 wm_get_swflag_ich8lan(struct wm_softc *s |
|
Line 14713 wm_get_swflag_ich8lan(struct wm_softc *s |
|
uint32_t ext_ctrl; |
uint32_t ext_ctrl; |
int timeout; |
int timeout; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
mutex_enter(sc->sc_ich_phymtx); |
mutex_enter(sc->sc_ich_phymtx); |
for (timeout = 0; timeout < WM_PHY_CFG_TIMEOUT; timeout++) { |
for (timeout = 0; timeout < WM_PHY_CFG_TIMEOUT; timeout++) { |
Line 14585 wm_put_swflag_ich8lan(struct wm_softc *s |
|
Line 14754 wm_put_swflag_ich8lan(struct wm_softc *s |
|
{ |
{ |
uint32_t ext_ctrl; |
uint32_t ext_ctrl; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR); |
ext_ctrl = CSR_READ(sc, WMREG_EXTCNFCTR); |
if (ext_ctrl & EXTCNFCTR_MDIO_SW_OWNERSHIP) { |
if (ext_ctrl & EXTCNFCTR_MDIO_SW_OWNERSHIP) { |
|
|
wm_get_nvm_ich8lan(struct wm_softc *sc) |
wm_get_nvm_ich8lan(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
mutex_enter(sc->sc_ich_nvmmtx); |
mutex_enter(sc->sc_ich_nvmmtx); |
|
|
|
|
wm_put_nvm_ich8lan(struct wm_softc *sc) |
wm_put_nvm_ich8lan(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
mutex_exit(sc->sc_ich_nvmmtx); |
mutex_exit(sc->sc_ich_nvmmtx); |
} |
} |
Line 14624 wm_get_hw_semaphore_82573(struct wm_soft |
|
Line 14793 wm_get_hw_semaphore_82573(struct wm_soft |
|
int i = 0; |
int i = 0; |
uint32_t reg; |
uint32_t reg; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
reg = CSR_READ(sc, WMREG_EXTCNFCTR); |
reg = CSR_READ(sc, WMREG_EXTCNFCTR); |
Line 14653 wm_put_hw_semaphore_82573(struct wm_soft |
|
Line 14822 wm_put_hw_semaphore_82573(struct wm_soft |
|
{ |
{ |
uint32_t reg; |
uint32_t reg; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
reg = CSR_READ(sc, WMREG_EXTCNFCTR); |
reg = CSR_READ(sc, WMREG_EXTCNFCTR); |
Line 14753 wm_enable_mng_pass_thru(struct wm_softc |
|
Line 14922 wm_enable_mng_pass_thru(struct wm_softc |
|
|
|
manc = CSR_READ(sc, WMREG_MANC); |
manc = CSR_READ(sc, WMREG_MANC); |
|
|
DPRINTF(WM_DEBUG_MANAGE, ("%s: MANC (%08x)\n", |
DPRINTF(sc, WM_DEBUG_MANAGE, ("%s: MANC (%08x)\n", |
device_xname(sc->sc_dev), manc)); |
device_xname(sc->sc_dev), manc)); |
if ((manc & MANC_RECV_TCO_EN) == 0) |
if ((manc & MANC_RECV_TCO_EN) == 0) |
return 0; |
return 0; |
Line 14769 wm_enable_mng_pass_thru(struct wm_softc |
|
Line 14938 wm_enable_mng_pass_thru(struct wm_softc |
|
|
|
factps = CSR_READ(sc, WMREG_FACTPS); |
factps = CSR_READ(sc, WMREG_FACTPS); |
wm_nvm_read(sc, NVM_OFF_CFG2, 1, &data); |
wm_nvm_read(sc, NVM_OFF_CFG2, 1, &data); |
DPRINTF(WM_DEBUG_MANAGE, ("%s: FACTPS = %08x, CFG2=%04x\n", |
DPRINTF(sc, WM_DEBUG_MANAGE, ("%s: FACTPS = %08x, CFG2=%04x\n", |
device_xname(sc->sc_dev), factps, data)); |
device_xname(sc->sc_dev), factps, data)); |
if (((factps & FACTPS_MNGCG) == 0) |
if (((factps & FACTPS_MNGCG) == 0) |
&& ((data & NVM_CFG2_MNGM_MASK) |
&& ((data & NVM_CFG2_MNGM_MASK) |
Line 14789 wm_phy_resetisblocked(struct wm_softc *s |
|
Line 14958 wm_phy_resetisblocked(struct wm_softc *s |
|
uint32_t reg; |
uint32_t reg; |
int i = 0; |
int i = 0; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
switch (sc->sc_type) { |
switch (sc->sc_type) { |
Line 14837 wm_get_hw_control(struct wm_softc *sc) |
|
Line 15006 wm_get_hw_control(struct wm_softc *sc) |
|
{ |
{ |
uint32_t reg; |
uint32_t reg; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->sc_type == WM_T_82573) { |
if (sc->sc_type == WM_T_82573) { |
Line 14854 wm_release_hw_control(struct wm_softc *s |
|
Line 15023 wm_release_hw_control(struct wm_softc *s |
|
{ |
{ |
uint32_t reg; |
uint32_t reg; |
|
|
DPRINTF(WM_DEBUG_LOCK, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_LOCK, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->sc_type == WM_T_82573) { |
if (sc->sc_type == WM_T_82573) { |
Line 14871 wm_gate_hw_phy_config_ich8lan(struct wm_ |
|
Line 15040 wm_gate_hw_phy_config_ich8lan(struct wm_ |
|
{ |
{ |
uint32_t reg; |
uint32_t reg; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->sc_type < WM_T_PCH2) |
if (sc->sc_type < WM_T_PCH2) |
Line 14893 wm_init_phy_workarounds_pchlan(struct wm |
|
Line 15062 wm_init_phy_workarounds_pchlan(struct wm |
|
uint32_t fwsm, reg; |
uint32_t fwsm, reg; |
int rv = 0; |
int rv = 0; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* Gate automatic PHY configuration by hardware on non-managed 82579 */ |
/* Gate automatic PHY configuration by hardware on non-managed 82579 */ |
Line 14905 wm_init_phy_workarounds_pchlan(struct wm |
|
Line 15074 wm_init_phy_workarounds_pchlan(struct wm |
|
/* Acquire PHY semaphore */ |
/* Acquire PHY semaphore */ |
rv = sc->phy.acquire(sc); |
rv = sc->phy.acquire(sc); |
if (rv != 0) { |
if (rv != 0) { |
DPRINTF(WM_DEBUG_INIT, ("%s: %s: failed\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s: failed\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
return -1; |
return -1; |
} |
} |
|
|
wm_init_manageability(struct wm_softc *sc) |
wm_init_manageability(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
if (sc->sc_flags & WM_F_HAS_MANAGE) { |
if (sc->sc_flags & WM_F_HAS_MANAGE) { |
uint32_t manc2h = CSR_READ(sc, WMREG_MANC2H); |
uint32_t manc2h = CSR_READ(sc, WMREG_MANC2H); |
Line 15116 wm_ulp_disable(struct wm_softc *sc) |
|
Line 15285 wm_ulp_disable(struct wm_softc *sc) |
|
uint16_t phyreg; |
uint16_t phyreg; |
int i = 0, rv = 0; |
int i = 0, rv = 0; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
/* Exclude old devices */ |
/* Exclude old devices */ |
if ((sc->sc_type < WM_T_PCH_LPT) |
if ((sc->sc_type < WM_T_PCH_LPT) |
Line 15152 wm_ulp_disable(struct wm_softc *sc) |
|
Line 15321 wm_ulp_disable(struct wm_softc *sc) |
|
/* Acquire semaphore */ |
/* Acquire semaphore */ |
rv = sc->phy.acquire(sc); |
rv = sc->phy.acquire(sc); |
if (rv != 0) { |
if (rv != 0) { |
DPRINTF(WM_DEBUG_INIT, ("%s: %s: failed\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s: failed\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
return -1; |
return -1; |
} |
} |
Line 15530 wm_enable_wakeup(struct wm_softc *sc) |
|
Line 15699 wm_enable_wakeup(struct wm_softc *sc) |
|
pcireg_t pmode; |
pcireg_t pmode; |
int rv = 0; |
int rv = 0; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PWRMGMT, |
if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_PWRMGMT, |
Line 15662 wm_lplu_d0_disable(struct wm_softc *sc) |
|
Line 15831 wm_lplu_d0_disable(struct wm_softc *sc) |
|
uint32_t reg; |
uint32_t reg; |
uint16_t phyval; |
uint16_t phyval; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->sc_phytype == WMPHY_IFE) |
if (sc->sc_phytype == WMPHY_IFE) |
Line 15865 wm_kmrn_lock_loss_workaround_ich8lan(str |
|
Line 16034 wm_kmrn_lock_loss_workaround_ich8lan(str |
|
int i, reg, rv; |
int i, reg, rv; |
uint16_t phyreg; |
uint16_t phyreg; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
/* If the link is not up, do nothing */ |
/* If the link is not up, do nothing */ |
Line 15949 wm_hv_phy_workarounds_ich8lan(struct wm_ |
|
Line 16118 wm_hv_phy_workarounds_ich8lan(struct wm_ |
|
int phytype = sc->sc_phytype; |
int phytype = sc->sc_phytype; |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
KASSERT(sc->sc_type == WM_T_PCH); |
KASSERT(sc->sc_type == WM_T_PCH); |
|
|
|
|
wm_copy_rx_addrs_to_phy_ich8lan(struct wm_softc *sc) |
wm_copy_rx_addrs_to_phy_ich8lan(struct wm_softc *sc) |
{ |
{ |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->phy.acquire(sc) != 0) |
if (sc->phy.acquire(sc) != 0) |
Line 16061 wm_copy_rx_addrs_to_phy_ich8lan_locked(s |
|
Line 16230 wm_copy_rx_addrs_to_phy_ich8lan_locked(s |
|
uint16_t i, wuce; |
uint16_t i, wuce; |
int count; |
int count; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
|
|
if (wm_enable_phy_wakeup_reg_access_bm(dev, &wuce) != 0) |
if (wm_enable_phy_wakeup_reg_access_bm(dev, &wuce) != 0) |
Line 16102 wm_lv_jumbo_workaround_ich8lan(struct wm |
|
Line 16271 wm_lv_jumbo_workaround_ich8lan(struct wm |
|
uint16_t dft_ctrl, data; |
uint16_t dft_ctrl, data; |
uint16_t i; |
uint16_t i; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
|
|
if (sc->sc_type < WM_T_PCH2) |
if (sc->sc_type < WM_T_PCH2) |
Line 16114 wm_lv_jumbo_workaround_ich8lan(struct wm |
|
Line 16283 wm_lv_jumbo_workaround_ich8lan(struct wm |
|
return rv; |
return rv; |
|
|
/* Disable Rx path while enabling/disabling workaround */ |
/* Disable Rx path while enabling/disabling workaround */ |
sc->phy.readreg_locked(dev, 2, I82579_DFT_CTRL, &dft_ctrl); |
rv = sc->phy.readreg_locked(dev, 2, I82579_DFT_CTRL, &dft_ctrl); |
if (rv != 0) |
if (rv != 0) |
goto out; |
goto out; |
rv = sc->phy.writereg_locked(dev, 2, I82579_DFT_CTRL, |
rv = sc->phy.writereg_locked(dev, 2, I82579_DFT_CTRL, |
Line 16273 wm_lv_phy_workarounds_ich8lan(struct wm_ |
|
Line 16442 wm_lv_phy_workarounds_ich8lan(struct wm_ |
|
device_t dev = sc->sc_dev; |
device_t dev = sc->sc_dev; |
int rv; |
int rv; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(dev), __func__)); |
device_xname(dev), __func__)); |
KASSERT(sc->sc_type == WM_T_PCH2); |
KASSERT(sc->sc_type == WM_T_PCH2); |
|
|
Line 16383 wm_k1_gig_workaround_hv(struct wm_softc |
|
Line 16552 wm_k1_gig_workaround_hv(struct wm_softc |
|
{ |
{ |
int k1_enable = sc->sc_nvm_k1_enabled; |
int k1_enable = sc->sc_nvm_k1_enabled; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (sc->phy.acquire(sc) != 0) |
if (sc->phy.acquire(sc) != 0) |
Line 16631 wm_phy_is_accessible_pchlan(struct wm_so |
|
Line 16800 wm_phy_is_accessible_pchlan(struct wm_so |
|
uint16_t id1, id2; |
uint16_t id1, id2; |
int i, rv; |
int i, rv; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
KASSERT(CSR_READ(sc, WMREG_EXTCNFCTR) & EXTCNFCTR_MDIO_SW_OWNERSHIP); |
KASSERT(CSR_READ(sc, WMREG_EXTCNFCTR) & EXTCNFCTR_MDIO_SW_OWNERSHIP); |
|
|
Line 16735 wm_platform_pm_pch_lpt(struct wm_softc * |
|
Line 16904 wm_platform_pm_pch_lpt(struct wm_softc * |
|
int32_t obff_hwm = 0; |
int32_t obff_hwm = 0; |
int64_t lat_ns, value; |
int64_t lat_ns, value; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
|
|
if (link) { |
if (link) { |
Line 16930 wm_legacy_irq_quirk_spt(struct wm_softc |
|
Line 17099 wm_legacy_irq_quirk_spt(struct wm_softc |
|
{ |
{ |
uint32_t reg; |
uint32_t reg; |
|
|
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n", |
DPRINTF(sc, WM_DEBUG_INIT, ("%s: %s called\n", |
device_xname(sc->sc_dev), __func__)); |
device_xname(sc->sc_dev), __func__)); |
KASSERT((sc->sc_type == WM_T_PCH_SPT) |
KASSERT((sc->sc_type == WM_T_PCH_SPT) |
|| (sc->sc_type == WM_T_PCH_CNP)); |
|| (sc->sc_type == WM_T_PCH_CNP)); |
Line 16943 wm_legacy_irq_quirk_spt(struct wm_softc |
|
Line 17112 wm_legacy_irq_quirk_spt(struct wm_softc |
|
reg |= FEXTNVM9_IOSFSB_CLKGATE_DIS | FEXTNVM9_IOSFSB_CLKREQ_DIS; |
reg |= FEXTNVM9_IOSFSB_CLKGATE_DIS | FEXTNVM9_IOSFSB_CLKREQ_DIS; |
CSR_WRITE(sc, WMREG_FEXTNVM9, reg); |
CSR_WRITE(sc, WMREG_FEXTNVM9, reg); |
} |
} |
|
|
|
/* Sysctl function */ |
|
#ifdef WM_DEBUG |
|
static int |
|
wm_sysctl_debug(SYSCTLFN_ARGS) |
|
{ |
|
struct sysctlnode node = *rnode; |
|
struct wm_softc *sc = (struct wm_softc *)node.sysctl_data; |
|
uint32_t dflags; |
|
int error; |
|
|
|
dflags = sc->sc_debug; |
|
node.sysctl_data = &dflags; |
|
error = sysctl_lookup(SYSCTLFN_CALL(&node)); |
|
|
|
if (error || newp == NULL) |
|
return error; |
|
|
|
sc->sc_debug = dflags; |
|
|
|
return 0; |
|
} |
|
#endif |