Skip to content

Commit 95d38e3

Browse files
Peter Chenfelipebalbi
authored andcommitted
usb: cdns3: should not use the same dev_id for shared interrupt handler
Both drd and gadget interrupt handler use the struct cdns3 pointer as dev_id, it causes devm_free_irq at cdns3_gadget_exit doesn't free gadget's interrupt handler, it freed drd's handler. So, when the host interrupt occurs, the gadget's interrupt hanlder is still called, and causes below oops. To fix it, we use gadget's private data priv_dev as interrupt dev_id for gadget. Unable to handle kernel NULL pointer dereference at virtual address 0000000000000380 Mem abort info: ESR = 0x96000006 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000006 CM = 0, WnR = 0 user pgtable: 4k pages, 48-bit VAs, pgdp=0000000971d79000 [0000000000000380] pgd=0000000971d6f003, pud=0000000971d6e003, pmd=0000000000000000 Internal error: Oops: 96000006 [#1] PREEMPT SMP Modules linked in: mxc_jpeg_encdec crct10dif_ce fsl_imx8_ddr_perf CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.0-03486-g69f4e7d9c54a-dirty torvalds#254 Hardware name: Freescale i.MX8QM MEK (DT) pstate: 00000085 (nzcv daIf -PAN -UAO) pc : cdns3_device_irq_handler+0x1c/0xb8 lr : __handle_irq_event_percpu+0x78/0x2c0 sp : ffff800010003e30 x29: ffff800010003e30 x28: ffff8000129bb000 x27: ffff8000126e9000 x26: ffff0008f61b5600 x25: ffff800011fe1018 x24: ffff8000126ea120 x23: ffff800010003f04 x22: 0000000000000000 x21: 0000000000000093 x20: ffff0008f61b5600 x19: ffff0008f5061a80 x18: 0000000000000000 x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 x14: 003d090000000000 x13: 00003d0900000000 x12: 0000000000000000 x11: 00003d0900000000 x10: 0000000000000040 x9 : ffff800012708cb8 x8 : ffff800012708cb0 x7 : ffff0008f7c7a9d0 x6 : 0000000000000000 x5 : ffff0008f7c7a910 x4 : ffff8008ed359000 x3 : ffff800010003f40 x2 : 0000000000000000 x1 : ffff0008f5061a80 x0 : ffff800010161a60 Call trace: cdns3_device_irq_handler+0x1c/0xb8 __handle_irq_event_percpu+0x78/0x2c0 handle_irq_event_percpu+0x40/0x98 handle_irq_event+0x4c/0xd0 handle_fasteoi_irq+0xbc/0x168 generic_handle_irq+0x34/0x50 __handle_domain_irq+0x6c/0xc0 gic_handle_irq+0xd4/0x174 el1_irq+0xb8/0x180 arch_cpu_idle+0x3c/0x230 default_idle_call+0x38/0x40 do_idle+0x20c/0x298 cpu_startup_entry+0x28/0x48 rest_init+0xdc/0xe8 arch_call_rest_init+0x14/0x1c start_kernel+0x48c/0x4b8 Code: aa0103f3 aa1e03e0 d503201f f940966 (f941c040) ---[ end trace 091dcf4dee011b0e ]--- Kernel panic - not syncing: Fatal exception in interrupt SMP: stopping secondary CPUs Kernel Offset: disabled CPU features: 0x0002,2100600c Memory Limit: none ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]--- Fixes: 7733f6c ("usb: cdns3: Add Cadence USB3 DRD Driver") Cc: <[email protected]> #v5.4 Signed-off-by: Peter Chen <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 7f81f3b commit 95d38e3

File tree

1 file changed

+5
-9
lines changed

1 file changed

+5
-9
lines changed

drivers/usb/cdns3/gadget.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,13 +1367,10 @@ static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,
13671367
*/
13681368
static irqreturn_t cdns3_device_irq_handler(int irq, void *data)
13691369
{
1370-
struct cdns3_device *priv_dev;
1371-
struct cdns3 *cdns = data;
1370+
struct cdns3_device *priv_dev = data;
13721371
irqreturn_t ret = IRQ_NONE;
13731372
u32 reg;
13741373

1375-
priv_dev = cdns->gadget_dev;
1376-
13771374
/* check USB device interrupt */
13781375
reg = readl(&priv_dev->regs->usb_ists);
13791376
if (reg) {
@@ -1411,14 +1408,12 @@ static irqreturn_t cdns3_device_irq_handler(int irq, void *data)
14111408
*/
14121409
static irqreturn_t cdns3_device_thread_irq_handler(int irq, void *data)
14131410
{
1414-
struct cdns3_device *priv_dev;
1415-
struct cdns3 *cdns = data;
1411+
struct cdns3_device *priv_dev = data;
14161412
irqreturn_t ret = IRQ_NONE;
14171413
unsigned long flags;
14181414
int bit;
14191415
u32 reg;
14201416

1421-
priv_dev = cdns->gadget_dev;
14221417
spin_lock_irqsave(&priv_dev->lock, flags);
14231418

14241419
reg = readl(&priv_dev->regs->usb_ists);
@@ -2508,7 +2503,7 @@ void cdns3_gadget_exit(struct cdns3 *cdns)
25082503

25092504
priv_dev = cdns->gadget_dev;
25102505

2511-
devm_free_irq(cdns->dev, cdns->dev_irq, cdns);
2506+
devm_free_irq(cdns->dev, cdns->dev_irq, priv_dev);
25122507

25132508
pm_runtime_mark_last_busy(cdns->dev);
25142509
pm_runtime_put_autosuspend(cdns->dev);
@@ -2684,7 +2679,8 @@ static int __cdns3_gadget_init(struct cdns3 *cdns)
26842679
ret = devm_request_threaded_irq(cdns->dev, cdns->dev_irq,
26852680
cdns3_device_irq_handler,
26862681
cdns3_device_thread_irq_handler,
2687-
IRQF_SHARED, dev_name(cdns->dev), cdns);
2682+
IRQF_SHARED, dev_name(cdns->dev),
2683+
cdns->gadget_dev);
26882684

26892685
if (ret)
26902686
goto err0;

0 commit comments

Comments
 (0)