diff options
| author | Nishanth Aravamudan <nacc@us.ibm.com> | 2005-06-24 01:01:47 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:05:24 -0400 |
| commit | 700d8bdcd0fa815b08638b1e4d43b66d60cc6a8d (patch) | |
| tree | c3defbf1cb77b9290a002cff04e1b2f054dfcb05 | |
| parent | 6a94f9209762a6eb286f668e1346ad87985cc765 (diff) | |
[PATCH] char/tpm: use msleep(), clean-up timers,
The TPM driver unnecessarily uses timers when it simply needs to maintain a
maximum delay via time_before(). msleep() is used instead of
schedule_timeout() to guarantee the task delays as expected. While
compile-testing, I found a typo in the driver, using tpm_chp instead of
tpm_chip. Remove the now unused timer callback function and change
TPM_TIMEOUT's units to milliseconds. Patch is compile-tested.
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Acked-by: Kylene Hall <kjhall@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | drivers/char/tpm/tpm.c | 35 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm.h | 3 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_nsc.c | 32 |
3 files changed, 18 insertions, 52 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 8ce508b29865..c937ea2bcdbc 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | * | 19 | * |
| 20 | * Note, the TPM chip is not interrupt driven (only polling) | 20 | * Note, the TPM chip is not interrupt driven (only polling) |
| 21 | * and can have very long timeouts (minutes!). Hence the unusual | 21 | * and can have very long timeouts (minutes!). Hence the unusual |
| 22 | * calls to schedule_timeout. | 22 | * calls to msleep. |
| 23 | * | 23 | * |
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| @@ -52,14 +52,6 @@ static void user_reader_timeout(unsigned long ptr) | |||
| 52 | up(&chip->buffer_mutex); | 52 | up(&chip->buffer_mutex); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | void tpm_time_expired(unsigned long ptr) | ||
| 56 | { | ||
| 57 | int *exp = (int *) ptr; | ||
| 58 | *exp = 1; | ||
| 59 | } | ||
| 60 | |||
| 61 | EXPORT_SYMBOL_GPL(tpm_time_expired); | ||
| 62 | |||
| 63 | /* | 55 | /* |
| 64 | * Initialize the LPC bus and enable the TPM ports | 56 | * Initialize the LPC bus and enable the TPM ports |
| 65 | */ | 57 | */ |
| @@ -135,6 +127,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
| 135 | ssize_t len; | 127 | ssize_t len; |
| 136 | u32 count; | 128 | u32 count; |
| 137 | __be32 *native_size; | 129 | __be32 *native_size; |
| 130 | unsigned long stop; | ||
| 138 | 131 | ||
| 139 | native_size = (__force __be32 *) (buf + 2); | 132 | native_size = (__force __be32 *) (buf + 2); |
| 140 | count = be32_to_cpu(*native_size); | 133 | count = be32_to_cpu(*native_size); |
| @@ -155,28 +148,16 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
| 155 | return len; | 148 | return len; |
| 156 | } | 149 | } |
| 157 | 150 | ||
| 158 | down(&chip->timer_manipulation_mutex); | 151 | stop = jiffies + 2 * 60 * HZ; |
| 159 | chip->time_expired = 0; | ||
| 160 | init_timer(&chip->device_timer); | ||
| 161 | chip->device_timer.function = tpm_time_expired; | ||
| 162 | chip->device_timer.expires = jiffies + 2 * 60 * HZ; | ||
| 163 | chip->device_timer.data = (unsigned long) &chip->time_expired; | ||
| 164 | add_timer(&chip->device_timer); | ||
| 165 | up(&chip->timer_manipulation_mutex); | ||
| 166 | |||
| 167 | do { | 152 | do { |
| 168 | u8 status = inb(chip->vendor->base + 1); | 153 | u8 status = inb(chip->vendor->base + 1); |
| 169 | if ((status & chip->vendor->req_complete_mask) == | 154 | if ((status & chip->vendor->req_complete_mask) == |
| 170 | chip->vendor->req_complete_val) { | 155 | chip->vendor->req_complete_val) { |
| 171 | down(&chip->timer_manipulation_mutex); | ||
| 172 | del_singleshot_timer_sync(&chip->device_timer); | ||
| 173 | up(&chip->timer_manipulation_mutex); | ||
| 174 | goto out_recv; | 156 | goto out_recv; |
| 175 | } | 157 | } |
| 176 | set_current_state(TASK_UNINTERRUPTIBLE); | 158 | msleep(TPM_TIMEOUT); /* CHECK */ |
| 177 | schedule_timeout(TPM_TIMEOUT); | ||
| 178 | rmb(); | 159 | rmb(); |
| 179 | } while (!chip->time_expired); | 160 | } while (time_before(jiffies, stop)); |
| 180 | 161 | ||
| 181 | 162 | ||
| 182 | chip->vendor->cancel(chip); | 163 | chip->vendor->cancel(chip); |
| @@ -453,10 +434,8 @@ ssize_t tpm_write(struct file * file, const char __user * buf, | |||
| 453 | 434 | ||
| 454 | /* cannot perform a write until the read has cleared | 435 | /* cannot perform a write until the read has cleared |
| 455 | either via tpm_read or a user_read_timer timeout */ | 436 | either via tpm_read or a user_read_timer timeout */ |
| 456 | while (atomic_read(&chip->data_pending) != 0) { | 437 | while (atomic_read(&chip->data_pending) != 0) |
| 457 | set_current_state(TASK_UNINTERRUPTIBLE); | 438 | msleep(TPM_TIMEOUT); |
| 458 | schedule_timeout(TPM_TIMEOUT); | ||
| 459 | } | ||
| 460 | 439 | ||
| 461 | down(&chip->buffer_mutex); | 440 | down(&chip->buffer_mutex); |
| 462 | 441 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index de0c796fce80..3c4ee433ec7f 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
| 26 | #include <linux/miscdevice.h> | 26 | #include <linux/miscdevice.h> |
| 27 | 27 | ||
| 28 | #define TPM_TIMEOUT msecs_to_jiffies(5) | 28 | #define TPM_TIMEOUT 5 /* msecs */ |
| 29 | 29 | ||
| 30 | /* TPM addresses */ | 30 | /* TPM addresses */ |
| 31 | #define TPM_ADDR 0x4E | 31 | #define TPM_ADDR 0x4E |
| @@ -78,7 +78,6 @@ static inline void tpm_write_index(int index, int value) | |||
| 78 | outb(value & 0xFF, TPM_DATA); | 78 | outb(value & 0xFF, TPM_DATA); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | extern void tpm_time_expired(unsigned long); | ||
| 82 | extern int tpm_lpc_bus_init(struct pci_dev *, u16); | 81 | extern int tpm_lpc_bus_init(struct pci_dev *, u16); |
| 83 | 82 | ||
| 84 | extern int tpm_register_hardware(struct pci_dev *, | 83 | extern int tpm_register_hardware(struct pci_dev *, |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 9cce833a0923..6e5ffcacea60 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
| @@ -55,10 +55,7 @@ | |||
| 55 | */ | 55 | */ |
| 56 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | 56 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) |
| 57 | { | 57 | { |
| 58 | int expired = 0; | 58 | unsigned long stop; |
| 59 | struct timer_list status_timer = | ||
| 60 | TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ, | ||
| 61 | (unsigned long) &expired); | ||
| 62 | 59 | ||
| 63 | /* status immediately available check */ | 60 | /* status immediately available check */ |
| 64 | *data = inb(chip->vendor->base + NSC_STATUS); | 61 | *data = inb(chip->vendor->base + NSC_STATUS); |
| @@ -66,17 +63,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | |||
| 66 | return 0; | 63 | return 0; |
| 67 | 64 | ||
| 68 | /* wait for status */ | 65 | /* wait for status */ |
| 69 | add_timer(&status_timer); | 66 | stop = jiffies + 10 * HZ; |
| 70 | do { | 67 | do { |
| 71 | set_current_state(TASK_UNINTERRUPTIBLE); | 68 | msleep(TPM_TIMEOUT); |
| 72 | schedule_timeout(TPM_TIMEOUT); | ||
| 73 | *data = inb(chip->vendor->base + 1); | 69 | *data = inb(chip->vendor->base + 1); |
| 74 | if ((*data & mask) == val) { | 70 | if ((*data & mask) == val) |
| 75 | del_singleshot_timer_sync(&status_timer); | ||
| 76 | return 0; | 71 | return 0; |
| 77 | } | ||
| 78 | } | 72 | } |
| 79 | while (!expired); | 73 | while (time_before(jiffies, stop)); |
| 80 | 74 | ||
| 81 | return -EBUSY; | 75 | return -EBUSY; |
| 82 | } | 76 | } |
| @@ -84,10 +78,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | |||
| 84 | static int nsc_wait_for_ready(struct tpm_chip *chip) | 78 | static int nsc_wait_for_ready(struct tpm_chip *chip) |
| 85 | { | 79 | { |
| 86 | int status; | 80 | int status; |
| 87 | int expired = 0; | 81 | unsigned long stop; |
| 88 | struct timer_list status_timer = | ||
| 89 | TIMER_INITIALIZER(tpm_time_expired, jiffies + 100, | ||
| 90 | (unsigned long) &expired); | ||
| 91 | 82 | ||
| 92 | /* status immediately available check */ | 83 | /* status immediately available check */ |
| 93 | status = inb(chip->vendor->base + NSC_STATUS); | 84 | status = inb(chip->vendor->base + NSC_STATUS); |
| @@ -97,19 +88,16 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) | |||
| 97 | return 0; | 88 | return 0; |
| 98 | 89 | ||
| 99 | /* wait for status */ | 90 | /* wait for status */ |
| 100 | add_timer(&status_timer); | 91 | stop = jiffies + 100; |
| 101 | do { | 92 | do { |
| 102 | set_current_state(TASK_UNINTERRUPTIBLE); | 93 | msleep(TPM_TIMEOUT); |
| 103 | schedule_timeout(TPM_TIMEOUT); | ||
| 104 | status = inb(chip->vendor->base + NSC_STATUS); | 94 | status = inb(chip->vendor->base + NSC_STATUS); |
| 105 | if (status & NSC_STATUS_OBF) | 95 | if (status & NSC_STATUS_OBF) |
| 106 | status = inb(chip->vendor->base + NSC_DATA); | 96 | status = inb(chip->vendor->base + NSC_DATA); |
| 107 | if (status & NSC_STATUS_RDY) { | 97 | if (status & NSC_STATUS_RDY) |
| 108 | del_singleshot_timer_sync(&status_timer); | ||
| 109 | return 0; | 98 | return 0; |
| 110 | } | ||
| 111 | } | 99 | } |
| 112 | while (!expired); | 100 | while (time_before(jiffies, stop)); |
| 113 | 101 | ||
| 114 | dev_info(&chip->pci_dev->dev, "wait for ready failed\n"); | 102 | dev_info(&chip->pci_dev->dev, "wait for ready failed\n"); |
| 115 | return -EBUSY; | 103 | return -EBUSY; |
