diff options
| author | Eric Tashakkor <w36098@motorola.com> | 2014-05-21 08:38:12 -0500 |
|---|---|---|
| committer | ERIC TASHAKKOR <w36098@motorola.com> | 2014-05-27 14:22:57 +0000 |
| commit | 024080a8aa7765f08d836d0322d80708361875d3 (patch) | |
| tree | 0ddf8d5785e3d21aed6253445ce20328802d869c /drivers/mfd/m4sensorhub-panic.c | |
| parent | 80eb3fbe8d147db15182cebbb937486945900be9 (diff) | |
| download | olio-linux-3.10-024080a8aa7765f08d836d0322d80708361875d3.tar.xz olio-linux-3.10-024080a8aa7765f08d836d0322d80708361875d3.zip | |
IKXCLOCK-1349 Fix Kernel Panics in M4 Core
Fixed several panics caused by missing NULL checks in exported core functions
(e.g., M4 fails to init but an outside process calls the sysfs interface)
Fixed/added error messages to check for bad conditions earlier
Fixed a bug in m4sensorhub-irq where IRQ book-keeping was not being done
Added missing callback string to m4sensorhub-panic.c
Change-Id: I82a8602f2327bf63982caa23af103c48a01bbcc1
Signed-off-by: Eric Tashakkor <w36098@motorola.com>
Diffstat (limited to 'drivers/mfd/m4sensorhub-panic.c')
| -rw-r--r-- | drivers/mfd/m4sensorhub-panic.c | 153 |
1 files changed, 108 insertions, 45 deletions
diff --git a/drivers/mfd/m4sensorhub-panic.c b/drivers/mfd/m4sensorhub-panic.c index f1cc373b12f..725c2ff80c0 100644 --- a/drivers/mfd/m4sensorhub-panic.c +++ b/drivers/mfd/m4sensorhub-panic.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Motorola, Inc. + * Copyright (C) 2012-2014 Motorola, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,7 +23,6 @@ #include <linux/slab.h> - /* --------------- Global Declarations -------------- */ #define PANIC_BANK 0xFF /* Reserved for Panic bank */ #define PANIC_CMD_CHECK 0xCD /* Panic Handoff command */ @@ -33,6 +32,7 @@ /* --------------- Local Declarations -------------- */ static const char *callback_name[PANICHDL_MAX] = { + [PANICHDL_DISPLAY_RESTORE] = "display_restore", [PANICHDL_IRQ_RESTORE] = "irq_restore", }; @@ -71,14 +71,32 @@ int m4sensorhub_panic_init(struct m4sensorhub_data *m4sensorhub) int retval = 0; struct m4sensorhub_panicdata *data; + if (m4sensorhub == NULL) { + KDEBUG(M4SH_ERROR, "%s: M4 data is NULL\n", __func__); + retval = -ENODATA; + goto m4sensorhub_panic_init_fail; + } + + if (m4sensorhub->panicdata != NULL) { + KDEBUG(M4SH_ERROR, + "%s: Trying to overwrite previous panic data\n", + __func__); + retval = -EPERM; + goto m4sensorhub_panic_init_fail; + } + data = kzalloc(sizeof(struct m4sensorhub_panicdata), GFP_KERNEL); - if (data) { - mutex_init(&data->lock); - m4sensorhub->panicdata = data; - } else { - KDEBUG(M4SH_ERROR, "m4sensorhub: Memory error in panic_init\n"); + if (data == NULL) { + KDEBUG(M4SH_ERROR, "%s: Memory error in panic_init\n", + __func__); retval = -ENOMEM; + goto m4sensorhub_panic_init_fail; } + + mutex_init(&data->lock); + m4sensorhub->panicdata = data; + +m4sensorhub_panic_init_fail: return retval; } EXPORT_SYMBOL_GPL(m4sensorhub_panic_init); @@ -91,54 +109,86 @@ EXPORT_SYMBOL_GPL(m4sensorhub_panic_init); */ void m4sensorhub_panic_shutdown(struct m4sensorhub_data *m4sensorhub) { - if (m4sensorhub && m4sensorhub->panicdata) { - struct m4sensorhub_panicdata *data = m4sensorhub->panicdata; + struct m4sensorhub_panicdata *data = NULL; + + if (m4sensorhub == NULL) { + KDEBUG(M4SH_ERROR, "%s: M4 data is NULL\n", __func__); + return; + } + + data = m4sensorhub->panicdata; + if (data != NULL) { m4sensorhub->panicdata = NULL; if (mutex_is_locked(&data->lock)) mutex_unlock(&data->lock); mutex_destroy(&data->lock); + /* + * Callback and data pointers were passed to us, so + * we leave it to the registering functions to + * clean up their own memory. + */ kfree(data); } + + return; } EXPORT_SYMBOL_GPL(m4sensorhub_panic_shutdown); /* m4sensorhub_panic_register() - Register an panic handler to monitor M4 panic reset + Register a panic handler to monitor M4 panic reset Returns 0 on success or negative error code on failure m4sensorhub - pointer to the main m4sensorhub data struct - index - M4 Sensor Hub panic handler to resiter for + index - M4 Sensor Hub panic handler to register for cb_func - panic handler function to execute after M4 reset data - pointer to data for panic handler function */ - int m4sensorhub_panic_register(struct m4sensorhub_data *m4sensorhub, enum m4sensorhub_panichdl_index index, void (*cb_func) (struct m4sensorhub_data *, void *), void *data) { - struct m4sensorhub_panicdata *panicdata; + struct m4sensorhub_panicdata *panicdata = NULL; int retval = 0; - if (!m4sensorhub || (index >= PANICHDL_MAX) || !cb_func) - return -EINVAL; + if (m4sensorhub == NULL) { + KDEBUG(M4SH_ERROR, "%s: M4 data is NULL\n", __func__); + retval = -ENODATA; + goto m4sensorhub_panic_register_exit; + } else if (cb_func == NULL) { + KDEBUG(M4SH_ERROR, "%s: Callback is NULL\n", __func__); + retval = -ENOSYS; + goto m4sensorhub_panic_register_exit; + } else if (index >= PANICHDL_MAX) { + KDEBUG(M4SH_ERROR, "%s: Number of panic handlers exceeded\n", + __func__); + retval = -EOVERFLOW; + goto m4sensorhub_panic_register_exit; + } else if (m4sensorhub->panicdata == NULL) { + KDEBUG(M4SH_ERROR, "%s: Panic data is missing\n", __func__); + retval = -ENODATA; + goto m4sensorhub_panic_register_exit; + } panicdata = (struct m4sensorhub_panicdata *)m4sensorhub->panicdata; mutex_lock(&panicdata->lock); if (panicdata->funcs[index].callback == NULL) { panicdata->funcs[index].callback = cb_func; panicdata->funcs[index].data = data; - KDEBUG(M4SH_NOTICE, "m4sensorhub: %s callback registered\n", - callback_name[index]); + KDEBUG(M4SH_NOTICE, "%s: %s callback registered\n", + __func__, callback_name[index]); } else { - KDEBUG(M4SH_ERROR, "m4sensorhub: %s callback"\ - " registration failed\n", callback_name[index]); + KDEBUG(M4SH_ERROR, "%s: %s %s", __func__, + callback_name[index], "callback registration failed\n"); retval = -EPERM; + goto m4sensorhub_panic_register_fail; } - mutex_unlock(&panicdata->lock); +m4sensorhub_panic_register_fail: + mutex_unlock(&panicdata->lock); +m4sensorhub_panic_register_exit: return retval; } EXPORT_SYMBOL_GPL(m4sensorhub_panic_register); @@ -155,20 +205,34 @@ EXPORT_SYMBOL_GPL(m4sensorhub_panic_register); int m4sensorhub_panic_unregister(struct m4sensorhub_data *m4sensorhub, enum m4sensorhub_panichdl_index index) { - struct m4sensorhub_panicdata *panicdata; + int retval = 0; + struct m4sensorhub_panicdata *panicdata = NULL; - if (!m4sensorhub || (index >= PANICHDL_MAX)) - return -EINVAL; + if (m4sensorhub == NULL) { + KDEBUG(M4SH_ERROR, "%s: M4 data is NULL\n", __func__); + retval = -ENODATA; + goto m4sensorhub_panic_unregister_fail; + } else if (index >= PANICHDL_MAX) { + KDEBUG(M4SH_ERROR, "%s: Number of panic handlers exceeded\n", + __func__); + retval = -EOVERFLOW; + goto m4sensorhub_panic_unregister_fail; + } else if (m4sensorhub->panicdata == NULL) { + KDEBUG(M4SH_ERROR, "%s: Panic data is missing\n", __func__); + retval = -ENODATA; + goto m4sensorhub_panic_unregister_fail; + } panicdata = (struct m4sensorhub_panicdata *)m4sensorhub->panicdata; mutex_lock(&panicdata->lock); panicdata->funcs[index].callback = NULL; panicdata->funcs[index].data = NULL; mutex_unlock(&panicdata->lock); - KDEBUG(M4SH_NOTICE, "m4sensorhub: %s callback un-registered\n", - callback_name[index]); + KDEBUG(M4SH_NOTICE, "%s: %s callback un-registered\n", + __func__, callback_name[index]); - return 0; +m4sensorhub_panic_unregister_fail: + return retval; } EXPORT_SYMBOL_GPL(m4sensorhub_panic_unregister); @@ -201,9 +265,11 @@ void m4sensorhub_panic_process(struct m4sensorhub_data *m4sensorhub) union panic_buf buf; struct m4sensorhub_panic_callback handler; - if (!m4sensorhub || !m4sensorhub->panicdata) { - KDEBUG(M4SH_ERROR, "m4sensorhub: Invalid parameter in %s!\n",\ - __func__); + if (m4sensorhub == NULL) { + KDEBUG(M4SH_ERROR, "%s: M4 data is NULL\n", __func__); + return; + } else if (m4sensorhub->panicdata == NULL) { + KDEBUG(M4SH_ERROR, "%s: Panic data is missing\n", __func__); return; } @@ -211,41 +277,38 @@ void m4sensorhub_panic_process(struct m4sensorhub_data *m4sensorhub) buf.in.bank = PANIC_BANK; buf.in.cmd = PANIC_CMD_CHECK; - ret = m4sensorhub_i2c_write_read(m4sensorhub,\ - (u8 *)&buf, sizeof(buf.in), sizeof(buf.data)); + ret = m4sensorhub_i2c_write_read(m4sensorhub, + (u8 *)&buf, sizeof(buf.in), sizeof(buf.data)); if ((ret != sizeof(buf.data)) || (buf.data != PANIC_RESP_CHECK)) { /* TODO maybe we shall check if M4/OMAP i2c broken */ - KDEBUG(M4SH_ERROR, "m4sensorhub: Unknown IRQ status! "\ - "M4 panic handoff ret=%d, data=0x%x\n",\ - ret, buf.data); + KDEBUG(M4SH_ERROR, "m4sensorhub: %s ret=%d, data=0x%x\n", + "Unknown IRQ status! M4 panic handoff", ret, buf.data); m4sensorhub_reg_access_unlock(); return; } - KDEBUG(M4SH_ERROR, "m4sensorhub_panic: Detected M4 panic, reset M4!\n"); + KDEBUG(M4SH_ERROR, "%s: Detected M4 panic, reset M4!\n", __func__); m4sensorhub->pdev->hw_reset(m4sensorhub); msleep(100); - if (m4sensorhub->i2c_client->addr == 0x39) { + if (m4sensorhub->i2c_client->addr == 0x39) ret = m4sensorhub_401_load_firmware(m4sensorhub, 0, NULL); - } else { + else ret = m4sensorhub_load_firmware(m4sensorhub, 0, NULL); - } if (ret < 0) { - KDEBUG(M4SH_ERROR, "m4sensorhub_panic: "\ - "Failed to restart M4, ret = %d\n", ret); + KDEBUG(M4SH_ERROR, "%s: Failed to restart M4, ret = %d\n", + __func__, ret); BUG(); } m4sensorhub_reg_access_unlock(); for (i = 0; i < PANICHDL_MAX; i++) { - handler = ((struct m4sensorhub_panicdata *)\ - (m4sensorhub->panicdata))->funcs[i]; + handler = ((struct m4sensorhub_panicdata *) + (m4sensorhub->panicdata))->funcs[i]; if (handler.callback) { - KDEBUG(M4SH_NOTICE, "m4sensorhub_panic: "\ - "Calling %s as M4 restarted!\n",\ - callback_name[i]); + KDEBUG(M4SH_NOTICE, "%s: Calling %s as M4 restarted!\n", + __func__, callback_name[i]); handler.callback(m4sensorhub, handler.data); } } |