@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
+#include <linux/sysfb.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/vt.h>
@@ -1582,22 +1583,30 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
* this lock.
*/
mutex_unlock(®istration_lock);
- if (dev_is_platform(device)) {
- platform_device_unregister(to_platform_device(device));
- } else {
- /*
- * If it's not a platform device, at least print a warning. A
- * fix would add to code to remove the device from the system.
- */
- pr_warn("fb%d: cannot remove device\n", i);
- /* call unregister_framebuffer() so it can take the lock */
- unregister_framebuffer(registered_fb[i]);
+ if (!sysfb_try_unregister(device)) {
+ if (dev_is_platform(device)) {
+ /*
+ * FIXME: sysfb didn't register this device, is a platform
+ * device registered by a video driver (e.g: vga16fb), so
+ * force its unregistration here. A proper fix would be to
+ * move all device registration to the sysfb infrastructure.
+ */
+ platform_device_unregister(to_platform_device(device));
+ } else {
+ /*
+ * If it's not a platform device, at least print a warning. A
+ * fix would add to code to remove the device from the system.
+ */
+ pr_warn("fb%d: cannot remove device\n", i);
+ /* call unregister_framebuffer() so it can take the lock */
+ unregister_framebuffer(registered_fb[i]);
+ }
}
- mutex_lock(®istration_lock);
/*
* Restart the removal loop now that the device has been
* unregistered and its associated framebuffer gone.
*/
+ mutex_lock(®istration_lock);
goto restart_removal;
}
}
@@ -1758,6 +1767,17 @@ int remove_conflicting_framebuffers(struct apertures_struct *a,
do_free = true;
}
+ /*
+ * If a driver asked to unregister a platform device registered by
+ * sysfb, then can be assumed that this is a driver for a display
+ * that is set up by the system firmware and has a generic driver.
+ *
+ * Drivers for devices that don't have a generic driver will never
+ * ask for this, so let's assume that a real driver for the display
+ * was already probed and prevent sysfb to register devices later.
+ */
+ sysfb_disable();
+
mutex_lock(®istration_lock);
do_remove_conflicting_framebuffers(a, name, primary);
mutex_unlock(®istration_lock);