Commit 15fced5b authored by Thomas Zimmermann's avatar Thomas Zimmermann

fbdev: Remove conflict-handling code

Remove the call to do_remove_conflicting_framebuffers() from the
framebuffer registration. Aperture helpers take care of removing
conflicting devices. With all ownership information stored in the
aperture datastrcutures, remove remove_conflicting_framebuffers()
entirely.

This change also rectifies DRM generic-framebuffer registration, which
tried to unregister conflicting framebuffers, even though it's entirely
build on top of DRM.

v2:
	* remove internal aperture-overlap helpers, which are
	  now unused
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-12-tzimmermann@suse.de
parent 72a6a3e0
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#include <linux/aperture.h> #include <linux/aperture.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/fb.h> /* for old fbdev helpers */
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -286,11 +285,6 @@ static void aperture_detach_devices(resource_size_t base, resource_size_t size) ...@@ -286,11 +285,6 @@ static void aperture_detach_devices(resource_size_t base, resource_size_t size)
int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size,
bool primary, const char *name) bool primary, const char *name)
{ {
#if IS_REACHABLE(CONFIG_FB)
struct apertures_struct *a;
int ret;
#endif
/* /*
* If a driver asked to unregister a platform device registered by * If a driver asked to unregister a platform device registered by
* sysfb, then can be assumed that this is a driver for a display * sysfb, then can be assumed that this is a driver for a display
...@@ -312,21 +306,6 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si ...@@ -312,21 +306,6 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si
if (primary) if (primary)
aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE); aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE);
#if IS_REACHABLE(CONFIG_FB)
a = alloc_apertures(1);
if (!a)
return -ENOMEM;
a->ranges[0].base = base;
a->ranges[0].size = size;
ret = remove_conflicting_framebuffers(a, name, primary);
kfree(a);
if (ret)
return ret;
#endif
return 0; return 0;
} }
EXPORT_SYMBOL(aperture_remove_conflicting_devices); EXPORT_SYMBOL(aperture_remove_conflicting_devices);
......
...@@ -1526,102 +1526,6 @@ static int fb_check_foreignness(struct fb_info *fi) ...@@ -1526,102 +1526,6 @@ static int fb_check_foreignness(struct fb_info *fi)
return 0; return 0;
} }
static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
{
/* is the generic aperture base the same as the HW one */
if (gen->base == hw->base)
return true;
/* is the generic aperture base inside the hw base->hw base+size */
if (gen->base > hw->base && gen->base < hw->base + hw->size)
return true;
return false;
}
static bool fb_do_apertures_overlap(struct apertures_struct *gena,
struct apertures_struct *hwa)
{
int i, j;
if (!hwa || !gena)
return false;
for (i = 0; i < hwa->count; ++i) {
struct aperture *h = &hwa->ranges[i];
for (j = 0; j < gena->count; ++j) {
struct aperture *g = &gena->ranges[j];
printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
(unsigned long long)g->base,
(unsigned long long)g->size,
(unsigned long long)h->base,
(unsigned long long)h->size);
if (apertures_overlap(g, h))
return true;
}
}
return false;
}
static void do_unregister_framebuffer(struct fb_info *fb_info);
static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{
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;
struct device *device;
if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
continue;
gen_aper = registered_fb[i]->apertures;
device = registered_fb[i]->device;
if (fb_do_apertures_overlap(gen_aper, a) ||
(primary && gen_aper && gen_aper->count &&
gen_aper->ranges[0].base == VGA_FB_PHYS_BASE)) {
printk(KERN_INFO "fb%d: switching to %s from %s\n",
i, name, registered_fb[i]->fix.id);
/*
* If we kick-out a firmware driver, we also want to remove
* the underlying platform device, such as simple-framebuffer,
* VESA, EFI, etc. A native driver will then be able to
* allocate the memory range.
*
* If it's not a platform device, at least print a warning. A
* fix would add code to remove the device from the system. For
* framebuffers without any Linux device, print a warning as
* well.
*/
if (!device) {
pr_warn("fb%d: no device set\n", i);
do_unregister_framebuffer(registered_fb[i]);
} else if (dev_is_platform(device)) {
/*
* 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;
}
}
}
static int do_register_framebuffer(struct fb_info *fb_info) static int do_register_framebuffer(struct fb_info *fb_info)
{ {
int i; int i;
...@@ -1630,10 +1534,6 @@ static int do_register_framebuffer(struct fb_info *fb_info) ...@@ -1630,10 +1534,6 @@ static int do_register_framebuffer(struct fb_info *fb_info)
if (fb_check_foreignness(fb_info)) if (fb_check_foreignness(fb_info))
return -ENOSYS; return -ENOSYS;
do_remove_conflicting_framebuffers(fb_info->apertures,
fb_info->fix.id,
fb_is_primary_device(fb_info));
if (num_registered_fb == FB_MAX) if (num_registered_fb == FB_MAX)
return -ENXIO; return -ENXIO;
...@@ -1778,42 +1678,6 @@ static int fb_aperture_acquire_for_platform_device(struct fb_info *fb_info) ...@@ -1778,42 +1678,6 @@ static int fb_aperture_acquire_for_platform_device(struct fb_info *fb_info)
return ret; return ret;
} }
/**
* remove_conflicting_framebuffers - remove firmware-configured framebuffers
* @a: memory range, users of which are to be removed
* @name: requesting driver name
* @primary: also kick vga16fb if present
*
* This function removes framebuffer devices (initialized by firmware/bootloader)
* which use memory range described by @a. If @a is NULL all such devices are
* removed.
*/
int remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{
bool do_free = false;
if (!a) {
a = alloc_apertures(1);
if (!a)
return -ENOMEM;
a->ranges[0].base = 0;
a->ranges[0].size = ~0;
do_free = true;
}
mutex_lock(&registration_lock);
do_remove_conflicting_framebuffers(a, name, primary);
mutex_unlock(&registration_lock);
if (do_free)
kfree(a);
return 0;
}
EXPORT_SYMBOL(remove_conflicting_framebuffers);
/** /**
* register_framebuffer - registers a frame buffer device * register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure * @fb_info: frame buffer info structure
......
...@@ -615,8 +615,6 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, ...@@ -615,8 +615,6 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
/* drivers/video/fbmem.c */ /* drivers/video/fbmem.c */
extern int register_framebuffer(struct fb_info *fb_info); extern int register_framebuffer(struct fb_info *fb_info);
extern void unregister_framebuffer(struct fb_info *fb_info); extern void unregister_framebuffer(struct fb_info *fb_info);
extern int remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary);
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern int fb_show_logo(struct fb_info *fb_info, int rotate);
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment