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 | |
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>
-rw-r--r-- | drivers/video/i810/i810.h | 3 | ||||
-rw-r--r-- | drivers/video/i810/i810_main.c | 25 | ||||
-rw-r--r-- | drivers/video/neofb.c | 21 | ||||
-rw-r--r-- | drivers/video/riva/fbdev.c | 19 | ||||
-rw-r--r-- | drivers/video/riva/rivafb.h | 3 | ||||
-rw-r--r-- | drivers/video/vga16fb.c | 23 | ||||
-rw-r--r-- | include/video/neomagic.h | 3 |
7 files changed, 62 insertions, 35 deletions
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h index 579195c2bea3..aa65ffce915b 100644 --- a/drivers/video/i810/i810.h +++ b/drivers/video/i810/i810.h | |||
@@ -264,7 +264,8 @@ struct i810fb_par { | |||
264 | struct heap_data cursor_heap; | 264 | struct heap_data cursor_heap; |
265 | struct vgastate state; | 265 | struct vgastate state; |
266 | struct i810fb_i2c_chan chan[3]; | 266 | struct i810fb_i2c_chan chan[3]; |
267 | atomic_t use_count; | 267 | struct mutex open_lock; |
268 | unsigned int use_count; | ||
268 | u32 pseudo_palette[17]; | 269 | u32 pseudo_palette[17]; |
269 | unsigned long mmio_start_phys; | 270 | unsigned long mmio_start_phys; |
270 | u8 __iomem *mmio_start_virtual; | 271 | u8 __iomem *mmio_start_virtual; |
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index b55a12d95eb2..e343c0da9618 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
@@ -1235,9 +1235,9 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, | |||
1235 | static int i810fb_open(struct fb_info *info, int user) | 1235 | static int i810fb_open(struct fb_info *info, int user) |
1236 | { | 1236 | { |
1237 | struct i810fb_par *par = info->par; | 1237 | struct i810fb_par *par = info->par; |
1238 | u32 count = atomic_read(&par->use_count); | 1238 | |
1239 | 1239 | mutex_lock(&par->open_lock); | |
1240 | if (count == 0) { | 1240 | if (par->use_count == 0) { |
1241 | memset(&par->state, 0, sizeof(struct vgastate)); | 1241 | memset(&par->state, 0, sizeof(struct vgastate)); |
1242 | par->state.flags = VGA_SAVE_CMAP; | 1242 | par->state.flags = VGA_SAVE_CMAP; |
1243 | par->state.vgabase = par->mmio_start_virtual; | 1243 | par->state.vgabase = par->mmio_start_virtual; |
@@ -1246,7 +1246,8 @@ static int i810fb_open(struct fb_info *info, int user) | |||
1246 | i810_save_vga_state(par); | 1246 | i810_save_vga_state(par); |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | atomic_inc(&par->use_count); | 1249 | par->use_count++; |
1250 | mutex_unlock(&par->open_lock); | ||
1250 | 1251 | ||
1251 | return 0; | 1252 | return 0; |
1252 | } | 1253 | } |
@@ -1254,18 +1255,20 @@ static int i810fb_open(struct fb_info *info, int user) | |||
1254 | static int i810fb_release(struct fb_info *info, int user) | 1255 | static int i810fb_release(struct fb_info *info, int user) |
1255 | { | 1256 | { |
1256 | struct i810fb_par *par = info->par; | 1257 | struct i810fb_par *par = info->par; |
1257 | u32 count; | 1258 | |
1258 | 1259 | mutex_lock(&par->open_lock); | |
1259 | count = atomic_read(&par->use_count); | 1260 | if (par->use_count == 0) { |
1260 | if (count == 0) | 1261 | mutex_unlock(&par->open_lock); |
1261 | return -EINVAL; | 1262 | return -EINVAL; |
1263 | } | ||
1262 | 1264 | ||
1263 | if (count == 1) { | 1265 | if (par->use_count == 1) { |
1264 | i810_restore_vga_state(par); | 1266 | i810_restore_vga_state(par); |
1265 | restore_vga(&par->state); | 1267 | restore_vga(&par->state); |
1266 | } | 1268 | } |
1267 | 1269 | ||
1268 | atomic_dec(&par->use_count); | 1270 | par->use_count--; |
1271 | mutex_unlock(&par->open_lock); | ||
1269 | 1272 | ||
1270 | return 0; | 1273 | return 0; |
1271 | } | 1274 | } |
@@ -1752,6 +1755,8 @@ static void __devinit i810_init_monspecs(struct fb_info *info) | |||
1752 | static void __devinit i810_init_defaults(struct i810fb_par *par, | 1755 | static void __devinit i810_init_defaults(struct i810fb_par *par, |
1753 | struct fb_info *info) | 1756 | struct fb_info *info) |
1754 | { | 1757 | { |
1758 | mutex_init(&par->open_lock); | ||
1759 | |||
1755 | if (voffset) | 1760 | if (voffset) |
1756 | v_offset_default = voffset; | 1761 | v_offset_default = voffset; |
1757 | else if (par->aperture.size > 32 * 1024 * 1024) | 1762 | else if (par->aperture.size > 32 * 1024 * 1024) |
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 459ca553ffc0..395ccedde9a6 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
@@ -556,14 +556,16 @@ static int | |||
556 | neofb_open(struct fb_info *info, int user) | 556 | neofb_open(struct fb_info *info, int user) |
557 | { | 557 | { |
558 | struct neofb_par *par = info->par; | 558 | struct neofb_par *par = info->par; |
559 | int cnt = atomic_read(&par->ref_count); | ||
560 | 559 | ||
561 | if (!cnt) { | 560 | mutex_lock(&par->open_lock); |
561 | if (!par->ref_count) { | ||
562 | memset(&par->state, 0, sizeof(struct vgastate)); | 562 | memset(&par->state, 0, sizeof(struct vgastate)); |
563 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; | 563 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; |
564 | save_vga(&par->state); | 564 | save_vga(&par->state); |
565 | } | 565 | } |
566 | atomic_inc(&par->ref_count); | 566 | par->ref_count++; |
567 | mutex_unlock(&par->open_lock); | ||
568 | |||
567 | return 0; | 569 | return 0; |
568 | } | 570 | } |
569 | 571 | ||
@@ -571,14 +573,18 @@ static int | |||
571 | neofb_release(struct fb_info *info, int user) | 573 | neofb_release(struct fb_info *info, int user) |
572 | { | 574 | { |
573 | struct neofb_par *par = info->par; | 575 | struct neofb_par *par = info->par; |
574 | int cnt = atomic_read(&par->ref_count); | ||
575 | 576 | ||
576 | if (!cnt) | 577 | mutex_lock(&par->open_lock); |
578 | if (!par->ref_count) { | ||
579 | mutex_unlock(&par->open_lock); | ||
577 | return -EINVAL; | 580 | return -EINVAL; |
578 | if (cnt == 1) { | 581 | } |
582 | if (par->ref_count == 1) { | ||
579 | restore_vga(&par->state); | 583 | restore_vga(&par->state); |
580 | } | 584 | } |
581 | atomic_dec(&par->ref_count); | 585 | par->ref_count--; |
586 | mutex_unlock(&par->open_lock); | ||
587 | |||
582 | return 0; | 588 | return 0; |
583 | } | 589 | } |
584 | 590 | ||
@@ -2047,6 +2053,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st | |||
2047 | 2053 | ||
2048 | info->fix.accel = id->driver_data; | 2054 | info->fix.accel = id->driver_data; |
2049 | 2055 | ||
2056 | mutex_init(&par->open_lock); | ||
2050 | par->pci_burst = !nopciburst; | 2057 | par->pci_burst = !nopciburst; |
2051 | par->lcd_stretch = !nostretch; | 2058 | par->lcd_stretch = !nostretch; |
2052 | par->libretto = libretto; | 2059 | par->libretto = libretto; |
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 1a13966b7d5b..7c19b5c2a541 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c | |||
@@ -1101,10 +1101,10 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var) | |||
1101 | static int rivafb_open(struct fb_info *info, int user) | 1101 | static int rivafb_open(struct fb_info *info, int user) |
1102 | { | 1102 | { |
1103 | struct riva_par *par = info->par; | 1103 | struct riva_par *par = info->par; |
1104 | int cnt = atomic_read(&par->ref_count); | ||
1105 | 1104 | ||
1106 | NVTRACE_ENTER(); | 1105 | NVTRACE_ENTER(); |
1107 | if (!cnt) { | 1106 | mutex_lock(&par->open_lock); |
1107 | if (!par->ref_count) { | ||
1108 | #ifdef CONFIG_X86 | 1108 | #ifdef CONFIG_X86 |
1109 | memset(&par->state, 0, sizeof(struct vgastate)); | 1109 | memset(&par->state, 0, sizeof(struct vgastate)); |
1110 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; | 1110 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; |
@@ -1119,7 +1119,8 @@ static int rivafb_open(struct fb_info *info, int user) | |||
1119 | 1119 | ||
1120 | riva_save_state(par, &par->initial_state); | 1120 | riva_save_state(par, &par->initial_state); |
1121 | } | 1121 | } |
1122 | atomic_inc(&par->ref_count); | 1122 | par->ref_count++; |
1123 | mutex_unlock(&par->open_lock); | ||
1123 | NVTRACE_LEAVE(); | 1124 | NVTRACE_LEAVE(); |
1124 | return 0; | 1125 | return 0; |
1125 | } | 1126 | } |
@@ -1127,12 +1128,14 @@ static int rivafb_open(struct fb_info *info, int user) | |||
1127 | static int rivafb_release(struct fb_info *info, int user) | 1128 | static int rivafb_release(struct fb_info *info, int user) |
1128 | { | 1129 | { |
1129 | struct riva_par *par = info->par; | 1130 | struct riva_par *par = info->par; |
1130 | int cnt = atomic_read(&par->ref_count); | ||
1131 | 1131 | ||
1132 | NVTRACE_ENTER(); | 1132 | NVTRACE_ENTER(); |
1133 | if (!cnt) | 1133 | mutex_lock(&par->open_lock); |
1134 | if (!par->ref_count) { | ||
1135 | mutex_unlock(&par->open_lock); | ||
1134 | return -EINVAL; | 1136 | return -EINVAL; |
1135 | if (cnt == 1) { | 1137 | } |
1138 | if (par->ref_count == 1) { | ||
1136 | par->riva.LockUnlock(&par->riva, 0); | 1139 | par->riva.LockUnlock(&par->riva, 0); |
1137 | par->riva.LoadStateExt(&par->riva, &par->initial_state.ext); | 1140 | par->riva.LoadStateExt(&par->riva, &par->initial_state.ext); |
1138 | riva_load_state(par, &par->initial_state); | 1141 | riva_load_state(par, &par->initial_state); |
@@ -1141,7 +1144,8 @@ static int rivafb_release(struct fb_info *info, int user) | |||
1141 | #endif | 1144 | #endif |
1142 | par->riva.LockUnlock(&par->riva, 1); | 1145 | par->riva.LockUnlock(&par->riva, 1); |
1143 | } | 1146 | } |
1144 | atomic_dec(&par->ref_count); | 1147 | par->ref_count--; |
1148 | mutex_unlock(&par->open_lock); | ||
1145 | NVTRACE_LEAVE(); | 1149 | NVTRACE_LEAVE(); |
1146 | return 0; | 1150 | return 0; |
1147 | } | 1151 | } |
@@ -1999,6 +2003,7 @@ static int __devinit rivafb_probe(struct pci_dev *pd, | |||
1999 | goto err_disable_device; | 2003 | goto err_disable_device; |
2000 | } | 2004 | } |
2001 | 2005 | ||
2006 | mutex_init(&default_par->open_lock); | ||
2002 | default_par->riva.Architecture = riva_get_arch(pd); | 2007 | default_par->riva.Architecture = riva_get_arch(pd); |
2003 | 2008 | ||
2004 | default_par->Chipset = (pd->vendor << 16) | pd->device; | 2009 | default_par->Chipset = (pd->vendor << 16) | pd->device; |
diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h index 7fa13fc9c413..48ead6d72f24 100644 --- a/drivers/video/riva/rivafb.h +++ b/drivers/video/riva/rivafb.h | |||
@@ -53,7 +53,8 @@ struct riva_par { | |||
53 | #ifdef CONFIG_X86 | 53 | #ifdef CONFIG_X86 |
54 | struct vgastate state; | 54 | struct vgastate state; |
55 | #endif | 55 | #endif |
56 | atomic_t ref_count; | 56 | struct mutex open_lock; |
57 | unsigned int ref_count; | ||
57 | unsigned char *EDID; | 58 | unsigned char *EDID; |
58 | unsigned int Chipset; | 59 | unsigned int Chipset; |
59 | int forceCRTC; | 60 | int forceCRTC; |
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; |
diff --git a/include/video/neomagic.h b/include/video/neomagic.h index 78b1f15a538f..a9e118a1cd16 100644 --- a/include/video/neomagic.h +++ b/include/video/neomagic.h | |||
@@ -140,7 +140,8 @@ typedef volatile struct { | |||
140 | 140 | ||
141 | struct neofb_par { | 141 | struct neofb_par { |
142 | struct vgastate state; | 142 | struct vgastate state; |
143 | atomic_t ref_count; | 143 | struct mutex open_lock; |
144 | unsigned int ref_count; | ||
144 | 145 | ||
145 | unsigned char MiscOutReg; /* Misc */ | 146 | unsigned char MiscOutReg; /* Misc */ |
146 | unsigned char CRTC[25]; /* Crtc Controller */ | 147 | unsigned char CRTC[25]; /* Crtc Controller */ |