aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Nieder <jrnieder@gmail.com>2011-05-01 05:29:37 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-20 08:29:36 -0400
commit1fe70e963028f34ba5e32488a7870ff4b410b19b (patch)
tree8185ba45b69831b8cb6a1b1aef5cb84ea092b8cc
parent8a317a8760cfffa8185b56ff59fb4b6c58488d79 (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>
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c4
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c3
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c4
-rw-r--r--drivers/media/video/cx88/cx88.h3
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 */