Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91f65fac authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Joerg Roedel
Browse files

iommu/amd: Fix amd_iommu_free_device()



put_device_state_wait() doesn't loop on the condition and a spurious
wakeup will have it free the device state even though there might still
be references out to it.

Fix this by using 'normal' wait primitives.

Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent e36f014e
Loading
Loading
Loading
Loading
+7 −13
Original line number Original line Diff line number Diff line
@@ -151,18 +151,6 @@ static void put_device_state(struct device_state *dev_state)
		wake_up(&dev_state->wq);
		wake_up(&dev_state->wq);
}
}


static void put_device_state_wait(struct device_state *dev_state)
{
	DEFINE_WAIT(wait);

	prepare_to_wait(&dev_state->wq, &wait, TASK_UNINTERRUPTIBLE);
	if (!atomic_dec_and_test(&dev_state->count))
		schedule();
	finish_wait(&dev_state->wq, &wait);

	free_device_state(dev_state);
}

/* Must be called under dev_state->lock */
/* Must be called under dev_state->lock */
static struct pasid_state **__get_pasid_state_ptr(struct device_state *dev_state,
static struct pasid_state **__get_pasid_state_ptr(struct device_state *dev_state,
						  int pasid, bool alloc)
						  int pasid, bool alloc)
@@ -851,7 +839,13 @@ void amd_iommu_free_device(struct pci_dev *pdev)
	/* Get rid of any remaining pasid states */
	/* Get rid of any remaining pasid states */
	free_pasid_states(dev_state);
	free_pasid_states(dev_state);


	put_device_state_wait(dev_state);
	put_device_state(dev_state);
	/*
	 * Wait until the last reference is dropped before freeing
	 * the device state.
	 */
	wait_event(dev_state->wq, !atomic_read(&dev_state->count));
	free_device_state(dev_state);
}
}
EXPORT_SYMBOL(amd_iommu_free_device);
EXPORT_SYMBOL(amd_iommu_free_device);