Skip to content

Commit

Permalink
MLK-18817 usb: cdns3: gadget: add mutex for role_start and role_stop
Browse files Browse the repository at this point in the history
The usb_add_hcd and usb_remove_hcd can't be called together, otherwise,
there is oops like below. To fix it, we add mutex to avoid calling
role_start and role_stop at the same time.

[3.336786] Can't support > 32 bit dma.
[3.340676]  xhci-cdns3: xHCI Host Controller
[3.345052]  xhci-cdns3: new USB bus registered, assigned bus number 1
[3.363462]  xhci-cdns3: hcc params 0x200073c8 hci version 0x100 quirks 0x60010010
[3.374555] hub 1-0:1.0: USB hub found
[3.378349] hub 1-0:1.0: 1 port detected
[3.382573]  xhci-cdns3: xHCI Host Controller
[3.386948]  xhci-cdns3: new USB bus registered, assigned bus number 2
[3.387707] cdns-usb3 5b110000.cdns3: current role is 0, switch to 1
[3.387711]  xhci-cdns3: remove, state 0
[3.387721] Unable to handle kernel NULL pointer dereference at virtual address 000000d8
[3.387723] pgd = ffff0000095f5000
[3.387731] [000000d8] *pgd=00000008bfffe003, *pud=00000008bfffd003, *pmd=0000000000000000
[3.387735] Internal error: Oops: 96000004 [Freescale#1] PREEMPT SMP
[3.387739] Modules linked in:
[3.387746] CPU: 0 PID: 745 Comm: kworker/0:1 Not tainted 4.9.88-05224-geb65e0981da1 #2087
[3.387748] Hardware name: Freescale i.MX8QXP MEK (DT)
[3.387765] Workqueue: events_freezable cdns3_role_switch
[3.387768] task: ffff80083a1d7080 task.stack: ffff80083aa5c000
[3.387775] PC is at sysfs_remove_group+0x18/0x98
[3.387781] LR is at usb_remove_hcd+0x58/0x200
[3.387784] pc : [<ffff000008265688>] lr : [<ffff00000885ac28>] pstate: 80000145
[3.387786] sp : ffff80083aa5fc70
[3.387791] x29: ffff80083aa5fc70 x28: 0000000000000000
[3.387795] x27: 0000000000000000 x26: ffff0000093cb2a8
[3.387800] x25: ffff000009506191 x24: ffff80083ff37280
[3.387804] x23: ffff80083b1b0138 x22: ffff80083b238000
[3.387809] x21: ffff80083b238000 x20: ffff0000094a1610
[3.387813] x19: ffff80083b1b0000 x18: 0000000000000020
[3.387817] x17: 0000000000000001 x16: 0000000000000019
[3.387822] x15: ffffffffffffffff x14: 00000000fffffff0
[3.387827] x13: ffff0000095a2068 x12: ffff0000093ce600
[3.387831] x11: ffff0000093ce000 x10: ffff00000959f000
[3.387836] x9 : 0000000000000000 x8 : ffff80083fe4244c
[3.387840] x7 : 0000000000000000 x6 : 0000000007cb5702
[3.387844] x5 : 00ffffffffffffff x4 : 0000000000000000
[3.387848] x3 : 0000000000000140 x2 : 00000000000008a6
[3.387852] x1 : 0000000000000000 x0 : 00000000000000a8
[3.387853]
[3.387856] Process kworker/0:1 (pid: 745, stack limit = 0xffff80083aa5c020)
[3.387860] Stack: (0xffff80083aa5fc70 to 0xffff80083aa60000)
[3.387865] fc60:                                   ffff80083aa5fca0 ffff00000885ac28
[3.387870] fc80: ffff80083b1b0000 ffff0000094a1000 ffff80083b238000 0000000000000000
[3.387875] fca0: ffff80083aa5fcf0 ffff00000889c5c8 ffff80083b1bf400 ffff80083b23e018
[3.387880] fcc0: ffff80083b238000 ffff80083b238000 ffff80083ff3bb00 ffff80083a1d7080
[3.387885] fce0: ffff000008ccc25c 0000000000000000 ffff80083aa5fd20 ffff000008897130
[3.387890] fd00: ffff80083b23e018 0000000000000001 0000000000000000 0000000000000000
[3.387895] fd20: ffff80083aa5fd50 ffff0000088972ec ffff80083b23e0d0 0000000000000000
[3.387901] fd40: ffff80083b23e018 ffff000008ccc25c ffff80083aa5fd80 ffff0000080dbc38
[3.387906] fd60: 0000000000000000 ffff80083ac3a600 ffff80083b23e0d0 ffff0000093b6000
[3.387911] fd80: ffff80083aa5fdc0 ffff0000080dbe40 ffff80083ac3a600 ffff80083ff37280
[3.387916] fda0: ffff80083ff37280 ffff80083ac3a630 ffff80083ff372a0 ffff0000093b6000
[3.387921] fdc0: ffff80083aa5fe20 ffff0000080e1c78 ffff80083a0fee80 ffff80083aa5c000
[3.387926] fde0: ffff00000908e2c8 ffff80083ac3a600 ffff0000080dbdf0 0000000000000000
[3.387931] fe00: 0000000000000000 0000000000000000 0000000000000000 ffff80083ac3a600
[3.387936] fe20: 0000000000000000 ffff000008083820 ffff0000080e1b98 ffff80083a0fee80
[3.387941] fe40: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387946] fe60: ffff80083aa5fea0 0000000000000000 ffff0000080e1b98 ffff80083ac3a600
[3.387951] fe80: 0000000000000000 0000000000000000 ffff80083aa5fe90 ffff80083aa5fe90
[3.387956] fea0: 0000000000000000 ffff000000000000 ffff80083aa5feb0 ffff80083aa5feb0
[3.387960] fec0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387965] fee0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387970] ff00: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387974] ff20: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387979] ff40: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387983] ff60: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387988] ff80: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387992] ffa0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[3.387997] ffc0: 0000000000000000 0000000000000005 0000000000000000 0000000000000000
[3.388002] ffe0: 0000000000000000 0000000000000000 fefffac7ef9fea6e f6ef6c26eeee7272
[3.388004] Call trace:
[3.388008] Exception stack(0xffff80083aa5faa0 to 0xffff80083aa5fbd0)
[3.388013] faa0: ffff80083b1b0000 0000ffffffffffff ffff80083aa5fc70 ffff000008265688
[3.388019] fac0: ffff80083b238000 ffff80083b238000 ffff80083b1b0138 ffff80083ff37280
[3.388024] fae0: ffff000009506191 ffff0000093cb2a8 0000000000000000 ffff80083aa5fcb0
[3.388029] fb00: ffff80083aa5fc20 ffff80083aa5fc20 ffff80083aa5fbf0 00000000ffffffd8
[3.388034] fb20: ffff000009506191 ffff0000093cb2a8 0000000000000000 ffff80083a11f408
[3.388038] fb40: 00000000000000a8 0000000000000000 00000000000008a6 0000000000000140
[3.388043] fb60: 0000000000000000 00ffffffffffffff 0000000007cb5702 0000000000000000
[3.388048] fb80: ffff80083fe4244c 0000000000000000 ffff00000959f000 ffff0000093ce000
[3.388054] fba0: ffff0000093ce600 ffff0000095a2068 00000000fffffff0 ffffffffffffffff
[3.388057] fbc0: 0000000000000019 0000000000000001
[3.388061] [<ffff000008265688>] sysfs_remove_group+0x18/0x98
[3.388066] [<ffff00000885ac28>] usb_remove_hcd+0x58/0x200
[3.388072] [<ffff00000889c5c8>] cdns3_host_stop+0x38/0xa0
[3.388077] [<ffff000008897130>] cdns3_do_role_switch+0x58/0x188
[3.388082] [<ffff0000088972ec>] cdns3_role_switch+0x8c/0xa0
[3.388089] [<ffff0000080dbc38>] process_one_work+0x1c8/0x380
[3.388094] [<ffff0000080dbe40>] worker_thread+0x50/0x4c0
[3.388099] [<ffff0000080e1c78>] kthread+0xe0/0xf8
[3.388104] [<ffff000008083820>] ret_from_fork+0x10/0x30

