From 09e12f9f6bcd9af516d901223cebdbae58b32c9f Mon Sep 17 00:00:00 2001
From: Kylene Jo Hall <kjhall@us.ibm.com>
Date: Sun, 13 Nov 2005 16:07:43 -0800
Subject: [PATCH] [PATCH] tpm: locking fix

Use schedule_work() to avoid down()-in-timer-handler problem.

Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 drivers/char/tpm/tpm.c | 9 +++++++++
 drivers/char/tpm/tpm.h | 1 +
 2 files changed, 10 insertions(+)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 1a53da99b58fc..0b283d246730b 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -43,6 +43,13 @@ static void user_reader_timeout(unsigned long ptr)
 {
 	struct tpm_chip *chip = (struct tpm_chip *) ptr;
 
+	schedule_work(&chip->work);
+}
+
+static void timeout_work(void * ptr)
+{
+	struct tpm_chip *chip = ptr;
+
 	down(&chip->buffer_mutex);
 	atomic_set(&chip->data_pending, 0);
 	memset(chip->data_buffer, 0, TPM_BUFSIZE);
@@ -527,6 +534,8 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
 	init_MUTEX(&chip->tpm_mutex);
 	INIT_LIST_HEAD(&chip->list);
 
+	INIT_WORK(&chip->work, timeout_work, chip);
+
 	init_timer(&chip->user_read_timer);
 	chip->user_read_timer.function = user_reader_timeout;
 	chip->user_read_timer.data = (unsigned long) chip;
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index ad51c6538034e..159882ca69dd0 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -77,6 +77,7 @@ struct tpm_chip {
 	struct semaphore buffer_mutex;
 
 	struct timer_list user_read_timer;	/* user needs to claim result */
+	struct work_struct work;
 	struct semaphore tpm_mutex;	/* tpm is processing */
 
 	struct tpm_vendor_specific *vendor;
-- 
GitLab