diff options
author | Russell King <rmk@arm.linux.org.uk> | 2014-08-26 09:22:20 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2014-08-27 09:01:26 +0200 |
commit | 5fa8a35296c80f2b37888adabf68e0e3b995e865 (patch) | |
tree | 9875e0364dde8faa37ee84c6ded529d05d5854b0 | |
parent | 2a28d1d9dda5a45ca8cf67e25151733e30f30165 (diff) | |
download | etna_viv-5fa8a35296c80f2b37888adabf68e0e3b995e865.tar.gz etna_viv-5fa8a35296c80f2b37888adabf68e0e3b995e865.tar.xz |
Properly handle ioctl() returning EINTR
Jon Nettleton's kernel galcore driver can return EINTR while waiting
for user signals. With this galcore version, if we are waiting on a
command buffer galcore signal (to indicate that the buffer is now
available for re-use), and we are sent a user signal (eg, SIGALRM),
then ioctl() may return EINTR.
This causes etnaviv to believe that the galcore signal was received,
and it is safe to proceed with the next command buffer. In reality,
this can cause the GPU to scribble over memory which it should not,
and can cause the entire platform to lock up.
Signed-off-by: Russell King <rmk@arm.linux.org.uk>
-rw-r--r-- | src/etnaviv/viv.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/src/etnaviv/viv.c b/src/etnaviv/viv.c index 13504b5..f7ca6b2 100644 --- a/src/etnaviv/viv.c +++ b/src/etnaviv/viv.c @@ -26,6 +26,7 @@ #include <unistd.h> #include <stdlib.h> #include <stdbool.h> +#include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> @@ -113,7 +114,18 @@ static int viv_ioctl(struct viv_conn *conn, int request, void *data, size_t size .out_buf_size = size #endif }; - return ioctl(conn->fd, request, &ic); + int ret, old_errno = errno; + + do { + errno = 0; + ret = ioctl(conn->fd, request, &ic); + } while (ret == -1 && errno == EINTR); + + /* if there was no error, restore the old errno for proper errno handling */ + if(errno == 0) + errno = old_errno; + + return ret; } /* Call ioctl interface with structure cmd as input and output. |