diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2007-02-12 03:55:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-12 12:48:42 -0500 |
commit | c4f28e54d61278203c2bb2aea0679e0a738235d2 (patch) | |
tree | d92cf0718084a4e659444741443ee38afb847836 /drivers/video/vga16fb.c | |
parent | 52e7c922f37907ab3cf3445b916fbbc53cbd6c75 (diff) |
[PATCH] Video: fb, add true ref_count atomicity
Some of fb drivers uses atomic_t in bad manner, since there are still some
race-prone gaps. Use mutexes to protect open/close code sections with
ref_count testing and finally use simple uint.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Acked-by: Denis Oliver Kropp <dok@directfb.org>
Cc: James Simmons <jsimmons@infradead.org>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/vga16fb.c')
-rw-r--r-- | drivers/video/vga16fb.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 6aff63d5b295..ec4c7dc54a66 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c | |||
@@ -70,7 +70,8 @@ struct vga16fb_par { | |||
70 | unsigned char ClockingMode; /* Seq-Controller:01h */ | 70 | unsigned char ClockingMode; /* Seq-Controller:01h */ |
71 | } vga_state; | 71 | } vga_state; |
72 | struct vgastate state; | 72 | struct vgastate state; |
73 | atomic_t ref_count; | 73 | struct mutex open_lock; |
74 | unsigned int ref_count; | ||
74 | int palette_blanked, vesa_blanked, mode, isVGA; | 75 | int palette_blanked, vesa_blanked, mode, isVGA; |
75 | u8 misc, pel_msk, vss, clkdiv; | 76 | u8 misc, pel_msk, vss, clkdiv; |
76 | u8 crtc[VGA_CRT_C]; | 77 | u8 crtc[VGA_CRT_C]; |
@@ -300,28 +301,33 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, | |||
300 | static int vga16fb_open(struct fb_info *info, int user) | 301 | static int vga16fb_open(struct fb_info *info, int user) |
301 | { | 302 | { |
302 | struct vga16fb_par *par = info->par; | 303 | struct vga16fb_par *par = info->par; |
303 | int cnt = atomic_read(&par->ref_count); | ||
304 | 304 | ||
305 | if (!cnt) { | 305 | mutex_lock(&par->open_lock); |
306 | if (!par->ref_count) { | ||
306 | memset(&par->state, 0, sizeof(struct vgastate)); | 307 | memset(&par->state, 0, sizeof(struct vgastate)); |
307 | par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE | | 308 | par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE | |
308 | VGA_SAVE_CMAP; | 309 | VGA_SAVE_CMAP; |
309 | save_vga(&par->state); | 310 | save_vga(&par->state); |
310 | } | 311 | } |
311 | atomic_inc(&par->ref_count); | 312 | par->ref_count++; |
313 | mutex_unlock(&par->open_lock); | ||
314 | |||
312 | return 0; | 315 | return 0; |
313 | } | 316 | } |
314 | 317 | ||
315 | static int vga16fb_release(struct fb_info *info, int user) | 318 | static int vga16fb_release(struct fb_info *info, int user) |
316 | { | 319 | { |
317 | struct vga16fb_par *par = info->par; | 320 | struct vga16fb_par *par = info->par; |
318 | int cnt = atomic_read(&par->ref_count); | ||
319 | 321 | ||
320 | if (!cnt) | 322 | mutex_lock(&par->open_lock); |
323 | if (!par->ref_count) { | ||
324 | mutex_unlock(&par->open_lock); | ||
321 | return -EINVAL; | 325 | return -EINVAL; |
322 | if (cnt == 1) | 326 | } |
327 | if (par->ref_count == 1) | ||
323 | restore_vga(&par->state); | 328 | restore_vga(&par->state); |
324 | atomic_dec(&par->ref_count); | 329 | par->ref_count--; |
330 | mutex_unlock(&par->open_lock); | ||
325 | 331 | ||
326 | return 0; | 332 | return 0; |
327 | } | 333 | } |
@@ -1357,6 +1363,7 @@ static int __init vga16fb_probe(struct platform_device *dev) | |||
1357 | printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); | 1363 | printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); |
1358 | par = info->par; | 1364 | par = info->par; |
1359 | 1365 | ||
1366 | mutex_init(&par->open_lock); | ||
1360 | par->isVGA = ORIG_VIDEO_ISVGA; | 1367 | par->isVGA = ORIG_VIDEO_ISVGA; |
1361 | par->palette_blanked = 0; | 1368 | par->palette_blanked = 0; |
1362 | par->vesa_blanked = 0; | 1369 | par->vesa_blanked = 0; |