msm: kgsl: Fix race between kgsl device open and close

In current code, kgsl_close_device holds device mutex and calls
last_close in case open_count goes to zero. But as part of
last_close call, device mutex is released intermittently to wait
for active count to go to zero and also for dispatcher idle. This
intermittent release of device mutex opens up a window where a
kgsl_open_device call can go ahead and call first_open. As this
first_open is triggered before last_close could finish it messes
up the complete state machine. To fix this, move decrement of
open_count after last_close to allow any open/close happening when
last_close is in progress to just increment/decrement open_count
without triggering first_open or last_close.

Change-Id: Ibb2567e3ef0dc1864f2bfca346b0682792d0b675
Signed-off-by: Deepak Kumar <dkumar@codeaurora.org>
This commit is contained in:
Deepak Kumar 2021-04-30 12:46:24 +05:30
commit e4f4b83ee1

View file

@ -1047,10 +1047,20 @@ static int kgsl_close_device(struct kgsl_device *device)
int result = 0;
mutex_lock(&device->mutex);
device->open_count--;
if (device->open_count == 0)
if (device->open_count == 1)
result = device->ftbl->last_close(device);
/*
* We must decrement the open_count after last_close() has finished.
* This is because last_close() relinquishes device mutex while
* waiting for active count to become 0. This opens up a window
* where a new process can come in, see that open_count is 0, and
* initiate a first_open(). This can potentially mess up the power
* state machine. To avoid a first_open() from happening before
* last_close() has finished, decrement the open_count after
* last_close().
*/
device->open_count--;
mutex_unlock(&device->mutex);
return result;