From db27ede6959624a99bfb9159c256665fa68501c4 Mon Sep 17 00:00:00 2001 From: Konstantin Makariev Date: Mon, 29 Apr 2019 15:12:43 -0500 Subject: [PATCH] synaptics_mmi: load module with regard to power state When FW upgrade happens, regmap might change. This makes access to test reporting invalid and thus DLKM needs to reload. However, if touch IC's power state does not allow successful I2C communications, DLKM will never properly initialize. This change introdices 2 things: * waiting for valid power state to load DLKM * new state "loading" that allows to hold on power state change during DLKM load Note: It has been evaluated for test reporting DLKM only at this time. Long term it would need to apply to all DLKMs. Change-Id: I86f1ab6b815053e499b01a655fccf517d1e9addc Signed-off-by: Konstantin Makariev Reviewed-on: https://gerrit.mot.com/1346820 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Konstantin Makariev Submit-Approved: Jira Key --- .../synaptics_dsx_control_access_block.c | 4 +- .../synaptics_mmi/synaptics_dsx_i2c.c | 54 ++++-- .../synaptics_mmi/synaptics_dsx_i2c.h | 1 + .../synaptics_mmi/synaptics_dsx_rmi_dev.c | 4 +- .../synaptics_dsx_test_reporting.c | 170 +++++++++--------- 5 files changed, 133 insertions(+), 100 deletions(-) diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_control_access_block.c b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_control_access_block.c index 3075bbb90903..fdbff7ac64cd 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_control_access_block.c +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_control_access_block.c @@ -419,7 +419,7 @@ static int __init synaptics_control_access_block_module_init(void) synaptics_rmi4_new_function(RMI_CTRL_ACCESS_BLK, true, synaptics_control_access_block_init, synaptics_control_access_block_remove, - NULL, NULL, IC_MODE_ANY); + NULL, NULL, IC_MODE_UI); return 0; } @@ -429,7 +429,7 @@ static void __exit synaptics_control_access_block_module_exit(void) synaptics_rmi4_new_function(RMI_CTRL_ACCESS_BLK, false, synaptics_control_access_block_init, synaptics_control_access_block_remove, - NULL, NULL, IC_MODE_ANY); + NULL, NULL, IC_MODE_UI); wait_for_completion(&remove_complete); return; } diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.c index 5cfa5c7dcc15..a1c17dfdaad7 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.c +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.c @@ -2653,7 +2653,7 @@ static void synaptics_dsx_enable_wakeup_source( static const char * const synaptics_state_names[] = {"UNKNOWN", "ACTIVE", "SUSPEND", "UNUSED", "STANDBY", "BL", "INIT", - "FLASH", "QUERY", "INVALID" }; + "FLASH", "QUERY", "LOADING", "INVALID" }; static const char *synaptics_dsx_state_name(int state) { @@ -2766,6 +2766,7 @@ static int synaptics_dsx_wait_for_idle(struct synaptics_rmi4_data *rmi4_data) current_state = synaptics_dsx_get_state_safe(rmi4_data); if (!(current_state == STATE_INIT || current_state == STATE_FLASH || + current_state == STATE_LOADING || current_state == STATE_UNKNOWN)) break; @@ -2884,6 +2885,7 @@ static void synaptics_dsx_sensor_state(struct synaptics_rmi4_data *rmi4_data, case STATE_UNKNOWN: rmi4_data->in_bootloader = false; case STATE_FLASH: + case STATE_LOADING: /* no special handling for these states */ break; @@ -6745,10 +6747,20 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) if (exp_fhandler->mode == IC_MODE_UI) { if (rmi4_data->in_bootloader) { - dev_err(dev, "%s: handler %d requires UI mode\n", + dev_warn(dev, "%s: handler %d requires UI mode\n", __func__, exp_fhandler->fn_type); continue; } + /* UI mode requires IC powered on */ + if (state == STATE_SUSPEND) { + dev_warn(dev, "%s: handler %d cannot operate while suspended\n", + __func__, exp_fhandler->fn_type); + scheduled_delay = 500; + continue; + } + /* postpone suspend for loading RMI_F54 and */ + if (exp_fhandler->fn_type == RMI_F54) + synaptics_dsx_sensor_state(rmi4_data, STATE_LOADING); } exp_fhandler->func_init(rmi4_data); @@ -6762,7 +6774,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) regs = find_function(rmi4_data, SYNAPTICS_RMI4_F54); if (!regs) - continue; + goto restore_state; error = rmi4_data->scan_f54_ctrl_regs(rmi4_data, regs); if (error) { regs->nr_regs = 0; @@ -6771,7 +6783,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) regs = find_function(rmi4_data, SYNAPTICS_RMI4_F54 | COMMAND_TYPE); if (!regs) - continue; + goto restore_state; error = rmi4_data->scan_f54_cmd_regs(rmi4_data, regs); if (error) { regs->nr_regs = 0; @@ -6780,7 +6792,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) regs = find_function(rmi4_data, SYNAPTICS_RMI4_F54 | DATA_TYPE); if (!regs) - continue; + goto restore_state; error = rmi4_data->scan_f54_data_regs(rmi4_data, regs); if (error) { regs->nr_regs = 0; @@ -6790,7 +6802,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) regs = find_function(rmi4_data, SYNAPTICS_RMI4_F54 | QUERY_TYPE); if (!regs) - continue; + goto restore_state; error = rmi4_data->scan_f54_query_regs(rmi4_data, regs); if (error) { regs->nr_regs = 0; @@ -6813,11 +6825,9 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) control_access_block_update_dynamic(rmi4_data); } - if (exp_fhandler->fn_type == RMI_FW_UPDATER) { + if (exp_fhandler->fn_type == RMI_FW_UPDATER && exp_fhandler->func_status) { int status; - if (!exp_fhandler->func_status) - continue; status = exp_fhandler->func_status(rmi4_data); /* consider changing to */ /* if (status == 1) */ @@ -6827,7 +6837,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) rmi = &(rmi4_data->rmi4_mod_info); rmi4_data->in_bootloader = true; - synaptics_dsx_set_state_safe(rmi4_data, STATE_BL); + synaptics_dsx_sensor_state(rmi4_data, STATE_BL); state = synaptics_dsx_get_state_safe(rmi4_data); dev_dbg(dev, "%s: current state %s\n", @@ -6855,11 +6865,17 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) /* allowing sufficient time for F34 to complete */ scheduled_delay = 3000; } + +restore_state: + if (STATE_LOADING == synaptics_dsx_get_state_safe(rmi4_data)) + synaptics_dsx_sensor_state(rmi4_data, state); } - if (scheduled_delay) + if (scheduled_delay) { queue_delayed_work(det_workqueue, &exp_fn_ctrl->det_work, msecs_to_jiffies(scheduled_delay)); + dev_dbg(dev, "%s: re-scheduled %d\n", __func__, scheduled_delay); + } release_mutex: mutex_unlock(&exp_fn_ctrl->list_mutex); @@ -6936,12 +6952,18 @@ void synaptics_rmi4_new_function( list_add_tail(&exp_fhandler->link, &rmi4_data->exp_fn_ctrl.fn_list); } else { list_for_each_entry(exp_fhandler, &rmi4_data->exp_fn_ctrl.fn_list, link) { - if (exp_fhandler->func_init == func_init) { - /* leave inserted flag ON to run */ - /* remove function in detection work */ - exp_fhandler->func_init = NULL; - goto exit; + if (exp_fhandler->func_init != func_init) + continue; + /* insert flag needed to run remove function in detection */ + /* work even though function was never properly inserted */ + if (!exp_fhandler->inserted) { + exp_fhandler->inserted = true; + dev_info(&rmi4_data->i2c_client->dev, + "removing not inserted handler %d\n", + exp_fhandler->fn_type); } + exp_fhandler->func_init = NULL; + goto exit; } } diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.h b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.h index 592aee7e762c..af11b0835388 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.h +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.h @@ -335,6 +335,7 @@ enum { STATE_INIT, STATE_FLASH, STATE_QUERY, + STATE_LOADING, STATE_INVALID }; diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_rmi_dev.c index 4eb87605a5b6..13b4a07c12f9 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_rmi_dev.c +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_rmi_dev.c @@ -850,7 +850,7 @@ static int __init rmidev_module_init(void) synaptics_rmi4_new_function(next, RMI_DEV, true, rmidev_init_device, rmidev_remove_device, - NULL, NULL, IC_MODE_ANY); + NULL, NULL, IC_MODE_UI); } return 0; @@ -869,7 +869,7 @@ static void __exit rmidev_module_exit(void) synaptics_rmi4_new_function(next, RMI_DEV, false, rmidev_init_device, rmidev_remove_device, - NULL, NULL, IC_MODE_ANY); + NULL, NULL, IC_MODE_UI); wait_for_completion(&rmidev->remove_complete); kfree(rmidev); next->rmidev_data = NULL; diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_test_reporting.c b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_test_reporting.c index 40359ea42d3b..0527a84e6ff1 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_test_reporting.c +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_test_reporting.c @@ -2304,6 +2304,7 @@ struct f54_kobj_data { #define to_f54_attr(x) container_of(x, struct f54_attribute, attr) struct synaptics_rmi4_f54_handle { + bool init_done; bool no_auto_cal; int status; unsigned char intr_mask; @@ -3453,92 +3454,92 @@ static void print_image_report(struct synaptics_rmi4_f54_handle *f54) static void free_control_mem(struct synaptics_rmi4_f54_handle *f54) { - struct f54_control control = f54->control; + struct f54_control *control = &f54->control; - kfree(control.reg_0); - kfree(control.reg_1); - kfree(control.reg_2); - kfree(control.reg_3); - kfree(control.reg_4__6); - kfree(control.reg_7); - kfree(control.reg_8__9); - kfree(control.reg_10); - kfree(control.reg_11); - kfree(control.reg_12__13); - kfree(control.reg_14); - if (control.reg_15) - kfree(control.reg_15->data); - kfree(control.reg_15); - if (control.reg_16) - kfree(control.reg_16->data); - kfree(control.reg_16); - if (control.reg_17) - kfree(control.reg_17->data); - kfree(control.reg_17); - if (control.reg_18) - kfree(control.reg_18->data); - kfree(control.reg_18); - if (control.reg_19) - kfree(control.reg_19->data); - kfree(control.reg_19); - kfree(control.reg_20); - kfree(control.reg_21); - kfree(control.reg_22__26); - kfree(control.reg_27); - kfree(control.reg_28); - kfree(control.reg_29); - kfree(control.reg_30); - kfree(control.reg_31); - kfree(control.reg_32__35); - if (control.reg_36) - kfree(control.reg_36->data); - kfree(control.reg_36); - if (control.reg_37) - kfree(control.reg_37->data); - kfree(control.reg_37); - if (control.reg_38) - kfree(control.reg_38->data); - kfree(control.reg_38); - if (control.reg_39) - kfree(control.reg_39->data); - kfree(control.reg_39); - if (control.reg_40) - kfree(control.reg_40->data); - kfree(control.reg_40); - if (control.reg_89) - kfree(control.reg_89->data); - kfree(control.reg_89); - kfree(control.reg_93); - if (control.reg_95) - kfree(control.reg_95->data); - kfree(control.reg_95); - kfree(control.reg_99); - kfree(control.reg_107); - kfree(control.reg_113); - kfree(control.reg_116); - kfree(control.reg_137); - kfree(control.reg_145); - kfree(control.reg_146); - kfree(control.reg_242); - kfree(control.reg_269); + kfree(control->reg_0); + kfree(control->reg_1); + kfree(control->reg_2); + kfree(control->reg_3); + kfree(control->reg_4__6); + kfree(control->reg_7); + kfree(control->reg_8__9); + kfree(control->reg_10); + kfree(control->reg_11); + kfree(control->reg_12__13); + kfree(control->reg_14); + if (control->reg_15) + kfree(control->reg_15->data); + kfree(control->reg_15); + if (control->reg_16) + kfree(control->reg_16->data); + kfree(control->reg_16); + if (control->reg_17) + kfree(control->reg_17->data); + kfree(control->reg_17); + if (control->reg_18) + kfree(control->reg_18->data); + kfree(control->reg_18); + if (control->reg_19) + kfree(control->reg_19->data); + kfree(control->reg_19); + kfree(control->reg_20); + kfree(control->reg_21); + kfree(control->reg_22__26); + kfree(control->reg_27); + kfree(control->reg_28); + kfree(control->reg_29); + kfree(control->reg_30); + kfree(control->reg_31); + kfree(control->reg_32__35); + if (control->reg_36) + kfree(control->reg_36->data); + kfree(control->reg_36); + if (control->reg_37) + kfree(control->reg_37->data); + kfree(control->reg_37); + if (control->reg_38) + kfree(control->reg_38->data); + kfree(control->reg_38); + if (control->reg_39) + kfree(control->reg_39->data); + kfree(control->reg_39); + if (control->reg_40) + kfree(control->reg_40->data); + kfree(control->reg_40); + if (control->reg_89) + kfree(control->reg_89->data); + kfree(control->reg_89); + kfree(control->reg_93); + if (control->reg_95) + kfree(control->reg_95->data); + kfree(control->reg_95); + kfree(control->reg_99); + kfree(control->reg_107); + kfree(control->reg_113); + kfree(control->reg_116); + kfree(control->reg_137); + kfree(control->reg_145); + kfree(control->reg_146); + kfree(control->reg_242); + kfree(control->reg_269); return; } static void free_data_mem(struct synaptics_rmi4_f54_handle *f54) { - struct f54_data data = f54->data; + struct f54_data *data = &f54->data; - kfree(data.reg_4); - kfree(data.reg_6); - kfree(data.reg_7_0); - kfree(data.reg_7_1); - kfree(data.reg_8); - kfree(data.reg_9); - kfree(data.reg_10); - kfree(data.reg_14); - kfree(data.reg_16); - kfree(data.reg_17); + kfree(data->reg_4); + kfree(data->reg_6); + kfree(data->reg_7_0); + kfree(data->reg_7_1); + kfree(data->reg_8); + kfree(data->reg_9); + kfree(data->reg_10); + kfree(data->reg_14); + kfree(data->reg_16); + kfree(data->reg_17); } static void remove_sysfs(struct synaptics_rmi4_f54_handle *f54) @@ -5868,6 +5869,8 @@ found: INIT_WORK(&f54->timeout_work, timeout_set_status); #endif + f54->init_done = true; + return 0; exit_sysfs: @@ -5891,6 +5894,12 @@ static void synaptics_rmi4_f54_remove(struct synaptics_rmi4_data *rmi4_data) { struct synaptics_rmi4_f54_handle *f54 = (struct synaptics_rmi4_f54_handle *)rmi4_data->f54_data; + + if (!f54->init_done) { + dev_dbg(&rmi4_data->i2c_client->dev, "%s: no cleanup necessary!!!\n", __func__); + goto exit_and_complete; + } + #ifdef WATCHDOG_HRTIMER hrtimer_cancel(&f54->watchdog); #endif @@ -5902,11 +5911,12 @@ static void synaptics_rmi4_f54_remove(struct synaptics_rmi4_data *rmi4_data) kfree(f54->report_data); kfree(f54->fn55); + /* cancel delayed work first then free fn_ptr!!! */ + cancel_delayed_work_sync(&f54->status_work); kfree(f54->fn_ptr); - cancel_delayed_work(&f54->status_work); wakeup_source_trash(&f54->test_wake_lock); - +exit_and_complete: complete(&f54->remove_complete); return;