aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2016-10-04 14:50:54 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2016-10-04 14:52:24 -0400
commit261d7794c49b9a3bb5115c5ffc452e00f969bf43 (patch)
tree936e7c8905f38587bc5190c5fb3711f896623aca /drivers/input
parentbbc2ceeb3220e54c7574f0b5e3a252fd9a62cf8a (diff)
Input: synaptics-rmi4 - fix error handling in I2C transport driver
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: 946c8432aab0 ("Input: synaptics-rmi4 - support regulator supplies") Cc: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/rmi4/rmi_i2c.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c
index 6f2e0e4f0296..1ebc2c1debae 100644
--- a/drivers/input/rmi4/rmi_i2c.c
+++ b/drivers/input/rmi4/rmi_i2c.c
@@ -221,6 +221,21 @@ static const struct of_device_id rmi_i2c_of_match[] = {
221MODULE_DEVICE_TABLE(of, rmi_i2c_of_match); 221MODULE_DEVICE_TABLE(of, rmi_i2c_of_match);
222#endif 222#endif
223 223
224static void rmi_i2c_regulator_bulk_disable(void *data)
225{
226 struct rmi_i2c_xport *rmi_i2c = data;
227
228 regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies),
229 rmi_i2c->supplies);
230}
231
232static void rmi_i2c_unregister_transport(void *data)
233{
234 struct rmi_i2c_xport *rmi_i2c = data;
235
236 rmi_unregister_transport_device(&rmi_i2c->xport);
237}
238
224static int rmi_i2c_probe(struct i2c_client *client, 239static int rmi_i2c_probe(struct i2c_client *client,
225 const struct i2c_device_id *id) 240 const struct i2c_device_id *id)
226{ 241{
@@ -264,6 +279,12 @@ static int rmi_i2c_probe(struct i2c_client *client,
264 if (retval < 0) 279 if (retval < 0)
265 return retval; 280 return retval;
266 281
282 retval = devm_add_action_or_reset(&client->dev,
283 rmi_i2c_regulator_bulk_disable,
284 rmi_i2c);
285 if (retval)
286 return retval;
287
267 of_property_read_u32(client->dev.of_node, "syna,startup-delay-ms", 288 of_property_read_u32(client->dev.of_node, "syna,startup-delay-ms",
268 &rmi_i2c->startup_delay); 289 &rmi_i2c->startup_delay);
269 290
@@ -294,6 +315,11 @@ static int rmi_i2c_probe(struct i2c_client *client,
294 client->addr); 315 client->addr);
295 return retval; 316 return retval;
296 } 317 }
318 retval = devm_add_action_or_reset(&client->dev,
319 rmi_i2c_unregister_transport,
320 rmi_i2c);
321 if (retval)
322 return retval;
297 323
298 retval = rmi_i2c_init_irq(client); 324 retval = rmi_i2c_init_irq(client);
299 if (retval < 0) 325 if (retval < 0)
@@ -304,17 +330,6 @@ static int rmi_i2c_probe(struct i2c_client *client,
304 return 0; 330 return 0;
305} 331}
306 332
307static int rmi_i2c_remove(struct i2c_client *client)
308{
309 struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client);
310
311 rmi_unregister_transport_device(&rmi_i2c->xport);
312 regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies),
313 rmi_i2c->supplies);
314
315 return 0;
316}
317
318#ifdef CONFIG_PM_SLEEP 333#ifdef CONFIG_PM_SLEEP
319static int rmi_i2c_suspend(struct device *dev) 334static int rmi_i2c_suspend(struct device *dev)
320{ 335{
@@ -431,7 +446,6 @@ static struct i2c_driver rmi_i2c_driver = {
431 }, 446 },
432 .id_table = rmi_id, 447 .id_table = rmi_id,
433 .probe = rmi_i2c_probe, 448 .probe = rmi_i2c_probe,
434 .remove = rmi_i2c_remove,
435}; 449};
436 450
437module_i2c_driver(rmi_i2c_driver); 451module_i2c_driver(rmi_i2c_driver);