iommu/amd: Fix accounting of device_state
This patch fixes a bug in the accounting of the device_state. In the current code, the device_state was put (decremented) too many times, which sometimes lead to the driver getting stuck permanently in put_device_state_wait(). That happen because the device_state->count would go below zero, which is never supposed to happen. The root cause is that the device_state was decremented in put_pasid_state() and put_pasid_state_wait() but also in all the functions that call those functions. Therefore, the device_state was decremented twice in each of these code paths. The fix is to decouple the device_state accounting from the pasid_state accounting - remove the call to put_device_state() from the put_pasid_state() and the put_pasid_state_wait()) Signed-off-by: Oded Gabbay <oded.gabbay@amd.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
206c5f60a3
commit
1c51099a42
|
@ -279,10 +279,8 @@ static void free_pasid_state(struct pasid_state *pasid_state)
|
|||
|
||||
static void put_pasid_state(struct pasid_state *pasid_state)
|
||||
{
|
||||
if (atomic_dec_and_test(&pasid_state->count)) {
|
||||
put_device_state(pasid_state->device_state);
|
||||
if (atomic_dec_and_test(&pasid_state->count))
|
||||
wake_up(&pasid_state->wq);
|
||||
}
|
||||
}
|
||||
|
||||
static void put_pasid_state_wait(struct pasid_state *pasid_state)
|
||||
|
@ -291,9 +289,7 @@ static void put_pasid_state_wait(struct pasid_state *pasid_state)
|
|||
|
||||
prepare_to_wait(&pasid_state->wq, &wait, TASK_UNINTERRUPTIBLE);
|
||||
|
||||
if (atomic_dec_and_test(&pasid_state->count))
|
||||
put_device_state(pasid_state->device_state);
|
||||
else
|
||||
if (!atomic_dec_and_test(&pasid_state->count))
|
||||
schedule();
|
||||
|
||||
finish_wait(&pasid_state->wq, &wait);
|
||||
|
|
Loading…
Reference in New Issue