All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Yongbo Zhang <giraffesnn123@gmail.com>,
	Heikki Krogerus <heikki.krogerus@linux.intel.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Sasha Levin <sashal@kernel.org>,
	krzysztof.kozlowski@linaro.org, sebastian.reichel@collabora.com
Subject: [PATCH AUTOSEL 6.6 48/59] usb: typec: fusb302: fix scheduling while atomic when using virtio-gpio
Date: Sun,  3 Aug 2025 20:34:02 -0400	[thread overview]
Message-ID: <20250804003413.3622950-48-sashal@kernel.org> (raw)
In-Reply-To: <20250804003413.3622950-1-sashal@kernel.org>

From: Yongbo Zhang <giraffesnn123@gmail.com>

[ Upstream commit 1c2d81bded1993bb2c7125a911db63612cdc8d40 ]

When the gpio irqchip connected to a slow bus(e.g., i2c bus or virtio
bus), calling disable_irq_nosync() in top-half ISR handler will trigger
the following kernel BUG:

BUG: scheduling while atomic: RenderEngine/253/0x00010002
...
Call trace:
 dump_backtrace+0x0/0x1c8
 show_stack+0x1c/0x2c
 dump_stack_lvl+0xdc/0x12c
 dump_stack+0x1c/0x64
 __schedule_bug+0x64/0x80
 schedule_debug+0x98/0x118
 __schedule+0x68/0x704
 schedule+0xa0/0xe8
 schedule_timeout+0x38/0x124
 wait_for_common+0xa4/0x134
 wait_for_completion+0x1c/0x2c
 _virtio_gpio_req+0xf8/0x198
 virtio_gpio_irq_bus_sync_unlock+0x94/0xf0
 __irq_put_desc_unlock+0x50/0x54
 disable_irq_nosync+0x64/0x94
 fusb302_irq_intn+0x24/0x84
 __handle_irq_event_percpu+0x84/0x278
 handle_irq_event+0x64/0x14c
 handle_level_irq+0x134/0x1d4
 generic_handle_domain_irq+0x40/0x68
 virtio_gpio_event_vq+0xb0/0x130
 vring_interrupt+0x7c/0x90
 vm_interrupt+0x88/0xd8
 __handle_irq_event_percpu+0x84/0x278
 handle_irq_event+0x64/0x14c
 handle_fasteoi_irq+0x110/0x210
 __handle_domain_irq+0x80/0xd0
 gic_handle_irq+0x78/0x154
 el0_irq_naked+0x60/0x6c

This patch replaces request_irq() with devm_request_threaded_irq() to
avoid the use of disable_irq_nosync().

Signed-off-by: Yongbo Zhang <giraffesnn123@gmail.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20250526043433.673097-1-giraffesnn123@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

**Backport Status: YES**

This commit should be backported to stable kernel trees. Here's my
extensive analysis:

## Bug Analysis

The commit fixes a critical "scheduling while atomic" bug that occurs
when the fusb302 USB Type-C controller uses GPIO interrupts connected
through slow buses (like I2C or virtio). The bug manifests as a kernel
BUG with the following call trace showing `__schedule_bug` being
triggered from within an atomic context.

## Technical Details of the Bug

1. **Root Cause**: The fusb302 driver's interrupt handler
   (`fusb302_irq_intn`) calls `disable_irq_nosync()` from the top-half
   ISR context (lines 1480-1481 in the original code). When the GPIO
   controller is connected via a slow bus like virtio-gpio, the
   `disable_irq_nosync()` operation requires bus transactions that can
   sleep, which is forbidden in atomic/interrupt context.

2. **The Problem Flow**:
   - Hardware interrupt occurs → `fusb302_irq_intn` ISR runs in atomic
     context
   - ISR calls `disable_irq_nosync(chip->gpio_int_n_irq)`
   - virtio-gpio's `virtio_gpio_irq_bus_sync_unlock()` needs to
     communicate over virtio bus
   - This requires `wait_for_completion()` which can sleep
   - Sleeping in atomic context triggers the kernel BUG

## The Fix

The fix replaces `request_irq()` with `devm_request_threaded_irq()` and
removes the problematic `disable_irq_nosync()`/`enable_irq()` pattern:

1. **Before**: Used regular IRQ handler that disabled the interrupt in
   top-half, scheduled work, then re-enabled in bottom-half
2. **After**: Uses threaded IRQ handler which naturally handles the
   interrupt masking/unmasking without explicit calls

Key changes:
- Line 1751-1754: Changed from `request_irq()` to
  `devm_request_threaded_irq()` with NULL top-half handler
