Commit 2cedb296 authored by Alexander Usyskin's avatar Alexander Usyskin Committed by Greg Kroah-Hartman
Browse files

mei: me: trigger link reset if hw ready is unexpected



Driver can receive HW not ready interrupt unexpectedly.
E.g. for cards that go donwn to D3cold.
Trigger link reset in this case to synchronize driver and
firmware state.
No need to do that sync if driver is going down or interrupt is
received before driver started initial link reset sequence.
Introduce UNINITIALIZED device state to allow interrupt handler
to ignore interrupts before first init.

Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20250918130435.3327400-2-alexander.usyskin@intel.com
parent 3ebcd346
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -1373,9 +1373,20 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
	/*  check if we need to start the dev */
	if (!mei_host_is_ready(dev)) {
		if (mei_hw_is_ready(dev)) {
			/* synchronized by dev mutex */
			if (waitqueue_active(&dev->wait_hw_ready)) {
				dev_dbg(&dev->dev, "we need to start the dev.\n");
				dev->recvd_hw_ready = true;
				wake_up(&dev->wait_hw_ready);
			} else if (dev->dev_state != MEI_DEV_UNINITIALIZED &&
				   dev->dev_state != MEI_DEV_POWERING_DOWN &&
				   dev->dev_state != MEI_DEV_POWER_DOWN) {
				dev_dbg(&dev->dev, "Force link reset.\n");
				schedule_work(&dev->reset_work);
			} else {
				dev_dbg(&dev->dev, "Ignore this interrupt in state = %d\n",
					dev->dev_state);
			}
		} else {
			dev_dbg(&dev->dev, "Spurious Interrupt\n");
		}
+1 −1
Original line number Diff line number Diff line
@@ -399,7 +399,7 @@ void mei_device_init(struct mei_device *dev,
	init_waitqueue_head(&dev->wait_hw_ready);
	init_waitqueue_head(&dev->wait_pg);
	init_waitqueue_head(&dev->wait_hbm_start);
	dev->dev_state = MEI_DEV_INITIALIZING;
	dev->dev_state = MEI_DEV_UNINITIALIZED;
	dev->reset_count = 0;

	INIT_LIST_HEAD(&dev->write_list);
+2 −1
Original line number Diff line number Diff line
@@ -57,7 +57,8 @@ enum file_state {

/* MEI device states */
enum mei_dev_state {
	MEI_DEV_INITIALIZING = 0,
	MEI_DEV_UNINITIALIZED = 0,
	MEI_DEV_INITIALIZING,
	MEI_DEV_INIT_CLIENTS,
	MEI_DEV_ENABLED,
	MEI_DEV_RESETTING,