Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: typec: fusb302: fix scheduling while atomic when using virtio-gpio

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>

authored by

Yongbo Zhang and committed by
Greg Kroah-Hartman
1c2d81bd 47c428fc

+4 -8
+4 -8
drivers/usb/typec/tcpm/fusb302.c
··· 1477 1477 struct fusb302_chip *chip = dev_id; 1478 1478 unsigned long flags; 1479 1479 1480 - /* Disable our level triggered IRQ until our irq_work has cleared it */ 1481 - disable_irq_nosync(chip->gpio_int_n_irq); 1482 - 1483 1480 spin_lock_irqsave(&chip->irq_lock, flags); 1484 1481 if (chip->irq_suspended) 1485 1482 chip->irq_while_suspended = true; ··· 1619 1622 } 1620 1623 done: 1621 1624 mutex_unlock(&chip->lock); 1622 - enable_irq(chip->gpio_int_n_irq); 1623 1625 } 1624 1626 1625 1627 static int init_gpio(struct fusb302_chip *chip) ··· 1743 1747 goto destroy_workqueue; 1744 1748 } 1745 1749 1746 - ret = request_irq(chip->gpio_int_n_irq, fusb302_irq_intn, 1747 - IRQF_ONESHOT | IRQF_TRIGGER_LOW, 1748 - "fsc_interrupt_int_n", chip); 1750 + ret = devm_request_threaded_irq(dev, chip->gpio_int_n_irq, 1751 + NULL, fusb302_irq_intn, 1752 + IRQF_ONESHOT | IRQF_TRIGGER_LOW, 1753 + "fsc_interrupt_int_n", chip); 1749 1754 if (ret < 0) { 1750 1755 dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret); 1751 1756 goto tcpm_unregister_port; ··· 1771 1774 struct fusb302_chip *chip = i2c_get_clientdata(client); 1772 1775 1773 1776 disable_irq_wake(chip->gpio_int_n_irq); 1774 - free_irq(chip->gpio_int_n_irq, chip); 1775 1777 cancel_work_sync(&chip->irq_work); 1776 1778 cancel_delayed_work_sync(&chip->bc_lvl_handler); 1777 1779 tcpm_unregister_port(chip->tcpm_port);