Date: Fri, 17 Jan 2020 03:23:17 +0000 From: <Shichun.Ma@dell.com> To: <hps@selasky.org>, <freebsd-usb@freebsd.org> Cc: <Jason_YH_Yang@wistron.com> Subject: Re: USB keyboard/mouse wake up from S3 Message-ID: <1579231397567.62223@Dell.com> In-Reply-To: <685f991f-6cb6-3f27-65d8-38181e4cfa8e@selasky.org> References: <1578625588784.46788@Dell.com> <47257477-bace-a9c5-69f5-7a0eb7af3947@selasky.org> <1578648297338.92657@Dell.com>, <685f991f-6cb6-3f27-65d8-38181e4cfa8e@selasky.org>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --]
HPS,
Here is my patch to enable USB wakeup under XHCI, I tested USB mouse/keyboard can wake up system from S3.
Thanks & Regards,
Shichun Ma
Software Engineer
Dell | Cloud Client Computing
office +86 10 82862579, Mobile +86 13241851528
shichun_ma@dell.com
________________________________________
From: Hans Petter Selasky <hps@selasky.org>
Sent: Friday, January 10, 2020 5:41 PM
To: Ma, Horse; freebsd-usb@freebsd.org
Subject: Re: USB keyboard/mouse wake up from S3
[EXTERNAL EMAIL]
On 2020-01-10 10:24, Shichun.Ma@dell.com wrote:
> The USB wake up can still even device is detached.
> Before system enter to S3 and when detach the USB device, we can enable device's remote wake up feature.
> it can still send out the resume signal to host if it connected from hardware.
>
I think we don't do that currently. Would need a patch in the USB core.
Only during normal USB suspend / resume, not host suspend / resume.
--HPS
[-- Attachment #2 --]
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 508ad45f6d9..a448787214a 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -3255,12 +3255,31 @@ acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate)
if (bootverbose)
device_printf(dev, "wake_prep disabled wake for %s (S%d)\n",
acpi_name(handle), sstate);
- } else if (dev && (acpi_get_flags(dev) & ACPI_FLAG_WAKE_ENABLED) != 0) {
+ } else if (dev && (((acpi_get_flags(dev) & ACPI_FLAG_WAKE_ENABLED) != 0) ||
+ (strstr(acpi_name(handle), "XHC")))) { //hard code XHCI as wake up signal, any susggestion on the setting?
acpi_pwr_wake_enable(handle, 1);
acpi_SetInteger(handle, "_PSW", 1);
- if (bootverbose)
+ if (1 || bootverbose)
device_printf(dev, "wake_prep enabled for %s (S%d)\n",
acpi_name(handle), sstate);
+ ACPI_OBJECT argl[3];
+ ACPI_OBJECT_LIST args = {3, argl};
+
+ acpi_pwr_wake_enable(handle, 1);
+
+ argl[0].Type = ACPI_TYPE_INTEGER;
+ argl[0].Integer.Value = 1;
+
+ argl[1].Type = ACPI_TYPE_INTEGER;
+ argl[1].Integer.Value = sstate;
+
+ argl[2].Type = ACPI_TYPE_INTEGER;
+ argl[2].Integer.Value = 3;
+ if (AcpiEvaluateObject(handle, "_DSW", &args, NULL))
+ device_printf(dev, "ACPI: AcpiEvaluateObject _DSW Failed\n");
+ acpi_SetInteger(handle, "_PSW", 1);
+ //AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit);
+ AcpiSetGpeWakeMask(prw.gpe_handle, prw.gpe_bit, ACPI_GPE_ENABLE);
}
return (0);
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 3887e0423b6..3694296dc15 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -452,6 +452,30 @@ usb_bus_detach(struct usb_proc_msg *pm)
bus->bdev = NULL;
}
+static void
+usb_suspend_all(struct usb_bus *bus)
+{
+ int max_depth = 0, i, j;
+ struct usb_device *udev;
+
+ for (i = 0; i < bus->devices_max; i++) {
+ udev = bus->devices[i];
+ if (!udev)
+ continue;
+ if (max_depth < udev->depth)
+ max_depth = udev->depth;
+ }
+
+ for (i = max_depth; i > 0; i--) {
+ for (j = 0; j < bus->devices_max; j++) {
+ udev = bus->devices[j];
+ if (udev && (udev->depth == i) &&
+ usb_peer_can_wakeup(udev))
+ usb_suspend_dev(udev);
+ }
+ }
+}
+
/*------------------------------------------------------------------------*
* usb_bus_suspend
*
@@ -483,7 +507,7 @@ usb_bus_suspend(struct usb_proc_msg *pm)
* subsequently. At resume all USB devices will be
* re-connected again.
*/
-
+ usb_suspend_all(bus);
bus_generic_shutdown(bus->bdev);
do_unlock = usbd_enum_lock(udev);
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index 8d60ba212de..659babb7af1 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -79,6 +79,7 @@
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_pci.h>
#include <dev/usb/usb_bus.h>
#endif /* USB_GLOBAL_INCLUDE_FILE */
@@ -695,11 +696,13 @@ xhci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state)
{
struct xhci_softc *sc = XHCI_BUS2SC(bus);
+ //xhci_dump_regs(sc);
+
switch (state) {
case USB_HW_POWER_SUSPEND:
DPRINTF("Stopping the XHCI\n");
xhci_halt_controller(sc);
- xhci_reset_controller(sc);
+ //xhci_reset_controller(sc);
break;
case USB_HW_POWER_SHUTDOWN:
DPRINTF("Stopping the XHCI\n");
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index 186d383e35f..53310548e72 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -2927,3 +2927,47 @@ usbd_start_set_config(struct usb_device *udev, uint8_t index)
}
return (USB_ERR_PENDING_REQUESTS);
}
+
+int
+usb_suspend_dev(struct usb_device *udev)
+{
+ int err;
+ struct usb_port_status ps;
+
+ err = usbd_req_set_device_feature(udev,
+ NULL, UF_DEVICE_REMOTE_WAKEUP);
+ if (err) {
+ DPRINTFN(0, "Setting remote wakeup failed, err %d\n", err);
+ return err;
+ }
+ usb_pause_mtx(NULL, USB_MS_TO_TICKS(10));
+ if (usb_device_20_compatible(udev)) {
+ err = usbd_req_set_port_feature(udev->parent_hub,
+ NULL, udev->port_no, UHF_PORT_SUSPEND);
+ if (err) {
+ DPRINTFN(0, "Suspending port failed\n");
+ return err;
+ }
+ } else {
+ err = usbd_req_set_port_link_state(udev->parent_hub,
+ NULL, udev->port_no, UPS_PORT_LS_U3);
+ if (err) {
+ DPRINTFN(0, "Suspending port failed\n");
+ return err;
+ }
+ }
+
+ err = usbd_req_get_port_status(udev->parent_hub, NULL, &ps,
+ udev->port_no);
+ if (UGETW(ps.wPortChange)) {
+ err = usbd_req_clear_port_feature(udev->parent_hub, NULL,
+ udev->port_no, UHF_C_PORT_CONNECTION);
+ }
+ err = usbd_req_get_port_status(udev->parent_hub, NULL, &ps,
+ udev->port_no);
+ if (!err)
+ DPRINTFN(0, "port %d, %x:%x, err %x:\n", udev->port_no,
+ UGETW(ps.wPortChange), UGETW(ps.wPortStatus), err);
+
+ return 0;
+}
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 0a393844511..8bbbdc26849 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -708,5 +708,6 @@ void *usb_fifo_softc(struct usb_fifo *fifo);
void usb_fifo_set_close_zlp(struct usb_fifo *, uint8_t);
void usb_fifo_set_write_defrag(struct usb_fifo *, uint8_t);
void usb_fifo_free(struct usb_fifo *f);
+int usb_suspend_dev(struct usb_device *udev);
#endif /* _KERNEL */
#endif /* _USB_USBDI_H_ */
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1579231397567.62223>
