diff options
author | PixelBot AutoMerger <android-nexus-securitybot@system.gserviceaccount.com> | 2023-11-19 19:04:16 -0800 |
---|---|---|
committer | SecurityBot <android-nexus-securitybot@system.gserviceaccount.com> | 2023-11-19 19:04:16 -0800 |
commit | 31112e7b331d43c7ff69c834e9a7f7ea286d4f6a (patch) | |
tree | 07b88976dc4acba94449b794750ecb3263ac5b71 | |
parent | ccecf6ec8abfb881106fc06105242054a04badf0 (diff) | |
parent | 91ad6953bf05ee72c3d2fdfa1ae816406489f29c (diff) | |
download | lwis-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.c | 47 | ||||
-rw-r--r-- | lwis_interrupt.h | 13 | ||||
-rw-r--r-- | lwis_ioctl.c | 7 |
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; |