From 0727ce2f2c1f04c717834bad94df7b752fe070a7 Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 4 Aug 2010 19:48:33 +0000 Subject: [PATCH] add suspend/resume support for PCI ral(4) devices. ok deraadt@, sthen@ tested by matthew@ (RT2560), dcoppa@ (RT2790), okan@ (RT2860), todd@ (RT2560) --- sys/dev/ic/rt2560.c | 26 ++++++-- sys/dev/ic/rt2560var.h | 4 +- sys/dev/ic/rt2661.c | 141 ++++++++++++++++++++++----------------- sys/dev/ic/rt2661var.h | 12 ++-- sys/dev/ic/rt2860.c | 108 ++++++++++++++++++------------ sys/dev/ic/rt2860var.h | 12 ++-- sys/dev/pci/if_ral_pci.c | 47 ++++++++++++- 7 files changed, 231 insertions(+), 119 deletions(-) diff --git a/sys/dev/ic/rt2560.c b/sys/dev/ic/rt2560.c index 634eb1cd45e..51499087a4a 100644 --- a/sys/dev/ic/rt2560.c +++ b/sys/dev/ic/rt2560.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2560.c,v 1.48 2010/05/19 15:27:35 oga Exp $ */ +/* $OpenBSD: rt2560.c,v 1.49 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2005, 2006 @@ -334,6 +334,24 @@ rt2560_detach(void *xsc) return 0; } +void +rt2560_suspend(void *xsc) +{ + struct rt2560_softc *sc = xsc; + struct ifnet *ifp = &sc->sc_ic.ic_if; + + if (ifp->if_flags & IFF_RUNNING) + rt2560_stop(ifp, 0); +} + +void +rt2560_resume(void *xsc) +{ + struct rt2560_softc *sc = xsc; + + rt2560_power(PWR_RESUME, sc); +} + int rt2560_alloc_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring, int count) @@ -2717,13 +2735,11 @@ rt2560_power(int why, void *arg) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - DPRINTF(("%s: rt2560_power(%d)\n", sc->sc_dev.dv_xname, why)); - s = splnet(); switch (why) { case PWR_SUSPEND: case PWR_STANDBY: - rt2560_stop(ifp, 1); + rt2560_stop(ifp, 0); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); break; @@ -2732,8 +2748,6 @@ rt2560_power(int why, void *arg) rt2560_init(ifp); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); - if (ifp->if_flags & IFF_RUNNING) - rt2560_start(ifp); } break; } diff --git a/sys/dev/ic/rt2560var.h b/sys/dev/ic/rt2560var.h index e2695083004..d6b94320dfd 100644 --- a/sys/dev/ic/rt2560var.h +++ b/sys/dev/ic/rt2560var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2560var.h,v 1.6 2009/08/10 17:47:23 damien Exp $ */ +/* $OpenBSD: rt2560var.h,v 1.7 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2005, 2006 @@ -167,4 +167,6 @@ struct rt2560_softc { int rt2560_attach(void *, int); int rt2560_detach(void *); +void rt2560_suspend(void *); +void rt2560_resume(void *); int rt2560_intr(void *); diff --git a/sys/dev/ic/rt2661.c b/sys/dev/ic/rt2661.c index b9ce6f07b20..ca351be844b 100644 --- a/sys/dev/ic/rt2661.c +++ b/sys/dev/ic/rt2661.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2661.c,v 1.54 2010/05/19 15:27:35 oga Exp $ */ +/* $OpenBSD: rt2661.c,v 1.55 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2006 @@ -74,6 +74,7 @@ int rt2661_debug = 1; #define DPRINTFN(n, x) #endif +void rt2661_attachhook(void *); int rt2661_alloc_tx_ring(struct rt2661_softc *, struct rt2661_tx_ring *, int); void rt2661_reset_tx_ring(struct rt2661_softc *, @@ -144,8 +145,7 @@ void rt2661_read_eeprom(struct rt2661_softc *); int rt2661_bbp_init(struct rt2661_softc *); int rt2661_init(struct ifnet *); void rt2661_stop(struct ifnet *, int); -int rt2661_load_microcode(struct rt2661_softc *, const uint8_t *, - int); +int rt2661_load_microcode(struct rt2661_softc *); void rt2661_rx_tune(struct rt2661_softc *); #ifdef notyet void rt2661_radar_start(struct rt2661_softc *); @@ -186,9 +186,8 @@ rt2661_attach(void *xsc, int id) { struct rt2661_softc *sc = xsc; struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; uint32_t val; - int error, ac, i, ntries; + int error, ac, ntries; sc->sc_id = id; @@ -243,6 +242,51 @@ rt2661_attach(void *xsc, int id) goto fail2; } + if (rootvp == NULL) + mountroothook_establish(rt2661_attachhook, sc); + else + rt2661_attachhook(sc); + + sc->sc_powerhook = powerhook_establish(rt2661_power, sc); + if (sc->sc_powerhook == NULL) { + printf("%s: WARNING: unable to establish power hook\n", + sc->sc_dev.dv_xname); + } + + return 0; + +fail2: rt2661_free_tx_ring(sc, &sc->mgtq); +fail1: while (--ac >= 0) + rt2661_free_tx_ring(sc, &sc->txq[ac]); + return ENXIO; +} + +void +rt2661_attachhook(void *xsc) +{ + struct rt2661_softc *sc = xsc; + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; + const char *name = NULL; /* make lint happy */ + int i, error; + + switch (sc->sc_id) { + case PCI_PRODUCT_RALINK_RT2561: + name = "ral-rt2561"; + break; + case PCI_PRODUCT_RALINK_RT2561S: + name = "ral-rt2561s"; + break; + case PCI_PRODUCT_RALINK_RT2661: + name = "ral-rt2661"; + break; + } + if ((error = loadfirmware(name, &sc->ucode, &sc->ucsize)) != 0) { + printf("%s: error %d, could not read firmware %s\n", + sc->sc_dev.dv_xname, error, name); + return; + } + ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ ic->ic_state = IEEE80211_S_INIT; @@ -328,19 +372,6 @@ rt2661_attach(void *xsc, int id) sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); sc->sc_txtap.wt_ihdr.it_present = htole32(RT2661_TX_RADIOTAP_PRESENT); #endif - - sc->sc_powerhook = powerhook_establish(rt2661_power, sc); - if (sc->sc_powerhook == NULL) { - printf("%s: WARNING: unable to establish power hook\n", - sc->sc_dev.dv_xname); - } - - return 0; - -fail2: rt2661_free_tx_ring(sc, &sc->mgtq); -fail1: while (--ac >= 0) - rt2661_free_tx_ring(sc, &sc->txq[ac]); - return ENXIO; } int @@ -364,9 +395,30 @@ rt2661_detach(void *xsc) rt2661_free_tx_ring(sc, &sc->mgtq); rt2661_free_rx_ring(sc, &sc->rxq); + if (sc->ucode != NULL) + free(sc->ucode, M_DEVBUF); + return 0; } +void +rt2661_suspend(void *xsc) +{ + struct rt2661_softc *sc = xsc; + struct ifnet *ifp = &sc->sc_ic.ic_if; + + if (ifp->if_flags & IFF_RUNNING) + rt2661_stop(ifp, 0); +} + +void +rt2661_resume(void *xsc) +{ + struct rt2661_softc *sc = xsc; + + rt2661_power(PWR_RESUME, sc); +} + int rt2661_alloc_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring, int count) @@ -2404,11 +2456,8 @@ rt2661_init(struct ifnet *ifp) { struct rt2661_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; - const char *name = NULL; /* make lint happy */ - uint8_t *ucode; - size_t size; uint32_t tmp, sta[3]; - int i, ntries, error; + int i, ntries; /* for CardBus, power on the socket */ if (!(sc->sc_flags & RT2661_ENABLED)) { @@ -2422,36 +2471,11 @@ rt2661_init(struct ifnet *ifp) rt2661_stop(ifp, 0); - if (!(sc->sc_flags & RT2661_FWLOADED)) { - switch (sc->sc_id) { - case PCI_PRODUCT_RALINK_RT2561: - name = "ral-rt2561"; - break; - case PCI_PRODUCT_RALINK_RT2561S: - name = "ral-rt2561s"; - break; - case PCI_PRODUCT_RALINK_RT2661: - name = "ral-rt2661"; - break; - } - - if ((error = loadfirmware(name, &ucode, &size)) != 0) { - printf("%s: error %d, could not read firmware %s\n", - sc->sc_dev.dv_xname, error, name); - rt2661_stop(ifp, 1); - return EIO; - } - - if (rt2661_load_microcode(sc, ucode, size) != 0) { - printf("%s: could not load 8051 microcode\n", - sc->sc_dev.dv_xname); - free(ucode, M_DEVBUF); - rt2661_stop(ifp, 1); - return EIO; - } - - free(ucode, M_DEVBUF); - sc->sc_flags |= RT2661_FWLOADED; + if (rt2661_load_microcode(sc) != 0) { + printf("%s: could not load 8051 microcode\n", + sc->sc_dev.dv_xname); + rt2661_stop(ifp, 1); + return EIO; } /* initialize Tx rings */ @@ -2614,13 +2638,13 @@ rt2661_stop(struct ifnet *ifp, int disable) if (disable && sc->sc_disable != NULL) { if (sc->sc_flags & RT2661_ENABLED) { (*sc->sc_disable)(sc); - sc->sc_flags &= ~(RT2661_ENABLED | RT2661_FWLOADED); + sc->sc_flags &= ~RT2661_ENABLED; } } } int -rt2661_load_microcode(struct rt2661_softc *sc, const uint8_t *ucode, int size) +rt2661_load_microcode(struct rt2661_softc *sc) { int ntries; @@ -2634,7 +2658,7 @@ rt2661_load_microcode(struct rt2661_softc *sc, const uint8_t *ucode, int size) /* write 8051's microcode */ RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET | RT2661_MCU_SEL); - RAL_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, ucode, size); + RAL_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, sc->ucode, sc->ucsize); RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET); /* kick 8051's ass */ @@ -2906,14 +2930,11 @@ rt2661_power(int why, void *arg) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - DPRINTF(("%s: rt2661_power(%d)\n", sc->sc_dev.dv_xname, why)); - s = splnet(); switch (why) { case PWR_SUSPEND: case PWR_STANDBY: - rt2661_stop(ifp, 1); - sc->sc_flags &= ~RT2661_FWLOADED; + rt2661_stop(ifp, 0); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); break; @@ -2922,8 +2943,6 @@ rt2661_power(int why, void *arg) rt2661_init(ifp); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); - if (ifp->if_flags & IFF_RUNNING) - rt2661_start(ifp); } break; } diff --git a/sys/dev/ic/rt2661var.h b/sys/dev/ic/rt2661var.h index 7793ade66b5..b426a8b4d47 100644 --- a/sys/dev/ic/rt2661var.h +++ b/sys/dev/ic/rt2661var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2661var.h,v 1.10 2009/08/10 17:47:23 damien Exp $ */ +/* $OpenBSD: rt2661var.h,v 1.11 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2006 @@ -109,14 +109,16 @@ struct rt2661_softc { int sc_id; int sc_flags; #define RT2661_ENABLED (1 << 0) -#define RT2661_FWLOADED (1 << 1) -#define RT2661_UPDATE_SLOT (1 << 2) -#define RT2661_SET_SLOTTIME (1 << 3) +#define RT2661_UPDATE_SLOT (1 << 1) +#define RT2661_SET_SLOTTIME (1 << 2) int sc_tx_timer; struct ieee80211_channel *sc_curchan; + u_char *ucode; + size_t ucsize; + uint8_t rf_rev; uint8_t rfprog; @@ -178,4 +180,6 @@ struct rt2661_softc { int rt2661_attach(void *, int); int rt2661_detach(void *); +void rt2661_suspend(void *); +void rt2661_resume(void *); int rt2661_intr(void *); diff --git a/sys/dev/ic/rt2860.c b/sys/dev/ic/rt2860.c index 88ecaa7cd4d..25b6a782968 100644 --- a/sys/dev/ic/rt2860.c +++ b/sys/dev/ic/rt2860.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2860.c,v 1.56 2010/07/19 19:47:52 damien Exp $ */ +/* $OpenBSD: rt2860.c,v 1.57 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2007-2010 Damien Bergamini @@ -78,6 +78,7 @@ int rt2860_debug = 0; #define DPRINTFN(n, x) #endif +void rt2860_attachhook(void *); int rt2860_alloc_tx_ring(struct rt2860_softc *, struct rt2860_tx_ring *); void rt2860_reset_tx_ring(struct rt2860_softc *, @@ -206,8 +207,7 @@ rt2860_attach(void *xsc, int id) { struct rt2860_softc *sc = xsc; struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - int i, qid, ntries, error; + int qid, ntries, error; uint32_t tmp; sc->amrr.amrr_min_success_threshold = 1; @@ -272,6 +272,40 @@ rt2860_attach(void *xsc, int id) sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ? EDCA_AC_VO : 5; + if (rootvp == NULL) + mountroothook_establish(rt2860_attachhook, sc); + else + rt2860_attachhook(sc); + + sc->sc_powerhook = powerhook_establish(rt2860_power, sc); + if (sc->sc_powerhook == NULL) { + printf("%s: WARNING: unable to establish power hook\n", + sc->sc_dev.dv_xname); + } + + return 0; + +fail2: rt2860_free_rx_ring(sc, &sc->rxq); +fail1: while (--qid >= 0) + rt2860_free_tx_ring(sc, &sc->txq[qid]); + return error; +} + +void +rt2860_attachhook(void *xsc) +{ + struct rt2860_softc *sc = xsc; + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; + int i, error; + + error = loadfirmware("ral-rt2860", &sc->ucode, &sc->ucsize); + if (error != 0) { + printf("%s: error %d, could not read firmware file %s\n", + sc->sc_dev.dv_xname, error, "ral-rt2860"); + return; + } + ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ ic->ic_state = IEEE80211_S_INIT; @@ -362,19 +396,6 @@ rt2860_attach(void *xsc, int id) sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); sc->sc_txtap.wt_ihdr.it_present = htole32(RT2860_TX_RADIOTAP_PRESENT); #endif - - sc->sc_powerhook = powerhook_establish(rt2860_power, sc); - if (sc->sc_powerhook == NULL) { - printf("%s: WARNING: unable to establish power hook\n", - sc->sc_dev.dv_xname); - } - - return 0; - -fail2: rt2860_free_rx_ring(sc, &sc->rxq); -fail1: while (--qid >= 0) - rt2860_free_tx_ring(sc, &sc->txq[qid]); - return error; } int @@ -395,9 +416,30 @@ rt2860_detach(void *xsc) rt2860_free_rx_ring(sc, &sc->rxq); rt2860_free_tx_pool(sc); + if (sc->ucode != NULL) + free(sc->ucode, M_DEVBUF); + return 0; } +void +rt2860_suspend(void *xsc) +{ + struct rt2860_softc *sc = xsc; + struct ifnet *ifp = &sc->sc_ic.ic_if; + + if (ifp->if_flags & IFF_RUNNING) + rt2860_stop(ifp, 0); +} + +void +rt2860_resume(void *xsc) +{ + struct rt2860_softc *sc = xsc; + + rt2860_power(PWR_RESUME, sc); +} + int rt2860_alloc_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) { @@ -3340,14 +3382,11 @@ rt2860_init(struct ifnet *ifp) RAL_BARRIER_WRITE(sc); RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe00); - if (!(sc->sc_flags & RT2860_FWLOADED)) { - if ((error = rt2860_load_microcode(sc)) != 0) { - printf("%s: could not load 8051 microcode\n", - sc->sc_dev.dv_xname); - rt2860_stop(ifp, 1); - return error; - } - sc->sc_flags |= RT2860_FWLOADED; + if ((error = rt2860_load_microcode(sc)) != 0) { + printf("%s: could not load 8051 microcode\n", + sc->sc_dev.dv_xname); + rt2860_stop(ifp, 1); + return error; } IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl)); @@ -3620,7 +3659,7 @@ rt2860_stop(struct ifnet *ifp, int disable) if (disable && sc->sc_disable != NULL) { if (sc->sc_flags & RT2860_ENABLED) { (*sc->sc_disable)(sc); - sc->sc_flags &= ~(RT2860_ENABLED | RT2860_FWLOADED); + sc->sc_flags &= ~RT2860_ENABLED; } } } @@ -3628,20 +3667,12 @@ rt2860_stop(struct ifnet *ifp, int disable) int rt2860_load_microcode(struct rt2860_softc *sc) { - u_char *ucode; - size_t size; - int error, ntries; - - if ((error = loadfirmware("ral-rt2860", &ucode, &size)) != 0) { - printf("%s: error %d, could not read firmware file %s\n", - sc->sc_dev.dv_xname, error, "ral-rt2860"); - return error; - } + int ntries; /* set "host program ram write selection" bit */ RAL_WRITE(sc, RT2860_SYS_CTRL, RT2860_HST_PM_SEL); /* write microcode image */ - RAL_WRITE_REGION_1(sc, RT2860_FW_BASE, ucode, size); + RAL_WRITE_REGION_1(sc, RT2860_FW_BASE, sc->ucode, sc->ucsize); /* kick microcontroller unit */ RAL_WRITE(sc, RT2860_SYS_CTRL, 0); RAL_BARRIER_WRITE(sc); @@ -3650,8 +3681,6 @@ rt2860_load_microcode(struct rt2860_softc *sc) RAL_WRITE(sc, RT2860_H2M_BBPAGENT, 0); RAL_WRITE(sc, RT2860_H2M_MAILBOX, 0); - free(ucode, M_DEVBUF); - /* wait until microcontroller is ready */ RAL_BARRIER_READ_WRITE(sc); for (ntries = 0; ntries < 1000; ntries++) { @@ -3845,8 +3874,7 @@ rt2860_power(int why, void *arg) switch (why) { case PWR_SUSPEND: case PWR_STANDBY: - rt2860_stop(ifp, 1); - sc->sc_flags &= ~RT2860_FWLOADED; + rt2860_stop(ifp, 0); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); break; @@ -3855,8 +3883,6 @@ rt2860_power(int why, void *arg) rt2860_init(ifp); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); - if (ifp->if_flags & IFF_RUNNING) - rt2860_start(ifp); } break; } diff --git a/sys/dev/ic/rt2860var.h b/sys/dev/ic/rt2860var.h index 1fd4a042010..5a1b538fe96 100644 --- a/sys/dev/ic/rt2860var.h +++ b/sys/dev/ic/rt2860var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2860var.h,v 1.17 2010/07/19 19:47:52 damien Exp $ */ +/* $OpenBSD: rt2860var.h,v 1.18 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2007 @@ -123,13 +123,15 @@ struct rt2860_softc { int sc_flags; #define RT2860_ENABLED (1 << 0) -#define RT2860_FWLOADED (1 << 1) -#define RT2860_ADVANCED_PS (1 << 2) -#define RT2860_PCIE (1 << 3) +#define RT2860_ADVANCED_PS (1 << 1) +#define RT2860_PCIE (1 << 2) uint32_t sc_ic_flags; int fixed_ridx; + u_char *ucode; + size_t ucsize; + struct rt2860_tx_ring txq[6]; struct rt2860_rx_ring rxq; @@ -202,4 +204,6 @@ struct rt2860_softc { int rt2860_attach(void *, int); int rt2860_detach(void *); +void rt2860_suspend(void *); +void rt2860_resume(void *); int rt2860_intr(void *); diff --git a/sys/dev/pci/if_ral_pci.c b/sys/dev/pci/if_ral_pci.c index ac1eaae7835..795c3cb97e5 100644 --- a/sys/dev/pci/if_ral_pci.c +++ b/sys/dev/pci/if_ral_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ral_pci.c,v 1.19 2010/04/05 14:14:02 damien Exp $ */ +/* $OpenBSD: if_ral_pci.c,v 1.20 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2005-2010 Damien Bergamini @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -57,21 +58,29 @@ static struct ral_opns { int (*attach)(void *, int); int (*detach)(void *); + void (*suspend)(void *); + void (*resume)(void *); int (*intr)(void *); } ral_rt2560_opns = { rt2560_attach, rt2560_detach, + rt2560_suspend, + rt2560_resume, rt2560_intr }, ral_rt2661_opns = { rt2661_attach, rt2661_detach, + rt2661_suspend, + rt2661_resume, rt2661_intr }, ral_rt2860_opns = { rt2860_attach, rt2860_detach, + rt2860_suspend, + rt2860_resume, rt2860_intr }; @@ -88,6 +97,7 @@ struct ral_pci_softc { pci_chipset_tag_t sc_pc; void *sc_ih; bus_size_t sc_mapsize; + struct workq_task sc_resume_wqt; }; /* Base Address Register */ @@ -96,10 +106,12 @@ struct ral_pci_softc { int ral_pci_match(struct device *, void *, void *); void ral_pci_attach(struct device *, struct device *, void *); int ral_pci_detach(struct device *, int); +int ral_pci_activate(struct device *, int); +void ral_pci_resume(void *, void *); struct cfattach ral_pci_ca = { sizeof (struct ral_pci_softc), ral_pci_match, ral_pci_attach, - ral_pci_detach + ral_pci_detach, ral_pci_activate }; const struct pci_matchid ral_pci_devices[] = { @@ -216,3 +228,34 @@ ral_pci_detach(struct device *self, int flags) return 0; } + +int +ral_pci_activate(struct device *self, int act) +{ + struct ral_pci_softc *psc = (struct ral_pci_softc *)self; + struct rt2560_softc *sc = &psc->sc_sc; + + switch (act) { + case DVACT_SUSPEND: + (*psc->sc_opns->suspend)(sc); + break; + case DVACT_RESUME: + workq_queue_task(NULL, &psc->sc_resume_wqt, 0, + ral_pci_resume, psc, NULL); + break; + } + + return 0; +} + +void +ral_pci_resume(void *arg1, void *arg2) +{ + struct ral_pci_softc *psc = arg1; + struct rt2560_softc *sc = &psc->sc_sc; + int s; + + s = splnet(); + (*psc->sc_opns->resume)(sc); + splx(s); +} -- 2.20.1