summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Diver <diverj@google.com>2024-03-13 12:54:08 +0000
committerJack Diver <diverj@google.com>2024-03-19 10:01:11 +0000
commit369c6eed8dcdd2c63efcfc877838cd873a8d6e63 (patch)
tree261f7d412c086016dd6f4aa703c99548ac6fa0fc
parentc38634e994eef70c283ed040ee27dc589fad7bca (diff)
downloadgs-android-gs-shusky-5.15-android15-dp.tar.gz
pt: Synchronously execute resize callbacksandroid-15-beta-1_r0.7android-gs-shusky-5.15-android15-dp
Synchronously execute resize callbacks. This removes the need for tracking in-progress resizes, and waiting on resizing to complete. Instead, pt_internal_data.sl is used to block on resize callback execution. This fixes a sleep in atomic context bug. Bug: 329273256 Test: Boot to home with debug_locking Signed-off-by: Jack Diver <diverj@google.com> (cherry picked from commit 80cbff3f50ee6218740db4e1414e23bb75602df4) Merged-In: I9e5e1e0be1b3332f8c9c15b4309e8a3d234068d8 Change-Id: I9e5e1e0be1b3332f8c9c15b4309e8a3d234068d8
-rw-r--r--drivers/soc/google/pt/pt.c66
1 files changed, 33 insertions, 33 deletions
diff --git a/drivers/soc/google/pt/pt.c b/drivers/soc/google/pt/pt.c
index 4dffd341e..c012190ba 100644
--- a/drivers/soc/google/pt/pt.c
+++ b/drivers/soc/google/pt/pt.c
@@ -110,9 +110,7 @@ struct {
/* Data for resize_callback thread */
struct task_struct *resize_thread;
- struct pt_pts *resize_pts_in_progress; /* callback is in progress */
struct list_head resize_list; /* callback to call */
- wait_queue_head_t resize_remove_wq; /* wait current callback return */
wait_queue_head_t resize_wq; /* wait for new callback */
} pt_internal_data;
@@ -154,10 +152,10 @@ static void pt_trace(struct pt_handle *handle, int id, bool enable)
*/
static struct pt_pts *pt_resize_list_next(u32 *size)
{
- unsigned long flags;
struct pt_pts *pts = NULL;
- spin_lock_irqsave(&pt_internal_data.sl, flags);
+ lockdep_assert_held(&pt_internal_data.sl);
+
if (!list_empty(&pt_internal_data.resize_list)) {
pts = list_first_entry(&pt_internal_data.resize_list,
struct pt_pts, resize_list);
@@ -166,14 +164,7 @@ static struct pt_pts *pt_resize_list_next(u32 *size)
pts->resize_list.prev = NULL;
*size = pts->size;
}
- pt_internal_data.resize_pts_in_progress = pts;
- spin_unlock_irqrestore(&pt_internal_data.sl, flags);
- wake_up(&pt_internal_data.resize_remove_wq);
-
- if (pts == NULL)
- wait_event_interruptible(pt_internal_data.resize_wq,
- !list_empty(&pt_internal_data.resize_list));
return pts;
}
@@ -189,8 +180,8 @@ static void pt_resize_list_add(struct pt_pts *pts, u32 size)
spin_lock_irqsave(&pt_internal_data.sl, flags);
if ((pts->resize_list.next == NULL) && (pts->enabled)
&& (pts->size != size)) {
+ waking = list_empty(&pt_internal_data.resize_list);
list_add(&pts->resize_list, &pt_internal_data.resize_list);
- waking = !pt_internal_data.resize_pts_in_progress;
}
pts->size = size;
spin_unlock_irqrestore(&pt_internal_data.sl, flags);
@@ -200,7 +191,7 @@ static void pt_resize_list_add(struct pt_pts *pts, u32 size)
}
/*
- * FLush and disable pts resize callback.
+ * Flush and disable pts resize callback.
* If a resize callback is in progress, we wait for its completion.
*/
static bool pt_resize_list_disable(struct pt_pts *pts)
@@ -219,8 +210,6 @@ static bool pt_resize_list_disable(struct pt_pts *pts)
}
spin_unlock_irqrestore(&pt_internal_data.sl, flags);
- wait_event(pt_internal_data.resize_remove_wq,
- pt_internal_data.resize_pts_in_progress != pts);
return enabled;
}
@@ -250,25 +239,37 @@ static int pt_resize_thread(void *data)
pt_resize_callback_t resize_callback = NULL;
int id;
- while (1) {
- /*
- * We are size snapshot from pt_resize_list_next().
- * because pts->size can change after the return.
- */
+ while (!kthread_should_stop()) {
+ spin_lock(&pt_internal_data.sl);
+
pts = pt_resize_list_next(&size);
- if (pts == NULL)
- continue;
- handle = pts->handle;
- resize_callback = handle->resize_callback;
- id = ((char *)pts - (char *)handle->pts)
- / sizeof(handle->pts[0]);
- resize_callback(handle->data, id, size);
-
- driver = pts->driver;
- trace_pt_resize_callback(handle->node->name,
- driver->properties->nodes[pts->property_index]->name,
- false, (int)size, pts->ptid);
+ if (pts != NULL) {
+ handle = pts->handle;
+ resize_callback = handle->resize_callback;
+ id = ((char *)pts - (char *)handle->pts) / sizeof(handle->pts[0]);
+ resize_callback(handle->data, id, size);
+ driver = pts->driver;
+ trace_pt_resize_callback(
+ handle->node->name,
+ driver->properties->nodes[pts->property_index]->name, false,
+ (int)size, pts->ptid);
+ }
+
+ spin_unlock(&pt_internal_data.sl);
+
+ /* List was empty, wait to be notified by pt_resize_list_add */
+ if (pts == NULL) {
+ int ret;
+ do {
+ ret = wait_event_interruptible(
+ pt_internal_data.resize_wq,
+ !list_empty(&pt_internal_data.resize_list) ||
+ kthread_should_stop());
+ } while (!ret);
+ }
}
+
+ return 0;
}
/*
@@ -1246,7 +1247,6 @@ static int __init pt_init(void)
INIT_LIST_HEAD(&pt_internal_data.driver_list);
INIT_LIST_HEAD(&pt_internal_data.resize_list);
init_waitqueue_head(&pt_internal_data.resize_wq);
- init_waitqueue_head(&pt_internal_data.resize_remove_wq);
sysctl_table = &pt_internal_data.sysctl_table[0];
sysctl_table[0].procname = "dev";
sysctl_table[0].mode = 0550;