summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMeghana Barkalle <mbarkalle@google.com>2023-06-07 08:06:08 +0000
committerTreehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com>2023-12-13 16:36:31 +0000
commitd71684befae0474ccb681ae1bfa784e25ca1e605 (patch)
tree90270a81e3cc823daf611276d503ebe3700a98d0
parent7094a6af934072220f561662c5bd32e6de61f5dd (diff)
downloadlwis-d71684befae0474ccb681ae1bfa784e25ca1e605.tar.gz
LWIS: Handle device flush for transactions with limit
Add flush state to indicate client's flush state: FLUSHING - indicates a flush call has been issued on the client NOT FLUSHING - indicates the device is processing transactions normally Add flush lock to protect the state variable. Test: GCA SMOKE Test Bug: 299130975 Change-Id: Iefbbe23ad936a6957f399a051cd40451b0ccfb3c (cherry picked from commit 1a84358ccca0a8635dde92e361559d69b79bdb2a) Signed-off-by: Meghana Barkalle <mbarkalle@google.com>
-rw-r--r--lwis_device.c6
-rw-r--r--lwis_device.h17
-rw-r--r--lwis_transaction.c34
3 files changed, 52 insertions, 5 deletions
diff --git a/lwis_device.c b/lwis_device.c
index 4735f62..6017095 100644
--- a/lwis_device.c
+++ b/lwis_device.c
@@ -122,6 +122,7 @@ static int lwis_open(struct inode *node, struct file *fp)
mutex_init(&lwis_client->lock);
spin_lock_init(&lwis_client->periodic_io_lock);
spin_lock_init(&lwis_client->event_lock);
+ spin_lock_init(&lwis_client->flush_lock);
/* Empty hash table for client event states */
hash_init(lwis_client->event_states);
@@ -160,6 +161,10 @@ static int lwis_open(struct inode *node, struct file *fp)
/* Storing the client handle in fp private_data for easy access */
fp->private_data = lwis_client;
+ spin_lock_irqsave(&lwis_client->flush_lock, flags);
+ lwis_client->flush_state = NOT_FLUSHING;
+ spin_unlock_irqrestore(&lwis_client->flush_lock, flags);
+
if (lwis_i2c_bus_manager_connect_client(lwis_client)) {
dev_err(lwis_dev->dev, "Failed to connect lwis client to I2C bus manager\n");
return -EINVAL;
@@ -224,6 +229,7 @@ static int lwis_release_client(struct lwis_client *lwis_client)
struct lwis_device *lwis_dev = lwis_client->lwis_dev;
int rc = 0;
unsigned long flags;
+
rc = lwis_cleanup_client(lwis_client);
if (rc) {
return rc;
diff --git a/lwis_device.h b/lwis_device.h
index 97d865a..1313587 100644
--- a/lwis_device.h
+++ b/lwis_device.h
@@ -47,6 +47,19 @@
#define BTS_UNSUPPORTED -1
#define MAX_UNIFIED_POWER_DEVICE 8
+/* enum lwis_client_flush_state
+ * Client flush states indicate if the client has been issued a
+ * flush on the transaction worker threads.
+ * Client will move to FLUSHING state only when a direct call to
+ * lwis_transaction_client_flush has been made.
+ * Once the flush is complete, the client will transition back
+ * to NOT_FLUSHING state.
+ */
+enum lwis_client_flush_state {
+ NOT_FLUSHING = 0,
+ FLUSHING
+};
+
/* Forward declaration for lwis_device. This is needed for the declaration for
lwis_device_subclass_operations data struct. */
struct lwis_device;
@@ -349,6 +362,10 @@ struct lwis_client {
bool is_enabled;
/* Work item to schedule I2C transfers */
struct kthread_work i2c_work;
+ /* Indicates if the client has been issued a flush worker call */
+ enum lwis_client_flush_state flush_state;
+ /* Lock to guard client's flush state changes */
+ spinlock_t flush_lock;
};
/*
diff --git a/lwis_transaction.c b/lwis_transaction.c
index 64c8b7d..bb0b1ad 100644
--- a/lwis_transaction.c
+++ b/lwis_transaction.c
@@ -524,15 +524,31 @@ void lwis_process_transactions_in_queue(struct lwis_client *client)
/*
* Queue the remaining transaction again on the transaction worker/bus maanger worker
- * to be processed again later
+ * to be processed again later if the client is not flushing
*/
- if (i2c_bus_manager) {
- kthread_queue_work(&i2c_bus_manager->i2c_bus_worker,
+ spin_lock_irqsave(&client->flush_lock, flags);
+ if (client->flush_state == NOT_FLUSHING) {
+ if (lwis_transaction_debug) {
+ dev_info(
+ client->lwis_dev->dev,
+ "Client is not flushing, schedule the remaining work");
+ }
+
+ if (i2c_bus_manager) {
+ kthread_queue_work(&i2c_bus_manager->i2c_bus_worker,
&client->i2c_work);
- } else {
- kthread_queue_work(&client->lwis_dev->transaction_worker,
+ } else {
+ kthread_queue_work(&client->lwis_dev->transaction_worker,
&client->transaction_work);
+ }
+ } else {
+ if (lwis_transaction_debug) {
+ dev_info(
+ client->lwis_dev->dev,
+ "Client is flushing, aborting the remaining transaction");
+ }
}
+ spin_unlock_irqrestore(&client->flush_lock, flags);
break;
}
}
@@ -622,6 +638,10 @@ int lwis_transaction_client_flush(struct lwis_client *client)
}
spin_unlock_irqrestore(&client->transaction_lock, flags);
+ spin_lock_irqsave(&client->flush_lock, flags);
+ client->flush_state = FLUSHING;
+ spin_unlock_irqrestore(&client->flush_lock, flags);
+
if (i2c_bus_manager) {
lwis_i2c_bus_manager_flush_i2c_worker(lwis_dev);
} else {
@@ -630,6 +650,10 @@ int lwis_transaction_client_flush(struct lwis_client *client)
}
}
+ spin_lock_irqsave(&client->flush_lock, flags);
+ client->flush_state = NOT_FLUSHING;
+ spin_unlock_irqrestore(&client->flush_lock, flags);
+
spin_lock_irqsave(&client->transaction_lock, flags);
/* The transaction queue should be empty after canceling all transactions,
* but check anyway. */