diff options
author | Meghana Barkalle <mbarkalle@google.com> | 2023-06-07 08:06:08 +0000 |
---|---|---|
committer | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2023-12-13 16:36:31 +0000 |
commit | d71684befae0474ccb681ae1bfa784e25ca1e605 (patch) | |
tree | 90270a81e3cc823daf611276d503ebe3700a98d0 | |
parent | 7094a6af934072220f561662c5bd32e6de61f5dd (diff) | |
download | lwis-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.c | 6 | ||||
-rw-r--r-- | lwis_device.h | 17 | ||||
-rw-r--r-- | lwis_transaction.c | 34 |
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. */ |