Implement WOL capability.
- Turn on WOL bits in suspend/shutdown method. - WOL is disabled in resume routine as WOL can interfere normal Rx operation. - Move stge_reset() to stge_init_locked() as resetting hardware clears configured Rx information which in turn results in non-working Rx module after suspend/shutdown operation.
This commit is contained in:
parent
6180b9de75
commit
346de09f2a
@ -187,6 +187,7 @@ static int stge_init_rx_ring(struct stge_softc *);
|
||||
static void stge_poll(struct ifnet *, enum poll_cmd, int);
|
||||
#endif
|
||||
|
||||
static void stge_setwol(struct stge_softc *);
|
||||
static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
|
||||
static int sysctl_hw_stge_rxint_nframe(SYSCTL_HANDLER_ARGS);
|
||||
static int sysctl_hw_stge_rxint_dmawait(SYSCTL_HANDLER_ARGS);
|
||||
@ -736,6 +737,7 @@ stge_attach(device_t dev)
|
||||
ifp->if_hwassist = 0;
|
||||
ifp->if_capabilities = 0;
|
||||
}
|
||||
ifp->if_capabilities |= IFCAP_WOL_MAGIC;
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
|
||||
/*
|
||||
@ -1121,15 +1123,33 @@ stge_dma_free(struct stge_softc *sc)
|
||||
static int
|
||||
stge_shutdown(device_t dev)
|
||||
{
|
||||
struct stge_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
return (stge_suspend(dev));
|
||||
}
|
||||
|
||||
STGE_LOCK(sc);
|
||||
stge_stop(sc);
|
||||
STGE_UNLOCK(sc);
|
||||
static void
|
||||
stge_setwol(struct stge_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
uint8_t v;
|
||||
|
||||
return (0);
|
||||
STGE_LOCK_ASSERT(sc);
|
||||
|
||||
ifp = sc->sc_ifp;
|
||||
v = CSR_READ_1(sc, STGE_WakeEvent);
|
||||
/* Disable all WOL bits. */
|
||||
v &= ~(WE_WakePktEnable | WE_MagicPktEnable | WE_LinkEventEnable |
|
||||
WE_WakeOnLanEnable);
|
||||
if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
|
||||
v |= WE_MagicPktEnable | WE_WakeOnLanEnable;
|
||||
CSR_WRITE_1(sc, STGE_WakeEvent, v);
|
||||
/* Reset Tx and prevent transmission. */
|
||||
CSR_WRITE_4(sc, STGE_AsicCtrl,
|
||||
CSR_READ_4(sc, STGE_AsicCtrl) | AC_TxReset);
|
||||
/*
|
||||
* TC9021 automatically reset link speed to 100Mbps when it's put
|
||||
* into sleep so there is no need to try to resetting link speed.
|
||||
*/
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1142,6 +1162,7 @@ stge_suspend(device_t dev)
|
||||
STGE_LOCK(sc);
|
||||
stge_stop(sc);
|
||||
sc->sc_suspended = 1;
|
||||
stge_setwol(sc);
|
||||
STGE_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
@ -1152,10 +1173,19 @@ stge_resume(device_t dev)
|
||||
{
|
||||
struct stge_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
uint8_t v;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
STGE_LOCK(sc);
|
||||
/*
|
||||
* Clear WOL bits, so special frames wouldn't interfere
|
||||
* normal Rx operation anymore.
|
||||
*/
|
||||
v = CSR_READ_1(sc, STGE_WakeEvent);
|
||||
v &= ~(WE_WakePktEnable | WE_MagicPktEnable | WE_LinkEventEnable |
|
||||
WE_WakeOnLanEnable);
|
||||
CSR_WRITE_1(sc, STGE_WakeEvent, v);
|
||||
ifp = sc->sc_ifp;
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
stge_init_locked(sc);
|
||||
@ -1450,6 +1480,11 @@ stge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
else
|
||||
ifp->if_hwassist = 0;
|
||||
}
|
||||
if ((mask & IFCAP_WOL) != 0 &&
|
||||
(ifp->if_capabilities & IFCAP_WOL) != 0) {
|
||||
if ((mask & IFCAP_WOL_MAGIC) != 0)
|
||||
ifp->if_capenable ^= IFCAP_WOL_MAGIC;
|
||||
}
|
||||
if ((mask & IFCAP_VLAN_HWTAGGING) != 0) {
|
||||
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
|
||||
@ -2096,6 +2131,11 @@ stge_init_locked(struct stge_softc *sc)
|
||||
*/
|
||||
stge_stop(sc);
|
||||
|
||||
/*
|
||||
* Reset the chip to a known state.
|
||||
*/
|
||||
stge_reset(sc, STGE_RESET_FULL);
|
||||
|
||||
/* Init descriptors. */
|
||||
error = stge_init_rx_ring(sc);
|
||||
if (error != 0) {
|
||||
@ -2308,11 +2348,6 @@ stge_stop(struct stge_softc *sc)
|
||||
callout_stop(&sc->sc_tick_ch);
|
||||
sc->sc_watchdog_timer = 0;
|
||||
|
||||
/*
|
||||
* Reset the chip to a known state.
|
||||
*/
|
||||
stge_reset(sc, STGE_RESET_FULL);
|
||||
|
||||
/*
|
||||
* Disable interrupts.
|
||||
*/
|
||||
|
@ -314,6 +314,14 @@ struct stge_rfd {
|
||||
#define STGE_ExpRomData 0x50 /* 8-bit */
|
||||
|
||||
#define STGE_WakeEvent 0x51 /* 8-bit */
|
||||
#define WE_WakePktEnable (1U << 0)
|
||||
#define WE_MagicPktEnable (1U << 1)
|
||||
#define WE_LinkEventEnable (1U << 2)
|
||||
#define WE_WakePolarity (1U << 3)
|
||||
#define WE_WakePktEvent (1U << 4)
|
||||
#define WE_MagicPktEvent (1U << 5)
|
||||
#define WE_LinkEvent (1U << 6)
|
||||
#define WE_WakeOnLanEnable (1U << 7)
|
||||
|
||||
#define STGE_Countdown 0x54
|
||||
#define CD_Count(x) ((x) & 0xffff)
|
||||
|
Loading…
Reference in New Issue
Block a user