Re: problem with resume after s2ram

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, 20 Apr 2014, Peter Münster wrote:

> On Fri, Apr 18 2014, Alan Stern wrote:
> 
> > Below is a first simple attempt, let's call it fix1. This should be
> > applied to the kernel you have been using, with diag1 but without any
> > of the diag3* patches. What happens with fix1 and with the mouse
> > plugged into the rear?
> 
> Hi Alan,
> 
> It does not work. Please find attached the log.

All right; it was a long shot anyway.

Here's a new diagnostic patch (diag4) to try, on the same kernel, along 
with diag1 and nothing else.  This patch does almost the same thing as 
turning off CONFIG_USB_SUSPEND used to do in earlier versions of the 
kernel.  If the behavior is consistent, this should work with both the 
keyboard and mouse attached to the rear ports.

Alan Stern



Index: peter/drivers/usb/core/hub.c
===================================================================
--- peter.orig/drivers/usb/core/hub.c
+++ peter/drivers/usb/core/hub.c
@@ -2907,144 +2907,11 @@ static unsigned wakeup_enabled_descendan
  */
 int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 {
-	struct usb_hub	*hub = usb_hub_to_struct_hub(udev->parent);
-	struct usb_port *port_dev = hub->ports[udev->portnum - 1];
-	enum pm_qos_flags_status pm_qos_stat;
-	int		port1 = udev->portnum;
 	int		status;
-	bool		really_suspend = true;
-
-	/* enable remote wakeup when appropriate; this lets the device
-	 * wake up the upstream hub (including maybe the root hub).
-	 *
-	 * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
-	 * we don't explicitly enable it here.
-	 */
-	if (udev->do_remote_wakeup) {
-		if (!hub_is_superspeed(hub->hdev)) {
-			status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-					USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
-					USB_DEVICE_REMOTE_WAKEUP, 0,
-					NULL, 0,
-					USB_CTRL_SET_TIMEOUT);
-		} else {
-			/* Assume there's only one function on the USB 3.0
-			 * device and enable remote wake for the first
-			 * interface. FIXME if the interface association
-			 * descriptor shows there's more than one function.
-			 */
-			status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-					USB_REQ_SET_FEATURE,
-					USB_RECIP_INTERFACE,
-					USB_INTRF_FUNC_SUSPEND,
-					USB_INTRF_FUNC_SUSPEND_RW |
-					USB_INTRF_FUNC_SUSPEND_LP,
-					NULL, 0,
-					USB_CTRL_SET_TIMEOUT);
-		}
-		if (status) {
-			dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
-					status);
-			/* bail if autosuspend is requested */
-			if (PMSG_IS_AUTO(msg))
-				return status;
-		}
-	}
-
-	/* disable USB2 hardware LPM */
-	if (udev->usb2_hw_lpm_enabled == 1)
-		usb_set_usb2_hardware_lpm(udev, 0);
-
-	if (usb_disable_ltm(udev)) {
-		dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
-				__func__);
-		return -ENOMEM;
-	}
-	if (usb_unlocked_disable_lpm(udev)) {
-		dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
-				__func__);
-		return -ENOMEM;
-	}
 
