summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixelBot AutoMerger <android-nexus-securitybot@system.gserviceaccount.com>2023-11-19 19:04:16 -0800
committerSecurityBot <android-nexus-securitybot@system.gserviceaccount.com>2023-11-19 19:04:16 -0800
commit31112e7b331d43c7ff69c834e9a7f7ea286d4f6a (patch)
tree07b88976dc4acba94449b794750ecb3263ac5b71
parentccecf6ec8abfb881106fc06105242054a04badf0 (diff)
parent91ad6953bf05ee72c3d2fdfa1ae816406489f29c (diff)
downloadlwis-31112e7b331d43c7ff69c834e9a7f7ea286d4f6a.tar.gz
Merge android14-gs-pixel-5.15-24Q1 into android14-gs-pixel-5.15
SBMerger: 571992243 Change-Id: I5a4bcef89f737ec210edf40af39c9a14cf396472 Signed-off-by: SecurityBot <android-nexus-securitybot@system.gserviceaccount.com>
-rw-r--r--lwis_interrupt.c47
-rw-r--r--lwis_interrupt.h13
-rw-r--r--lwis_ioctl.c7
3 files changed, 66 insertions, 1 deletions
diff --git a/lwis_interrupt.c b/lwis_interrupt.c
index a29b903..1753be1 100644
--- a/lwis_interrupt.c
+++ b/lwis_interrupt.c
@@ -40,6 +40,16 @@ static irqreturn_t lwis_interrupt_regular_isr(int irq_number, void *data);
static irqreturn_t lwis_interrupt_aggregate_isr(int irq_number, void *data);
static irqreturn_t lwis_interrupt_gpios_event_isr(int irq_number, void *data);
+static void combine_mask_value(struct lwis_interrupt *irq, int int_reg_bit, bool is_set)
+{
+ /* Unmask the interrupt */
+ if (is_set) {
+ irq->mask_value |= BIT_ULL(int_reg_bit);
+ } else {
+ irq->mask_value &= ~BIT_ULL(int_reg_bit);
+ }
+}
+
struct lwis_interrupt_list *lwis_interrupt_list_alloc(struct lwis_device *lwis_dev, int count)
{
struct lwis_interrupt_list *list;
@@ -151,6 +161,8 @@ int lwis_interrupt_get(struct lwis_interrupt_list *list, int index,
spin_lock_irqsave(&list->irq[index].lock, flags);
list->irq[index].irq = irq;
+ list->irq[index].has_mask_value = false;
+ list->irq[index].mask_value = 0;
spin_unlock_irqrestore(&list->irq[index].lock, flags);
return 0;
@@ -712,12 +724,44 @@ static int lwis_interrupt_single_event_enable_locked(struct lwis_interrupt *irq,
is_set = (!irq->mask_toggled) ? enabled : !enabled;
/* GPIO HW interrupt doesn't support to set interrupt mask */
if (irq->irq_type != GPIO_HW_INTERRUPT) {
- ret = lwis_interrupt_set_mask(irq, event->int_reg_bit, is_set);
+ combine_mask_value(irq, event->int_reg_bit, is_set);
}
return ret;
}
+int lwis_interrupt_write_combined_mask_value(struct lwis_interrupt_list *list)
+{
+ int index, ret = 0;
+ unsigned long flags;
+
+ for (index = 0; index < list->count; index++) {
+ spin_lock_irqsave(&list->irq[index].lock, flags);
+ /* GPIO HW interrupt doesn't support to set interrupt mask */
+ if (list->irq[index].irq_type != GPIO_HW_INTERRUPT) {
+ if (list->irq[index].has_mask_value) {
+ /* Write the mask register */
+ ret = lwis_device_single_register_write(
+ list->irq[index].lwis_dev, list->irq[index].irq_reg_bid,
+ list->irq[index].irq_mask_reg, list->irq[index].mask_value,
+ list->irq[index].irq_reg_access_size);
+ if (ret) {
+ dev_err(list->lwis_dev->dev,
+ "Failed to write IRQ mask register(0x%llx): %d\n",
+ list->irq[index].irq_mask_reg, ret);
+ spin_unlock_irqrestore(&list->irq[index].lock, flags);
+ return ret;
+ }
+ /* Set the flag to false because the mask register is written. */
+ list->irq[index].has_mask_value = false;
+ }
+ }
+ spin_unlock_irqrestore(&list->irq[index].lock, flags);
+ }
+
+ return 0;
+}
+
int lwis_interrupt_event_enable(struct lwis_interrupt_list *list, int64_t event_id, bool enabled)
{
int index, ret = -EINVAL;
@@ -733,6 +777,7 @@ int lwis_interrupt_event_enable(struct lwis_interrupt_list *list, int64_t event_
spin_lock_irqsave(&list->irq[index].lock, flags);
event = lwis_interrupt_get_single_event_info_locked(&list->irq[index], event_id);
if (event) {
+ list->irq[index].has_mask_value = true;
ret = lwis_interrupt_single_event_enable_locked(&list->irq[index], event,
enabled);
}
diff --git a/lwis_interrupt.h b/lwis_interrupt.h
index d6106bc..893ffde 100644
--- a/lwis_interrupt.h
+++ b/lwis_interrupt.h
@@ -80,6 +80,10 @@ struct lwis_interrupt {
/* List of aggregate interrupt leaf nodes */
/* GUARDED_BY(lock) */
struct list_head leaf_nodes;
+ /* Store the combined IRQ mask value */
+ uint64_t mask_value;
+ /* If IRQ mask value is written */
+ bool has_mask_value;
};
/*
@@ -170,6 +174,15 @@ int lwis_interrupt_set_gpios_event_info(struct lwis_interrupt_list *list, int in
int64_t irq_event);
/*
+ * lwis_interrupt_write_combined_mask_value: Handles writing combined mask value
+ *
+ * Locks: May lock list->irq[index].lock
+ * Alloc: No
+ * Returns: 0 on success
+ */
+int lwis_interrupt_write_combined_mask_value(struct lwis_interrupt_list *list);
+
+/*
* lwis_interrupt_event_enable: Handles masking and unmasking interrupts when
* an event is enabled or disabled
*
diff --git a/lwis_ioctl.c b/lwis_ioctl.c
index fe8dc8a..27f21cc 100644
--- a/lwis_ioctl.c
+++ b/lwis_ioctl.c
@@ -1030,6 +1030,13 @@ static int cmd_event_control_set(struct lwis_client *lwis_client, struct lwis_cm
goto exit;
}
}
+
+ if (lwis_dev->irqs) {
+ ret = lwis_interrupt_write_combined_mask_value(lwis_dev->irqs);
+ if (ret) {
+ goto exit;
+ }
+ }
exit:
kfree(k_event_controls);
header->ret_code = ret;