• Gustavo Padovan's avatar
    drm/exynos: move Exynos platform drivers registration to init · 820687be
    Gustavo Padovan authored
    Registering the Exynos DRM subdevices platform drivers in the probe
    function is causing an infinite loop. Fix this by moving it to the
    exynos_drm_init() function to register the drivers on module init.
    
    Registering drivers in the probe functions causes a deadlock in the parent
    device lock. See Grant Likely explanation on the topic:
    
    "I think the problem is that exynos_drm_init() is registering a normal
    (non-OF) platform device, so the parent will be /sys/devices/platform.
    It immediately gets bound against exynos_drm_platform_driver which
    calls the exynos drm_platform_probe() hook. The driver core obtains
    device_lock() on the device *and on the device parent*.
    
    Inside the probe hook, additional platform_drivers get registered.
    Each time one does, it tries to bind against every platform device in
    the system, which includes the ones created by OF. When it attempts to
    bind, it obtains device_lock() on the device *and on the device
    parent*.
    
    Before the change to move of-generated platform devices into
    /sys/devices/platform, the devices had different parents. Now both
    devices have /sys/devices/platform as the parent, so yes they are
    going to deadlock.
    
    The real problem is registering drivers from within a probe hook. That
    is completely wrong for the above deadlock reason. __driver_attach()
    will deadlock. Those registrations must be pulled out of .probe().
    
    Registering devices in .probe() is okay because __device_attach()
    doesn't try to obtain device_lock() on the parent."
    
     INFO: task swapper/0:1 blocked for more than 120 seconds.
           Not tainted 3.18.0-rc3-next-20141105 #794
     "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
     swapper/0       D c052534c     0     1      0 0x00000000
     [<c052534c>] (__schedule) from [<c0525b34>] (schedule_preempt_disabled+0x14/0x20)
     [<c0525b34>] (schedule_preempt_disabled) from [<c0526d44>] (mutex_lock_nested+0x1c4/0x464
    
     [<c0526d44>] (mutex_lock_nested) from [<c02be908>] (__driver_attach+0x48/0x98)
     [<c02be908>] (__driver_attach) from [<c02bcc00>] (bus_for_each_dev+0x54/0x88)
     [<c02bcc00>] (bus_for_each_dev) from [<c02bdce0>] (bus_add_driver+0xe4/0x200)
     [<c02bdce0>] (bus_add_driver) from [<c02bef94>] (driver_register+0x78/0xf4)
     [<c02bef94>] (driver_register) from [<c029e99c>] (exynos_drm_platform_probe+0x34/0x234)
     [<c029e99c>] (exynos_drm_platform_probe) from [<c02bfcf0>] (platform_drv_probe+0x48/0xa4)
     [<c02bfcf0>] (platform_drv_probe) from [<c02be680>] (driver_probe_device+0x13c/0x37c)
     [<c02be680>] (driver_probe_device) from [<c02be954>] (__driver_attach+0x94/0x98)
     [<c02be954>] (__driver_attach) from [<c02bcc00>] (bus_for_each_dev+0x54/0x88)
     [<c02bcc00>] (bus_for_each_dev) from [<c02bdce0>] (bus_add_driver+0xe4/0x200)
     [<c02bdce0>] (bus_add_driver) from [<c02bef94>] (driver_register+0x78/0xf4)
     [<c02bef94>] (driver_register) from [<c029e938>] (exynos_drm_init+0x70/0xa0)
     [<c029e938>] (exynos_drm_init) from [<c00089b0>] (do_one_initcall+0xac/0x1f0)
     [<c00089b0>] (do_one_initcall) from [<c074bd90>] (kernel_init_freeable+0x10c/0x1d8)
     [<c074bd90>] (kernel_init_freeable) from [<c051eabc>] (kernel_init+0x8/0xec)
     [<c051eabc>] (kernel_init) from [<c000f268>] (ret_from_fork+0x14/0x2c)
     3 locks held by swapper/0/1:
      #0:  (&dev->mutex){......}, at: [<c02be908>] __driver_attach+0x48/0x98
      #1:  (&dev->mutex){......}, at: [<c02be918>] __driver_attach+0x58/0x98
      #2:  (&dev->mutex){......}, at: [<c02be908>] __driver_attach+0x48/0x98
    
    Changelog v2:
    - call platform_driver_register after all kms and non kms drivers are
      registered
    - rebased it to exynos-drm-next
    Signed-off-by: default avatarJavier Martinez Canillas <javier.martinez@collabora.co.uk>
    Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
    Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
    820687be
exynos_drm_drv.c 17.7 KB