From c818a94c77a9980709197c53368aa83451fd659f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 4 Dec 2014 13:06:07 +0100 Subject: [PATCH 1/3] usb: phy: Restore deferred probing path Commit 1290a958d48e ("usb: phy: propagate __of_usb_find_phy()'s error on failure") broke platforms that rely on deferred probing to order probing of PHY and host controller drivers. The reason is that the commit simply propagates errors from __of_usb_find_phy(), which returns -ENODEV if no PHY has been registered yet for a given device tree node. The only case in which -EPROBE_DEFER would now be returned is if try_module_get() did fail, which does not make sense. The correct thing to do is to return -EPROBE_DEFER if a PHY hasn't been registered yet. The only condition under which it makes sense to return -ENODEV is if the device tree node representing the PHY has been disabled (via the status property) because in that case the PHY will never be registered. This patch addresses the problem by making __of_usb_find_phy() return an appropriate error code while keeping in line with the above-mentioned commit to propagate error codes rather than overwriting them. At the same time the check for a valid PHY is decoupled from the check for the try_module_get() call and a separate error code is returned if the latter fails. Fixes: 1290a95 (usb: phy: propagate __of_usb_find_phy()'s error on failure) Signed-off-by: Thierry Reding Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index b4066a001ba0..2f9735b35338 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -59,6 +59,9 @@ static struct usb_phy *__of_usb_find_phy(struct device_node *node) { struct usb_phy *phy; + if (!of_device_is_available(node)) + return ERR_PTR(-ENODEV); + list_for_each_entry(phy, &phy_list, head) { if (node != phy->dev->of_node) continue; @@ -66,7 +69,7 @@ static struct usb_phy *__of_usb_find_phy(struct device_node *node) return phy; } - return ERR_PTR(-ENODEV); + return ERR_PTR(-EPROBE_DEFER); } static void devm_usb_phy_release(struct device *dev, void *res) @@ -190,10 +193,13 @@ struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, spin_lock_irqsave(&phy_lock, flags); phy = __of_usb_find_phy(node); - if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { - if (!IS_ERR(phy)) - phy = ERR_PTR(-EPROBE_DEFER); + if (IS_ERR(phy)) { + devres_free(ptr); + goto err1; + } + if (!try_module_get(phy->dev->driver->owner)) { + phy = ERR_PTR(-ENODEV); devres_free(ptr); goto err1; } From 42d6cfa0caec4b68a7f17147fbf13a36e94a8bf2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 6 Jan 2015 13:19:21 +0300 Subject: [PATCH 2/3] usb: gadget: gadgetfs: fix an oops in ep_write() We try to free an ERR_PTR on this error path. Fixes: b44be2462dbe ('usb: gadget: gadgetfs: Free memory allocated by memdup_user()') Signed-off-by: Dan Carpenter Signed-off-by: Felipe Balbi --- drivers/usb/gadget/legacy/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 08048613eed6..db49ec4c748e 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -441,6 +441,7 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) kbuf = memdup_user(buf, len); if (IS_ERR(kbuf)) { value = PTR_ERR(kbuf); + kbuf = NULL; goto free1; } From 5fb694f96e7c19e66b1c55124b98812e32e3efa5 Mon Sep 17 00:00:00 2001 From: Songjun Wu Date: Fri, 9 Jan 2015 17:11:24 +0100 Subject: [PATCH 3/3] usb: gadget: udc: atmel: fix possible oops when unloading module When unloading the module 'g_hid.ko', the urb request will be dequeued and the completion routine will be excuted. If there is no urb packet, the urb request will not be added to the endpoint queue and the completion routine pointer in urb request is NULL. Accessing to this NULL function pointer will cause the Oops issue reported below. Add the code to check if the urb request is in the endpoint queue or not. If the urb request is not in the endpoint queue, a negative error code will be returned. Here is the Oops log: Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = dedf0000 [00000000] *pgd=3ede5831, *pte=00000000, *ppte=00000000 Internal error: Oops: 80000007 [#1] ARM Modules linked in: g_hid(-) usb_f_hid libcomposite CPU: 0 PID: 923 Comm: rmmod Not tainted 3.18.0+ #2 Hardware name: Atmel SAMA5 (Device Tree) task: df6b1100 ti: dedf6000 task.ti: dedf6000 PC is at 0x0 LR is at usb_gadget_giveback_request+0xc/0x10 pc : [<00000000>] lr : [] psr: 60000093 sp : dedf7eb0 ip : df572634 fp : 00000000 r10: 00000000 r9 : df52e210 r8 : 60000013 r7 : df6a9858 r6 : df52e210 r5 : df6a9858 r4 : df572600 r3 : 00000000 r2 : ffffff98 r1 : df572600 r0 : df6a9868 Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c53c7d Table: 3edf0059 DAC: 00000015 Process rmmod (pid: 923, stack limit = 0xdedf6230) Stack: (0xdedf7eb0 to 0xdedf8000) 7ea0: 00000000 c02adbbc df572580 deced608 7ec0: df572600 df6a9868 df572634 c02aed3c df577c00 c01b8608 00000000 df6be27c 7ee0: 00200200 00100100 bf0162f4 c000e544 dedf6000 00000000 00000000 bf010c00 7f00: bf0162cc bf00159c 00000000 df572980 df52e218 00000001 df5729b8 bf0031d0 [..] [] (usb_gadget_giveback_request) from [] (request_complete+0x64/0x88) [] (request_complete) from [] (usba_ep_dequeue+0x70/0x128) [] (usba_ep_dequeue) from [] (hidg_unbind+0x50/0x7c [usb_f_hid]) [] (hidg_unbind [usb_f_hid]) from [] (remove_config.isra.6+0x98/0x9c [libcomposite]) [] (remove_config.isra.6 [libcomposite]) from [] (__composite_unbind+0x34/0x98 [libcomposite]) [] (__composite_unbind [libcomposite]) from [] (usb_gadget_remove_driver+0x50/0x78) [] (usb_gadget_remove_driver) from [] (usb_gadget_unregister_driver+0x64/0x94) [] (usb_gadget_unregister_driver) from [] (hidg_cleanup+0x10/0x34 [g_hid]) [] (hidg_cleanup [g_hid]) from [] (SyS_delete_module+0x118/0x19c) [] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x30) Code: bad PC value Signed-off-by: Songjun Wu [nicolas.ferre@atmel.com: reworked the commit message] Signed-off-by: Nicolas Ferre Fixes: 914a3f3b3754 ("USB: add atmel_usba_udc driver") Cc: # 2.6.x-ish Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/atmel_usba_udc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 93328ea7eb1b..9f93bed42052 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -828,7 +828,7 @@ static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) { struct usba_ep *ep = to_usba_ep(_ep); struct usba_udc *udc = ep->udc; - struct usba_request *req = to_usba_req(_req); + struct usba_request *req; unsigned long flags; u32 status; @@ -837,6 +837,16 @@ static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) spin_lock_irqsave(&udc->lock, flags); + list_for_each_entry(req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + + if (&req->req != _req) { + spin_unlock_irqrestore(&udc->lock, flags); + return -EINVAL; + } + if (req->using_dma) { /* * If this request is currently being transferred,