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 <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1346820
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Konstantin Makariev <kmakariev@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2019-04-29 15:12:43 -05:00 • committed by Konstantin Makariev
commit db27ede695
5 changed files with 135 additions and 102 deletions

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -335,6 +335,7 @@ enum {
STATE_INIT,
STATE_FLASH,
STATE_QUERY,
STATE_LOADING,
STATE_INVALID
};

View file

@ -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;

View file

@ -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;