- Line 1481: Removed `disable_irq_nosync()` call from ISR
- Line 1625: Removed corresponding `enable_irq()` call from work
  function
- Line 1750: Removed `free_irq()` call (handled by devm_*)

## Stable Backport Criteria Evaluation

1. **Fixes a bug affecting users**: YES - This fixes a kernel BUG that
   causes system instability
2. **Relatively small and contained**: YES - Only 7 lines changed,
   confined to one driver file
3. **Clear side effects**: NO - The fix is straightforward with no
   architectural changes
4. **Major architectural changes**: NO - Simply changes IRQ registration
   method
5. **Critical kernel subsystems**: NO - Limited to USB Type-C controller
   driver
6. **Stable tree mention**: NO - But follows stable tree rules perfectly
7. **Follows stable rules**: YES - Important bugfix with minimal risk

## Additional Considerations

- The bug only manifests with specific hardware configurations (virtio-
  gpio or slow I2C GPIO expanders)
- The fix is a standard pattern used throughout the kernel for similar
  issues
- Using `devm_request_threaded_irq()` is actually cleaner and provides
  automatic cleanup
- No functional changes to the driver's behavior, only fixes the atomic
  scheduling violation
- Similar fixes have been applied to other drivers facing the same issue
  pattern

This is an ideal stable backport candidate: it fixes a real bug that
causes kernel panics, the fix is minimal and well-understood, and
there's virtually no risk of regression.

 drivers/usb/typec/tcpm/fusb302.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index bc21006e979c..111c46df4a1f 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -1477,9 +1477,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id)
 	struct fusb302_chip *chip = dev_id;
 	unsigned long flags;
 
-	/* Disable our level triggered IRQ until our irq_work has cleared it */
-	disable_irq_nosync(chip->gpio_int_n_irq);
-
 	spin_lock_irqsave(&chip->irq_lock, flags);
 	if (chip->irq_suspended)
 		chip->irq_while_suspended = true;
@@ -1622,7 +1619,6 @@ static void fusb302_irq_work(struct work_struct *work)
 	}
 done:
 	mutex_unlock(&chip->lock);
-	enable_irq(chip->gpio_int_n_irq);
 }
 
 static int init_gpio(struct fusb302_chip *chip)
@@ -1747,9 +1743,10 @@ static int fusb302_probe(struct i2c_client *client)
 		goto destroy_workqueue;
 	}
 
-	ret = request_irq(chip->gpio_int_n_irq, fusb302_irq_intn,
-			  IRQF_ONESHOT | IRQF_TRIGGER_LOW,
-			  "fsc_interrupt_int_n", chip);
+	ret = devm_request_threaded_irq(dev, chip->gpio_int_n_irq,
+					NULL, fusb302_irq_intn,
+					IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+					"fsc_interrupt_int_n", chip);
 	if (ret < 0) {
 		dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret);
 		goto tcpm_unregister_port;
@@ -1774,7 +1771,6 @@ static void fusb302_remove(struct i2c_client *client)
 	struct fusb302_chip *chip = i2c_get_clientdata(client);
 
 	disable_irq_wake(chip->gpio_int_n_irq);
-	free_irq(chip->gpio_int_n_irq, chip);
 	cancel_work_sync(&chip->irq_work);
 	cancel_delayed_work_sync(&chip->bc_lvl_handler);
 	tcpm_unregister_port(chip->tcpm_port);
-- 
2.39.5


  parent reply	other threads:[~2025-08-04  0:36 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-04  0:33 [PATCH AUTOSEL 6.6 01/59] usb: xhci: print xhci->xhc_state when queue_command failed Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 02/59] platform/x86/amd: pmc: Add Lenovo Yoga 6 13ALC6 to pmc quirk list Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 03/59] cpufreq: CPPC: Mark driver with NEED_UPDATE_LIMITS flag Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 04/59] selftests/futex: Define SYS_futex on 32-bit architectures with 64-bit time_t Sasha Levin
