提交 c4a8828d 编写于 作者: M Mike Isely 提交者: Mauro Carvalho Chehab

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: NMike Isely <isely@pobox.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 ee9ca4b2
...@@ -75,10 +75,9 @@ struct pvr2_context *pvr2_context_create( ...@@ -75,10 +75,9 @@ struct pvr2_context *pvr2_context_create(
mp = NULL; mp = NULL;
goto done; goto done;
} }
pvr2_hdw_set_state_callback(mp->hdw, pvr2_hdw_initialize(mp->hdw,
(void (*)(void *))pvr2_context_state_check, (void (*)(void *))pvr2_context_state_check,
mp); mp);
pvr2_context_state_check(mp);
done: done:
return mp; return mp;
} }
......
...@@ -1813,8 +1813,23 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw) ...@@ -1813,8 +1813,23 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
} }
/* Create and return a structure for interacting with the underlying /* Perform second stage initialization. Set callback pointer first so that
hardware */ 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, struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
const struct usb_device_id *devid) const struct usb_device_id *devid)
{ {
...@@ -2039,7 +2054,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, ...@@ -2039,7 +2054,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
mutex_init(&hdw->ctl_lock_mutex); mutex_init(&hdw->ctl_lock_mutex);
mutex_init(&hdw->big_lock_mutex); mutex_init(&hdw->big_lock_mutex);
queue_work(hdw->workqueue,&hdw->workinit);
return hdw; return hdw;
fail: fail:
if (hdw) { if (hdw) {
...@@ -2521,17 +2535,6 @@ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state) ...@@ -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 */ /* Return name for this driver instance */
const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
{ {
......
...@@ -101,14 +101,15 @@ struct pvr2_hdw; ...@@ -101,14 +101,15 @@ struct pvr2_hdw;
struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
const struct usb_device_id *devid); 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 */ /* Destroy hardware interaction structure */
void pvr2_hdw_destroy(struct pvr2_hdw *); 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 */ /* Return true if in the ready (normal) state */
int pvr2_hdw_dev_ok(struct pvr2_hdw *); int pvr2_hdw_dev_ok(struct pvr2_hdw *);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册