aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/video/i810/i810.h3
-rw-r--r--drivers/video/i810/i810_main.c25
-rw-r--r--drivers/video/neofb.c21
-rw-r--r--drivers/video/riva/fbdev.c19
-rw-r--r--drivers/video/riva/rivafb.h3
-rw-r--r--drivers/video/vga16fb.c23
-rw-r--r--include/video/neomagic.h3
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,
1235static int i810fb_open(struct fb_info *info, int user) 1235static 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)
1254static int i810fb_release(struct fb_info *info, int user) 1255static 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)
1752static void __devinit i810_init_defaults(struct i810fb_par *par, 1755static 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
556neofb_open(struct fb_info *info, int user) 556neofb_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
571neofb_release(struct fb_info *info, int user) 573neofb_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)
1101static int rivafb_open(struct fb_info *info, int user) 1101static 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)
1127static int rivafb_release(struct fb_info *info, int user) 1128static 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,
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;
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
141struct neofb_par { 141struct 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 */