summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixelBot AutoMerger <android-nexus-securitybot@system.gserviceaccount.com>2023-02-05 19:48:23 -0800
committerSecurityBot <android-nexus-securitybot@system.gserviceaccount.com>2023-02-05 19:48:23 -0800
commitc7569561a0f2a411a110af601db83ce42715b9b2 (patch)
tree3a5e4872ab430c95466a20f168fa7ee02bc485dd
parent67af8da3ceabbe5f8c00a62fb7a4251ccfb3016a (diff)
parent6247e718e12b5393da220c370bdc55f7f6eb6c7c (diff)
downloadlwis-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.c2
-rw-r--r--lwis_device.h6
-rw-r--r--lwis_device_top.c85
-rw-r--r--lwis_device_top.h6
-rw-r--r--lwis_periodic_io.c1
-rw-r--r--lwis_transaction.c60
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);