-	/* see 7.1.7.6 */
-	if (hub_is_superspeed(hub->hdev))
-		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
-
-	/*
-	 * For system suspend, we do not need to enable the suspend feature
-	 * on individual USB-2 ports.  The devices will automatically go
-	 * into suspend a few ms after the root hub stops sending packets.
-	 * The USB 2.0 spec calls this "global suspend".
-	 *
-	 * However, many USB hubs have a bug: They don't relay wakeup requests
-	 * from a downstream port if the port's suspend feature isn't on.
-	 * Therefore we will turn on the suspend feature if udev or any of its
-	 * descendants is enabled for remote wakeup.
-	 */
-	else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0)
-		status = set_port_feature(hub->hdev, port1,
-				USB_PORT_FEAT_SUSPEND);
-	else {
-		really_suspend = false;
 		status = 0;
-	}
-	if (status) {
-		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
-				port1, status);
-		/* paranoia:  "should not happen" */
-		if (udev->do_remote_wakeup) {
-			if (!hub_is_superspeed(hub->hdev)) {
-				(void) usb_control_msg(udev,
-						usb_sndctrlpipe(udev, 0),
-						USB_REQ_CLEAR_FEATURE,
-						USB_RECIP_DEVICE,
-						USB_DEVICE_REMOTE_WAKEUP, 0,
-						NULL, 0,
-						USB_CTRL_SET_TIMEOUT);
-			} else
-				(void) usb_disable_function_remotewakeup(udev);
-
-		}
-
-		/* Try to enable USB2 hardware LPM again */
-		if (udev->usb2_hw_lpm_capable == 1)
-			usb_set_usb2_hardware_lpm(udev, 1);
-
-		/* Try to enable USB3 LTM and LPM again */
-		usb_enable_ltm(udev);
-		usb_unlocked_enable_lpm(udev);
-
-		/* System sleep transitions should never fail */
-		if (!PMSG_IS_AUTO(msg))
-			status = 0;
-	} else {
-		dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n",
-				(PMSG_IS_AUTO(msg) ? "auto-" : ""),
-				udev->do_remote_wakeup);
-		if (really_suspend) {
-			udev->port_is_suspended = 1;
-
-			/* device has up to 10 msec to fully suspend */
-			msleep(10);
-		}
 		usb_set_device_state(udev, USB_STATE_SUSPENDED);
-	}
 
-	/*
-	 * Check whether current status meets the requirement of
-	 * usb port power off mechanism
-	 */
-	pm_qos_stat = dev_pm_qos_flags(&port_dev->dev,
-			PM_QOS_FLAG_NO_POWER_OFF);
-	if (!udev->do_remote_wakeup
-			&& pm_qos_stat != PM_QOS_FLAGS_ALL
-			&& udev->persist_enabled
-			&& !status) {
-		pm_runtime_put_sync(&port_dev->dev);
-		port_dev->did_runtime_put = true;
-	}
-
-	usb_mark_last_busy(hub->hdev);
 	return status;
 }
 
@@ -3062,7 +2929,6 @@ int usb_port_suspend(struct usb_device *
 static int finish_port_resume(struct usb_device *udev)
 {
 	int	status = 0;
-	u16	devstatus = 0;
 
 	/* caller owns the udev device lock */
 	dev_dbg(&udev->dev, "%s\n",
@@ -3077,69 +2943,6 @@ static int finish_port_resume(struct usb
 			? USB_STATE_CONFIGURED
 			: USB_STATE_ADDRESS);
 
-	/* 10.5.4.5 says not to reset a suspended port if the attached
-	 * device is enabled for remote wakeup.  Hence the reset
-	 * operation is carried out here, after the port has been
-	 * resumed.
-	 */
-	if (udev->reset_resume)
- retry_reset_resume:
-		status = usb_reset_and_verify_device(udev);
-
- 	/* 10.5.4.5 says be sure devices in the tree are still there.
- 	 * For now let's assume the device didn't go crazy on resume,
-	 * and device drivers will know about any resume quirks.
-	 */
-	if (status == 0) {
-		devstatus = 0;
-		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
-		if (status >= 0)
-			status = (status > 0 ? 0 : -ENODEV);
-
-		/* If a normal resume failed, try doing a reset-resume */
-		if (status && !udev->reset_resume && udev->persist_enabled) {
-			dev_dbg(&udev->dev, "retry with reset-resume\n");
-			udev->reset_resume = 1;
-			goto retry_reset_resume;
-		}
-	}
-
-	if (status) {
-		dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
-				status);
-	/*
-	 * There are a few quirky devices which violate the standard
-	 * by claiming to have remote wakeup enabled after a reset,
-	 * which crash if the feature is cleared, hence check for
-	 * udev->reset_resume
-	 */
-	} else if (udev->actconfig && !udev->reset_resume) {
-		if (!hub_is_superspeed(udev->parent)) {
-			le16_to_cpus(&devstatus);
-			if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
-				status = usb_control_msg(udev,
-						usb_sndctrlpipe(udev, 0),
-						USB_REQ_CLEAR_FEATURE,
-						USB_RECIP_DEVICE,
-						USB_DEVICE_REMOTE_WAKEUP, 0,
-						NULL, 0,
-						USB_CTRL_SET_TIMEOUT);
-		} else {
-			status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
-					&devstatus);
-			le16_to_cpus(&devstatus);
-			if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
-					| USB_INTRF_STAT_FUNC_RW))
-				status =
-					usb_disable_function_remotewakeup(udev);
-		}
-
-		if (status)
-			dev_dbg(&udev->dev,
-				"disable remote wakeup, status %d\n",
-				status);
-		status = 0;
-	}
 	return status;
 }
 
