Backmerge tag 'v5.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds...
[linux-2.6-microblaze.git] / drivers / video / fbdev / core / fbmem.c
index 7ee6eb2..02b0cf2 100644 (file)
@@ -1568,6 +1568,7 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
 {
        int i;
 
+restart_removal:
        /* check all firmware fbs and kick off if the base addr overlaps */
        for_each_registered_fb(i) {
                struct apertures_struct *gen_aper;
@@ -1600,12 +1601,23 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
                                pr_warn("fb%d: no device set\n", i);
                                do_unregister_framebuffer(registered_fb[i]);
                        } else if (dev_is_platform(device)) {
-                               registered_fb[i]->forced_out = true;
+                               /*
+                                * 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));
+                               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
+                        * unregistered and its associated framebuffer gone.
+                        */
+                       goto restart_removal;
                }
        }
 }
@@ -1876,13 +1888,9 @@ EXPORT_SYMBOL(register_framebuffer);
 void
 unregister_framebuffer(struct fb_info *fb_info)
 {
-       bool forced_out = fb_info->forced_out;
-
-       if (!forced_out)
-               mutex_lock(&registration_lock);
+       mutex_lock(&registration_lock);
        do_unregister_framebuffer(fb_info);
-       if (!forced_out)
-               mutex_unlock(&registration_lock);
+       mutex_unlock(&registration_lock);
 }
 EXPORT_SYMBOL(unregister_framebuffer);