aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/chrome/chromeos_laptop.c
diff options
context:
space:
mode:
authorBenson Leung <bleung@chromium.org>2014-07-15 20:43:11 -0400
committerOlof Johansson <olof@lixom.net>2014-07-15 21:02:01 -0400
commit5502486a2077e4280c618b82e8a77ed35932956f (patch)
treeda09e9c88c6b6f716c01cd72e457912a9aec20f6 /drivers/platform/chrome/chromeos_laptop.c
parentb90b3c4ae06af135e279c9a5aa1c640d22787fc4 (diff)
platform/chrome: chromeos_laptop - Add a limit for deferred retries
Limit the number of times we allow deferred probing to attempt to add i2c devices. This will help with some device flakiness at probe time. For example, some touchpads and touchscreens may be in transition between bootloader and operational mode and may appear at neither address briefly. Adapters, however, have no limit as it depends on when the i2c adapter driver module is loaded. The module may even be loaded manually by the user using modprobe or insmod. By default, set MAX_I2C_DEVICE_DEFERALS to 5. Based on this patch from the chromeos-kernel : https://chromium-review.googlesource.com/168130 Signed-off-by: Benson Leung <bleung@chromium.org> Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/platform/chrome/chromeos_laptop.c')
-rw-r--r--drivers/platform/chrome/chromeos_laptop.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
index 15b1b162890f..6ed6375fe6bf 100644
--- a/drivers/platform/chrome/chromeos_laptop.c
+++ b/drivers/platform/chrome/chromeos_laptop.c
@@ -37,6 +37,8 @@
37#define ISL_ALS_I2C_ADDR 0x44 37#define ISL_ALS_I2C_ADDR 0x44
38#define TAOS_ALS_I2C_ADDR 0x29 38#define TAOS_ALS_I2C_ADDR 0x29
39 39
40#define MAX_I2C_DEVICE_DEFERRALS 5
41
40static struct i2c_client *als; 42static struct i2c_client *als;
41static struct i2c_client *tp; 43static struct i2c_client *tp;
42static struct i2c_client *ts; 44static struct i2c_client *ts;
@@ -58,9 +60,17 @@ enum i2c_adapter_type {
58 I2C_ADAPTER_DESIGNWARE_1, 60 I2C_ADAPTER_DESIGNWARE_1,
59}; 61};
60 62
63enum i2c_peripheral_state {
64 UNPROBED = 0,
65 PROBED,
66 TIMEDOUT,
67};
68
61struct i2c_peripheral { 69struct i2c_peripheral {
62 int (*add)(enum i2c_adapter_type type); 70 int (*add)(enum i2c_adapter_type type);
63 enum i2c_adapter_type type; 71 enum i2c_adapter_type type;
72 enum i2c_peripheral_state state;
73 int tries;
64}; 74};
65 75
66#define MAX_I2C_PERIPHERALS 3 76#define MAX_I2C_PERIPHERALS 3
@@ -166,8 +176,8 @@ static struct i2c_client *__add_probed_i2c_device(
166 /* add the i2c device */ 176 /* add the i2c device */
167 client = i2c_new_probed_device(adapter, info, addrs, NULL); 177 client = i2c_new_probed_device(adapter, info, addrs, NULL);
168 if (!client) 178 if (!client)
169 pr_err("%s failed to register device %d-%02x\n", 179 pr_notice("%s failed to register device %d-%02x\n",
170 __func__, bus, info->addr); 180 __func__, bus, info->addr);
171 else 181 else
172 pr_debug("%s added i2c device %d-%02x\n", 182 pr_debug("%s added i2c device %d-%02x\n",
173 __func__, bus, info->addr); 183 __func__, bus, info->addr);
@@ -347,9 +357,36 @@ static int chromeos_laptop_probe(struct platform_device *pdev)
347 if (i2c_dev->add == NULL) 357 if (i2c_dev->add == NULL)
348 break; 358 break;
349 359
350 /* Add the device. Set -EPROBE_DEFER on any failure */ 360 if (i2c_dev->state == TIMEDOUT || i2c_dev->state == PROBED)
351 if (i2c_dev->add(i2c_dev->type)) 361 continue;
362
363 /*
364 * Check that the i2c adapter is present.
365 * -EPROBE_DEFER if missing as the adapter may appear much
366 * later.
367 */
368 if (find_i2c_adapter_num(i2c_dev->type) == -ENODEV) {
352 ret = -EPROBE_DEFER; 369 ret = -EPROBE_DEFER;
370 continue;
371 }
372
373 /* Add the device. */
374 if (i2c_dev->add(i2c_dev->type) == -EAGAIN) {
375 /*
376 * Set -EPROBE_DEFER a limited num of times
377 * if device is not successfully added.
378 */
379 if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) {
380 ret = -EPROBE_DEFER;
381 } else {
382 /* Ran out of tries. */
383 pr_notice("%s: Ran out of tries for device.\n",
384 __func__);
385 i2c_dev->state = TIMEDOUT;
386 }
387 } else {
388 i2c_dev->state = PROBED;
389 }
353 } 390 }
354 391
355 return ret; 392 return ret;