aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorKylene Jo Hall <kjhall@us.ibm.com>2006-04-22 05:37:38 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-22 12:19:54 -0400
commit9e18ee19179a7742999d0e2d4bfcba75b5562439 (patch)
treeda87b5f7547ae840fd797d2e3ddc71e5c7cb3307 /drivers/char
parente0dd03caf20d040a0a86b6bd74028ec9bda545f5 (diff)
[PATCH] tpm: command duration update
With the TPM 1.2 Specification, each command is classified as short, medium or long and the chip tells you the maximum amount of time for a response to each class of command. This patch provides and array of the classifications and a function to determine how long the response should be waited for. Also, it uses that information in the command processing to determine how long to poll for. The function is exported so the 1.2 driver can use the functionality to determine how long to wait for a DataAvailable interrupt if interrupts are being used. 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>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/tpm/tpm.c312
-rw-r--r--drivers/char/tpm/tpm.h2
2 files changed, 311 insertions, 3 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 5e58296f2832..e54bcb4e4e3e 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -35,10 +35,290 @@ enum tpm_const {
35 TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int)) 35 TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
36}; 36};
37 37
38enum tpm_duration {
39 TPM_SHORT = 0,
40 TPM_MEDIUM = 1,
41 TPM_LONG = 2,
42 TPM_UNDEFINED,
43};
44
45#define TPM_MAX_ORDINAL 243
46#define TPM_MAX_PROTECTED_ORDINAL 12
47#define TPM_PROTECTED_ORDINAL_MASK 0xFF
48
38static LIST_HEAD(tpm_chip_list); 49static LIST_HEAD(tpm_chip_list);
39static DEFINE_SPINLOCK(driver_lock); 50static DEFINE_SPINLOCK(driver_lock);
40static int dev_mask[TPM_NUM_MASK_ENTRIES]; 51static int dev_mask[TPM_NUM_MASK_ENTRIES];
41 52
53/*
54 * Array with one entry per ordinal defining the maximum amount
55 * of time the chip could take to return the result. The ordinal
56 * designation of short, medium or long is defined in a table in
57 * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
58 * values of the SHORT, MEDIUM, and LONG durations are retrieved
59 * from the chip during initialization with a call to tpm_get_timeouts.
60 */
61static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
62 TPM_UNDEFINED, /* 0 */
63 TPM_UNDEFINED,
64 TPM_UNDEFINED,
65 TPM_UNDEFINED,
66 TPM_UNDEFINED,
67 TPM_UNDEFINED, /* 5 */
68 TPM_UNDEFINED,
69 TPM_UNDEFINED,
70 TPM_UNDEFINED,
71 TPM_UNDEFINED,
72 TPM_SHORT, /* 10 */
73 TPM_SHORT,
74};
75
76static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
77 TPM_UNDEFINED, /* 0 */
78 TPM_UNDEFINED,
79 TPM_UNDEFINED,
80 TPM_UNDEFINED,
81 TPM_UNDEFINED,
82 TPM_UNDEFINED, /* 5 */
83 TPM_UNDEFINED,
84 TPM_UNDEFINED,
85 TPM_UNDEFINED,
86 TPM_UNDEFINED,
87 TPM_SHORT, /* 10 */
88 TPM_SHORT,
89 TPM_MEDIUM,
90 TPM_LONG,
91 TPM_LONG,
92 TPM_MEDIUM, /* 15 */
93 TPM_SHORT,
94 TPM_SHORT,
95 TPM_MEDIUM,
96 TPM_LONG,
97 TPM_SHORT, /* 20 */
98 TPM_SHORT,
99 TPM_MEDIUM,
100 TPM_MEDIUM,
101 TPM_MEDIUM,
102 TPM_SHORT, /* 25 */
103 TPM_SHORT,
104 TPM_MEDIUM,
105 TPM_SHORT,
106 TPM_SHORT,
107 TPM_MEDIUM, /* 30 */
108 TPM_LONG,
109 TPM_MEDIUM,
110 TPM_SHORT,
111 TPM_SHORT,
112 TPM_SHORT, /* 35 */
113 TPM_MEDIUM,
114 TPM_MEDIUM,
115 TPM_UNDEFINED,
116 TPM_UNDEFINED,
117 TPM_MEDIUM, /* 40 */
118 TPM_LONG,
119 TPM_MEDIUM,
120 TPM_SHORT,
121 TPM_SHORT,
122 TPM_SHORT, /* 45 */
123 TPM_SHORT,
124 TPM_SHORT,
125 TPM_SHORT,
126 TPM_LONG,
127 TPM_MEDIUM, /* 50 */
128 TPM_MEDIUM,
129 TPM_UNDEFINED,
130 TPM_UNDEFINED,
131 TPM_UNDEFINED,
132 TPM_UNDEFINED, /* 55 */
133 TPM_UNDEFINED,
134 TPM_UNDEFINED,
135 TPM_UNDEFINED,
136 TPM_UNDEFINED,
137 TPM_MEDIUM, /* 60 */
138 TPM_MEDIUM,
139 TPM_MEDIUM,
140 TPM_SHORT,
141 TPM_SHORT,
142 TPM_MEDIUM, /* 65 */
143 TPM_UNDEFINED,
144 TPM_UNDEFINED,
145 TPM_UNDEFINED,
146 TPM_UNDEFINED,
147 TPM_SHORT, /* 70 */
148 TPM_SHORT,
149 TPM_UNDEFINED,
150 TPM_UNDEFINED,
151 TPM_UNDEFINED,
152 TPM_UNDEFINED, /* 75 */
153 TPM_UNDEFINED,
154 TPM_UNDEFINED,
155 TPM_UNDEFINED,
156 TPM_UNDEFINED,
157 TPM_LONG, /* 80 */
158 TPM_UNDEFINED,
159 TPM_MEDIUM,
160 TPM_LONG,
161 TPM_SHORT,
162 TPM_UNDEFINED, /* 85 */
163 TPM_UNDEFINED,
164 TPM_UNDEFINED,
165 TPM_UNDEFINED,
166 TPM_UNDEFINED,
167 TPM_SHORT, /* 90 */
168 TPM_SHORT,
169 TPM_SHORT,
170 TPM_SHORT,
171 TPM_SHORT,
172 TPM_UNDEFINED, /* 95 */
173 TPM_UNDEFINED,
174 TPM_UNDEFINED,
175 TPM_UNDEFINED,
176 TPM_UNDEFINED,
177 TPM_MEDIUM, /* 100 */
178 TPM_SHORT,
179 TPM_SHORT,
180 TPM_UNDEFINED,
181 TPM_UNDEFINED,
182 TPM_UNDEFINED, /* 105 */
183 TPM_UNDEFINED,
184 TPM_UNDEFINED,
185 TPM_UNDEFINED,
186 TPM_UNDEFINED,
187 TPM_SHORT, /* 110 */
188 TPM_SHORT,
189 TPM_SHORT,
190 TPM_SHORT,
191 TPM_SHORT,
192 TPM_SHORT, /* 115 */
193 TPM_SHORT,
194 TPM_SHORT,
195 TPM_UNDEFINED,
196 TPM_UNDEFINED,
197 TPM_LONG, /* 120 */
198 TPM_LONG,
199 TPM_MEDIUM,
200 TPM_UNDEFINED,
201 TPM_SHORT,
202 TPM_SHORT, /* 125 */
203 TPM_SHORT,
204 TPM_LONG,
205 TPM_SHORT,
206 TPM_SHORT,
207 TPM_SHORT, /* 130 */
208 TPM_MEDIUM,
209 TPM_UNDEFINED,
210 TPM_SHORT,
211 TPM_MEDIUM,
212 TPM_UNDEFINED, /* 135 */
213 TPM_UNDEFINED,
214 TPM_UNDEFINED,
215 TPM_UNDEFINED,
216 TPM_UNDEFINED,
217 TPM_SHORT, /* 140 */
218 TPM_SHORT,
219 TPM_UNDEFINED,
220 TPM_UNDEFINED,
221 TPM_UNDEFINED,
222 TPM_UNDEFINED, /* 145 */
223 TPM_UNDEFINED,
224 TPM_UNDEFINED,
225 TPM_UNDEFINED,
226 TPM_UNDEFINED,
227 TPM_SHORT, /* 150 */
228 TPM_MEDIUM,
229 TPM_MEDIUM,
230 TPM_SHORT,
231 TPM_SHORT,
232 TPM_UNDEFINED, /* 155 */
233 TPM_UNDEFINED,
234 TPM_UNDEFINED,
235 TPM_UNDEFINED,
236 TPM_UNDEFINED,
237 TPM_SHORT, /* 160 */
238 TPM_SHORT,
239 TPM_SHORT,
240 TPM_SHORT,
241 TPM_UNDEFINED,
242 TPM_UNDEFINED, /* 165 */
243 TPM_UNDEFINED,
244 TPM_UNDEFINED,
245 TPM_UNDEFINED,
246 TPM_UNDEFINED,
247 TPM_LONG, /* 170 */
248 TPM_UNDEFINED,
249 TPM_UNDEFINED,
250 TPM_UNDEFINED,
251 TPM_UNDEFINED,
252 TPM_UNDEFINED, /* 175 */
253 TPM_UNDEFINED,
254 TPM_UNDEFINED,
255 TPM_UNDEFINED,
256 TPM_UNDEFINED,
257 TPM_MEDIUM, /* 180 */
258 TPM_SHORT,
259 TPM_MEDIUM,
260 TPM_MEDIUM,
261 TPM_MEDIUM,
262 TPM_MEDIUM, /* 185 */
263 TPM_SHORT,
264 TPM_UNDEFINED,
265 TPM_UNDEFINED,
266 TPM_UNDEFINED,
267 TPM_UNDEFINED, /* 190 */
268 TPM_UNDEFINED,
269 TPM_UNDEFINED,
270 TPM_UNDEFINED,
271 TPM_UNDEFINED,
272 TPM_UNDEFINED, /* 195 */
273 TPM_UNDEFINED,
274 TPM_UNDEFINED,
275 TPM_UNDEFINED,
276 TPM_UNDEFINED,
277 TPM_SHORT, /* 200 */
278 TPM_UNDEFINED,
279 TPM_UNDEFINED,
280 TPM_UNDEFINED,
281 TPM_SHORT,
282 TPM_SHORT, /* 205 */
283 TPM_SHORT,
284 TPM_SHORT,
285 TPM_SHORT,
286 TPM_SHORT,
287 TPM_MEDIUM, /* 210 */
288 TPM_UNDEFINED,
289 TPM_MEDIUM,
290 TPM_MEDIUM,
291 TPM_MEDIUM,
292 TPM_UNDEFINED, /* 215 */
293 TPM_MEDIUM,
294 TPM_UNDEFINED,
295 TPM_UNDEFINED,
296 TPM_SHORT,
297 TPM_SHORT, /* 220 */
298 TPM_SHORT,
299 TPM_SHORT,
300 TPM_SHORT,
301 TPM_SHORT,
302 TPM_UNDEFINED, /* 225 */
303 TPM_UNDEFINED,
304 TPM_UNDEFINED,
305 TPM_UNDEFINED,
306 TPM_UNDEFINED,
307 TPM_SHORT, /* 230 */
308 TPM_LONG,
309 TPM_MEDIUM,
310 TPM_UNDEFINED,
311 TPM_UNDEFINED,
312 TPM_UNDEFINED, /* 235 */
313 TPM_UNDEFINED,
314 TPM_UNDEFINED,
315 TPM_UNDEFINED,
316 TPM_UNDEFINED,
317 TPM_SHORT, /* 240 */
318 TPM_UNDEFINED,
319 TPM_MEDIUM,
320};
321
42static void user_reader_timeout(unsigned long ptr) 322static void user_reader_timeout(unsigned long ptr)
43{ 323{
44 struct tpm_chip *chip = (struct tpm_chip *) ptr; 324 struct tpm_chip *chip = (struct tpm_chip *) ptr;
@@ -57,17 +337,43 @@ static void timeout_work(void *ptr)
57} 337}
58 338
59/* 339/*
340 * Returns max number of jiffies to wait
341 */
342unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
343 u32 ordinal)
344{
345 int duration_idx = TPM_UNDEFINED;
346 int duration = 0;
347
348 if (ordinal < TPM_MAX_ORDINAL)
349 duration_idx = tpm_ordinal_duration[ordinal];
350 else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
351 TPM_MAX_PROTECTED_ORDINAL)
352 duration_idx =
353 tpm_protected_ordinal_duration[ordinal &
354 TPM_PROTECTED_ORDINAL_MASK];
355
356 if (duration_idx != TPM_UNDEFINED)
357 duration = chip->vendor.duration[duration_idx] * HZ / 1000;
358 if (duration <= 0)
359 return 2 * 60 * HZ;
360 else
361 return duration;
362}
363EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
364
365/*
60 * Internal kernel interface to transmit TPM commands 366 * Internal kernel interface to transmit TPM commands
61 */ 367 */
62static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, 368static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
63 size_t bufsiz) 369 size_t bufsiz)
64{ 370{
65 ssize_t rc; 371 ssize_t rc;
66 u32 count; 372 u32 count, ordinal;
67 unsigned long stop; 373 unsigned long stop;
68 374
69 count = be32_to_cpu(*((__be32 *) (buf + 2))); 375 count = be32_to_cpu(*((__be32 *) (buf + 2)));
70 376 ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
71 if (count == 0) 377 if (count == 0)
72 return -ENODATA; 378 return -ENODATA;
73 if (count > bufsiz) { 379 if (count > bufsiz) {
@@ -84,7 +390,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
84 goto out; 390 goto out;
85 } 391 }
86 392
87 stop = jiffies + 2 * 60 * HZ; 393 stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
88 do { 394 do {
89 u8 status = chip->vendor.status(chip); 395 u8 status = chip->vendor.status(chip);
90 if ((status & chip->vendor.req_complete_mask) == 396 if ((status & chip->vendor.req_complete_mask) ==
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 4f005345bf37..1d28485b8fb3 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -63,6 +63,7 @@ struct tpm_vendor_specific {
63 u8 (*status) (struct tpm_chip *); 63 u8 (*status) (struct tpm_chip *);
64 struct miscdevice miscdev; 64 struct miscdevice miscdev;
65 struct attribute_group *attr_group; 65 struct attribute_group *attr_group;
66 u32 duration[3];
66}; 67};
67 68
68struct tpm_chip { 69struct tpm_chip {
@@ -100,6 +101,7 @@ static inline void tpm_write_index(int base, int index, int value)
100 outb(value & 0xFF, base+1); 101 outb(value & 0xFF, base+1);
101} 102}
102 103
104extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
103extern struct tpm_chip* tpm_register_hardware(struct device *, 105extern struct tpm_chip* tpm_register_hardware(struct device *,
104 const struct tpm_vendor_specific *); 106 const struct tpm_vendor_specific *);
105extern int tpm_open(struct inode *, struct file *); 107extern int tpm_open(struct inode *, struct file *);