summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAkihiro Tsukada <tskd08@gmail.com>2017-07-10 04:40:13 -0400
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-07-20 15:01:30 -0400
commitd0a0548adeee87ac2d7890d15dfd3800db2099e6 (patch)
tree8eee965b3c85b5fef8fafc57fef936ffca144fcd /drivers
parent62055056da6a722ab770d45bad63ed41dfb4f283 (diff)
media: media/dvb: earth-pt3: fix hang-up in a rare case
When a user starts and stops filtering at a demux device too quickly in a very short interval, the user process hangs in uninterruptible sleep, due to an inconsistency of kthread status in the driver. The kthread can be stopped before it starts running its thread function, but the invocation status was partly managed in the kthread function, which resulted in a double kthread_stop() of one kthread. Signed-off-by: Akihiro Tsukada <tskd08@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/pci/pt3/pt3.c11
1 files changed, 3 insertions, 8 deletions
diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c
index e8b5d0992157..34044a45fecc 100644
--- a/drivers/media/pci/pt3/pt3.c
+++ b/drivers/media/pci/pt3/pt3.c
@@ -472,7 +472,6 @@ static int pt3_fetch_thread(void *data)
}
dev_dbg(adap->dvb_adap.device, "PT3: [%s] exited\n",
adap->thread->comm);
- adap->thread = NULL;
return 0;
}
@@ -486,6 +485,7 @@ static int pt3_start_streaming(struct pt3_adapter *adap)
if (IS_ERR(thread)) {
int ret = PTR_ERR(thread);
+ adap->thread = NULL;
dev_warn(adap->dvb_adap.device,
"PT3 (adap:%d, dmx:%d): failed to start kthread\n",
adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
@@ -508,6 +508,7 @@ static int pt3_stop_streaming(struct pt3_adapter *adap)
/* kill the fetching thread */
ret = kthread_stop(adap->thread);
+ adap->thread = NULL;
return ret;
}
@@ -520,14 +521,8 @@ static int pt3_start_feed(struct dvb_demux_feed *feed)
adap = container_of(feed->demux, struct pt3_adapter, demux);
adap->num_feeds++;
- if (adap->thread)
+ if (adap->num_feeds > 1)
return 0;
- if (adap->num_feeds != 1) {
- dev_warn(adap->dvb_adap.device,
- "%s: unmatched start/stop_feed in adap:%i/dmx:%i\n",
- __func__, adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
- adap->num_feeds = 1;
- }
return pt3_start_streaming(adap);