Em Wed, 10 Jun 2015 18:27:30 +0100
Andy Furniss <adf.li...@gmail.com> escreveu:

> Mauro Carvalho Chehab wrote:
> 
> > Just applied a fix for it:
> >     
> > http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=c7c9af17163f282a147ea76f1a3c0e9a0a86e7fa
> >
> > It will retry up to 10 times. This should very likely be enough if the
> > driver doesn't have any bug.
> >
> > Please let me know if this fixes the issue.
> 
> No, it doesn't, so I reverted the above and added back my hack + a 
> counter as below and it seems to be retrying > a million times.

Hmm.... that's likely a bug at the demod driver. It doesn't make much
sense to keep a mutex hold for that long. 

Anyway, I modified the patch to use a timeout of 1 second, instead of
trying 10 times. It is still a hack, as IMHO this is a driver bug,
but it should produce a better result.

Please check if the patch below works for you.

You may change the MAX_TIME there if 1 second is not enough.

It could be interesting if you add a printf with the difference
between start and end time, for us to have an idea about how
much time the driver is kept on such unreliable state.

Thanks!
Mauro


[PATCH] libdvbv5: use a timeout for ioctl

Some frontends don't play nice: they return -EAGAIN if the
device doesn't lock. That actually means that it may take
some time for some ioctl's to succeed. On experimental tests,
the loop may happen ~2 million times!

Well, better to waste power on a loop than to fail. So, let's
change the code that detects EAGAIN by a loop that waits up
to 1 second.

This is not the right thing to do, but the Kernel drivers
require fixes. We can do it only for newer versions of the
Kernel.

Signed-off-by: Mauro Carvalho Chehab <mche...@osg.samsung.com>

diff --git a/lib/libdvbv5/dvb-demux.c b/lib/libdvbv5/dvb-demux.c
index 867d7b9dddde..af124ae3a7cc 100644
--- a/lib/libdvbv5/dvb-demux.c
+++ b/lib/libdvbv5/dvb-demux.c
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <time.h>
 #include <errno.h>
 
 #include <sys/ioctl.h>
@@ -40,12 +41,25 @@
 
 #include <libdvbv5/dvb-demux.h>
 
+#define MAX_TIME               10      /* 1.0 seconds */
+
 #define xioctl(fh, request, arg...) ({                                 \
-       int __rc, __retry;                                              \
+       int __rc;                                                       \
+       struct timespec __start, __end;                                 \
                                                                        \
-       for (__retry = 0; __retry < 10; __retry++) {                    \
+       clock_gettime(CLOCK_MONOTONIC, &__start);                       \
+       do {                                                            \
                __rc = ioctl(fh, request, ##arg);                       \
-       } while (__rc == -1 && ((errno == EINTR) || (errno == EAGAIN)));\
+               if (__rc != -1)                                         \
+                       break;                                          \
+               if (!((errno == EINTR) | (errno == EAGAIN)))            \
+                       break;                                          \
+               clock_gettime(CLOCK_MONOTONIC, &__end);                 \
+               if (__end.tv_sec * 10 + __end.tv_nsec / 100000000 >     \
+                   __start.tv_sec * 10 + __start.tv_nsec / 100000000 + \
+                   MAX_TIME)                                           \
+                       break;                                          \
+       } while (1);                                                    \
                                                                        \
        __rc;                                                           \
 })
diff --git a/lib/libdvbv5/dvb-fe.c b/lib/libdvbv5/dvb-fe.c
index 48b09cd9ceaa..8607401841f2 100644
--- a/lib/libdvbv5/dvb-fe.c
+++ b/lib/libdvbv5/dvb-fe.c
@@ -26,6 +26,7 @@
 #include <inttypes.h>
 #include <math.h>
 #include <stddef.h>
+#include <time.h>
 #include <unistd.h>
 
 #include <config.h>
@@ -43,12 +44,25 @@ static int libdvbv5_initialized = 0;
 
 # define N_(string) string
 
+#define MAX_TIME               10      /* 1.0 seconds */
+
 #define xioctl(fh, request, arg...) ({                                 \
-       int __rc, __retry;                                              \
+       int __rc;                                                       \
+       struct timespec __start, __end;                                 \
                                                                        \
-       for (__retry = 0; __retry < 10; __retry++) {                    \
+       clock_gettime(CLOCK_MONOTONIC, &__start);                       \
+       do {                                                            \
                __rc = ioctl(fh, request, ##arg);                       \
-       } while (__rc == -1 && ((errno == EINTR) || (errno == EAGAIN)));\
+               if (__rc != -1)                                         \
+                       break;                                          \
+               if (!((errno == EINTR) | (errno == EAGAIN)))            \
+                       break;                                          \
+               clock_gettime(CLOCK_MONOTONIC, &__end);                 \
+               if (__end.tv_sec * 10 + __end.tv_nsec / 100000000 >     \
+                   __start.tv_sec * 10 + __start.tv_nsec / 100000000 + \
+                   MAX_TIME)                                           \
+                       break;                                          \
+       } while (1);                                                    \
                                                                        \
        __rc;                                                           \
 })

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to