Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4f28e54 authored by Jiri Slaby's avatar Jiri Slaby Committed by Linus Torvalds
Browse files

[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: default avatarJiri Slaby <jirislaby@gmail.com>
Acked-by: default avatarDenis Oliver Kropp <dok@directfb.org>
Cc: James Simmons <jsimmons@infradead.org>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 52e7c922
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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;
+15 −10
Original line number Diff line number Diff line
@@ -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)
	mutex_lock(&par->open_lock);
	if (par->use_count == 0) {
		mutex_unlock(&par->open_lock);
		return -EINVAL;
	}

	if (count == 1) {
	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)
+14 −7
Original line number Diff line number Diff line
@@ -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;
+12 −7
Original line number Diff line number Diff line
@@ -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;
+2 −1
Original line number Diff line number Diff line
@@ -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;
Loading