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

Commit 2a9c0520 authored by Sumukh Hallymysore Ravindra's avatar Sumukh Hallymysore Ravindra
Browse files

msm: synx: Finish signaling and callback dispatch before releasing lock



Finishing the callback dispatch and external fence signaling
within the same atomic lock context prevents the probable race
condition when the dma fence signaling has woken the wait process
which might continue to release the fence once completed before
the actual signaling thread is context switched back. This will
result null pointer dereference as metadata have been cleaned.
Ensuring all the signaling functionalities have completed before
releasing the lock prevent this.
Have also added couple more checks for null pointer dereference.

Change-Id: Ib0ba849dc17dff038a1370efcd268bab8663123f
Signed-off-by: default avatarSumukh Hallymysore Ravindra <shallymy@codeaurora.org>
parent fe38b6f0
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -259,9 +259,7 @@ int synx_signal_core(struct synx_table_row *row, u32 status)
	if (status == SYNX_STATE_SIGNALED_ERROR)
		dma_fence_set_error(row->fence, -EINVAL);

	spin_unlock_bh(&synx_dev->row_spinlocks[row->index]);

	rc = dma_fence_signal(row->fence);
	rc = dma_fence_signal_locked(row->fence);
	if (rc < 0) {
		pr_err("unable to signal synx 0x%x, err: %d\n",
			row->synx_obj, rc);
@@ -271,8 +269,6 @@ int synx_signal_core(struct synx_table_row *row, u32 status)
		}
	}

	spin_lock_bh(&synx_dev->row_spinlocks[row->index]);

	synx_callback_dispatch(row);

	/*
+15 −3
Original line number Diff line number Diff line
@@ -356,8 +356,10 @@ void synx_util_cb_dispatch(struct work_struct *cb_dispatch_work)

bool is_merged_synx(struct synx_table_row *row)
{
	if (!row)
	if (!row || !row->fence) {
		pr_err("invalid row argument\n");
		return false;
	}

	if (dma_fence_is_array(row->fence))
		return true;
@@ -370,6 +372,11 @@ u32 __fence_state(struct dma_fence *fence, bool locked)
	s32 status;
	u32 state = SYNX_STATE_INVALID;

	if (!fence) {
		pr_err("invalid dma fence addr\n");
		return SYNX_STATE_INVALID;
	}

	if (locked)
		status = dma_fence_get_status_locked(fence);
	else
@@ -394,11 +401,16 @@ u32 __fence_group_state(struct dma_fence *fence, bool locked)
{
	u32 i = 0;
	u32 state = SYNX_STATE_INVALID;
	struct dma_fence_array *array = to_dma_fence_array(fence);
	struct dma_fence_array *array = NULL;
	u32 intr, actv_cnt, sig_cnt, err_cnt;

	actv_cnt = sig_cnt = err_cnt = 0;
	if (!fence) {
		pr_err("invalid dma fence addr\n");
		return SYNX_STATE_INVALID;
	}

	actv_cnt = sig_cnt = err_cnt = 0;
	array = to_dma_fence_array(fence);
	if (!array)
		return SYNX_STATE_INVALID;