Fix #1666 - dvb: rework the adapter tuning to stop possible deadlock
This commit is contained in:
parent
4f2f68a4b6
commit
d75b99a610
3 changed files with 52 additions and 123 deletions
|
@ -209,6 +209,7 @@ typedef struct th_dvb_adapter {
|
|||
uint32_t tda_enabled;
|
||||
|
||||
int tda_locked;
|
||||
time_t tda_monitor;
|
||||
|
||||
const char *tda_rootpath;
|
||||
char *tda_identifier;
|
||||
|
@ -250,7 +251,6 @@ typedef struct th_dvb_adapter {
|
|||
struct service_list tda_transports; /* Currently bound transports */
|
||||
|
||||
gtimer_t tda_fe_monitor_timer;
|
||||
int tda_fe_monitor_hold;
|
||||
|
||||
int tda_sat; // Set if this adapter is a satellite receiver (DVB-S, etc)
|
||||
|
||||
|
|
|
@ -1020,13 +1020,25 @@ static void *
|
|||
dvb_adapter_input_dvr(void *aux)
|
||||
{
|
||||
th_dvb_adapter_t *tda = aux;
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
int fd = -1, i, r, c, efd, nfds, dmx = -1;
|
||||
uint8_t tsb[188 * 10];
|
||||
service_t *t;
|
||||
struct epoll_event ev;
|
||||
int delay = 10, locked = 0;
|
||||
fe_status_t festat;
|
||||
int delay = 10;
|
||||
|
||||
/* Install RAW demux */
|
||||
if (tda->tda_rawmode) {
|
||||
if ((dmx = dvb_adapter_raw_filter(tda)) == -1) {
|
||||
tvhlog(LOG_ALERT, "dvb", "Unable to install raw mux filter");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open DVR */
|
||||
if ((fd = tvh_open(tda->tda_dvr_path, O_RDONLY | O_NONBLOCK, 0)) == -1) {
|
||||
close(dmx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create poll */
|
||||
efd = epoll_create(2);
|
||||
|
@ -1034,6 +1046,8 @@ dvb_adapter_input_dvr(void *aux)
|
|||
ev.events = EPOLLIN;
|
||||
ev.data.fd = tda->tda_dvr_pipe.rd;
|
||||
epoll_ctl(efd, EPOLL_CTL_ADD, tda->tda_dvr_pipe.rd, &ev);
|
||||
ev.data.fd = fd;
|
||||
epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev);
|
||||
|
||||
r = i = 0;
|
||||
while(1) {
|
||||
|
@ -1041,62 +1055,12 @@ dvb_adapter_input_dvr(void *aux)
|
|||
/* Wait for input */
|
||||
nfds = epoll_wait(efd, &ev, 1, delay);
|
||||
|
||||
/* Exit */
|
||||
if ((nfds > 0) && (ev.data.fd != fd)) break;
|
||||
|
||||
/* Check for lock */
|
||||
if (!locked) {
|
||||
if (ioctl(tda->tda_fe_fd, FE_READ_STATUS, &festat))
|
||||
continue;
|
||||
if (!(festat & FE_HAS_LOCK))
|
||||
continue;
|
||||
|
||||
/* Open DVR */
|
||||
fd = tvh_open(tda->tda_dvr_path, O_RDONLY | O_NONBLOCK, 0);
|
||||
if (fd == -1) {
|
||||
tvhlog(LOG_ALERT, "dvb", "Unable to open %s -- %s",
|
||||
tda->tda_dvr_path, strerror(errno));
|
||||
break;
|
||||
}
|
||||
ev.data.fd = fd;
|
||||
epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev);
|
||||
|
||||
/* Note: table handlers must be installed with global lock */
|
||||
pthread_mutex_lock(&global_lock);
|
||||
tda->tda_locked = locked = 1;
|
||||
delay = -1;
|
||||
if ((tdmi = tda->tda_mux_current)) {
|
||||
|
||||
/* Install table handlers */
|
||||
dvb_table_add_default(tdmi);
|
||||
epggrab_mux_start(tdmi);
|
||||
|
||||
/* Raw filter */
|
||||
if(tda->tda_rawmode)
|
||||
dmx = dvb_adapter_raw_filter(tda);
|
||||
|
||||
/* Service filters */
|
||||
pthread_mutex_lock(&tda->tda_delivery_mutex);
|
||||
LIST_FOREACH(t, &tda->tda_transports, s_active_link) {
|
||||
if (t->s_dvb_mux_instance == tdmi) {
|
||||
tda->tda_open_service(tda, t);
|
||||
dvb_table_add_pmt(tdmi, t->s_pmt_pid);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&tda->tda_delivery_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
/* Error */
|
||||
if (tda->tda_rawmode && (dmx == -1)) {
|
||||
tvhlog(LOG_ALERT, "dvb", "Unable to install raw mux filter");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No data */
|
||||
if (nfds < 1) continue;
|
||||
|
||||
/* Exit */
|
||||
if (ev.data.fd != fd) break;
|
||||
|
||||
/* Read data */
|
||||
c = read(fd, tsb+r, sizeof(tsb)-r);
|
||||
if (c < 0) {
|
||||
|
|
|
@ -101,8 +101,6 @@ dvb_fe_monitor(void *aux)
|
|||
int store = 0;
|
||||
int notify = 0;
|
||||
|
||||
gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);
|
||||
|
||||
if(tdmi == NULL)
|
||||
return;
|
||||
|
||||
|
@ -110,9 +108,8 @@ dvb_fe_monitor(void *aux)
|
|||
* Read out front end status
|
||||
*/
|
||||
if(ioctl(tda->tda_fe_fd, FE_READ_STATUS, &fe_status))
|
||||
fe_status = 0;
|
||||
|
||||
if(fe_status & FE_HAS_LOCK)
|
||||
status = TDMI_FE_UNKNOWN;
|
||||
else if(fe_status & FE_HAS_LOCK)
|
||||
status = -1;
|
||||
else if(fe_status & (FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER))
|
||||
status = TDMI_FE_BAD_SIGNAL;
|
||||
|
@ -121,18 +118,34 @@ dvb_fe_monitor(void *aux)
|
|||
else
|
||||
status = TDMI_FE_NO_SIGNAL;
|
||||
|
||||
if(tda->tda_fe_monitor_hold > 0) {
|
||||
/* Post tuning threshold */
|
||||
if(status == -1) { /* We have a lock, don't hold off */
|
||||
tda->tda_fe_monitor_hold = 0;
|
||||
/* Reset FEC counter */
|
||||
dvb_fe_get_unc(tda);
|
||||
/**
|
||||
* Waiting for initial lock
|
||||
*/
|
||||
if(tda->tda_locked == 0) {
|
||||
|
||||
/* Read */
|
||||
if (status == -1) {
|
||||
tda->tda_locked = 1;
|
||||
dvb_adapter_start(tda, TDA_OPT_ALL);
|
||||
gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);
|
||||
|
||||
/* Re-arm (50ms) */
|
||||
} else {
|
||||
tda->tda_fe_monitor_hold--;
|
||||
return;
|
||||
gtimer_arm_ms(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 50);
|
||||
|
||||
/* Monitor (1 per sec) */
|
||||
if (dispatch_clock < tda->tda_monitor)
|
||||
return;
|
||||
tda->tda_monitor = dispatch_clock + 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update stats
|
||||
*/
|
||||
if(status == -1) {
|
||||
/* Read FEC counter (delta) */
|
||||
|
||||
|
@ -312,46 +325,6 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune)
|
|||
|
||||
#if DVB_API_VERSION >= 5
|
||||
|
||||
static int check_frontend (int fe_fd, int dvr, int human_readable) {
|
||||
(void)dvr;
|
||||
fe_status_t status;
|
||||
uint16_t snr, signal;
|
||||
uint32_t ber;
|
||||
int timeout = 0;
|
||||
|
||||
do {
|
||||
if (ioctl(fe_fd, FE_READ_STATUS, &status) == -1)
|
||||
perror("FE_READ_STATUS failed");
|
||||
/* some frontends might not support all these ioctls, thus we
|
||||
* avoid printing errors
|
||||
*/
|
||||
if (ioctl(fe_fd, FE_READ_SIGNAL_STRENGTH, &signal) == -1)
|
||||
signal = -2;
|
||||
if (ioctl(fe_fd, FE_READ_SNR, &snr) == -1)
|
||||
snr = -2;
|
||||
if (ioctl(fe_fd, FE_READ_BER, &ber) == -1)
|
||||
ber = -2;
|
||||
|
||||
if (human_readable) {
|
||||
printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | ",
|
||||
status, (signal * 100) / 0xffff, (snr * 100) / 0xffff, ber);
|
||||
} else {
|
||||
printf ("status %02x | signal %04x | snr %04x | ber %08x | ",
|
||||
status, signal, snr, ber);
|
||||
}
|
||||
if (status & FE_HAS_LOCK)
|
||||
printf("FE_HAS_LOCK");
|
||||
printf("\n");
|
||||
|
||||
if ((status & FE_HAS_LOCK) || (++timeout >= 10))
|
||||
break;
|
||||
|
||||
usleep(1000000);
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dtv_property clear_p[] = {
|
||||
{ .cmd = DTV_CLEAR },
|
||||
};
|
||||
|
@ -361,7 +334,6 @@ static struct dtv_properties clear_cmdseq = {
|
|||
.props = clear_p
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -404,8 +376,6 @@ dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc)
|
|||
/* do tuning now */
|
||||
r = ioctl(tda->tda_fe_fd, FE_SET_PROPERTY, &_dvbs_cmdseq);
|
||||
|
||||
if(0)
|
||||
check_frontend (tda->tda_fe_fd, 0, 1);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
@ -493,8 +463,6 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
|
|||
|
||||
dvb_mux_nicename(buf, sizeof(buf), tdmi);
|
||||
|
||||
tda->tda_fe_monitor_hold = 4;
|
||||
|
||||
#if DVB_API_VERSION >= 5
|
||||
if (tda->tda_type == FE_QPSK) {
|
||||
tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning via s2api to \"%s\" (%d, %d Baud, "
|
||||
|
@ -524,19 +492,16 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
|
|||
/* Mark as bad */
|
||||
if (errno == EINVAL)
|
||||
dvb_mux_set_enable(tdmi, 0);
|
||||
|
||||
dvb_adapter_stop(tda, TDA_OPT_ALL);
|
||||
return SM_CODE_TUNING_FAILED;
|
||||
}
|
||||
|
||||
tda->tda_mux_current = tdmi;
|
||||
|
||||
dvb_adapter_start(tda, TDA_OPT_ALL);
|
||||
|
||||
gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);
|
||||
|
||||
#if 0
|
||||
dvb_table_add_default(tdmi);
|
||||
epggrab_mux_start(tdmi);
|
||||
#endif
|
||||
time(&tda->tda_monitor);
|
||||
tda->tda_monitor += 4; // wait a few secs before monitoring (unlocked)
|
||||
gtimer_arm_ms(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 50);
|
||||
|
||||
dvb_adapter_notify(tda);
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue