forked from Minki/linux
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: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220718072322.8927-12-tzimmermann@suse.de
This commit is contained in:
parent
72a6a3e03b
commit
15fced5b05
@ -2,7 +2,6 @@
|
||||
|
||||
#include <linux/aperture.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fb.h> /* for old fbdev helpers */
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pci.h>
|
||||
@ -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,
|
||||
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
|
||||
* 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
|
||||
if (primary)
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL(aperture_remove_conflicting_devices);
|
||||
|
@ -1526,102 +1526,6 @@ static int fb_check_foreignness(struct fb_info *fi)
|
||||
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(®istration_lock);
|
||||
platform_device_unregister(to_platform_device(device));
|
||||
mutex_lock(®istration_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)
|
||||
{
|
||||
int i;
|
||||
@ -1630,10 +1534,6 @@ static int do_register_framebuffer(struct fb_info *fb_info)
|
||||
if (fb_check_foreignness(fb_info))
|
||||
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)
|
||||
return -ENXIO;
|
||||
|
||||
@ -1778,42 +1678,6 @@ static int fb_aperture_acquire_for_platform_device(struct fb_info *fb_info)
|
||||
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(®istration_lock);
|
||||
do_remove_conflicting_framebuffers(a, name, primary);
|
||||
mutex_unlock(®istration_lock);
|
||||
|
||||
if (do_free)
|
||||
kfree(a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(remove_conflicting_framebuffers);
|
||||
|
||||
/**
|
||||
* register_framebuffer - registers a frame buffer device
|
||||
* @fb_info: frame buffer info structure
|
||||
|
@ -615,8 +615,6 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
|
||||
/* drivers/video/fbmem.c */
|
||||
extern int register_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_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);
|
||||
|
Loading…
Reference in New Issue
Block a user