Skip to content

Commit

Permalink
[media] cx88: fix locking of sub-driver operations
Browse files Browse the repository at this point in the history
The BKL conversion of this driver seems to have gone wrong.
Loading the cx88-blackbird driver deadlocks.

The cause: mpeg_ops::open in the cx2388x blackbird driver acquires the
device lock and calls the sub-driver's request_acquire, which tries to
acquire the lock again.  Fix it by clarifying the semantics of
request_acquire, request_release, advise_acquire, and advise_release:
now all will rely on the caller to acquire the device lock.

Based on work by Ben Hutchings <ben@decadent.org.uk>.

Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=31962

Reported-by: Andi Huber <hobrom@gmx.at>
Tested-by: Andi Huber <hobrom@gmx.at>
Tested-by: Marlon de Boer <marlon@hyves.nl>
Cc: stable@kernel.org
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Jonathan Nieder authored and Mauro Carvalho Chehab committed May 20, 2011
1 parent 8a317a8 commit 1fe70e9
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 9 deletions.
4 changes: 2 additions & 2 deletions drivers/media/video/cx88/cx88-blackbird.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,13 +1125,13 @@ static int mpeg_release(struct file *file)

/* Make sure we release the hardware */
drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
mutex_unlock(&dev->core->lock);

if (drv)
drv->request_release(drv);

atomic_dec(&dev->core->mpeg_users);

mutex_unlock(&dev->core->lock);

return 0;
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/media/video/cx88/cx88-dvb.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,6 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)

mutex_lock(&dev->core->lock);
drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
mutex_unlock(&dev->core->lock);

if (drv) {
if (acquire){
dev->frontends.active_fe_id = fe_id;
Expand All @@ -146,6 +144,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
dev->frontends.active_fe_id = 0;
}
}
mutex_unlock(&dev->core->lock);

return ret;
}
Expand Down
4 changes: 0 additions & 4 deletions drivers/media/video/cx88/cx88-mpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,13 +624,11 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)

if (drv->advise_acquire)
{
mutex_lock(&drv->core->lock);
core->active_ref++;
if (core->active_type_id == CX88_BOARD_NONE) {
core->active_type_id = drv->type_id;
drv->advise_acquire(drv);
}
mutex_unlock(&drv->core->lock);

mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
}
Expand All @@ -643,14 +641,12 @@ static int cx8802_request_release(struct cx8802_driver *drv)
{
struct cx88_core *core = drv->core;

mutex_lock(&drv->core->lock);
if (drv->advise_release && --core->active_ref == 0)
{
drv->advise_release(drv);
core->active_type_id = CX88_BOARD_NONE;
mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
}
mutex_unlock(&drv->core->lock);

return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/media/video/cx88/cx88.h
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,8 @@ struct cx8802_driver {
/* Caller must _not_ hold core->lock */
int (*probe)(struct cx8802_driver *drv);

/* Caller must hold core->lock */
/* Callers to the following functions must hold core->lock */

int (*remove)(struct cx8802_driver *drv);

/* MPEG 8802 -> mini driver - Access for hardware control */
Expand Down

0 comments on commit 1fe70e9

Please sign in to comment.