aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/vga16fb.c
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2007-02-12 03:55:11 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-12 12:48:42 -0500
commitc4f28e54d61278203c2bb2aea0679e0a738235d2 (patch)
treed92cf0718084a4e659444741443ee38afb847836 /drivers/video/vga16fb.c
parent52e7c922f37907ab3cf3445b916fbbc53cbd6c75 (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.c23
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,
300static int vga16fb_open(struct fb_info *info, int user) 301static 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
315static int vga16fb_release(struct fb_info *info, int user) 318static 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;