The platform devices registered in sysfb match with a firmware-based fbdev
or DRM driver, that are used to have early graphics using framebuffers set
up by the system firmware.

Real DRM drivers later are probed and remove all conflicting framebuffers,
leading to these platform devices for generic drivers to be unregistered.

But the current solution has the problem that sysfb doesn't know when the
device that registered is unregistered. This means that is not able to do
any cleanup if needed since the device pointer may not be valid anymore.

Not all platforms use sysfb to register the simple framebuffer devices,
so an unregistration has to be forced by fbmem if sysfb_try_unregister()
does not succeed at unregister the device.

Suggested-by: Daniel Vetter <[email protected]>
Signed-off-by: Javier Martinez Canillas <[email protected]>
Reviewed-by: Daniel Vetter <[email protected]>

---

Changes in v4:
- Drop call to sysfb_disable() in fbmem since is done in other places now.

Changes in v2:
- Explain in the commit message that fbmem has to unregister the device
  as fallback if a driver registered the device itself (Daniel Vetter).
- Also explain that fallback in a comment in the code (Daniel Vetter).
- Don't encode in fbmem the assumption that sysfb will always register
  platform devices (Daniel Vetter).
- Add a FIXME comment about drivers registering devices (Daniel Vetter).

 drivers/video/fbdev/core/fbmem.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 0bb459258df3..d6ae33990f40 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1585,18 +1585,35 @@ static void do_remove_conflicting_framebuffers(struct 
apertures_struct *a,
                        if (!device) {
                                pr_warn("fb%d: no device set\n", i);
                                do_unregister_framebuffer(registered_fb[i]);
-                       } else if (dev_is_platform(device)) {
+                       } else {
                                /*
                                 * Drop the lock because if the device is 
unregistered, its
                                 * driver will call to 
unregister_framebuffer(), that takes
                                 * this lock.
                                 */
                                mutex_unlock(&registration_lock);
-                               
platform_device_unregister(to_platform_device(device));
+                               /*
+                                * First attempt the device to be unregistered 
by sysfb.
+                                */
+                               if (!sysfb_try_unregister(device)) {
+                                       if (dev_is_platform(device)) {
+                                               /*
+                                                * FIXME: sysfb didn't register 
this device, the platform
+                                                * device was registered in 
other platform code.
+                                                */
+                                               
platform_device_unregister(to_platform_device(device));
+                                       } else {
+                                               /*
+                                                * If is not a platform device, 
at least print a warning. A
+                                                * fix would add to make the 
code that registered the device
+                                                * to also unregister it.
+                                                */
+                                               pr_warn("fb%d: cannot remove 
device\n", i);
+                                               /* call 
unregister_framebuffer() since the lock was dropped */
+                                               
unregister_framebuffer(registered_fb[i]);
+                                       }
+                               }
                                mutex_lock(&registration_lock);
-                       } else {
-                               pr_warn("fb%d: cannot remove device\n", i);
-                               do_unregister_framebuffer(registered_fb[i]);
                        }
                        /*
                         * Restart the removal loop now that the device has been
-- 
2.35.1

Reply via email to