summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
index 84e9627aa..df9dbc902 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -110,6 +110,7 @@ struct dvb_frontend_data {
int max_drift;
int step_size;
int exit;
+ int wakeup;
fe_status_t status;
};
@@ -460,6 +461,19 @@ static int dvb_frontend_is_exiting (struct dvb_frontend_data *fe)
return 0;
}
+static int dvb_frontend_should_wakeup (struct dvb_frontend_data *fe)
+{
+ if (fe->wakeup) {
+ fe->wakeup = 0;
+ return 1;
+ }
+ return dvb_frontend_is_exiting(fe);
+}
+
+static void dvb_frontend_wakeup (struct dvb_frontend_data *fe) {
+ fe->wakeup = 1;
+ wake_up_interruptible(&fe->wait_queue);
+}
static int dvb_frontend_thread (void *data)
{
@@ -483,7 +497,7 @@ static int dvb_frontend_thread (void *data)
while (1) {
up (&fe->sem); /* is locked when we enter the thread... */
- timeout = wait_event_interruptible_timeout(fe->wait_queue,0 != dvb_frontend_is_exiting (fe), delay);
+ timeout = wait_event_interruptible_timeout(fe->wait_queue,0 != dvb_frontend_should_wakeup (fe), delay);
if (-ERESTARTSYS == timeout || 0 != dvb_frontend_is_exiting (fe)) {
/* got signal or quitting */
break;
@@ -578,6 +592,7 @@ static int dvb_frontend_thread (void *data)
// tune occurs
if (fe->state & FESTATE_RETUNE) {
fe->state = FESTATE_TUNING_FAST;
+ dvb_frontend_wakeup(fe);
}
}
@@ -599,7 +614,7 @@ static int dvb_frontend_thread (void *data)
fe->thread_pid = 0;
mb();
- wake_up_interruptible (&fe->wait_queue);
+ dvb_frontend_wakeup(fe);
return 0;
}
@@ -626,7 +641,7 @@ static void dvb_frontend_stop (struct dvb_frontend_data *fe)
}
/* wake up the frontend thread, so it notices that fe->exit == 1 */
- wake_up_interruptible(&fe->wait_queue);
+ dvb_frontend_wakeup(fe);
/* wait until the frontend thread has exited */
ret = wait_event_interruptible(fe->wait_queue,0 == fe->thread_pid);
@@ -791,13 +806,8 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
// This ensures the app doesn't start reading data too quickly, perhaps from the
// previous lock, which is REALLY CONFUSING TO DEBUG!
if ((cmd == FE_SET_FRONTEND) && (err == 0)) {
- // note: cannot use wait_event_interruptible_* here as that
- // causes the thread not to wake until AFTER the call here returns. This is useless
- // because the whole point is to have the thread wake first, and perform at least one tune
- wake_up_interruptible(&fe->wait_queue);
- while(fe->state & FESTATE_RETUNE) {
- dvb_delay(10);
- }
+ dvb_frontend_wakeup(fe);
+ err = wait_event_interruptible(fe->wait_queue, fe->state & ~FESTATE_RETUNE);
}
return err;