@@ -3197,53 +3000,8 @@ int usb_port_resume(struct usb_device *u
 
 	/* Skip the initial Clear-Suspend step for a remote wakeup */
 	status = hub_port_status(hub, port1, &portstatus, &portchange);
-	if (status == 0 && !port_is_suspended(hub, portstatus))
-		goto SuspendCleared;
-
-	// dev_dbg(hub->intfdev, "resume port %d\n", port1);
-
-	set_bit(port1, hub->busy_bits);
-
-	/* see 7.1.7.7; affects power usage, but not budgeting */
-	if (hub_is_superspeed(hub->hdev))
-		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0);
-	else
-		status = usb_clear_port_feature(hub->hdev,
-				port1, USB_PORT_FEAT_SUSPEND);
-	if (status) {
-		dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
-				port1, status);
-	} else {
-		/* drive resume for at least 20 msec */
-		dev_dbg(&udev->dev, "usb %sresume\n",
-				(PMSG_IS_AUTO(msg) ? "auto-" : ""));
-		msleep(25);
-
-		/* Virtual root hubs can trigger on GET_PORT_STATUS to
-		 * stop resume signaling.  Then finish the resume
-		 * sequence.
-		 */
-		status = hub_port_status(hub, port1, &portstatus, &portchange);
-
-		/* TRSMRCY = 10 msec */
-		msleep(10);
-	}
-
- SuspendCleared:
-	if (status == 0) {
-		udev->port_is_suspended = 0;
-		if (hub_is_superspeed(hub->hdev)) {
-			if (portchange & USB_PORT_STAT_C_LINK_STATE)
-				usb_clear_port_feature(hub->hdev, port1,
-					USB_PORT_FEAT_C_PORT_LINK_STATE);
-		} else {
-			if (portchange & USB_PORT_STAT_C_SUSPEND)
-				usb_clear_port_feature(hub->hdev, port1,
-						USB_PORT_FEAT_C_SUSPEND);
-		}
-	}
-
-	clear_bit(port1, hub->busy_bits);
+	dev_info(&udev->dev, "port status %x change %x\n",
+			portstatus, portchange);
 
 	status = check_port_resume_type(udev,
 			hub, port1, status, portchange, portstatus);
@@ -3252,14 +3010,6 @@ int usb_port_resume(struct usb_device *u
 	if (status < 0) {
 		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
 		hub_port_logical_disconnect(hub, port1);
-	} else  {
-		/* Try to enable USB2 hardware LPM */
-		if (udev->usb2_hw_lpm_capable == 1)
-			usb_set_usb2_hardware_lpm(udev, 1);
-
-		/* Try to enable USB3 LTM and LPM */
-		usb_enable_ltm(udev);
-		usb_unlocked_enable_lpm(udev);
 	}
 
 	return status;

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux