Commit b64576cb authored by Finn Thain's avatar Finn Thain Committed by Jens Axboe

m68k/mac: Don't remap SWIM MMIO region

For reasons I don't understand, calling ioremap() then iounmap() on
the SWIM MMIO region causes a hang on 68030 (but not on 68040).

~# modprobe swim_mod
SWIM floppy driver Version 0.2 (2008-10-30)
SWIM device not found !
watchdog: BUG: soft lockup - CPU#0 stuck for 23s! [modprobe:285]
Modules linked in: swim_mod(+)
Format 00  Vector: 0064  PC: 000075aa  Status: 2000    Not tainted
ORIG_D0: ffffffff  D0: d00c0000  A2: 007c2370  A1: 003f810c
A0: 00040000  D5: d0096800  D4: d0097e00
D3: 00000001  D2: 00000003  D1: 00000000
Non-Maskable Interrupt
Modules linked in: swim_mod(+)
PC: [<000075ba>] __iounmap+0x24/0x10e
SR: 2000  SP: 007abc48  a2: 007c2370
d0: d00c0000    d1: 000001a0    d2: 00000019    d3: 00000001
d4: d0097e00    d5: d0096800    a0: 00040000    a1: 003f810c
Process modprobe (pid: 285, task=007c2370)
Frame format=0
Stack from 007abc7c:
        ffffffed 00000000 006a4060 004712e0 007abca0 000076ea d0080000 00080000
        010bb4b8 007abcd8 010ba542 d0096000 00000000 00000000 00000001 010bb59c
        00000000 007abf30 010bb4b8 0047760a 0047763c 00477612 00616540 007abcec
        0020a91a 00477600 0047760a 010bb4cc 007abd18 002092f2 0047760a 00333b06
        007abd5c 00000000 0047760a 010bb4cc 00404f90 004776b8 00000001 007abd38
        00209446 010bb4cc 0047760a 010bb4cc 0020938e 0031f8be 00616540 007abd64
Call Trace: [<000076ea>] iounmap+0x46/0x5a
 [<00080000>] shrink_page_list+0x7f6/0xe06
 [<010ba542>] swim_probe+0xe4/0x496 [swim_mod]
 [<0020a91a>] platform_drv_probe+0x20/0x5e
 [<002092f2>] driver_probe_device+0x21c/0x2b8
 [<00333b06>] mutex_lock+0x0/0x2e
 [<00209446>] __driver_attach+0xb8/0xce
 [<0020938e>] __driver_attach+0x0/0xce
 [<0031f8be>] klist_next+0x0/0xa0
 [<00207562>] bus_for_each_dev+0x74/0xba
 [<000344c0>] blocking_notifier_call_chain+0x0/0x20
 [<00333b06>] mutex_lock+0x0/0x2e
 [<00208e44>] driver_attach+0x1a/0x1e
 [<0020938e>] __driver_attach+0x0/0xce
 [<00207e26>] bus_add_driver+0x188/0x234
 [<000344c0>] blocking_notifier_call_chain+0x0/0x20
 [<00209894>] driver_register+0x58/0x104
 [<000344c0>] blocking_notifier_call_chain+0x0/0x20
 [<010bd000>] swim_init+0x0/0x2c [swim_mod]
 [<0020a7be>] __platform_driver_register+0x38/0x3c
 [<010bd028>] swim_init+0x28/0x2c [swim_mod]
 [<000020dc>] do_one_initcall+0x38/0x196
 [<000344c0>] blocking_notifier_call_chain+0x0/0x20
 [<003331cc>] mutex_unlock+0x0/0x3e
 [<00333b06>] mutex_lock+0x0/0x2e
 [<003331cc>] mutex_unlock+0x0/0x3e
 [<00333b06>] mutex_lock+0x0/0x2e
 [<003331cc>] mutex_unlock+0x0/0x3e
 [<00333b06>] mutex_lock+0x0/0x2e
 [<003331cc>] mutex_unlock+0x0/0x3e
 [<00333b06>] mutex_lock+0x0/0x2e
 [<00075008>] __free_pages+0x0/0x38
 [<000045c0>] mangle_kernel_stack+0x30/0xda
 [<000344c0>] blocking_notifier_call_chain+0x0/0x20
 [<003331cc>] mutex_unlock+0x0/0x3e
 [<00333b06>] mutex_lock+0x0/0x2e
 [<0005ced4>] do_init_module+0x42/0x266
 [<010bd000>] swim_init+0x0/0x2c [swim_mod]
 [<000344c0>] blocking_notifier_call_chain+0x0/0x20
 [<0005eda0>] load_module+0x1a30/0x1e70
 [<0000465d>] mangle_kernel_stack+0xcd/0xda
 [<00331c64>] __generic_copy_from_user+0x0/0x46
 [<0033256e>] _cond_resched+0x0/0x32
 [<00331b9c>] memset+0x0/0x98
 [<0033256e>] _cond_resched+0x0/0x32
 [<0005f25c>] SyS_init_module+0x7c/0x112
 [<00002000>] _start+0x0/0x8
 [<00002000>] _start+0x0/0x8
 [<00331c82>] __generic_copy_from_user+0x1e/0x46
 [<0005f2b2>] SyS_init_module+0xd2/0x112
 [<0000465d>] mangle_kernel_stack+0xcd/0xda
 [<00002b40>] syscall+0x8/0xc
 [<0000465d>] mangle_kernel_stack+0xcd/0xda
 [<0008c00c>] pcpu_balance_workfn+0xb2/0x40e
