diff options
author | Dave Airlie <airlied@redhat.com> | 2013-02-07 21:10:18 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-02-07 21:10:18 -0500 |
commit | 6dc1c49da6dd3bf020a66b2a135b9625ac01c2c7 (patch) | |
tree | 38a6c5d4896de01449e9d224088ae223161fcd3c /drivers/video | |
parent | cd17ef4114ad5c514b17e6a0bb02a309ab90b692 (diff) | |
parent | 5845b81bdad374f98f809a658ec747d92c9595c4 (diff) |
Merge branch 'fbcon-locking-fixes' of ssh://people.freedesktop.org/~airlied/linux into drm-next
This pulls in most of Linus tree up to -rc6, this fixes the worst lockdep
reported issues and re-enables fbcon lockdep.
(not the fbcon maintainer)
* 'fbcon-locking-fixes' of ssh://people.freedesktop.org/~airlied/linux: (529 commits)
Revert "Revert "console: implement lockdep support for console_lock""
fbcon: fix locking harder
fb: Yet another band-aid for fixing lockdep mess
fb: rework locking to fix lock ordering on takeover
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/console/fbcon.c | 44 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 11 | ||||
-rw-r--r-- | drivers/video/fbsysfs.c | 3 | ||||
-rw-r--r-- | drivers/video/imxfb.c | 13 |
4 files changed, 61 insertions, 10 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index fdefa8fd72c4..2e2d959acae6 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -529,6 +529,33 @@ static int search_for_mapped_con(void) | |||
529 | return retval; | 529 | return retval; |
530 | } | 530 | } |
531 | 531 | ||
532 | static int do_fbcon_takeover(int show_logo) | ||
533 | { | ||
534 | int err, i; | ||
535 | |||
536 | if (!num_registered_fb) | ||
537 | return -ENODEV; | ||
538 | |||
539 | if (!show_logo) | ||
540 | logo_shown = FBCON_LOGO_DONTSHOW; | ||
541 | |||
542 | for (i = first_fb_vc; i <= last_fb_vc; i++) | ||
543 | con2fb_map[i] = info_idx; | ||
544 | |||
545 | err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc, | ||
546 | fbcon_is_default); | ||
547 | |||
548 | if (err) { | ||
549 | for (i = first_fb_vc; i <= last_fb_vc; i++) | ||
550 | con2fb_map[i] = -1; | ||
551 | info_idx = -1; | ||
552 | } else { | ||
553 | fbcon_has_console_bind = 1; | ||
554 | } | ||
555 | |||
556 | return err; | ||
557 | } | ||
558 | |||
532 | static int fbcon_takeover(int show_logo) | 559 | static int fbcon_takeover(int show_logo) |
533 | { | 560 | { |
534 | int err, i; | 561 | int err, i; |
@@ -815,6 +842,8 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, | |||
815 | * | 842 | * |
816 | * Maps a virtual console @unit to a frame buffer device | 843 | * Maps a virtual console @unit to a frame buffer device |
817 | * @newidx. | 844 | * @newidx. |
845 | * | ||
846 | * This should be called with the console lock held. | ||
818 | */ | 847 | */ |
819 | static int set_con2fb_map(int unit, int newidx, int user) | 848 | static int set_con2fb_map(int unit, int newidx, int user) |
820 | { | 849 | { |
@@ -832,7 +861,7 @@ static int set_con2fb_map(int unit, int newidx, int user) | |||
832 | 861 | ||
833 | if (!search_for_mapped_con() || !con_is_bound(&fb_con)) { | 862 | if (!search_for_mapped_con() || !con_is_bound(&fb_con)) { |
834 | info_idx = newidx; | 863 | info_idx = newidx; |
835 | return fbcon_takeover(0); | 864 | return do_fbcon_takeover(0); |
836 | } | 865 | } |
837 | 866 | ||
838 | if (oldidx != -1) | 867 | if (oldidx != -1) |
@@ -840,7 +869,6 @@ static int set_con2fb_map(int unit, int newidx, int user) | |||
840 | 869 | ||
841 | found = search_fb_in_map(newidx); | 870 | found = search_fb_in_map(newidx); |
842 | 871 | ||
843 | console_lock(); | ||
844 | con2fb_map[unit] = newidx; | 872 | con2fb_map[unit] = newidx; |
845 | if (!err && !found) | 873 | if (!err && !found) |
846 | err = con2fb_acquire_newinfo(vc, info, unit, oldidx); | 874 | err = con2fb_acquire_newinfo(vc, info, unit, oldidx); |
@@ -867,7 +895,6 @@ static int set_con2fb_map(int unit, int newidx, int user) | |||
867 | if (!search_fb_in_map(info_idx)) | 895 | if (!search_fb_in_map(info_idx)) |
868 | info_idx = newidx; | 896 | info_idx = newidx; |
869 | 897 | ||
870 | console_unlock(); | ||
871 | return err; | 898 | return err; |
872 | } | 899 | } |
873 | 900 | ||
@@ -2977,7 +3004,7 @@ static int fbcon_unbind(void) | |||
2977 | { | 3004 | { |
2978 | int ret; | 3005 | int ret; |
2979 | 3006 | ||
2980 | ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, | 3007 | ret = do_unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, |
2981 | fbcon_is_default); | 3008 | fbcon_is_default); |
2982 | 3009 | ||
2983 | if (!ret) | 3010 | if (!ret) |
@@ -2992,6 +3019,7 @@ static inline int fbcon_unbind(void) | |||
2992 | } | 3019 | } |
2993 | #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ | 3020 | #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ |
2994 | 3021 | ||
3022 | /* called with console_lock held */ | ||
2995 | static int fbcon_fb_unbind(int idx) | 3023 | static int fbcon_fb_unbind(int idx) |
2996 | { | 3024 | { |
2997 | int i, new_idx = -1, ret = 0; | 3025 | int i, new_idx = -1, ret = 0; |
@@ -3018,6 +3046,7 @@ static int fbcon_fb_unbind(int idx) | |||
3018 | return ret; | 3046 | return ret; |
3019 | } | 3047 | } |
3020 | 3048 | ||
3049 | /* called with console_lock held */ | ||
3021 | static int fbcon_fb_unregistered(struct fb_info *info) | 3050 | static int fbcon_fb_unregistered(struct fb_info *info) |
3022 | { | 3051 | { |
3023 | int i, idx; | 3052 | int i, idx; |
@@ -3050,11 +3079,12 @@ static int fbcon_fb_unregistered(struct fb_info *info) | |||
3050 | primary_device = -1; | 3079 | primary_device = -1; |
3051 | 3080 | ||
3052 | if (!num_registered_fb) | 3081 | if (!num_registered_fb) |
3053 | unregister_con_driver(&fb_con); | 3082 | do_unregister_con_driver(&fb_con); |
3054 | 3083 | ||
3055 | return 0; | 3084 | return 0; |
3056 | } | 3085 | } |
3057 | 3086 | ||
3087 | /* called with console_lock held */ | ||
3058 | static void fbcon_remap_all(int idx) | 3088 | static void fbcon_remap_all(int idx) |
3059 | { | 3089 | { |
3060 | int i; | 3090 | int i; |
@@ -3099,6 +3129,7 @@ static inline void fbcon_select_primary(struct fb_info *info) | |||
3099 | } | 3129 | } |
3100 | #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ | 3130 | #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ |
3101 | 3131 | ||
3132 | /* called with console_lock held */ | ||
3102 | static int fbcon_fb_registered(struct fb_info *info) | 3133 | static int fbcon_fb_registered(struct fb_info *info) |
3103 | { | 3134 | { |
3104 | int ret = 0, i, idx; | 3135 | int ret = 0, i, idx; |
@@ -3115,7 +3146,7 @@ static int fbcon_fb_registered(struct fb_info *info) | |||
3115 | } | 3146 | } |
3116 | 3147 | ||
3117 | if (info_idx != -1) | 3148 | if (info_idx != -1) |
3118 | ret = fbcon_takeover(1); | 3149 | ret = do_fbcon_takeover(1); |
3119 | } else { | 3150 | } else { |
3120 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | 3151 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
3121 | if (con2fb_map_boot[i] == idx) | 3152 | if (con2fb_map_boot[i] == idx) |
@@ -3251,6 +3282,7 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3251 | ret = fbcon_fb_unregistered(info); | 3282 | ret = fbcon_fb_unregistered(info); |
3252 | break; | 3283 | break; |
3253 | case FB_EVENT_SET_CONSOLE_MAP: | 3284 | case FB_EVENT_SET_CONSOLE_MAP: |
3285 | /* called with console lock held */ | ||
3254 | con2fb = event->data; | 3286 | con2fb = event->data; |
3255 | ret = set_con2fb_map(con2fb->console - 1, | 3287 | ret = set_con2fb_map(con2fb->console - 1, |
3256 | con2fb->framebuffer, 1); | 3288 | con2fb->framebuffer, 1); |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 3ff0105a496a..dc61c12ecf8c 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1177,8 +1177,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1177 | event.data = &con2fb; | 1177 | event.data = &con2fb; |
1178 | if (!lock_fb_info(info)) | 1178 | if (!lock_fb_info(info)) |
1179 | return -ENODEV; | 1179 | return -ENODEV; |
1180 | console_lock(); | ||
1180 | event.info = info; | 1181 | event.info = info; |
1181 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); | 1182 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); |
1183 | console_unlock(); | ||
1182 | unlock_fb_info(info); | 1184 | unlock_fb_info(info); |
1183 | break; | 1185 | break; |
1184 | case FBIOBLANK: | 1186 | case FBIOBLANK: |
@@ -1650,7 +1652,9 @@ static int do_register_framebuffer(struct fb_info *fb_info) | |||
1650 | event.info = fb_info; | 1652 | event.info = fb_info; |
1651 | if (!lock_fb_info(fb_info)) | 1653 | if (!lock_fb_info(fb_info)) |
1652 | return -ENODEV; | 1654 | return -ENODEV; |
1655 | console_lock(); | ||
1653 | fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); | 1656 | fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); |
1657 | console_unlock(); | ||
1654 | unlock_fb_info(fb_info); | 1658 | unlock_fb_info(fb_info); |
1655 | return 0; | 1659 | return 0; |
1656 | } | 1660 | } |
@@ -1666,8 +1670,10 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) | |||
1666 | 1670 | ||
1667 | if (!lock_fb_info(fb_info)) | 1671 | if (!lock_fb_info(fb_info)) |
1668 | return -ENODEV; | 1672 | return -ENODEV; |
1673 | console_lock(); | ||
1669 | event.info = fb_info; | 1674 | event.info = fb_info; |
1670 | ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); | 1675 | ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); |
1676 | console_unlock(); | ||
1671 | unlock_fb_info(fb_info); | 1677 | unlock_fb_info(fb_info); |
1672 | 1678 | ||
1673 | if (ret) | 1679 | if (ret) |
@@ -1682,7 +1688,9 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) | |||
1682 | num_registered_fb--; | 1688 | num_registered_fb--; |
1683 | fb_cleanup_device(fb_info); | 1689 | fb_cleanup_device(fb_info); |
1684 | event.info = fb_info; | 1690 | event.info = fb_info; |
1691 | console_lock(); | ||
1685 | fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); | 1692 | fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); |
1693 | console_unlock(); | ||
1686 | 1694 | ||
1687 | /* this may free fb info */ | 1695 | /* this may free fb info */ |
1688 | put_fb_info(fb_info); | 1696 | put_fb_info(fb_info); |
@@ -1853,11 +1861,8 @@ int fb_new_modelist(struct fb_info *info) | |||
1853 | err = 1; | 1861 | err = 1; |
1854 | 1862 | ||
1855 | if (!list_empty(&info->modelist)) { | 1863 | if (!list_empty(&info->modelist)) { |
1856 | if (!lock_fb_info(info)) | ||
1857 | return -ENODEV; | ||
1858 | event.info = info; | 1864 | event.info = info; |
1859 | err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); | 1865 | err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); |
1860 | unlock_fb_info(info); | ||
1861 | } | 1866 | } |
1862 | 1867 | ||
1863 | return err; | 1868 | return err; |
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index a55e3669d135..ef476b02fbe5 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
@@ -177,6 +177,8 @@ static ssize_t store_modes(struct device *device, | |||
177 | if (i * sizeof(struct fb_videomode) != count) | 177 | if (i * sizeof(struct fb_videomode) != count) |
178 | return -EINVAL; | 178 | return -EINVAL; |
179 | 179 | ||
180 | if (!lock_fb_info(fb_info)) | ||
181 | return -ENODEV; | ||
180 | console_lock(); | 182 | console_lock(); |
181 | list_splice(&fb_info->modelist, &old_list); | 183 | list_splice(&fb_info->modelist, &old_list); |
182 | fb_videomode_to_modelist((const struct fb_videomode *)buf, i, | 184 | fb_videomode_to_modelist((const struct fb_videomode *)buf, i, |
@@ -188,6 +190,7 @@ static ssize_t store_modes(struct device *device, | |||
188 | fb_destroy_modelist(&old_list); | 190 | fb_destroy_modelist(&old_list); |
189 | 191 | ||
190 | console_unlock(); | 192 | console_unlock(); |
193 | unlock_fb_info(fb_info); | ||
191 | 194 | ||
192 | return 0; | 195 | return 0; |
193 | } | 196 | } |
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 12526787a7c7..0abf2bf20836 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -139,6 +139,7 @@ struct imxfb_info { | |||
139 | struct clk *clk_ahb; | 139 | struct clk *clk_ahb; |
140 | struct clk *clk_per; | 140 | struct clk *clk_per; |
141 | enum imxfb_type devtype; | 141 | enum imxfb_type devtype; |
142 | bool enabled; | ||
142 | 143 | ||
143 | /* | 144 | /* |
144 | * These are the addresses we mapped | 145 | * These are the addresses we mapped |
@@ -536,6 +537,10 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi) | |||
536 | 537 | ||
537 | static void imxfb_enable_controller(struct imxfb_info *fbi) | 538 | static void imxfb_enable_controller(struct imxfb_info *fbi) |
538 | { | 539 | { |
540 | |||
541 | if (fbi->enabled) | ||
542 | return; | ||
543 | |||
539 | pr_debug("Enabling LCD controller\n"); | 544 | pr_debug("Enabling LCD controller\n"); |
540 | 545 | ||
541 | writel(fbi->screen_dma, fbi->regs + LCDC_SSA); | 546 | writel(fbi->screen_dma, fbi->regs + LCDC_SSA); |
@@ -556,6 +561,7 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) | |||
556 | clk_prepare_enable(fbi->clk_ipg); | 561 | clk_prepare_enable(fbi->clk_ipg); |
557 | clk_prepare_enable(fbi->clk_ahb); | 562 | clk_prepare_enable(fbi->clk_ahb); |
558 | clk_prepare_enable(fbi->clk_per); | 563 | clk_prepare_enable(fbi->clk_per); |
564 | fbi->enabled = true; | ||
559 | 565 | ||
560 | if (fbi->backlight_power) | 566 | if (fbi->backlight_power) |
561 | fbi->backlight_power(1); | 567 | fbi->backlight_power(1); |
@@ -565,6 +571,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) | |||
565 | 571 | ||
566 | static void imxfb_disable_controller(struct imxfb_info *fbi) | 572 | static void imxfb_disable_controller(struct imxfb_info *fbi) |
567 | { | 573 | { |
574 | if (!fbi->enabled) | ||
575 | return; | ||
576 | |||
568 | pr_debug("Disabling LCD controller\n"); | 577 | pr_debug("Disabling LCD controller\n"); |
569 | 578 | ||
570 | if (fbi->backlight_power) | 579 | if (fbi->backlight_power) |
@@ -575,6 +584,7 @@ static void imxfb_disable_controller(struct imxfb_info *fbi) | |||
575 | clk_disable_unprepare(fbi->clk_per); | 584 | clk_disable_unprepare(fbi->clk_per); |
576 | clk_disable_unprepare(fbi->clk_ipg); | 585 | clk_disable_unprepare(fbi->clk_ipg); |
577 | clk_disable_unprepare(fbi->clk_ahb); | 586 | clk_disable_unprepare(fbi->clk_ahb); |
587 | fbi->enabled = false; | ||
578 | 588 | ||
579 | writel(0, fbi->regs + LCDC_RMCR); | 589 | writel(0, fbi->regs + LCDC_RMCR); |
580 | } | 590 | } |
@@ -729,6 +739,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev) | |||
729 | 739 | ||
730 | memset(fbi, 0, sizeof(struct imxfb_info)); | 740 | memset(fbi, 0, sizeof(struct imxfb_info)); |
731 | 741 | ||
742 | fbi->devtype = pdev->id_entry->driver_data; | ||
743 | |||
732 | strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); | 744 | strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); |
733 | 745 | ||
734 | info->fix.type = FB_TYPE_PACKED_PIXELS; | 746 | info->fix.type = FB_TYPE_PACKED_PIXELS; |
@@ -789,7 +801,6 @@ static int __init imxfb_probe(struct platform_device *pdev) | |||
789 | return -ENOMEM; | 801 | return -ENOMEM; |
790 | 802 | ||
791 | fbi = info->par; | 803 | fbi = info->par; |
792 | fbi->devtype = pdev->id_entry->driver_data; | ||
793 | 804 | ||
794 | if (!fb_mode) | 805 | if (!fb_mode) |
795 | fb_mode = pdata->mode[0].mode.name; | 806 | fb_mode = pdata->mode[0].mode.name; |