-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rpi-3.11.y - use of gpio_to_irq hangs kernel #389
Comments
Looking at the code:
so gpio_to_irq(MCP2515_CAN_INT_GPIO_PIN) = 25 + 64+21 + 64+21 = 195 Does this work with 3.10.y kernel? |
The problem is that in the current code the kernel does not even PRINT anything on the serial console - I think it gets stuck prior to the usart being configured for output... So any additional printk will not work - and there is already a printk after the assign... I believe just adding a line: "gpio_to_irq(MCP2515_CAN_INT_GPIO_PIN)" in the function bcm2708_init will do the same... I have been compiling it as is - and the objdump of the object file shows that: So there is no macro that handles that! Ciao, P.s: here the assembler code for the section showing that it is an actual call to the function __gpio_to_irq:
|
One observation: That is quite a confusing and dangerous change that got introduced somewhere after 3.6.y... (and if you look here you find a very old recipe stating <linux/gpio.h> with kernel 3.2.27+: http://lnxpps.de/rpie/) |
So if you include |
yes - the strange thing is that
was working with 3.6.y and earlier - so suspecting a change there is not very obvious... For me it is solved - but you may want to look at the "bigger picture" to find other issues that may be related... |
So I went back to a backup with the 3.6.y branch and looked at the generated object file there (compiled on the 25th march) and found that the assembly code directly loads 195 into a register - so it is using <mach/gpio.h>!
so something must have changed on the include structure so that <linux/gpio.h> does no longer include <mach/gpio.h> directly or indirectly... So there must be some other traps lurking as well in other places as that is probably not the only thing that has changed... |
There is a change in arch/arm/asm/gpio.h between 3.6 and 3.7 with regards to mach/gpio.h and gpio_to_irq. This is 3.6: http://lxr.free-electrons.com/source/arch/arm/include/asm/gpio.h?v=3.6;a=arm
This is 3.7: http://lxr.free-electrons.com/source/arch/arm/include/asm/gpio.h?v=3.7;a=arm
Commit: 0146422 linux/gpio.h includes arch/arm/asm/gpio.h because |
To finish up in the 3.11 case: A call to gpio_to_irq will always return Edit: I'm wrong in this use case. Since the driver is not loaded yet, it will return http://lxr.free-electrons.com/source/drivers/gpio/gpiolib.c?a=arm#L1970
This is because
|
Notro: to thanks for investigating. Still the question is: why does it only fail while running the board config - it works correctly after a boot when loading a module via modprobe - see spi-config as an example... This means that at some point in time during the boot the value must be set... So for now the workaround is to use the Mach include in bcm2708.c - or better still: use spi-config to define spi-settings on the fly... Martin |
I don't have an answer to this. It's rather strange. Have you checked that gpio_to_irq actually compiles to a function call in spi-config.c?
I rather think the solution would be to change arch/arm/Kconfig as was done in the commit I mentioned.
This should give the right gpio_to_irq macro when including linux/gpio.h |
Well, it does compile as a branch: objdump -Dz spi-config.o |grep -A3 -B 3 gpio_to As said: it only seems to effect the system during board-initialization - maybe gpio has not been set up correctly at that time and then the call runs into an exception - did not check on the serial at that time, so I can not tell you the details... Ciao, Martin |
Now I know why gpio_to_irq() fails in bcm2708.c, but works fine in a module. The gpio driver hasn't been probed yet in bcm2708_init(), which makes gpio_to_irq() return -EINVAL This include
gives (because CONFIG_NEED_MACH_GPIO_H is not defined)
gpio_to_desc() returns NULL, because there is no gpio_chip registered yet, which makes gpiod_to_irq() return -EINVAL In a module when the gpio driver already has been probed, chip->to_irq will point to bcm2708_gpio_to_irq() in bcm2708_gpio.c:
Here the mach/gpio.h macro is used, because of the include ordering in that file:
So the solution for bcm2708_init() is:
which gives
|
I did not want to recompile the whole kernel with NEED_MACH_GPIO_H as the "work-around" including: #include mach/gpio.h instead is good enough... Anything that uses it during the post-boot phase (when all portions are configured) using the standard gpio include is probably the better choice... The observation is really just in the board-config, so defining that overall might open up another can of worms... Still - there must have been a bit of reordering in the kernel after 3.6, that resulted in this reordering of the init sequence - (GPIO getting initialized after the board-config runs.) This also shows that there is some return value check missing somewhere, so that it "fails" with a lockup of the kernel (maybe a memory exception) prior to getting the UART up and running and thus we do not know where it is really stuck. Finally to admit - I have even moved away from modifying the board-config and instead use the "spi-config" module to define the spi devices on the fly when loading this driver - see http://github.com/msperl/spi-config. Martin |
I agree with Martin, I think it's better to leave this alone, since the "problem" only applies to the board-config, and there is a good solution to the problem. But to be honest: my real reason for not wanting this, is that I'm going to try and use the BCM2835 irq driver with BCM2708, and NEED_MACH_GPIO_H will break that. |
Well - there is a relatively simple patch to make the "upstream" spi-bcm2835 work. But in the end the spi-bcm2835 is still wasting lots of CPU-resources unnecessarily - the 2nd version of the SPI pipeline driver is much faster and does not require any CPU besides setup. And I am fighting to get an SPI-API extension in place to make DMA work with less setup cost, so that there is even less latency... Get in contact with me via the forum if you are interested, as you want to use it for your framebuffer drivers... |
I was referring to drivers/irqchip/irq-bcm2835.c |
Oh, you mean the one that would allow level interrupts... |
No, it replaces arch/arm/mach-bcm2708/armctrl.c Level interrupts is in drivers/pinctrl/pinctrl-bcm2835.c I wrote this page to understand the difference between BCM2708 and BCM2835: https://github.com/notro/rpi-firmware/wiki/BCM2708vsBCM2835 Right now I'm trying to understand the kernel boot process: https://github.com/notro/rpi-firmware/wiki/start_kernel |
IMHO the problem with the gpio_to_irq() crash is that it is easy to confuse the BCM2708's gpio_to_irq() macro from <mach/gpio.h> with the public subsystem's gpio_to_irq() from <linux/gpio.h>. Which one applies depends on which header is included first. There's no point in having duplicate names. Here's a patch to fix this. Tested on 3.10.y, compiled on 3.11.y. Please have a look and comment; I can push and submit a pull request if you prefer. Cheers,
|
Cool, thank you. Please note that my patch itself doesn't fix anything, it just resolves the gpio_to_irq() name conflict. This makes it explicit that gpio_to_irq() is a generic subsystem interface which has to be backed by a driver, whereas __bcm2708_gpio_to_irq() is board code. Btw __bcm2708_gpio_to_irq() is a constant macro - so one can initialize an interrupt line at compile time, rather than jump through hoops and calculate it at runtime. (This was already the case before I renamed it, of course.) For example,
|
commit 5b1c4bf upstream. When we are explicitly using GPIO hogging mechanism in the pinctrl node, such as: &pio { line_input { gpio-hog; gpios = <95 0>, <96 0>, <97 0>; input; }; }; A kernel panic happens at dereferencing a NULL pointer: In this case, the drvdata is still not setup properly yet when it is being accessed. A better solution for fixing up this issue should be we should obtain the private data from struct gpio_chip using a specific gpiochip_get_data instead of a generic dev_get_drvdata. [ 0.249424] Unable to handle kernel NULL pointer dereference at virtual address 000000c8 [ 0.257818] Mem abort info: [ 0.260704] ESR = 0x96000005 [ 0.263869] Exception class = DABT (current EL), IL = 32 bits [ 0.270011] SET = 0, FnV = 0 [ 0.273167] EA = 0, S1PTW = 0 [ 0.276421] Data abort info: [ 0.279398] ISV = 0, ISS = 0x00000005 [ 0.283372] CM = 0, WnR = 0 [ 0.286440] [00000000000000c8] user address but active_mm is swapper [ 0.293027] Internal error: Oops: 96000005 [#1] PREEMPT SMP [ 0.298795] Modules linked in: [ 0.301958] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.16.0-rc1+ #389 [ 0.308716] Hardware name: MediaTek MT7622 RFB1 board (DT) [ 0.314396] pstate: 80000005 (Nzcv daif -PAN -UAO) [ 0.319362] pc : mtk_hw_pin_field_get+0x28/0x118 [ 0.324140] lr : mtk_hw_set_value+0x30/0x104 [ 0.328557] sp : ffffff800801b6d0 [ 0.331983] x29: ffffff800801b6d0 x28: ffffff80086b7970 [ 0.337484] x27: 0000000000000000 x26: ffffff80087b8000 [ 0.342986] x25: 0000000000000000 x24: ffffffc00324c230 [ 0.348487] x23: 0000000000000003 x22: 0000000000000000 [ 0.353988] x21: ffffff80087b8000 x20: 0000000000000000 [ 0.359489] x19: 0000000000000054 x18: 00000000fffff7c0 [ 0.364990] x17: 0000000000006300 x16: 000000000000003f [ 0.370492] x15: 000000000000000e x14: ffffffffffffffff [ 0.375993] x13: 0000000000000000 x12: 0000000000000020 [ 0.381494] x11: 0000000000000006 x10: 0101010101010101 [ 0.386995] x9 : fffffffffffffffa x8 : 0000000000000007 [ 0.392496] x7 : ffffff80085d63f8 x6 : 0000000000000003 [ 0.397997] x5 : 0000000000000054 x4 : ffffffc0031eb800 [ 0.403499] x3 : ffffff800801b728 x2 : 0000000000000003 [ 0.409000] x1 : 0000000000000054 x0 : 0000000000000000 [ 0.414502] Process swapper/0 (pid: 1, stack limit = 0x000000002a913c1c) [ 0.421441] Call trace: [ 0.423968] mtk_hw_pin_field_get+0x28/0x118 [ 0.428387] mtk_hw_set_value+0x30/0x104 [ 0.432445] mtk_gpio_set+0x20/0x28 [ 0.436052] mtk_gpio_direction_output+0x18/0x30 [ 0.440833] gpiod_direction_output_raw_commit+0x7c/0xa0 [ 0.446333] gpiod_direction_output+0x104/0x114 [ 0.451022] gpiod_configure_flags+0xbc/0xfc [ 0.455441] gpiod_hog+0x8c/0x140 [ 0.458869] of_gpiochip_add+0x27c/0x2d4 [ 0.462928] gpiochip_add_data_with_key+0x338/0x5f0 [ 0.467976] mtk_pinctrl_probe+0x388/0x400 [ 0.472217] platform_drv_probe+0x58/0xa4 [ 0.476365] driver_probe_device+0x204/0x44c [ 0.480783] __device_attach_driver+0xac/0x108 [ 0.485384] bus_for_each_drv+0x7c/0xac [ 0.489352] __device_attach+0xa0/0x144 [ 0.493320] device_initial_probe+0x10/0x18 [ 0.497647] bus_probe_device+0x2c/0x8c [ 0.501616] device_add+0x2f8/0x540 [ 0.505226] of_device_add+0x3c/0x44 [ 0.508925] of_platform_device_create_pdata+0x80/0xb8 [ 0.514245] of_platform_bus_create+0x290/0x3e8 [ 0.518933] of_platform_populate+0x78/0x100 [ 0.523352] of_platform_default_populate+0x24/0x2c [ 0.528403] of_platform_default_populate_init+0x94/0xa4 [ 0.533903] do_one_initcall+0x98/0x130 [ 0.537874] kernel_init_freeable+0x13c/0x1d4 [ 0.542385] kernel_init+0x10/0xf8 [ 0.545903] ret_from_fork+0x10/0x18 [ 0.549603] Code: 900020a1 f9400800 911dcc21 1400001f (f9406401) [ 0.555916] ---[ end trace de8c34787fdad3b3 ]--- [ 0.560722] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b [ 0.560722] [ 0.570188] SMP: stopping secondary CPUs [ 0.574253] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b [ 0.574253] Cc: stable@vger.kernel.org Fixes: d6ed935 ("pinctrl: mediatek: add pinctrl driver for MT7622 SoC") Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
When we are explicitly using GPIO hogging mechanism in the pinctrl node, such as: &pio { line_input { gpio-hog; gpios = <95 0>, <96 0>, <97 0>; input; }; }; A kernel panic happens at dereferencing a NULL pointer: In this case, the drvdata is still not setup properly yet when it is being accessed. A better solution for fixing up this issue should be we should obtain the private data from struct gpio_chip using a specific gpiochip_get_data instead of a generic dev_get_drvdata. [ 0.249424] Unable to handle kernel NULL pointer dereference at virtual address 000000c8 [ 0.257818] Mem abort info: [ 0.260704] ESR = 0x96000005 [ 0.263869] Exception class = DABT (current EL), IL = 32 bits [ 0.270011] SET = 0, FnV = 0 [ 0.273167] EA = 0, S1PTW = 0 [ 0.276421] Data abort info: [ 0.279398] ISV = 0, ISS = 0x00000005 [ 0.283372] CM = 0, WnR = 0 [ 0.286440] [00000000000000c8] user address but active_mm is swapper [ 0.293027] Internal error: Oops: 96000005 [#1] PREEMPT SMP [ 0.298795] Modules linked in: [ 0.301958] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.16.0-rc1+ #389 [ 0.308716] Hardware name: MediaTek MT7622 RFB1 board (DT) [ 0.314396] pstate: 80000005 (Nzcv daif -PAN -UAO) [ 0.319362] pc : mtk_hw_pin_field_get+0x28/0x118 [ 0.324140] lr : mtk_hw_set_value+0x30/0x104 [ 0.328557] sp : ffffff800801b6d0 [ 0.331983] x29: ffffff800801b6d0 x28: ffffff80086b7970 [ 0.337484] x27: 0000000000000000 x26: ffffff80087b8000 [ 0.342986] x25: 0000000000000000 x24: ffffffc00324c230 [ 0.348487] x23: 0000000000000003 x22: 0000000000000000 [ 0.353988] x21: ffffff80087b8000 x20: 0000000000000000 [ 0.359489] x19: 0000000000000054 x18: 00000000fffff7c0 [ 0.364990] x17: 0000000000006300 x16: 000000000000003f [ 0.370492] x15: 000000000000000e x14: ffffffffffffffff [ 0.375993] x13: 0000000000000000 x12: 0000000000000020 [ 0.381494] x11: 0000000000000006 x10: 0101010101010101 [ 0.386995] x9 : fffffffffffffffa x8 : 0000000000000007 [ 0.392496] x7 : ffffff80085d63f8 x6 : 0000000000000003 [ 0.397997] x5 : 0000000000000054 x4 : ffffffc0031eb800 [ 0.403499] x3 : ffffff800801b728 x2 : 0000000000000003 [ 0.409000] x1 : 0000000000000054 x0 : 0000000000000000 [ 0.414502] Process swapper/0 (pid: 1, stack limit = 0x000000002a913c1c) [ 0.421441] Call trace: [ 0.423968] mtk_hw_pin_field_get+0x28/0x118 [ 0.428387] mtk_hw_set_value+0x30/0x104 [ 0.432445] mtk_gpio_set+0x20/0x28 [ 0.436052] mtk_gpio_direction_output+0x18/0x30 [ 0.440833] gpiod_direction_output_raw_commit+0x7c/0xa0 [ 0.446333] gpiod_direction_output+0x104/0x114 [ 0.451022] gpiod_configure_flags+0xbc/0xfc [ 0.455441] gpiod_hog+0x8c/0x140 [ 0.458869] of_gpiochip_add+0x27c/0x2d4 [ 0.462928] gpiochip_add_data_with_key+0x338/0x5f0 [ 0.467976] mtk_pinctrl_probe+0x388/0x400 [ 0.472217] platform_drv_probe+0x58/0xa4 [ 0.476365] driver_probe_device+0x204/0x44c [ 0.480783] __device_attach_driver+0xac/0x108 [ 0.485384] bus_for_each_drv+0x7c/0xac [ 0.489352] __device_attach+0xa0/0x144 [ 0.493320] device_initial_probe+0x10/0x18 [ 0.497647] bus_probe_device+0x2c/0x8c [ 0.501616] device_add+0x2f8/0x540 [ 0.505226] of_device_add+0x3c/0x44 [ 0.508925] of_platform_device_create_pdata+0x80/0xb8 [ 0.514245] of_platform_bus_create+0x290/0x3e8 [ 0.518933] of_platform_populate+0x78/0x100 [ 0.523352] of_platform_default_populate+0x24/0x2c [ 0.528403] of_platform_default_populate_init+0x94/0xa4 [ 0.533903] do_one_initcall+0x98/0x130 [ 0.537874] kernel_init_freeable+0x13c/0x1d4 [ 0.542385] kernel_init+0x10/0xf8 [ 0.545903] ret_from_fork+0x10/0x18 [ 0.549603] Code: 900020a1 f9400800 911dcc21 1400001f (f9406401) [ 0.555916] ---[ end trace de8c34787fdad3b3 ]--- [ 0.560722] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b [ 0.560722] [ 0.570188] SMP: stopping secondary CPUs [ 0.574253] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b [ 0.574253] Cc: stable@vger.kernel.org Fixes: d6ed935 ("pinctrl: mediatek: add pinctrl driver for MT7622 SoC") Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Hi!
When modifying the SPI section of arch/arm/mach-bcm2708/bcm2708.c
and then adding an interrupt "translation" from GPIO PIN to interrupt like this:
then the Kernel does not boot (not a single byte shows up on the serial console) - I have to take the SD card and I have to copy the emergency kernel to the running kernel to make the RPI boot again.
On the other hand: the SAME piece of config/code works with the 3.6.y kernel branch and has been recommended in several "recipes" to configure SPI devices...
The work-around it to use the hardcoded-interrupt number instead, which is not an optimal solution(see the other branch of "#if 1") .
Is there any "better" option than hardcoding the irq line?
Thanks,
Martin
The text was updated successfully, but these errors were encountered: