diff options
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; |