Commit 309b6341 authored by Sebastian Reichel's avatar Sebastian Reichel Committed by Greg Kroah-Hartman
Browse files

usb: typec: fusb302: Revert incorrect threaded irq fix



The fusb302 irq handler has been carefully optimized by Hans de Goede in
commit 207338ec ("usb: typec: fusb302: Improve suspend/resume
handling"). A recent 'fix' undid most of that work to avoid a virtio-gpio
driver bug.

This reverts the incorrect fix, since it is of very low quality. It
reverts the quirks from Hans change (and thus reintroduces the problems
fixed by Hans) while keeping the overhead from the original change.

The proper fix to support using fusb302 with an interrupt line provided
by virtio-gpio must be implemented in the virtio driver instead, which
should support disabling the IRQ from the fusb302 interrupt routine.

Cc: Hans de Goede <hansg@kernel.org>
Cc: Yongbo Zhang <giraffesnn123@gmail.com>
Fixes: 1c2d81bd ("usb: typec: fusb302: fix scheduling while atomic when using virtio-gpio")
Signed-off-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Link: https://lore.kernel.org/r/20250818-fusb302-unthreaded-irq-v1-1-3a9a11a9f56f@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 70fb252a
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -1485,6 +1485,9 @@ 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;
@@ -1627,6 +1630,7 @@ 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)
@@ -1751,8 +1755,7 @@ static int fusb302_probe(struct i2c_client *client)
		goto destroy_workqueue;
	}

	ret = devm_request_threaded_irq(dev, chip->gpio_int_n_irq,
					NULL, fusb302_irq_intn,
	ret = request_irq(chip->gpio_int_n_irq, fusb302_irq_intn,
			  IRQF_ONESHOT | IRQF_TRIGGER_LOW,
			  "fsc_interrupt_int_n", chip);
	if (ret < 0) {
@@ -1779,6 +1782,7 @@ 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);