From: Richard Purdie Date: Sat, 10 Feb 2007 14:10:33 +0000 (+0000) Subject: backlight: Rework backlight/fb interaction simplifying, lots X-Git-Tag: v2.6.21-rc1~52^2~5 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37ce69a57ff217a4ca0871e9ee5aa58c052b7d86;p=linux-2.6 backlight: Rework backlight/fb interaction simplifying, lots fb_info->bl_mutex is badly thought out and the backlight class doesn't need it if the framebuffer/backlight register/unregister order is consistent, particularly after the backlight locking fixes. Fix the drivers to use the order: backlight_device_register() register_framebuffer() unregister_framebuffer() backlight_device_unregister() and turn bl_mutex into a lock for the bl_curve data only. Signed-off-by: Richard Purdie --- diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 1c77cfb8e6..ef3e7861c2 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1697,7 +1697,6 @@ static int __devinit aty128fb_setup(char *options) static struct backlight_properties aty128_bl_data; -/* Call with fb_info->bl_mutex held */ static int aty128_bl_get_level_brightness(struct aty128fb_par *par, int level) { @@ -1705,6 +1704,7 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par, int atylevel; /* Get and convert the value */ + /* No locking of bl_curve since we read a single value */ atylevel = MAX_LEVEL - (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); @@ -1724,8 +1724,7 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par, /* That one prevents proper CRT output with LCD off */ #undef BACKLIGHT_DAC_OFF -/* Call with fb_info->bl_mutex held */ -static int __aty128_bl_update_status(struct backlight_device *bd) +static int aty128_bl_update_status(struct backlight_device *bd) { struct aty128fb_par *par = class_get_devdata(&bd->class_dev); unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); @@ -1778,19 +1777,6 @@ static int __aty128_bl_update_status(struct backlight_device *bd) return 0; } -static int aty128_bl_update_status(struct backlight_device *bd) -{ - struct aty128fb_par *par = class_get_devdata(&bd->class_dev); - struct fb_info *info = pci_get_drvdata(par->pdev); - int ret; - - mutex_lock(&info->bl_mutex); - ret = __aty128_bl_update_status(bd); - mutex_unlock(&info->bl_mutex); - - return ret; -} - static int aty128_bl_get_brightness(struct backlight_device *bd) { return bd->props->brightness; @@ -1804,14 +1790,10 @@ static struct backlight_properties aty128_bl_data = { static void aty128_bl_set_power(struct fb_info *info, int power) { - mutex_lock(&info->bl_mutex); - if (info->bl_dev) { info->bl_dev->props->power = power; - __aty128_bl_update_status(info->bl_dev); + backlight_update_status(info->bl_dev); } - - mutex_unlock(&info->bl_mutex); } static void aty128_bl_init(struct aty128fb_par *par) @@ -1838,12 +1820,10 @@ static void aty128_bl_init(struct aty128fb_par *par) goto error; } - mutex_lock(&info->bl_mutex); info->bl_dev = bd; fb_bl_default_curve(info, 0, 63 * FB_BACKLIGHT_MAX / MAX_LEVEL, 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); - mutex_unlock(&info->bl_mutex); bd->props->brightness = aty128_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; @@ -1864,31 +1844,19 @@ error: return; } -static void aty128_bl_exit(struct aty128fb_par *par) +static void aty128_bl_exit(struct backlight_device *bd) { - struct fb_info *info = pci_get_drvdata(par->pdev); - + if (bd) { #ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); -#endif - - mutex_lock(&info->bl_mutex); - if (info->bl_dev) { -#ifdef CONFIG_PMAC_BACKLIGHT - if (pmac_backlight == info->bl_dev) + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight == bd) pmac_backlight = NULL; + mutex_unlock(&pmac_backlight_mutex); #endif - - backlight_device_unregister(info->bl_dev); - info->bl_dev = NULL; + backlight_device_unregister(bd); printk("aty128: Backlight unloaded\n"); } - mutex_unlock(&info->bl_mutex); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_unlock(&pmac_backlight_mutex); -#endif } #endif /* CONFIG_FB_ATY128_BACKLIGHT */ @@ -2175,11 +2143,12 @@ static void __devexit aty128_remove(struct pci_dev *pdev) par = info->par; + unregister_framebuffer(info); + #ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_exit(par); + aty128_bl_exit(info->bl_dev); #endif - unregister_framebuffer(info); #ifdef CONFIG_MTRR if (par->mtrr.vram_valid) mtrr_del(par->mtrr.vram, info->fix.smem_start, diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 3b65293923..66462286e7 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2116,13 +2116,13 @@ static int atyfb_pci_resume(struct pci_dev *pdev) static struct backlight_properties aty_bl_data; -/* Call with fb_info->bl_mutex held */ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) { struct fb_info *info = pci_get_drvdata(par->pdev); int atylevel; /* Get and convert the value */ + /* No locking of bl_curve since we read a single value */ atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; if (atylevel < 0) @@ -2133,8 +2133,7 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) return atylevel; } -/* Call with fb_info->bl_mutex held */ -static int __aty_bl_update_status(struct backlight_device *bd) +static int aty_bl_update_status(struct backlight_device *bd) { struct atyfb_par *par = class_get_devdata(&bd->class_dev); unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); @@ -2159,19 +2158,6 @@ static int __aty_bl_update_status(struct backlight_device *bd) return 0; } -static int aty_bl_update_status(struct backlight_device *bd) -{ - struct atyfb_par *par = class_get_devdata(&bd->class_dev); - struct fb_info *info = pci_get_drvdata(par->pdev); - int ret; - - mutex_lock(&info->bl_mutex); - ret = __aty_bl_update_status(bd); - mutex_unlock(&info->bl_mutex); - - return ret; -} - static int aty_bl_get_brightness(struct backlight_device *bd) { return bd->props->brightness; @@ -2203,12 +2189,10 @@ static void aty_bl_init(struct atyfb_par *par) goto error; } - mutex_lock(&info->bl_mutex); info->bl_dev = bd; fb_bl_default_curve(info, 0, 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); - mutex_unlock(&info->bl_mutex); bd->props->brightness = aty_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; @@ -2229,30 +2213,19 @@ error: return; } -static void aty_bl_exit(struct atyfb_par *par) +static void aty_bl_exit(struct backlight_device *bd) { - struct fb_info *info = pci_get_drvdata(par->pdev); - + if (bd) { #ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); -#endif - - mutex_lock(&info->bl_mutex); - if (info->bl_dev) { -#ifdef CONFIG_PMAC_BACKLIGHT - if (pmac_backlight == info->bl_dev) + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight == bd) pmac_backlight = NULL; + mutex_unlock(&pmac_backlight_mutex); #endif - - backlight_device_unregister(info->bl_dev); + backlight_device_unregister(bd); printk("aty: Backlight unloaded\n"); } - mutex_unlock(&info->bl_mutex); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_unlock(&pmac_backlight_mutex); -#endif } #endif /* CONFIG_FB_ATY_BACKLIGHT */ @@ -3705,13 +3678,13 @@ static void __devexit atyfb_remove(struct fb_info *info) aty_set_crtc(par, &saved_crtc); par->pll_ops->set_pll(info, &saved_pll); + unregister_framebuffer(info); + #ifdef CONFIG_FB_ATY_BACKLIGHT if (M64_HAS(MOBIL_BUS)) - aty_bl_exit(par); + aty_bl_exit(info->bl_dev); #endif - unregister_framebuffer(info); - #ifdef CONFIG_MTRR if (par->mtrr_reg >= 0) { mtrr_del(par->mtrr_reg, 0, 0); diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c index 9cfcecac8b..f94e461678 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c @@ -29,17 +29,13 @@ struct radeon_bl_privdata { static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata, int level) { - struct fb_info *info = pdata->rinfo->info; int rlevel; - mutex_lock(&info->bl_mutex); - /* Get and convert the value */ + /* No locking of bl_curve since we read a single value */ rlevel = pdata->rinfo->info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL; - mutex_unlock(&info->bl_mutex); - if (rlevel < 0) rlevel = 0; else if (rlevel > MAX_RADEON_LEVEL) @@ -187,12 +183,10 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo) machine_is_compatible("PowerBook6,5"); #endif - mutex_lock(&rinfo->info->bl_mutex); rinfo->info->bl_dev = bd; fb_bl_default_curve(rinfo->info, 0, 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL, 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); - mutex_unlock(&rinfo->info->bl_mutex); bd->props->brightness = radeon_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; @@ -216,29 +210,22 @@ error: void radeonfb_bl_exit(struct radeonfb_info *rinfo) { -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); -#endif + struct backlight_device *bd = rinfo->info->bl_dev; - mutex_lock(&rinfo->info->bl_mutex); - if (rinfo->info->bl_dev) { + if (bd) { struct radeon_bl_privdata *pdata; #ifdef CONFIG_PMAC_BACKLIGHT - if (pmac_backlight == rinfo->info->bl_dev) + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight == bd) pmac_backlight = NULL; + mutex_unlock(&pmac_backlight_mutex); #endif - - pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev); - backlight_device_unregister(rinfo->info->bl_dev); + pdata = class_get_devdata(&bd->class_dev); + backlight_device_unregister(bd); kfree(pdata); rinfo->info->bl_dev = NULL; printk("radeonfb: Backlight unloaded\n"); } - mutex_unlock(&rinfo->info->bl_mutex); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_unlock(&pmac_backlight_mutex); -#endif } diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 0ed577e7cc..7e228aded4 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -2393,7 +2393,6 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev) if (!rinfo) return; - radeonfb_bl_exit(rinfo); radeonfb_pm_exit(rinfo); if (rinfo->mon1_EDID) @@ -2420,6 +2419,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev) unregister_framebuffer(info); + radeonfb_bl_exit(rinfo); + iounmap(rinfo->mmio_base); iounmap(rinfo->fb_base); diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 818fb09105..40c80c8190 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -59,7 +59,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) info->device = dev; #ifdef CONFIG_FB_BACKLIGHT - mutex_init(&info->bl_mutex); + mutex_init(&info->bl_curve_mutex); #endif return info; @@ -445,10 +445,10 @@ static ssize_t store_bl_curve(struct device *device, /* If there has been an error in the input data, we won't * reach this loop. */ - mutex_lock(&fb_info->bl_mutex); + mutex_lock(&fb_info->bl_curve_mutex); for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i) fb_info->bl_curve[i] = tmp_curve[i]; - mutex_unlock(&fb_info->bl_mutex); + mutex_unlock(&fb_info->bl_curve_mutex); return count; } @@ -466,7 +466,7 @@ static ssize_t show_bl_curve(struct device *device, if (!fb_info || !fb_info->bl_dev) return -ENODEV; - mutex_lock(&fb_info->bl_mutex); + mutex_lock(&fb_info->bl_curve_mutex); for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8) len += snprintf(&buf[len], PAGE_SIZE, "%02x %02x %02x %02x %02x %02x %02x %02x\n", @@ -478,7 +478,7 @@ static ssize_t show_bl_curve(struct device *device, fb_info->bl_curve[i + 5], fb_info->bl_curve[i + 6], fb_info->bl_curve[i + 7]); - mutex_unlock(&fb_info->bl_mutex); + mutex_unlock(&fb_info->bl_curve_mutex); return len; } @@ -552,6 +552,8 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max) { unsigned int i, flat, count, range = (max - min); + mutex_lock(&fb_info->bl_curve_mutex); + fb_info->bl_curve[0] = off; for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) @@ -560,6 +562,8 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max) count = FB_BACKLIGHT_LEVELS * 15 / 16; for (i = 0; i < count; ++i) fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count); + + mutex_unlock(&fb_info->bl_curve_mutex); } EXPORT_SYMBOL_GPL(fb_bl_default_curve); #endif diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c index 695b6bf54d..2bebfeeb4f 100644 --- a/drivers/video/nvidia/nv_backlight.c +++ b/drivers/video/nvidia/nv_backlight.c @@ -30,7 +30,6 @@ static struct backlight_properties nvidia_bl_data; -/* Call with fb_info->bl_mutex held */ static int nvidia_bl_get_level_brightness(struct nvidia_par *par, int level) { @@ -38,6 +37,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par, int nlevel; /* Get and convert the value */ + /* No locking of bl_curve since we read a single value */ nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP; if (nlevel < 0) @@ -50,8 +50,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par, return nlevel; } -/* Call with fb_info->bl_mutex held */ -static int __nvidia_bl_update_status(struct backlight_device *bd) +static int nvidia_bl_update_status(struct backlight_device *bd) { struct nvidia_par *par = class_get_devdata(&bd->class_dev); u32 tmp_pcrt, tmp_pmc, fpcontrol; @@ -85,19 +84,6 @@ static int __nvidia_bl_update_status(struct backlight_device *bd) return 0; } -static int nvidia_bl_update_status(struct backlight_device *bd) -{ - struct nvidia_par *par = class_get_devdata(&bd->class_dev); - struct fb_info *info = pci_get_drvdata(par->pci_dev); - int ret; - - mutex_lock(&info->bl_mutex); - ret = __nvidia_bl_update_status(bd); - mutex_unlock(&info->bl_mutex); - - return ret; -} - static int nvidia_bl_get_brightness(struct backlight_device *bd) { return bd->props->brightness; @@ -133,12 +119,10 @@ void nvidia_bl_init(struct nvidia_par *par) goto error; } - mutex_lock(&info->bl_mutex); info->bl_dev = bd; fb_bl_default_curve(info, 0, 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); - mutex_unlock(&info->bl_mutex); bd->props->brightness = nvidia_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; @@ -162,25 +146,17 @@ error: void nvidia_bl_exit(struct nvidia_par *par) { struct fb_info *info = pci_get_drvdata(par->pci_dev); + struct backlight_device *bd = info->bl_dev; + if (bd) { #ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); -#endif - - mutex_lock(&info->bl_mutex); - if (info->bl_dev) { -#ifdef CONFIG_PMAC_BACKLIGHT - if (pmac_backlight == info->bl_dev) + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight == bd) pmac_backlight = NULL; + mutex_unlock(&pmac_backlight_mutex); #endif - - backlight_device_unregister(info->bl_dev); + backlight_device_unregister(bd); printk("nvidia: Backlight unloaded\n"); } - mutex_unlock(&info->bl_mutex); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_unlock(&pmac_backlight_mutex); -#endif } diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 64f59119c4..c18e9557ca 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1350,9 +1350,10 @@ static void __devexit nvidiafb_remove(struct pci_dev *pd) NVTRACE_ENTER(); + unregister_framebuffer(info); + nvidia_bl_exit(par); - unregister_framebuffer(info); #ifdef CONFIG_MTRR if (par->mtrr.vram_valid) mtrr_del(par->mtrr.vram, info->fix.smem_start, diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 9e7d3fcde2..ab00350907 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -282,7 +282,6 @@ static const struct riva_regs reg_template = { static struct backlight_properties riva_bl_data; -/* Call with fb_info->bl_mutex held */ static int riva_bl_get_level_brightness(struct riva_par *par, int level) { @@ -290,6 +289,7 @@ static int riva_bl_get_level_brightness(struct riva_par *par, int nlevel; /* Get and convert the value */ + /* No locking on bl_curve since accessing a single value */ nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP; if (nlevel < 0) @@ -302,8 +302,7 @@ static int riva_bl_get_level_brightness(struct riva_par *par, return nlevel; } -/* Call with fb_info->bl_mutex held */ -static int __riva_bl_update_status(struct backlight_device *bd) +static int riva_bl_update_status(struct backlight_device *bd) { struct riva_par *par = class_get_devdata(&bd->class_dev); U032 tmp_pcrt, tmp_pmc; @@ -328,19 +327,6 @@ static int __riva_bl_update_status(struct backlight_device *bd) return 0; } -static int riva_bl_update_status(struct backlight_device *bd) -{ - struct riva_par *par = class_get_devdata(&bd->class_dev); - struct fb_info *info = pci_get_drvdata(par->pdev); - int ret; - - mutex_lock(&info->bl_mutex); - ret = __riva_bl_update_status(bd); - mutex_unlock(&info->bl_mutex); - - return ret; -} - static int riva_bl_get_brightness(struct backlight_device *bd) { return bd->props->brightness; @@ -376,12 +362,10 @@ static void riva_bl_init(struct riva_par *par) goto error; } - mutex_lock(&info->bl_mutex); info->bl_dev = bd; fb_bl_default_curve(info, 0, MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL, FB_BACKLIGHT_MAX); - mutex_unlock(&info->bl_mutex); bd->props->brightness = riva_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; @@ -402,34 +386,25 @@ error: return; } -static void riva_bl_exit(struct riva_par *par) +static void riva_bl_exit(struct fb_info *info) { - struct fb_info *info = pci_get_drvdata(par->pdev); + struct backlight_device *bd = info->bl_dev; + if (bd) { #ifdef CONFIG_PMAC_BACKLIGHT - mutex_lock(&pmac_backlight_mutex); -#endif - - mutex_lock(&info->bl_mutex); - if (info->bl_dev) { -#ifdef CONFIG_PMAC_BACKLIGHT - if (pmac_backlight == info->bl_dev) + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight == bd) pmac_backlight = NULL; + mutex_unlock(&pmac_backlight_mutex); #endif - - backlight_device_unregister(info->bl_dev); + backlight_device_unregister(bd); printk("riva: Backlight unloaded\n"); } - mutex_unlock(&info->bl_mutex); - -#ifdef CONFIG_PMAC_BACKLIGHT - mutex_unlock(&pmac_backlight_mutex); -#endif } #else static inline void riva_bl_init(struct riva_par *par) {} -static inline void riva_bl_exit(struct riva_par *par) {} +static inline void riva_bl_exit(struct fb_info *info) {} #endif /* CONFIG_FB_RIVA_BACKLIGHT */ /* ------------------------------------------------------------------------- * @@ -2146,14 +2121,15 @@ static void __exit rivafb_remove(struct pci_dev *pd) NVTRACE_ENTER(); - riva_bl_exit(par); - #ifdef CONFIG_FB_RIVA_I2C riva_delete_i2c_busses(par); kfree(par->EDID); #endif unregister_framebuffer(info); + + riva_bl_exit(info); + #ifdef CONFIG_MTRR if (par->mtrr.vram_valid) mtrr_del(par->mtrr.vram, info->fix.smem_start, diff --git a/include/linux/fb.h b/include/linux/fb.h index bf7158b59b..be913ec871 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -769,16 +769,13 @@ struct fb_info { struct fb_videomode *mode; /* current mode */ #ifdef CONFIG_FB_BACKLIGHT - /* Lock ordering: - * bl_mutex (protects bl_dev and bl_curve) - * bl_dev->sem (backlight class) - */ - struct mutex bl_mutex; - /* assigned backlight device */ + /* set before framebuffer registration, + remove after unregister */ struct backlight_device *bl_dev; /* Backlight level curve */ + struct mutex bl_curve_mutex; u8 bl_curve[FB_BACKLIGHT_LEVELS]; #endif