usb: dwc3: Skip check for U3 when handling Function Suspend

Skip check for U3 link state when we receive Function Suspend.
Link is not in U3 when host sends Function Suspend, but will
be in U3 if/when the subsequent Bus Suspend arrives.
If we check for U3 in the case of Function Suspend, we will
not disconnect channels with IPA as the API that checks
pre-conditions for suspend will always return FALSE.
The U3 check is done as usual in the case of Bus Suspend from
the host.

CRs-Fixed: 966352
Change-Id: Ie9ee045a096b58256d2e8814338ffe0aa3c01163
Signed-off-by: Devdutt Patnaik <dpatnaik@codeaurora.org>
This commit is contained in:
Devdutt Patnaik 2016-02-12 18:23:25 -08:00 committed by David Keitel
parent 64e4a14d1f
commit 5028f26ab3

View file

@ -1180,7 +1180,7 @@ static void gsi_set_clear_dbell(struct usb_ep *ep,
*
* @usb_ep - pointer to usb_ep instance to access DWC3 regs
*/
static bool gsi_check_ready_to_suspend(struct usb_ep *ep)
static bool gsi_check_ready_to_suspend(struct usb_ep *ep, bool f_suspend)
{
u32 timeout = 1500;
u32 reg = 0;
@ -1196,11 +1196,13 @@ static bool gsi_check_ready_to_suspend(struct usb_ep *ep)
return false;
}
}
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U3) {
dev_err(mdwc->dev, "Unable to suspend GSI ch\n");
return false;
/* Check for U3 only if we are not handling Function Suspend */
if (!f_suspend) {
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U3) {
dev_err(mdwc->dev, "Unable to suspend GSI ch\n");
return false;
}
}
return true;
@ -1226,7 +1228,7 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
struct usb_gsi_request *request;
struct gsi_channel_info *ch_info;
bool block_db;
bool block_db, f_suspend;
switch (op) {
case GSI_EP_OP_PREPARE_TRBS:
@ -1286,7 +1288,8 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep,
break;
case GSI_EP_OP_CHECK_FOR_SUSPEND:
dev_dbg(mdwc->dev, "EP_OP_CHECK_FOR_SUSPEND\n");
ret = gsi_check_ready_to_suspend(ep);
f_suspend = *((bool *)op_data);
ret = gsi_check_ready_to_suspend(ep, f_suspend);
break;
default:
dev_err(mdwc->dev, "%s: Invalid opcode GSI EP\n", __func__);