[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>
This commit is contained in:
Родитель
52e7c922f3
Коммит
c4f28e54d6
|
@ -264,7 +264,8 @@ struct i810fb_par {
|
|||
struct heap_data cursor_heap;
|
||||
struct vgastate state;
|
||||
struct i810fb_i2c_chan chan[3];
|
||||
atomic_t use_count;
|
||||
struct mutex open_lock;
|
||||
unsigned int use_count;
|
||||
u32 pseudo_palette[17];
|
||||
unsigned long mmio_start_phys;
|
||||
u8 __iomem *mmio_start_virtual;
|
||||
|
|
|
@ -1235,9 +1235,9 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
|
|||
static int i810fb_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct i810fb_par *par = info->par;
|
||||
u32 count = atomic_read(&par->use_count);
|
||||
|
||||
if (count == 0) {
|
||||
|
||||
mutex_lock(&par->open_lock);
|
||||
if (par->use_count == 0) {
|
||||
memset(&par->state, 0, sizeof(struct vgastate));
|
||||
par->state.flags = VGA_SAVE_CMAP;
|
||||
par->state.vgabase = par->mmio_start_virtual;
|
||||
|
@ -1246,7 +1246,8 @@ static int i810fb_open(struct fb_info *info, int user)
|
|||
i810_save_vga_state(par);
|
||||
}
|
||||
|
||||
atomic_inc(&par->use_count);
|
||||
par->use_count++;
|
||||
mutex_unlock(&par->open_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1254,18 +1255,20 @@ static int i810fb_open(struct fb_info *info, int user)
|
|||
static int i810fb_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct i810fb_par *par = info->par;
|
||||
u32 count;
|
||||
|
||||
count = atomic_read(&par->use_count);
|
||||
if (count == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (count == 1) {
|
||||
mutex_lock(&par->open_lock);
|
||||
if (par->use_count == 0) {
|
||||
mutex_unlock(&par->open_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (par->use_count == 1) {
|
||||
i810_restore_vga_state(par);
|
||||
restore_vga(&par->state);
|
||||
}
|
||||
|
||||
atomic_dec(&par->use_count);
|
||||
par->use_count--;
|
||||
mutex_unlock(&par->open_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1752,6 +1755,8 @@ static void __devinit i810_init_monspecs(struct fb_info *info)
|
|||
static void __devinit i810_init_defaults(struct i810fb_par *par,
|
||||
struct fb_info *info)
|
||||
{
|
||||
mutex_init(&par->open_lock);
|
||||
|
||||
if (voffset)
|
||||
v_offset_default = voffset;
|
||||
else if (par->aperture.size > 32 * 1024 * 1024)
|
||||
|
|
|
@ -556,14 +556,16 @@ static int
|
|||
neofb_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct neofb_par *par = info->par;
|
||||
int cnt = atomic_read(&par->ref_count);
|
||||
|
||||
if (!cnt) {
|
||||
mutex_lock(&par->open_lock);
|
||||
if (!par->ref_count) {
|
||||
memset(&par->state, 0, sizeof(struct vgastate));
|
||||
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
|
||||
save_vga(&par->state);
|
||||
}
|
||||
atomic_inc(&par->ref_count);
|
||||
par->ref_count++;
|
||||
mutex_unlock(&par->open_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -571,14 +573,18 @@ static int
|
|||
neofb_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct neofb_par *par = info->par;
|
||||
int cnt = atomic_read(&par->ref_count);
|
||||
|
||||
if (!cnt)
|
||||
mutex_lock(&par->open_lock);
|
||||
if (!par->ref_count) {
|
||||
mutex_unlock(&par->open_lock);
|
||||
return -EINVAL;
|
||||
if (cnt == 1) {
|
||||
}
|
||||
if (par->ref_count == 1) {
|
||||
restore_vga(&par->state);
|
||||
}
|
||||
atomic_dec(&par->ref_count);
|
||||
par->ref_count--;
|
||||
mutex_unlock(&par->open_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2047,6 +2053,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
|
|||
|
||||
info->fix.accel = id->driver_data;
|
||||
|
||||
mutex_init(&par->open_lock);
|
||||
par->pci_burst = !nopciburst;
|
||||
par->lcd_stretch = !nostretch;
|
||||
par->libretto = libretto;
|
||||
|
|
|
@ -1101,10 +1101,10 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
|
|||
static int rivafb_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct riva_par *par = info->par;
|
||||
int cnt = atomic_read(&par->ref_count);
|
||||
|
||||
NVTRACE_ENTER();
|
||||
if (!cnt) {
|
||||
mutex_lock(&par->open_lock);
|
||||
if (!par->ref_count) {
|
||||
#ifdef CONFIG_X86
|
||||
memset(&par->state, 0, sizeof(struct vgastate));
|
||||
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
|
||||
|
@ -1119,7 +1119,8 @@ static int rivafb_open(struct fb_info *info, int user)
|
|||
|
||||
riva_save_state(par, &par->initial_state);
|
||||
}
|
||||
atomic_inc(&par->ref_count);
|
||||
par->ref_count++;
|
||||
mutex_unlock(&par->open_lock);
|
||||
NVTRACE_LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1127,12 +1128,14 @@ static int rivafb_open(struct fb_info *info, int user)
|
|||
static int rivafb_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct riva_par *par = info->par;
|
||||
int cnt = atomic_read(&par->ref_count);
|
||||
|
||||
NVTRACE_ENTER();
|
||||
if (!cnt)
|
||||
mutex_lock(&par->open_lock);
|
||||
if (!par->ref_count) {
|
||||
mutex_unlock(&par->open_lock);
|
||||
return -EINVAL;
|
||||
if (cnt == 1) {
|
||||
}
|
||||
if (par->ref_count == 1) {
|
||||
par->riva.LockUnlock(&par->riva, 0);
|
||||
par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
|
||||
riva_load_state(par, &par->initial_state);
|
||||
|
@ -1141,7 +1144,8 @@ static int rivafb_release(struct fb_info *info, int user)
|
|||
#endif
|
||||
par->riva.LockUnlock(&par->riva, 1);
|
||||
}
|
||||
atomic_dec(&par->ref_count);
|
||||
par->ref_count--;
|
||||
mutex_unlock(&par->open_lock);
|
||||
NVTRACE_LEAVE();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1999,6 +2003,7 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
|
|||
goto err_disable_device;
|
||||
}
|
||||
|
||||
mutex_init(&default_par->open_lock);
|
||||
default_par->riva.Architecture = riva_get_arch(pd);
|
||||
|
||||
default_par->Chipset = (pd->vendor << 16) | pd->device;
|
||||
|
|
|
@ -53,7 +53,8 @@ struct riva_par {
|
|||
#ifdef CONFIG_X86
|
||||
struct vgastate state;
|
||||
#endif
|
||||
atomic_t ref_count;
|
||||
struct mutex open_lock;
|
||||
unsigned int ref_count;
|
||||
unsigned char *EDID;
|
||||
unsigned int Chipset;
|
||||
int forceCRTC;
|
||||
|
|
|
@ -70,7 +70,8 @@ struct vga16fb_par {
|
|||
unsigned char ClockingMode; /* Seq-Controller:01h */
|
||||
} vga_state;
|
||||
struct vgastate state;
|
||||
atomic_t ref_count;
|
||||
struct mutex open_lock;
|
||||
unsigned int ref_count;
|
||||
int palette_blanked, vesa_blanked, mode, isVGA;
|
||||
u8 misc, pel_msk, vss, clkdiv;
|
||||
u8 crtc[VGA_CRT_C];
|
||||
|
@ -300,28 +301,33 @@ static void vga16fb_clock_chip(struct vga16fb_par *par,
|
|||
static int vga16fb_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct vga16fb_par *par = info->par;
|
||||
int cnt = atomic_read(&par->ref_count);
|
||||
|
||||
if (!cnt) {
|
||||
mutex_lock(&par->open_lock);
|
||||
if (!par->ref_count) {
|
||||
memset(&par->state, 0, sizeof(struct vgastate));
|
||||
par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
|
||||
VGA_SAVE_CMAP;
|
||||
save_vga(&par->state);
|
||||
}
|
||||
atomic_inc(&par->ref_count);
|
||||
par->ref_count++;
|
||||
mutex_unlock(&par->open_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vga16fb_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct vga16fb_par *par = info->par;
|
||||
int cnt = atomic_read(&par->ref_count);
|
||||
|
||||
if (!cnt)
|
||||
mutex_lock(&par->open_lock);
|
||||
if (!par->ref_count) {
|
||||
mutex_unlock(&par->open_lock);
|
||||
return -EINVAL;
|
||||
if (cnt == 1)
|
||||
}
|
||||
if (par->ref_count == 1)
|
||||
restore_vga(&par->state);
|
||||
atomic_dec(&par->ref_count);
|
||||
par->ref_count--;
|
||||
mutex_unlock(&par->open_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1357,6 +1363,7 @@ static int __init vga16fb_probe(struct platform_device *dev)
|
|||
printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
|
||||
par = info->par;
|
||||
|
||||
mutex_init(&par->open_lock);
|
||||
par->isVGA = ORIG_VIDEO_ISVGA;
|
||||
par->palette_blanked = 0;
|
||||
par->vesa_blanked = 0;
|
||||
|
|
|
@ -140,7 +140,8 @@ typedef volatile struct {
|
|||
|
||||
struct neofb_par {
|
||||
struct vgastate state;
|
||||
atomic_t ref_count;
|
||||
struct mutex open_lock;
|
||||
unsigned int ref_count;
|
||||
|
||||
unsigned char MiscOutReg; /* Misc */
|
||||
unsigned char CRTC[25]; /* Crtc Controller */
|
||||
|
|
Загрузка…
Ссылка в новой задаче