summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authordyoung <dyoung@NetBSD.org>2008-03-12 18:02:21 +0000
committerdyoung <dyoung@NetBSD.org>2008-03-12 18:02:21 +0000
commit3df2b2feb5ec81dbf34ffb230078ff45e416489a (patch)
tree95e014f7e88d3c18f858be14e80133e9435df658 /sys/dev
parent15bb494e456ec9a47b21cc5a3e96f57807f590f0 (diff)
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.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpi/acpi.c10
-rw-r--r--sys/dev/apm/apm.c10
-rw-r--r--sys/dev/audio.c22
-rw-r--r--sys/dev/cardbus/cardbus.c9
-rw-r--r--sys/dev/cardbus/if_ath_cardbus.c195
-rw-r--r--sys/dev/cardbus/if_rtw_cardbus.c122
-rw-r--r--sys/dev/ic/ath.c257
-rw-r--r--sys/dev/ic/athvar.h13
-rw-r--r--sys/dev/ic/rtw.c162
-rw-r--r--sys/dev/ic/rtwvar.h20
-rw-r--r--sys/dev/pci/if_ath_pci.c70
-rw-r--r--sys/dev/pci/if_rtw_pci.c95
-rw-r--r--sys/dev/pci/if_sip.c36
13 files changed, 454 insertions, 567 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index dff318cf764..d8903626858 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -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;
diff --git a/sys/dev/apm/apm.c b/sys/dev/apm/apm.c
index be6ee1de858..f3981ba2fa3 100644
--- a/sys/dev/apm/apm.c
+++ b/sys/dev/apm/apm.c
@@ -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);
diff --git a/sys/dev/audio.c b/sys/dev/audio.c
index 62f7b525b1d..90214df0d2b 100644
--- a/sys/dev/audio.c
+++ b/sys/dev/audio.c
@@ -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;
diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c
index f795e0036f9..1582d919618 100644
--- a/sys/dev/cardbus/cardbus.c
+++ b/sys/dev/cardbus/cardbus.c
@@ -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;
}
diff --git a/sys/dev/cardbus/if_ath_cardbus.c b/sys/dev/cardbus/if_ath_cardbus.c
index 75e4a3e5e91..819a2ec468f 100644
--- a/sys/dev/cardbus/if_ath_cardbus.c
+++ b/sys/dev/cardbus/if_ath_cardbus.c
@@ -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_suspend(device_t self PMF_FN_ARGS)
+{
+ 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 dv)
+ath_cardbus_resume(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);
+ 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
- ath_resume(&csc->sc_ath);
- return true;
+ 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);
}
diff --git a/sys/dev/cardbus/if_rtw_cardbus.c b/sys/dev/cardbus/if_rtw_cardbus.c
index 5d9e407e92f..1f82719a2b5 100644
--- a/sys/dev/cardbus/if_rtw_cardbus.c
+++ b/sys/dev/cardbus/if_rtw_cardbus.c
@@ -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, &regs->r_bt, &regs->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,
+ &regs->r_bt, &regs->r_bh, &adr, &regs->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, &regs->r_bt, &regs->r_bh, &adr,
- &csc->sc_mapsize) == 0) {
+ } else if (Cardbus_mapreg_map(ct, RTW_PCI_IOBA, CARDBUS_MAPREG_TYPE_IO,
+ 0, &regs->r_bt, &regs->r_bh, &adr, &regs->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,34 +351,21 @@ 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.
*/
csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
@@ -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);
}
diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c
index bc91b6a5e0e..8097a7fab57 100644
--- a/sys/dev/ic/ath.c
+++ b/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);
}
@@ -1839,49 +1821,16 @@ ath_calcrxfilter(struct ath_softc *sc, enum ieee80211_state state)
}
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);
diff --git a/sys/dev/ic/athvar.h b/sys/dev/ic/athvar.h
index 84f47ecf859..13b2a1f0353 100644
--- a/sys/dev/ic/athvar.h
+++ b/sys/dev/ic/athvar.h
@@ -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 *);
diff --git a/sys/dev/ic/rtw.c b/sys/dev/ic/rtw.c
index 42d8dcfcbe0..ef9f3f17a67 100644
--- a/sys/dev/ic/rtw.c
+++ b/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;
-
- if ((rc = rtw_enable(sc)) != 0)
- goto out;
+ int rc;
- /* 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;
-}
diff --git a/sys/dev/ic/rtwvar.h b/sys/dev/ic/rtwvar.h
index c5e6a217faf..f83971f2d26 100644
--- a/sys/dev/ic/rtwvar.h
+++ b/sys/dev/ic/rtwvar.h
@@ -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);
diff --git a/sys/dev/pci/if_ath_pci.c b/sys/dev/pci/if_ath_pci.c
index ed793f19a91..9750be549b7 100644
--- a/sys/dev/pci/if_ath_pci.c
+++ b/sys/dev/pci/if_ath_pci.c
@@ -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);
diff --git a/sys/dev/pci/if_rtw_pci.c b/sys/dev/pci/if_rtw_pci.c
index edb540c4aab..04bf431831f 100644
--- a/sys/dev/pci/if_rtw_pci.c
+++ b/sys/dev/pci/if_rtw_pci.c
@@ -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;
@@ -193,12 +196,6 @@ rtw_pci_attach(device_t parent, device_t self, void *aux)
}
/*
- * 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.
*/
sc->sc_rev = PCI_REVISION(pa->pa_class);
@@ -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");
+ &regs->r_bt, &regs->r_bh, NULL, &regs->r_sz) == 0)
+ ;
+ else if (pci_mapreg_map(pa, RTW_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0,
+ &regs->r_bt, &regs->r_bh, NULL, &regs->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;
}
diff --git a/sys/dev/pci/if_sip.c b/sys/dev/pci/if_sip.c
index 853b23bbee3..21f5f6b31e0 100644
--- a/sys/dev/pci/if_sip.c
+++ b/sys/dev/pci/if_sip.c
@@ -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 "