Message ID | 1387473881-26179-1-git-send-email-dh.herrmann@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
* David Herrmann <dh.herrmann@gmail.com> wrote: > +/* > + * Unregister the sysfb and prevent new sysfbs from getting registered. Can be > + * called from any context except recursively or from sysfb_register(). > + * Used by remove_conflicting_framebuffers() and friends. > + */ > +void sysfb_unregister(const struct apertures_struct *apert, bool primary) > +{ > + mutex_lock(&sysfb_lock); > + if (!IS_ERR(sysfb_dev) && sysfb_dev) { > + if (sysfb_match(apert, primary)) { > + platform_device_unregister(sysfb_dev); > + sysfb_dev = ERR_PTR(-EALREADY); > + } > + } else { > + /* if !sysfb_dev, set err so no new sysfb is probed later */ > + sysfb_dev = ERR_PTR(-EALREADY); Just a small detail: we can get into this 'else' branch not just with NULL, but also with IS_ERR(sysfb_dev). In that case we override whatever error code is contained in sysfb_dev and overwrite it with ERR_PTR(-EALREADY). (Probably not a big deal, because we don't actually ever seem to extract the error code from the pointer, but wanted to mention it.) > +#ifdef CONFIG_X86_SYSFB > +#include <asm/sysfb.h> > +#endif Pet peeve, this looks sexier: #ifdef CONFIG_X86_SYSFB # include <asm/sysfb.h> #endif > @@ -1604,6 +1607,17 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a, > } > } > > +static void remove_conflicting_sysfb(const struct apertures_struct *apert, > + bool primary) > +{ > + if (!apert) > + return; > + > +#ifdef CONFIG_X86_SYSFB > + sysfb_unregister(apert, primary); > +#endif > +} So why not make sysfb_unregister() accept a !apert parameter (it would simply return), at which point remove_conflicting_sysfb() could be eliminated and just be replaced with a direct sysfb_unregister() call - with no #ifdefs. We only need #ifdefs for the sysfb_unregister() declaration in the .h file. At first sight this looks simpler and cleaner for the fix itself - no need for extra cleanups for this detail. Thanks, Ingo -- To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi On Thu, Dec 19, 2013 at 7:33 PM, Ingo Molnar <mingo@kernel.org> wrote: > > * David Herrmann <dh.herrmann@gmail.com> wrote: > >> +/* >> + * Unregister the sysfb and prevent new sysfbs from getting registered. Can be >> + * called from any context except recursively or from sysfb_register(). >> + * Used by remove_conflicting_framebuffers() and friends. >> + */ >> +void sysfb_unregister(const struct apertures_struct *apert, bool primary) >> +{ >> + mutex_lock(&sysfb_lock); >> + if (!IS_ERR(sysfb_dev) && sysfb_dev) { >> + if (sysfb_match(apert, primary)) { >> + platform_device_unregister(sysfb_dev); >> + sysfb_dev = ERR_PTR(-EALREADY); >> + } >> + } else { >> + /* if !sysfb_dev, set err so no new sysfb is probed later */ >> + sysfb_dev = ERR_PTR(-EALREADY); > > Just a small detail: we can get into this 'else' branch not just with > NULL, but also with IS_ERR(sysfb_dev). In that case we override > whatever error code is contained in sysfb_dev and overwrite it with > ERR_PTR(-EALREADY). > > (Probably not a big deal, because we don't actually ever seem to > extract the error code from the pointer, but wanted to mention it.) Yepp, I know, but that's just fine. >> +#ifdef CONFIG_X86_SYSFB >> +#include <asm/sysfb.h> >> +#endif > > Pet peeve, this looks sexier: > > #ifdef CONFIG_X86_SYSFB > # include <asm/sysfb.h> > #endif > >> @@ -1604,6 +1607,17 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a, >> } >> } >> >> +static void remove_conflicting_sysfb(const struct apertures_struct *apert, >> + bool primary) >> +{ >> + if (!apert) >> + return; >> + >> +#ifdef CONFIG_X86_SYSFB >> + sysfb_unregister(apert, primary); >> +#endif >> +} > > So why not make sysfb_unregister() accept a !apert parameter (it would > simply return), at which point remove_conflicting_sysfb() could be > eliminated and just be replaced with a direct sysfb_unregister() call > - with no #ifdefs. > > We only need #ifdefs for the sysfb_unregister() declaration in the .h > file. I can do that but we still need the #ifdef. sysfb is an x86-asm header so it's not available on other archs. Even with #ifdef in the header I still need it around the actual function call. Thanks David > At first sight this looks simpler and cleaner for the fix itself - no > need for extra cleanups for this detail. > > Thanks, > > Ingo -- To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/x86/include/asm/sysfb.h b/arch/x86/include/asm/sysfb.h index 2aeb3e2..0877cf1 100644 --- a/arch/x86/include/asm/sysfb.h +++ b/arch/x86/include/asm/sysfb.h @@ -11,6 +11,7 @@ * any later version. */ +#include <linux/fb.h> #include <linux/kernel.h> #include <linux/platform_data/simplefb.h> #include <linux/screen_info.h> @@ -59,6 +60,11 @@ struct efifb_dmi_info { int flags; }; +int __init sysfb_register(const char *name, int id, + const struct resource *res, unsigned int res_num, + const void *data, size_t data_size); +void sysfb_unregister(const struct apertures_struct *apert, bool primary); + #ifdef CONFIG_EFI extern struct efifb_dmi_info efifb_dmi_list[]; diff --git a/arch/x86/kernel/sysfb.c b/arch/x86/kernel/sysfb.c index 193ec2c..882dc7c 100644 --- a/arch/x86/kernel/sysfb.c +++ b/arch/x86/kernel/sysfb.c @@ -33,11 +33,79 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/mm.h> +#include <linux/mutex.h> #include <linux/platform_data/simplefb.h> #include <linux/platform_device.h> #include <linux/screen_info.h> #include <asm/sysfb.h> +static DEFINE_MUTEX(sysfb_lock); +static struct platform_device *sysfb_dev; + +int __init sysfb_register(const char *name, int id, + const struct resource *res, unsigned int res_num, + const void *data, size_t data_size) +{ + struct platform_device *pd; + int ret = 0; + + mutex_lock(&sysfb_lock); + if (!sysfb_dev) { + pd = platform_device_register_resndata(NULL, name, id, + res, res_num, + data, data_size); + if (IS_ERR(pd)) + ret = PTR_ERR(pd); + else + sysfb_dev = pd; + } + mutex_unlock(&sysfb_lock); + + return ret; +} + +static bool sysfb_match(const struct apertures_struct *apert, bool primary) +{ + struct screen_info *si = &screen_info; + unsigned int i; + const struct aperture *a; + + if (!apert || primary) + return true; + + for (i = 0; i < apert->count; ++i) { + a = &apert->ranges[i]; + if (a->base >= si->lfb_base && + a->base < si->lfb_base + ((u64)si->lfb_size << 16)) + return true; + if (si->lfb_base >= a->base && + si->lfb_base < a->base + a->size) + return true; + } + + return false; +} + +/* + * Unregister the sysfb and prevent new sysfbs from getting registered. Can be + * called from any context except recursively or from sysfb_register(). + * Used by remove_conflicting_framebuffers() and friends. + */ +void sysfb_unregister(const struct apertures_struct *apert, bool primary) +{ + mutex_lock(&sysfb_lock); + if (!IS_ERR(sysfb_dev) && sysfb_dev) { + if (sysfb_match(apert, primary)) { + platform_device_unregister(sysfb_dev); + sysfb_dev = ERR_PTR(-EALREADY); + } + } else { + /* if !sysfb_dev, set err so no new sysfb is probed later */ + sysfb_dev = ERR_PTR(-EALREADY); + } + mutex_unlock(&sysfb_lock); +} + static __init int sysfb_init(void) { struct screen_info *si = &screen_info; diff --git a/arch/x86/kernel/sysfb_simplefb.c b/arch/x86/kernel/sysfb_simplefb.c index 86179d4..a760d47 100644 --- a/arch/x86/kernel/sysfb_simplefb.c +++ b/arch/x86/kernel/sysfb_simplefb.c @@ -64,7 +64,6 @@ __init bool parse_mode(const struct screen_info *si, __init int create_simplefb(const struct screen_info *si, const struct simplefb_platform_data *mode) { - struct platform_device *pd; struct resource res; unsigned long len; @@ -86,10 +85,6 @@ __init int create_simplefb(const struct screen_info *si, if (res.end <= res.start) return -EINVAL; - pd = platform_device_register_resndata(NULL, "simple-framebuffer", 0, - &res, 1, mode, sizeof(*mode)); - if (IS_ERR(pd)) - return PTR_ERR(pd); - - return 0; + return sysfb_register("simple-framebuffer", 0, &res, 1, mode, + sizeof(*mode)); } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 010d191..7dc0491 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -35,6 +35,9 @@ #include <asm/fb.h> +#ifdef CONFIG_X86_SYSFB +#include <asm/sysfb.h> +#endif /* * Frame buffer device initialization and setup routines @@ -1604,6 +1607,17 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a, } } +static void remove_conflicting_sysfb(const struct apertures_struct *apert, + bool primary) +{ + if (!apert) + return; + +#ifdef CONFIG_X86_SYSFB + sysfb_unregister(apert, primary); +#endif +} + static int do_register_framebuffer(struct fb_info *fb_info) { int i; @@ -1742,6 +1756,8 @@ EXPORT_SYMBOL(unlink_framebuffer); void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name, bool primary) { + remove_conflicting_sysfb(a, primary); + mutex_lock(®istration_lock); do_remove_conflicting_framebuffers(a, name, primary); mutex_unlock(®istration_lock); @@ -1762,6 +1778,9 @@ register_framebuffer(struct fb_info *fb_info) { int ret; + remove_conflicting_sysfb(fb_info->apertures, + fb_is_primary_device(fb_info)); + mutex_lock(®istration_lock); ret = do_register_framebuffer(fb_info); mutex_unlock(®istration_lock); diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c index 210f3a0..9f4a0cf 100644 --- a/drivers/video/simplefb.c +++ b/drivers/video/simplefb.c @@ -209,14 +209,6 @@ static int simplefb_probe(struct platform_device *pdev) info->var.blue = params.format->blue; info->var.transp = params.format->transp; - info->apertures = alloc_apertures(1); - if (!info->apertures) { - framebuffer_release(info); - return -ENOMEM; - } - info->apertures->ranges[0].base = info->fix.smem_start; - info->apertures->ranges[0].size = info->fix.smem_len; - info->fbops = &simplefb_ops; info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE; info->screen_base = ioremap_wc(info->fix.smem_start,