Signed-off-by: Peter Chen <peter.chen@nxp.com>
  • Loading branch information
Peter Chen authored and Jason Liu committed Feb 12, 2019
1 parent 1d7b68e commit 814cab7
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/usb/cdns3/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ static int cdns3_probe(struct platform_device *pdev)
return PTR_ERR(regs);
cdns->otg_regs = regs;

mutex_init(&cdns->mutex);
ret = cdns3_get_clks(dev);
if (ret)
return ret;
Expand Down
10 changes: 9 additions & 1 deletion drivers/usb/cdns3/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct cdns3_role_driver {
* @role_switch_wq: work queue item for role switch
* @in_lpm: the controller in low power mode
* @wakeup_int: the wakeup interrupt
* @mutex: the mutex for concurrent code at driver
*/
struct cdns3 {
struct device *dev;
Expand All @@ -89,6 +90,7 @@ struct cdns3 {
struct work_struct role_switch_wq;
bool in_lpm;
bool wakeup_int;
struct mutex mutex;
};

static inline struct cdns3_role_driver *cdns3_role(struct cdns3 *cdns)
Expand All @@ -99,14 +101,18 @@ static inline struct cdns3_role_driver *cdns3_role(struct cdns3 *cdns)

static inline int cdns3_role_start(struct cdns3 *cdns, enum cdns3_roles role)
{
int ret;
if (role >= CDNS3_ROLE_END)
return 0;

if (!cdns->roles[role])
return -ENXIO;

mutex_lock(&cdns->mutex);
cdns->role = role;
return cdns->roles[role]->start(cdns);
ret = cdns->roles[role]->start(cdns);
mutex_unlock(&cdns->mutex);
return ret;
}

static inline void cdns3_role_stop(struct cdns3 *cdns)
Expand All @@ -116,8 +122,10 @@ static inline void cdns3_role_stop(struct cdns3 *cdns)
if (role == CDNS3_ROLE_END)
return;

mutex_lock(&cdns->mutex);
cdns->roles[role]->stop(cdns);
cdns->role = CDNS3_ROLE_END;
mutex_unlock(&cdns->mutex);
}

#endif /* __DRIVERS_USB_CDNS3_CORE_H */

0 comments on commit 814cab7

Please sign in to comment.