V4L/DVB (7319): pvrusb2: Close potential race condition during initialization

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>
This commit is contained in:
Mike Isely 2008-04-22 14:45:44 -03:00 committed by Mauro Carvalho Chehab
parent ee9ca4b24f
commit c4a8828ddb
3 changed files with 26 additions and 23 deletions

View File

@ -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;
}

View File

@ -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)
{
@ -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) {
@ -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)
{

View File

@ -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 *);