diff options
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r-- | usr/src/uts/common/io/ipw/ipw2100.c | 137 | ||||
-rw-r--r-- | usr/src/uts/common/io/ipw/ipw2100_impl.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/io/pci-ide/pci-ide.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/io/usb/hcd/uhci/uhci.c | 39 | ||||
-rw-r--r-- | usr/src/uts/common/sys/usb/hcd/uhci/uhci.h | 4 |
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 |