From 44f3f2bc01cdfd86ea7c199925daac4dd52e4b36 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Mar 2012 11:51:01 -0700 Subject: [PATCH] 3.2-stable patches added patches: usb-gadgetfs-return-number-of-bytes-on-ep0-read-request.patch usb-gadget-make-g_hid-device-class-conform-to-spec.patch usb-musb-reselect-index-reg-in-interrupt-context.patch usb-renesas_usbhs-bugfix-add-.release-function-to-gpriv-gadget.dev.patch --- queue-3.2/series | 4 + ...e-g_hid-device-class-conform-to-spec.patch | 36 ++++++ ...-number-of-bytes-on-ep0-read-request.patch | 34 ++++++ ...elect-index-reg-in-interrupt-context.patch | 109 ++++++++++++++++++ ...release-function-to-gpriv-gadget.dev.patch | 57 +++++++++ 5 files changed, 240 insertions(+) create mode 100644 queue-3.2/usb-gadget-make-g_hid-device-class-conform-to-spec.patch create mode 100644 queue-3.2/usb-gadgetfs-return-number-of-bytes-on-ep0-read-request.patch create mode 100644 queue-3.2/usb-musb-reselect-index-reg-in-interrupt-context.patch create mode 100644 queue-3.2/usb-renesas_usbhs-bugfix-add-.release-function-to-gpriv-gadget.dev.patch diff --git a/queue-3.2/series b/queue-3.2/series index 77777da6fac..495bba70065 100644 --- a/queue-3.2/series +++ b/queue-3.2/series @@ -15,3 +15,7 @@ staging-r8712u-fix-regression-introduced-by-commit-a5ee652.patch staging-r8712u-fix-regression-in-signal-level-after-commit-c6dc001.patch usb-dwc3-fix-bogus-test-in-dwc3_gadget_start_isoc.patch usb-dwc3-use-proper-function-for-setting-endpoint-name.patch +usb-musb-reselect-index-reg-in-interrupt-context.patch +usb-renesas_usbhs-bugfix-add-.release-function-to-gpriv-gadget.dev.patch +usb-gadgetfs-return-number-of-bytes-on-ep0-read-request.patch +usb-gadget-make-g_hid-device-class-conform-to-spec.patch diff --git a/queue-3.2/usb-gadget-make-g_hid-device-class-conform-to-spec.patch b/queue-3.2/usb-gadget-make-g_hid-device-class-conform-to-spec.patch new file mode 100644 index 00000000000..2be817f5593 --- /dev/null +++ b/queue-3.2/usb-gadget-make-g_hid-device-class-conform-to-spec.patch @@ -0,0 +1,36 @@ +From 33d2832ab0149a26418d360af3c444969a63fb28 Mon Sep 17 00:00:00 2001 +From: Orjan Friberg +Date: Wed, 7 Mar 2012 17:16:14 +0100 +Subject: USB: gadget: Make g_hid device class conform to spec. + +From: Orjan Friberg + +commit 33d2832ab0149a26418d360af3c444969a63fb28 upstream. + +HID devices should specify this in their interface descriptors, not in the +device descriptor. This fixes a "missing hardware id" bug under Windows 7 with +a VIA VL800 (3.0) controller. + +Signed-off-by: Orjan Friberg +Cc: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/hid.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/gadget/hid.c ++++ b/drivers/usb/gadget/hid.c +@@ -60,9 +60,9 @@ static struct usb_device_descriptor devi + /* .bDeviceClass = USB_CLASS_COMM, */ + /* .bDeviceSubClass = 0, */ + /* .bDeviceProtocol = 0, */ +- .bDeviceClass = 0xEF, +- .bDeviceSubClass = 2, +- .bDeviceProtocol = 1, ++ .bDeviceClass = USB_CLASS_PER_INTERFACE, ++ .bDeviceSubClass = 0, ++ .bDeviceProtocol = 0, + /* .bMaxPacketSize0 = f(hardware) */ + + /* Vendor and product id can be overridden by module parameters. */ diff --git a/queue-3.2/usb-gadgetfs-return-number-of-bytes-on-ep0-read-request.patch b/queue-3.2/usb-gadgetfs-return-number-of-bytes-on-ep0-read-request.patch new file mode 100644 index 00000000000..0f54172264a --- /dev/null +++ b/queue-3.2/usb-gadgetfs-return-number-of-bytes-on-ep0-read-request.patch @@ -0,0 +1,34 @@ +From 85b4b3c8c189e0159101f7628a71411af072ff69 Mon Sep 17 00:00:00 2001 +From: Thomas Faber +Date: Fri, 2 Mar 2012 09:41:50 +0100 +Subject: usb: gadgetfs: return number of bytes on ep0 read request + +From: Thomas Faber + +commit 85b4b3c8c189e0159101f7628a71411af072ff69 upstream. + +A read from GadgetFS endpoint 0 during the data stage of a control +request would always return 0 on success (as returned by +wait_event_interruptible) despite having written data into the user +buffer. +This patch makes it correctly set the return value to the number of +bytes read. + +Signed-off-by: Thomas Faber +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/gadget/inode.c ++++ b/drivers/usb/gadget/inode.c +@@ -1043,6 +1043,8 @@ ep0_read (struct file *fd, char __user * + // FIXME don't call this with the spinlock held ... + if (copy_to_user (buf, dev->req->buf, len)) + retval = -EFAULT; ++ else ++ retval = len; + clean_req (dev->gadget->ep0, dev->req); + /* NOTE userspace can't yet choose to stall */ + } diff --git a/queue-3.2/usb-musb-reselect-index-reg-in-interrupt-context.patch b/queue-3.2/usb-musb-reselect-index-reg-in-interrupt-context.patch new file mode 100644 index 00000000000..a0f0f2c7696 --- /dev/null +++ b/queue-3.2/usb-musb-reselect-index-reg-in-interrupt-context.patch @@ -0,0 +1,109 @@ +From 39287076e46d2c19aaceaa6f0a44168ae4d257ec Mon Sep 17 00:00:00 2001 +From: Supriya Karanth +Date: Fri, 17 Feb 2012 14:54:52 +0530 +Subject: usb: musb: Reselect index reg in interrupt context + +From: Supriya Karanth + +commit 39287076e46d2c19aaceaa6f0a44168ae4d257ec upstream. + +musb INDEX register is getting modified/corrupted during temporary +un-locking in a SMP system. Set this register with proper value +after re-acquiring the lock + +Scenario: +--------- +CPU1 is handling a data transfer completion interrupt received for +the CLASS1 EP +CPU2 is handling a CLASS2 thread which is queuing data to musb for +transfer + +Below is the error sequence: + + CPU1 | CPU2 +-------------------------------------------------------------------- +Data transfer completion inter- | +rupt recieved. | + | +musb INDEX reg set to CLASS1 EP | + | +musb LOCK is acquired. | + | + | CLASS2 thread queues data. + | + | CLASS2 thread tries to acquire musb + | LOCK but lock is already taken by + | CLASS1, so CLASS2 thread is + | spinning. + | +From Interrupt Context musb | +giveback function is called | + | +The giveback function releases | CLASS2 thread now acquires LOCK +LOCK | + | +ClASS1 Request's completion cal-| ClASS2 schedules the data transfer and +lback is called | sets the MUSB INDEX to Class2 EP number + | +Interrupt handler for CLASS1 EP | +tries to acquire LOCK and is | +spinning | + | +Interrupt for Class1 EP acquires| Class2 completes the scheduling etc and +the MUSB LOCK | releases the musb LOCK + | +Interrupt for Class1 EP schedul-| +es the next data transfer | +but musb INDEX register is still| +set to CLASS2 EP | + +Since the MUSB INDEX register is set to a different endpoint, we +read and modify the wrong registers. Hence data transfer will not +happen properly. This results in unpredictable behavior + +So, the MUSB INDEX register is set to proper value again when +interrupt re-acquires the lock + +Signed-off-by: Supriya Karanth +Signed-off-by: Praveena Nadahally +Reviewed-by: srinidhi kasagar +Signed-off-by: Felipe Balbi + +--- + drivers/usb/musb/musb_gadget.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -576,6 +576,15 @@ void musb_g_tx(struct musb *musb, u8 epn + + if (request->actual == request->length) { + musb_g_giveback(musb_ep, request, 0); ++ /* ++ * In the giveback function the MUSB lock is ++ * released and acquired after sometime. During ++ * this time period the INDEX register could get ++ * changed by the gadget_queue function especially ++ * on SMP systems. Reselect the INDEX to be sure ++ * we are reading/modifying the right registers ++ */ ++ musb_ep_select(mbase, epnum); + req = musb_ep->desc ? next_request(musb_ep) : NULL; + if (!req) { + dev_dbg(musb->controller, "%s idle now\n", +@@ -985,6 +994,15 @@ void musb_g_rx(struct musb *musb, u8 epn + } + #endif + musb_g_giveback(musb_ep, request, 0); ++ /* ++ * In the giveback function the MUSB lock is ++ * released and acquired after sometime. During ++ * this time period the INDEX register could get ++ * changed by the gadget_queue function especially ++ * on SMP systems. Reselect the INDEX to be sure ++ * we are reading/modifying the right registers ++ */ ++ musb_ep_select(mbase, epnum); + + req = next_request(musb_ep); + if (!req) diff --git a/queue-3.2/usb-renesas_usbhs-bugfix-add-.release-function-to-gpriv-gadget.dev.patch b/queue-3.2/usb-renesas_usbhs-bugfix-add-.release-function-to-gpriv-gadget.dev.patch new file mode 100644 index 00000000000..5d6c0dcb460 --- /dev/null +++ b/queue-3.2/usb-renesas_usbhs-bugfix-add-.release-function-to-gpriv-gadget.dev.patch @@ -0,0 +1,57 @@ +From 3b2a2e47174cd978258bbb0fdf2e2b1b5ec2144c Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto +Date: Mon, 20 Feb 2012 17:35:50 -0800 +Subject: usb: renesas_usbhs: bugfix: add .release function to gpriv->gadget.dev + +From: Kuninori Morimoto + +commit 3b2a2e47174cd978258bbb0fdf2e2b1b5ec2144c upstream. + +This patch fixup below warning on device_unregister() + +renesas_usbhs renesas_usbhs.1: host probed +renesas_usbhs renesas_usbhs.1: gadget probed +renesas_usbhs renesas_usbhs.1: irq request err +------------[ cut here ]------------ +WARNING: at ${LINUX}/drivers/base/core.c:1) +Device 'gadget' does not have a release() function, it is broken and must be fi. +Modules linked in: +[] (unwind_backtrace+0x0/0xe4) from [] (warn_slowpath_commo) +[] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_) +[] (warn_slowpath_fmt+0x2c/0x3c) from [] (device_release+0x) +[] (device_release+0x70/0x84) from [] (kobject_cleanup+0x58) +[] (kobject_cleanup+0x58/0x6c) from [] (usbhs_mod_gadget_re) +[] (usbhs_mod_gadget_remove+0x3c/0x6c) from [] (usbhs_mod_p) +[] (usbhs_mod_probe+0x68/0x80) from [] (usbhs_probe+0x1cc/0) +... + +Signed-off-by: Kuninori Morimoto +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/renesas_usbhs/mod_gadget.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/usb/renesas_usbhs/mod_gadget.c ++++ b/drivers/usb/renesas_usbhs/mod_gadget.c +@@ -816,6 +816,11 @@ static int usbhsg_stop(struct usbhs_priv + return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); + } + ++static void usbhs_mod_gadget_release(struct device *pdev) ++{ ++ /* do nothing */ ++} ++ + int usbhs_mod_gadget_probe(struct usbhs_priv *priv) + { + struct usbhsg_gpriv *gpriv; +@@ -864,6 +869,7 @@ int usbhs_mod_gadget_probe(struct usbhs_ + */ + dev_set_name(&gpriv->gadget.dev, "gadget"); + gpriv->gadget.dev.parent = dev; ++ gpriv->gadget.dev.release = usbhs_mod_gadget_release; + gpriv->gadget.name = "renesas_usbhs_udc"; + gpriv->gadget.ops = &usbhsg_gadget_ops; + gpriv->gadget.is_dualspeed = 1; -- 2.47.3