mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-20 16:30:53 +00:00
Input: eeti_ts - cancel pending work when going to suspend
This fixes a race between the suspend code and input events. Signed-off-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
parent
5f57d67da8
commit
7fbef0d1e2
@ -123,14 +123,25 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eeti_ts_open(struct input_dev *dev)
|
static void eeti_ts_start(struct eeti_ts_priv *priv)
|
||||||
{
|
{
|
||||||
struct eeti_ts_priv *priv = input_get_drvdata(dev);
|
|
||||||
|
|
||||||
enable_irq(priv->irq);
|
enable_irq(priv->irq);
|
||||||
|
|
||||||
/* Read the events once to arm the IRQ */
|
/* Read the events once to arm the IRQ */
|
||||||
eeti_ts_read(&priv->work);
|
eeti_ts_read(&priv->work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eeti_ts_stop(struct eeti_ts_priv *priv)
|
||||||
|
{
|
||||||
|
disable_irq(priv->irq);
|
||||||
|
cancel_work_sync(&priv->work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int eeti_ts_open(struct input_dev *dev)
|
||||||
|
{
|
||||||
|
struct eeti_ts_priv *priv = input_get_drvdata(dev);
|
||||||
|
|
||||||
|
eeti_ts_start(priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -139,8 +150,7 @@ static void eeti_ts_close(struct input_dev *dev)
|
|||||||
{
|
{
|
||||||
struct eeti_ts_priv *priv = input_get_drvdata(dev);
|
struct eeti_ts_priv *priv = input_get_drvdata(dev);
|
||||||
|
|
||||||
disable_irq(priv->irq);
|
eeti_ts_stop(priv);
|
||||||
cancel_work_sync(&priv->work);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit eeti_ts_probe(struct i2c_client *client,
|
static int __devinit eeti_ts_probe(struct i2c_client *client,
|
||||||
@ -152,10 +162,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,
|
|||||||
unsigned int irq_flags;
|
unsigned int irq_flags;
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
|
|
||||||
/* In contrast to what's described in the datasheet, there seems
|
/*
|
||||||
|
* In contrast to what's described in the datasheet, there seems
|
||||||
* to be no way of probing the presence of that device using I2C
|
* to be no way of probing the presence of that device using I2C
|
||||||
* commands. So we need to blindly believe it is there, and wait
|
* commands. So we need to blindly believe it is there, and wait
|
||||||
* for interrupts to occur. */
|
* for interrupts to occur.
|
||||||
|
*/
|
||||||
|
|
||||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
if (!priv) {
|
if (!priv) {
|
||||||
@ -211,9 +223,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable the irq for now. It will be enabled once the input device
|
/*
|
||||||
* is opened. */
|
* Disable the device for now. It will be enabled once the
|
||||||
disable_irq(priv->irq);
|
* input device is opened.
|
||||||
|
*/
|
||||||
|
eeti_ts_stop(priv);
|
||||||
|
|
||||||
device_init_wakeup(&client->dev, 0);
|
device_init_wakeup(&client->dev, 0);
|
||||||
return 0;
|
return 0;
|
||||||
@ -234,6 +248,12 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)
|
|||||||
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
|
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
|
||||||
|
|
||||||
free_irq(priv->irq, priv);
|
free_irq(priv->irq, priv);
|
||||||
|
/*
|
||||||
|
* eeti_ts_stop() leaves IRQ disabled. We need to re-enable it
|
||||||
|
* so that device still works if we reload the driver.
|
||||||
|
*/
|
||||||
|
enable_irq(priv->irq);
|
||||||
|
|
||||||
input_unregister_device(priv->input);
|
input_unregister_device(priv->input);
|
||||||
i2c_set_clientdata(client, NULL);
|
i2c_set_clientdata(client, NULL);
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
@ -245,6 +265,14 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)
|
|||||||
static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)
|
static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)
|
||||||
{
|
{
|
||||||
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
|
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
|
||||||
|
struct input_dev *input_dev = priv->input;
|
||||||
|
|
||||||
|
mutex_lock(&input_dev->mutex);
|
||||||
|
|
||||||
|
if (input_dev->users)
|
||||||
|
eeti_ts_stop(priv);
|
||||||
|
|
||||||
|
mutex_unlock(&input_dev->mutex);
|
||||||
|
|
||||||
if (device_may_wakeup(&client->dev))
|
if (device_may_wakeup(&client->dev))
|
||||||
enable_irq_wake(priv->irq);
|
enable_irq_wake(priv->irq);
|
||||||
@ -255,10 +283,18 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)
|
|||||||
static int eeti_ts_resume(struct i2c_client *client)
|
static int eeti_ts_resume(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
|
struct eeti_ts_priv *priv = i2c_get_clientdata(client);
|
||||||
|
struct input_dev *input_dev = priv->input;
|
||||||
|
|
||||||
if (device_may_wakeup(&client->dev))
|
if (device_may_wakeup(&client->dev))
|
||||||
disable_irq_wake(priv->irq);
|
disable_irq_wake(priv->irq);
|
||||||
|
|
||||||
|
mutex_lock(&input_dev->mutex);
|
||||||
|
|
||||||
|
if (input_dev->users)
|
||||||
|
eeti_ts_start(priv);
|
||||||
|
|
||||||
|
mutex_unlock(&input_dev->mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
Loading…
Reference in New Issue
Block a user