diff options
author | PixelBot AutoMerger <android-nexus-securitybot@system.gserviceaccount.com> | 2023-02-05 19:48:23 -0800 |
---|---|---|
committer | SecurityBot <android-nexus-securitybot@system.gserviceaccount.com> | 2023-02-05 19:48:23 -0800 |
commit | c7569561a0f2a411a110af601db83ce42715b9b2 (patch) | |
tree | 3a5e4872ab430c95466a20f168fa7ee02bc485dd | |
parent | 67af8da3ceabbe5f8c00a62fb7a4251ccfb3016a (diff) | |
parent | 6247e718e12b5393da220c370bdc55f7f6eb6c7c (diff) | |
download | lwis-c7569561a0f2a411a110af601db83ce42715b9b2.tar.gz |
Merge android13-gs-pixel-5.10-tm-qpr2 into android13-gs-pixel-5.10-tm-qpr3
SBMerger: 478053055
Change-Id: If1542ab2a27ef0209268c6210bf1414cfef65a92
Signed-off-by: SecurityBot <android-nexus-securitybot@system.gserviceaccount.com>
-rw-r--r-- | lwis_device.c | 2 | ||||
-rw-r--r-- | lwis_device.h | 6 | ||||
-rw-r--r-- | lwis_device_top.c | 85 | ||||
-rw-r--r-- | lwis_device_top.h | 6 | ||||
-rw-r--r-- | lwis_periodic_io.c | 1 | ||||
-rw-r--r-- | lwis_transaction.c | 60 |
6 files changed, 75 insertions, 85 deletions
diff --git a/lwis_device.c b/lwis_device.c index 7f5aefc..56ceafc 100644 --- a/lwis_device.c +++ b/lwis_device.c @@ -158,7 +158,7 @@ static int lwis_cleanup_client(struct lwis_client *lwis_client) /* Clean up all periodic io state for the client */ lwis_periodic_io_client_cleanup(lwis_client); - /* Cancel all pending transactions for the client and destory workqueue*/ + /* Cancel all pending transactions for the client */ lwis_transaction_clear(lwis_client); /* Run cleanup transactions. */ diff --git a/lwis_device.h b/lwis_device.h index 830d81b..42c0bdb 100644 --- a/lwis_device.h +++ b/lwis_device.h @@ -22,7 +22,6 @@ #include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/poll.h> -#include <linux/workqueue.h> #include "lwis_clock.h" #include "lwis_commands.h" @@ -257,6 +256,8 @@ struct lwis_device { struct task_struct *transaction_worker_thread; struct kthread_worker periodic_io_worker; struct task_struct *periodic_io_worker_thread; + struct kthread_worker subscribe_worker; + struct task_struct *subscribe_worker_thread; }; /* @@ -284,12 +285,9 @@ struct lwis_client { DECLARE_HASHTABLE(enrolled_buffers, BUFFER_HASH_BITS); /* Hash table of transactions keyed by trigger event ID */ DECLARE_HASHTABLE(transaction_list, TRANSACTION_HASH_BITS); - /* Transaction task-related variables */ - struct tasklet_struct transaction_tasklet; /* Spinlock used to synchronize access to transaction data structs */ spinlock_t transaction_lock; /* List of transaction triggers */ - struct list_head transaction_process_queue_tasklet; struct list_head transaction_process_queue; /* Transaction counter, which also provides transacton ID */ int64_t transaction_counter; diff --git a/lwis_device_top.c b/lwis_device_top.c index c124f2b..c5de1ed 100644 --- a/lwis_device_top.c +++ b/lwis_device_top.c @@ -18,6 +18,7 @@ #include <linux/device.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/kthread.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -27,6 +28,8 @@ #endif #define LWIS_DRIVER_NAME "lwis-top" +#define LWIS_SUBSCRIBER_THREAD_NAME "lwis_s_top" +#define LWIS_SUBSCRIBER_THREAD_PRIORITY 99 static int lwis_top_register_io(struct lwis_device *lwis_dev, struct lwis_io_entry *entry, int access_size); @@ -89,7 +92,9 @@ struct lwis_trigger_event_info { static struct lwis_event_subscriber_list *event_subscriber_list_find(struct lwis_device *lwis_dev, int64_t trigger_event_id) { - struct lwis_top_device *lwis_top_dev = (struct lwis_top_device *)lwis_dev; + struct lwis_top_device *lwis_top_dev = + container_of(lwis_dev, struct lwis_top_device, base_dev); + struct lwis_event_subscriber_list *list; hash_for_each_possible (lwis_top_dev->event_subscribers, list, node, trigger_event_id) { if (list->trigger_event_id == trigger_event_id) { @@ -102,7 +107,8 @@ static struct lwis_event_subscriber_list *event_subscriber_list_find(struct lwis static struct lwis_event_subscriber_list *event_subscriber_list_create(struct lwis_device *lwis_dev, int64_t trigger_event_id) { - struct lwis_top_device *lwis_top_dev = (struct lwis_top_device *)lwis_dev; + struct lwis_top_device *lwis_top_dev = + container_of(lwis_dev, struct lwis_top_device, base_dev); struct lwis_event_subscriber_list *event_subscriber_list = kmalloc(sizeof(struct lwis_event_subscriber_list), GFP_KERNEL); if (!event_subscriber_list) { @@ -123,9 +129,10 @@ event_subscriber_list_find_or_create(struct lwis_device *lwis_dev, int64_t trigg return (list == NULL) ? event_subscriber_list_create(lwis_dev, trigger_event_id) : list; } -static void subscribe_tasklet_func(unsigned long data) +static void subscribe_work_func(struct kthread_work *work) { - struct lwis_top_device *lwis_top_dev = (struct lwis_top_device *)data; + struct lwis_top_device *lwis_top_dev = + container_of(work, struct lwis_top_device, subscribe_work); struct lwis_trigger_event_info *trigger_event; struct lwis_event_subscribe_info *subscribe_info; struct list_head *it_sub, *it_sub_tmp; @@ -134,10 +141,10 @@ static void subscribe_tasklet_func(unsigned long data) unsigned long flags; spin_lock_irqsave(&lwis_top_dev->base_dev.lock, flags); - list_for_each_safe (it_sub, it_sub_tmp, &lwis_top_dev->emitted_event_list_tasklet) { + list_for_each_safe (it_sub, it_sub_tmp, &lwis_top_dev->emitted_event_list_work) { trigger_event = list_entry(it_sub, struct lwis_trigger_event_info, node); list_del(&trigger_event->node); - event_subscriber_list = event_subscriber_list_find((struct lwis_device *)data, + event_subscriber_list = event_subscriber_list_find(&lwis_top_dev->base_dev, trigger_event->trigger_event_id); if (!event_subscriber_list || list_empty(&event_subscriber_list->list)) { dev_err(lwis_top_dev->base_dev.dev, @@ -166,7 +173,8 @@ static void lwis_top_event_notify(struct lwis_device *lwis_dev, int64_t trigger_ int64_t trigger_event_count, int64_t trigger_event_timestamp, bool in_irq) { - struct lwis_top_device *lwis_top_dev = (struct lwis_top_device *)lwis_dev; + struct lwis_top_device *lwis_top_dev = + container_of(lwis_dev, struct lwis_top_device, base_dev); unsigned long flags; struct lwis_trigger_event_info *trigger_event = @@ -181,16 +189,17 @@ static void lwis_top_event_notify(struct lwis_device *lwis_dev, int64_t trigger_ trigger_event->trigger_event_count = trigger_event_count; trigger_event->trigger_event_timestamp = trigger_event_timestamp; spin_lock_irqsave(&lwis_top_dev->base_dev.lock, flags); - list_add_tail(&trigger_event->node, &lwis_top_dev->emitted_event_list_tasklet); + list_add_tail(&trigger_event->node, &lwis_top_dev->emitted_event_list_work); spin_unlock_irqrestore(&lwis_top_dev->base_dev.lock, flags); /* Schedule deferred subscribed events */ - tasklet_schedule(&lwis_top_dev->subscribe_tasklet); + kthread_queue_work(&lwis_top_dev->base_dev.subscribe_worker, &lwis_top_dev->subscribe_work); } static int lwis_top_event_subscribe(struct lwis_device *lwis_dev, int64_t trigger_event_id, int trigger_device_id, int subscriber_device_id) { - struct lwis_top_device *lwis_top_dev = (struct lwis_top_device *)lwis_dev; + struct lwis_top_device *lwis_top_dev = + container_of(lwis_dev, struct lwis_top_device, base_dev); struct lwis_device *lwis_trigger_dev = lwis_find_dev_by_id(trigger_device_id); struct lwis_device *lwis_subscriber_dev = lwis_find_dev_by_id(subscriber_device_id); struct lwis_event_subscribe_info *old_subscription; @@ -259,7 +268,8 @@ static int lwis_top_event_subscribe(struct lwis_device *lwis_dev, int64_t trigge static int lwis_top_event_unsubscribe(struct lwis_device *lwis_dev, int64_t trigger_event_id, int subscriber_device_id) { - struct lwis_top_device *lwis_top_dev = (struct lwis_top_device *)lwis_dev; + struct lwis_top_device *lwis_top_dev = + container_of(lwis_dev, struct lwis_top_device, base_dev); struct lwis_device *trigger_dev = NULL; struct lwis_event_subscribe_info *subscribe_info = NULL; struct lwis_event_subscriber_list *event_subscriber_list; @@ -292,7 +302,7 @@ static int lwis_top_event_unsubscribe(struct lwis_device *lwis_dev, int64_t trig if (list_empty(&subscribe_info->event_subscriber_list->list)) { /* Clear pending events */ list_for_each_entry_safe (pending_event, n, - &lwis_top_dev->emitted_event_list_tasklet, + &lwis_top_dev->emitted_event_list_work, node) { if (pending_event->trigger_event_id == trigger_event_id) { list_del(&pending_event->node); @@ -317,14 +327,12 @@ static int lwis_top_event_unsubscribe(struct lwis_device *lwis_dev, int64_t trig static void lwis_top_event_subscribe_init(struct lwis_top_device *lwis_top_dev) { hash_init(lwis_top_dev->event_subscribers); - INIT_LIST_HEAD(&lwis_top_dev->emitted_event_list_tasklet); - tasklet_init(&lwis_top_dev->subscribe_tasklet, subscribe_tasklet_func, - (unsigned long)lwis_top_dev); + INIT_LIST_HEAD(&lwis_top_dev->emitted_event_list_work); + kthread_init_work(&lwis_top_dev->subscribe_work, subscribe_work_func); } -static void lwis_top_event_subscribe_clear(struct lwis_device *lwis_dev) +static void lwis_top_event_subscribe_clear(struct lwis_top_device *lwis_top_dev) { - struct lwis_top_device *lwis_top_dev = (struct lwis_top_device *)lwis_dev; struct lwis_event_subscriber_list *event_subscriber_list; struct list_head *it_event_subscriber, *it_event_subscriber_tmp; struct lwis_event_subscribe_info *subscribe_info; @@ -351,26 +359,29 @@ static void lwis_top_event_subscribe_clear(struct lwis_device *lwis_dev) } /* Clean up emitted event list */ - list_for_each_entry_safe (pending_event, n, &lwis_top_dev->emitted_event_list_tasklet, - node) { + list_for_each_entry_safe (pending_event, n, &lwis_top_dev->emitted_event_list_work, node) { list_del(&pending_event->node); kfree(pending_event); } spin_unlock_irqrestore(&lwis_top_dev->base_dev.lock, flags); + + if (lwis_top_dev->base_dev.subscribe_worker_thread) { + kthread_flush_worker(&lwis_top_dev->base_dev.subscribe_worker); + } } static void lwis_top_event_subscribe_release(struct lwis_device *lwis_dev) { - struct lwis_top_device *lwis_top_dev = (struct lwis_top_device *)lwis_dev; - lwis_top_event_subscribe_clear(lwis_dev); - /* Clean up tasklet process */ - tasklet_kill(&lwis_top_dev->subscribe_tasklet); + struct lwis_top_device *lwis_top_dev = + container_of(lwis_dev, struct lwis_top_device, base_dev); + /* Clean up subscription work */ + lwis_top_event_subscribe_clear(lwis_top_dev); } static int lwis_top_register_io(struct lwis_device *lwis_dev, struct lwis_io_entry *entry, int access_size) { - struct lwis_top_device *top_dev = (struct lwis_top_device *)lwis_dev; + struct lwis_top_device *top_dev = container_of(lwis_dev, struct lwis_top_device, base_dev); struct lwis_io_entry_rw_batch *rw_batch; int i; uint64_t reg_value; @@ -438,7 +449,9 @@ static int lwis_top_register_io(struct lwis_device *lwis_dev, struct lwis_io_ent static int lwis_top_close(struct lwis_device *lwis_dev) { - lwis_top_event_subscribe_clear(lwis_dev); + struct lwis_top_device *lwis_top_dev = + container_of(lwis_dev, struct lwis_top_device, base_dev); + lwis_top_event_subscribe_clear(lwis_top_dev); return 0; } @@ -468,7 +481,6 @@ static int lwis_top_device_probe(struct platform_device *plat_dev) /* Allocate top device specific data construct */ top_dev = kzalloc(sizeof(struct lwis_top_device), GFP_KERNEL); if (!top_dev) { - pr_err("Failed to allocate top device structure\n"); return -ENOMEM; } @@ -479,7 +491,6 @@ static int lwis_top_device_probe(struct platform_device *plat_dev) /* Call the base device probe function */ ret = lwis_base_probe(&top_dev->base_dev, plat_dev); if (ret) { - pr_err("Error in lwis base probe\n"); goto error_probe; } @@ -493,6 +504,14 @@ static int lwis_top_device_probe(struct platform_device *plat_dev) lwis_top_event_subscribe_init(top_dev); + kthread_init_worker(&top_dev->base_dev.subscribe_worker); + top_dev->base_dev.subscribe_worker_thread = kthread_run(kthread_worker_fn, + &top_dev->base_dev.subscribe_worker, LWIS_SUBSCRIBER_THREAD_NAME); + if (IS_ERR(top_dev->base_dev.subscribe_worker_thread)) { + dev_err(top_dev->base_dev.dev, "subscribe kthread_run failed\n"); + goto error_probe; + } + /* Create associated kworker threads */ ret = lwis_create_kthread_workers(&top_dev->base_dev); if (ret) { @@ -501,6 +520,16 @@ static int lwis_top_device_probe(struct platform_device *plat_dev) goto error_probe; } + ret = lwis_set_kthread_priority(&top_dev->base_dev, + top_dev->base_dev.subscribe_worker_thread, + LWIS_SUBSCRIBER_THREAD_PRIORITY); + if (ret) { + dev_err(top_dev->base_dev.dev, + "Failed to set LWIS top subscriber kthread priority (%d)", ret); + lwis_base_unprobe(&top_dev->base_dev); + goto error_probe; + } + return 0; error_probe: @@ -564,4 +593,4 @@ int lwis_top_device_deinit(void) { platform_driver_unregister(&lwis_driver); return 0; -} +}
\ No newline at end of file diff --git a/lwis_device_top.h b/lwis_device_top.h index 3800f95..11bbebc 100644 --- a/lwis_device_top.h +++ b/lwis_device_top.h @@ -28,9 +28,9 @@ struct lwis_top_device { /* Hash table of event subscribers keyed by trigger event id */ DECLARE_HASHTABLE(event_subscribers, EVENT_HASH_BITS); - /* Subscription tasklet */ - struct tasklet_struct subscribe_tasklet; - struct list_head emitted_event_list_tasklet; + /* Subscription work */ + struct kthread_work subscribe_work; + struct list_head emitted_event_list_work; }; int lwis_top_device_deinit(void); diff --git a/lwis_periodic_io.c b/lwis_periodic_io.c index 5751745..699a7fe 100644 --- a/lwis_periodic_io.c +++ b/lwis_periodic_io.c @@ -15,7 +15,6 @@ #include <linux/completion.h> #include <linux/kthread.h> #include <linux/slab.h> -#include <linux/workqueue.h> #include "lwis_allocator.h" #include "lwis_event.h" diff --git a/lwis_transaction.c b/lwis_transaction.c index 0ed5ecb..434846c 100644 --- a/lwis_transaction.c +++ b/lwis_transaction.c @@ -16,7 +16,6 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/slab.h> -#include <linux/workqueue.h> #include "lwis_allocator.h" #include "lwis_device.h" @@ -272,18 +271,18 @@ static void cancel_transaction(struct lwis_device *lwis_dev, struct lwis_transac lwis_transaction_free(lwis_dev, transaction); } -static void process_transactions_in_queue(struct lwis_client *client, - struct list_head *transaction_queue, bool in_irq) +static void transaction_work_func(struct kthread_work *work) { unsigned long flags; - struct lwis_transaction *transaction; + struct lwis_client *client = container_of(work, struct lwis_client, transaction_work); struct list_head *it_tran, *it_tran_tmp; struct list_head pending_events; + struct lwis_transaction *transaction; INIT_LIST_HEAD(&pending_events); spin_lock_irqsave(&client->transaction_lock, flags); - list_for_each_safe (it_tran, it_tran_tmp, transaction_queue) { + list_for_each_safe (it_tran, it_tran_tmp, &client->transaction_process_queue) { transaction = list_entry(it_tran, struct lwis_transaction, process_queue_node); list_del(&transaction->process_queue_node); if (transaction->resp->error_code) { @@ -291,35 +290,20 @@ static void process_transactions_in_queue(struct lwis_client *client, transaction->resp->error_code, &pending_events); } else { spin_unlock_irqrestore(&client->transaction_lock, flags); - process_transaction(client, transaction, &pending_events, in_irq, + process_transaction(client, transaction, &pending_events, + /*in_irq=*/false, /*skip_err=*/false); spin_lock_irqsave(&client->transaction_lock, flags); } } spin_unlock_irqrestore(&client->transaction_lock, flags); - lwis_pending_events_emit(client->lwis_dev, &pending_events, in_irq); -} - -static void transaction_tasklet_func(unsigned long data) -{ - struct lwis_client *client = (struct lwis_client *)data; - - process_transactions_in_queue(client, &client->transaction_process_queue_tasklet, - /*in_irq=*/true); -} - -static void transaction_work_func(struct kthread_work *work) -{ - struct lwis_client *client = container_of(work, struct lwis_client, transaction_work); - process_transactions_in_queue(client, &client->transaction_process_queue, /*in_irq=*/false); + lwis_pending_events_emit(client->lwis_dev, &pending_events, /*in_irq=*/false); } int lwis_transaction_init(struct lwis_client *client) { spin_lock_init(&client->transaction_lock); - INIT_LIST_HEAD(&client->transaction_process_queue_tasklet); - tasklet_init(&client->transaction_tasklet, transaction_tasklet_func, (unsigned long)client); INIT_LIST_HEAD(&client->transaction_process_queue); kthread_init_work(&client->transaction_work, transaction_work_func); client->transaction_counter = 0; @@ -337,7 +321,6 @@ int lwis_transaction_clear(struct lwis_client *client) "Failed to wait for all in-process transactions to complete (%d)\n", ret); return ret; } - tasklet_kill(&client->transaction_tasklet); return 0; } @@ -391,18 +374,12 @@ int lwis_transaction_client_flush(struct lwis_client *client) if (client->lwis_dev->transaction_worker_thread) kthread_flush_worker(&client->lwis_dev->transaction_worker); - /* Wait for tasklet to complete in-progress transactions and disable. */ - tasklet_disable(&client->transaction_tasklet); - spin_lock_irqsave(&client->transaction_lock, flags); - /* Both transaction queues should be empty after draining, but check anyway. */ + /* The transaction queue should be empty after canceling all transactions, + * but check anyway. */ cancel_all_transactions_in_queue_locked(client, &client->transaction_process_queue); - cancel_all_transactions_in_queue_locked(client, &client->transaction_process_queue_tasklet); spin_unlock_irqrestore(&client->transaction_lock, flags); - /* Resume the tasklet once making sure transactions are all flushed. */ - tasklet_enable(&client->transaction_tasklet); - return 0; } @@ -622,16 +599,9 @@ static int queue_transaction_locked(struct lwis_client *client, if (info->trigger_event_id == LWIS_EVENT_ID_NONE) { /* Immediate trigger. */ - if (info->run_at_real_time) { - list_add_tail(&transaction->process_queue_node, - &client->transaction_process_queue_tasklet); - tasklet_schedule(&client->transaction_tasklet); - } else { - list_add_tail(&transaction->process_queue_node, - &client->transaction_process_queue); - kthread_queue_work(&client->lwis_dev->transaction_worker, - &client->transaction_work); - } + list_add_tail(&transaction->process_queue_node, &client->transaction_process_queue); + kthread_queue_work(&client->lwis_dev->transaction_worker, + &client->transaction_work); } else { /* Trigger by event. */ event_list = event_list_find_or_create(client, info->trigger_event_id); @@ -724,9 +694,6 @@ static void defer_transaction_locked(struct lwis_client *client, process_transaction(client, transaction, pending_events, in_irq, /*skip_err=*/false); spin_lock_irqsave(&client->transaction_lock, flags); - } else if (transaction->info.run_at_real_time) { - list_add_tail(&transaction->process_queue_node, - &client->transaction_process_queue_tasklet); } else { list_add_tail(&transaction->process_queue_node, &client->transaction_process_queue); } @@ -784,9 +751,6 @@ int lwis_transaction_event_trigger(struct lwis_client *client, int64_t event_id, } /* Schedule deferred transactions */ - if (!list_empty(&client->transaction_process_queue_tasklet)) { - tasklet_schedule(&client->transaction_tasklet); - } if (!list_empty(&client->transaction_process_queue)) { kthread_queue_work(&client->lwis_dev->transaction_worker, &client->transaction_work); |