Use device_t and its accessors throughout. Use aprint_*_dev().
Improve PMF-ability. Add a 'flags' argument to suspend/resume handlers and callers such as pmf_system_suspend(). Define a flag, PMF_F_SELF, which indicates to PMF that a device is suspending/resuming itself. Add helper routines, pmf_device_suspend_self(dev) and pmf_device_resume_self(dev), that call pmf_device_suspend(dev, PMF_F_SELF) and pmf_device_resume(dev, PMF_F_SELF), respectively. Use PMF_F_SELF to suspend/resume self in ath(4), audio(4), rtw(4), and sip(4). In ath(4) and in rtw(4), replace the icky sc_enable/sc_disable callbacks, provided by the bus front-end, with self-suspension/resumption. Also, clean up the bus front-ends. Make sure that the interrupt handler is disestablished during suspension. Get rid of driver-private flags (e.g., RTW_F_ENABLED, ath_softc->sc_invalid); use device_is_active()/device_has_power() calls, instead. In the network-class suspend handler, call if_stop(, 0) instead of if_stop(, 1), because the latter is superfluous (bus- and driver-suspension hooks will 'disable' the NIC), and it may cause recursion. In the network-class resume handler, prevent infinite recursion through if_init() by getting out early if we are self-suspending (PMF_F_SELF). rtw(4) improvements: Destroy rtw(4) callouts when we detach it. Make rtw at pci detachable. Print some more information with the "rx frame too long" warning. Remove activate() methods: Get rid of rtw_activate() and ath_activate(). The device activate() methods are not good for much these days. Make ath at cardbus resume with crypto functions intact: Introduce a boolean device property, "pmf-powerdown". If pmf-powerdown is present and false, it indicates that a bus back-end should not remove power from a device. Honor this property in cardbus_child_suspend(). Set this property to 'false' in ath_attach(), since removing power from an ath at cardbus seems to lobotomize the WPA crypto engine. XXX Should the pmf-powerdown property propagate toward the root of the device tree? Miscellaneous ath(4) changes: Warn if ath(4) tries to write crypto keys to suspended hardware. Reduce differences between FreeBSD and NetBSD in ath(4) multicast filter setup. Make ath_printrxbuf() print an rx descriptor's status & key index, to help debug crypto errors. Shorten a staircase in ath_ioctl(). Don't check for ieee80211_ioctl() return code ERESTART, it never happens.
This commit is contained in:
parent
15bb494e45
commit
3df2b2feb5
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: acpi.c,v 1.111 2008/03/10 20:58:38 dyoung Exp $ */
|
||||
/* $NetBSD: acpi.c,v 1.112 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
|
||||
|
@ -77,7 +77,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.111 2008/03/10 20:58:38 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.112 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include "opt_acpi.h"
|
||||
#include "opt_pcifixup.h"
|
||||
|
@ -1198,7 +1198,7 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state)
|
|||
break;
|
||||
}
|
||||
|
||||
if (state != ACPI_STATE_S1 && !pmf_system_suspend()) {
|
||||
if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_F_NONE)) {
|
||||
aprint_error_dev(&sc->sc_dev, "aborting suspend\n");
|
||||
break;
|
||||
}
|
||||
|
@ -1221,9 +1221,9 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state)
|
|||
err = acpi_md_sleep(state);
|
||||
if (state == ACPI_STATE_S4)
|
||||
AcpiEnable();
|
||||
pmf_system_bus_resume();
|
||||
pmf_system_bus_resume(PMF_F_NONE);
|
||||
AcpiLeaveSleepState((UINT8)state);
|
||||
pmf_system_resume();
|
||||
pmf_system_resume(PMF_F_NONE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: apm.c,v 1.19 2008/03/07 21:45:08 cube Exp $ */
|
||||
/* $NetBSD: apm.c,v 1.20 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
|
||||
|
@ -40,7 +40,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: apm.c,v 1.19 2008/03/07 21:45:08 cube Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: apm.c,v 1.20 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include "opt_apm.h"
|
||||
|
||||
|
@ -316,7 +316,7 @@ apm_suspend(struct apm_softc *sc)
|
|||
sc->sc_power_state = PWR_SUSPEND;
|
||||
|
||||
if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) {
|
||||
pmf_system_suspend();
|
||||
pmf_system_suspend(PMF_F_NONE);
|
||||
apm_spl = splhigh();
|
||||
}
|
||||
|
||||
|
@ -342,7 +342,7 @@ apm_standby(struct apm_softc *sc)
|
|||
sc->sc_power_state = PWR_STANDBY;
|
||||
|
||||
if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) {
|
||||
pmf_system_suspend();
|
||||
pmf_system_suspend(PMF_F_NONE);
|
||||
apm_spl = splhigh();
|
||||
}
|
||||
error = (*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS,
|
||||
|
@ -373,7 +373,7 @@ apm_resume(struct apm_softc *sc, u_int event_type, u_int event_info)
|
|||
inittodr(time_second);
|
||||
if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) {
|
||||
splx(apm_spl);
|
||||
pmf_system_resume();
|
||||
pmf_system_resume(PMF_F_NONE);
|
||||
}
|
||||
|
||||
apm_record_event(sc, event_type);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: audio.c,v 1.236 2008/03/04 18:23:44 cube Exp $ */
|
||||
/* $NetBSD: audio.c,v 1.237 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991-1993 Regents of the University of California.
|
||||
|
@ -61,7 +61,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.236 2008/03/04 18:23:44 cube Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.237 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include "audio.h"
|
||||
#if NAUDIO > 0
|
||||
|
@ -183,8 +183,8 @@ static void audio_idle(void *);
|
|||
static void audio_activity(device_t, devactive_t);
|
||||
#endif
|
||||
|
||||
static bool audio_suspend(device_t dv);
|
||||
static bool audio_resume(device_t dv);
|
||||
static bool audio_suspend(device_t dv PMF_FN_PROTO);
|
||||
static bool audio_resume(device_t dv PMF_FN_PROTO);
|
||||
static void audio_volume_down(device_t);
|
||||
static void audio_volume_up(device_t);
|
||||
static void audio_volume_toggle(device_t);
|
||||
|
@ -3993,11 +3993,11 @@ audio_idle(void *arg)
|
|||
sc->sc_idle = true;
|
||||
|
||||
/* XXX joerg Make pmf_device_suspend handle children? */
|
||||
if (!pmf_device_suspend(dv))
|
||||
if (!pmf_device_suspend(dv, PMF_F_SELF))
|
||||
return;
|
||||
|
||||
if (!pmf_device_suspend(sc->sc_dev))
|
||||
pmf_device_resume(dv);
|
||||
if (!pmf_device_suspend(sc->sc_dev, PMF_F_SELF))
|
||||
pmf_device_resume(dv, PMF_F_SELF);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -4013,14 +4013,14 @@ audio_activity(device_t dv, devactive_t type)
|
|||
sc->sc_idle = false;
|
||||
if (!device_is_active(dv)) {
|
||||
/* XXX joerg How to deal with a failing resume... */
|
||||
pmf_device_resume(sc->sc_dev);
|
||||
pmf_device_resume(dv);
|
||||
pmf_device_resume(sc->sc_dev, PMF_F_SELF);
|
||||
pmf_device_resume(dv, PMF_F_SELF);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
audio_suspend(device_t dv)
|
||||
audio_suspend(device_t dv PMF_FN_ARGS)
|
||||
{
|
||||
struct audio_softc *sc = device_private(dv);
|
||||
const struct audio_hw_if *hwp = sc->hw_if;
|
||||
|
@ -4041,7 +4041,7 @@ audio_suspend(device_t dv)
|
|||
}
|
||||
|
||||
static bool
|
||||
audio_resume(device_t dv)
|
||||
audio_resume(device_t dv PMF_FN_ARGS)
|
||||
{
|
||||
struct audio_softc *sc = device_private(dv);
|
||||
int s;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: cardbus.c,v 1.90 2008/02/28 14:25:12 drochner Exp $ */
|
||||
/* $NetBSD: cardbus.c,v 1.91 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998, 1999 and 2000
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.90 2008/02/28 14:25:12 drochner Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.91 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include "opt_cardbus.h"
|
||||
|
||||
|
@ -1167,6 +1167,7 @@ struct cardbus_child_power {
|
|||
static bool
|
||||
cardbus_child_suspend(device_t dv PMF_FN_ARGS)
|
||||
{
|
||||
bool powerdown;
|
||||
struct cardbus_child_power *priv = device_pmf_bus_private(dv);
|
||||
|
||||
cardbus_conf_capture(priv->p_cc, priv->p_cf, priv->p_tag,
|
||||
|
@ -1179,7 +1180,9 @@ cardbus_child_suspend(device_t dv PMF_FN_ARGS)
|
|||
return false;
|
||||
}
|
||||
|
||||
Cardbus_function_disable(priv->p_ct);
|
||||
if (!prop_dictionary_get_bool(device_properties(dv), "pmf-powerdown",
|
||||
&powerdown) || powerdown)
|
||||
Cardbus_function_disable(priv->p_ct);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_ath_cardbus.c,v 1.25 2007/12/22 00:39:47 dyoung Exp $ */
|
||||
/* $NetBSD: if_ath_cardbus.c,v 1.26 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2003
|
||||
* Ichiro FUKUHARA <ichiro@ichiro.org>.
|
||||
|
@ -36,7 +36,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ath_cardbus.c,v 1.25 2007/12/22 00:39:47 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ath_cardbus.c,v 1.26 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "bpfilter.h"
|
||||
|
@ -109,70 +109,72 @@ struct ath_cardbus_softc {
|
|||
bus_space_handle_t sc_ioh;
|
||||
};
|
||||
|
||||
int ath_cardbus_match(struct device *, struct cfdata *, void *);
|
||||
void ath_cardbus_attach(struct device *, struct device *, void *);
|
||||
int ath_cardbus_detach(struct device *, int);
|
||||
int ath_cardbus_match(device_t, struct cfdata *, void *);
|
||||
void ath_cardbus_attach(device_t, device_t, void *);
|
||||
int ath_cardbus_detach(device_t, int);
|
||||
|
||||
CFATTACH_DECL(ath_cardbus, sizeof(struct ath_cardbus_softc),
|
||||
ath_cardbus_match, ath_cardbus_attach, ath_cardbus_detach, ath_activate);
|
||||
ath_cardbus_match, ath_cardbus_attach, ath_cardbus_detach, NULL);
|
||||
|
||||
void ath_cardbus_setup(struct ath_cardbus_softc *);
|
||||
|
||||
int ath_cardbus_enable(struct ath_softc *);
|
||||
void ath_cardbus_disable(struct ath_softc *);
|
||||
|
||||
static bool
|
||||
ath_cardbus_resume(device_t dv)
|
||||
ath_cardbus_suspend(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct ath_cardbus_softc *csc = device_private(dv);
|
||||
|
||||
/* Insofar as I understand what the PCI retry timeout is
|
||||
* (it does not appear to be documented in any PCI standard,
|
||||
* and we don't have any Atheros documentation), disabling
|
||||
* it on resume does not seem to be justified.
|
||||
*
|
||||
* Taking a guess, the DMA engine counts down from the
|
||||
* retry timeout to 0 while it retries a delayed PCI
|
||||
* transaction. When it reaches 0, it ceases retrying.
|
||||
* A PCI master is *never* supposed to stop retrying a
|
||||
* delayed transaction, though.
|
||||
*
|
||||
* Incidentally, while I am hopeful that cardbus_disable_retry()
|
||||
* does disable retries, because that would help to explain
|
||||
* some ath(4) lossage, I suspect that writing 0 to the
|
||||
* register does not disable *retries*, but it disables
|
||||
* the timeout. That is, the device will *never* timeout.
|
||||
*/
|
||||
#if 0
|
||||
cardbus_devfunc_t ct = csc->sc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
cardbus_disable_retry(cc, cf, csc->sc_tag);
|
||||
#endif
|
||||
ath_resume(&csc->sc_ath);
|
||||
struct ath_cardbus_softc *csc = device_private(self);
|
||||
|
||||
ath_suspend(&csc->sc_ath);
|
||||
if (csc->sc_ih != NULL) {
|
||||
cardbus_intr_disestablish(csc->sc_ct->ct_cc, csc->sc_ct->ct_cf,
|
||||
csc->sc_ih);
|
||||
csc->sc_ih = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ath_cardbus_resume(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct ath_cardbus_softc *csc = device_private(self);
|
||||
|
||||
#if 1
|
||||
ath_cardbus_setup(csc);
|
||||
#else
|
||||
int rc;
|
||||
rc = cardbus_set_powerstate(csc->sc_ct, csc->sc_tag, PCI_PWR_D0);
|
||||
if (rc != 0)
|
||||
aprint_debug("%s: cardbus_set_powerstate %d\n", __func__, rc);
|
||||
#endif
|
||||
|
||||
csc->sc_ih = cardbus_intr_establish(csc->sc_ct->ct_cc,
|
||||
csc->sc_ct->ct_cf, csc->sc_intrline, IPL_NET, ath_intr,
|
||||
&csc->sc_ath);
|
||||
|
||||
if (csc->sc_ih == NULL) {
|
||||
aprint_error_dev(self,
|
||||
"unable to establish interrupt at %d\n", csc->sc_intrline);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ath_resume(&csc->sc_ath);
|
||||
}
|
||||
|
||||
int
|
||||
ath_cardbus_match(struct device *parent, struct cfdata *match,
|
||||
void *aux)
|
||||
ath_cardbus_match(device_t parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct cardbus_attach_args *ca = aux;
|
||||
const char* devname;
|
||||
const char *devname;
|
||||
|
||||
devname = ath_hal_probe(PCI_VENDOR(ca->ca_id),
|
||||
PCI_PRODUCT(ca->ca_id));
|
||||
devname = ath_hal_probe(PCI_VENDOR(ca->ca_id), PCI_PRODUCT(ca->ca_id));
|
||||
|
||||
if (devname)
|
||||
return (1);
|
||||
return 1;
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ath_cardbus_attach(struct device *parent, struct device *self,
|
||||
void *aux)
|
||||
ath_cardbus_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct ath_cardbus_softc *csc = device_private(self);
|
||||
struct ath_softc *sc = &csc->sc_ath;
|
||||
|
@ -184,29 +186,20 @@ ath_cardbus_attach(struct device *parent, struct device *self,
|
|||
csc->sc_ct = ct;
|
||||
csc->sc_tag = ca->ca_tag;
|
||||
|
||||
printf("\n");
|
||||
|
||||
/*
|
||||
* Power management hooks.
|
||||
*/
|
||||
sc->sc_enable = ath_cardbus_enable;
|
||||
sc->sc_disable = ath_cardbus_disable;
|
||||
aprint_normal("\n");
|
||||
|
||||
/*
|
||||
* Map the device.
|
||||
*/
|
||||
if (Cardbus_mapreg_map(ct, ATH_PCI_MMBA, CARDBUS_MAPREG_TYPE_MEM, 0,
|
||||
if (Cardbus_mapreg_map(ct, ATH_PCI_MMBA, PCI_MAPREG_TYPE_MEM, 0,
|
||||
&csc->sc_iot, &csc->sc_ioh, &adr, &csc->sc_mapsize) == 0) {
|
||||
#if rbus
|
||||
#else
|
||||
(*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize);
|
||||
#endif
|
||||
csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
|
||||
}
|
||||
|
||||
else {
|
||||
printf("%s: unable to map device registers\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM;
|
||||
} else {
|
||||
aprint_error_dev(self, "unable to map device registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -223,19 +216,22 @@ ath_cardbus_attach(struct device *parent, struct device *self,
|
|||
|
||||
ATH_LOCK_INIT(sc);
|
||||
|
||||
if (!pmf_device_register(self, NULL, ath_cardbus_resume))
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
else
|
||||
pmf_class_network_register(self, &sc->sc_if);
|
||||
|
||||
/*
|
||||
* Finish off the attach.
|
||||
*/
|
||||
ath_attach(PCI_PRODUCT(ca->ca_id), sc);
|
||||
if (ath_attach(PCI_PRODUCT(ca->ca_id), sc) != 0)
|
||||
return;
|
||||
|
||||
if (!pmf_device_register(self, ath_cardbus_suspend, ath_cardbus_resume))
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
else {
|
||||
pmf_class_network_register(self, &sc->sc_if);
|
||||
pmf_device_suspend_self(self);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ath_cardbus_detach(struct device *self, int flags)
|
||||
ath_cardbus_detach(device_t self, int flags)
|
||||
{
|
||||
struct ath_cardbus_softc *csc = device_private(self);
|
||||
struct ath_softc *sc = &csc->sc_ath;
|
||||
|
@ -272,79 +268,24 @@ ath_cardbus_detach(struct device *self, int flags)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ath_cardbus_enable(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_cardbus_softc *csc = (void *) sc;
|
||||
cardbus_devfunc_t ct = csc->sc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
|
||||
/*
|
||||
* Power on the socket.
|
||||
*/
|
||||
Cardbus_function_enable(ct);
|
||||
|
||||
/*
|
||||
* Set up the PCI configuration registers.
|
||||
*/
|
||||
ath_cardbus_setup(csc);
|
||||
|
||||
/*
|
||||
* Map and establish the interrupt.
|
||||
*/
|
||||
csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
|
||||
ath_intr, sc);
|
||||
if (csc->sc_ih == NULL) {
|
||||
printf("%s: unable to establish interrupt at %d\n",
|
||||
sc->sc_dev.dv_xname, csc->sc_intrline);
|
||||
Cardbus_function_disable(csc->sc_ct);
|
||||
return (1);
|
||||
}
|
||||
printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname,
|
||||
csc->sc_intrline);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ath_cardbus_disable(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_cardbus_softc *csc = (void *) sc;
|
||||
cardbus_devfunc_t ct = csc->sc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
|
||||
/* Unhook the interrupt handler. */
|
||||
cardbus_intr_disestablish(cc, cf, csc->sc_ih);
|
||||
csc->sc_ih = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ath_cardbus_setup(struct ath_cardbus_softc *csc)
|
||||
{
|
||||
cardbus_devfunc_t ct = csc->sc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
int error;
|
||||
int rc;
|
||||
pcireg_t reg;
|
||||
|
||||
if ((error = cardbus_set_powerstate(ct, csc->sc_tag,
|
||||
PCI_PWR_D0)) != 0)
|
||||
aprint_debug("%s: cardbus_set_powerstate %d\n", __func__, error);
|
||||
if ((rc = cardbus_set_powerstate(ct, csc->sc_tag, PCI_PWR_D0)) != 0)
|
||||
aprint_debug("%s: cardbus_set_powerstate %d\n", __func__, rc);
|
||||
|
||||
/* Program the BAR. */
|
||||
cardbus_conf_write(cc, cf, csc->sc_tag, ATH_PCI_MMBA,
|
||||
csc->sc_bar_val);
|
||||
|
||||
/* Make sure the right access type is on the CardBus bridge. */
|
||||
(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
|
||||
(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
|
||||
cardbus_conf_write(cc, cf, csc->sc_tag, ATH_PCI_MMBA, csc->sc_bar_val);
|
||||
|
||||
/* Enable the appropriate bits in the PCI CSR. */
|
||||
reg = cardbus_conf_read(cc, cf, csc->sc_tag,
|
||||
CARDBUS_COMMAND_STATUS_REG);
|
||||
reg |= CARDBUS_COMMAND_MASTER_ENABLE | CARDBUS_COMMAND_MEM_ENABLE;
|
||||
cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_COMMAND_STATUS_REG,
|
||||
reg);
|
||||
PCI_COMMAND_STATUS_REG);
|
||||
reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
|
||||
cardbus_conf_write(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_rtw_cardbus.c,v 1.22 2008/01/08 18:26:09 dyoung Exp $ */
|
||||
/* $NetBSD: if_rtw_cardbus.c,v 1.23 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2005 David Young. All rights reserved.
|
||||
|
@ -74,7 +74,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_rtw_cardbus.c,v 1.22 2008/01/08 18:26:09 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_rtw_cardbus.c,v 1.23 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "bpfilter.h"
|
||||
|
@ -141,14 +141,10 @@ struct rtw_cardbus_softc {
|
|||
* region
|
||||
*/
|
||||
|
||||
int sc_cben; /* CardBus enables */
|
||||
int sc_bar_reg; /* which BAR to use */
|
||||
pcireg_t sc_bar_val; /* value of the BAR */
|
||||
|
||||
int sc_intrline; /* interrupt line */
|
||||
#if 0
|
||||
struct cardbus_conf_state sc_conf; /* configuration regs */
|
||||
#endif
|
||||
};
|
||||
|
||||
int rtw_cardbus_match(device_t, struct cfdata *, void *);
|
||||
|
@ -156,13 +152,12 @@ void rtw_cardbus_attach(device_t, device_t, void *);
|
|||
int rtw_cardbus_detach(device_t, int);
|
||||
|
||||
CFATTACH_DECL_NEW(rtw_cardbus, sizeof(struct rtw_cardbus_softc),
|
||||
rtw_cardbus_match, rtw_cardbus_attach, rtw_cardbus_detach, rtw_activate);
|
||||
rtw_cardbus_match, rtw_cardbus_attach, rtw_cardbus_detach, NULL);
|
||||
|
||||
void rtw_cardbus_setup(struct rtw_cardbus_softc *);
|
||||
|
||||
int rtw_cardbus_enable(struct rtw_softc *);
|
||||
void rtw_cardbus_disable(struct rtw_softc *);
|
||||
void rtw_cardbus_power(struct rtw_softc *, int);
|
||||
bool rtw_cardbus_resume(device_t PMF_FN_PROTO);
|
||||
bool rtw_cardbus_suspend(device_t PMF_FN_PROTO);
|
||||
|
||||
const struct rtw_cardbus_product *rtw_cardbus_lookup(
|
||||
const struct cardbus_attach_args *);
|
||||
|
@ -250,12 +245,6 @@ rtw_cardbus_attach(device_t parent, device_t self, void *aux)
|
|||
panic("rtw_cardbus_attach: impossible");
|
||||
}
|
||||
|
||||
/*
|
||||
* Power management hooks.
|
||||
*/
|
||||
sc->sc_enable = rtw_cardbus_enable;
|
||||
sc->sc_disable = rtw_cardbus_disable;
|
||||
|
||||
sc->sc_intr_ack = rtw_cardbus_intr_ack;
|
||||
|
||||
/* Get revision info. */
|
||||
|
@ -264,47 +253,42 @@ rtw_cardbus_attach(device_t parent, device_t self, void *aux)
|
|||
printf(": %s\n", rcp->rcp_product_name);
|
||||
|
||||
RTW_DPRINTF(RTW_DEBUG_ATTACH,
|
||||
("%s: pass %d.%d signature %08x\n", device_xname(sc->sc_dev),
|
||||
("%s: pass %d.%d signature %08x\n", device_xname(self),
|
||||
(rev >> 4) & 0xf, rev & 0xf,
|
||||
cardbus_conf_read(ct->ct_cc, ct->ct_cf, csc->sc_tag, 0x80)));
|
||||
|
||||
/*
|
||||
* Map the device.
|
||||
*/
|
||||
csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
|
||||
if (Cardbus_mapreg_map(ct, RTW_PCI_MMBA,
|
||||
CARDBUS_MAPREG_TYPE_MEM, 0, ®s->r_bt, ®s->r_bh, &adr,
|
||||
&csc->sc_mapsize) == 0) {
|
||||
csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE |
|
||||
CARDBUS_COMMAND_PARITY_ENABLE |
|
||||
CARDBUS_COMMAND_SERR_ENABLE;
|
||||
if (Cardbus_mapreg_map(ct, RTW_PCI_MMBA, CARDBUS_MAPREG_TYPE_MEM, 0,
|
||||
®s->r_bt, ®s->r_bh, &adr, ®s->r_sz) == 0) {
|
||||
RTW_DPRINTF(RTW_DEBUG_ATTACH,
|
||||
("%s: %s mapped %lu bytes mem space\n",
|
||||
device_xname(sc->sc_dev), __func__,
|
||||
(long)csc->sc_mapsize));
|
||||
("%s: %s mapped %" PRIuMAX " bytes mem space\n",
|
||||
device_xname(self), __func__, regs->r_sz));
|
||||
#if rbus
|
||||
#else
|
||||
(*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize);
|
||||
#endif
|
||||
csc->sc_cben = CARDBUS_MEM_ENABLE;
|
||||
csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
|
||||
csc->sc_bar_reg = RTW_PCI_MMBA;
|
||||
csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
|
||||
} else if (Cardbus_mapreg_map(ct, RTW_PCI_IOBA,
|
||||
CARDBUS_MAPREG_TYPE_IO, 0, ®s->r_bt, ®s->r_bh, &adr,
|
||||
&csc->sc_mapsize) == 0) {
|
||||
} else if (Cardbus_mapreg_map(ct, RTW_PCI_IOBA, CARDBUS_MAPREG_TYPE_IO,
|
||||
0, ®s->r_bt, ®s->r_bh, &adr, ®s->r_sz) == 0) {
|
||||
RTW_DPRINTF(RTW_DEBUG_ATTACH,
|
||||
("%s: %s mapped %lu bytes I/O space\n",
|
||||
device_xname(sc->sc_dev), __func__,
|
||||
(long)csc->sc_mapsize));
|
||||
("%s: %s mapped %" PRIuMAX " bytes I/O space\n",
|
||||
device_xname(self), __func__, regs->r_sz));
|
||||
#if rbus
|
||||
#else
|
||||
(*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr+csc->sc_mapsize);
|
||||
#endif
|
||||
csc->sc_cben = CARDBUS_IO_ENABLE;
|
||||
csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
|
||||
csc->sc_bar_reg = RTW_PCI_IOBA;
|
||||
csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
|
||||
} else {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"unable to map device registers\n");
|
||||
aprint_error_dev(self, "unable to map device registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -317,7 +301,7 @@ rtw_cardbus_attach(device_t parent, device_t self, void *aux)
|
|||
/* Remember which interrupt line. */
|
||||
csc->sc_intrline = ca->ca_intrline;
|
||||
|
||||
aprint_normal_dev(sc->sc_dev, "interrupting at %d\n", csc->sc_intrline);
|
||||
aprint_normal_dev(self, "interrupting at %d\n", csc->sc_intrline);
|
||||
/*
|
||||
* Finish off the attach.
|
||||
*/
|
||||
|
@ -328,14 +312,15 @@ rtw_cardbus_attach(device_t parent, device_t self, void *aux)
|
|||
RTW_WRITE(regs, RTW_FEMR, RTW_FEMR_INTR);
|
||||
RTW_WRITE(regs, RTW_FER, RTW_FER_INTR);
|
||||
|
||||
#if 0
|
||||
cardbus_conf_capture(ct->ct_cc, ct->ct_cf, csc->sc_tag, &csc->sc_conf);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Power down the socket.
|
||||
*/
|
||||
Cardbus_function_disable(csc->sc_ct);
|
||||
if (!pmf_device_register(self, rtw_cardbus_suspend, rtw_cardbus_resume))
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
else {
|
||||
pmf_class_network_register(self, &sc->sc_if);
|
||||
/*
|
||||
* Power down the socket.
|
||||
*/
|
||||
pmf_device_suspend_self(self);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -366,33 +351,20 @@ rtw_cardbus_detach(device_t self, int flags)
|
|||
*/
|
||||
if (csc->sc_bar_reg != 0)
|
||||
Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
|
||||
regs->r_bt, regs->r_bh, csc->sc_mapsize);
|
||||
regs->r_bt, regs->r_bh, regs->r_sz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rtw_cardbus_enable(struct rtw_softc *sc)
|
||||
bool
|
||||
rtw_cardbus_resume(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct rtw_cardbus_softc *csc = (void *) sc;
|
||||
struct rtw_cardbus_softc *csc = device_private(self);
|
||||
struct rtw_softc *sc = &csc->sc_rtw;
|
||||
cardbus_devfunc_t ct = csc->sc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
|
||||
/*
|
||||
* Power on the socket.
|
||||
*/
|
||||
Cardbus_function_enable(ct);
|
||||
|
||||
#if 0
|
||||
cardbus_conf_restore(cc, cf, csc->sc_tag, &csc->sc_conf);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set up the PCI configuration registers.
|
||||
*/
|
||||
rtw_cardbus_setup(csc);
|
||||
|
||||
/*
|
||||
* Map and establish the interrupt.
|
||||
*/
|
||||
|
@ -401,8 +373,7 @@ rtw_cardbus_enable(struct rtw_softc *sc)
|
|||
if (csc->sc_ih == NULL) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"unable to establish interrupt at %d\n", csc->sc_intrline);
|
||||
Cardbus_function_disable(csc->sc_ct);
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
rtw_cardbus_funcregen(&sc->sc_regs, 1);
|
||||
|
@ -410,17 +381,21 @@ rtw_cardbus_enable(struct rtw_softc *sc)
|
|||
RTW_WRITE(&sc->sc_regs, RTW_FEMR, RTW_FEMR_INTR);
|
||||
RTW_WRITE(&sc->sc_regs, RTW_FER, RTW_FER_INTR);
|
||||
|
||||
return 0;
|
||||
return rtw_resume(self, flags);
|
||||
}
|
||||
|
||||
void
|
||||
rtw_cardbus_disable(struct rtw_softc *sc)
|
||||
bool
|
||||
rtw_cardbus_suspend(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct rtw_cardbus_softc *csc = (void *) sc;
|
||||
struct rtw_cardbus_softc *csc = device_private(self);
|
||||
struct rtw_softc *sc = &csc->sc_rtw;
|
||||
cardbus_devfunc_t ct = csc->sc_ct;
|
||||
cardbus_chipset_tag_t cc = ct->ct_cc;
|
||||
cardbus_function_tag_t cf = ct->ct_cf;
|
||||
|
||||
if (!rtw_suspend(self, flags))
|
||||
return false;
|
||||
|
||||
RTW_WRITE(&sc->sc_regs, RTW_FEMR,
|
||||
RTW_READ(&sc->sc_regs, RTW_FEMR) & ~RTW_FEMR_INTR);
|
||||
|
||||
|
@ -429,13 +404,7 @@ rtw_cardbus_disable(struct rtw_softc *sc)
|
|||
/* Unhook the interrupt handler. */
|
||||
cardbus_intr_disestablish(cc, cf, csc->sc_ih);
|
||||
csc->sc_ih = NULL;
|
||||
|
||||
#if 0
|
||||
cardbus_conf_capture(cc, cf, csc->sc_tag, &csc->sc_conf);
|
||||
#endif
|
||||
|
||||
/* Power down the socket. */
|
||||
Cardbus_function_disable(ct);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -463,14 +432,9 @@ rtw_cardbus_setup(struct rtw_cardbus_softc *csc)
|
|||
/* Program the BAR. */
|
||||
cardbus_conf_write(cc, cf, tag, csc->sc_bar_reg, csc->sc_bar_val);
|
||||
|
||||
/* Make sure the right access type is on the CardBus bridge. */
|
||||
(*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
|
||||
(*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
|
||||
|
||||
/* Enable the appropriate bits in the PCI CSR. */
|
||||
csr = cardbus_conf_read(cc, cf, tag, PCI_COMMAND_STATUS_REG);
|
||||
csr &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
|
||||
csr |= csc->sc_csr;
|
||||
csr |= CARDBUS_COMMAND_PARITY_ENABLE | CARDBUS_COMMAND_SERR_ENABLE;
|
||||
cardbus_conf_write(cc, cf, tag, PCI_COMMAND_STATUS_REG, csr);
|
||||
}
|
||||
|
|
257
sys/dev/ic/ath.c
257
sys/dev/ic/ath.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ath.c,v 1.98 2008/01/04 21:17:54 ad Exp $ */
|
||||
/* $NetBSD: ath.c,v 1.99 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
|
@ -41,7 +41,7 @@
|
|||
__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath.c,v 1.104 2005/09/16 10:09:23 ru Exp $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.98 2008/01/04 21:17:54 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.99 2008/03/12 18:02:21 dyoung Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -199,11 +199,6 @@ static void ath_restore_diversity(struct ath_softc *);
|
|||
static int ath_rate_setup(struct ath_softc *, u_int mode);
|
||||
static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
|
||||
|
||||
#ifdef __NetBSD__
|
||||
int ath_enable(struct ath_softc *);
|
||||
void ath_disable(struct ath_softc *);
|
||||
#endif
|
||||
|
||||
#if NBPFILTER > 0
|
||||
static void ath_bpfattach(struct ath_softc *);
|
||||
#endif
|
||||
|
@ -264,51 +259,6 @@ static void ath_printtxbuf(struct ath_buf *bf, int);
|
|||
#define KEYPRINTF(sc, k, ix, mac)
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
int
|
||||
ath_activate(struct device *self, enum devact act)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)self;
|
||||
int rv = 0, s;
|
||||
|
||||
s = splnet();
|
||||
switch (act) {
|
||||
case DVACT_ACTIVATE:
|
||||
rv = EOPNOTSUPP;
|
||||
break;
|
||||
case DVACT_DEACTIVATE:
|
||||
if_deactivate(&sc->sc_if);
|
||||
break;
|
||||
}
|
||||
splx(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
ath_enable(struct ath_softc *sc)
|
||||
{
|
||||
if (ATH_IS_ENABLED(sc) == 0) {
|
||||
if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
|
||||
printf("%s: device enable failed\n",
|
||||
device_xname(&sc->sc_dev));
|
||||
return (EIO);
|
||||
}
|
||||
sc->sc_flags |= ATH_ENABLED;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ath_disable(struct ath_softc *sc)
|
||||
{
|
||||
if (!ATH_IS_ENABLED(sc))
|
||||
return;
|
||||
if (sc->sc_disable != NULL)
|
||||
(*sc->sc_disable)(sc);
|
||||
sc->sc_flags &= ~ATH_ENABLED;
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers");
|
||||
|
||||
int
|
||||
|
@ -339,7 +289,10 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
|
|||
goto bad;
|
||||
}
|
||||
sc->sc_ah = ah;
|
||||
sc->sc_invalid = 0; /* ready to go, enable interrupt handling */
|
||||
|
||||
if (!prop_dictionary_set_bool(device_properties(&sc->sc_dev),
|
||||
"pmf-powerdown", false))
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* Check if the MAC has multi-rate retry support.
|
||||
|
@ -655,7 +608,8 @@ bad2:
|
|||
bad:
|
||||
if (ah)
|
||||
ath_hal_detach(ah);
|
||||
sc->sc_invalid = 1;
|
||||
/* XXX don't get under the abstraction like this */
|
||||
sc->sc_dev.dv_flags &= ~DVF_ACTIVE;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -705,12 +659,45 @@ ath_detach(struct ath_softc *sc)
|
|||
}
|
||||
|
||||
void
|
||||
ath_suspend(struct ath_softc *sc)
|
||||
{
|
||||
/*
|
||||
* Set the chip in full sleep mode. Note that we are
|
||||
* careful to do this only when bringing the interface
|
||||
* completely to a stop. When the chip is in this state
|
||||
* it must be carefully woken up or references to
|
||||
* registers in the PCI clock domain may freeze the bus
|
||||
* (and system). This varies by chip and is mostly an
|
||||
* issue with newer parts that go to sleep more quickly.
|
||||
*/
|
||||
ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
|
||||
}
|
||||
|
||||
bool
|
||||
ath_resume(struct ath_softc *sc)
|
||||
{
|
||||
int i;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
|
||||
ath_hal_setpower(ah, HAL_PM_AWAKE);
|
||||
|
||||
/*
|
||||
* Reset the key cache since some parts do not
|
||||
* reset the contents on initial power up.
|
||||
*/
|
||||
for (i = 0; i < sc->sc_keymax; i++)
|
||||
ath_hal_keyreset(ah, i);
|
||||
|
||||
ath_hal_resettxqueue(ah, sc->sc_bhalq);
|
||||
for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
|
||||
if (ATH_TXQ_SETUP(sc, i))
|
||||
ath_hal_resettxqueue(ah, i);
|
||||
|
||||
if (sc->sc_softled) {
|
||||
ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin);
|
||||
ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -724,7 +711,7 @@ ath_intr(void *arg)
|
|||
struct ath_hal *ah = sc->sc_ah;
|
||||
HAL_INT status;
|
||||
|
||||
if (sc->sc_invalid) {
|
||||
if (!device_is_active(&sc->sc_dev)) {
|
||||
/*
|
||||
* The hardware is not ready/present, don't touch anything.
|
||||
* Note this can happen early on if the IRQ is shared.
|
||||
|
@ -946,15 +933,12 @@ ath_init(struct ath_softc *sc)
|
|||
DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
|
||||
__func__, ifp->if_flags);
|
||||
|
||||
if (!device_has_power(&sc->sc_dev))
|
||||
return EBUSY;
|
||||
|
||||
ATH_LOCK(sc);
|
||||
|
||||
if ((error = ath_enable(sc)) != 0) {
|
||||
ATH_UNLOCK(sc);
|
||||
return error;
|
||||
}
|
||||
if (device_is_active(&sc->sc_dev)) {
|
||||
ATH_LOCK(sc);
|
||||
} else if (!pmf_device_resume_self(&sc->sc_dev))
|
||||
return ENXIO;
|
||||
else
|
||||
ATH_LOCK(sc);
|
||||
|
||||
/*
|
||||
* Stop anything previously setup. This is safe
|
||||
|
@ -1048,8 +1032,8 @@ ath_stop_locked(struct ifnet *ifp, int disable)
|
|||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
|
||||
DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
|
||||
__func__, sc->sc_invalid, ifp->if_flags);
|
||||
DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid %d if_flags 0x%x\n",
|
||||
__func__, !device_is_enabled(&sc->sc_dev), ifp->if_flags);
|
||||
|
||||
ATH_LOCK_ASSERT(sc);
|
||||
if (ifp->if_flags & IFF_RUNNING) {
|
||||
|
@ -1075,7 +1059,7 @@ ath_stop_locked(struct ifnet *ifp, int disable)
|
|||
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
ifp->if_timer = 0;
|
||||
if (!sc->sc_invalid) {
|
||||
if (device_is_enabled(&sc->sc_dev)) {
|
||||
if (sc->sc_softled) {
|
||||
callout_stop(&sc->sc_ledtimer);
|
||||
ath_hal_gpioset(ah, sc->sc_ledpin,
|
||||
|
@ -1085,7 +1069,7 @@ ath_stop_locked(struct ifnet *ifp, int disable)
|
|||
ath_hal_intrset(ah, 0);
|
||||
}
|
||||
ath_draintxq(sc);
|
||||
if (!sc->sc_invalid) {
|
||||
if (device_is_enabled(&sc->sc_dev)) {
|
||||
ath_stoprecv(sc);
|
||||
ath_hal_phydisable(ah);
|
||||
} else
|
||||
|
@ -1093,7 +1077,7 @@ ath_stop_locked(struct ifnet *ifp, int disable)
|
|||
IF_PURGE(&ifp->if_snd);
|
||||
ath_beacon_free(sc);
|
||||
if (disable)
|
||||
ath_disable(sc);
|
||||
pmf_device_suspend_self(&sc->sc_dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1104,18 +1088,6 @@ ath_stop(struct ifnet *ifp, int disable)
|
|||
|
||||
ATH_LOCK(sc);
|
||||
ath_stop_locked(ifp, disable);
|
||||
if (!sc->sc_invalid) {
|
||||
/*
|
||||
* Set the chip in full sleep mode. Note that we are
|
||||
* careful to do this only when bringing the interface
|
||||
* completely to a stop. When the chip is in this state
|
||||
* it must be carefully woken up or references to
|
||||
* registers in the PCI clock domain may freeze the bus
|
||||
* (and system). This varies by chip and is mostly an
|
||||
* issue with newer parts that go to sleep more quickly.
|
||||
*/
|
||||
ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
|
||||
}
|
||||
ATH_UNLOCK(sc);
|
||||
}
|
||||
|
||||
|
@ -1249,7 +1221,8 @@ ath_start(struct ifnet *ifp)
|
|||
struct ether_header *eh;
|
||||
ath_bufhead frags;
|
||||
|
||||
if ((ifp->if_flags & IFF_RUNNING) == 0 || sc->sc_invalid)
|
||||
if ((ifp->if_flags & IFF_RUNNING) == 0 ||
|
||||
!device_is_active(&sc->sc_dev))
|
||||
return;
|
||||
for (;;) {
|
||||
/*
|
||||
|
@ -1730,6 +1703,11 @@ ath_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k)
|
|||
|
||||
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: delete key %u\n", __func__, keyix);
|
||||
|
||||
if (!device_has_power(&sc->sc_dev)) {
|
||||
aprint_error_dev(&sc->sc_dev, "deleting keyix %d w/o power\n",
|
||||
k->wk_keyix);
|
||||
}
|
||||
|
||||
ath_hal_keyreset(ah, keyix);
|
||||
/*
|
||||
* Handle split tx/rx keying required for TKIP with h/w MIC.
|
||||
|
@ -1764,6 +1742,10 @@ ath_key_set(struct ieee80211com *ic, const struct ieee80211_key *k,
|
|||
{
|
||||
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
if (!device_has_power(&sc->sc_dev)) {
|
||||
aprint_error_dev(&sc->sc_dev, "setting keyix %d w/o power\n",
|
||||
k->wk_keyix);
|
||||
}
|
||||
return ath_keyset(sc, k, mac, ic->ic_bss);
|
||||
}
|
||||
|
||||
|
@ -1838,50 +1820,17 @@ ath_calcrxfilter(struct ath_softc *sc, enum ieee80211_state state)
|
|||
return rfilt;
|
||||
}
|
||||
|
||||
static void
|
||||
ath_mcastfilter_accum(void *dl, u_int32_t *mfilt)
|
||||
{
|
||||
u_int32_t val;
|
||||
u_int8_t pos;
|
||||
|
||||
/* calculate XOR of eight 6bit values */
|
||||
val = LE_READ_4((char *)dl + 0);
|
||||
pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
val = LE_READ_4((char *)dl + 3);
|
||||
pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
pos &= 0x3f;
|
||||
mfilt[pos / 32] |= (1 << (pos % 32));
|
||||
}
|
||||
|
||||
static void
|
||||
ath_mcastfilter_compute(struct ath_softc *sc, u_int32_t *mfilt)
|
||||
{
|
||||
struct ifnet *ifp = &sc->sc_if;
|
||||
struct ether_multi *enm;
|
||||
struct ether_multistep estep;
|
||||
|
||||
mfilt[0] = mfilt[1] = 0;
|
||||
ETHER_FIRST_MULTI(estep, &sc->sc_ec, enm);
|
||||
while (enm != NULL) {
|
||||
/* XXX Punt on ranges. */
|
||||
if (!IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi)) {
|
||||
mfilt[0] = mfilt[1] = ~((u_int32_t)0);
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
return;
|
||||
}
|
||||
ath_mcastfilter_accum(enm->enm_addrlo, mfilt);
|
||||
ETHER_NEXT_MULTI(estep, enm);
|
||||
}
|
||||
ifp->if_flags &= ~IFF_ALLMULTI;
|
||||
}
|
||||
|
||||
static void
|
||||
ath_mode_init(struct ath_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = &sc->sc_if;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
u_int32_t rfilt, mfilt[2];
|
||||
struct ether_multi *enm;
|
||||
struct ether_multistep estep;
|
||||
u_int32_t rfilt, mfilt[2], val;
|
||||
int i;
|
||||
uint8_t pos;
|
||||
|
||||
/* configure rx filter */
|
||||
rfilt = ath_calcrxfilter(sc, ic->ic_state);
|
||||
|
@ -1911,30 +1860,28 @@ ath_mode_init(struct ath_softc *sc)
|
|||
ath_hal_setmac(ah, ic->ic_myaddr);
|
||||
|
||||
/* calculate and install multicast filter */
|
||||
#ifdef __FreeBSD__
|
||||
if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
|
||||
mfilt[0] = mfilt[1] = 0;
|
||||
IF_ADDR_LOCK(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
void *dl;
|
||||
|
||||
/* calculate XOR of eight 6bit values */
|
||||
dl = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
|
||||
val = LE_READ_4((char *)dl + 0);
|
||||
pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
val = LE_READ_4((char *)dl + 3);
|
||||
pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
pos &= 0x3f;
|
||||
mfilt[pos / 32] |= (1 << (pos % 32));
|
||||
ifp->if_flags &= ~IFF_ALLMULTI;
|
||||
mfilt[0] = mfilt[1] = 0;
|
||||
ETHER_FIRST_MULTI(estep, &sc->sc_ec, enm);
|
||||
while (enm != NULL) {
|
||||
void *dl;
|
||||
/* XXX Punt on ranges. */
|
||||
if (!IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi)) {
|
||||
mfilt[0] = mfilt[1] = 0xffffffff;
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
break;
|
||||
}
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
} else {
|
||||
mfilt[0] = mfilt[1] = ~0;
|
||||
dl = enm->enm_addrlo;
|
||||
val = LE_READ_4((char *)dl + 0);
|
||||
pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
val = LE_READ_4((char *)dl + 3);
|
||||
pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
||||
pos &= 0x3f;
|
||||
mfilt[pos / 32] |= (1 << (pos % 32));
|
||||
|
||||
ETHER_NEXT_MULTI(estep, enm);
|
||||
}
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
ath_mcastfilter_compute(sc, mfilt);
|
||||
#endif
|
||||
|
||||
ath_hal_setmcastfilter(ah, mfilt[0], mfilt[1]);
|
||||
DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x, MC filter %08x:%08x\n",
|
||||
__func__, rfilt, mfilt[0], mfilt[1]);
|
||||
|
@ -4216,7 +4163,7 @@ ath_draintxq(struct ath_softc *sc)
|
|||
int i;
|
||||
|
||||
/* XXX return value */
|
||||
if (!sc->sc_invalid) {
|
||||
if (device_is_active(&sc->sc_dev)) {
|
||||
/* don't touch the hardware if marked invalid */
|
||||
(void) ath_hal_stoptxdma(ah, sc->sc_bhalq);
|
||||
DPRINTF(sc, ATH_DEBUG_RESET,
|
||||
|
@ -5051,11 +4998,12 @@ ath_printrxbuf(struct ath_buf *bf, int done)
|
|||
|
||||
for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) {
|
||||
printf("R%d (%p %" PRIx64
|
||||
") %08x %08x %08x %08x %08x %08x %c\n", i, ds,
|
||||
") %08x %08x %08x %08x %08x %08x %02x %02x %c\n", i, ds,
|
||||
(uint64_t)bf->bf_daddr + sizeof (struct ath_desc) * i,
|
||||
ds->ds_link, ds->ds_data,
|
||||
ds->ds_ctl0, ds->ds_ctl1,
|
||||
ds->ds_hw[0], ds->ds_hw[1],
|
||||
ds->ds_rxstat.rs_status, ds->ds_rxstat.rs_keyix,
|
||||
!done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
|
||||
}
|
||||
}
|
||||
|
@ -5088,7 +5036,8 @@ ath_watchdog(struct ifnet *ifp)
|
|||
int i;
|
||||
|
||||
ifp->if_timer = 0;
|
||||
if ((ifp->if_flags & IFF_RUNNING) == 0 || sc->sc_invalid)
|
||||
if ((ifp->if_flags & IFF_RUNNING) == 0 ||
|
||||
!device_is_active(&sc->sc_dev))
|
||||
return;
|
||||
for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
|
||||
if (!ATH_TXQ_SETUP(sc, i))
|
||||
|
@ -5202,9 +5151,8 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, void *data)
|
|||
* torn down much of our state. There's
|
||||
* probably a better way to deal with this.
|
||||
*/
|
||||
if (!sc->sc_invalid && ic->ic_bss != NULL)
|
||||
ath_init(sc); /* XXX lose error */
|
||||
} else
|
||||
error = ath_init(sc);
|
||||
} else if (device_is_active(&sc->sc_dev))
|
||||
ath_stop_locked(ifp, 1);
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
|
@ -5234,14 +5182,13 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, void *data)
|
|||
break;
|
||||
default:
|
||||
error = ieee80211_ioctl(ic, cmd, data);
|
||||
if (error == ENETRESET) {
|
||||
if (IS_RUNNING(ifp) &&
|
||||
ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
|
||||
ath_init(sc); /* XXX lose error */
|
||||
if (error != ENETRESET)
|
||||
;
|
||||
else if (IS_RUNNING(ifp) &&
|
||||
ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
|
||||
error = ath_init(sc);
|
||||
else
|
||||
error = 0;
|
||||
}
|
||||
if (error == ERESTART)
|
||||
error = IS_RUNNING(ifp) ? ath_reset(ifp) : 0;
|
||||
break;
|
||||
}
|
||||
ATH_UNLOCK(sc);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: athvar.h,v 1.23 2007/12/22 00:41:02 dyoung Exp $ */
|
||||
/* $NetBSD: athvar.h,v 1.24 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
|
@ -170,8 +170,6 @@ struct ath_softc {
|
|||
struct ethercom sc_ec; /* interface common */
|
||||
struct ath_stats sc_stats; /* interface statistics */
|
||||
struct ieee80211com sc_ic; /* IEEE 802.11 common */
|
||||
int (*sc_enable)(struct ath_softc *);
|
||||
void (*sc_disable)(struct ath_softc *);
|
||||
void (*sc_power)(struct ath_softc *, int);
|
||||
int sc_regdomain;
|
||||
int sc_countrycode;
|
||||
|
@ -192,8 +190,7 @@ struct ath_softc {
|
|||
struct ath_ratectrl *sc_rc; /* tx rate control support */
|
||||
struct ath_tx99 *sc_tx99; /* tx99 adjunct state */
|
||||
void (*sc_setdefantenna)(struct ath_softc *, u_int);
|
||||
unsigned int sc_invalid : 1, /* disable hardware accesses */
|
||||
sc_mrretry : 1, /* multi-rate retry support */
|
||||
unsigned int sc_mrretry : 1, /* multi-rate retry support */
|
||||
sc_softled : 1, /* enable LED gpio status */
|
||||
sc_splitmic: 1, /* split TKIP MIC keys */
|
||||
sc_needmib : 1, /* enable MIB stats intr */
|
||||
|
@ -297,16 +294,14 @@ struct ath_softc {
|
|||
#define sc_rx_th u_rx_rt.th
|
||||
|
||||
#define ATH_ATTACHED 0x0001 /* attach has succeeded */
|
||||
#define ATH_ENABLED 0x0002 /* chip is enabled */
|
||||
|
||||
#define ATH_IS_ENABLED(sc) ((sc)->sc_flags & ATH_ENABLED)
|
||||
|
||||
#define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i))
|
||||
|
||||
int ath_attach(u_int16_t, struct ath_softc *);
|
||||
int ath_detach(struct ath_softc *);
|
||||
int ath_activate(struct device *, enum devact);
|
||||
void ath_resume(struct ath_softc *);
|
||||
bool ath_resume(struct ath_softc *);
|
||||
void ath_suspend(struct ath_softc *);
|
||||
int ath_intr(void *);
|
||||
int ath_reset(struct ifnet *);
|
||||
void ath_sysctlattach(struct ath_softc *);
|
||||
|
|
162
sys/dev/ic/rtw.c
162
sys/dev/ic/rtw.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rtw.c,v 1.100 2008/03/12 15:47:49 dyoung Exp $ */
|
||||
/* $NetBSD: rtw.c,v 1.101 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2004, 2005, 2006, 2007 David Young. All rights
|
||||
* reserved.
|
||||
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.100 2008/03/12 15:47:49 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.101 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include "bpfilter.h"
|
||||
|
||||
|
@ -92,6 +92,11 @@ static int rtw_rxbufs_limit = RTW_RXQLEN;
|
|||
int rtw_dwelltime = 200; /* milliseconds */
|
||||
static struct ieee80211_cipher rtw_cipher_wep;
|
||||
|
||||
static void rtw_disable_interrupts(struct rtw_regs *);
|
||||
static void rtw_enable_interrupts(struct rtw_softc *);
|
||||
|
||||
static int rtw_init(struct ifnet *);
|
||||
|
||||
static void rtw_start(struct ifnet *);
|
||||
static void rtw_reset_oactive(struct rtw_softc *);
|
||||
static struct mbuf *rtw_beacon_alloc(struct rtw_softc *,
|
||||
|
@ -108,6 +113,7 @@ static int rtw_wep_decap(struct ieee80211_key *, struct mbuf *, int);
|
|||
static void rtw_wep_setkeys(struct rtw_softc *, struct ieee80211_key *, int);
|
||||
|
||||
static void rtw_led_attach(struct rtw_led_state *, void *);
|
||||
static void rtw_led_detach(struct rtw_led_state *);
|
||||
static void rtw_led_init(struct rtw_regs *);
|
||||
static void rtw_led_slowblink(void *);
|
||||
static void rtw_led_fastblink(void *);
|
||||
|
@ -599,8 +605,7 @@ rtw_key_update_end(struct ieee80211com *ic)
|
|||
DPRINTF(sc, RTW_DEBUG_KEY, ("%s:\n", __func__));
|
||||
|
||||
if ((sc->sc_flags & RTW_F_DK_VALID) != 0 ||
|
||||
(sc->sc_flags & RTW_F_ENABLED) == 0 ||
|
||||
(sc->sc_flags & RTW_F_INVALID) != 0)
|
||||
!device_is_active(sc->sc_dev))
|
||||
return;
|
||||
|
||||
rtw_io_enable(sc, RTW_CR_RE | RTW_CR_TE, 0);
|
||||
|
@ -1518,7 +1523,10 @@ rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
|
|||
goto next;
|
||||
}
|
||||
if (len > rs->rs_mbuf->m_len) {
|
||||
aprint_error_dev(sc->sc_dev, "rx frame too long\n");
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"rx frame too long, %d > %d, %08" PRIx32
|
||||
", desc %d\n",
|
||||
len, rs->rs_mbuf->m_len, hstat, next);
|
||||
ifp->if_ierrors++;
|
||||
goto next;
|
||||
}
|
||||
|
@ -2107,8 +2115,7 @@ rtw_intr(void *arg)
|
|||
* If the interface isn't running, the interrupt couldn't
|
||||
* possibly have come from us.
|
||||
*/
|
||||
if ((sc->sc_flags & RTW_F_ENABLED) == 0 ||
|
||||
(ifp->if_flags & IFF_RUNNING) == 0 ||
|
||||
if ((ifp->if_flags & IFF_RUNNING) == 0 ||
|
||||
!device_is_active(sc->sc_dev)) {
|
||||
RTW_DPRINTF(RTW_DEBUG_INTR, ("%s: stray interrupt\n",
|
||||
device_xname(sc->sc_dev)));
|
||||
|
@ -2189,14 +2196,11 @@ rtw_stop(struct ifnet *ifp, int disable)
|
|||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct rtw_regs *regs = &sc->sc_regs;
|
||||
|
||||
if ((sc->sc_flags & RTW_F_ENABLED) == 0)
|
||||
return;
|
||||
|
||||
rtw_suspend_ticks(sc);
|
||||
|
||||
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
|
||||
|
||||
if ((sc->sc_flags & RTW_F_INVALID) == 0) {
|
||||
if (device_has_power(sc->sc_dev)) {
|
||||
/* Disable interrupts. */
|
||||
RTW_WRITE16(regs, RTW_IMR, 0);
|
||||
|
||||
|
@ -2219,13 +2223,13 @@ rtw_stop(struct ifnet *ifp, int disable)
|
|||
|
||||
rtw_rxbufs_release(sc->sc_dmat, &sc->sc_rxsoft[0]);
|
||||
|
||||
if (disable)
|
||||
rtw_disable(sc);
|
||||
|
||||
/* Mark the interface as not running. Cancel the watchdog timer. */
|
||||
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
|
||||
ifp->if_timer = 0;
|
||||
|
||||
if (disable)
|
||||
pmf_device_suspend_self(sc->sc_dev);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2448,7 +2452,7 @@ rtw_tune(struct rtw_softc *sc)
|
|||
|
||||
/* TBD wait for Tx to complete */
|
||||
|
||||
KASSERT((sc->sc_flags & RTW_F_ENABLED) != 0);
|
||||
KASSERT(device_has_power(sc->sc_dev));
|
||||
|
||||
if ((rc = rtw_phy_init(&sc->sc_regs, sc->sc_rf,
|
||||
rtw_chan2txpower(&sc->sc_srom, ic, ic->ic_curchan), sc->sc_csthr,
|
||||
|
@ -2466,43 +2470,39 @@ rtw_tune(struct rtw_softc *sc)
|
|||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
rtw_disable(struct rtw_softc *sc)
|
||||
bool
|
||||
rtw_suspend(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
int rc;
|
||||
struct rtw_softc *sc = device_private(self);
|
||||
|
||||
if ((sc->sc_flags & RTW_F_ENABLED) == 0)
|
||||
return;
|
||||
sc->sc_flags &= ~RTW_F_DK_VALID;
|
||||
|
||||
if (!device_has_power(self))
|
||||
return false;
|
||||
|
||||
/* turn off PHY */
|
||||
if ((sc->sc_flags & RTW_F_INVALID) == 0 &&
|
||||
(rc = rtw_pwrstate(sc, RTW_OFF)) != 0) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"failed to turn off PHY (%d)\n", rc);
|
||||
if ((rc = rtw_pwrstate(sc, RTW_OFF)) != 0) {
|
||||
aprint_error_dev(self, "failed to turn off PHY (%d)\n", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sc->sc_disable != NULL)
|
||||
(*sc->sc_disable)(sc);
|
||||
rtw_disable_interrupts(&sc->sc_regs);
|
||||
|
||||
sc->sc_flags &= ~RTW_F_ENABLED;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
rtw_enable(struct rtw_softc *sc)
|
||||
bool
|
||||
rtw_resume(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
if ((sc->sc_flags & RTW_F_ENABLED) == 0) {
|
||||
if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"device enable failed\n");
|
||||
return (EIO);
|
||||
}
|
||||
sc->sc_flags |= RTW_F_ENABLED;
|
||||
/* Power may have been removed, and WEP keys thus
|
||||
* reset.
|
||||
*/
|
||||
sc->sc_flags &= ~RTW_F_DK_VALID;
|
||||
}
|
||||
return (0);
|
||||
struct rtw_softc *sc = device_private(self);
|
||||
|
||||
/* Power may have been removed, resetting WEP keys.
|
||||
*/
|
||||
sc->sc_flags &= ~RTW_F_DK_VALID;
|
||||
rtw_enable_interrupts(sc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2529,7 +2529,16 @@ rtw_transmit_config(struct rtw_regs *regs)
|
|||
RTW_SYNC(regs, RTW_TCR, RTW_TCR);
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
rtw_disable_interrupts(struct rtw_regs *regs)
|
||||
{
|
||||
RTW_WRITE16(regs, RTW_IMR, 0);
|
||||
RTW_WBW(regs, RTW_IMR, RTW_ISR);
|
||||
RTW_WRITE16(regs, RTW_ISR, 0xffff);
|
||||
RTW_SYNC(regs, RTW_IMR, RTW_ISR);
|
||||
}
|
||||
|
||||
static void
|
||||
rtw_enable_interrupts(struct rtw_softc *sc)
|
||||
{
|
||||
struct rtw_regs *regs = &sc->sc_regs;
|
||||
|
@ -2685,13 +2694,13 @@ rtw_init(struct ifnet *ifp)
|
|||
struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct rtw_regs *regs = &sc->sc_regs;
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
if ((rc = rtw_enable(sc)) != 0)
|
||||
goto out;
|
||||
|
||||
/* Cancel pending I/O and reset. */
|
||||
rtw_stop(ifp, 0);
|
||||
if (device_is_active(sc->sc_dev)) {
|
||||
/* Cancel pending I/O and reset. */
|
||||
rtw_stop(ifp, 0);
|
||||
} else if (!pmf_device_resume_self(sc->sc_dev))
|
||||
return 0; /* XXX error? */
|
||||
|
||||
DPRINTF(sc, RTW_DEBUG_TUNE, ("%s: channel %d freq %d flags 0x%04x\n",
|
||||
__func__, ieee80211_chan2ieee(ic, ic->ic_curchan),
|
||||
|
@ -2800,6 +2809,7 @@ rtw_led_newstate(struct rtw_softc *sc, enum ieee80211_state nstate)
|
|||
switch (nstate) {
|
||||
case IEEE80211_S_INIT:
|
||||
rtw_led_init(&sc->sc_regs);
|
||||
aprint_debug_dev(sc->sc_dev, "stopping blink\n");
|
||||
callout_stop(&ls->ls_slow_ch);
|
||||
callout_stop(&ls->ls_fast_ch);
|
||||
ls->ls_slowblink = 0;
|
||||
|
@ -2807,6 +2817,7 @@ rtw_led_newstate(struct rtw_softc *sc, enum ieee80211_state nstate)
|
|||
ls->ls_default = 0;
|
||||
break;
|
||||
case IEEE80211_S_SCAN:
|
||||
aprint_debug_dev(sc->sc_dev, "scheduling blink\n");
|
||||
callout_schedule(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
|
||||
callout_schedule(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
|
||||
/*FALLTHROUGH*/
|
||||
|
@ -2896,6 +2907,7 @@ rtw_led_fastblink(void *arg)
|
|||
rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
|
||||
splx(s);
|
||||
|
||||
aprint_debug_dev(sc->sc_dev, "scheduling fast blink\n");
|
||||
callout_schedule(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
|
||||
}
|
||||
|
||||
|
@ -2910,10 +2922,18 @@ rtw_led_slowblink(void *arg)
|
|||
ls->ls_state ^= RTW_LED_S_SLOW;
|
||||
rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
|
||||
splx(s);
|
||||
aprint_debug_dev(sc->sc_dev, "scheduling slow blink\n");
|
||||
callout_schedule(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
|
||||
}
|
||||
|
||||
static inline void
|
||||
static void
|
||||
rtw_led_detach(struct rtw_led_state *ls)
|
||||
{
|
||||
callout_destroy(&ls->ls_fast_ch);
|
||||
callout_destroy(&ls->ls_slow_ch);
|
||||
}
|
||||
|
||||
static void
|
||||
rtw_led_attach(struct rtw_led_state *ls, void *arg)
|
||||
{
|
||||
callout_init(&ls->ls_fast_ch, 0);
|
||||
|
@ -2931,12 +2951,12 @@ rtw_ioctl(struct ifnet *ifp, u_long cmd, void *data)
|
|||
s = splnet();
|
||||
if (cmd == SIOCSIFFLAGS) {
|
||||
if ((ifp->if_flags & IFF_UP) != 0) {
|
||||
if ((sc->sc_flags & RTW_F_ENABLED) != 0)
|
||||
if (device_is_active(sc->sc_dev))
|
||||
rtw_pktfilt_load(sc);
|
||||
else
|
||||
rc = rtw_init(ifp);
|
||||
RTW_PRINT_REGS(&sc->sc_regs, ifp->if_xname, __func__);
|
||||
} else if ((sc->sc_flags & RTW_F_ENABLED) != 0) {
|
||||
} else if (device_is_active(sc->sc_dev)) {
|
||||
RTW_PRINT_REGS(&sc->sc_regs, ifp->if_xname, __func__);
|
||||
rtw_stop(ifp, 1);
|
||||
}
|
||||
|
@ -2947,8 +2967,7 @@ rtw_ioctl(struct ifnet *ifp, u_long cmd, void *data)
|
|||
if (ifp->if_flags & IFF_RUNNING)
|
||||
rtw_pktfilt_load(sc);
|
||||
rc = 0;
|
||||
} else if ((sc->sc_flags & RTW_F_ENABLED) != 0)
|
||||
/* reinitialize h/w if activated */
|
||||
} else if ((ifp->if_flags & IFF_UP) != 0)
|
||||
rc = rtw_init(ifp);
|
||||
else
|
||||
rc = 0;
|
||||
|
@ -3463,7 +3482,7 @@ rtw_watchdog(struct ifnet *ifp)
|
|||
|
||||
ifp->if_timer = 0;
|
||||
|
||||
if ((sc->sc_flags & RTW_F_ENABLED) == 0)
|
||||
if (!device_is_active(sc->sc_dev))
|
||||
return;
|
||||
|
||||
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
||||
|
@ -3554,8 +3573,10 @@ rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
|
|||
|
||||
ostate = ic->ic_state;
|
||||
|
||||
aprint_debug_dev(sc->sc_dev, "%s: l.%d\n", __func__, __LINE__);
|
||||
rtw_led_newstate(sc, nstate);
|
||||
|
||||
aprint_debug_dev(sc->sc_dev, "%s: l.%d\n", __func__, __LINE__);
|
||||
if (nstate == IEEE80211_S_INIT) {
|
||||
callout_stop(&sc->sc_scan_ch);
|
||||
sc->sc_cur_chan = IEEE80211_CHAN_ANY;
|
||||
|
@ -3636,7 +3657,8 @@ rtw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m,
|
|||
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
|
||||
case IEEE80211_FC0_SUBTYPE_BEACON:
|
||||
if (ic->ic_opmode == IEEE80211_M_IBSS &&
|
||||
ic->ic_state == IEEE80211_S_RUN) {
|
||||
ic->ic_state == IEEE80211_S_RUN &&
|
||||
device_is_active(sc->sc_dev)) {
|
||||
uint64_t tsf = rtw_tsf_extend(&sc->sc_regs, rstamp);
|
||||
if (le64toh(ni->ni_tstamp.tsf) >= tsf)
|
||||
(void)ieee80211_ibss_merge(ni);
|
||||
|
@ -3693,7 +3715,7 @@ rtw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
|||
{
|
||||
struct rtw_softc *sc = ifp->if_softc;
|
||||
|
||||
if ((sc->sc_flags & RTW_F_ENABLED) == 0) {
|
||||
if (!device_is_active(sc->sc_dev)) {
|
||||
imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
|
||||
imr->ifm_status = 0;
|
||||
return;
|
||||
|
@ -4131,12 +4153,6 @@ rtw_attach(struct rtw_softc *sc)
|
|||
sizeof(struct ieee80211_frame) + 64, &sc->sc_radiobpf);
|
||||
#endif
|
||||
|
||||
if (!pmf_device_register(sc->sc_dev, NULL, NULL)) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"couldn't establish power handler\n");
|
||||
} else
|
||||
pmf_class_network_register(sc->sc_dev, &sc->sc_if);
|
||||
|
||||
NEXT_ATTACH_STATE(sc, FINISHED);
|
||||
|
||||
ieee80211_announce(ic);
|
||||
|
@ -4153,7 +4169,6 @@ rtw_detach(struct rtw_softc *sc)
|
|||
int pri, s;
|
||||
|
||||
s = splnet();
|
||||
sc->sc_flags |= RTW_F_INVALID;
|
||||
|
||||
switch (sc->sc_attach_state) {
|
||||
case FINISHED:
|
||||
|
@ -4163,6 +4178,7 @@ rtw_detach(struct rtw_softc *sc)
|
|||
callout_stop(&sc->sc_scan_ch);
|
||||
ieee80211_ifdetach(&sc->sc_ic);
|
||||
if_detach(ifp);
|
||||
rtw_led_detach(&sc->sc_led_state);
|
||||
/*FALLTHROUGH*/
|
||||
case FINISH_ID_STA:
|
||||
case FINISH_RF_ATTACH:
|
||||
|
@ -4210,23 +4226,3 @@ rtw_detach(struct rtw_softc *sc)
|
|||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rtw_activate(device_t self, enum devact act)
|
||||
{
|
||||
struct rtw_softc *sc = device_private(self);
|
||||
int rc = 0, s;
|
||||
|
||||
s = splnet();
|
||||
switch (act) {
|
||||
case DVACT_ACTIVATE:
|
||||
rc = EOPNOTSUPP;
|
||||
break;
|
||||
|
||||
case DVACT_DEACTIVATE:
|
||||
if_deactivate(&sc->sc_if);
|
||||
break;
|
||||
}
|
||||
splx(s);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rtwvar.h,v 1.36 2007/12/25 18:33:39 perry Exp $ */
|
||||
/* $NetBSD: rtwvar.h,v 1.37 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2004, 2005 David Young. All rights reserved.
|
||||
*
|
||||
|
@ -94,18 +94,14 @@ enum rtw_rfchipid {
|
|||
RTW_RFCHIPID_MAXIM = 4,
|
||||
RTW_RFCHIPID_GCT = 5
|
||||
};
|
||||
|
||||
/* sc_flags */
|
||||
#define RTW_F_ENABLED 0x00000001 /* chip is enabled */
|
||||
#define RTW_F_DIGPHY 0x00000002 /* digital PHY */
|
||||
#define RTW_F_DFLANTB 0x00000004 /* B antenna is default */
|
||||
#define RTW_F_ANTDIV 0x00000010 /* h/w antenna diversity */
|
||||
#define RTW_F_9356SROM 0x00000020 /* 93c56 SROM */
|
||||
#define RTW_F_SLEEP 0x00000040 /* chip is asleep */
|
||||
#define RTW_F_INVALID 0x00000080 /* chip is absent */
|
||||
#define RTW_F_DK_VALID 0x00000100 /* keys in DK0-DK3 are valid */
|
||||
#define RTW_C_RXWEP_40 0x00000200 /* h/w decrypts 40-bit WEP */
|
||||
#define RTW_C_RXWEP_104 0x00000400 /* h/w decrypts 104-bit WEP */
|
||||
#define RTW_F_DK_VALID 0x00000040 /* keys in DK0-DK3 are valid */
|
||||
#define RTW_C_RXWEP_40 0x00000080 /* h/w decrypts 40-bit WEP */
|
||||
#define RTW_C_RXWEP_104 0x00000100 /* h/w decrypts 104-bit WEP */
|
||||
/* all PHY flags */
|
||||
#define RTW_F_ALLPHY (RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV)
|
||||
enum rtw_access {RTW_ACCESS_NONE = 0,
|
||||
|
@ -115,6 +111,7 @@ enum rtw_access {RTW_ACCESS_NONE = 0,
|
|||
struct rtw_regs {
|
||||
bus_space_tag_t r_bt;
|
||||
bus_space_handle_t r_bh;
|
||||
bus_size_t r_sz;
|
||||
enum rtw_access r_access;
|
||||
};
|
||||
|
||||
|
@ -459,8 +456,6 @@ struct rtw_softc {
|
|||
/* interrupt acknowledge hook */
|
||||
void (*sc_intr_ack)(struct rtw_regs *);
|
||||
|
||||
int (*sc_enable)(struct rtw_softc *);
|
||||
void (*sc_disable)(struct rtw_softc *);
|
||||
struct rtw_mtbl sc_mtbl;
|
||||
|
||||
void * sc_radiobpf;
|
||||
|
@ -507,11 +502,10 @@ void rtw_attach(struct rtw_softc *);
|
|||
int rtw_detach(struct rtw_softc *);
|
||||
int rtw_intr(void *);
|
||||
|
||||
void rtw_disable(struct rtw_softc *);
|
||||
int rtw_enable(struct rtw_softc *);
|
||||
bool rtw_suspend(device_t PMF_FN_PROTO);
|
||||
bool rtw_resume(device_t PMF_FN_PROTO);
|
||||
|
||||
int rtw_activate(device_t, enum devact);
|
||||
void rtw_shutdown(void *);
|
||||
|
||||
const char *rtw_pwrstate_string(enum rtw_pwrstate);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_ath_pci.c,v 1.29 2008/03/07 22:17:03 dyoung Exp $ */
|
||||
/* $NetBSD: if_ath_pci.c,v 1.30 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
|
||||
|
@ -41,7 +41,7 @@
|
|||
__FBSDID("$FreeBSD: src/sys/dev/ath/if_ath_pci.c,v 1.11 2005/01/18 18:08:16 sam Exp $");
|
||||
#endif
|
||||
#ifdef __NetBSD__
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ath_pci.c,v 1.29 2008/03/07 22:17:03 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ath_pci.c,v 1.30 2008/03/12 18:02:21 dyoung Exp $");
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -84,6 +84,7 @@ struct ath_pci_softc {
|
|||
struct ath_softc sc_sc;
|
||||
pci_chipset_tag_t sc_pc;
|
||||
pcitag_t sc_pcitag;
|
||||
pci_intr_handle_t sc_pih;
|
||||
void *sc_ih; /* interrupt handler */
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
|
@ -92,10 +93,10 @@ struct ath_pci_softc {
|
|||
|
||||
#define BS_BAR 0x10
|
||||
|
||||
static void ath_pci_attach(struct device *, struct device *, void *);
|
||||
static int ath_pci_detach(struct device *, int);
|
||||
static int ath_pci_match(struct device *, struct cfdata *, void *);
|
||||
static int ath_pci_detach(struct device *, int);
|
||||
static void ath_pci_attach(device_t, device_t, void *);
|
||||
static int ath_pci_detach(device_t, int);
|
||||
static int ath_pci_match(device_t, struct cfdata *, void *);
|
||||
static int ath_pci_detach(device_t, int);
|
||||
|
||||
CFATTACH_DECL(ath_pci,
|
||||
sizeof(struct ath_pci_softc),
|
||||
|
@ -105,7 +106,7 @@ CFATTACH_DECL(ath_pci,
|
|||
NULL);
|
||||
|
||||
static int
|
||||
ath_pci_match(struct device *parent, struct cfdata *match, void *aux)
|
||||
ath_pci_match(device_t parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
const char* devname;
|
||||
struct pci_attach_args *pa = aux;
|
||||
|
@ -117,10 +118,28 @@ ath_pci_match(struct device *parent, struct cfdata *match, void *aux)
|
|||
}
|
||||
|
||||
static bool
|
||||
ath_pci_resume(device_t dv)
|
||||
ath_pci_suspend(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct ath_pci_softc *sc = device_private(dv);
|
||||
struct ath_pci_softc *sc = device_private(self);
|
||||
|
||||
ath_suspend(&sc->sc_sc);
|
||||
pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
|
||||
sc->sc_ih = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ath_pci_resume(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct ath_pci_softc *sc = device_private(self);
|
||||
|
||||
sc->sc_ih = pci_intr_establish(sc->sc_pc, sc->sc_pih, IPL_NET, ath_intr,
|
||||
&sc->sc_sc);
|
||||
if (sc->sc_ih == NULL) {
|
||||
aprint_error_dev(self, "couldn't map interrupt\n");
|
||||
return false;
|
||||
}
|
||||
ath_resume(&sc->sc_sc);
|
||||
|
||||
return true;
|
||||
|
@ -180,13 +199,12 @@ ath_pci_setup(struct ath_pci_softc *sc)
|
|||
}
|
||||
|
||||
static void
|
||||
ath_pci_attach(struct device *parent, struct device *self, void *aux)
|
||||
ath_pci_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct ath_pci_softc *psc = (struct ath_pci_softc *)self;
|
||||
struct ath_pci_softc *psc = device_private(self);
|
||||
struct ath_softc *sc = &psc->sc_sc;
|
||||
struct pci_attach_args *pa = aux;
|
||||
pci_chipset_tag_t pc = pa->pa_pc;
|
||||
pci_intr_handle_t ih;
|
||||
pcireg_t mem_type;
|
||||
const char *intrstr = NULL;
|
||||
|
||||
|
@ -215,37 +233,39 @@ ath_pci_attach(struct device *parent, struct device *self, void *aux)
|
|||
sc->sc_st = HALTAG(psc->sc_iot);
|
||||
sc->sc_sh = HALHANDLE(psc->sc_ioh);
|
||||
|
||||
sc->sc_invalid = 1;
|
||||
|
||||
/*
|
||||
* Arrange interrupt line.
|
||||
*/
|
||||
if (pci_intr_map(pa, &ih)) {
|
||||
if (pci_intr_map(pa, &psc->sc_pih)) {
|
||||
aprint_error("couldn't map interrupt\n");
|
||||
goto bad1;
|
||||
}
|
||||
|
||||
intrstr = pci_intr_string(pc, ih);
|
||||
psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ath_intr, sc);
|
||||
intrstr = pci_intr_string(pc, psc->sc_pih);
|
||||
psc->sc_ih = pci_intr_establish(pc, psc->sc_pih, IPL_NET, ath_intr, sc);
|
||||
if (psc->sc_ih == NULL) {
|
||||
aprint_error("couldn't map interrupt\n");
|
||||
goto bad2;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
|
||||
aprint_normal("\n");
|
||||
aprint_verbose_dev(self, "interrupting at %s\n", intrstr);
|
||||
|
||||
sc->sc_dmat = pa->pa_dmat;
|
||||
|
||||
ATH_LOCK_INIT(sc);
|
||||
|
||||
if (!pmf_device_register(self, NULL, ath_pci_resume))
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
if (ath_attach(PCI_PRODUCT(pa->pa_id), sc) != 0)
|
||||
goto bad3;
|
||||
|
||||
if (ath_attach(PCI_PRODUCT(pa->pa_id), sc) == 0) {
|
||||
if (!pmf_device_register(self, ath_pci_suspend, ath_pci_resume))
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
else {
|
||||
pmf_class_network_register(self, &sc->sc_if);
|
||||
return;
|
||||
pmf_device_suspend_self(self);
|
||||
}
|
||||
return;
|
||||
bad3:
|
||||
ATH_LOCK_DESTROY(sc);
|
||||
|
||||
pci_intr_disestablish(pc, psc->sc_ih);
|
||||
|
@ -257,9 +277,9 @@ bad: /* XXX */
|
|||
}
|
||||
|
||||
static int
|
||||
ath_pci_detach(struct device *self, int flags)
|
||||
ath_pci_detach(device_t self, int flags)
|
||||
{
|
||||
struct ath_pci_softc *psc = (struct ath_pci_softc *)self;
|
||||
struct ath_pci_softc *psc = device_private(self);
|
||||
|
||||
ath_detach(&psc->sc_sc);
|
||||
pmf_device_deregister(self);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_rtw_pci.c,v 1.9 2007/12/21 18:22:44 dyoung Exp $ */
|
||||
/* $NetBSD: if_rtw_pci.c,v 1.10 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999, 2000, 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -46,7 +46,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_rtw_pci.c,v 1.9 2007/12/21 18:22:44 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_rtw_pci.c,v 1.10 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -98,9 +98,10 @@ struct rtw_pci_softc {
|
|||
|
||||
static int rtw_pci_match(device_t, struct cfdata *, void *);
|
||||
static void rtw_pci_attach(device_t, device_t, void *);
|
||||
static int rtw_pci_detach(device_t, int);
|
||||
|
||||
CFATTACH_DECL_NEW(rtw_pci, sizeof(struct rtw_pci_softc),
|
||||
rtw_pci_match, rtw_pci_attach, NULL, NULL);
|
||||
rtw_pci_match, rtw_pci_attach, rtw_pci_detach, NULL);
|
||||
|
||||
static const struct rtw_pci_product {
|
||||
u_int32_t app_vendor; /* PCI vendor ID */
|
||||
|
@ -141,30 +142,35 @@ rtw_pci_match(device_t parent, struct cfdata *match, void *aux)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rtw_pci_enable(struct rtw_softc *sc)
|
||||
static bool
|
||||
rtw_pci_resume(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct rtw_pci_softc *psc = (void *)sc;
|
||||
struct rtw_pci_softc *psc = device_private(self);
|
||||
struct rtw_softc *sc = &psc->psc_rtw;
|
||||
|
||||
/* Establish the interrupt. */
|
||||
psc->psc_intrcookie = pci_intr_establish(psc->psc_pc, psc->psc_ih,
|
||||
IPL_NET, rtw_intr, sc);
|
||||
if (psc->psc_intrcookie == NULL) {
|
||||
aprint_error_dev(sc->sc_dev, "unable to establish interrupt\n");
|
||||
return (1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return (0);
|
||||
return rtw_resume(self, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
rtw_pci_disable(struct rtw_softc *sc)
|
||||
static bool
|
||||
rtw_pci_suspend(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct rtw_pci_softc *psc = (void *)sc;
|
||||
struct rtw_pci_softc *psc = device_private(self);
|
||||
|
||||
if (!rtw_suspend(self, flags))
|
||||
return false;
|
||||
|
||||
/* Unhook the interrupt handler. */
|
||||
pci_intr_disestablish(psc->psc_pc, psc->psc_intrcookie);
|
||||
psc->psc_intrcookie = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -176,9 +182,6 @@ rtw_pci_attach(device_t parent, device_t self, void *aux)
|
|||
struct pci_attach_args *pa = aux;
|
||||
pci_chipset_tag_t pc = pa->pa_pc;
|
||||
const char *intrstr = NULL;
|
||||
bus_space_tag_t iot, memt;
|
||||
bus_space_handle_t ioh, memh;
|
||||
int ioh_valid, memh_valid;
|
||||
const struct rtw_pci_product *app;
|
||||
int error;
|
||||
|
||||
|
@ -192,12 +195,6 @@ rtw_pci_attach(device_t parent, device_t self, void *aux)
|
|||
panic("rtw_pci_attach: impossible");
|
||||
}
|
||||
|
||||
/*
|
||||
* No power management hooks.
|
||||
* XXX Maybe we should add some!
|
||||
*/
|
||||
sc->sc_flags |= RTW_F_ENABLED;
|
||||
|
||||
/*
|
||||
* Get revision info, and set some chip-specific variables.
|
||||
*/
|
||||
|
@ -206,8 +203,8 @@ rtw_pci_attach(device_t parent, device_t self, void *aux)
|
|||
(sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf);
|
||||
|
||||
/* power up chip */
|
||||
if ((error = pci_activate(pa->pa_pc, pa->pa_tag, sc,
|
||||
NULL)) && error != EOPNOTSUPP) {
|
||||
if ((error = pci_activate(pa->pa_pc, pa->pa_tag, sc, NULL)) != 0 &&
|
||||
error != EOPNOTSUPP) {
|
||||
aprint_error_dev(self, "cannot activate %d\n", error);
|
||||
return;
|
||||
}
|
||||
|
@ -215,21 +212,15 @@ rtw_pci_attach(device_t parent, device_t self, void *aux)
|
|||
/*
|
||||
* Map the device.
|
||||
*/
|
||||
ioh_valid = (pci_mapreg_map(pa, RTW_PCI_IOBA,
|
||||
PCI_MAPREG_TYPE_IO, 0,
|
||||
&iot, &ioh, NULL, NULL) == 0);
|
||||
memh_valid = (pci_mapreg_map(pa, RTW_PCI_MMBA,
|
||||
if (pci_mapreg_map(pa, RTW_PCI_MMBA,
|
||||
PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
|
||||
&memt, &memh, NULL, NULL) == 0);
|
||||
|
||||
if (memh_valid) {
|
||||
regs->r_bt = memt;
|
||||
regs->r_bh = memh;
|
||||
} else if (ioh_valid) {
|
||||
regs->r_bt = iot;
|
||||
regs->r_bh = ioh;
|
||||
} else {
|
||||
aprint_error(": unable to map device registers\n");
|
||||
®s->r_bt, ®s->r_bh, NULL, ®s->r_sz) == 0)
|
||||
;
|
||||
else if (pci_mapreg_map(pa, RTW_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0,
|
||||
®s->r_bt, ®s->r_bh, NULL, ®s->r_sz) == 0)
|
||||
;
|
||||
else {
|
||||
aprint_error_dev(self, "unable to map device registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -262,11 +253,37 @@ rtw_pci_attach(device_t parent, device_t self, void *aux)
|
|||
|
||||
aprint_normal_dev(self, "interrupting at %s\n", intrstr);
|
||||
|
||||
sc->sc_enable = rtw_pci_enable;
|
||||
sc->sc_disable = rtw_pci_disable;
|
||||
|
||||
/*
|
||||
* Finish off the attach.
|
||||
*/
|
||||
rtw_attach(sc);
|
||||
|
||||
if (!pmf_device_register(sc->sc_dev, rtw_pci_suspend,
|
||||
rtw_pci_resume)) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"couldn't establish power handler\n");
|
||||
} else {
|
||||
pmf_class_network_register(self, &sc->sc_if);
|
||||
/*
|
||||
* Power down the socket.
|
||||
*/
|
||||
pmf_device_suspend_self(self);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
rtw_pci_detach(device_t self, int flags)
|
||||
{
|
||||
struct rtw_pci_softc *psc = device_private(self);
|
||||
struct rtw_softc *sc = &psc->psc_rtw;
|
||||
struct rtw_regs *regs = &sc->sc_regs;
|
||||
int rc;
|
||||
|
||||
if ((rc = rtw_detach(sc)) != 0)
|
||||
return rc;
|
||||
if (psc->psc_intrcookie != NULL)
|
||||
pci_intr_disestablish(psc->psc_pc, psc->psc_intrcookie);
|
||||
bus_space_unmap(regs->r_bt, regs->r_bh, regs->r_sz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_sip.c,v 1.129 2008/03/11 22:26:14 dyoung Exp $ */
|
||||
/* $NetBSD: if_sip.c,v 1.130 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -80,7 +80,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.129 2008/03/11 22:26:14 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.130 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include "bpfilter.h"
|
||||
#include "rnd.h"
|
||||
|
@ -614,6 +614,7 @@ static void sipcom_attach(device_t, device_t, void *);
|
|||
static void sipcom_do_detach(device_t, enum sip_attach_stage);
|
||||
static int sipcom_detach(device_t, int);
|
||||
static bool sipcom_resume(device_t PMF_FN_PROTO);
|
||||
static bool sipcom_suspend(device_t PMF_FN_PROTO);
|
||||
|
||||
int gsip_copy_small = 0;
|
||||
int sip_copy_small = 0;
|
||||
|
@ -972,6 +973,15 @@ sipcom_resume(device_t self PMF_FN_ARGS)
|
|||
return sipcom_reset(sc);
|
||||
}
|
||||
|
||||
static bool
|
||||
sipcom_suspend(device_t self PMF_FN_ARGS)
|
||||
{
|
||||
struct sip_softc *sc = device_private(self);
|
||||
|
||||
sipcom_rxdrain(sc);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
sipcom_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
|
@ -1363,7 +1373,7 @@ sipcom_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
#endif /* SIP_EVENT_COUNTERS */
|
||||
|
||||
if (!pmf_device_register(self, NULL, sipcom_resume))
|
||||
if (!pmf_device_register(self, sipcom_suspend, sipcom_resume))
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
else
|
||||
pmf_class_network_register(self, ifp);
|
||||
|
@ -2551,13 +2561,13 @@ sipcom_init(struct ifnet *ifp)
|
|||
struct sip_desc *sipd;
|
||||
int i, error = 0;
|
||||
|
||||
if (!device_has_power(&sc->sc_dev))
|
||||
return EBUSY;
|
||||
|
||||
/*
|
||||
* Cancel any pending I/O.
|
||||
*/
|
||||
sipcom_stop(ifp, 0);
|
||||
if (device_is_active(&sc->sc_dev)) {
|
||||
/*
|
||||
* Cancel any pending I/O.
|
||||
*/
|
||||
sipcom_stop(ifp, 0);
|
||||
} else if (!pmf_device_resume_self(&sc->sc_dev))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Reset the chip to a known state.
|
||||
|
@ -2877,15 +2887,15 @@ sipcom_stop(struct ifnet *ifp, int disable)
|
|||
SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
|
||||
}
|
||||
|
||||
if (disable)
|
||||
sipcom_rxdrain(sc);
|
||||
|
||||
/*
|
||||
* Mark the interface down and cancel the watchdog timer.
|
||||
*/
|
||||
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
|
||||
ifp->if_timer = 0;
|
||||
|
||||
if (disable)
|
||||
pmf_device_suspend_self(&sc->sc_dev);
|
||||
|
||||
if ((ifp->if_flags & IFF_DEBUG) != 0 &&
|
||||
(cmdsts & CMDSTS_INTR) == 0 && sc->sc_txfree != sc->sc_ntxdesc)
|
||||
printf("%s: sip_stop: no INTR bits set in dirty tx "
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_drvctl.c,v 1.15 2008/03/05 07:09:18 dyoung Exp $ */
|
||||
/* $NetBSD: kern_drvctl.c,v 1.16 2008/03/12 18:02:21 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_drvctl.c,v 1.15 2008/03/05 07:09:18 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_drvctl.c,v 1.16 2008/03/12 18:02:21 dyoung Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -63,12 +63,15 @@ pmdevbyname(int cmd, struct devpmargs *a)
|
|||
|
||||
switch (cmd) {
|
||||
case DRVSUSPENDDEV:
|
||||
return pmf_device_recursive_suspend(d) ? 0 : EBUSY;
|
||||
return pmf_device_recursive_suspend(d, PMF_F_NONE) ? 0 : EBUSY;
|
||||
case DRVRESUMEDEV:
|
||||
if (a->flags & DEVPM_F_SUBTREE)
|
||||
return pmf_device_resume_subtree(d) ? 0 : EBUSY;
|
||||
else
|
||||
return pmf_device_recursive_resume(d) ? 0 : EBUSY;
|
||||
if (a->flags & DEVPM_F_SUBTREE) {
|
||||
return pmf_device_resume_subtree(d, PMF_F_NONE)
|
||||
? 0 : EBUSY;
|
||||
} else {
|
||||
return pmf_device_recursive_resume(d, PMF_F_NONE)
|
||||
? 0 : EBUSY;
|
||||
}
|
||||
default:
|
||||
return EPASSTHROUGH;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_pmf.c,v 1.16 2008/03/07 07:03:06 dyoung Exp $ */
|
||||
/* $NetBSD: kern_pmf.c,v 1.17 2008/03/12 18:02:22 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_pmf.c,v 1.16 2008/03/07 07:03:06 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_pmf.c,v 1.17 2008/03/12 18:02:22 dyoung Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -375,6 +375,12 @@ pmf_device_deregister(device_t dev)
|
|||
device_pmf_driver_deregister(dev);
|
||||
}
|
||||
|
||||
bool
|
||||
pmf_device_suspend_self(device_t dev)
|
||||
{
|
||||
return pmf_device_suspend(dev, PMF_F_SELF);
|
||||
}
|
||||
|
||||
bool
|
||||
pmf_device_suspend(device_t dev PMF_FN_ARGS)
|
||||
{
|
||||
|
@ -398,6 +404,8 @@ pmf_device_suspend(device_t dev PMF_FN_ARGS)
|
|||
static bool
|
||||
pmf_device_suspend_locked(device_t dev PMF_FN_ARGS)
|
||||
{
|
||||
PMF_TRANSITION_PRINTF2(1, ("%s: self suspend\n", device_xname(dev)));
|
||||
device_pmf_self_suspend(dev, flags);
|
||||
PMF_TRANSITION_PRINTF2(1, ("%s: class suspend\n", device_xname(dev)));
|
||||
if (!device_pmf_class_suspend(dev PMF_FN_CALL))
|
||||
return false;
|
||||
|
@ -411,6 +419,12 @@ pmf_device_suspend_locked(device_t dev PMF_FN_ARGS)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
pmf_device_resume_self(device_t dev)
|
||||
{
|
||||
return pmf_device_resume(dev, PMF_F_SELF);
|
||||
}
|
||||
|
||||
bool
|
||||
pmf_device_resume(device_t dev PMF_FN_ARGS)
|
||||
{
|
||||
|
@ -443,6 +457,9 @@ pmf_device_resume_locked(device_t dev PMF_FN_ARGS)
|
|||
PMF_TRANSITION_PRINTF2(1, ("%s: class resume\n", device_xname(dev)));
|
||||
if (!device_pmf_class_resume(dev PMF_FN_CALL))
|
||||
return false;
|
||||
PMF_TRANSITION_PRINTF2(1, ("%s: self resume\n", device_xname(dev)));
|
||||
device_pmf_self_resume(dev, flags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -519,7 +536,7 @@ pmf_class_network_suspend(device_t dev PMF_FN_ARGS)
|
|||
int s;
|
||||
|
||||
s = splnet();
|
||||
(*ifp->if_stop)(ifp, 1);
|
||||
(*ifp->if_stop)(ifp, 0);
|
||||
splx(s);
|
||||
|
||||
return true;
|
||||
|
@ -531,6 +548,9 @@ pmf_class_network_resume(device_t dev PMF_FN_ARGS)
|
|||
struct ifnet *ifp = device_pmf_class_private(dev);
|
||||
int s;
|
||||
|
||||
if ((flags & PMF_F_SELF) != 0)
|
||||
return true;
|
||||
|
||||
s = splnet();
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: subr_autoconf.c,v 1.140 2008/03/11 02:42:41 matt Exp $ */
|
||||
/* $NetBSD: subr_autoconf.c,v 1.141 2008/03/12 18:02:22 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996, 2000 Christopher G. Demetriou
|
||||
|
@ -77,7 +77,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.140 2008/03/11 02:42:41 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.141 2008/03/12 18:02:22 dyoung Exp $");
|
||||
|
||||
#include "opt_multiprocessor.h"
|
||||
#include "opt_ddb.h"
|
||||
|
@ -1952,6 +1952,8 @@ device_pmf_driver_resume(device_t dev PMF_FN_ARGS)
|
|||
return true;
|
||||
if ((dev->dv_flags & DVF_BUS_SUSPENDED) != 0)
|
||||
return false;
|
||||
if ((flags & PMF_F_SELF) != 0 && !device_is_self_suspended(dev))
|
||||
return false;
|
||||
if (*dev->dv_driver_resume != NULL &&
|
||||
!(*dev->dv_driver_resume)(dev PMF_FN_CALL))
|
||||
return false;
|
||||
|
@ -2047,6 +2049,36 @@ device_pmf_driver_set_child_register(device_t dev,
|
|||
dev->dv_driver_child_register = child_register;
|
||||
}
|
||||
|
||||
void
|
||||
device_pmf_self_resume(device_t dev PMF_FN_ARGS)
|
||||
{
|
||||
pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
|
||||
if ((dev->dv_flags & DVF_SELF_SUSPENDED) != 0)
|
||||
dev->dv_flags &= ~DVF_SELF_SUSPENDED;
|
||||
pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
|
||||
}
|
||||
|
||||
bool
|
||||
device_is_self_suspended(device_t dev)
|
||||
{
|
||||
return (dev->dv_flags & DVF_SELF_SUSPENDED) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
device_pmf_self_suspend(device_t dev PMF_FN_ARGS)
|
||||
{
|
||||
bool self = (flags & PMF_F_SELF) != 0;
|
||||
|
||||
pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
|
||||
|
||||
if (!self)
|
||||
dev->dv_flags &= ~DVF_SELF_SUSPENDED;
|
||||
else if (device_is_active(dev))
|
||||
dev->dv_flags |= DVF_SELF_SUSPENDED;
|
||||
|
||||
pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
|
||||
}
|
||||
|
||||
static void
|
||||
pmflock_debug(device_t dev, const char *func, int line)
|
||||
{
|
||||
|
@ -2154,6 +2186,8 @@ device_pmf_bus_resume(device_t dev PMF_FN_ARGS)
|
|||
{
|
||||
if ((dev->dv_flags & DVF_BUS_SUSPENDED) == 0)
|
||||
return true;
|
||||
if ((flags & PMF_F_SELF) != 0 && !device_is_self_suspended(dev))
|
||||
return false;
|
||||
if (*dev->dv_bus_resume != NULL &&
|
||||
!(*dev->dv_bus_resume)(dev PMF_FN_CALL))
|
||||
return false;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: device.h,v 1.108 2008/03/11 02:42:41 matt Exp $ */
|
||||
/* $NetBSD: device.h,v 1.109 2008/03/12 18:02:22 dyoung Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996, 2000 Christopher G. Demetriou
|
||||
|
@ -166,6 +166,7 @@ struct device {
|
|||
#define DVF_CLASS_SUSPENDED 0x0008 /* device class suspend was called */
|
||||
#define DVF_DRIVER_SUSPENDED 0x0010 /* device driver suspend was called */
|
||||
#define DVF_BUS_SUSPENDED 0x0020 /* device bus suspend was called */
|
||||
#define DVF_SELF_SUSPENDED 0x0040 /* device suspended itself */
|
||||
|
||||
TAILQ_HEAD(devicelist, device);
|
||||
|
||||
|
@ -499,6 +500,11 @@ void *device_pmf_private(device_t);
|
|||
void device_pmf_unlock(device_t PMF_FN_PROTO);
|
||||
bool device_pmf_lock(device_t PMF_FN_PROTO);
|
||||
|
||||
bool device_is_self_suspended(device_t);
|
||||
void device_pmf_self_suspend(device_t PMF_FN_PROTO);
|
||||
void device_pmf_self_resume(device_t PMF_FN_PROTO);
|
||||
bool device_pmf_self_wait(device_t PMF_FN_PROTO);
|
||||
|
||||
void device_pmf_bus_register(device_t, void *,
|
||||
bool (*)(device_t PMF_FN_PROTO),
|
||||
bool (*)(device_t PMF_FN_PROTO),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pmf.h,v 1.9 2008/03/07 07:03:06 dyoung Exp $ */
|
||||
/* $NetBSD: pmf.h,v 1.10 2008/03/12 18:02:22 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
|
@ -54,14 +54,21 @@ typedef enum {
|
|||
PMFE_CHASSIS_LID_OPEN
|
||||
} pmf_generic_event_t;
|
||||
|
||||
#define PMF_FN_PROTO1 void /* pmf_flags_t */
|
||||
#define PMF_FN_ARGS1 void /* pmf_flags_t flags */
|
||||
enum pmf_flags {
|
||||
PMF_F_NONE = 0x0
|
||||
, PMF_F_SELF = 0x1
|
||||
};
|
||||
|
||||
#define PMF_FN_PROTO /* , pmf_flags_t */
|
||||
#define PMF_FN_ARGS /* , pmf_flags_t flags */
|
||||
#define PMF_FN_CALL /* , flags */
|
||||
typedef enum pmf_flags pmf_flags_t;
|
||||
|
||||
#define PMF_FLAGS_FMT "n/a" /* "%x" */
|
||||
#define PMF_FN_PROTO1 pmf_flags_t
|
||||
#define PMF_FN_ARGS1 pmf_flags_t flags
|
||||
|
||||
#define PMF_FN_PROTO , pmf_flags_t
|
||||
#define PMF_FN_ARGS , pmf_flags_t flags
|
||||
#define PMF_FN_CALL , flags
|
||||
|
||||
#define PMF_FLAGS_FMT "%x" /* "n/a" */
|
||||
|
||||
void pmf_init(void);
|
||||
|
||||
|
@ -91,6 +98,9 @@ void pmf_device_deregister(device_t);
|
|||
bool pmf_device_suspend(device_t PMF_FN_PROTO);
|
||||
bool pmf_device_resume(device_t PMF_FN_PROTO);
|
||||
|
||||
bool pmf_device_suspend_self(device_t);
|
||||
bool pmf_device_resume_self(device_t);
|
||||
|
||||
bool pmf_device_recursive_suspend(device_t PMF_FN_PROTO);
|
||||
bool pmf_device_recursive_resume(device_t PMF_FN_PROTO);
|
||||
bool pmf_device_resume_subtree(device_t PMF_FN_PROTO);
|
||||
|
|
Loading…
Reference in New Issue