Skip to content

Commit

Permalink
V4L/DVB (7319): pvrusb2: Close potential race condition during initia…
Browse files Browse the repository at this point in the history
…lization

There is a callback that is issued to into pvr2_context from pvr2_hdw
after initialization is done.  There was a probability that this
callback could get missed.  Fixed.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
  • Loading branch information
Mike Isely authored and Mauro Carvalho Chehab committed Apr 24, 2008
1 parent ee9ca4b commit c4a8828
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 23 deletions.
7 changes: 3 additions & 4 deletions drivers/media/video/pvrusb2/pvrusb2-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,9 @@ struct pvr2_context *pvr2_context_create(
mp = NULL;
goto done;
}
pvr2_hdw_set_state_callback(mp->hdw,
(void (*)(void *))pvr2_context_state_check,
mp);
pvr2_context_state_check(mp);
pvr2_hdw_initialize(mp->hdw,
(void (*)(void *))pvr2_context_state_check,
mp);
done:
return mp;
}
Expand Down
31 changes: 17 additions & 14 deletions drivers/media/video/pvrusb2/pvrusb2-hdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1813,8 +1813,23 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
}


/* Create and return a structure for interacting with the underlying
hardware */
/* Perform second stage initialization. Set callback pointer first so that
we can avoid a possible initialization race (if the kernel thread runs
before the callback has been set). */
void pvr2_hdw_initialize(struct pvr2_hdw *hdw,
void (*callback_func)(void *),
void *callback_data)
{
LOCK_TAKE(hdw->big_lock); do {
hdw->state_data = callback_data;
hdw->state_func = callback_func;
} while (0); LOCK_GIVE(hdw->big_lock);
queue_work(hdw->workqueue,&hdw->workinit);
}


/* Create, set up, and return a structure for interacting with the
underlying hardware. */
struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
const struct usb_device_id *devid)
{
Expand Down Expand Up @@ -2039,7 +2054,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
mutex_init(&hdw->ctl_lock_mutex);
mutex_init(&hdw->big_lock_mutex);

queue_work(hdw->workqueue,&hdw->workinit);
return hdw;
fail:
if (hdw) {
Expand Down Expand Up @@ -2521,17 +2535,6 @@ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
}


void pvr2_hdw_set_state_callback(struct pvr2_hdw *hdw,
void (*callback_func)(void *),
void *callback_data)
{
LOCK_TAKE(hdw->big_lock); do {
hdw->state_data = callback_data;
hdw->state_func = callback_func;
} while (0); LOCK_GIVE(hdw->big_lock);
}


/* Return name for this driver instance */
const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
{
Expand Down
11 changes: 6 additions & 5 deletions drivers/media/video/pvrusb2/pvrusb2-hdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,15 @@ struct pvr2_hdw;
struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
const struct usb_device_id *devid);

/* Perform second stage initialization, passing in a notification callback
for when the master state changes. */
void pvr2_hdw_initialize(struct pvr2_hdw *,
void (*callback_func)(void *),
void *callback_data);

/* Destroy hardware interaction structure */
void pvr2_hdw_destroy(struct pvr2_hdw *);

/* Register a function to be called whenever the master state changes. */
void pvr2_hdw_set_state_callback(struct pvr2_hdw *,
void (*callback_func)(void *),
void *callback_data);

/* Return true if in the ready (normal) state */
int pvr2_hdw_dev_ok(struct pvr2_hdw *);

Expand Down

0 comments on commit c4a8828

Please sign in to comment.