2025-08-04  0:33   ` Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 05/59] usb: typec: ucsi: psy: Set current max to 100mA for BC 1.2 and Default Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 06/59] regulator: core: repeat voltage setting request for stepped regulators Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 07/59] usb: xhci: Avoid showing warnings for dying controller Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 08/59] usb: xhci: Set avg_trb_len = 8 for EP0 during Address Device Command Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 09/59] usb: xhci: Avoid showing errors during surprise removal Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 10/59] soc: qcom: rpmh-rsc: Add RSC version 4 support Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 11/59] ACPI: APEI: send SIGBUS to current task if synchronous memory error not recovered Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 12/59] remoteproc: imx_rproc: skip clock enable when M-core is managed by the SCU Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 13/59] gpio: wcd934x: check the return value of regmap_update_bits() Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 14/59] cpufreq: Exit governor when failed to start old governor Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 15/59] ARM: rockchip: fix kernel hang during smp initialization Sasha Levin
2025-08-04  0:33   ` Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 16/59] PM / devfreq: governor: Replace sscanf() with kstrtoul() in set_freq_store() Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 17/59] EDAC/synopsys: Clear the ECC counters on init Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 18/59] ASoC: soc-dapm: set bias_level if snd_soc_dapm_set_bias_level() was successed Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 19/59] thermal/drivers/qcom-spmi-temp-alarm: Enable stage 2 shutdown when required Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 20/59] tools/nolibc: define time_t in terms of __kernel_old_time_t Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 21/59] iio: adc: ad_sigma_delta: don't overallocate scan buffer Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 22/59] gpio: tps65912: check the return value of regmap_update_bits() Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 23/59] ARM: tegra: Use I/O memcpy to write to IRAM Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 24/59] tools/build: Fix s390(x) cross-compilation with clang Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 25/59] selftests: tracing: Use mutex_unlock for testing glob filter Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 26/59] ACPI: PRM: Reduce unnecessary printing to avoid user confusion Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 27/59] firmware: tegra: Fix IVC dependency problems Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 28/59] pwm: sifive: Fix PWM algorithm and clarify inverted compare behavior Sasha Levin
2025-08-04  0:33   ` Sasha Levin
2025-08-04 10:45   ` Uwe Kleine-König
2025-08-04 10:45     ` Uwe Kleine-König
2025-08-04 13:27     ` Sasha Levin
2025-08-04 13:27       ` Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 29/59] PM: runtime: Clear power.needs_force_resume in pm_runtime_reinit() Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 30/59] thermal: sysfs: Return ENODATA instead of EAGAIN for reads Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 31/59] PM: sleep: console: Fix the black screen issue Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 32/59] ACPI: processor: fix acpi_object initialization Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 33/59] mmc: sdhci-msm: Ensure SD card power isn't ON when card removed Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 34/59] ACPI: APEI: GHES: add TAINT_MACHINE_CHECK on GHES panic path Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 35/59] pps: clients: gpio: fix interrupt handling order in remove path Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 36/59] reset: brcmstb: Enable reset drivers for ARCH_BCM2835 Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 37/59] char: misc: Fix improper and inaccurate error code returned by misc_init() Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 38/59] mei: bus: Check for still connected devices in mei_cl_bus_dev_release() Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 39/59] mmc: rtsx_usb_sdmmc: Fix error-path in sd_set_power_mode() Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 40/59] ALSA: hda: Handle the jack polling always via a work Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 41/59] ALSA: hda: Disable jack polling at shutdown Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 42/59] x86/bugs: Avoid warning when overriding return thunk Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 43/59] ASoC: hdac_hdmi: Rate limit logging on connection and disconnection Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 44/59] ALSA: intel8x0: Fix incorrect codec index usage in mixer for ICH4 Sasha Levin
2025-08-04  0:33 ` [PATCH AUTOSEL 6.6 45/59] ASoC: core: Check for rtd == NULL in snd_soc_remove_pcm_runtime() Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 46/59] usb: typec: intel_pmc_mux: Defer probe if SCU IPC isn't present Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 47/59] usb: core: usb_submit_urb: downgrade type check Sasha Levin
2025-08-04  0:34 ` Sasha Levin [this message]
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 49/59] pm: cpupower: Fix the snapshot-order of tsc,mperf, clock in mperf_stop() Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 50/59] imx8m-blk-ctrl: set ISI panic write hurry level Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 51/59] soc: qcom: mdt_loader: Actually use the e_phoff Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 52/59] platform/x86: thinkpad_acpi: Handle KCOV __init vs inline mismatches Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 53/59] platform/chrome: cros_ec_typec: Defer probe on missing EC parent Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 54/59] ALSA: hda/ca0132: Fix buffer overflow in add_tuning_control Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 55/59] ALSA: pcm: Rewrite recalculate_boundary() to avoid costly loop Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 56/59] ALSA: usb-audio: Avoid precedence issues in mixer_quirks macros Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 57/59] iio: adc: ad7768-1: Ensure SYNC_IN pulse minimum timing requirement Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 58/59] ASoC: codecs: rt5640: Retry DEVICE_ID verification Sasha Levin
2025-08-04  0:34 ` [PATCH AUTOSEL 6.6 59/59] ASoC: qcom: use drvdata instead of component to keep id Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250804003413.3622950-48-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=giraffesnn123@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=krzysztof.kozlowski@linaro.org \
    --cc=patches@lists.linux.dev \
    --cc=sebastian.reichel@collabora.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.