Skip to content

Commit

Permalink
Input: synaptics-rmi4 - fix error handling in I2C transport driver
Browse files Browse the repository at this point in the history
Instantiating the rmi4 I2C transport driver without interrupts assigned
(for example using manual i2c instantiation from the command line)
caused the driver to fail to load, but it does not clean up its regulator
or transport device registrations. Result is a crash at a later time,
for example when rebooting the system.

Fixes: 946c843 ("Input: synaptics-rmi4 - support regulator supplies")
Cc: Bjorn Andersson <[email protected]>
Signed-off-by: Guenter Roeck <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
  • Loading branch information
groeck authored and dtor committed Oct 4, 2016
1 parent bbc2cee commit 261d779
Showing 1 changed file with 26 additions and 12 deletions.
38 changes: 26 additions & 12 deletions drivers/input/rmi4/rmi_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,21 @@ static const struct of_device_id rmi_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, rmi_i2c_of_match);
#endif

static void rmi_i2c_regulator_bulk_disable(void *data)
{
struct rmi_i2c_xport *rmi_i2c = data;

regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies),
rmi_i2c->supplies);
}

static void rmi_i2c_unregister_transport(void *data)
{
struct rmi_i2c_xport *rmi_i2c = data;

rmi_unregister_transport_device(&rmi_i2c->xport);
}

static int rmi_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
Expand Down Expand Up @@ -264,6 +279,12 @@ static int rmi_i2c_probe(struct i2c_client *client,
if (retval < 0)
return retval;

retval = devm_add_action_or_reset(&client->dev,
rmi_i2c_regulator_bulk_disable,
rmi_i2c);
if (retval)
return retval;

of_property_read_u32(client->dev.of_node, "syna,startup-delay-ms",
&rmi_i2c->startup_delay);

Expand Down Expand Up @@ -294,6 +315,11 @@ static int rmi_i2c_probe(struct i2c_client *client,
client->addr);
return retval;
}
retval = devm_add_action_or_reset(&client->dev,
rmi_i2c_unregister_transport,
rmi_i2c);
if (retval)
return retval;

retval = rmi_i2c_init_irq(client);
if (retval < 0)
Expand All @@ -304,17 +330,6 @@ static int rmi_i2c_probe(struct i2c_client *client,
return 0;
}

static int rmi_i2c_remove(struct i2c_client *client)
{
struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client);

rmi_unregister_transport_device(&rmi_i2c->xport);
regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies),
rmi_i2c->supplies);

return 0;
}

#ifdef CONFIG_PM_SLEEP
static int rmi_i2c_suspend(struct device *dev)
{
Expand Down Expand Up @@ -431,7 +446,6 @@ static struct i2c_driver rmi_i2c_driver = {
},
.id_table = rmi_id,
.probe = rmi_i2c_probe,
.remove = rmi_i2c_remove,
};

module_i2c_driver(rmi_i2c_driver);
Expand Down

0 comments on commit 261d779

Please sign in to comment.