summaryrefslogtreecommitdiff
path: root/drivers/mfd/m4sensorhub-panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/m4sensorhub-panic.c')
-rw-r--r--drivers/mfd/m4sensorhub-panic.c153
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);
}
}