summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun Yan <juyan@nvidia.com>2013-09-30 11:36:45 -0700
committerRiham Haidar <rhaidar@nvidia.com>2013-09-30 18:46:20 -0700
commit84f2500adc00a29415ac742ff2ccfa5514a03b96 (patch)
tree5c929584b5098cf09fdd8d8bccf293b5fc59500f
parentaa760d99fb5ebeab8661a6ced8fef7f85e65f411 (diff)
misc: issp: add lock for usb reset operation
usb reset operation should be in critical region. Add mutex lock to prevent two WARs resetting the USB together. Bug 1364476 Change-Id: I4c17a61a594cad496f5444e919cf101f8098da25 Signed-off-by: Jun Yan <juyan@nvidia.com> Reviewed-on: http://git-master/r/278072 Reviewed-by: Anshul Jain (SW) <anshulj@nvidia.com> Tested-by: Anshul Jain (SW) <anshulj@nvidia.com> Reviewed-on: http://git-master/r/279102 Reviewed-by: Automatic_Commit_Validation_User
-rw-r--r--drivers/misc/issp/issp.c14
-rw-r--r--drivers/misc/issp/issp_priv.h2
2 files changed, 14 insertions, 2 deletions
diff --git a/drivers/misc/issp/issp.c b/drivers/misc/issp/issp.c
index daa5b9a37355..dbe5110c890c 100644
--- a/drivers/misc/issp/issp.c
+++ b/drivers/misc/issp/issp.c
@@ -25,6 +25,7 @@
#include <linux/gpio.h>
#include <linux/wakelock.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include "issp_priv.h"
@@ -158,9 +159,11 @@ static void issp_recovery_work_func(struct work_struct *work)
for (i = 0; i < 1; i++) {
dev_info(&g_issp_host->pdev->dev,
"%s: recovery attempt #%d\n", __func__, i);
+ mutex_lock(&g_issp_host->issp_lock);
roth_usb_unload();
issp_uc_reset();
roth_usb_reload();
+ mutex_unlock(&g_issp_host->issp_lock);
msleep(500);
}
@@ -186,22 +189,28 @@ void issp_start_recovery_work(void)
static ssize_t issp_reset_set(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) {
- dev_info(dev, "resetting uC\n");
wake_lock(g_issp_wake_lock);
+ mutex_lock(&g_issp_host->issp_lock);
issp_uc_reset();
+ mutex_unlock(&g_issp_host->issp_lock);
wake_unlock(g_issp_wake_lock);
+ dev_info(&g_issp_host->pdev->dev,
+ "issp: toggling reset pin on uC!");
return count;
}
static ssize_t issp_usbreset_set(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count) {
- dev_info(dev, "resetting USB and uC\n");
wake_lock(g_issp_wake_lock);
+ mutex_lock(&g_issp_host->issp_lock);
roth_usb_unload();
issp_uc_reset();
roth_usb_reload();
+ mutex_unlock(&g_issp_host->issp_lock);
wake_unlock(g_issp_wake_lock);
+ dev_info(&g_issp_host->pdev->dev,
+ "issp: reset both usb and uC!");
return count;
}
@@ -327,6 +336,7 @@ static int __init issp_probe(struct platform_device *pdev)
dev_err(dev, "Firmware update failed!\n");
}
+ mutex_init(&host->issp_lock);
ret = device_create_file(dev, &dev_attr_issp_reset);
if (ret)
dev_err(dev, "ISSP sysfs node create failed\n");
diff --git a/drivers/misc/issp/issp_priv.h b/drivers/misc/issp/issp_priv.h
index f1988a429db8..55db7b9c280f 100644
--- a/drivers/misc/issp/issp_priv.h
+++ b/drivers/misc/issp/issp_priv.h
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/issp.h>
+#include <linux/mutex.h>
struct issp_host {
struct platform_device *pdev;
@@ -35,6 +36,7 @@ struct issp_host {
/* context to get fw data */
const struct ihex_binrec *cur_rec;
int cur_idx;
+ struct mutex issp_lock;
};
#define ISSP_FW_SECURITY_ADDR 0x00100000