Code: 2200 7419 e4a9 e589 2841 d9fc 0000 1000 <2414> 7203 c282 7602 b681 6600 0096 0242 fe00 0482 0000 0000 e9c0 11c3 ed89 2642

There's no need to call ioremap() for the SWIM address range, as it lies
within the usual IO device region at 0x5000 0000, which has already been
mapped by head.S.

Remove the redundant ioremap() and iounmap() calls to fix the hang.

Cc: Laurent Vivier <lvivier@redhat.com>
Cc: stable@vger.kernel.org # v4.14+
Tested-by: default avatarStan Johnson <userm57@yahoo.com>
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Acked-by: default avatarLaurent Vivier <lvivier@redhat.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent f9de14bc
...@@ -911,7 +911,7 @@ static int swim_probe(struct platform_device *dev) ...@@ -911,7 +911,7 @@ static int swim_probe(struct platform_device *dev)
goto out; goto out;
} }
swim_base = ioremap(res->start, resource_size(res)); swim_base = (struct swim __iomem *)res->start;
if (!swim_base) { if (!swim_base) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_release_io; goto out_release_io;
...@@ -923,7 +923,7 @@ static int swim_probe(struct platform_device *dev) ...@@ -923,7 +923,7 @@ static int swim_probe(struct platform_device *dev)
if (!get_swim_mode(swim_base)) { if (!get_swim_mode(swim_base)) {
printk(KERN_INFO "SWIM device not found !\n"); printk(KERN_INFO "SWIM device not found !\n");
ret = -ENODEV; ret = -ENODEV;
goto out_iounmap; goto out_release_io;
} }
/* set platform driver data */ /* set platform driver data */
...@@ -931,7 +931,7 @@ static int swim_probe(struct platform_device *dev) ...@@ -931,7 +931,7 @@ static int swim_probe(struct platform_device *dev)
swd = kzalloc(sizeof(struct swim_priv), GFP_KERNEL); swd = kzalloc(sizeof(struct swim_priv), GFP_KERNEL);
if (!swd) { if (!swd) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_iounmap; goto out_release_io;
} }
platform_set_drvdata(dev, swd); platform_set_drvdata(dev, swd);
...@@ -945,8 +945,6 @@ static int swim_probe(struct platform_device *dev) ...@@ -945,8 +945,6 @@ static int swim_probe(struct platform_device *dev)
out_kfree: out_kfree:
kfree(swd); kfree(swd);
out_iounmap:
iounmap(swim_base);
out_release_io: out_release_io:
release_mem_region(res->start, resource_size(res)); release_mem_region(res->start, resource_size(res));
out: out:
...@@ -974,8 +972,6 @@ static int swim_remove(struct platform_device *dev) ...@@ -974,8 +972,6 @@ static int swim_remove(struct platform_device *dev)
for (drive = 0; drive < swd->floppy_count; drive++) for (drive = 0; drive < swd->floppy_count; drive++)
floppy_eject(&swd->unit[drive]); floppy_eject(&swd->unit[drive]);
iounmap(swd->base);
res = platform_get_resource(dev, IORESOURCE_MEM, 0); res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (res) if (res)
release_mem_region(res->start, resource_size(res)); release_mem_region(res->start, resource_size(res));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment