diff options
author | Wendly Li <wendlyli@google.com> | 2023-02-03 17:26:04 +0000 |
---|---|---|
committer | Wendly Li <wendlyli@google.com> | 2023-02-08 05:52:25 +0000 |
commit | 1a043be839f671f70b1e6fa826daefae8270d1bd (patch) | |
tree | 5f8002f6b79f1eaf3c4fb3bc39bfd9c74f1dd8ab | |
parent | d2a3010da273bd6d0fd316ecce8c4721588dafa1 (diff) | |
download | common-1a043be839f671f70b1e6fa826daefae8270d1bd.tar.gz |
gti: fix heatmap protection
The goodix driver read heatmap in vendor_irq_thread_fn. We need to
protect it as well.
Bug: 262053705
Test: check heatmap works properly
Change-Id: I2d5d285634c34da6dd82993b6ca1dc255d72cf5b
Signed-off-by: Wendly Li <wendlyli@google.com>
-rw-r--r-- | goog_touch_interface.c | 88 | ||||
-rw-r--r-- | goog_touch_interface.h | 3 |
2 files changed, 65 insertions, 26 deletions
diff --git a/goog_touch_interface.c b/goog_touch_interface.c index 18d0f99..f6ad08e 100644 --- a/goog_touch_interface.c +++ b/goog_touch_interface.c @@ -2178,8 +2178,52 @@ static void goog_offload_populate_stylus_status_channel( ss->pen_active = stylus_cmd->pen_active; } +static int goog_get_sensor_data(struct goog_touch_interface *gti, + struct gti_sensor_data_cmd *cmd, bool reset_data) +{ + int ret = 0; + int err = 0; + u16 tx = gti->offload.caps.tx_size; + u16 rx = gti->offload.caps.rx_size; + + if (reset_data) { + if (cmd->type == GTI_SENSOR_DATA_TYPE_MS) { + cmd->size = TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx); + } else if (cmd->type == GTI_SENSOR_DATA_TYPE_SS) { + cmd->size = TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx); + } else { + ret = -EINVAL; + goto exit; + } + + memset(gti->heatmap_buf, 0, cmd->size); + cmd->buffer = gti->heatmap_buf; + goto exit; + } + + err = goog_pm_wake_lock(gti, GTI_PM_WAKELOCK_TYPE_SENSOR_DATA, true); + if (err < 0) { + GOOG_WARN(gti, "Failed to lock GTI_PM_WAKELOCK_TYPE_SENSOR_DATA: %d!\n", err); + ret = err; + goto exit; + } + + err = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA); + if (err < 0) { + GOOG_WARN(gti, "Failed to get sensor data: %d!\n", err); + ret = err; + } + + err = goog_pm_wake_unlock(gti, GTI_PM_WAKELOCK_TYPE_SENSOR_DATA); + if (err < 0) + GOOG_WARN(gti, "Failed to unlock GTI_PM_WAKELOCK_TYPE_SENSOR_DATA: %d!\n", err); + +exit: + return ret; +} + void goog_offload_populate_frame(struct goog_touch_interface *gti, - struct touch_offload_frame *frame, bool report_from_irq) + struct touch_offload_frame *frame, bool reset_data) { static u64 index; char trace_tag[128]; @@ -2233,14 +2277,8 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti, } else if (channel_type & TOUCH_SCAN_TYPE_MUTUAL) { ATRACE_BEGIN("populate mutual data"); cmd->type = GTI_SENSOR_DATA_TYPE_MS; - if (!report_from_irq) { - cmd->size = TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx); - memset(gti->heatmap_buf, 0, cmd->size); - cmd->buffer = gti->heatmap_buf; - ret = 0; - } else { - ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA); - } + + ret = goog_get_sensor_data(gti, cmd, reset_data); if (ret == 0 && cmd->buffer && cmd->size == TOUCH_OFFLOAD_DATA_SIZE_2D(rx, tx)) { goog_offload_populate_mutual_channel(gti, frame, i, @@ -2253,14 +2291,8 @@ void goog_offload_populate_frame(struct goog_touch_interface *gti, } else if (channel_type & TOUCH_SCAN_TYPE_SELF) { ATRACE_BEGIN("populate self data"); cmd->type = GTI_SENSOR_DATA_TYPE_SS; - if (!report_from_irq) { - cmd->size = TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx); - memset(gti->heatmap_buf, 0, cmd->size); - cmd->buffer = gti->heatmap_buf; - ret = 0; - } else { - ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA); - } + + ret = goog_get_sensor_data(gti, cmd, reset_data); if (ret == 0 && cmd->buffer && cmd->size == TOUCH_OFFLOAD_DATA_SIZE_1D(rx, tx)) { goog_offload_populate_self_channel(gti, frame, i, @@ -2575,7 +2607,7 @@ bool goog_input_legacy_report(struct goog_touch_interface *gti) return false; } -int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq) +int goog_input_process(struct goog_touch_interface *gti, bool reset_data) { int ret = 0; struct touch_offload_frame **frame = >i->offload_frame; @@ -2610,7 +2642,7 @@ int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq) ret = -EBUSY; } else { goog_offload_set_running(gti, true); - goog_offload_populate_frame(gti, *frame, report_from_irq); + goog_offload_populate_frame(gti, *frame, reset_data); ret = touch_offload_queue_frame(>i->offload, *frame); if (ret) GOOG_ERR(gti, "failed to queue reserved frame(ret %d)!\n", ret); @@ -2632,7 +2664,7 @@ int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq) cmd->buffer = NULL; cmd->size = 0; cmd->type = GTI_SENSOR_DATA_TYPE_MS; - ret = goog_process_vendor_cmd(gti, GTI_CMD_GET_SENSOR_DATA); + ret = goog_get_sensor_data(gti, cmd, reset_data); if (ret == 0 && cmd->buffer && cmd->size) memcpy(gti->heatmap_buf, cmd->buffer, cmd->size); goog_v4l2_read(gti, gti->input_timestamp); @@ -2794,9 +2826,7 @@ void goog_input_release_all_fingers(struct goog_touch_interface *gti) goog_input_unlock(gti); - mutex_lock(>i->input_process_lock); - goog_input_process(gti, false); - mutex_unlock(>i->input_process_lock); + goog_input_process(gti, true); } void goog_register_tbn(struct goog_touch_interface *gti) @@ -3596,13 +3626,21 @@ static irqreturn_t gti_irq_thread_fn(int irq, void *data) ATRACE_BEGIN(__func__); cpu_latency_qos_update_request(>i->pm_qos_req, 100 /* usec */); + + /* + * Some vendor drivers read sensor data inside vendor_irq_thread_fn. + * We need to lock input_process_lock before vendor_irq_thread_fn to + * avoid thread safe issue. + */ + mutex_lock(>i->input_process_lock); + if (gti->vendor_irq_thread_fn) ret = gti->vendor_irq_thread_fn(irq, gti->vendor_irq_cookie); else ret = IRQ_HANDLED; - mutex_lock(>i->input_process_lock); - goog_input_process(gti, true); + goog_input_process(gti, false); + mutex_unlock(>i->input_process_lock); gti_debug_hc_update(gti, false); diff --git a/goog_touch_interface.h b/goog_touch_interface.h index d515098..d7ffc88 100644 --- a/goog_touch_interface.h +++ b/goog_touch_interface.h @@ -160,6 +160,7 @@ enum gti_pm_wakelock_type : u32 { GTI_PM_WAKELOCK_TYPE_FORCE_ACTIVE = (1 << 4), GTI_PM_WAKELOCK_TYPE_BUGREPORT = (1 << 5), GTI_PM_WAKELOCK_TYPE_OFFLOAD_REPORT = (1 << 6), + GTI_PM_WAKELOCK_TYPE_SENSOR_DATA = (1 << 7), }; enum gti_proc_type : u32 { @@ -697,7 +698,7 @@ inline int goog_request_threaded_irq(struct goog_touch_interface *gti, unsigned long irqflags, const char *devname, void *dev_id); int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type cmd_type); -int goog_input_process(struct goog_touch_interface *gti, bool report_from_irq); +int goog_input_process(struct goog_touch_interface *gti, bool reset_data); struct goog_touch_interface *goog_touch_interface_probe( void *private_data, struct device *dev, |