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

Commit fb6de081 authored by Sumukh Hallymysore Ravindra's avatar Sumukh Hallymysore Ravindra
Browse files

msm: synx: fix callback dispatch registered



The change fixes the callback handling if synx obj is destroyed
before it is signaled. Earlier the release would return fail if
the synx obj has not been signaled. But, this does not suit the
non-blocking wait where callback will be registered and the synx
obj will be ideally released and when the synx is signaled later
the registered callbacks will be invoked.
Change removes need for synx obj to be signaled before release
occurs. And in case if the synx obj deinit occurs without being
signaled, then registered callbacks will be dispatched with
cancelled status so any cleanup required by the client can be
achieved.

Change-Id: Ic4aed09bee2d818064db1bc415372eedd63d1872
Signed-off-by: default avatarSumukh Hallymysore Ravindra <shallymy@codeaurora.org>
parent 99a8045e
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -453,13 +453,6 @@ int synx_release(s32 synx_obj)
	fence = row->fence;
	idx = row->index;
	spin_lock_bh(&synx_dev->row_spinlocks[idx]);
	if (synx_status_locked(row) == SYNX_STATE_ACTIVE) {
		pr_err("need to signal before release synx = 0x%x\n",
			synx_obj);
		spin_unlock_bh(&synx_dev->row_spinlocks[idx]);
		return -EINVAL;
	}

	/*
	 * we need to clear the metadata for merged synx obj upon synx_release
	 * itself as it does not invoke the synx_fence_release function.
+37 −12
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ int synx_activate(struct synx_table_row *row)
int synx_deinit_object(struct synx_table_row *row)
{
	s32 synx_obj;
	struct synx_client *client;
	struct synx_callback_info *synx_cb, *temp_cb;
	struct synx_cb_data  *upayload_info, *temp_upayload;

@@ -163,21 +164,45 @@ int synx_deinit_object(struct synx_table_row *row)
	 * dma fence array will release all the allocated mem
	 * in its registered release function.
	 */
	if (!is_merged_synx(row))
	if (!is_merged_synx(row)) {
		kfree(row->fence);

		/*
		 * invoke remaining userspace and kernel callbacks on
		 * synx obj destroyed, not signaled, with cancellation
		 * event.
		 */
		list_for_each_entry_safe(upayload_info, temp_upayload,
				&row->user_payload_list, list) {
		pr_err("pending user callback payload\n");
		list_del_init(&upayload_info->list);
		kfree(upayload_info);
			upayload_info->data.status =
				SYNX_CALLBACK_RESULT_CANCELED;
			memcpy(&upayload_info->data.payload_data[2],
				&upayload_info->data.payload_data[0],
				sizeof(u64));
			client = upayload_info->client;
			if (!client) {
				pr_err("invalid client member in cb list\n");
				continue;
			}
			spin_lock_bh(&client->eventq_lock);
			list_move_tail(&upayload_info->list, &client->eventq);
			spin_unlock_bh(&client->eventq_lock);
			/*
			 * since cb can be registered by multiple clients,
			 * wake the process right away
			 */
			wake_up_all(&client->wq);
			pr_debug("dispatched user cb\n");
		}

		list_for_each_entry_safe(synx_cb, temp_cb,
				&row->callback_list, list) {
		pr_err("pending kernel callback payload\n");
			synx_cb->status = SYNX_CALLBACK_RESULT_CANCELED;
			list_del_init(&synx_cb->list);
		kfree(synx_cb);
			queue_work(synx_dev->work_queue,
				&synx_cb->cb_dispatch_work);
			pr_debug("dispatched kernel cb\n");
		}
	}

	clear_bit(row->index, synx_dev->bitmap);