synaptics_mmi_class: handle delayed init

When Synaptics touch belongs to secondary display and splash screen
option enabled, driver depends on DRM display notification to follow
with HW init. In this case suspend/resule and irq enable/disable
methods can be called by class driver un-initialized causing kernel
to panic. Added atomic flag to indicate device queried successfully
to prevent un-initialized methods execution.

Change-Id: I3debfb80eac129f550acdd2fc104eacc32f499a2
Signed-off-by: Konstantin Makariev <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1641558
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Ryan Lattrel <ryanl@motorola.com>
Reviewed-by: Konstantin Makariev <kmakariev@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2020-06-24 13:04:13 -05:00 • committed by Konstantin Makariev
commit e347ef6e9c
3 changed files with 34 additions and 2 deletions

View file

@ -5788,6 +5788,8 @@ skip_f12_single_i2c_setup:
synaptics_rmi4_scan_f01_reg_info(rmi4_data);
}
atomic_set(&rmi4_data->query_done, 1);
return 0;
}
@ -6894,6 +6896,11 @@ int synaptics_rmi4_suspend(struct device *dev)
*platform_data = &rmi4_data->board;
static char ud_stats[PAGE_SIZE];
if (atomic_read(&rmi4_data->query_done) == 0) {
pr_warn("called before ic queried\n");
return 0;
}
if (atomic_cmpxchg(&rmi4_data->touch_stopped, 0, 1) == 1)
return 0;
@ -6958,6 +6965,11 @@ int synaptics_rmi4_resume(struct device *dev)
struct synaptics_dsx_platform_data
*platform_data = &rmi4_data->board;
if (atomic_read(&rmi4_data->query_done) == 0) {
pr_warn("called before ic queried\n");
return 0;
}
if (atomic_cmpxchg(&rmi4_data->touch_stopped, 1, 0) == 0)
return 0;

View file

@ -546,6 +546,7 @@ struct synaptics_rmi4_data {
int sensor_max_y;
bool irq_enabled;
atomic_t touch_stopped;
atomic_t query_done;
bool splash_screen_mode;
bool flash_enabled;
bool ic_on;

View file

@ -115,6 +115,8 @@ static int synaptics_mmi_drv_irq(struct device *dev, int state)
ASSERT_PTR(ts);
dev_dbg(dev, "%s\n", __func__);
if (atomic_read(&ts->query_done) != 1)
return -EBUSY;
switch (state) {
case 0: /* Disable irq */
synaptics_rmi4_irq_enable(ts, false);
@ -137,6 +139,8 @@ static int synaptics_mmi_reset(struct device *dev, int type)
ASSERT_PTR(ts);
dev_dbg(dev, "%s\n", __func__);
if (atomic_read(&ts->query_done) != 1)
return -EBUSY;
ret = synaptics_dsx_ic_reset(ts, type);
if (ret > 0)
dev_dbg(dev,"%s: successful reset took %dms\n", __func__, ret);
@ -152,6 +156,8 @@ static int synaptics_mmi_panel_state(struct device *dev,
struct synaptics_rmi4_data *ts = dev_get_drvdata(dev);
ASSERT_PTR(ts);
dev_dbg(dev, "%s: panel state change: %d->%d\n", __func__, from, to);
if (atomic_read(&ts->query_done) != 1)
return -EBUSY;
switch (to) {
case TS_MMI_PM_GESTURE:
case TS_MMI_PM_DEEPSLEEP:
@ -171,6 +177,8 @@ static int synaptics_mmi_post_resume(struct device *dev)
struct synaptics_rmi4_data *ts = dev_get_drvdata(dev);
ASSERT_PTR(ts);
dev_dbg(dev, "%s\n", __func__);
if (atomic_read(&ts->query_done) != 1)
return -EBUSY;
synaptics_rmi4_resume(dev);
return 0;
}
@ -183,7 +191,12 @@ static int synaptics_mmi_fw_update(struct device *dev, char *fwname)
ASSERT_PTR(ts);
dev_dbg(dev, "%s\n", __func__);
fwu = ts->fwu_data;
return (fwu && fwu->firmware_update) ? fwu->firmware_update(dev, name) : -ENOSYS;
if (!fwu || !fwu->firmware_update)
return -ENOSYS;
if (atomic_read(&ts->query_done) != 1)
return -EBUSY;
atomic_set(&ts->query_done, 0);
return fwu->firmware_update(dev, name);
}
static int synaptics_mmi_fw_erase(struct device *dev)
@ -193,7 +206,11 @@ static int synaptics_mmi_fw_erase(struct device *dev)
ASSERT_PTR(ts);
dev_dbg(dev, "%s\n", __func__);
fwu = ts->fwu_data;
return (fwu && fwu->firmware_erase) ? fwu->firmware_erase(dev) : -ENOSYS;
if (!fwu || !fwu->firmware_erase)
return -ENOSYS;
if (atomic_read(&ts->query_done) != 1)
return -EBUSY;
return fwu->firmware_erase(dev);
}
static int synaptics_mmi_charger_mode(struct device *dev, int mode)
@ -201,6 +218,8 @@ static int synaptics_mmi_charger_mode(struct device *dev, int mode)
struct synaptics_rmi4_data *ts = dev_get_drvdata(dev);
ASSERT_PTR(ts);
dev_dbg(dev, "%s\n", __func__);
if (atomic_read(&ts->query_done) != 1)
return -EBUSY;
synaptics_dsx_charger_mode(ts, mode);
return 0;
}