{"action":"created","issue":{"url":"https://api.github.com/repos/raspberrypi/linux/issues/760","labels_url":"https://api.github.com/repos/raspberrypi/linux/issues/760/labels{/name}","comments_url":"https://api.github.com/repos/raspberrypi/linux/issues/760/comments","events_url":"https://api.github.com/repos/raspberrypi/linux/issues/760/events","html_url":"https://github.com/raspberrypi/linux/issues/760","id":53623605,"number":760,"title":"lost gpio interrupts","user":{"login":"chaosjug","id":3767486,"avatar_url":"https://avatars.githubusercontent.com/u/3767486?v=3","gravatar_id":"","url":"https://api.github.com/users/chaosjug","html_url":"https://github.com/chaosjug","followers_url":"https://api.github.com/users/chaosjug/followers","following_url":"https://api.github.com/users/chaosjug/following{/other_user}","gists_url":"https://api.github.com/users/chaosjug/gists{/gist_id}","starred_url":"https://api.github.com/users/chaosjug/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chaosjug/subscriptions","organizations_url":"https://api.github.com/users/chaosjug/orgs","repos_url":"https://api.github.com/users/chaosjug/repos","events_url":"https://api.github.com/users/chaosjug/events{/privacy}","received_events_url":"https://api.github.com/users/chaosjug/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":22,"created_at":"2015-01-07T11:37:21Z","updated_at":"2015-01-12T17:19:38Z","closed_at":null,"body":"If gpio interrupts on different gpios occur on almost the same time, sometime some of them seem to get lost.\r\n\r\nThis is what I do to test this issue.\r\n\r\nCreate 100 Interrupts with pigpio and this code (wave.c):\r\n```c\r\n#include <stdio.h>\r\n#include <pigpio.h>\r\n\r\n#define PULSE 200\r\n#define GPIO 12\r\n\r\nint main()\r\n{\r\n\tint i, wave_id, len;\r\n\tgpioPulse_t pulse[PULSE];\r\n\tuint32_t g_mask;\r\n\t\r\n\tg_mask |= (1<<GPIO);\r\n\t\r\n\tif (gpioInitialise()<0) return 1;\r\n\t\r\n\tfor (i=0; i<PULSE; i += 2) {\r\n\t\tpulse[i].gpioOn  = g_mask;\r\n\t\tpulse[i].gpioOff = 0;\r\n\t\tpulse[i].usDelay = 1000;\r\n\t\tpulse[i+1].gpioOn  = 0;\r\n\t\tpulse[i+1].gpioOff = g_mask;\r\n\t\tpulse[i+1].usDelay = 1000;\r\n\t}\r\n\tgpioSetMode(GPIO, PI_OUTPUT);\r\n\tgpioWaveClear();\r\n\tgpioWaveAddGeneric(PULSE, pulse);\r\n\twave_id = gpioWaveCreate();\r\n\tgpioWaveTxSend(wave_id, PI_WAVE_MODE_ONE_SHOT);\r\n\t\r\n\tlen = gpioWaveGetMicros();\r\n\tgpioDelay(PULSE*1000);\r\n\t\r\n\tgpioTerminate();\r\n\treturn 0;\r\n}\r\n```\r\n\r\nConnect the gpio to two other gpios (in my case connect 12 to 4 and 22.\r\nExport gpios in sysfs and enable interrupt:\r\n\r\n```\r\necho 4 > /sys/class/gpio/export\r\necho rising > /sys/class/gpio/gpio4/edge\r\necho 22 > /sys/class/gpio/export\r\necho rising > /sys/class/gpio/gpio22/edge\r\n```\r\n\r\ncount interrupts with this code (cnt_irqs.c):\r\n```c\r\n#include <stdio.h>\r\n#include <poll.h>\r\n#include <stdlib.h>\r\n#include <fcntl.h>\r\n#include <string.h>\r\n#include <time.h>\r\n\r\n#define GPIO_FN_MAXLEN\t32\r\n#define POLL_TIMEOUT\t5000\r\n#define RDBUF_LEN\t5\r\n\r\nint main(int argc, char **argv) {\r\n\tchar fn[GPIO_FN_MAXLEN];\r\n\tint fd,ret,cnt;\r\n\tstruct pollfd pfd;\r\n\tchar rdbuf[RDBUF_LEN];\r\n\tstruct timespec old_t, new_t;\r\n\r\n\tmemset(rdbuf, 0x00, RDBUF_LEN);\r\n\tif(argc!=2) {\r\n\t\tprintf(\"Usage: %s <GPIO>\\nGPIO must be exported to sysfs and have enabled edge detection\\n\", argv[0]);\r\n\t\treturn 1;\r\n\t}\r\n\tsnprintf(fn, GPIO_FN_MAXLEN-1, \"/sys/class/gpio/gpio%s/value\", argv[1]);\r\n\tfd=open(fn, O_RDONLY);\r\n\tif(fd<0) {\r\n\t\tperror(fn);\r\n\t\treturn 2;\r\n\t}\r\n\tpfd.fd=fd;\r\n\tpfd.events=POLLPRI;\r\n\t\r\n\tret=read(fd, rdbuf, RDBUF_LEN-1);\r\n\tif(ret<0) {\r\n\t\tperror(\"read()\");\r\n\t\treturn 4;\r\n\t}\r\n\tprintf(\"value is: %s\\n\", rdbuf);\r\n\t\r\n\tclock_gettime(CLOCK_REALTIME, &old_t);\r\n\tcnt = 0;\r\n\twhile(1) {\r\n\t\tmemset(rdbuf, 0x00, RDBUF_LEN);\r\n\t\tlseek(fd, 0, SEEK_SET);\r\n\t\tret=poll(&pfd, 1, POLL_TIMEOUT);\r\n\t\tif(ret<0) {\r\n\t\t\tperror(\"poll()\");\r\n\t\t\tclose(fd);\r\n\t\t\treturn 3;\r\n\t\t}\r\n\t\tif(ret==0) {\r\n\t\t\tprintf(\"timeout\\n\");\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tret=read(fd, rdbuf, RDBUF_LEN-1);\r\n\t\tif(ret<0) {\r\n\t\t\tperror(\"read()\");\r\n\t\t\treturn 4;\r\n\t\t}\r\n\t\tcnt++;\r\n\t}\r\n\tclose(fd);\r\n\tprintf(\"%d interupts\\n\", cnt);\r\n\treturn 0;\r\n}\r\n```\r\n\r\nWhat I do now is open 3 shells on the pi. In short order I start `./cnt_irqs 4`, `./cnt_irqs 22` and ` sudo ./wave`\r\nI would now expect `100 interupts` as a result on both cnt_irqs, but I usually get something between 95 and 99.\r\nIf I start only one cnt_irqs then I get the expected 100 interrupts.\r\n\r\nwhen I look at bcm2708_gpio_interrupt in bcm2708_gpio.c,\r\n```c\r\nstatic irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id)\r\n{\r\n\tunsigned long edsr;\r\n\tunsigned bank;\r\n\tint i;\r\n\tunsigned gpio;\r\n\tfor (bank = 0; bank <= 1; bank++) {\r\n\t\tedsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank));\r\n\t\tfor_each_set_bit(i, &edsr, 32) {\r\n\t\t\tgpio = i + bank * 32;\r\n\t\t\tgeneric_handle_irq(gpio_to_irq(gpio));\r\n\t\t}\r\n \twritel(0xffffffff, __io_address(GPIO_BASE) + GPIOEDS(bank));\r\n\t}\r\n\treturn IRQ_HANDLED;\r\n}\r\n```\r\nThe `writel(0xffffffff, __io_address(GPIO_BASE) + GPIOEDS(bank));` seems to be the problem, as it resets all bit. So if an interrupt occurs during the for_each_bit loop, it will not get handled.\r\n\r\nIf I add `writel(1<<i,__io_address(GPIO_BASE) + GPIOEDS(bank));` in the loop instead, it seems to work for me.\r\n\r\nI got the idea from [here](http://www.raspberrypi.org/forums/viewtopic.php?f=44&t=35371) where similar issues were discussed.\r\n"},"comment":{"url":"https://api.github.com/repos/raspberrypi/linux/issues/comments/69607176","html_url":"https://github.com/raspberrypi/linux/issues/760#issuecomment-69607176","issue_url":"https://api.github.com/repos/raspberrypi/linux/issues/760","id":69607176,"user":{"login":"pelwell","id":8911409,"avatar_url":"https://avatars.githubusercontent.com/u/8911409?v=3","gravatar_id":"","url":"https://api.github.com/users/pelwell","html_url":"https://github.com/pelwell","followers_url":"https://api.github.com/users/pelwell/followers","following_url":"https://api.github.com/users/pelwell/following{/other_user}","gists_url":"https://api.github.com/users/pelwell/gists{/gist_id}","starred_url":"https://api.github.com/users/pelwell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pelwell/subscriptions","organizations_url":"https://api.github.com/users/pelwell/orgs","repos_url":"https://api.github.com/users/pelwell/repos","events_url":"https://api.github.com/users/pelwell/events{/privacy}","received_events_url":"https://api.github.com/users/pelwell/received_events","type":"User","site_admin":false},"created_at":"2015-01-12T17:19:38Z","updated_at":"2015-01-12T17:19:38Z","body":"I've got a patch that prevents ...irq_mask and ...irq_unmask from being called for each interrupt. The code is based on that in pinctrl-bcm2835.c, and works by requesting that handle_simple_irq is used instead of handle_level_irq. The patch also removes the write to the EDS register in ...irq_unmask.\r\n\r\nYou can find the patch here: http://pastebin.com/DS5Redjs\r\n"}}