aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAntonio Borneo <borneo.antonio@gmail.com>2019-09-05 10:48:12 +0200
committerTomas Vanek <vanekt@fbl.cz>2019-12-19 20:42:01 +0000
commit49d71d06d19e1b5006c8be5b35319658654dfe21 (patch)
tree2dc6bc3dc9205548bddd358259f50bf68f1764c9 /src
parent964c4db9cec3e619545490ccb525be210e8008d5 (diff)
sysfsgpio: give time to udev to change gpio permission
When a gpio is exported by writing in /sys/class/gpio/export, the corresponding gpio control files appear immediately in sysfs but with default access permission for root user only. The daemon udev requires some time to get notified of the new files before it can change the permissions to allow access to unprivileged users. Due to this race condition, sysfsgpio can fail with EACCES error if OpenOCD is executed by any unprivileged user. Give 0.5 seconds to udev to identify the new files and change the permission. Tested with udev rules: SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'find -L /sys/class/gpio/ -maxdepth 2 -exec chown root:uucp {} \; -exec chmod g=u {} \; || true'" Change-Id: I1316c66ff103ffe23e5e4720f33372dc272a3766 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/5302 Tested-by: jenkins Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Diffstat (limited to 'src')
-rw-r--r--src/jtag/drivers/sysfsgpio.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c
index eb4941e6..c6ffa320 100644
--- a/src/jtag/drivers/sysfsgpio.c
+++ b/src/jtag/drivers/sysfsgpio.c
@@ -52,6 +52,7 @@
#include "config.h"
#endif
+#include <helper/time_support.h>
#include <jtag/interface.h>
#include "bitbang.h"
@@ -112,6 +113,7 @@ static void unexport_sysfs_gpio(int gpio)
*/
static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
{
+ struct timeval timeout, now;
char buf[40];
char gpiostr[5];
int ret;
@@ -131,8 +133,19 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
}
}
+ gettimeofday(&timeout, NULL);
+ timeval_add_time(&timeout, 0, 500000);
+
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
- ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
+ for (;;) {
+ ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
+ if (ret >= 0 || errno != EACCES)
+ break;
+ gettimeofday(&now, NULL);
+ if (timeval_compare(&now, &timeout) >= 0)
+ break;
+ jtag_sleep(10000);
+ }
if (ret < 0) {
LOG_ERROR("Couldn't set direction for gpio %d", gpio);
perror("sysfsgpio: ");
@@ -141,7 +154,15 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
}
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);
- ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
+ for (;;) {
+ ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
+ if (ret >= 0 || errno != EACCES)
+ break;
+ gettimeofday(&now, NULL);
+ if (timeval_compare(&now, &timeout) >= 0)
+ break;
+ jtag_sleep(10000);
+ }
if (ret < 0) {
LOG_ERROR("Couldn't open value for gpio %d", gpio);
perror("sysfsgpio: ");