diff options
author | Jack Diver <diverj@google.com> | 2024-03-13 12:54:08 +0000 |
---|---|---|
committer | Jack Diver <diverj@google.com> | 2024-03-19 10:01:11 +0000 |
commit | 369c6eed8dcdd2c63efcfc877838cd873a8d6e63 (patch) | |
tree | 261f7d412c086016dd6f4aa703c99548ac6fa0fc | |
parent | c38634e994eef70c283ed040ee27dc589fad7bca (diff) | |
download | gs-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.c | 66 |
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; |