[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 <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>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
8a317a8760
commit
1fe70e9630
@@ -1125,13 +1125,13 @@ static int mpeg_release(struct file *file)
|
|||||||
|
|
||||||
/* Make sure we release the hardware */
|
/* Make sure we release the hardware */
|
||||||
drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
|
drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
|
||||||
mutex_unlock(&dev->core->lock);
|
|
||||||
|
|
||||||
if (drv)
|
if (drv)
|
||||||
drv->request_release(drv);
|
drv->request_release(drv);
|
||||||
|
|
||||||
atomic_dec(&dev->core->mpeg_users);
|
atomic_dec(&dev->core->mpeg_users);
|
||||||
|
|
||||||
|
mutex_unlock(&dev->core->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -135,8 +135,6 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
|
|||||||
|
|
||||||
mutex_lock(&dev->core->lock);
|
mutex_lock(&dev->core->lock);
|
||||||
drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
|
drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
|
||||||
mutex_unlock(&dev->core->lock);
|
|
||||||
|
|
||||||
if (drv) {
|
if (drv) {
|
||||||
if (acquire){
|
if (acquire){
|
||||||
dev->frontends.active_fe_id = fe_id;
|
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;
|
dev->frontends.active_fe_id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&dev->core->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -624,13 +624,11 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
|
|||||||
|
|
||||||
if (drv->advise_acquire)
|
if (drv->advise_acquire)
|
||||||
{
|
{
|
||||||
mutex_lock(&drv->core->lock);
|
|
||||||
core->active_ref++;
|
core->active_ref++;
|
||||||
if (core->active_type_id == CX88_BOARD_NONE) {
|
if (core->active_type_id == CX88_BOARD_NONE) {
|
||||||
core->active_type_id = drv->type_id;
|
core->active_type_id = drv->type_id;
|
||||||
drv->advise_acquire(drv);
|
drv->advise_acquire(drv);
|
||||||
}
|
}
|
||||||
mutex_unlock(&drv->core->lock);
|
|
||||||
|
|
||||||
mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
|
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;
|
struct cx88_core *core = drv->core;
|
||||||
|
|
||||||
mutex_lock(&drv->core->lock);
|
|
||||||
if (drv->advise_release && --core->active_ref == 0)
|
if (drv->advise_release && --core->active_ref == 0)
|
||||||
{
|
{
|
||||||
drv->advise_release(drv);
|
drv->advise_release(drv);
|
||||||
core->active_type_id = CX88_BOARD_NONE;
|
core->active_type_id = CX88_BOARD_NONE;
|
||||||
mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
|
mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
|
||||||
}
|
}
|
||||||
mutex_unlock(&drv->core->lock);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -510,7 +510,8 @@ struct cx8802_driver {
|
|||||||
/* Caller must _not_ hold core->lock */
|
/* Caller must _not_ hold core->lock */
|
||||||
int (*probe)(struct cx8802_driver *drv);
|
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);
|
int (*remove)(struct cx8802_driver *drv);
|
||||||
|
|
||||||
/* MPEG 8802 -> mini driver - Access for hardware control */
|
/* MPEG 8802 -> mini driver - Access for hardware control */
|
||||||
|
Reference in New Issue
Block a user