diff options
author | Russell King <rmk@arm.linux.org.uk> | 2014-08-26 09:22:20 +0100 |
---|---|---|
committer | Russell King <rmk@arm.linux.org.uk> | 2014-08-26 19:07:42 +0100 |
commit | e518c3ff34ac6805db6a234e0f1b990baac5bc5a (patch) | |
tree | 7ce336da9b729827eded66fb9666c4c04e77a427 | |
parent | affce951808ae2c5809a74520abfdb778ea52707 (diff) |
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 67d41c9..b14341e 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 @@ 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. |