diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2010-08-30 20:33:19 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2010-08-30 20:33:19 +0000 |
commit | 1b9d5cf69aa6b4f17ba09d184d8d66a8966a1170 (patch) | |
tree | 68d3aa9318f2f86f0e64dfc5a68c9d88f9b8b3bf | |
parent | 1666f053551d1880fb077fa33820b96dfffbcc3e (diff) |
Convert the pcmcia power hook to an activate function. Then change the
model so that DVACT_SUSPEND methods call sub-drivers with DVACT_SUSPEND
not DVACT_DEACTIVATE, and such. This creates a whole bunch of fallout,
which needs fixing.
wdc(4), ne(4), and wi(4) have been fully tested and actually work better
than they ever have before (no more wdc timeouts on resume!)
malo(4) has some other nasty bug which has not yet been spotted which
causes crazy panics.
The other drivers are more rare and will be fixed if people show up
with hardware; for now at least they have been adapted to the new model.
ok kettenis
-rw-r--r-- | sys/dev/pcmcia/cfxga.c | 10 | ||||
-rw-r--r-- | sys/dev/pcmcia/com_pcmcia.c | 22 | ||||
-rw-r--r-- | sys/dev/pcmcia/gpr.c | 8 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_an_pcmcia.c | 13 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_cnw.c | 10 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_ep_pcmcia.c | 34 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_malo.c | 78 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_malovar.h | 5 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_ne_pcmcia.c | 36 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_ray.c | 13 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_sm_pcmcia.c | 10 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_wi_pcmcia.c | 48 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_xe.c | 39 | ||||
-rw-r--r-- | sys/dev/pcmcia/pcmcia.c | 67 | ||||
-rw-r--r-- | sys/dev/pcmcia/wdc_pcmcia.c | 96 |
15 files changed, 284 insertions, 205 deletions
diff --git a/sys/dev/pcmcia/cfxga.c b/sys/dev/pcmcia/cfxga.c index 32b84d6e648..ac7949ca9e4 100644 --- a/sys/dev/pcmcia/cfxga.c +++ b/sys/dev/pcmcia/cfxga.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cfxga.c,v 1.19 2009/10/13 19:33:16 pirofti Exp $ */ +/* $OpenBSD: cfxga.c,v 1.20 2010/08/30 20:33:18 deraadt Exp $ */ /* * Copyright (c) 2005, 2006, Matthieu Herrb and Miodrag Vallat @@ -319,12 +319,8 @@ cfxga_activate(struct device *dev, int act) switch (act) { case DVACT_ACTIVATE: - if (pcmcia_function_enable(sc->sc_pf) != 0) { - printf("%s: function enable failed\n", - sc->sc_dev.dv_xname); - } else { - cfxga_reset_and_repaint(sc); - } + pcmcia_function_enable(sc->sc_pf); + cfxga_reset_and_repaint(sc); break; case DVACT_DEACTIVATE: pcmcia_function_disable(sc->sc_pf); diff --git a/sys/dev/pcmcia/com_pcmcia.c b/sys/dev/pcmcia/com_pcmcia.c index 58ebfb4556f..daaae7816ba 100644 --- a/sys/dev/pcmcia/com_pcmcia.c +++ b/sys/dev/pcmcia/com_pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: com_pcmcia.c,v 1.50 2010/06/26 23:24:45 guenther Exp $ */ +/* $OpenBSD: com_pcmcia.c,v 1.51 2010/08/30 20:33:18 deraadt Exp $ */ /* $NetBSD: com_pcmcia.c,v 1.15 1998/08/22 17:47:58 msaitoh Exp $ */ /* @@ -210,22 +210,32 @@ com_pcmcia_activate(dev, act) int act; { struct com_pcmcia_softc *sc = (void *) dev; - int s; - s = spltty(); switch (act) { case DVACT_ACTIVATE: pcmcia_function_enable(sc->sc_pf); sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_TTY, comintr, sc, sc->sc_com.sc_dev.dv_xname); break; - + case DVACT_SUSPEND: + if (sc->sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; + pcmcia_function_disable(sc->sc_pf); + break; + case DVACT_RESUME: + pcmcia_function_enable(sc->sc_pf); + sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_TTY, + comintr, sc, sc->sc_com.sc_dev.dv_xname); + com_resume(&sc->sc_com); + break; case DVACT_DEACTIVATE: - pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + if (sc->sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); break; } - splx(s); return (0); } diff --git a/sys/dev/pcmcia/gpr.c b/sys/dev/pcmcia/gpr.c index 2a708216614..767b680ae79 100644 --- a/sys/dev/pcmcia/gpr.c +++ b/sys/dev/pcmcia/gpr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gpr.c,v 1.14 2009/10/29 08:03:16 fgsch Exp $ */ +/* $OpenBSD: gpr.c,v 1.15 2010/08/30 20:33:18 deraadt Exp $ */ /* * Copyright (c) 2002, Federico G. Schwindt @@ -247,13 +247,13 @@ gpr_activate(struct device *dev, int act) sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_TTY, gpr_intr, sc, sc->sc_dev.dv_xname); break; - case DVACT_DEACTIVATE: - pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + if (sc->sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); break; } - return (0); } diff --git a/sys/dev/pcmcia/if_an_pcmcia.c b/sys/dev/pcmcia/if_an_pcmcia.c index d5208d9f3d3..5acbddd40cc 100644 --- a/sys/dev/pcmcia/if_an_pcmcia.c +++ b/sys/dev/pcmcia/if_an_pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_an_pcmcia.c,v 1.20 2009/10/13 19:33:16 pirofti Exp $ */ +/* $OpenBSD: if_an_pcmcia.c,v 1.21 2010/08/30 20:33:18 deraadt Exp $ */ /* * Copyright (c) 1999 Michael Shalayeff @@ -130,7 +130,6 @@ an_pcmcia_attach(struct device *parent, struct device *self, void *aux) sc->sc_iot = psc->sc_pcioh.iot; sc->sc_ioh = psc->sc_pcioh.ioh; - sc->sc_enabled = 1; sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, an_intr, sc, sc->sc_dev.dv_xname); @@ -146,7 +145,6 @@ an_pcmcia_attach(struct device *parent, struct device *self, void *aux) return; } - sc->sc_enabled = 0; psc->sc_state = AN_PCMCIA_ATTACHED; } @@ -176,9 +174,7 @@ an_pcmcia_activate(struct device *dev, int act) struct an_softc *sc = &psc->sc_an; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - int s; - s = splnet(); switch (act) { case DVACT_ACTIVATE: pcmcia_function_enable(psc->sc_pf); @@ -186,16 +182,15 @@ an_pcmcia_activate(struct device *dev, int act) an_intr, sc, sc->sc_dev.dv_xname); an_init(ifp); break; - case DVACT_DEACTIVATE: ifp->if_timer = 0; if (ifp->if_flags & IFF_RUNNING) an_stop(ifp, 1); - pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); + if (sc->sc_ih) + pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; pcmcia_function_disable(psc->sc_pf); break; } - - splx(s); return (0); } diff --git a/sys/dev/pcmcia/if_cnw.c b/sys/dev/pcmcia/if_cnw.c index ea8d72cf14a..cf34c4e8ef7 100644 --- a/sys/dev/pcmcia/if_cnw.c +++ b/sys/dev/pcmcia/if_cnw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_cnw.c,v 1.20 2009/10/13 19:33:16 pirofti Exp $ */ +/* $OpenBSD: if_cnw.c,v 1.21 2010/08/30 20:33:18 deraadt Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. @@ -860,9 +860,7 @@ cnw_activate(dev, act) { struct cnw_softc *sc = (struct cnw_softc *)dev; struct ifnet *ifp = &sc->sc_arpcom.ac_if; - int s; - s = splnet(); switch (act) { case DVACT_ACTIVATE: pcmcia_function_enable(sc->sc_pf); @@ -870,14 +868,14 @@ cnw_activate(dev, act) cnw_intr, sc, sc->sc_dev.dv_xname); cnw_init(sc); break; - case DVACT_DEACTIVATE: ifp->if_timer = 0; ifp->if_flags &= ~IFF_RUNNING; /* XXX no cnw_stop() ? */ - pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + if (sc->sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); break; } - splx(s); return (0); } diff --git a/sys/dev/pcmcia/if_ep_pcmcia.c b/sys/dev/pcmcia/if_ep_pcmcia.c index fa14d7b539b..1b9f3222b4e 100644 --- a/sys/dev/pcmcia/if_ep_pcmcia.c +++ b/sys/dev/pcmcia/if_ep_pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ep_pcmcia.c,v 1.38 2009/10/13 19:33:16 pirofti Exp $ */ +/* $OpenBSD: if_ep_pcmcia.c,v 1.39 2010/08/30 20:33:18 deraadt Exp $ */ /* $NetBSD: if_ep_pcmcia.c,v 1.16 1998/08/17 23:20:40 thorpej Exp $ */ /*- @@ -408,26 +408,40 @@ ep_pcmcia_activate(dev, act) struct ep_pcmcia_softc *sc = (struct ep_pcmcia_softc *)dev; struct ep_softc *esc = &sc->sc_ep; struct ifnet *ifp = &esc->sc_arpcom.ac_if; - int s; - s = splnet(); switch (act) { case DVACT_ACTIVATE: + if (sc->sc_ep.sc_ih == NULL) { + pcmcia_function_enable(sc->sc_pf); + sc->sc_ep.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, + epintr, sc, esc->sc_dev.dv_xname); + } + if (ifp->if_flags & IFF_UP) + epinit(esc); + break; + case DVACT_SUSPEND: + ifp->if_timer = 0; + if (ifp->if_flags & IFF_RUNNING) + epstop(esc); + if (sc->sc_ep.sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ep.sc_ih); + sc->sc_ep.sc_ih = NULL; + pcmcia_function_disable(sc->sc_pf); + break; + case DVACT_RESUME: pcmcia_function_enable(sc->sc_pf); sc->sc_ep.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, epintr, sc, esc->sc_dev.dv_xname); - epinit(esc); + if (ifp->if_flags & IFF_UP) + epinit(esc); break; - case DVACT_DEACTIVATE: - ifp->if_timer = 0; - if (ifp->if_flags & IFF_RUNNING) - epstop(esc); - pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ep.sc_ih); + if (sc->sc_ep.sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ep.sc_ih); + sc->sc_ep.sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); break; } - splx(s); return (0); } diff --git a/sys/dev/pcmcia/if_malo.c b/sys/dev/pcmcia/if_malo.c index f97141ab59f..b4d4c400aa8 100644 --- a/sys/dev/pcmcia/if_malo.c +++ b/sys/dev/pcmcia/if_malo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_malo.c,v 1.70 2010/08/27 17:08:00 jsg Exp $ */ +/* $OpenBSD: if_malo.c,v 1.71 2010/08/30 20:33:18 deraadt Exp $ */ /* * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> @@ -29,6 +29,7 @@ #include <sys/malloc.h> #include <sys/sockio.h> #include <sys/mbuf.h> +#include <sys/workq.h> #if NBPFILTER > 0 #include <net/bpf.h> @@ -71,6 +72,7 @@ int malo_pcmcia_match(struct device *, void *, void *); void malo_pcmcia_attach(struct device *, struct device *, void *); int malo_pcmcia_detach(struct device *, int); int malo_pcmcia_activate(struct device *, int); +void malo_pcmcia_resume(void *, void *); void cmalo_attach(void *); int cmalo_ioctl(struct ifnet *, u_long, caddr_t); @@ -236,30 +238,64 @@ malo_pcmcia_activate(struct device *dev, int act) struct malo_softc *sc = &psc->sc_malo; struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - int s; - s = splnet(); switch (act) { case DVACT_ACTIVATE: pcmcia_function_enable(psc->sc_pf); psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, cmalo_intr, sc, sc->sc_dev.dv_xname); - cmalo_init(ifp); + workq_queue_task(NULL, &sc->sc_resume_wqt, 0, + malo_pcmcia_resume, sc, NULL); break; - case DVACT_DEACTIVATE: - ifp->if_timer = 0; - if (ifp->if_flags & IFF_RUNNING) + case DVACT_SUSPEND: + if ((sc->sc_flags & MALO_DEVICE_ATTACHED) && + (ifp->if_flags & IFF_RUNNING)) cmalo_stop(sc); - if (psc->sc_ih != NULL) + if (psc->sc_ih) pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); + psc->sc_ih = NULL; + pcmcia_function_disable(psc->sc_pf); + break; + case DVACT_RESUME: + pcmcia_function_enable(psc->sc_pf); + psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, + cmalo_intr, sc, sc->sc_dev.dv_xname); + workq_queue_task(NULL, &sc->sc_resume_wqt, 0, + malo_pcmcia_resume, sc, NULL); + break; + case DVACT_DEACTIVATE: + if ((sc->sc_flags & MALO_DEVICE_ATTACHED) && + (ifp->if_flags & IFF_RUNNING)) + cmalo_stop(sc); /* XXX tries to touch regs */ + if (psc->sc_ih) + pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); + psc->sc_ih = NULL; pcmcia_function_disable(psc->sc_pf); break; } - splx(s); - return (0); } +void +malo_pcmcia_resume(void *arg1, void *arg2) +{ + struct malo_softc *sc = arg1; + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; + int s; + + s = splnet(); + while (sc->sc_flags & MALO_BUSY) + tsleep(&sc->sc_flags, 0, "malopwr", 0); + sc->sc_flags |= MALO_BUSY; + + cmalo_init(ifp); + + sc->sc_flags &= ~MALO_BUSY; + wakeup(&sc->sc_flags); + splx(s); +} + /* * Driver. */ @@ -350,6 +386,17 @@ cmalo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) int i, j, s, error = 0; s = splnet(); + /* + * Prevent processes from entering this function while another + * process is tsleep'ing in it. + */ + while ((sc->sc_flags & MALO_BUSY) && error == 0) + error = tsleep(&sc->sc_flags, PCATCH, "maloioc", 0); + if (error != 0) { + splx(s); + return error; + } + sc->sc_flags |= MALO_BUSY; switch (cmd) { case SIOCSIFADDR: @@ -430,6 +477,8 @@ cmalo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = 0; } + sc->sc_flags &= ~MALO_BUSY; + wakeup(&sc->sc_flags); splx(s); return (error); @@ -587,7 +636,7 @@ cmalo_fw_load_main(struct malo_softc *sc) for (i = 0; i < bsize / 2; i++) MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); - MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, + MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_CMD_DL_OVER); /* poll for an acknowledgement */ @@ -648,8 +697,8 @@ cmalo_init(struct ifnet *ifp) sc->sc_flags &= ~MALO_ASSOC_FAILED; /* get current channel */ - ic->ic_bss->ni_chan = ic->ic_ibss_chan; - sc->sc_curchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); + ic->ic_bss->ni_chan = ic->ic_ibss_chan; + sc->sc_curchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); DPRINTF(1, "%s: current channel is %d\n", sc->sc_dev.dv_xname, sc->sc_curchan); @@ -704,7 +753,7 @@ void cmalo_stop(struct malo_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; + struct ifnet *ifp = &ic->ic_if; /* device down */ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); @@ -715,6 +764,7 @@ cmalo_stop(struct malo_softc *sc) /* reset device */ cmalo_cmd_set_reset(sc); sc->sc_flags &= ~MALO_FW_LOADED; + ifp->if_timer = 0; DPRINTF(1, "%s: device down\n", sc->sc_dev.dv_xname); } diff --git a/sys/dev/pcmcia/if_malovar.h b/sys/dev/pcmcia/if_malovar.h index 4ffbf7d65be..e98a19177f0 100644 --- a/sys/dev/pcmcia/if_malovar.h +++ b/sys/dev/pcmcia/if_malovar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_malovar.h,v 1.27 2007/10/09 20:37:32 mglocker Exp $ */ +/* $OpenBSD: if_malovar.h,v 1.28 2010/08/30 20:33:18 deraadt Exp $ */ /* * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> @@ -42,7 +42,7 @@ #define MALO_DEVICE_ATTACHED (1 << 0) #define MALO_FW_LOADED (1 << 1) #define MALO_ASSOC_FAILED (1 << 2) - +#define MALO_BUSY (1 << 3) /* * FW command structures */ @@ -365,4 +365,5 @@ struct malo_softc { int sc_net_cur; struct malo_networks sc_net[12]; struct timeout sc_scan_to; + struct workq_task sc_resume_wqt; }; diff --git a/sys/dev/pcmcia/if_ne_pcmcia.c b/sys/dev/pcmcia/if_ne_pcmcia.c index 0f15416c425..f96a14da897 100644 --- a/sys/dev/pcmcia/if_ne_pcmcia.c +++ b/sys/dev/pcmcia/if_ne_pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ne_pcmcia.c,v 1.93 2009/10/13 19:33:16 pirofti Exp $ */ +/* $OpenBSD: if_ne_pcmcia.c,v 1.94 2010/08/30 20:33:18 deraadt Exp $ */ /* $NetBSD: if_ne_pcmcia.c,v 1.17 1998/08/15 19:00:04 thorpej Exp $ */ /* @@ -865,29 +865,47 @@ ne_pcmcia_activate(dev, act) struct ne_pcmcia_softc *sc = (struct ne_pcmcia_softc *)dev; struct dp8390_softc *esc = &sc->sc_ne2000.sc_dp8390; struct ifnet *ifp = &esc->sc_arpcom.ac_if; - int s; - s = splnet(); switch (act) { case DVACT_ACTIVATE: pcmcia_function_enable(sc->sc_pf); sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, dp8390_intr, sc, esc->sc_dev.dv_xname); + /* XXX this is ridiculous */ dp8390_init(esc); + dp8390_stop(esc); break; - - case DVACT_DEACTIVATE: + case DVACT_SUSPEND: ifp->if_timer = 0; - if (ifp->if_flags & IFF_RUNNING) + if (ifp->if_flags & IFF_RUNNING) { dp8390_stop(esc); - if (sc->sc_ih != NULL) { + ifp->if_flags &= ~IFF_RUNNING; + } + if (sc->sc_ih != NULL) pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); - sc->sc_ih = NULL; + sc->sc_ih = NULL; + pcmcia_function_disable(sc->sc_pf); + break; + case DVACT_RESUME: + pcmcia_function_enable(sc->sc_pf); + sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, + dp8390_intr, sc, esc->sc_dev.dv_xname); + dp8390_enable(esc); + if (ifp->if_flags & IFF_UP) + dp8390_init(esc); + break; + case DVACT_DEACTIVATE: + ifp->if_timer = 0; + if (ifp->if_flags & IFF_RUNNING) { + dp8390_stop(esc); + ifp->if_flags &= ~IFF_RUNNING; } + if (sc->sc_ih != NULL) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); break; } - splx(s); return (0); } diff --git a/sys/dev/pcmcia/if_ray.c b/sys/dev/pcmcia/if_ray.c index 595d481f261..c6eefbfa63c 100644 --- a/sys/dev/pcmcia/if_ray.c +++ b/sys/dev/pcmcia/if_ray.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ray.c,v 1.42 2010/08/27 05:04:12 deraadt Exp $ */ +/* $OpenBSD: if_ray.c,v 1.43 2010/08/30 20:33:18 deraadt Exp $ */ /* $NetBSD: if_ray.c,v 1.21 2000/07/05 02:35:54 onoe Exp $ */ /* @@ -654,11 +654,7 @@ ray_activate(struct device *dev, int act) { struct ray_softc *sc = (struct ray_softc *)dev; struct ifnet *ifp = &sc->sc_if; - int s; - - RAY_DPRINTF(("%s: activate\n", sc->sc_xname)); - s = splnet(); switch (act) { case DVACT_ACTIVATE: pcmcia_function_enable(sc->sc_pf); @@ -666,18 +662,15 @@ ray_activate(struct device *dev, int act) ray_enable(sc); printf("\n"); break; - case DVACT_DEACTIVATE: if (ifp->if_flags & IFF_RUNNING) ray_disable(sc); - if (sc->sc_ih) { + if (sc->sc_ih) pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); - sc->sc_ih = NULL; - } + sc->sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); break; } - splx(s); return (0); } diff --git a/sys/dev/pcmcia/if_sm_pcmcia.c b/sys/dev/pcmcia/if_sm_pcmcia.c index 21c35cf064d..a6327cd7204 100644 --- a/sys/dev/pcmcia/if_sm_pcmcia.c +++ b/sys/dev/pcmcia/if_sm_pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sm_pcmcia.c,v 1.29 2009/10/13 19:33:16 pirofti Exp $ */ +/* $OpenBSD: if_sm_pcmcia.c,v 1.30 2010/08/30 20:33:18 deraadt Exp $ */ /* $NetBSD: if_sm_pcmcia.c,v 1.11 1998/08/15 20:47:32 thorpej Exp $ */ /*- @@ -252,9 +252,7 @@ sm_pcmcia_activate(dev, act) { struct sm_pcmcia_softc *sc = (struct sm_pcmcia_softc *)dev; struct ifnet *ifp = &sc->sc_smc.sc_arpcom.ac_if; - int s; - s = splnet(); switch (act) { case DVACT_ACTIVATE: pcmcia_function_enable(sc->sc_pf); @@ -262,16 +260,16 @@ sm_pcmcia_activate(dev, act) smc91cxx_intr, sc, sc->sc_smc.sc_dev.dv_xname); smc91cxx_init(&sc->sc_smc); break; - case DVACT_DEACTIVATE: ifp->if_timer = 0; if (ifp->if_flags & IFF_RUNNING) smc91cxx_stop(&sc->sc_smc); - pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + if (sc->sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); break; } - splx(s); return (0); } diff --git a/sys/dev/pcmcia/if_wi_pcmcia.c b/sys/dev/pcmcia/if_wi_pcmcia.c index 3a3ad263808..3c45273fec2 100644 --- a/sys/dev/pcmcia/if_wi_pcmcia.c +++ b/sys/dev/pcmcia/if_wi_pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wi_pcmcia.c,v 1.68 2009/10/13 19:33:16 pirofti Exp $ */ +/* $OpenBSD: if_wi_pcmcia.c,v 1.69 2010/08/30 20:33:18 deraadt Exp $ */ /* $NetBSD: if_wi_pcmcia.c,v 1.14 2001/11/26 04:34:56 ichiro Exp $ */ /* @@ -49,6 +49,7 @@ #include <sys/socket.h> #include <sys/device.h> #include <sys/tree.h> +#include <sys/workq.h> #include <net/if.h> #include <net/if_dl.h> @@ -76,6 +77,7 @@ int wi_pcmcia_match(struct device *, void *, void *); void wi_pcmcia_attach(struct device *, struct device *, void *); int wi_pcmcia_detach(struct device *, int); int wi_pcmcia_activate(struct device *, int); +void wi_pcmcia_resume(void *, void *); struct wi_pcmcia_softc { struct wi_softc sc_wi; @@ -83,6 +85,7 @@ struct wi_pcmcia_softc { struct pcmcia_io_handle sc_pcioh; int sc_io_window; struct pcmcia_function *sc_pf; + struct workq_task sc_resume_wqt; }; struct cfattach wi_pcmcia_ca = { @@ -472,28 +475,57 @@ wi_pcmcia_activate(struct device *dev, int act) struct wi_pcmcia_softc *psc = (struct wi_pcmcia_softc *)dev; struct wi_softc *sc = &psc->sc_wi; struct ifnet *ifp = &sc->sc_ic.ic_if; - int s; - s = splnet(); switch (act) { case DVACT_ACTIVATE: pcmcia_function_enable(psc->sc_pf); sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, wi_intr, sc, sc->sc_dev.dv_xname); - wi_cor_reset(sc); - wi_init(sc); + workq_queue_task(NULL, &psc->sc_resume_wqt, 0, + wi_pcmcia_resume, sc, NULL); break; - - case DVACT_DEACTIVATE: + case DVACT_SUSPEND: ifp->if_timer = 0; if (ifp->if_flags & IFF_RUNNING) wi_stop(sc); sc->wi_flags &= ~WI_FLAGS_INITIALIZED; if (sc->sc_ih != NULL) pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; + pcmcia_function_disable(psc->sc_pf); + break; + case DVACT_RESUME: + pcmcia_function_enable(psc->sc_pf); + sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, + wi_intr, sc, sc->sc_dev.dv_xname); + workq_queue_task(NULL, &psc->sc_resume_wqt, 0, + wi_pcmcia_resume, sc, NULL); + break; + case DVACT_DEACTIVATE: + if (sc->sc_ih != NULL) + pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; pcmcia_function_disable(psc->sc_pf); break; } - splx(s); return (0); } + +void +wi_pcmcia_resume(void *arg1, void *arg2) +{ + struct wi_softc *sc = (struct wi_softc *)arg1; + int s; + + s = splnet(); + while (sc->wi_flags & WI_FLAGS_BUSY) + tsleep(&sc->wi_flags, 0, "wipwr", 0); + sc->wi_flags |= WI_FLAGS_BUSY; + + wi_cor_reset(sc); + wi_init(sc); + + sc->wi_flags &= ~WI_FLAGS_BUSY; + wakeup(&sc->wi_flags); + splx(s); +} diff --git a/sys/dev/pcmcia/if_xe.c b/sys/dev/pcmcia/if_xe.c index 778ae416423..e73631c0098 100644 --- a/sys/dev/pcmcia/if_xe.c +++ b/sys/dev/pcmcia/if_xe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_xe.c,v 1.38 2009/10/13 19:33:16 pirofti Exp $ */ +/* $OpenBSD: if_xe.c,v 1.39 2010/08/30 20:33:18 deraadt Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist, Brandon Creighton, Job de Haas @@ -420,11 +420,6 @@ xe_pcmcia_attach(parent, self, aux) ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE); xe_stop(sc); } - -#ifdef notyet - pcmcia_function_disable(pa->pf); -#endif /* notyet */ - return; bad: @@ -466,26 +461,42 @@ xe_pcmcia_activate(dev, act) { struct xe_pcmcia_softc *sc = (struct xe_pcmcia_softc *)dev; struct ifnet *ifp = &sc->sc_xe.sc_arpcom.ac_if; - int s; - s = splnet(); switch (act) { case DVACT_ACTIVATE: + if (sc->sc_xe.sc_ih == NULL) { + pcmcia_function_enable(sc->sc_pf); + sc->sc_xe.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, + xe_intr, sc, sc->sc_xe.sc_dev.dv_xname); + } + break; + case DVACT_SUSPEND: + if (ifp->if_flags & IFF_RUNNING) + xe_stop(&sc->sc_xe); + ifp->if_flags &= ~IFF_RUNNING; + if (sc->sc_xe.sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_xe.sc_ih); + sc->sc_xe.sc_ih = NULL; + pcmcia_function_disable(sc->sc_pf); + break; + case DVACT_RESUME: pcmcia_function_enable(sc->sc_pf); sc->sc_xe.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, xe_intr, sc, sc->sc_xe.sc_dev.dv_xname); - xe_init(&sc->sc_xe); + /* XXX this is a ridiculous */ + xe_reset(&sc->sc_xe); + if ((ifp->if_flags & IFF_UP) == 0) + xe_stop(&sc->sc_xe); break; - case DVACT_DEACTIVATE: ifp->if_timer = 0; - if (ifp->if_flags & IFF_RUNNING) - xe_stop(&sc->sc_xe); - pcmcia_intr_disestablish(sc->sc_pf, sc->sc_xe.sc_ih); + ifp->if_flags &= ~IFF_RUNNING; + if (sc->sc_xe.sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_xe.sc_ih); + sc->sc_xe.sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); break; } - splx(s); return (0); } diff --git a/sys/dev/pcmcia/pcmcia.c b/sys/dev/pcmcia/pcmcia.c index 6659f0538c7..08dc0476296 100644 --- a/sys/dev/pcmcia/pcmcia.c +++ b/sys/dev/pcmcia/pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcmcia.c,v 1.39 2007/09/11 13:39:34 gilles Exp $ */ +/* $OpenBSD: pcmcia.c,v 1.40 2010/08/30 20:33:18 deraadt Exp $ */ /* $NetBSD: pcmcia.c,v 1.9 1998/08/13 02:10:55 eeh Exp $ */ /* @@ -55,9 +55,10 @@ int pcmcia_verbose = 0; int pcmcia_match(struct device *, void *, void *); int pcmcia_submatch(struct device *, void *, void *); void pcmcia_attach(struct device *, struct device *, void *); +int pcmcia_activate(struct device *, int); int pcmcia_print(void *, const char *); void pcmcia_card_detach_notify(struct device *, void *); -void pcmcia_power(int why, void *arg); +void pcmcia_powerhook(int why, void *arg); static inline void pcmcia_socket_enable(pcmcia_chipset_tag_t, pcmcia_chipset_handle_t *); @@ -71,7 +72,8 @@ struct cfdriver pcmcia_cd = { }; struct cfattach pcmcia_ca = { - sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach + sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach, NULL, + pcmcia_activate }; int @@ -128,34 +130,46 @@ pcmcia_attach(parent, self, aux) sc->iosize = paa->iosize; sc->ih = NULL; - powerhook_establish(pcmcia_power, sc); + powerhook_establish(pcmcia_powerhook, sc); } -void -pcmcia_power(why, arg) - int why; - void *arg; +int +pcmcia_activate(struct device *self, int act) { - struct pcmcia_softc *sc = (struct pcmcia_softc *) arg; + struct pcmcia_softc *sc = (struct pcmcia_softc *)self; struct pcmcia_function *pf; - struct device *d; - int act = DVACT_ACTIVATE; - if (why != PWR_RESUME) - act = DVACT_DEACTIVATE; - - for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; - pf = SIMPLEQ_NEXT(pf, pf_list)) { - if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL) - continue; - d = pf->child; - if (d == NULL) - continue; - if (act == DVACT_ACTIVATE) - config_activate(pf->child); - else + switch (act) { + case DVACT_ACTIVATE: + /* No children yet */ + break; + case DVACT_DEACTIVATE: + for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; + pf = SIMPLEQ_NEXT(pf, pf_list)) { + if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL || + pf->child == NULL) + continue; config_deactivate(pf->child); + } + break; + case DVACT_SUSPEND: + case DVACT_RESUME: + for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; + pf = SIMPLEQ_NEXT(pf, pf_list)) { + if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL || + pf->child == NULL) + continue; + config_suspend(pf->child, act); + } + break; } + return 0; +} + +void +pcmcia_powerhook(int why, void *arg) +{ + pcmcia_activate(arg, why); } int @@ -296,9 +310,8 @@ pcmcia_card_deactivate(dev) */ for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; pf = SIMPLEQ_NEXT(pf, pf_list)) { - if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL) - continue; - if (pf->child == NULL) + if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL || + pf->child == NULL) continue; DPRINTF(("%s: deactivating %s (function %d)\n", sc->dev.dv_xname, pf->child->dv_xname, pf->number)); diff --git a/sys/dev/pcmcia/wdc_pcmcia.c b/sys/dev/pcmcia/wdc_pcmcia.c index bed15e261e3..97d29d4ed10 100644 --- a/sys/dev/pcmcia/wdc_pcmcia.c +++ b/sys/dev/pcmcia/wdc_pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wdc_pcmcia.c,v 1.22 2010/08/29 18:41:24 deraadt Exp $ */ +/* $OpenBSD: wdc_pcmcia.c,v 1.23 2010/08/30 20:33:18 deraadt Exp $ */ /* $NetBSD: wdc_pcmcia.c,v 1.19 1999/02/19 21:49:43 abs Exp $ */ /*- @@ -138,8 +138,6 @@ int wdc_pcmcia_disk_device_interface(struct pcmcia_function *); struct wdc_pcmcia_product * wdc_pcmcia_lookup(struct pcmcia_attach_args *); -int wdc_pcmcia_enable(void *, int); - int wdc_pcmcia_disk_device_interface_callback(tuple, arg) struct pcmcia_tuple *tuple; @@ -354,23 +352,12 @@ wdc_pcmcia_attach(parent, self, aux) if (quirks & WDC_PCMCIA_NO_EXTRA_RESETS) sc->sc_wdcdev.cap |= WDC_CAPABILITY_NO_EXTRA_RESETS; -#ifdef notyet - /* We can enable and disable the controller. */ - sc->sc_wdcdev.sc_atapi_adapter.scsipi_enable = wdc_pcmcia_enable; - - /* - * Disable the pcmcia function now; wdcattach() will enable - * us again as it adds references to probe for children. - */ - pcmcia_function_disable(pa->pf); -#else /* Establish the interrupt handler. */ sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_BIO, wdcintr, &sc->wdc_channel, sc->sc_wdcdev.sc_dev.dv_xname); intrstr = pcmcia_intr_string(sc->sc_pf, sc->sc_ih); if (*intrstr) printf(": %s", intrstr); -#endif printf("\n"); @@ -438,81 +425,44 @@ wdc_pcmcia_activate(self, act) int act; { struct wdc_pcmcia_softc *sc = (struct wdc_pcmcia_softc *)self; - int rv = 0, s; + int rv = 0; if (sc->sc_iowindow == -1) /* Nothing to activate/deactivate. */ return (0); - s = splbio(); switch (act) { case DVACT_ACTIVATE: - if (pcmcia_function_enable(sc->sc_pf)) { - printf("%s: couldn't enable PCMCIA function\n", - sc->sc_wdcdev.sc_dev.dv_xname); - rv = EIO; - break; + if (sc->sc_ih == NULL) { + /* XXX attach function already did the work */ + pcmcia_function_enable(sc->sc_pf); + sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_BIO, + wdcintr, &sc->wdc_channel, sc->sc_wdcdev.sc_dev.dv_xname); + wdcreset(&sc->wdc_channel, VERBOSE); } - + rv = config_activate_children(self, act); + break; + case DVACT_SUSPEND: + rv = config_activate_children(self, act); + if (sc->sc_ih) + pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; + pcmcia_function_disable(sc->sc_pf); + break; + case DVACT_RESUME: + pcmcia_function_enable(sc->sc_pf); sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_BIO, wdcintr, &sc->wdc_channel, sc->sc_wdcdev.sc_dev.dv_xname); - if (sc->sc_ih == NULL) { - printf("%s: " - "couldn't establish interrupt handler\n", - sc->sc_wdcdev.sc_dev.dv_xname); - pcmcia_function_disable(sc->sc_pf); - rv = EIO; - break; - } - wdcreset(&sc->wdc_channel, VERBOSE); rv = config_activate_children(self, act); break; - case DVACT_DEACTIVATE: - pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); - pcmcia_function_disable(sc->sc_pf); rv = config_activate_children(self, act); - break; - } - splx(s); - return (rv); -} - -#if 0 -int -wdc_pcmcia_enable(arg, onoff) - void *arg; - int onoff; -{ - struct wdc_pcmcia_softc *sc = arg; - - if (onoff) { - if ((sc->sc_flags & WDC_PCMCIA_ATTACH) == 0) { - if (pcmcia_function_enable(sc->sc_pf)) { - printf("%s: couldn't enable PCMCIA function\n", - sc->sc_wdcdev.sc_dev.dv_xname); - return (EIO); - } - - sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_BIO, - wdcintr, &sc->wdc_channel, sc->sc_dev.dv_xname); - if (sc->sc_ih == NULL) { - printf("%s: " - "couldn't establish interrupt handler\n", - sc->sc_wdcdev.sc_dev.dv_xname); - pcmcia_function_disable(sc->sc_pf); - return (EIO); - } - - wdcreset(&sc->wdc_channel, VERBOSE); - } - } else { - if ((sc->sc_flags & WDC_PCMCIA_ATTACH) == 0) + if (sc->sc_ih) pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); + sc->sc_ih = NULL; pcmcia_function_disable(sc->sc_pf); + break; } - - return (0); + return (rv); } -#endif |