Skip to content

Commit

Permalink
Merge branch 'fbmem'
Browse files Browse the repository at this point in the history
* fbmem:
  Further fbcon sanity checking
  fbmem: fix remove_conflicting_framebuffers races
  • Loading branch information
Linus Torvalds committed May 14, 2011
2 parents 22fe944 + c590cec commit afa4979
Showing 1 changed file with 71 additions and 52 deletions.
123 changes: 71 additions & 52 deletions drivers/video/fbmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1537,8 +1537,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena,
return false;
}

static int do_unregister_framebuffer(struct fb_info *fb_info);

#define VGA_FB_PHYS 0xA0000
void remove_conflicting_framebuffers(struct apertures_struct *a,
static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{
int i;
Expand All @@ -1560,39 +1562,26 @@ void remove_conflicting_framebuffers(struct apertures_struct *a,
printk(KERN_INFO "fb: conflicting fb hw usage "
"%s vs %s - removing generic driver\n",
name, registered_fb[i]->fix.id);
unregister_framebuffer(registered_fb[i]);
do_unregister_framebuffer(registered_fb[i]);
}
}
}
EXPORT_SYMBOL(remove_conflicting_framebuffers);

/**
* register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure
*
* Registers a frame buffer device @fb_info.
*
* Returns negative errno on error, or zero for success.
*
*/

int
register_framebuffer(struct fb_info *fb_info)
static int do_register_framebuffer(struct fb_info *fb_info)
{
int i;
struct fb_event event;
struct fb_videomode mode;

if (num_registered_fb == FB_MAX)
return -ENXIO;

if (fb_check_foreignness(fb_info))
return -ENOSYS;

remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
fb_is_primary_device(fb_info));

mutex_lock(&registration_lock);
if (num_registered_fb == FB_MAX)
return -ENXIO;

num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)
if (!registered_fb[i])
Expand Down Expand Up @@ -1635,7 +1624,6 @@ register_framebuffer(struct fb_info *fb_info)
fb_var_to_videomode(&mode, &fb_info->var);
fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;
mutex_unlock(&registration_lock);

event.info = fb_info;
if (!lock_fb_info(fb_info))
Expand All @@ -1645,48 +1633,23 @@ register_framebuffer(struct fb_info *fb_info)
return 0;
}


/**
* unregister_framebuffer - releases a frame buffer device
* @fb_info: frame buffer info structure
*
* Unregisters a frame buffer device @fb_info.
*
* Returns negative errno on error, or zero for success.
*
* This function will also notify the framebuffer console
* to release the driver.
*
* This is meant to be called within a driver's module_exit()
* function. If this is called outside module_exit(), ensure
* that the driver implements fb_open() and fb_release() to
* check that no processes are using the device.
*/

int
unregister_framebuffer(struct fb_info *fb_info)
static int do_unregister_framebuffer(struct fb_info *fb_info)
{
struct fb_event event;
int i, ret = 0;

mutex_lock(&registration_lock);
i = fb_info->node;
if (!registered_fb[i]) {
ret = -EINVAL;
goto done;
}

if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
return -EINVAL;

if (!lock_fb_info(fb_info))
return -ENODEV;
event.info = fb_info;
ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
unlock_fb_info(fb_info);

if (ret) {
ret = -EINVAL;
goto done;
}
if (ret)
return -EINVAL;

if (fb_info->pixmap.addr &&
(fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
Expand All @@ -1701,8 +1664,64 @@ unregister_framebuffer(struct fb_info *fb_info)

/* this may free fb info */
put_fb_info(fb_info);
done:
return 0;
}

void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{
mutex_lock(&registration_lock);
do_remove_conflicting_framebuffers(a, name, primary);
mutex_unlock(&registration_lock);
}
EXPORT_SYMBOL(remove_conflicting_framebuffers);

/**
* register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure
*
* Registers a frame buffer device @fb_info.
*
* Returns negative errno on error, or zero for success.
*
*/
int
register_framebuffer(struct fb_info *fb_info)
{
int ret;

mutex_lock(&registration_lock);
ret = do_register_framebuffer(fb_info);
mutex_unlock(&registration_lock);

return ret;
}

/**
* unregister_framebuffer - releases a frame buffer device
* @fb_info: frame buffer info structure
*
* Unregisters a frame buffer device @fb_info.
*
* Returns negative errno on error, or zero for success.
*
* This function will also notify the framebuffer console
* to release the driver.
*
* This is meant to be called within a driver's module_exit()
* function. If this is called outside module_exit(), ensure
* that the driver implements fb_open() and fb_release() to
* check that no processes are using the device.
*/
int
unregister_framebuffer(struct fb_info *fb_info)
{
int ret;

mutex_lock(&registration_lock);
ret = do_unregister_framebuffer(fb_info);
mutex_unlock(&registration_lock);

return ret;
}

Expand Down

0 comments on commit afa4979

Please sign in to comment.