[PATCH] drivers: usb: host: Fix GFP_KERNEL in spinlock context

From: shrikant . maurya
Date: Fri Dec 22 2017 - 01:03:42 EST


From: Shrikant Maurya <shrikant.maurya@xxxxxxxxxxxx>

As reported by Jia-Ju Bai (https://lkml.org/lkml/2017/12/11/872):
API's are using GFP_KERNEL to allocate memory, which may sleep.
To ensure atomicity such allocations must be avoided in critical
sections under spinlock.
Fixed by moving part of the code which is using GFP_KERNEL for
memory allocation out of spinlock.

Reported-by: Jia-Ju Bai <baijiaju1990@xxxxxxxxx>
Signed-off-by: Shrikant Maurya <shrikant.maurya@xxxxxxxxxxxx>
Signed-off-by: Suniel Mahesh <sunil.m@xxxxxxxxxxxx>
Signed-off-by: Raghu Bharadwaj <raghu@xxxxxxxxxxxx>
Signed-off-by: Karthik Tummala <karthik@xxxxxxxxxxxx>
---
Note:
- trace of device_init_wakeup() leads to creation of a struct
wakeup_source object and addition of the object to the list
of wakeup sources. While allocating wakeup_source object, API
is using GFP_KERNEL. This particular section is removed out of
spinlock.
- Changeset was compile tested and built(ARCH=arm) on linux-next
(latest).
- No build issues reported.
- Changeset was not tested on hardware.
- Please discard this changeset, if this is not
making the code any better.
---
drivers/usb/host/isp116x-hcd.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 5f9234b..47334e8 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1319,6 +1319,11 @@ static int isp116x_start(struct usb_hcd *hcd)
u32 val;
unsigned long flags;

+ if (board->remote_wakeup_enable) {
+ if (!device_can_wakeup(hcd->self.controller))
+ device_init_wakeup(hcd->self.controller, 1);
+ }
+
spin_lock_irqsave(&isp116x->lock, flags);

/* clear interrupt status and disable all interrupt sources */
@@ -1369,11 +1374,8 @@ static int isp116x_start(struct usb_hcd *hcd)
isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB);

val = 0;
- if (board->remote_wakeup_enable) {
- if (!device_can_wakeup(hcd->self.controller))
- device_init_wakeup(hcd->self.controller, 1);
+ if (board->remote_wakeup_enable)
val |= RH_HS_DRWE;
- }
isp116x_write_reg32(isp116x, HCRHSTATUS, val);
isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);

--
1.9.1