input: qcom-hv-haptics: move set_gain() operation into a work
In commit ba1e02b8f5b0("input: qcom-hv-haptics: poll HPWR_INTF status
after setting Vmax"), the mutex lock in haptics_play_info is used to
protect the data structure in haptics_set_gain(), and set_vmax() also
introduced a mutex lock and it's also called in haptics_set_gain().
However, haptics_set_gain() is running in an atomic context with
spinlock held and it shouldn't call any sleep function, hence, move the
set_gain() operation into to a work.
Fixes: ba1e02b8f5b0("input: qcom-hv-haptics: poll HPWR_INTF status after setting Vmax")
Change-Id: Ic2c95cb6dd6fc4646ac9038cdda0e311a3b71e62
Signed-off-by: xuanpeng <quic_xuanpeng@quicinc.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/atomic.h>
|
||||
@@ -557,6 +557,7 @@ struct haptics_play_info {
|
||||
struct brake_cfg *brake;
|
||||
struct fifo_play_status fifo_status;
|
||||
struct mutex lock;
|
||||
atomic_t gain;
|
||||
u32 vmax_mv;
|
||||
u32 length_us;
|
||||
enum pattern_src pattern_src;
|
||||
@@ -608,6 +609,7 @@ struct haptics_chip {
|
||||
struct hrtimer hbst_off_timer;
|
||||
struct notifier_block hboost_nb;
|
||||
struct mutex vmax_lock;
|
||||
struct work_struct set_gain_work;
|
||||
int fifo_empty_irq;
|
||||
u32 hpwr_voltage_mv;
|
||||
u32 effects_count;
|
||||
@@ -2778,22 +2780,17 @@ static int haptics_erase(struct input_dev *dev, int effect_id)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void haptics_set_gain(struct input_dev *dev, u16 gain)
|
||||
static void haptics_set_gain_work(struct work_struct *work)
|
||||
{
|
||||
struct haptics_chip *chip = input_get_drvdata(dev);
|
||||
struct haptics_chip *chip =
|
||||
container_of(work, struct haptics_chip, set_gain_work);
|
||||
struct haptics_hw_config *config = &chip->config;
|
||||
struct haptics_play_info *play = &chip->play;
|
||||
u32 vmax_mv, amplitude;
|
||||
|
||||
if (gain == 0)
|
||||
return;
|
||||
u16 gain;
|
||||
|
||||
mutex_lock(&play->lock);
|
||||
if (gain > 0x7fff)
|
||||
gain = 0x7fff;
|
||||
|
||||
dev_dbg(chip->dev, "Set gain: %#x\n", gain);
|
||||
|
||||
gain = atomic_read(&play->gain);
|
||||
/* scale amplitude when playing in DIRECT_PLAY mode */
|
||||
if (chip->play.pattern_src == DIRECT_PLAY) {
|
||||
amplitude = get_direct_play_max_amplitude(chip);
|
||||
@@ -2819,6 +2816,23 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain)
|
||||
mutex_unlock(&play->lock);
|
||||
}
|
||||
|
||||
static void haptics_set_gain(struct input_dev *dev, u16 gain)
|
||||
{
|
||||
struct haptics_chip *chip = input_get_drvdata(dev);
|
||||
struct haptics_play_info *play = &chip->play;
|
||||
|
||||
if (gain == 0)
|
||||
return;
|
||||
|
||||
if (gain > 0x7fff)
|
||||
gain = 0x7fff;
|
||||
|
||||
cancel_work_sync(&chip->set_gain_work);
|
||||
atomic_set(&play->gain, gain);
|
||||
schedule_work(&chip->set_gain_work);
|
||||
dev_dbg(chip->dev, "Set gain: %#x\n", gain);
|
||||
}
|
||||
|
||||
static int haptics_store_cl_brake_settings(struct haptics_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -5585,6 +5599,7 @@ static int haptics_probe(struct platform_device *pdev)
|
||||
hrtimer_init(&chip->hbst_off_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
chip->hbst_off_timer.function = haptics_disable_hbst_timer;
|
||||
INIT_DELAYED_WORK(&chip->stop_work, haptics_stop_constant_effect_play);
|
||||
INIT_WORK(&chip->set_gain_work, haptics_set_gain_work);
|
||||
|
||||
atomic_set(&chip->play.fifo_status.is_busy, 0);
|
||||
atomic_set(&chip->play.fifo_status.written_done, 0);
|
||||
|
||||
Reference in New Issue
Block a user