diff options
author | Jonathan Nieder <jrnieder@gmail.com> | 2011-05-01 05:29:37 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-20 08:29:36 -0400 |
commit | 1fe70e963028f34ba5e32488a7870ff4b410b19b (patch) | |
tree | 8185ba45b69831b8cb6a1b1aef5cb84ea092b8cc /drivers | |
parent | 8a317a8760cfffa8185b56ff59fb4b6c58488d79 (diff) |
[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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 3 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 3 |
4 files changed, 5 insertions, 9 deletions
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) | |||
1125 | 1125 | ||
1126 | /* Make sure we release the hardware */ | 1126 | /* Make sure we release the hardware */ |
1127 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | 1127 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); |
1128 | mutex_unlock(&dev->core->lock); | ||
1129 | |||
1130 | if (drv) | 1128 | if (drv) |
1131 | drv->request_release(drv); | 1129 | drv->request_release(drv); |
1132 | 1130 | ||
1133 | atomic_dec(&dev->core->mpeg_users); | 1131 | atomic_dec(&dev->core->mpeg_users); |
1134 | 1132 | ||
1133 | mutex_unlock(&dev->core->lock); | ||
1134 | |||
1135 | return 0; | 1135 | return 0; |
1136 | } | 1136 | } |
1137 | 1137 | ||
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) | |||
135 | 135 | ||
136 | mutex_lock(&dev->core->lock); | 136 | mutex_lock(&dev->core->lock); |
137 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); | 137 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); |
138 | mutex_unlock(&dev->core->lock); | ||
139 | |||
140 | if (drv) { | 138 | if (drv) { |
141 | if (acquire){ | 139 | if (acquire){ |
142 | dev->frontends.active_fe_id = fe_id; | 140 | dev->frontends.active_fe_id = fe_id; |
@@ -146,6 +144,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | |||
146 | dev->frontends.active_fe_id = 0; | 144 | dev->frontends.active_fe_id = 0; |
147 | } | 145 | } |
148 | } | 146 | } |
147 | mutex_unlock(&dev->core->lock); | ||
149 | 148 | ||
150 | return ret; | 149 | return ret; |
151 | } | 150 | } |
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) | |||
624 | 624 | ||
625 | if (drv->advise_acquire) | 625 | if (drv->advise_acquire) |
626 | { | 626 | { |
627 | mutex_lock(&drv->core->lock); | ||
628 | core->active_ref++; | 627 | core->active_ref++; |
629 | if (core->active_type_id == CX88_BOARD_NONE) { | 628 | if (core->active_type_id == CX88_BOARD_NONE) { |
630 | core->active_type_id = drv->type_id; | 629 | core->active_type_id = drv->type_id; |
631 | drv->advise_acquire(drv); | 630 | drv->advise_acquire(drv); |
632 | } | 631 | } |
633 | mutex_unlock(&drv->core->lock); | ||
634 | 632 | ||
635 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); | 633 | mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); |
636 | } | 634 | } |
@@ -643,14 +641,12 @@ static int cx8802_request_release(struct cx8802_driver *drv) | |||
643 | { | 641 | { |
644 | struct cx88_core *core = drv->core; | 642 | struct cx88_core *core = drv->core; |
645 | 643 | ||
646 | mutex_lock(&drv->core->lock); | ||
647 | if (drv->advise_release && --core->active_ref == 0) | 644 | if (drv->advise_release && --core->active_ref == 0) |
648 | { | 645 | { |
649 | drv->advise_release(drv); | 646 | drv->advise_release(drv); |
650 | core->active_type_id = CX88_BOARD_NONE; | 647 | core->active_type_id = CX88_BOARD_NONE; |
651 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); | 648 | mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); |
652 | } | 649 | } |
653 | mutex_unlock(&drv->core->lock); | ||
654 | 650 | ||
655 | return 0; | 651 | return 0; |
656 | } | 652 | } |
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 { | |||
510 | /* Caller must _not_ hold core->lock */ | 510 | /* Caller must _not_ hold core->lock */ |
511 | int (*probe)(struct cx8802_driver *drv); | 511 | int (*probe)(struct cx8802_driver *drv); |
512 | 512 | ||
513 | /* Caller must hold core->lock */ | 513 | /* Callers to the following functions must hold core->lock */ |
514 | |||
514 | int (*remove)(struct cx8802_driver *drv); | 515 | int (*remove)(struct cx8802_driver *drv); |
515 | 516 | ||
516 | /* MPEG 8802 -> mini driver - Access for hardware control */ | 517 | /* MPEG 8802 -> mini driver - Access for hardware control */ |