Subject: powerhook for wm(4) + ath(4)
To: None <netbsd-users@NetBSD.org>
From: Alexander Becher <abecher@kawo2.rwth-aachen.de>
List: netbsd-users
Date: 08/28/2005 22:49:39
--Boundary_(ID_vnDns2RqMHomvcuGybsKtA)
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8BIT
Content-disposition: inline
Hi everyone,
I have attached a patch to add a powerhook to the PCI network
interfaces wm and ath. It is against the netbsd-3 branch. I have drawn
upon if_rtk_pci.c for "inspiration". The patch makes both interfaces
survive an APM suspend/resume on an IBM Thinkpad X40.
I also have a patch for NetBSD 2.0 for both interfaces, but it is not
using pci_conf_capture/pci_conf_restore and is really just a hack (but
it worked).
Annoyingly, the interfaces only become usable after about 30 seconds,
which was not the case with the patch against netbsd-2. The same is
however also true for auich(4), so it's probably due to some other part
of the system.
Maybe someone will find it useful.
Regards
Alexander Becher
--
PGP key available
Port Payé / Entgelt bezahlt / Postage Paid: http://www.hashcash.org/
--Boundary_(ID_vnDns2RqMHomvcuGybsKtA)
Content-type: text/plain; charset=us-ascii; NAME=wm+ath-powerhook-netbsd3.patch
Content-transfer-encoding: 7BIT
Content-disposition: attachment; filename=wm+ath-powerhook-netbsd3.patch
Index: if_ath_pci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_ath_pci.c,v
retrieving revision 1.8
diff -u -r1.8 if_ath_pci.c
--- if_ath_pci.c 27 Feb 2005 00:27:32 -0000 1.8
+++ if_ath_pci.c 21 Aug 2005 19:37:52 -0000
@@ -96,7 +96,10 @@
struct resource *sc_sr; /* memory resource */
struct resource *sc_irq; /* irq resource */
#else
+ void *sc_powerhook;
pci_chipset_tag_t sc_pc;
+ pcitag_t sc_pcitag;
+ struct pci_conf_state sc_pciconf;
#endif
void *sc_ih; /* intererupt handler */
u_int8_t sc_saved_intline;
@@ -109,6 +112,7 @@
static int ath_pci_match(struct device *, struct cfdata *, void *);
static void ath_pci_attach(struct device *, struct device *, void *);
static void ath_pci_shutdown(void *);
+static void ath_pci_power(int, void *);
static int ath_pci_detach(struct device *, int);
CFATTACH_DECL(ath_pci,
@@ -225,6 +229,12 @@
goto bad3;
}
+ psc->sc_pcitag = pa->pa_tag;
+ psc->sc_powerhook = powerhook_establish(ath_pci_power, psc);
+ if (psc->sc_powerhook == NULL)
+ aprint_error("%s: WARNING: unable to establish power hook\n",
+ sc->sc_dev.dv_xname);
+
if (ath_attach(ath_product(pa->pa_id), sc) == 0)
return;
@@ -255,3 +265,26 @@
ath_shutdown(&psc->sc_sc);
}
+
+static void
+ath_pci_power(int why, void *arg)
+{
+ struct ath_pci_softc *psc = arg;
+ int s;
+
+ s = splnet();
+ switch (why) {
+ case PWR_SUSPEND:
+ case PWR_STANDBY:
+ pci_conf_capture(psc->sc_pc, psc->sc_pcitag, &psc->sc_pciconf);
+ break;
+ case PWR_RESUME:
+ pci_conf_restore(psc->sc_pc, psc->sc_pcitag, &psc->sc_pciconf);
+ break;
+ case PWR_SOFTSUSPEND:
+ case PWR_SOFTSTANDBY:
+ case PWR_SOFTRESUME:
+ break;
+ }
+ splx(s);
+}
Index: if_wm.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_wm.c,v
retrieving revision 1.100.2.2
diff -u -r1.100.2.2 if_wm.c
--- if_wm.c 28 Apr 2005 11:03:16 -0000 1.100.2.2
+++ if_wm.c 21 Aug 2005 19:37:52 -0000
@@ -227,6 +227,7 @@
bus_dma_tag_t sc_dmat; /* bus DMA tag */
struct ethercom sc_ethercom; /* ethernet common data */
void *sc_sdhook; /* shutdown hook */
+ void *sc_powerhook; /* power management hook */
wm_chip_type sc_type; /* chip type */
int sc_flags; /* flags; see below */
@@ -235,6 +236,9 @@
int sc_flowflags; /* 802.3x flow control flags */
void *sc_ih; /* interrupt cookie */
+ pci_chipset_tag_t sc_pc; /* PCI chipset tag */
+ pcitag_t sc_pcitag; /* PCI register tag */
+ struct pci_conf_state sc_pciconf; /* PCI configuration state */
int sc_ee_addrbits; /* EEPROM address bits */
@@ -495,6 +499,8 @@
static int wm_match(struct device *, struct cfdata *, void *);
static void wm_attach(struct device *, struct device *, void *);
+static void wm_power(int, void *);
+
CFATTACH_DECL(wm, sizeof(struct wm_softc),
wm_match, wm_attach, NULL, NULL);
@@ -1299,6 +1305,15 @@
if (sc->sc_sdhook == NULL)
aprint_error("%s: WARNING: unable to establish shutdown hook\n",
sc->sc_dev.dv_xname);
+
+ sc->sc_pc = pc;
+ sc->sc_pcitag = pa->pa_tag;
+
+ sc->sc_powerhook = powerhook_establish(wm_power, sc);
+ if (sc->sc_powerhook == NULL)
+ aprint_error("%s: WARNING: unable to establish power hook\n",
+ sc->sc_dev.dv_xname);
+
return;
/*
@@ -3848,3 +3863,26 @@
CSR_WRITE(sc, (sc->sc_type < WM_T_82543) ? WMREG_OLD_FCRTL
: WMREG_FCRTL, sc->sc_fcrtl);
}
+
+static void
+wm_power(int why, void *arg)
+{
+ struct wm_softc *sc = arg;
+ int s;
+
+ s = splnet();
+ switch (why) {
+ case PWR_SUSPEND:
+ case PWR_STANDBY:
+ pci_conf_capture(sc->sc_pc, sc->sc_pcitag, &sc->sc_pciconf);
+ break;
+ case PWR_RESUME:
+ pci_conf_restore(sc->sc_pc, sc->sc_pcitag, &sc->sc_pciconf);
+ break;
+ case PWR_SOFTSUSPEND:
+ case PWR_SOFTSTANDBY:
+ case PWR_SOFTRESUME:
+ break;
+ }
+ splx(s);
+}
--Boundary_(ID_vnDns2RqMHomvcuGybsKtA)--