summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/io/ipw/ipw2100.c137
-rw-r--r--usr/src/uts/common/io/ipw/ipw2100_impl.h3
-rw-r--r--usr/src/uts/common/io/pci-ide/pci-ide.c9
-rw-r--r--usr/src/uts/common/io/usb/hcd/uhci/uhci.c39
-rw-r--r--usr/src/uts/common/sys/usb/hcd/uhci/uhci.h4
5 files changed, 174 insertions, 18 deletions
diff --git a/usr/src/uts/common/io/ipw/ipw2100.c b/usr/src/uts/common/io/ipw/ipw2100.c
index a5feab7846..e882cae4b1 100644
--- a/usr/src/uts/common/io/ipw/ipw2100.c
+++ b/usr/src/uts/common/io/ipw/ipw2100.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -172,6 +172,12 @@ static int ipw_wificfg_disassoc(struct ipw2100_softc *sc,
wldp_t *outfp);
/*
+ * Suspend / Resume operations
+ */
+static int ipw2100_cpr_suspend(struct ipw2100_softc *sc);
+static int ipw2100_cpr_resume(struct ipw2100_softc *sc);
+
+/*
* Mac Call Back entries
*/
mac_callbacks_t ipw2100_m_callbacks = {
@@ -254,7 +260,17 @@ ipw2100_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
wifi_data_t wd = { 0 };
mac_register_t *macp;
- if (cmd != DDI_ATTACH) {
+ switch (cmd) {
+ case DDI_ATTACH:
+ break;
+ case DDI_RESUME:
+ sc = ddi_get_soft_state(ipw2100_ssp, ddi_get_instance(dip));
+ if (sc == NULL) {
+ err = DDI_FAILURE;
+ goto fail1;
+ }
+ return (ipw2100_cpr_resume(sc));
+ default:
err = DDI_FAILURE;
goto fail1;
}
@@ -508,8 +524,14 @@ ipw2100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
ASSERT(sc != NULL);
- if (cmd != DDI_DETACH)
+ switch (cmd) {
+ case DDI_DETACH:
+ break;
+ case DDI_SUSPEND:
+ return (ipw2100_cpr_suspend(sc));
+ default:
return (DDI_FAILURE);
+ }
/*
* Destroy the mf_thread
@@ -523,7 +545,7 @@ ipw2100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
mutex_exit(&sc->sc_mflock);
/*
- * Unregiste from the MAC layer subsystem
+ * Unregister from the MAC layer subsystem
*/
err = mac_unregister(sc->sc_ic.ic_mach);
if (err != DDI_SUCCESS)
@@ -558,6 +580,103 @@ ipw2100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
return (DDI_SUCCESS);
}
+int
+ipw2100_cpr_suspend(struct ipw2100_softc *sc)
+{
+ IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
+ "ipw2100_cpr_suspend(): enter\n"));
+
+ /*
+ * Destroy the mf_thread
+ */
+ mutex_enter(&sc->sc_mflock);
+ sc->sc_mfthread_switch = 0;
+ while (sc->sc_mf_thread != NULL) {
+ if (cv_wait_sig(&sc->sc_mfthread_cv, &sc->sc_mflock) == 0)
+ break;
+ }
+ mutex_exit(&sc->sc_mflock);
+
+ /*
+ * stop the hardware; this mask all interrupts
+ */
+ ipw2100_stop(sc);
+ sc->sc_flags &= ~IPW2100_FLAG_RUNNING;
+ sc->sc_suspended = 1;
+
+ (void) ipw2100_free_firmware(sc);
+ ipw2100_ring_free(sc);
+
+ return (DDI_SUCCESS);
+}
+
+int
+ipw2100_cpr_resume(struct ipw2100_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ dev_info_t *dip = sc->sc_dip;
+ int err;
+
+ IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
+ "ipw2100_cpr_resume(): enter\n"));
+
+ /*
+ * Reset the chip
+ */
+ err = ipw2100_chip_reset(sc);
+ if (err != DDI_SUCCESS) {
+ IPW2100_WARN((dip, CE_WARN,
+ "ipw2100_attach(): reset failed\n"));
+ return (DDI_FAILURE);
+ }
+
+ /*
+ * Get the hw conf, including MAC address, then init all rings.
+ */
+ /* ipw2100_hwconf_get(sc); */
+ err = ipw2100_ring_init(sc);
+ if (err != DDI_SUCCESS) {
+ IPW2100_WARN((dip, CE_WARN,
+ "ipw2100_attach(): "
+ "unable to allocate and initialize rings\n"));
+ return (DDI_FAILURE);
+ }
+
+ /*
+ * Cache firmware, always return true
+ */
+ (void) ipw2100_cache_firmware(sc);
+
+ /*
+ * Notify link is down now
+ */
+ mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
+
+ /*
+ * create the mf thread to handle the link status,
+ * recovery fatal error, etc.
+ */
+ sc->sc_mfthread_switch = 1;
+ if (sc->sc_mf_thread == NULL)
+ sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
+ ipw2100_thread, sc, 0, &p0, TS_RUN, minclsyspri);
+
+ /*
+ * enable all interrupts
+ */
+ sc->sc_suspended = 0;
+ ipw2100_csr_put32(sc, IPW2100_CSR_INTR_MASK, IPW2100_INTR_MASK_ALL);
+
+ /*
+ * initialize ipw2100 hardware
+ */
+ (void) ipw2100_init(sc);
+
+ sc->sc_flags |= IPW2100_FLAG_RUNNING;
+
+ return (DDI_SUCCESS);
+}
+
/*
* quiesce(9E) entry point.
* This function is called when the system is single-threaded at high
@@ -977,6 +1096,9 @@ ipw2100_init(struct ipw2100_softc *sc)
{
int err;
+ IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
+ "ipw2100_init(): enter\n"));
+
/*
* no firmware is available, return fail directly
*/
@@ -998,6 +1120,8 @@ ipw2100_init(struct ipw2100_softc *sc)
/*
* load microcode
*/
+ IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
+ "ipw2100_init(): loading microcode\n"));
err = ipw2100_load_uc(sc);
if (err != DDI_SUCCESS) {
IPW2100_WARN((sc->sc_dip, CE_WARN,
@@ -1012,6 +1136,8 @@ ipw2100_init(struct ipw2100_softc *sc)
/*
* load firmware
*/
+ IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
+ "ipw2100_init(): loading firmware\n"));
err = ipw2100_load_fw(sc);
if (err != DDI_SUCCESS) {
IPW2100_WARN((sc->sc_dip, CE_WARN,
@@ -2537,6 +2663,9 @@ ipw2100_intr(caddr_t arg)
struct ipw2100_bd *rxbd;
#endif
+ if (sc->sc_suspended)
+ return (DDI_INTR_UNCLAIMED);
+
ireg = ipw2100_csr_get32(sc, IPW2100_CSR_INTR);
if (!(ireg & IPW2100_INTR_MASK_ALL))
diff --git a/usr/src/uts/common/io/ipw/ipw2100_impl.h b/usr/src/uts/common/io/ipw/ipw2100_impl.h
index f0de7961d5..7207468323 100644
--- a/usr/src/uts/common/io/ipw/ipw2100_impl.h
+++ b/usr/src/uts/common/io/ipw/ipw2100_impl.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -99,6 +99,7 @@ struct ipw2100_softc {
int (*sc_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
int sc_authmode;
+ int sc_suspended;
/* CSR */
ddi_acc_handle_t sc_ioh;
caddr_t sc_regs;
diff --git a/usr/src/uts/common/io/pci-ide/pci-ide.c b/usr/src/uts/common/io/pci-ide/pci-ide.c
index 7156aaa091..87f228c170 100644
--- a/usr/src/uts/common/io/pci-ide/pci-ide.c
+++ b/usr/src/uts/common/io/pci-ide/pci-ide.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -381,6 +381,13 @@ pciide_ddi_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
return (rc);
+ case DDI_CTLOPS_ATTACH:
+ case DDI_CTLOPS_DETACH:
+ /*
+ * Don't pass child ide ATTACH/DETACH to parent
+ */
+ return (DDI_SUCCESS);
+
default:
return (ddi_ctlops(dip, rdip, ctlop, arg, result));
}
diff --git a/usr/src/uts/common/io/usb/hcd/uhci/uhci.c b/usr/src/uts/common/io/usb/hcd/uhci/uhci.c
index 4da8376838..0dfca00755 100644
--- a/usr/src/uts/common/io/usb/hcd/uhci/uhci.c
+++ b/usr/src/uts/common/io/usb/hcd/uhci/uhci.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -850,6 +850,9 @@ uhci_cleanup(uhci_state_t *uhcip)
static int
uhci_cpr_suspend(uhci_state_t *uhcip)
{
+ uint16_t cmd_reg;
+ int i;
+
USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
"uhci_cpr_suspend:");
@@ -861,20 +864,36 @@ uhci_cpr_suspend(uhci_state_t *uhcip)
mutex_enter(&uhcip->uhci_int_mutex);
- /* Disable interrupts */
- Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
+ /* Stop the Host Controller */
+ cmd_reg = Get_OpReg16(USBCMD);
+ cmd_reg &= ~USBCMD_REG_HC_RUN;
+ Set_OpReg16(USBCMD, cmd_reg);
- mutex_exit(&uhcip->uhci_int_mutex);
+ /*
+ * Wait for the duration of an SOF period until the host controller
+ * reaches the stopped state, indicated by the HCHalted bit in the
+ * USB status register.
+ */
+ for (i = 0; i <= UHCI_TIMEWAIT / 1000; i++) {
+ if (Get_OpReg16(USBSTS) & USBSTS_REG_HC_HALTED)
+ break;
+ drv_usecwait(1000);
+ }
- /* Wait for SOF time to handle the scheduled interrupt */
- delay(drv_usectohz(UHCI_TIMEWAIT));
+ USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
+ "uhci_cpr_suspend: waited %d milliseconds for hc to halt", i);
- mutex_enter(&uhcip->uhci_int_mutex);
- /* Stop the Host Controller */
- Set_OpReg16(USBCMD, 0);
+ /* Disable interrupts */
+ Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
+
+ /* Clear any scheduled pending interrupts */
+ Set_OpReg16(USBSTS, USBSTS_REG_HC_HALTED |
+ USBSTS_REG_HC_PROCESS_ERR | USBSTS_REG_HOST_SYS_ERR |
+ USBSTS_REG_RESUME_DETECT | USBSTS_REG_USB_ERR_INTR |
+ USBSTS_REG_USB_INTR);
/* Set Global Suspend bit */
- Set_OpReg16(USBCMD, USBCMD_REG_ENER_GBL_SUSPEND);
+ Set_OpReg16(USBCMD, USBCMD_REG_ENTER_GBL_SUSPEND);
/* Set host controller soft state to suspend */
uhcip->uhci_hc_soft_state = UHCI_CTLR_SUSPEND_STATE;
diff --git a/usr/src/uts/common/sys/usb/hcd/uhci/uhci.h b/usr/src/uts/common/sys/usb/hcd/uhci/uhci.h
index 0b547ff4e9..a275e13bfe 100644
--- a/usr/src/uts/common/sys/usb/hcd/uhci/uhci.h
+++ b/usr/src/uts/common/sys/usb/hcd/uhci/uhci.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -68,7 +68,7 @@ typedef volatile struct hcr_regs {
#define USBCMD_REG_CONFIG_FLAG 0x0040
#define USBCMD_REG_SW_DEBUG 0x0020
#define USBCMD_REG_FGBL_RESUME 0x0010
-#define USBCMD_REG_ENER_GBL_SUSPEND 0x0008
+#define USBCMD_REG_ENTER_GBL_SUSPEND 0x0008
#define USBCMD_REG_GBL_RESET 0x0004
#define USBCMD_REG_HC_RESET 0x0002
#define USBCMD_REG_HC_RUN 0x0001