From: Mauro Carvalho Chehab Date: Wed, 16 Dec 2015 17:33:54 +0000 (-0200) Subject: [media] media-entity: don't sleep at media_device_register_entity() X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=ba0dd729bfc09e51af238a630deba70205442afe;p=linux-beck.git [media] media-entity: don't sleep at media_device_register_entity() media_device_register_entity() is protected by a spin_lock. Calling ida_pre_get() with GFP_KERNEL may put it to sleep, with is a bad idea and causes this warning: [ 8812.397195] BUG: sleeping function called from invalid context at mm/slub.c:1287 [ 8812.397203] in_atomic(): 1, irqs_disabled(): 0, pid: 15179, name: modprobe [ 8812.397207] INFO: lockdep is turned off. [ 8812.397213] CPU: 2 PID: 15179 Comm: modprobe Tainted: G B 4.4.0-rc2+ #41 [ 8812.397218] Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 [ 8812.397222] 0000000000000000 ffff880314c77268 ffffffff818f8ba7 ffff8803b17dde00 [ 8812.397232] ffff880314c77290 ffffffff811c2ee5 ffff8803b17dde00 ffffffff8284dbc9 [ 8812.397241] 0000000000000507 ffff880314c772d0 ffffffff811c30d5 0000000041b58ab3 [ 8812.397250] Call Trace: [ 8812.397258] [] dump_stack+0x4b/0x64 [ 8812.397265] [] ___might_sleep+0x245/0x3a0 [ 8812.397270] [] __might_sleep+0x95/0x1a0 [ 8812.397276] [] ? ida_pre_get+0x113/0x250 [ 8812.397282] [] kmem_cache_alloc+0x197/0x250 [ 8812.397288] [] ida_pre_get+0x113/0x250 [ 8812.397293] [] ida_simple_get+0xa5/0x170 [ 8812.397298] [] ? ida_pre_get+0x250/0x250 [ 8812.397306] [] media_device_register_entity+0x171/0x420 [media] [ 8812.397318] [] v4l2_device_register_subdev+0x34f/0x640 [videodev] [ 8812.397324] [] v4l2_i2c_new_subdev_board+0x12a/0x250 [v4l2_common] [ 8812.397330] [] v4l2_i2c_new_subdev+0xd7/0x110 [v4l2_common] [ 8812.397337] [] ? v4l2_i2c_new_subdev_board+0x250/0x250 [v4l2_common] [ 8812.397347] [] au0828_card_analog_fe_setup+0x2e6/0x3f0 [au0828] [ 8812.397352] [] ? power_down+0xc4/0xc4 [ 8812.397361] [] ? au0828_tuner_callback+0x160/0x160 [au0828] [ 8812.397370] [] au0828_card_setup+0x11f/0x340 [au0828] [ 8812.397378] [] ? au0828_card_analog_fe_setup+0x3f0/0x3f0 [au0828] [ 8812.397384] [] ? msleep+0x7b/0xc0 [ 8812.397393] [] au0828_usb_probe+0x679/0xcf0 [au0828] [ 8812.397399] [] usb_probe_interface+0x45d/0x940 [ 8812.397406] [] driver_probe_device+0x454/0xd90 [ 8812.397411] [] ? driver_probe_device+0xd90/0xd90 [ 8812.397417] [] ? driver_probe_device+0xd90/0xd90 [ 8812.397422] [] __driver_attach+0x121/0x160 [ 8812.397427] [] bus_for_each_dev+0x11f/0x1a0 [ 8812.397433] [] ? subsys_dev_iter_exit+0x10/0x10 [ 8812.397439] [] ? _raw_spin_unlock+0x27/0x40 [ 8812.397445] [] driver_attach+0x3d/0x50 [ 8812.397450] [] bus_add_driver+0x4c9/0x770 [ 8812.397456] [] driver_register+0x18c/0x3b0 [ 8812.397462] [] ? __raw_spin_lock_init+0x32/0x100 [ 8812.397468] [] usb_register_driver+0x1f8/0x440 [ 8812.397473] [] ? 0xffffffffa0208000 [ 8812.397481] [] au0828_init+0xb7/0x1000 [au0828] [ 8812.397486] [] do_one_initcall+0x141/0x300 [ 8812.397492] [] ? try_to_run_init_process+0x40/0x40 [ 8812.397497] [] ? trace_hardirqs_on_caller+0x16/0x590 [ 8812.397502] [] ? kasan_unpoison_shadow+0x36/0x50 [ 8812.397507] [] ? kasan_unpoison_shadow+0x36/0x50 [ 8812.397512] [] ? kasan_unpoison_shadow+0x36/0x50 [ 8812.397517] [] ? __asan_register_globals+0x87/0xa0 [ 8812.397524] [] do_init_module+0x1d0/0x5a4 [ 8812.397530] [] load_module+0x6648/0x9d70 [ 8812.397535] [] ? symbol_put_addr+0x50/0x50 [ 8812.397546] [] ? module_frob_arch_sections+0x20/0x20 [ 8812.397552] [] ? open_exec+0x50/0x50 [ 8812.397559] [] ? ns_capable+0x5b/0xd0 [ 8812.397565] [] SyS_finit_module+0x108/0x130 [ 8812.397571] [] ? SyS_init_module+0x1f0/0x1f0 [ 8812.397576] [] ? lockdep_sys_exit_thunk+0x12/0x14 [ 8812.397582] [] entry_SYSCALL_64_fastpath+0x16/0x7a Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index fd67b34dcda3..4d1c13de494b 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -537,6 +537,7 @@ int __must_check media_device_register_entity(struct media_device *mdev, struct media_entity *entity) { unsigned int i; + int ret; if (entity->function == MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN || entity->function == MEDIA_ENT_F_UNKNOWN) @@ -551,13 +552,16 @@ int __must_check media_device_register_entity(struct media_device *mdev, entity->num_links = 0; entity->num_backlinks = 0; + if (!ida_pre_get(&mdev->entity_internal_idx, GFP_KERNEL)) + return -ENOMEM; + spin_lock(&mdev->lock); - entity->internal_idx = ida_simple_get(&mdev->entity_internal_idx, 1, 0, - GFP_KERNEL); - if (entity->internal_idx < 0) { + ret = ida_get_new_above(&mdev->entity_internal_idx, 1, + &entity->internal_idx); + if (ret < 0) { spin_unlock(&mdev->lock); - return entity->internal_idx; + return ret; } mdev->entity_internal_idx_max =