touchscreen_mmi: use try to call and try to read

To call touchscreen methods may cause concurrent competition.
So use uniform macro TRY_TO_CALL and TRY_TO_GET to call and get from
touch IC.
Add a mutex to lock all method invoke.

Change-Id: Ifca60891582e76c5d31fbdb31a386618665d7258
Signed-off-by: haojl2 <haojl2@motorola.com>
Reviewed-on: https://gerrit.mot.com/1544138
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Jianqi Yang <yangj@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
haojl2 2020-04-28 20:34:28 +08:00 • committed by Jialei Hao
commit beca016ae8
3 changed files with 68 additions and 53 deletions

View file

@ -38,13 +38,13 @@ static ssize_t name##_show(struct device *dev, \
{ \
struct ts_mmi_dev *touch_cdev = dev_get_drvdata(dev); \
int ret = 0; \
if (!touch_cdev || !touch_cdev->mdata->get_##name) { \
if (!touch_cdev) { \
dev_err(dev, "get_%s: invalid pointer\n", #name); \
return (ssize_t)0; \
} \
mutex_lock(&touch_cdev->extif_mutex); \
if (!chk_tp_status || is_touch_active) { \
ret = touch_cdev->mdata->get_##name(DEV_TS, &touch_cdev->name); \
TRY_TO_GET(name, &touch_cdev->name); \
if (ret < 0) { \
dev_err(dev, "get_%s: return error %d\n", #name, ret); \
ret = 0; \
@ -63,27 +63,29 @@ static ssize_t name##_store(struct device *dev, \
{ \
struct ts_mmi_dev *touch_cdev = dev_get_drvdata(dev); \
unsigned long value = 0; \
int err = 0; \
err = kstrtoul(buf, 0, &value); \
if (err < 0) { \
int ret = 0; \
ret = kstrtoul(buf, 0, &value); \
if (ret < 0) { \
dev_err(dev, "%s: Failed to convert value\n", #name); \
return -EINVAL; \
} \
if (!touch_cdev || !touch_cdev->mdata->name) { \
if (!touch_cdev) { \
dev_err(dev, "%s: invalid pointer\n", #name); \
return -EINVAL; \
} \
mutex_lock(&touch_cdev->extif_mutex); \
mutex_lock(&touch_cdev->method_mutex); \
touch_cdev->name = value; \
if (!chk_tp_status || is_touch_active) { \
err = touch_cdev->mdata->name(DEV_TS, touch_cdev->name); \
if (err < 0) { \
dev_err(dev, "%s: return error %d\n", #name, err); \
_TRY_TO_CALL(name, touch_cdev->name); \
if (ret < 0) { \
dev_err(dev, "%s: return error %d\n", #name, ret); \
goto TOUCH_MMI_STORE_OUT; \
} \
} else \
dev_dbg(dev, "%s: write to cache data.\n", #name); \
TOUCH_MMI_STORE_OUT: \
mutex_unlock(&touch_cdev->method_mutex); \
mutex_unlock(&touch_cdev->extif_mutex); \
return size; \
} \
@ -214,7 +216,7 @@ static ssize_t ts_mmi_doreflash_store(struct device *dev,
struct ts_mmi_dev *touch_cdev = dev_get_drvdata(dev);
char fw_path[TS_MMI_MAX_FW_PATH];
char template[TS_MMI_MAX_FW_PATH];
int err;
int ret = 0;
if (size > TS_MMI_MAX_FW_PATH) {
dev_err(dev, "%s: FW filename is too long\n", __func__);
@ -222,7 +224,7 @@ static ssize_t ts_mmi_doreflash_store(struct device *dev,
}
if (!touch_cdev->forcereflash) {
touch_cdev->mdata->get_vendor(DEV_TS, &touch_cdev->vendor);
TRY_TO_GET(vendor, &touch_cdev->vendor);
if (strncmp(buf, touch_cdev->vendor,
strnlen(touch_cdev->vendor, TS_MMI_MAX_VENDOR_LEN))) {
dev_err(dev,
@ -231,7 +233,7 @@ static ssize_t ts_mmi_doreflash_store(struct device *dev,
return -EINVAL;
}
touch_cdev->mdata->get_productinfo(DEV_TS, &touch_cdev->productinfo);
TRY_TO_GET(productinfo, &touch_cdev->productinfo);
snprintf(template, sizeof(template), "-%s-", touch_cdev->productinfo);
if (!strnstr(buf + strnlen(touch_cdev->vendor, TS_MMI_MAX_VENDOR_LEN),
template, size)) {
@ -243,19 +245,15 @@ static ssize_t ts_mmi_doreflash_store(struct device *dev,
strlcpy(fw_path, buf, size);
dev_dbg(dev, "%s: FW filename: %s\n", __func__, fw_path);
if (!touch_cdev->mdata->firmware_update) {
dev_err(dev,
"%s: firmware_update method not exist.\n", __func__);
return -EINVAL;
}
err = touch_cdev->mdata->firmware_update(DEV_TS, fw_path);
if (err < 0) {
dev_err(dev, "%s: firmware_update failed %d.\n", __func__, err);
TRY_TO_CALL(firmware_update, fw_path);
if (ret < 0) {
dev_err(dev, "%s: firmware_update failed %d.\n", __func__, ret);
return -EINVAL;
}
dev_info(dev, "%s: update fw from %s, return %d\n",
__func__, fw_path, err);
__func__, fw_path, ret);
return size;
}
@ -266,17 +264,17 @@ static ssize_t pwr_store(struct device *dev,
{
struct ts_mmi_dev *touch_cdev = dev_get_drvdata(dev);
unsigned long value = 0;
int err = 0;
err = kstrtoul(buf, 10, &value);
if (err < 0) {
int ret = 0;
ret = kstrtoul(buf, 10, &value);
if (ret < 0) {
dev_err(dev, "%s: Failed to convert value\n", __func__);
return -EINVAL;
}
if (!touch_cdev || !touch_cdev->mdata->power) {
if (!touch_cdev) {
dev_err(dev, "%s: invalid pointer\n", __func__);
return -EINVAL;
}
touch_cdev->mdata->power(DEV_TS, value);
TRY_TO_CALL(power, value);
return size;
}
static DEVICE_ATTR(pwr, (S_IWUSR | S_IWGRP), NULL, pwr_store);
@ -319,13 +317,13 @@ static ssize_t pill_region_show(struct device *dev,
struct ts_mmi_dev *touch_cdev = dev_get_drvdata(dev);
int ret = 0;
if (!touch_cdev || !touch_cdev->mdata->get_pill_region) {
if (!touch_cdev) {
dev_err(dev, "get_pill_region: invalid pointer\n");
return (ssize_t)0;
}
mutex_lock(&touch_cdev->extif_mutex);
if (is_touch_active) {
ret = touch_cdev->mdata->get_pill_region(DEV_TS, &touch_cdev->pill_region);
TRY_TO_GET(pill_region, &touch_cdev->pill_region);
if (ret < 0) {
dev_err(dev, "get_pill_region: return error %d\n", ret);
ret = 0;
@ -346,26 +344,28 @@ static ssize_t pill_region_store(struct device *dev,
{
struct ts_mmi_dev *touch_cdev = dev_get_drvdata(dev);
unsigned int args[TS_MMI_PILL_REGION_REQ_ARGS_NUM] = {0};
int err = 0;
int ret = 0;
int i = TS_MMI_PILL_REGION_REQ_ARGS_NUM;
err = sscanf(buf, "0x%x 0x%x 0x%x", &args[0], &args[1], &args[2]);
if (err < TS_MMI_PILL_REGION_REQ_ARGS_NUM) {
ret = sscanf(buf, "0x%x 0x%x 0x%x", &args[0], &args[1], &args[2]);
if (ret < TS_MMI_PILL_REGION_REQ_ARGS_NUM) {
dev_err(dev, "pill_region: Failed to convert value\n");
return -EINVAL;
}
if (!touch_cdev || !touch_cdev->mdata->pill_region) {
if (!touch_cdev) {
dev_err(dev, "pill_region: invalid pointer\n");
return -EINVAL;
}
mutex_lock(&touch_cdev->extif_mutex);
mutex_lock(&touch_cdev->method_mutex); \
while (i--)
touch_cdev->pill_region[i] = args[i];
if (is_touch_active)
touch_cdev->mdata->pill_region(DEV_TS, touch_cdev->pill_region);
_TRY_TO_CALL(pill_region, touch_cdev->pill_region);
else
dev_dbg(dev, "pill_region: write to cache data.\n");
mutex_unlock(&touch_cdev->method_mutex); \
mutex_unlock(&touch_cdev->extif_mutex);
return size;
}
@ -462,14 +462,12 @@ CREATE_SUPPRESSION_FAILED:
static int ts_mmi_get_vendor_info(
struct ts_mmi_dev *touch_cdev) {
struct ts_mmi_methods *mdata = touch_cdev->mdata;
int ret = 0;
TRY_TO_GET(productinfo, &touch_cdev->productinfo);
TRY_TO_GET(vendor, &touch_cdev->vendor);
TRY_TO_GET(bus_type, &touch_cdev->bus_type);
if (mdata->get_productinfo)
mdata->get_productinfo(DEV_TS, &touch_cdev->productinfo);
if (mdata->get_vendor)
mdata->get_vendor(DEV_TS, &touch_cdev->vendor);
if (mdata->get_bus_type)
mdata->get_bus_type(DEV_TS, &touch_cdev->bus_type);
return 0;
}
@ -519,6 +517,7 @@ int ts_mmi_dev_register(struct device *parent,
DEV_TS = parent;
touch_cdev->mdata = mdata;
mutex_init(&touch_cdev->extif_mutex);
mutex_init(&touch_cdev->method_mutex);
ret = ts_mmi_parse_dt(touch_cdev, DEV_TS->of_node);
if (ret < 0) {

View file

@ -59,6 +59,8 @@ enum ts_mmi_work {
#if defined(CONFIG_PANEL_NOTIFICATIONS)
static int ts_mmi_panel_off(struct ts_mmi_dev *touch_cdev) {
int ret = 0;
if (atomic_cmpxchg(&touch_cdev->touch_stopped, 0, 1) == 1)
return 0;
@ -103,6 +105,7 @@ static int ts_mmi_panel_cb(struct notifier_block *nb,
int idx = evd ? *(int *)evd : -1;
struct ts_mmi_dev *touch_cdev =
container_of(nb, struct ts_mmi_dev, panel_nb);
int ret = 0;
if (!touch_cdev)
return 0;
@ -128,14 +131,14 @@ static int ts_mmi_panel_cb(struct notifier_block *nb,
ts_mmi_panel_off(touch_cdev);
if (NEED_TO_SET_PINCTRL) {
dev_dbg(DEV_MMI, "%s: touch pinctrl off\n", __func__);
touch_cdev->mdata->pinctrl(DEV_TS, TS_MMI_PINCTL_OFF);
TRY_TO_CALL(pinctrl, TS_MMI_PINCTL_OFF);
}
break;
case PANEL_EVENT_DISPLAY_OFF:
if (NEED_TO_SET_POWER) {
/* then proceed with de-powering */
touch_cdev->mdata->power(DEV_TS, TS_MMI_POWER_OFF);
TRY_TO_CALL(power, TS_MMI_POWER_OFF);
dev_dbg(DEV_MMI, "%s: touch powered off\n", __func__);
}
break;
@ -143,7 +146,7 @@ static int ts_mmi_panel_cb(struct notifier_block *nb,
case PANEL_EVENT_PRE_DISPLAY_ON:
if (NEED_TO_SET_POWER) {
/* powering on early */
touch_cdev->mdata->power(DEV_TS, TS_MMI_POWER_ON);
TRY_TO_CALL(power, TS_MMI_POWER_ON);
dev_dbg(DEV_MMI, "%s: touch powered on\n", __func__);
} else if (touch_cdev->pdata.reset &&
touch_cdev->mdata->reset) {
@ -151,14 +154,14 @@ static int ts_mmi_panel_cb(struct notifier_block *nb,
* But need reset IC in resume.
*/
dev_dbg(DEV_MMI, "%s: resetting...\n", __func__);
touch_cdev->mdata->reset(DEV_TS, TS_MMI_RESET_HARD);
TRY_TO_CALL(reset, TS_MMI_RESET_HARD);
}
break;
case PANEL_EVENT_DISPLAY_ON:
/* out of reset to allow wait for boot complete */
if (NEED_TO_SET_PINCTRL) {
touch_cdev->mdata->pinctrl(DEV_TS, TS_MMI_PINCTL_ON);
TRY_TO_CALL(pinctrl, TS_MMI_PINCTL_ON);
dev_dbg(DEV_MMI, "%s: touch pinctrl_on\n", __func__);
}
ts_mmi_panel_on(touch_cdev);
@ -174,6 +177,8 @@ static int ts_mmi_panel_cb(struct notifier_block *nb,
static inline void ts_mmi_restore_settings(struct ts_mmi_dev *touch_cdev)
{
int ret = 0;
if (touch_cdev->pdata.usb_detection)
TRY_TO_CALL(charger_mode, (int)touch_cdev->ps_is_present);
if (touch_cdev->pdata.update_refresh_rate)
@ -193,6 +198,7 @@ static inline void ts_mmi_restore_settings(struct ts_mmi_dev *touch_cdev)
static void ts_mmi_queued_resume(struct ts_mmi_dev *touch_cdev)
{
bool wait4_boot_complete = true;
int ret = 0;
if (atomic_cmpxchg(&touch_cdev->touch_stopped, 1, 0) == 0)
return;
@ -243,13 +249,13 @@ static void ts_mmi_worker_func(struct work_struct *w)
container_of(w, struct delayed_work, work);
struct ts_mmi_dev *touch_cdev =
container_of(dw, struct ts_mmi_dev, work);
int rc, cmd = 0;
int ret, cmd = 0;
while (kfifo_get(&touch_cdev->cmd_pipe, &cmd)) {
switch (cmd) {
case TS_MMI_DO_RESUME:
rc = atomic_read(&touch_cdev->resume_should_stop);
if (rc) {
ret = atomic_read(&touch_cdev->resume_should_stop);
if (ret) {
dev_info(DEV_MMI, "%s: resume cancelled\n", __func__);
break;
}

View file

@ -176,6 +176,7 @@ struct ts_mmi_dev {
struct ts_mmi_dev_pdata pdata;
struct notifier_block panel_nb;
struct mutex extif_mutex;
struct mutex method_mutex;
atomic_t touch_stopped;
enum ts_mmi_pm_mode pm_mode;
@ -190,7 +191,6 @@ struct ts_mmi_dev {
struct work_struct ps_notify_work;
struct notifier_block ps_notif;
bool ps_is_present;
/*
* sys entey variable
*/
@ -224,17 +224,27 @@ struct ts_mmi_dev {
#define DEV_MMI (touch_cdev->class_dev)
#define DEV_TS (touch_cdev->dev)
#define MMI_DEV_TO_TS_DEV(cdev) (((struct ts_mmi_dev *)dev_get_drvdata(dev))->dev)
#define TRY_TO_CALL(_method, ...) \
/* call this after hold method mutex */
#define _TRY_TO_CALL(_method, ...) \
do { \
if (touch_cdev->mdata->_method) { \
touch_cdev->mdata->_method(DEV_TS, ##__VA_ARGS__); \
ret = touch_cdev->mdata->_method(DEV_TS, ##__VA_ARGS__); \
} \
} while (0)
#define TRY_TO_CALL(_method, ...) \
do { \
ret = ret; \
mutex_lock(&touch_cdev->method_mutex); \
_TRY_TO_CALL(_method, ##__VA_ARGS__); \
mutex_unlock(&touch_cdev->method_mutex); \
} while (0)
#define TRY_TO_GET(_method, ...) \
do { \
ret = ret; \
if (touch_cdev->mdata->_method) { \
if (touch_cdev->mdata->get_##_method) { \
mutex_lock(&touch_cdev->method_mutex); \
ret = touch_cdev->mdata->get_##_method(DEV_TS, ##__VA_ARGS__); \
mutex_unlock(&touch_cdev->method_mutex); \
} \
} while (0)
#define is_touch_stopped (atomic_read(&touch_cdev->touch_stopped) == 1)