summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2014-08-26 09:22:20 +0100
committerRussell King <rmk@arm.linux.org.uk>2014-08-26 19:07:42 +0100
commite518c3ff34ac6805db6a234e0f1b990baac5bc5a (patch)
tree7ce336da9b729827eded66fb9666c4c04e77a427
parentaffce951808ae2c5809a74520abfdb778ea52707 (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.c14
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.