Skip to content

rk_gpio: implement PIC masking methods and mask unhandled IRQs#2197

Open
b1nc0d3x wants to merge 1 commit into
freebsd:mainfrom
b1nc0d3x:submit/d1-rk_gpio
Open

rk_gpio: implement PIC masking methods and mask unhandled IRQs#2197
b1nc0d3x wants to merge 1 commit into
freebsd:mainfrom
b1nc0d3x:submit/d1-rk_gpio

Conversation

@b1nc0d3x
Copy link
Copy Markdown

Summary

The Rockchip GPIO controller implements PIC operations for the INTRNG framework but is missing four masking methods that INTRNG calls during the filter / ithread handoff:

  • pic_disable_intr
  • pic_enable_intr
  • pic_pre_ithread
  • pic_post_ithread

Without them, level-sensitive interrupt sources connected to a Rockchip GPIO pin re-fire continuously while their ithread runs. On a RockPro64 with a FUSB302B Type-C controller (i2c) attached to gpio1 INT_N, the system enters a ~210 kHz interrupt storm the moment the fusb302 driver attaches and INT_N goes low. Observed via:

dtrace -n 'fbt::intr_event_schedule_thread:entry { @[stack()]=count(); }'

Edge-triggered GPIO IRQs were already self-acking and unaffected.

Two complementary changes:

  1. Add the four pic_disable_intr / pic_enable_intr / pic_pre_ithread / pic_post_ithread method bodies. Each toggles the pin's RK_GPIO_INTMASK bit so the source is masked during the in-flight ithread window and unmasked on return. This honours the generic INTRNG mask/unmask sequence and mirrors what other arm64 GPIO drivers do (qoriq_gpio, bcm2835_gpio).

  2. When the GPIO IRQ filter dispatches a pin and finds no consumer registered, mask the pin at the controller (INTMASK=1, INTEN=0) before continuing. Level-triggered sources keep asserting until acked, so a single stuck pin (e.g. fusb302 INT_N during attach races or after detach) used to flood the console with thousands of "Interrupt pin=N unhandled" lines per second. The mask survives until something re-attaches and re-enables the IRQ via the standard pic_enable_intr path. The single warning line is preserved (now reading "unhandled -- masked") so the underlying issue is still visible.

Test plan

  • RockPro64 (rk3399), level-triggered IRQ on gpio1 RK_PA2 (fusb302 INT_N). Before: ~210 kHz storm, top -SH shows swi1:gpio1 pinned. After: 0 spurious IRQs at steady state; pin masks correctly after a detach.
  • Same board, edge-triggered IRQ on gpio0 (button input) — still fires once per press, no regression.
  • Synthesize an unhandled IRQ by raising a GPIO pin with no FDT consumer wired: console shows one "unhandled -- masked" line, storm does not recur.

Suggested reviewers

manu, mhorne, andrew, mmel — arm64 / Rockchip / INTRNG maintainers per git log. Not @-mentioned to avoid spam if the GitHub handles don't match; happy to ping on request.

Notes

First in a series of patches landing the RockPro64 USB-C DisplayPort + audio path. Successor patches (drm_fb_helper hotplug fix, usbc PD framework, fusb302, rk_typec_phy DP altmode, rk_cdn_dp) will follow in their own PRs after this one gets a sign-of-life from a reviewer.

This patch is independent of the rest of that series and useful on its own for anyone running a Rockchip board with a level-triggered GPIO interrupt source.

Author: Kyle Crenshaw <B1nc0d3x@gmail.com>

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

Thank you for taking the time to contribute to FreeBSD!

Some of files have special handling:

Important

@evadot wants to review changes to sys/arm64/rockchip

The Rockchip GPIO controller implements PIC operations for the INTRNG
framework but is missing four masking methods that INTRNG calls during
the filter/ithread handoff: pic_disable_intr, pic_enable_intr,
pic_pre_ithread, pic_post_ithread.

Without them, level-sensitive interrupt sources connected to a
Rockchip GPIO pin re-fire continuously while their ithread runs.  On
a RockPro64 with a FUSB302B Type-C controller (i2c) attached to
gpio1 INT_N, the system enters a ~210 kHz interrupt storm the moment
the fusb302 driver attaches and INT_N goes low.

Two complementary changes:

1. Add the four pic_disable_intr/pic_enable_intr/pic_pre_ithread/
   pic_post_ithread method bodies.  Each toggles the pin's
   RK_GPIO_INTMASK bit so the source is masked during the in-flight
   ithread window and unmasked on return, honouring the generic
   INTRNG mask/unmask sequence.

2. When the GPIO IRQ filter dispatches a pin and finds no consumer
   registered, mask the pin at the controller (INTMASK=1, INTEN=0)
   before continuing.  Level-triggered sources keep asserting until
   acked, so a single stuck pin used to flood the console with
   thousands of "Interrupt pin=N unhandled" lines per second.  The
   mask survives until something re-attaches and re-enables the IRQ
   via the standard pic_enable_intr path.

Affects all level-triggered IRQs on Rockchip GPIO banks; edge-
triggered IRQs were already self-acking and unaffected.

Signed-off-by: Kyle Crenshaw <B1nc0d3x@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant