diff options
author | Vincent Wang <Vincent.Wang@Sun.COM> | 2010-07-14 13:55:12 +0800 |
---|---|---|
committer | Vincent Wang <Vincent.Wang@Sun.COM> | 2010-07-14 13:55:12 +0800 |
commit | 6f6c7d2b51705d612c5f11ed385afd87c89c1a12 (patch) | |
tree | 282b3dcc2a42987264e3183d633138c0d7616683 | |
parent | 82722020b3918ce4d9594e3c6e0462bab345d102 (diff) | |
download | illumos-joyent-6f6c7d2b51705d612c5f11ed385afd87c89c1a12.tar.gz |
6867140 ultra 27 does not resume from either mouse or keyboard event
-rw-r--r-- | usr/src/uts/common/io/usb/clients/hid/hid.c | 2 | ||||
-rw-r--r-- | usr/src/uts/common/io/usb/hcd/ehci/ehci_hub.c | 10 | ||||
-rw-r--r-- | usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/io/usb/hcd/uhci/uhci.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/io/usb/usba/hubdi.c | 20 | ||||
-rw-r--r-- | usr/src/uts/common/io/usb/usba/usbai.c | 62 | ||||
-rw-r--r-- | usr/src/uts/common/os/sunpci.c | 128 | ||||
-rw-r--r-- | usr/src/uts/intel/io/acpica/acpica.c | 51 |
8 files changed, 149 insertions, 143 deletions
diff --git a/usr/src/uts/common/io/usb/clients/hid/hid.c b/usr/src/uts/common/io/usb/clients/hid/hid.c index 6cfc444f6e..be771b1ec3 100644 --- a/usr/src/uts/common/io/usb/clients/hid/hid.c +++ b/usr/src/uts/common/io/usb/clients/hid/hid.c @@ -68,7 +68,7 @@ uint_t hid_instance_debug = (uint_t)-1; /* tunables */ int hid_default_pipe_drain_timeout = HID_DEFAULT_PIPE_DRAIN_TIMEOUT; -int hid_pm_mouse = 0; +int hid_pm_mouse = 1; /* enable remote_wakeup for USB mouse/keyboard */ /* soft state structures */ #define HID_INITIAL_SOFT_SPACE 4 diff --git a/usr/src/uts/common/io/usb/hcd/ehci/ehci_hub.c b/usr/src/uts/common/io/usb/hcd/ehci/ehci_hub.c index b6ab2eeb96..d2c7f2a51f 100644 --- a/usr/src/uts/common/io/usb/hcd/ehci/ehci_hub.c +++ b/usr/src/uts/common/io/usb/hcd/ehci/ehci_hub.c @@ -19,11 +19,9 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ - /* * EHCI Host Controller Driver (EHCI) * @@ -1080,11 +1078,11 @@ ehci_handle_port_reset( ~EHCI_RH_PORT_CLEAR_MASK; /* - * Enable over-current, connect, and disconnect + * Disable over-current, connect, and disconnect * wakeup bits. */ - Set_OpReg(ehci_rh_port_status[port], (port_status | - EHCI_RH_PORT_OVER_CURENT_ENABLE | + Set_OpReg(ehci_rh_port_status[port], port_status & + ~(EHCI_RH_PORT_OVER_CURENT_ENABLE | EHCI_RH_PORT_DISCONNECT_ENABLE | EHCI_RH_PORT_CONNECT_ENABLE)); diff --git a/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c b/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c index 81ac127138..a7e7d6c494 100644 --- a/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c +++ b/usr/src/uts/common/io/usb/hcd/ehci/ehci_util.c @@ -23,7 +23,6 @@ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. */ - /* * EHCI Host Controller Driver (EHCI) * @@ -2062,16 +2061,11 @@ ehci_cpr_suspend(ehci_state_t *ehcip) Set_OpReg(ehci_command, Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN); - drv_usecwait(EHCI_RESET_TIMEWAIT); } /* Set host controller soft state to suspend */ ehcip->ehci_hc_soft_state = EHCI_CTLR_SUSPEND_STATE; - /* Reset the host controller. This can poweroff downstream ports */ - Set_OpReg(ehci_command, - Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET); - mutex_exit(&ehcip->ehci_int_mutex); return (DDI_SUCCESS); 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 5fe9bb533a..0dfcf754e3 100644 --- a/usr/src/uts/common/io/usb/hcd/uhci/uhci.c +++ b/usr/src/uts/common/io/usb/hcd/uhci/uhci.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -898,16 +897,6 @@ uhci_cpr_suspend(uhci_state_t *uhcip) /* Set host controller soft state to suspend */ uhcip->uhci_hc_soft_state = UHCI_CTLR_SUSPEND_STATE; - /* Reset the host controller. This can poweroff downstream ports */ - Set_OpReg16(USBCMD, USBCMD_REG_GBL_RESET); - - /* Wait 10ms for reset to complete */ - mutex_exit(&uhcip->uhci_int_mutex); - delay(drv_usectohz(UHCI_RESET_DELAY)); - mutex_enter(&uhcip->uhci_int_mutex); - - Set_OpReg16(USBCMD, 0); - mutex_exit(&uhcip->uhci_int_mutex); return (USB_SUCCESS); diff --git a/usr/src/uts/common/io/usb/usba/hubdi.c b/usr/src/uts/common/io/usb/usba/hubdi.c index ac044fddb5..23ab998f0e 100644 --- a/usr/src/uts/common/io/usb/usba/hubdi.c +++ b/usr/src/uts/common/io/usb/usba/hubdi.c @@ -992,6 +992,11 @@ hubd_suspend_port(hubd_t *hubd, usb_port_t port) retval = USB_SUCCESS; break; + } else { + USB_DPRINTF_L0(DPRINT_MASK_PM, + hubd->h_log_handle, + "hubdi: port%d failed to be suspended!", + port); } } @@ -7034,7 +7039,6 @@ hubd_cpr_suspend(hubd_t *hubd) } /* quiesce ourselves now */ - hubd->h_dev_state = USB_DEV_SUSPENDED; hubd_stop_polling(hubd); /* close all the open pipes of our children */ @@ -7043,14 +7047,18 @@ hubd_cpr_suspend(hubd_t *hubd) if (usba_dev != NULL) { mutex_exit(HUBD_MUTEX(hubd)); usba_persistent_pipe_close(usba_dev); + if (hubd_suspend_port(hubd, port)) { + USB_DPRINTF_L0( + DPRINT_MASK_HOTPLUG, + hubd->h_log_handle, + "suspending port %d failed", + port); + } mutex_enter(HUBD_MUTEX(hubd)); } + } - /* - * turn off power to all the ports so that we - * don't see any spurious activity - */ - (void) hubd_disable_all_port_power(hubd); + hubd->h_dev_state = USB_DEV_SUSPENDED; /* * if we are the root hub, we close our pipes diff --git a/usr/src/uts/common/io/usb/usba/usbai.c b/usr/src/uts/common/io/usb/usba/usbai.c index e6bf864680..1ff8507ff1 100644 --- a/usr/src/uts/common/io/usb/usba/usbai.c +++ b/usr/src/uts/common/io/usb/usba/usbai.c @@ -17,9 +17,9 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + */ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -77,11 +77,6 @@ static char *usba_debug_buf = NULL; /* The debug buf */ static char *usba_buf_sptr, *usba_buf_eptr; static hrtime_t usba_last_timestamp; /* last time stamp in trace */ -/* - * Set to 1 to enable PM. - */ -int usb_force_enable_pm = 0; - /* USBA framework initializations */ void usba_usbai_initialization() @@ -677,52 +672,11 @@ usb_req_lower_power(dev_info_t *dip, int comp, int level, int usb_is_pm_enabled(dev_info_t *dip) { - usba_device_t *usba_device = usba_get_usba_device(dip); - - switch (usb_force_enable_pm) { - case -1: - /* no PM at all */ - - return (USB_FAILURE); - case 1: - /* PM on all platforms, regardless of hcd */ - - return (USB_SUCCESS); - case 0: - default: - - break; - - } - - if (usba_device) { - dev_info_t *root_hub_dip; - usba_hcdi_t *hcdi; - int rval; - - root_hub_dip = usba_device->usb_root_hub_dip; - if (root_hub_dip == NULL) { - - return (USB_FAILURE); - } - - hcdi = usba_hcdi_get_hcdi(root_hub_dip); - if (hcdi && hcdi->hcdi_ops->usba_hcdi_pm_support) { - rval = hcdi->hcdi_ops-> - usba_hcdi_pm_support(root_hub_dip); - if (rval != USB_SUCCESS) { - USB_DPRINTF_L2(DPRINT_MASK_USBA, - usbai_log_handle, - "%s%d: no PM enabled for this device", - ddi_driver_name(dip), - ddi_get_instance(dip)); - } - - return (rval); - } - } - - return (USB_FAILURE); + /* + * At this point we should assume that all devices + * are capable of supporting PM + */ + return (USB_SUCCESS); } diff --git a/usr/src/uts/common/os/sunpci.c b/usr/src/uts/common/os/sunpci.c index 6dc4ae2040..c39e8aa698 100644 --- a/usr/src/uts/common/os/sunpci.c +++ b/usr/src/uts/common/os/sunpci.c @@ -18,10 +18,8 @@ * * CDDL HEADER END */ - /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/types.h> @@ -32,6 +30,8 @@ #include <sys/pci_impl.h> #include <sys/epm.h> +int pci_enable_wakeup = 1; + int pci_config_setup(dev_info_t *dip, ddi_acc_handle_t *handle) { @@ -1041,9 +1041,7 @@ pci_post_suspend(dev_info_t *dip) } else { ret = DDI_SUCCESS; } - kmem_free(p, sizeof (*p)); - pci_config_teardown(&hdl); - return (DDI_SUCCESS); + goto done; } /* * Upon suspend, set the power level to the lowest that can @@ -1052,10 +1050,10 @@ pci_post_suspend(dev_info_t *dip) * XXX device has had wakeup disabled */ pmcap = pci_config_get16(hdl, p->ppc_cap_offset + PCI_PMCAP); - if ((pmcap & PCI_PMCAP_D3COLD_PME) != 0) + if ((pmcap & (PCI_PMCAP_D3COLD_PME | PCI_PMCAP_D3HOT_PME)) != 0) p->ppc_suspend_level = (PCI_PMCSR_PME_EN | PCI_PMCSR_D3HOT); - else if ((pmcap & (PCI_PMCAP_D3HOT_PME | PCI_PMCAP_D2_PME)) != + else if ((pmcap & PCI_PMCAP_D2_PME) != 0) p->ppc_suspend_level = PCI_PMCSR_PME_EN | PCI_PMCSR_D2; else if ((pmcap & PCI_PMCAP_D1_PME) != 0) @@ -1072,43 +1070,13 @@ pci_post_suspend(dev_info_t *dip) } /* If we set this in kmem_zalloc'd memory, we already returned above */ if ((p->ppc_flags & PPCF_NOPMCAP) != 0) { - ddi_prop_free(p); - pci_config_teardown(&hdl); - return (DDI_SUCCESS); + goto done; } - - /* - * Turn off (Bus) Master Enable, since acpica will be turning off - * bus master aribitration - */ - pcicmd = pci_config_get16(hdl, PCI_CONF_COMM); - pcicmd &= ~PCI_COMM_ME; - pci_config_put16(hdl, PCI_CONF_COMM, pcicmd); - - /* - * set pm csr - */ pmcsr = pci_config_get16(hdl, p->ppc_cap_offset + PCI_PMCSR); p->ppc_pmcsr = pmcsr; pmcsr &= (PCI_PMCSR_STATE_MASK); pmcsr |= (PCI_PMCSR_PME_STAT | p->ppc_suspend_level); - pci_config_put16(hdl, p->ppc_cap_offset + PCI_PMCSR, pmcsr); - -#if defined(__x86) - /* - * Arrange for platform wakeup enabling - */ - if ((p->ppc_suspend_level & PCI_PMCSR_PME_EN) != 0) { - int retval; - - retval = acpi_ddi_setwake(dip, 3); /* XXX 3 for now */ - if (retval) { - PMD(PMD_SX, ("pci_post_suspend, setwake %s@%s rets " - "%x\n", PM_NAME(dip), PM_ADDR(dip), retval)); - } - } -#endif /* * Push out saved register values @@ -1116,12 +1084,7 @@ pci_post_suspend(dev_info_t *dip) ret = ndi_prop_update_byte_array(DDI_DEV_T_NONE, dip, SAVED_PM_CONTEXT, (uchar_t *)p, sizeof (pci_pm_context_t)); if (ret == DDI_PROP_SUCCESS) { - if (fromprop) - ddi_prop_free(p); - else - kmem_free(p, sizeof (*p)); - pci_config_teardown(&hdl); - return (DDI_SUCCESS); + goto done; } /* Failed; put things back the way we found them */ (void) pci_restore_config_regs(dip); @@ -1132,6 +1095,67 @@ pci_post_suspend(dev_info_t *dip) (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, SAVED_PM_CONTEXT); pci_config_teardown(&hdl); return (DDI_FAILURE); + +done: + + /* + * According to 8.2.2 of "PCI Bus Power Management Interface + * Specification Revision 1.2": + * "When placing a function into D3, the operating system software is + * required to disable I/O and memory space as well as bus mastering via + * the PCI Command register." + */ + + pcicmd = pci_config_get16(hdl, PCI_CONF_COMM); + pcicmd &= ~(PCI_COMM_ME|PCI_COMM_MAE|PCI_COMM_IO); + pci_config_put16(hdl, PCI_CONF_COMM, pcicmd); + + +#if defined(__x86) + if (pci_enable_wakeup) { + + ret = acpi_ddi_setwake(dip, 3); + + if (ret) { + PMD(PMD_SX, ("pci_post_suspend, setwake %s@%s rets " + "%x\n", PM_NAME(dip), PM_ADDR(dip), ret)); + } + } +#endif + + if (p) { + + /* + * Some BIOS (e.g. Toshiba M10) expects pci-ide to be in D0 + * state when we set SLP_EN, otherwise it takes 5 minutes for + * the BIOS to put the system into S3. + */ + if (strcmp(ddi_node_name(dip), "pci-ide") == 0) { + pmcsr = 0; + } + + /* + * pmcsr is the last write-operation to the device's PCI + * config space, because we found that there are + * some faulty devices whose PCI config space may not + * respond correctly once in D3 state. + */ + if ((p->ppc_flags & PPCF_NOPMCAP) == 0 && pci_enable_wakeup) { + pci_config_put16(hdl, p->ppc_cap_offset + PCI_PMCSR, + PCI_PMCSR_PME_STAT); + pci_config_put16(hdl, p->ppc_cap_offset + PCI_PMCSR, + pmcsr); + } + + if (fromprop) + ddi_prop_free(p); + else + kmem_free(p, sizeof (*p)); + } + + pci_config_teardown(&hdl); + + return (DDI_SUCCESS); } /* @@ -1150,7 +1174,7 @@ pci_pre_resume(dev_info_t *dip) uint_t length; clock_t drv_usectohz(clock_t microsecs); #if defined(__x86) - uint16_t suspend_level; + int retval; #endif PMD(PMD_SX, ("pci_pre_resume %s:%d\n", ddi_driver_name(dip), @@ -1163,19 +1187,14 @@ pci_pre_resume(dev_info_t *dip) flags = p->ppc_flags; pmcap = p->ppc_cap_offset; pmcsr = p->ppc_pmcsr; -#if defined(__x86) - suspend_level = p->ppc_suspend_level; -#endif ddi_prop_free(p); - if ((flags & PPCF_NOPMCAP) != 0) - goto done; + #if defined(__x86) /* * Turn platform wake enable back off */ - if ((suspend_level & PCI_PMCSR_PME_EN) != 0) { - int retval; + if (pci_enable_wakeup) { retval = acpi_ddi_setwake(dip, 0); /* 0 for now */ if (retval) { PMD(PMD_SX, ("pci_pre_resume, setwake %s@%s rets " @@ -1183,6 +1202,9 @@ pci_pre_resume(dev_info_t *dip) } } #endif + if ((flags & PPCF_NOPMCAP) != 0) + goto done; + if (pci_config_setup(dip, &hdl) != DDI_SUCCESS) { return (DDI_FAILURE); } diff --git a/usr/src/uts/intel/io/acpica/acpica.c b/usr/src/uts/intel/io/acpica/acpica.c index 30a8d79be1..6e367d9b97 100644 --- a/usr/src/uts/intel/io/acpica/acpica.c +++ b/usr/src/uts/intel/io/acpica/acpica.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright (c) 2009, Intel Corporation. @@ -550,6 +549,8 @@ acpica_ddi_setwake(dev_info_t *dip, int level) ACPI_HANDLE devobj, gpeobj; ACPI_OBJECT *prw, *gpe; ACPI_BUFFER prw_buf; + ACPI_OBJECT_LIST arglist; + ACPI_OBJECT args[3]; int gpebit, pwr_res_count, prw_level, rv; /* @@ -578,6 +579,48 @@ acpica_ddi_setwake(dev_info_t *dip, int level) } /* + * ACPI3.0 7.2.1: only use the _PSW method if OSPM does not support + * _DSW or if the _DSW method is not present. + * + * _DSW arguments: + * args[0] - Enable/Disable + * args[1] - Target system state + * args[2] - Target device state + */ + + arglist.Count = 3; + arglist.Pointer = args; + args[0].Type = ACPI_TYPE_INTEGER; + args[0].Integer.Value = level ? 1 : 0; + args[1].Type = ACPI_TYPE_INTEGER; + args[1].Integer.Value = level; + args[2].Type = ACPI_TYPE_INTEGER; + args[2].Integer.Value = level; + if (ACPI_FAILURE(status = AcpiEvaluateObject(devobj, "_DSW", + &arglist, NULL))) { + + if (status == AE_NOT_FOUND) { + arglist.Count = 1; + args[0].Type = ACPI_TYPE_INTEGER; + args[0].Integer.Value = level ? 1 : 0; + + if (ACPI_FAILURE(status = AcpiEvaluateObject(devobj, + "_PSW", &arglist, NULL))) { + + if (status != AE_NOT_FOUND) { + cmn_err(CE_NOTE, + "!_PSW failure %d for device %s", + status, ddi_driver_name(dip)); + } + } + + } else { + cmn_err(CE_NOTE, "!_DSW failure %d for device %s", + status, ddi_driver_name(dip)); + } + } + + /* * Attempt to evaluate _PRW object. * If no valid object is found, return quietly, since not all * devices have _PRW objects. @@ -587,8 +630,6 @@ acpica_ddi_setwake(dev_info_t *dip, int level) if (ACPI_FAILURE(status) || prw_buf.Length == 0 || prw == NULL || prw->Type != ACPI_TYPE_PACKAGE || prw->Package.Count < 2 || prw->Package.Elements[1].Type != ACPI_TYPE_INTEGER) { - cmn_err(CE_NOTE, "acpica_ddi_setwake: could not " - " evaluate _PRW"); goto done; } @@ -620,7 +661,7 @@ acpica_ddi_setwake(dev_info_t *dip, int level) if (level == 0) { if (ACPI_FAILURE(AcpiDisableGpe(gpeobj, gpebit, ACPI_NOT_ISR))) goto done; - } else if (prw_level <= level) { + } else if (prw_level >= level) { if (ACPI_SUCCESS( AcpiSetGpeType(gpeobj, gpebit, ACPI_GPE_TYPE_WAKE))) if (ACPI_FAILURE( |