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>
struct heap_data cursor_heap;
struct vgastate state;
struct i810fb_i2c_chan chan[3];
struct heap_data cursor_heap;
struct vgastate state;
struct i810fb_i2c_chan chan[3];
+ struct mutex open_lock;
+ unsigned int use_count;
u32 pseudo_palette[17];
unsigned long mmio_start_phys;
u8 __iomem *mmio_start_virtual;
u32 pseudo_palette[17];
unsigned long mmio_start_phys;
u8 __iomem *mmio_start_virtual;
static int i810fb_open(struct fb_info *info, int user)
{
struct i810fb_par *par = info->par;
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;
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_CMAP;
par->state.vgabase = par->mmio_start_virtual;
i810_save_vga_state(par);
}
i810_save_vga_state(par);
}
- atomic_inc(&par->use_count);
+ par->use_count++;
+ mutex_unlock(&par->open_lock);
static int i810fb_release(struct fb_info *info, int user)
{
struct i810fb_par *par = info->par;
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)
+
+ mutex_lock(&par->open_lock);
+ if (par->use_count == 0) {
+ mutex_unlock(&par->open_lock);
+ if (par->use_count == 1) {
i810_restore_vga_state(par);
restore_vga(&par->state);
}
i810_restore_vga_state(par);
restore_vga(&par->state);
}
- atomic_dec(&par->use_count);
+ par->use_count--;
+ mutex_unlock(&par->open_lock);
static void __devinit i810_init_defaults(struct i810fb_par *par,
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)
if (voffset)
v_offset_default = voffset;
else if (par->aperture.size > 32 * 1024 * 1024)
neofb_open(struct fb_info *info, int user)
{
struct neofb_par *par = info->par;
neofb_open(struct fb_info *info, int user)
{
struct neofb_par *par = info->par;
- int cnt = atomic_read(&par->ref_count);
+ 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);
}
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);
+
neofb_release(struct fb_info *info, int user)
{
struct neofb_par *par = info->par;
neofb_release(struct fb_info *info, int user)
{
struct neofb_par *par = info->par;
- int cnt = atomic_read(&par->ref_count);
+ mutex_lock(&par->open_lock);
+ if (!par->ref_count) {
+ mutex_unlock(&par->open_lock);
+ }
+ if (par->ref_count == 1) {
restore_vga(&par->state);
}
restore_vga(&par->state);
}
- atomic_dec(&par->ref_count);
+ par->ref_count--;
+ mutex_unlock(&par->open_lock);
+
info->fix.accel = id->driver_data;
info->fix.accel = id->driver_data;
+ mutex_init(&par->open_lock);
par->pci_burst = !nopciburst;
par->lcd_stretch = !nostretch;
par->libretto = libretto;
par->pci_burst = !nopciburst;
par->lcd_stretch = !nostretch;
par->libretto = libretto;
static int rivafb_open(struct fb_info *info, int user)
{
struct riva_par *par = info->par;
static int rivafb_open(struct fb_info *info, int user)
{
struct riva_par *par = info->par;
- int cnt = atomic_read(&par->ref_count);
+ 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;
#ifdef CONFIG_X86
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
riva_save_state(par, &par->initial_state);
}
riva_save_state(par, &par->initial_state);
}
- atomic_inc(&par->ref_count);
+ par->ref_count++;
+ mutex_unlock(&par->open_lock);
NVTRACE_LEAVE();
return 0;
}
NVTRACE_LEAVE();
return 0;
}
static int rivafb_release(struct fb_info *info, int user)
{
struct riva_par *par = info->par;
static int rivafb_release(struct fb_info *info, int user)
{
struct riva_par *par = info->par;
- int cnt = atomic_read(&par->ref_count);
+ mutex_lock(&par->open_lock);
+ if (!par->ref_count) {
+ mutex_unlock(&par->open_lock);
+ }
+ 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);
par->riva.LockUnlock(&par->riva, 0);
par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
riva_load_state(par, &par->initial_state);
#endif
par->riva.LockUnlock(&par->riva, 1);
}
#endif
par->riva.LockUnlock(&par->riva, 1);
}
- atomic_dec(&par->ref_count);
+ par->ref_count--;
+ mutex_unlock(&par->open_lock);
NVTRACE_LEAVE();
return 0;
}
NVTRACE_LEAVE();
return 0;
}
goto err_disable_device;
}
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;
default_par->riva.Architecture = riva_get_arch(pd);
default_par->Chipset = (pd->vendor << 16) | pd->device;
#ifdef CONFIG_X86
struct vgastate state;
#endif
#ifdef CONFIG_X86
struct vgastate state;
#endif
+ struct mutex open_lock;
+ unsigned int ref_count;
unsigned char *EDID;
unsigned int Chipset;
int forceCRTC;
unsigned char *EDID;
unsigned int Chipset;
int forceCRTC;
unsigned char ClockingMode; /* Seq-Controller:01h */
} vga_state;
struct vgastate state;
unsigned char ClockingMode; /* Seq-Controller:01h */
} vga_state;
struct vgastate state;
+ 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];
int palette_blanked, vesa_blanked, mode, isVGA;
u8 misc, pel_msk, vss, clkdiv;
u8 crtc[VGA_CRT_C];
static int vga16fb_open(struct fb_info *info, int user)
{
struct vga16fb_par *par = info->par;
static int vga16fb_open(struct fb_info *info, int user)
{
struct vga16fb_par *par = info->par;
- int cnt = atomic_read(&par->ref_count);
+ 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);
}
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;
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);
+ mutex_lock(&par->open_lock);
+ if (!par->ref_count) {
+ mutex_unlock(&par->open_lock);
+ }
+ if (par->ref_count == 1)
restore_vga(&par->state);
restore_vga(&par->state);
- atomic_dec(&par->ref_count);
+ par->ref_count--;
+ mutex_unlock(&par->open_lock);
printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
par = info->par;
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;
par->isVGA = ORIG_VIDEO_ISVGA;
par->palette_blanked = 0;
par->vesa_blanked = 0;
struct neofb_par {
struct vgastate state;
struct neofb_par {
struct vgastate state;
+ struct mutex open_lock;
+ unsigned int ref_count;
unsigned char MiscOutReg; /* Misc */
unsigned char CRTC[25]; /* Crtc Controller */
unsigned char MiscOutReg; /* Misc */
unsigned char CRTC[25]; /* Crtc Controller */