Patch "usb: dwc3: gadget: fix set_halt() bug with pending transfers" has been added to the 3.17-stable tree

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

 



This is a note to let you know that I've just added the patch titled

    usb: dwc3: gadget: fix set_halt() bug with pending transfers

to the 3.17-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     usb-dwc3-gadget-fix-set_halt-bug-with-pending-transfers.patch
and it can be found in the queue-3.17 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.


>From balbi@xxxxxx  Wed Nov 12 08:38:02 2014
From: Felipe Balbi <balbi@xxxxxx>
Date: Mon, 10 Nov 2014 08:55:44 -0600
Subject: usb: dwc3: gadget: fix set_halt() bug with pending transfers
To: Greg KH <gregkh@xxxxxxxxxxxxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx>, Felipe Balbi <balbi@xxxxxx>
Message-ID: <1415631344-23269-1-git-send-email-balbi@xxxxxx>

From: Felipe Balbi <balbi@xxxxxx>

[ Upstream commit 7a60855972f0d3c014093046cb6f013a1ee5bb19 ]

According to our Gadget Framework API documentation,
->set_halt() *must* return -EAGAIN if we have pending
transfers (on either direction) or FIFO isn't empty (on
TX endpoints).

Fix this bug so that the mass storage gadget can be used
without stall=0 parameter.

This patch should be backported to all kernels since v3.2.

Suggested-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Felipe Balbi <balbi@xxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
 drivers/usb/dwc3/ep0.c    |    4 ++--
 drivers/usb/dwc3/gadget.c |   16 ++++++++++++----
 drivers/usb/dwc3/gadget.h |    2 +-
 3 files changed, 15 insertions(+), 7 deletions(-)

--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -251,7 +251,7 @@ static void dwc3_ep0_stall_and_restart(s
 
 	/* stall is always issued on EP0 */
 	dep = dwc->eps[0];
-	__dwc3_gadget_ep_set_halt(dep, 1);
+	__dwc3_gadget_ep_set_halt(dep, 1, false);
 	dep->flags = DWC3_EP_ENABLED;
 	dwc->delayed_status = false;
 
@@ -461,7 +461,7 @@ static int dwc3_ep0_handle_feature(struc
 				return -EINVAL;
 			if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
 				break;
-			ret = __dwc3_gadget_ep_set_halt(dep, set);
+			ret = __dwc3_gadget_ep_set_halt(dep, set, true);
 			if (ret)
 				return -EINVAL;
 			break;
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -670,7 +670,7 @@ static int __dwc3_gadget_ep_disable(stru
 
 	/* make sure HW endpoint isn't stalled */
 	if (dep->flags & DWC3_EP_STALL)
-		__dwc3_gadget_ep_set_halt(dep, 0);
+		__dwc3_gadget_ep_set_halt(dep, 0, false);
 
 	reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
 	reg &= ~DWC3_DALEPENA_EP(dep->number);
@@ -1286,7 +1286,7 @@ out0:
 	return ret;
 }
 
-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
+int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
 {
 	struct dwc3_gadget_ep_cmd_params	params;
 	struct dwc3				*dwc = dep->dwc;
@@ -1295,6 +1295,14 @@ int __dwc3_gadget_ep_set_halt(struct dwc
 	memset(&params, 0x00, sizeof(params));
 
 	if (value) {
+		if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) ||
+				(!list_empty(&dep->req_queued) ||
+				 !list_empty(&dep->request_list)))) {
+			dev_dbg(dwc->dev, "%s: pending request, cannot halt\n",
+					dep->name);
+			return -EAGAIN;
+		}
+
 		ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
 			DWC3_DEPCMD_SETSTALL, &params);
 		if (ret)
@@ -1332,7 +1340,7 @@ static int dwc3_gadget_ep_set_halt(struc
 		goto out;
 	}
 
-	ret = __dwc3_gadget_ep_set_halt(dep, value);
+	ret = __dwc3_gadget_ep_set_halt(dep, value, false);
 out:
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -1352,7 +1360,7 @@ static int dwc3_gadget_ep_set_wedge(stru
 	if (dep->number == 0 || dep->number == 1)
 		return dwc3_gadget_ep0_set_halt(ep, 1);
 	else
-		return dwc3_gadget_ep_set_halt(ep, 1);
+		return __dwc3_gadget_ep_set_halt(dep, 1, false);
 }
 
 /* -------------------------------------------------------------------------- */
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -85,7 +85,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc
 int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
 int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
 		gfp_t gfp_flags);
-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
+int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
 
 /**
  * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW


Patches currently in stable-queue which might be from balbi@xxxxxx are

queue-3.17/usb-musb-cppi41-restart-hrtimer-only-if-not-yet-done.patch
queue-3.17/usb-dwc3-gadget-fix-set_halt-bug-with-pending-transfers.patch
queue-3.17/usb-ffs-fix-regression-when-quirk_ep_out_aligned_size-flag-is-set.patch
queue-3.17/usb-gadget-f_fs-remove-redundant-ffs_data_get.patch
queue-3.17/usb-musb-dsps-start-otg-timer-on-resume-again.patch
queue-3.17/revert-usb-dwc3-dwc3-omap-disable-enable-only-wrapper-interrupts-in-prepare-complete.patch
queue-3.17/usb-gadget-function-acm-make-f_acm-pass-usb20cv-chapter9.patch
queue-3.17/usb-gadget-udc-core-fix-kernel-oops-with-soft-connect.patch
queue-3.17/usb-dwc3-gadget-properly-initialize-link-trb.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]