RE: Possible bug in xhci_resume()

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

 



> -----Original Message-----
> From: Sarah Sharp [mailto:sarah.a.sharp@xxxxxxxxxxxxxxx]
> Sent: Friday, December 24, 2010 7:14 AM
> To: Xu, Andiry
> Cc: linux-usb@xxxxxxxxxxxxxxx
> Subject: Possible bug in xhci_resume()
> 
> Hi Andiry,
> 
> I'm seeing an unreachable code path in xhci_resume().  Can you please
> explain what you meant to do here?
> 
> In xhci_resume, you save the host controller's state in the variable
> old_state.  But then you only use it on an unreachable code path:
> 
> int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
> {
> 	u32			command, temp = 0;
> 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
> 	int	old_state, retval;
> 
> 	old_state = hcd->state;
> 	...
> 
> 	if (!hibernated) {
> 		/* restore registers */
> 	}
> 
> 	if ((temp & STS_SRE) || hibernated) {
> 		/* restart the host controller */
> 
> 		if (!retval)
> 			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
> 		hcd->state = HC_STATE_SUSPENDED;
> 		return retval;
> 
> 		/* Note the return here - this means if hibernated is
> 		 * true, we will always return out of this function
> 		 * here.
> 		 */
> 	}
> 
> 	...
> 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
> 	if (!hibernated)
> 		hcd->state = old_state;
> 	else
> 		hcd->state = HC_STATE_SUSPENDED;
> 	...
> }
> 
> Did you mean to set the hcd->state back to the old value when the host
> was resumed after a power loss?  If so, perhaps the if statement that
> tests for hibernation or a power loss could be changed to:
> 
> 	if ((temp & STS_SRE) || hibernated) {
> 		/* restart the host controller */
> 		if (!retval)
> 			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
> 		if (temp & STS_SRE)
> 			hcd->state = old_state;
> 		else
> 			hcd->state = HC_STATE_SUSPENDED;
> 		return retval;
> 	}
> 

Oh, thanks for catching this. I think it's another legacy design issue.

The right logic should be: set hcd->state = HC_STATE_SUSPENDED if there
is a power loss in resume or the system is hibernated, otherwise leave
it be. I referred to ehci_pci_resume().

So the old_state variable is redundant. The solution would be like this:

--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -705,9 +705,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool
hibernated)
 {
 	u32			command, temp = 0;
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
-	int	old_state, retval;
+	int	retval;
 
-	old_state = hcd->state;
 	if (time_before(jiffies, xhci->next_statechange))
 		msleep(100);
 
@@ -791,10 +790,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool
hibernated)
 	 */
 
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	if (!hibernated)
-		hcd->state = old_state;
-	else
-		hcd->state = HC_STATE_SUSPENDED;
 
 	spin_unlock_irq(&xhci->lock);
 	return 0;

If you are OK with this, I'll send a formal patch later. And Merry
Christmas!

Thanks,
Andiry




--
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