Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Jiri Slaby and committed by
Linus Torvalds
c4f28e54 52e7c922

+63 -36
+2 -1
drivers/video/i810/i810.h
··· 264 264 struct heap_data cursor_heap; 265 265 struct vgastate state; 266 266 struct i810fb_i2c_chan chan[3]; 267 - atomic_t use_count; 267 + struct mutex open_lock; 268 + unsigned int use_count; 268 269 u32 pseudo_palette[17]; 269 270 unsigned long mmio_start_phys; 270 271 u8 __iomem *mmio_start_virtual;
+16 -11
drivers/video/i810/i810_main.c
··· 1235 1235 static int i810fb_open(struct fb_info *info, int user) 1236 1236 { 1237 1237 struct i810fb_par *par = info->par; 1238 - u32 count = atomic_read(&par->use_count); 1239 - 1240 - if (count == 0) { 1238 + 1239 + mutex_lock(&par->open_lock); 1240 + if (par->use_count == 0) { 1241 1241 memset(&par->state, 0, sizeof(struct vgastate)); 1242 1242 par->state.flags = VGA_SAVE_CMAP; 1243 1243 par->state.vgabase = par->mmio_start_virtual; ··· 1246 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 1252 return 0; 1252 1253 } ··· 1255 1254 static int i810fb_release(struct fb_info *info, int user) 1256 1255 { 1257 1256 struct i810fb_par *par = info->par; 1258 - u32 count; 1259 - 1260 - count = atomic_read(&par->use_count); 1261 - if (count == 0) 1262 - return -EINVAL; 1263 1257 1264 - if (count == 1) { 1258 + mutex_lock(&par->open_lock); 1259 + if (par->use_count == 0) { 1260 + mutex_unlock(&par->open_lock); 1261 + return -EINVAL; 1262 + } 1263 + 1264 + if (par->use_count == 1) { 1265 1265 i810_restore_vga_state(par); 1266 1266 restore_vga(&par->state); 1267 1267 } 1268 1268 1269 - atomic_dec(&par->use_count); 1269 + par->use_count--; 1270 + mutex_unlock(&par->open_lock); 1270 1271 1271 1272 return 0; 1272 1273 } ··· 1755 1752 static void __devinit i810_init_defaults(struct i810fb_par *par, 1756 1753 struct fb_info *info) 1757 1754 { 1755 + mutex_init(&par->open_lock); 1756 + 1758 1757 if (voffset) 1759 1758 v_offset_default = voffset; 1760 1759 else if (par->aperture.size > 32 * 1024 * 1024)
+14 -7
drivers/video/neofb.c
··· 556 556 neofb_open(struct fb_info *info, int user) 557 557 { 558 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 562 memset(&par->state, 0, sizeof(struct vgastate)); 563 563 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; 564 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 569 return 0; 568 570 } 569 571 ··· 573 571 neofb_release(struct fb_info *info, int user) 574 572 { 575 573 struct neofb_par *par = info->par; 576 - int cnt = atomic_read(&par->ref_count); 577 574 578 - if (!cnt) 575 + mutex_lock(&par->open_lock); 576 + if (!par->ref_count) { 577 + mutex_unlock(&par->open_lock); 579 578 return -EINVAL; 580 - if (cnt == 1) { 579 + } 580 + if (par->ref_count == 1) { 581 581 restore_vga(&par->state); 582 582 } 583 - atomic_dec(&par->ref_count); 583 + par->ref_count--; 584 + mutex_unlock(&par->open_lock); 585 + 584 586 return 0; 585 587 } 586 588 ··· 2053 2047 2054 2048 info->fix.accel = id->driver_data; 2055 2049 2050 + mutex_init(&par->open_lock); 2056 2051 par->pci_burst = !nopciburst; 2057 2052 par->lcd_stretch = !nostretch; 2058 2053 par->libretto = libretto;
+12 -7
drivers/video/riva/fbdev.c
··· 1101 1101 static int rivafb_open(struct fb_info *info, int user) 1102 1102 { 1103 1103 struct riva_par *par = info->par; 1104 - int cnt = atomic_read(&par->ref_count); 1105 1104 1106 1105 NVTRACE_ENTER(); 1107 - if (!cnt) { 1106 + mutex_lock(&par->open_lock); 1107 + if (!par->ref_count) { 1108 1108 #ifdef CONFIG_X86 1109 1109 memset(&par->state, 0, sizeof(struct vgastate)); 1110 1110 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; ··· 1119 1119 1120 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 1124 NVTRACE_LEAVE(); 1124 1125 return 0; 1125 1126 } ··· 1128 1127 static int rivafb_release(struct fb_info *info, int user) 1129 1128 { 1130 1129 struct riva_par *par = info->par; 1131 - int cnt = atomic_read(&par->ref_count); 1132 1130 1133 1131 NVTRACE_ENTER(); 1134 - if (!cnt) 1132 + mutex_lock(&par->open_lock); 1133 + if (!par->ref_count) { 1134 + mutex_unlock(&par->open_lock); 1135 1135 return -EINVAL; 1136 - if (cnt == 1) { 1136 + } 1137 + if (par->ref_count == 1) { 1137 1138 par->riva.LockUnlock(&par->riva, 0); 1138 1139 par->riva.LoadStateExt(&par->riva, &par->initial_state.ext); 1139 1140 riva_load_state(par, &par->initial_state); ··· 1144 1141 #endif 1145 1142 par->riva.LockUnlock(&par->riva, 1); 1146 1143 } 1147 - atomic_dec(&par->ref_count); 1144 + par->ref_count--; 1145 + mutex_unlock(&par->open_lock); 1148 1146 NVTRACE_LEAVE(); 1149 1147 return 0; 1150 1148 } ··· 2003 1999 goto err_disable_device; 2004 2000 } 2005 2001 2002 + mutex_init(&default_par->open_lock); 2006 2003 default_par->riva.Architecture = riva_get_arch(pd); 2007 2004 2008 2005 default_par->Chipset = (pd->vendor << 16) | pd->device;
+2 -1
drivers/video/riva/rivafb.h
··· 53 53 #ifdef CONFIG_X86 54 54 struct vgastate state; 55 55 #endif 56 - atomic_t ref_count; 56 + struct mutex open_lock; 57 + unsigned int ref_count; 57 58 unsigned char *EDID; 58 59 unsigned int Chipset; 59 60 int forceCRTC;
+15 -8
drivers/video/vga16fb.c
··· 70 70 unsigned char ClockingMode; /* Seq-Controller:01h */ 71 71 } vga_state; 72 72 struct vgastate state; 73 - atomic_t ref_count; 73 + struct mutex open_lock; 74 + unsigned int ref_count; 74 75 int palette_blanked, vesa_blanked, mode, isVGA; 75 76 u8 misc, pel_msk, vss, clkdiv; 76 77 u8 crtc[VGA_CRT_C]; ··· 301 300 static int vga16fb_open(struct fb_info *info, int user) 302 301 { 303 302 struct vga16fb_par *par = info->par; 304 - int cnt = atomic_read(&par->ref_count); 305 303 306 - if (!cnt) { 304 + mutex_lock(&par->open_lock); 305 + if (!par->ref_count) { 307 306 memset(&par->state, 0, sizeof(struct vgastate)); 308 307 par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE | 309 308 VGA_SAVE_CMAP; 310 309 save_vga(&par->state); 311 310 } 312 - atomic_inc(&par->ref_count); 311 + par->ref_count++; 312 + mutex_unlock(&par->open_lock); 313 + 313 314 return 0; 314 315 } 315 316 316 317 static int vga16fb_release(struct fb_info *info, int user) 317 318 { 318 319 struct vga16fb_par *par = info->par; 319 - int cnt = atomic_read(&par->ref_count); 320 320 321 - if (!cnt) 321 + mutex_lock(&par->open_lock); 322 + if (!par->ref_count) { 323 + mutex_unlock(&par->open_lock); 322 324 return -EINVAL; 323 - if (cnt == 1) 325 + } 326 + if (par->ref_count == 1) 324 327 restore_vga(&par->state); 325 - atomic_dec(&par->ref_count); 328 + par->ref_count--; 329 + mutex_unlock(&par->open_lock); 326 330 327 331 return 0; 328 332 } ··· 1363 1357 printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); 1364 1358 par = info->par; 1365 1359 1360 + mutex_init(&par->open_lock); 1366 1361 par->isVGA = ORIG_VIDEO_ISVGA; 1367 1362 par->palette_blanked = 0; 1368 1363 par->vesa_blanked = 0;
+2 -1
include/video/neomagic.h
··· 140 140 141 141 struct neofb_par { 142 142 struct vgastate state; 143 - atomic_t ref_count; 143 + struct mutex open_lock; 144 + unsigned int ref_count; 144 145 145 146 unsigned char MiscOutReg; /* Misc */ 146 147 unsigned char CRTC[25]; /* Crtc Controller */