From 1fe70e963028f34ba5e32488a7870ff4b410b19b Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Sun, 1 May 2011 06:29:37 -0300 Subject: [media] cx88: fix locking of sub-driver operations 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 . Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=31962 Reported-by: Andi Huber Tested-by: Andi Huber Tested-by: Marlon de Boer Cc: stable@kernel.org Signed-off-by: Jonathan Nieder Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 4 ++-- drivers/media/video/cx88/cx88-dvb.c | 3 +-- drivers/media/video/cx88/cx88-mpeg.c | 4 ---- drivers/media/video/cx88/cx88.h | 3 ++- 4 files changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index b93fbd39a39e..a6f7d53a4510 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -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; } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 84002bc80db5..c69df7ebb6a7 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -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; @@ -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; } diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index a092c3a4c56d..91d3d179c3c7 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -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)); } @@ -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; } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index e3d56c235203..9731daa92a06 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -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 */ -- cgit v1.2.3