diff options
Diffstat (limited to 'drivers')
35 files changed, 2018 insertions, 582 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index e1aadae00623..cb76e5ca9a23 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -889,7 +889,6 @@ extern int drm_lock_free(drm_device_t * dev, | |||
889 | /* Buffer management support (drm_bufs.h) */ | 889 | /* Buffer management support (drm_bufs.h) */ |
890 | extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); | 890 | extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); |
891 | extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request); | 891 | extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request); |
892 | extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request); | ||
893 | extern int drm_addmap(drm_device_t * dev, unsigned int offset, | 892 | extern int drm_addmap(drm_device_t * dev, unsigned int offset, |
894 | unsigned int size, drm_map_type_t type, | 893 | unsigned int size, drm_map_type_t type, |
895 | drm_map_flags_t flags, drm_local_map_t ** map_ptr); | 894 | drm_map_flags_t flags, drm_local_map_t ** map_ptr); |
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c index fabc930c67a2..40bfd9b01e39 100644 --- a/drivers/char/drm/drm_agpsupport.c +++ b/drivers/char/drm/drm_agpsupport.c | |||
@@ -503,8 +503,6 @@ int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start) | |||
503 | return agp_bind_memory(handle, start); | 503 | return agp_bind_memory(handle, start); |
504 | } | 504 | } |
505 | 505 | ||
506 | EXPORT_SYMBOL(drm_agp_bind_memory); | ||
507 | |||
508 | /** Calls agp_unbind_memory() */ | 506 | /** Calls agp_unbind_memory() */ |
509 | int drm_agp_unbind_memory(DRM_AGP_MEM * handle) | 507 | int drm_agp_unbind_memory(DRM_AGP_MEM * handle) |
510 | { | 508 | { |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 8a9cf12e6183..006b06d29727 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -386,7 +386,6 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
386 | 386 | ||
387 | return 0; | 387 | return 0; |
388 | } | 388 | } |
389 | EXPORT_SYMBOL(drm_rmmap_locked); | ||
390 | 389 | ||
391 | int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) | 390 | int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) |
392 | { | 391 | { |
@@ -398,7 +397,6 @@ int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) | |||
398 | 397 | ||
399 | return ret; | 398 | return ret; |
400 | } | 399 | } |
401 | EXPORT_SYMBOL(drm_rmmap); | ||
402 | 400 | ||
403 | /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on | 401 | /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on |
404 | * the last close of the device, and this is necessary for cleanup when things | 402 | * the last close of the device, and this is necessary for cleanup when things |
@@ -1053,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
1053 | return 0; | 1051 | return 0; |
1054 | } | 1052 | } |
1055 | 1053 | ||
1056 | int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | 1054 | static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) |
1057 | { | 1055 | { |
1058 | drm_device_dma_t *dma = dev->dma; | 1056 | drm_device_dma_t *dma = dev->dma; |
1059 | drm_buf_entry_t *entry; | 1057 | drm_buf_entry_t *entry; |
@@ -1212,7 +1210,6 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1212 | atomic_dec(&dev->buf_alloc); | 1210 | atomic_dec(&dev->buf_alloc); |
1213 | return 0; | 1211 | return 0; |
1214 | } | 1212 | } |
1215 | EXPORT_SYMBOL(drm_addbufs_fb); | ||
1216 | 1213 | ||
1217 | 1214 | ||
1218 | /** | 1215 | /** |
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 68073e14fdec..9a842a36bb27 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -229,8 +229,6 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
229 | return ret; | 229 | return ret; |
230 | } | 230 | } |
231 | 231 | ||
232 | EXPORT_SYMBOL(drm_get_dev); | ||
233 | |||
234 | /** | 232 | /** |
235 | * Put a device minor number. | 233 | * Put a device minor number. |
236 | * | 234 | * |
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index b108c7f913b2..26bdf2ca59d7 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
@@ -723,7 +723,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, | |||
723 | 723 | ||
724 | dev_priv->scratch_ages[header.scratch.reg]++; | 724 | dev_priv->scratch_ages[header.scratch.reg]++; |
725 | 725 | ||
726 | ref_age_base = *(u32 **)cmdbuf->buf; | 726 | ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf); |
727 | 727 | ||
728 | cmdbuf->buf += sizeof(u64); | 728 | cmdbuf->buf += sizeof(u64); |
729 | cmdbuf->bufsz -= sizeof(u64); | 729 | cmdbuf->bufsz -= sizeof(u64); |
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index b543821d8cb4..56c8243cdb73 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c | |||
@@ -390,7 +390,8 @@ scdrv_init(void) | |||
390 | format_module_id(devnamep, geo_module(geoid), | 390 | format_module_id(devnamep, geo_module(geoid), |
391 | MODULE_FORMAT_BRIEF); | 391 | MODULE_FORMAT_BRIEF); |
392 | devnamep = devname + strlen(devname); | 392 | devnamep = devname + strlen(devname); |
393 | sprintf(devnamep, "#%d", geo_slab(geoid)); | 393 | sprintf(devnamep, "^%d#%d", geo_slot(geoid), |
394 | geo_slab(geoid)); | ||
394 | 395 | ||
395 | /* allocate sysctl device data */ | 396 | /* allocate sysctl device data */ |
396 | scd = kzalloc(sizeof (struct sysctl_data_s), | 397 | scd = kzalloc(sizeof (struct sysctl_data_s), |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index a6873bf89ffa..1efde3b27619 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -20,9 +20,18 @@ config TCG_TPM | |||
20 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | 20 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI |
21 | and CONFIG_PNPACPI. | 21 | and CONFIG_PNPACPI. |
22 | 22 | ||
23 | config TCG_TIS | ||
24 | tristate "TPM Interface Specification 1.2 Interface" | ||
25 | depends on TCG_TPM | ||
26 | ---help--- | ||
27 | If you have a TPM security chip that is compliant with the | ||
28 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | ||
29 | from within Linux. To compile this driver as a module, choose | ||
30 | M here; the module will be called tpm_tis. | ||
31 | |||
23 | config TCG_NSC | 32 | config TCG_NSC |
24 | tristate "National Semiconductor TPM Interface" | 33 | tristate "National Semiconductor TPM Interface" |
25 | depends on TCG_TPM | 34 | depends on TCG_TPM && PNPACPI |
26 | ---help--- | 35 | ---help--- |
27 | If you have a TPM security chip from National Semicondutor | 36 | If you have a TPM security chip from National Semicondutor |
28 | say Yes and it will be accessible from within Linux. To | 37 | say Yes and it will be accessible from within Linux. To |
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index ba4582d160fd..ea3a1e02a824 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile | |||
@@ -5,6 +5,7 @@ obj-$(CONFIG_TCG_TPM) += tpm.o | |||
5 | ifdef CONFIG_ACPI | 5 | ifdef CONFIG_ACPI |
6 | obj-$(CONFIG_TCG_TPM) += tpm_bios.o | 6 | obj-$(CONFIG_TCG_TPM) += tpm_bios.o |
7 | endif | 7 | endif |
8 | obj-$(CONFIG_TCG_TIS) += tpm_tis.o | ||
8 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o | 9 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o |
9 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o | 10 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o |
10 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o | 11 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 5a3870477ef1..6889e7db3aff 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -32,12 +32,291 @@ enum tpm_const { | |||
32 | TPM_MINOR = 224, /* officially assigned */ | 32 | TPM_MINOR = 224, /* officially assigned */ |
33 | TPM_BUFSIZE = 2048, | 33 | TPM_BUFSIZE = 2048, |
34 | TPM_NUM_DEVICES = 256, | 34 | TPM_NUM_DEVICES = 256, |
35 | TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int)) | ||
36 | }; | 35 | }; |
37 | 36 | ||
37 | enum tpm_duration { | ||
38 | TPM_SHORT = 0, | ||
39 | TPM_MEDIUM = 1, | ||
40 | TPM_LONG = 2, | ||
41 | TPM_UNDEFINED, | ||
42 | }; | ||
43 | |||
44 | #define TPM_MAX_ORDINAL 243 | ||
45 | #define TPM_MAX_PROTECTED_ORDINAL 12 | ||
46 | #define TPM_PROTECTED_ORDINAL_MASK 0xFF | ||
47 | |||
38 | static LIST_HEAD(tpm_chip_list); | 48 | static LIST_HEAD(tpm_chip_list); |
39 | static DEFINE_SPINLOCK(driver_lock); | 49 | static DEFINE_SPINLOCK(driver_lock); |
40 | static int dev_mask[TPM_NUM_MASK_ENTRIES]; | 50 | static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); |
51 | |||
52 | /* | ||
53 | * Array with one entry per ordinal defining the maximum amount | ||
54 | * of time the chip could take to return the result. The ordinal | ||
55 | * designation of short, medium or long is defined in a table in | ||
56 | * TCG Specification TPM Main Part 2 TPM Structures Section 17. The | ||
57 | * values of the SHORT, MEDIUM, and LONG durations are retrieved | ||
58 | * from the chip during initialization with a call to tpm_get_timeouts. | ||
59 | */ | ||
60 | static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { | ||
61 | TPM_UNDEFINED, /* 0 */ | ||
62 | TPM_UNDEFINED, | ||
63 | TPM_UNDEFINED, | ||
64 | TPM_UNDEFINED, | ||
65 | TPM_UNDEFINED, | ||
66 | TPM_UNDEFINED, /* 5 */ | ||
67 | TPM_UNDEFINED, | ||
68 | TPM_UNDEFINED, | ||
69 | TPM_UNDEFINED, | ||
70 | TPM_UNDEFINED, | ||
71 | TPM_SHORT, /* 10 */ | ||
72 | TPM_SHORT, | ||
73 | }; | ||
74 | |||
75 | static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { | ||
76 | TPM_UNDEFINED, /* 0 */ | ||
77 | TPM_UNDEFINED, | ||
78 | TPM_UNDEFINED, | ||
79 | TPM_UNDEFINED, | ||
80 | TPM_UNDEFINED, | ||
81 | TPM_UNDEFINED, /* 5 */ | ||
82 | TPM_UNDEFINED, | ||
83 | TPM_UNDEFINED, | ||
84 | TPM_UNDEFINED, | ||
85 | TPM_UNDEFINED, | ||
86 | TPM_SHORT, /* 10 */ | ||
87 | TPM_SHORT, | ||
88 | TPM_MEDIUM, | ||
89 | TPM_LONG, | ||
90 | TPM_LONG, | ||
91 | TPM_MEDIUM, /* 15 */ | ||
92 | TPM_SHORT, | ||
93 | TPM_SHORT, | ||
94 | TPM_MEDIUM, | ||
95 | TPM_LONG, | ||
96 | TPM_SHORT, /* 20 */ | ||
97 | TPM_SHORT, | ||
98 | TPM_MEDIUM, | ||
99 | TPM_MEDIUM, | ||
100 | TPM_MEDIUM, | ||
101 | TPM_SHORT, /* 25 */ | ||
102 | TPM_SHORT, | ||
103 | TPM_MEDIUM, | ||
104 | TPM_SHORT, | ||
105 | TPM_SHORT, | ||
106 | TPM_MEDIUM, /* 30 */ | ||
107 | TPM_LONG, | ||
108 | TPM_MEDIUM, | ||
109 | TPM_SHORT, | ||
110 | TPM_SHORT, | ||
111 | TPM_SHORT, /* 35 */ | ||
112 | TPM_MEDIUM, | ||
113 | TPM_MEDIUM, | ||
114 | TPM_UNDEFINED, | ||
115 | TPM_UNDEFINED, | ||
116 | TPM_MEDIUM, /* 40 */ | ||
117 | TPM_LONG, | ||
118 | TPM_MEDIUM, | ||
119 | TPM_SHORT, | ||
120 | TPM_SHORT, | ||
121 | TPM_SHORT, /* 45 */ | ||
122 | TPM_SHORT, | ||
123 | TPM_SHORT, | ||
124 | TPM_SHORT, | ||
125 | TPM_LONG, | ||
126 | TPM_MEDIUM, /* 50 */ | ||
127 | TPM_MEDIUM, | ||
128 | TPM_UNDEFINED, | ||
129 | TPM_UNDEFINED, | ||
130 | TPM_UNDEFINED, | ||
131 | TPM_UNDEFINED, /* 55 */ | ||
132 | TPM_UNDEFINED, | ||
133 | TPM_UNDEFINED, | ||
134 | TPM_UNDEFINED, | ||
135 | TPM_UNDEFINED, | ||
136 | TPM_MEDIUM, /* 60 */ | ||
137 | TPM_MEDIUM, | ||
138 | TPM_MEDIUM, | ||
139 | TPM_SHORT, | ||
140 | TPM_SHORT, | ||
141 | TPM_MEDIUM, /* 65 */ | ||
142 | TPM_UNDEFINED, | ||
143 | TPM_UNDEFINED, | ||
144 | TPM_UNDEFINED, | ||
145 | TPM_UNDEFINED, | ||
146 | TPM_SHORT, /* 70 */ | ||
147 | TPM_SHORT, | ||
148 | TPM_UNDEFINED, | ||
149 | TPM_UNDEFINED, | ||
150 | TPM_UNDEFINED, | ||
151 | TPM_UNDEFINED, /* 75 */ | ||
152 | TPM_UNDEFINED, | ||
153 | TPM_UNDEFINED, | ||
154 | TPM_UNDEFINED, | ||
155 | TPM_UNDEFINED, | ||
156 | TPM_LONG, /* 80 */ | ||
157 | TPM_UNDEFINED, | ||
158 | TPM_MEDIUM, | ||
159 | TPM_LONG, | ||
160 | TPM_SHORT, | ||
161 | TPM_UNDEFINED, /* 85 */ | ||
162 | TPM_UNDEFINED, | ||
163 | TPM_UNDEFINED, | ||
164 | TPM_UNDEFINED, | ||
165 | TPM_UNDEFINED, | ||
166 | TPM_SHORT, /* 90 */ | ||
167 | TPM_SHORT, | ||
168 | TPM_SHORT, | ||
169 | TPM_SHORT, | ||
170 | TPM_SHORT, | ||
171 | TPM_UNDEFINED, /* 95 */ | ||
172 | TPM_UNDEFINED, | ||
173 | TPM_UNDEFINED, | ||
174 | TPM_UNDEFINED, | ||
175 | TPM_UNDEFINED, | ||
176 | TPM_MEDIUM, /* 100 */ | ||
177 | TPM_SHORT, | ||
178 | TPM_SHORT, | ||
179 | TPM_UNDEFINED, | ||
180 | TPM_UNDEFINED, | ||
181 | TPM_UNDEFINED, /* 105 */ | ||
182 | TPM_UNDEFINED, | ||
183 | TPM_UNDEFINED, | ||
184 | TPM_UNDEFINED, | ||
185 | TPM_UNDEFINED, | ||
186 | TPM_SHORT, /* 110 */ | ||
187 | TPM_SHORT, | ||
188 | TPM_SHORT, | ||
189 | TPM_SHORT, | ||
190 | TPM_SHORT, | ||
191 | TPM_SHORT, /* 115 */ | ||
192 | TPM_SHORT, | ||
193 | TPM_SHORT, | ||
194 | TPM_UNDEFINED, | ||
195 | TPM_UNDEFINED, | ||
196 | TPM_LONG, /* 120 */ | ||
197 | TPM_LONG, | ||
198 | TPM_MEDIUM, | ||
199 | TPM_UNDEFINED, | ||
200 | TPM_SHORT, | ||
201 | TPM_SHORT, /* 125 */ | ||
202 | TPM_SHORT, | ||
203 | TPM_LONG, | ||
204 | TPM_SHORT, | ||
205 | TPM_SHORT, | ||
206 | TPM_SHORT, /* 130 */ | ||
207 | TPM_MEDIUM, | ||
208 | TPM_UNDEFINED, | ||
209 | TPM_SHORT, | ||
210 | TPM_MEDIUM, | ||
211 | TPM_UNDEFINED, /* 135 */ | ||
212 | TPM_UNDEFINED, | ||
213 | TPM_UNDEFINED, | ||
214 | TPM_UNDEFINED, | ||
215 | TPM_UNDEFINED, | ||
216 | TPM_SHORT, /* 140 */ | ||
217 | TPM_SHORT, | ||
218 | TPM_UNDEFINED, | ||
219 | TPM_UNDEFINED, | ||
220 | TPM_UNDEFINED, | ||
221 | TPM_UNDEFINED, /* 145 */ | ||
222 | TPM_UNDEFINED, | ||
223 | TPM_UNDEFINED, | ||
224 | TPM_UNDEFINED, | ||
225 | TPM_UNDEFINED, | ||
226 | TPM_SHORT, /* 150 */ | ||
227 | TPM_MEDIUM, | ||
228 | TPM_MEDIUM, | ||
229 | TPM_SHORT, | ||
230 | TPM_SHORT, | ||
231 | TPM_UNDEFINED, /* 155 */ | ||
232 | TPM_UNDEFINED, | ||
233 | TPM_UNDEFINED, | ||
234 | TPM_UNDEFINED, | ||
235 | TPM_UNDEFINED, | ||
236 | TPM_SHORT, /* 160 */ | ||
237 | TPM_SHORT, | ||
238 | TPM_SHORT, | ||
239 | TPM_SHORT, | ||
240 | TPM_UNDEFINED, | ||
241 | TPM_UNDEFINED, /* 165 */ | ||
242 | TPM_UNDEFINED, | ||
243 | TPM_UNDEFINED, | ||
244 | TPM_UNDEFINED, | ||
245 | TPM_UNDEFINED, | ||
246 | TPM_LONG, /* 170 */ | ||
247 | TPM_UNDEFINED, | ||
248 | TPM_UNDEFINED, | ||
249 | TPM_UNDEFINED, | ||
250 | TPM_UNDEFINED, | ||
251 | TPM_UNDEFINED, /* 175 */ | ||
252 | TPM_UNDEFINED, | ||
253 | TPM_UNDEFINED, | ||
254 | TPM_UNDEFINED, | ||
255 | TPM_UNDEFINED, | ||
256 | TPM_MEDIUM, /* 180 */ | ||
257 | TPM_SHORT, | ||
258 | TPM_MEDIUM, | ||
259 | TPM_MEDIUM, | ||
260 | TPM_MEDIUM, | ||
261 | TPM_MEDIUM, /* 185 */ | ||
262 | TPM_SHORT, | ||
263 | TPM_UNDEFINED, | ||
264 | TPM_UNDEFINED, | ||
265 | TPM_UNDEFINED, | ||
266 | TPM_UNDEFINED, /* 190 */ | ||
267 | TPM_UNDEFINED, | ||
268 | TPM_UNDEFINED, | ||
269 | TPM_UNDEFINED, | ||
270 | TPM_UNDEFINED, | ||
271 | TPM_UNDEFINED, /* 195 */ | ||
272 | TPM_UNDEFINED, | ||
273 | TPM_UNDEFINED, | ||
274 | TPM_UNDEFINED, | ||
275 | TPM_UNDEFINED, | ||
276 | TPM_SHORT, /* 200 */ | ||
277 | TPM_UNDEFINED, | ||
278 | TPM_UNDEFINED, | ||
279 | TPM_UNDEFINED, | ||
280 | TPM_SHORT, | ||
281 | TPM_SHORT, /* 205 */ | ||
282 | TPM_SHORT, | ||
283 | TPM_SHORT, | ||
284 | TPM_SHORT, | ||
285 | TPM_SHORT, | ||
286 | TPM_MEDIUM, /* 210 */ | ||
287 | TPM_UNDEFINED, | ||
288 | TPM_MEDIUM, | ||
289 | TPM_MEDIUM, | ||
290 | TPM_MEDIUM, | ||
291 | TPM_UNDEFINED, /* 215 */ | ||
292 | TPM_MEDIUM, | ||
293 | TPM_UNDEFINED, | ||
294 | TPM_UNDEFINED, | ||
295 | TPM_SHORT, | ||
296 | TPM_SHORT, /* 220 */ | ||
297 | TPM_SHORT, | ||
298 | TPM_SHORT, | ||
299 | TPM_SHORT, | ||
300 | TPM_SHORT, | ||
301 | TPM_UNDEFINED, /* 225 */ | ||
302 | TPM_UNDEFINED, | ||
303 | TPM_UNDEFINED, | ||
304 | TPM_UNDEFINED, | ||
305 | TPM_UNDEFINED, | ||
306 | TPM_SHORT, /* 230 */ | ||
307 | TPM_LONG, | ||
308 | TPM_MEDIUM, | ||
309 | TPM_UNDEFINED, | ||
310 | TPM_UNDEFINED, | ||
311 | TPM_UNDEFINED, /* 235 */ | ||
312 | TPM_UNDEFINED, | ||
313 | TPM_UNDEFINED, | ||
314 | TPM_UNDEFINED, | ||
315 | TPM_UNDEFINED, | ||
316 | TPM_SHORT, /* 240 */ | ||
317 | TPM_UNDEFINED, | ||
318 | TPM_MEDIUM, | ||
319 | }; | ||
41 | 320 | ||
42 | static void user_reader_timeout(unsigned long ptr) | 321 | static void user_reader_timeout(unsigned long ptr) |
43 | { | 322 | { |
@@ -46,7 +325,7 @@ static void user_reader_timeout(unsigned long ptr) | |||
46 | schedule_work(&chip->work); | 325 | schedule_work(&chip->work); |
47 | } | 326 | } |
48 | 327 | ||
49 | static void timeout_work(void * ptr) | 328 | static void timeout_work(void *ptr) |
50 | { | 329 | { |
51 | struct tpm_chip *chip = ptr; | 330 | struct tpm_chip *chip = ptr; |
52 | 331 | ||
@@ -57,17 +336,43 @@ static void timeout_work(void * ptr) | |||
57 | } | 336 | } |
58 | 337 | ||
59 | /* | 338 | /* |
339 | * Returns max number of jiffies to wait | ||
340 | */ | ||
341 | unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, | ||
342 | u32 ordinal) | ||
343 | { | ||
344 | int duration_idx = TPM_UNDEFINED; | ||
345 | int duration = 0; | ||
346 | |||
347 | if (ordinal < TPM_MAX_ORDINAL) | ||
348 | duration_idx = tpm_ordinal_duration[ordinal]; | ||
349 | else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < | ||
350 | TPM_MAX_PROTECTED_ORDINAL) | ||
351 | duration_idx = | ||
352 | tpm_protected_ordinal_duration[ordinal & | ||
353 | TPM_PROTECTED_ORDINAL_MASK]; | ||
354 | |||
355 | if (duration_idx != TPM_UNDEFINED) | ||
356 | duration = chip->vendor.duration[duration_idx]; | ||
357 | if (duration <= 0) | ||
358 | return 2 * 60 * HZ; | ||
359 | else | ||
360 | return duration; | ||
361 | } | ||
362 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); | ||
363 | |||
364 | /* | ||
60 | * Internal kernel interface to transmit TPM commands | 365 | * Internal kernel interface to transmit TPM commands |
61 | */ | 366 | */ |
62 | static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | 367 | static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, |
63 | size_t bufsiz) | 368 | size_t bufsiz) |
64 | { | 369 | { |
65 | ssize_t rc; | 370 | ssize_t rc; |
66 | u32 count; | 371 | u32 count, ordinal; |
67 | unsigned long stop; | 372 | unsigned long stop; |
68 | 373 | ||
69 | count = be32_to_cpu(*((__be32 *) (buf + 2))); | 374 | count = be32_to_cpu(*((__be32 *) (buf + 2))); |
70 | 375 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | |
71 | if (count == 0) | 376 | if (count == 0) |
72 | return -ENODATA; | 377 | return -ENODATA; |
73 | if (count > bufsiz) { | 378 | if (count > bufsiz) { |
@@ -78,21 +383,23 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
78 | 383 | ||
79 | down(&chip->tpm_mutex); | 384 | down(&chip->tpm_mutex); |
80 | 385 | ||
81 | if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { | 386 | if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { |
82 | dev_err(chip->dev, | 387 | dev_err(chip->dev, |
83 | "tpm_transmit: tpm_send: error %zd\n", rc); | 388 | "tpm_transmit: tpm_send: error %zd\n", rc); |
84 | goto out; | 389 | goto out; |
85 | } | 390 | } |
86 | 391 | ||
87 | stop = jiffies + 2 * 60 * HZ; | 392 | if (chip->vendor.irq) |
393 | goto out_recv; | ||
394 | |||
395 | stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); | ||
88 | do { | 396 | do { |
89 | u8 status = chip->vendor->status(chip); | 397 | u8 status = chip->vendor.status(chip); |
90 | if ((status & chip->vendor->req_complete_mask) == | 398 | if ((status & chip->vendor.req_complete_mask) == |
91 | chip->vendor->req_complete_val) { | 399 | chip->vendor.req_complete_val) |
92 | goto out_recv; | 400 | goto out_recv; |
93 | } | ||
94 | 401 | ||
95 | if ((status == chip->vendor->req_canceled)) { | 402 | if ((status == chip->vendor.req_canceled)) { |
96 | dev_err(chip->dev, "Operation Canceled\n"); | 403 | dev_err(chip->dev, "Operation Canceled\n"); |
97 | rc = -ECANCELED; | 404 | rc = -ECANCELED; |
98 | goto out; | 405 | goto out; |
@@ -102,14 +409,13 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
102 | rmb(); | 409 | rmb(); |
103 | } while (time_before(jiffies, stop)); | 410 | } while (time_before(jiffies, stop)); |
104 | 411 | ||
105 | 412 | chip->vendor.cancel(chip); | |
106 | chip->vendor->cancel(chip); | ||
107 | dev_err(chip->dev, "Operation Timed out\n"); | 413 | dev_err(chip->dev, "Operation Timed out\n"); |
108 | rc = -ETIME; | 414 | rc = -ETIME; |
109 | goto out; | 415 | goto out; |
110 | 416 | ||
111 | out_recv: | 417 | out_recv: |
112 | rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz); | 418 | rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz); |
113 | if (rc < 0) | 419 | if (rc < 0) |
114 | dev_err(chip->dev, | 420 | dev_err(chip->dev, |
115 | "tpm_transmit: tpm_recv: error %zd\n", rc); | 421 | "tpm_transmit: tpm_recv: error %zd\n", rc); |
@@ -119,17 +425,247 @@ out: | |||
119 | } | 425 | } |
120 | 426 | ||
121 | #define TPM_DIGEST_SIZE 20 | 427 | #define TPM_DIGEST_SIZE 20 |
122 | #define CAP_PCR_RESULT_SIZE 18 | 428 | #define TPM_ERROR_SIZE 10 |
123 | static const u8 cap_pcr[] = { | 429 | #define TPM_RET_CODE_IDX 6 |
430 | #define TPM_GET_CAP_RET_SIZE_IDX 10 | ||
431 | #define TPM_GET_CAP_RET_UINT32_1_IDX 14 | ||
432 | #define TPM_GET_CAP_RET_UINT32_2_IDX 18 | ||
433 | #define TPM_GET_CAP_RET_UINT32_3_IDX 22 | ||
434 | #define TPM_GET_CAP_RET_UINT32_4_IDX 26 | ||
435 | #define TPM_GET_CAP_PERM_DISABLE_IDX 16 | ||
436 | #define TPM_GET_CAP_PERM_INACTIVE_IDX 18 | ||
437 | #define TPM_GET_CAP_RET_BOOL_1_IDX 14 | ||
438 | #define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 | ||
439 | |||
440 | #define TPM_CAP_IDX 13 | ||
441 | #define TPM_CAP_SUBCAP_IDX 21 | ||
442 | |||
443 | enum tpm_capabilities { | ||
444 | TPM_CAP_FLAG = 4, | ||
445 | TPM_CAP_PROP = 5, | ||
446 | }; | ||
447 | |||
448 | enum tpm_sub_capabilities { | ||
449 | TPM_CAP_PROP_PCR = 0x1, | ||
450 | TPM_CAP_PROP_MANUFACTURER = 0x3, | ||
451 | TPM_CAP_FLAG_PERM = 0x8, | ||
452 | TPM_CAP_FLAG_VOL = 0x9, | ||
453 | TPM_CAP_PROP_OWNER = 0x11, | ||
454 | TPM_CAP_PROP_TIS_TIMEOUT = 0x15, | ||
455 | TPM_CAP_PROP_TIS_DURATION = 0x20, | ||
456 | }; | ||
457 | |||
458 | /* | ||
459 | * This is a semi generic GetCapability command for use | ||
460 | * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG | ||
461 | * and their associated sub_capabilities. | ||
462 | */ | ||
463 | |||
464 | static const u8 tpm_cap[] = { | ||
124 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 465 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
125 | 0, 0, 0, 22, /* length */ | 466 | 0, 0, 0, 22, /* length */ |
126 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | 467 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ |
127 | 0, 0, 0, 5, | 468 | 0, 0, 0, 0, /* TPM_CAP_<TYPE> */ |
128 | 0, 0, 0, 4, | 469 | 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */ |
129 | 0, 0, 1, 1 | 470 | 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */ |
130 | }; | 471 | }; |
131 | 472 | ||
132 | #define READ_PCR_RESULT_SIZE 30 | 473 | static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, |
474 | char *desc) | ||
475 | { | ||
476 | int err; | ||
477 | |||
478 | len = tpm_transmit(chip, data, len); | ||
479 | if (len < 0) | ||
480 | return len; | ||
481 | if (len == TPM_ERROR_SIZE) { | ||
482 | err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); | ||
483 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | ||
484 | return err; | ||
485 | } | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | void tpm_gen_interrupt(struct tpm_chip *chip) | ||
490 | { | ||
491 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; | ||
492 | ssize_t rc; | ||
493 | |||
494 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
495 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
496 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; | ||
497 | |||
498 | rc = transmit_cmd(chip, data, sizeof(data), | ||
499 | "attempting to determine the timeouts"); | ||
500 | } | ||
501 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | ||
502 | |||
503 | void tpm_get_timeouts(struct tpm_chip *chip) | ||
504 | { | ||
505 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; | ||
506 | ssize_t rc; | ||
507 | u32 timeout; | ||
508 | |||
509 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
510 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
511 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; | ||
512 | |||
513 | rc = transmit_cmd(chip, data, sizeof(data), | ||
514 | "attempting to determine the timeouts"); | ||
515 | if (rc) | ||
516 | goto duration; | ||
517 | |||
518 | if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) | ||
519 | != 4 * sizeof(u32)) | ||
520 | goto duration; | ||
521 | |||
522 | /* Don't overwrite default if value is 0 */ | ||
523 | timeout = | ||
524 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); | ||
525 | if (timeout) | ||
526 | chip->vendor.timeout_a = msecs_to_jiffies(timeout); | ||
527 | timeout = | ||
528 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); | ||
529 | if (timeout) | ||
530 | chip->vendor.timeout_b = msecs_to_jiffies(timeout); | ||
531 | timeout = | ||
532 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); | ||
533 | if (timeout) | ||
534 | chip->vendor.timeout_c = msecs_to_jiffies(timeout); | ||
535 | timeout = | ||
536 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); | ||
537 | if (timeout) | ||
538 | chip->vendor.timeout_d = msecs_to_jiffies(timeout); | ||
539 | |||
540 | duration: | ||
541 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
542 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
543 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; | ||
544 | |||
545 | rc = transmit_cmd(chip, data, sizeof(data), | ||
546 | "attempting to determine the durations"); | ||
547 | if (rc) | ||
548 | return; | ||
549 | |||
550 | if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) | ||
551 | != 3 * sizeof(u32)) | ||
552 | return; | ||
553 | |||
554 | chip->vendor.duration[TPM_SHORT] = | ||
555 | msecs_to_jiffies(be32_to_cpu | ||
556 | (*((__be32 *) (data + | ||
557 | TPM_GET_CAP_RET_UINT32_1_IDX)))); | ||
558 | chip->vendor.duration[TPM_MEDIUM] = | ||
559 | msecs_to_jiffies(be32_to_cpu | ||
560 | (*((__be32 *) (data + | ||
561 | TPM_GET_CAP_RET_UINT32_2_IDX)))); | ||
562 | chip->vendor.duration[TPM_LONG] = | ||
563 | msecs_to_jiffies(be32_to_cpu | ||
564 | (*((__be32 *) (data + | ||
565 | TPM_GET_CAP_RET_UINT32_3_IDX)))); | ||
566 | } | ||
567 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); | ||
568 | |||
569 | void tpm_continue_selftest(struct tpm_chip *chip) | ||
570 | { | ||
571 | u8 data[] = { | ||
572 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
573 | 0, 0, 0, 10, /* length */ | ||
574 | 0, 0, 0, 83, /* TPM_ORD_GetCapability */ | ||
575 | }; | ||
576 | |||
577 | tpm_transmit(chip, data, sizeof(data)); | ||
578 | } | ||
579 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | ||
580 | |||
581 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | ||
582 | char *buf) | ||
583 | { | ||
584 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; | ||
585 | ssize_t rc; | ||
586 | |||
587 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
588 | if (chip == NULL) | ||
589 | return -ENODEV; | ||
590 | |||
591 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
592 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
593 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | ||
594 | |||
595 | rc = transmit_cmd(chip, data, sizeof(data), | ||
596 | "attemtping to determine the permanent state"); | ||
597 | if (rc) | ||
598 | return 0; | ||
599 | return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); | ||
600 | } | ||
601 | EXPORT_SYMBOL_GPL(tpm_show_enabled); | ||
602 | |||
603 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, | ||
604 | char *buf) | ||
605 | { | ||
606 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; | ||
607 | ssize_t rc; | ||
608 | |||
609 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
610 | if (chip == NULL) | ||
611 | return -ENODEV; | ||
612 | |||
613 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
614 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
615 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | ||
616 | |||
617 | rc = transmit_cmd(chip, data, sizeof(data), | ||
618 | "attemtping to determine the permanent state"); | ||
619 | if (rc) | ||
620 | return 0; | ||
621 | return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); | ||
622 | } | ||
623 | EXPORT_SYMBOL_GPL(tpm_show_active); | ||
624 | |||
625 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, | ||
626 | char *buf) | ||
627 | { | ||
628 | u8 data[sizeof(tpm_cap)]; | ||
629 | ssize_t rc; | ||
630 | |||
631 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
632 | if (chip == NULL) | ||
633 | return -ENODEV; | ||
634 | |||
635 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
636 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
637 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; | ||
638 | |||
639 | rc = transmit_cmd(chip, data, sizeof(data), | ||
640 | "attempting to determine the owner state"); | ||
641 | if (rc) | ||
642 | return 0; | ||
643 | return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); | ||
644 | } | ||
645 | EXPORT_SYMBOL_GPL(tpm_show_owned); | ||
646 | |||
647 | ssize_t tpm_show_temp_deactivated(struct device * dev, | ||
648 | struct device_attribute * attr, char *buf) | ||
649 | { | ||
650 | u8 data[sizeof(tpm_cap)]; | ||
651 | ssize_t rc; | ||
652 | |||
653 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
654 | if (chip == NULL) | ||
655 | return -ENODEV; | ||
656 | |||
657 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
658 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
659 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; | ||
660 | |||
661 | rc = transmit_cmd(chip, data, sizeof(data), | ||
662 | "attempting to determine the temporary state"); | ||
663 | if (rc) | ||
664 | return 0; | ||
665 | return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); | ||
666 | } | ||
667 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); | ||
668 | |||
133 | static const u8 pcrread[] = { | 669 | static const u8 pcrread[] = { |
134 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 670 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
135 | 0, 0, 0, 14, /* length */ | 671 | 0, 0, 0, 14, /* length */ |
@@ -140,8 +676,8 @@ static const u8 pcrread[] = { | |||
140 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | 676 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, |
141 | char *buf) | 677 | char *buf) |
142 | { | 678 | { |
143 | u8 data[READ_PCR_RESULT_SIZE]; | 679 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; |
144 | ssize_t len; | 680 | ssize_t rc; |
145 | int i, j, num_pcrs; | 681 | int i, j, num_pcrs; |
146 | __be32 index; | 682 | __be32 index; |
147 | char *str = buf; | 683 | char *str = buf; |
@@ -150,29 +686,24 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | |||
150 | if (chip == NULL) | 686 | if (chip == NULL) |
151 | return -ENODEV; | 687 | return -ENODEV; |
152 | 688 | ||
153 | memcpy(data, cap_pcr, sizeof(cap_pcr)); | 689 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
154 | if ((len = tpm_transmit(chip, data, sizeof(data))) | 690 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
155 | < CAP_PCR_RESULT_SIZE) { | 691 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; |
156 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | 692 | |
157 | "attempting to determine the number of PCRS\n", | 693 | rc = transmit_cmd(chip, data, sizeof(data), |
158 | be32_to_cpu(*((__be32 *) (data + 6)))); | 694 | "attempting to determine the number of PCRS"); |
695 | if (rc) | ||
159 | return 0; | 696 | return 0; |
160 | } | ||
161 | 697 | ||
162 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); | 698 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); |
163 | |||
164 | for (i = 0; i < num_pcrs; i++) { | 699 | for (i = 0; i < num_pcrs; i++) { |
165 | memcpy(data, pcrread, sizeof(pcrread)); | 700 | memcpy(data, pcrread, sizeof(pcrread)); |
166 | index = cpu_to_be32(i); | 701 | index = cpu_to_be32(i); |
167 | memcpy(data + 10, &index, 4); | 702 | memcpy(data + 10, &index, 4); |
168 | if ((len = tpm_transmit(chip, data, sizeof(data))) | 703 | rc = transmit_cmd(chip, data, sizeof(data), |
169 | < READ_PCR_RESULT_SIZE){ | 704 | "attempting to read a PCR"); |
170 | dev_dbg(chip->dev, "A TPM error (%d) occurred" | 705 | if (rc) |
171 | " attempting to read PCR %d of %d\n", | ||
172 | be32_to_cpu(*((__be32 *) (data + 6))), | ||
173 | i, num_pcrs); | ||
174 | goto out; | 706 | goto out; |
175 | } | ||
176 | str += sprintf(str, "PCR-%02d: ", i); | 707 | str += sprintf(str, "PCR-%02d: ", i); |
177 | for (j = 0; j < TPM_DIGEST_SIZE; j++) | 708 | for (j = 0; j < TPM_DIGEST_SIZE; j++) |
178 | str += sprintf(str, "%02X ", *(data + 10 + j)); | 709 | str += sprintf(str, "%02X ", *(data + 10 + j)); |
@@ -194,7 +725,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
194 | char *buf) | 725 | char *buf) |
195 | { | 726 | { |
196 | u8 *data; | 727 | u8 *data; |
197 | ssize_t len; | 728 | ssize_t err; |
198 | int i, rc; | 729 | int i, rc; |
199 | char *str = buf; | 730 | char *str = buf; |
200 | 731 | ||
@@ -208,14 +739,10 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
208 | 739 | ||
209 | memcpy(data, readpubek, sizeof(readpubek)); | 740 | memcpy(data, readpubek, sizeof(readpubek)); |
210 | 741 | ||
211 | if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) < | 742 | err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, |
212 | READ_PUBEK_RESULT_SIZE) { | 743 | "attempting to read the PUBEK"); |
213 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | 744 | if (err) |
214 | "attempting to read the PUBEK\n", | ||
215 | be32_to_cpu(*((__be32 *) (data + 6)))); | ||
216 | rc = 0; | ||
217 | goto out; | 745 | goto out; |
218 | } | ||
219 | 746 | ||
220 | /* | 747 | /* |
221 | ignore header 10 bytes | 748 | ignore header 10 bytes |
@@ -245,67 +772,110 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
245 | if ((i + 1) % 16 == 0) | 772 | if ((i + 1) % 16 == 0) |
246 | str += sprintf(str, "\n"); | 773 | str += sprintf(str, "\n"); |
247 | } | 774 | } |
248 | rc = str - buf; | ||
249 | out: | 775 | out: |
776 | rc = str - buf; | ||
250 | kfree(data); | 777 | kfree(data); |
251 | return rc; | 778 | return rc; |
252 | } | 779 | } |
253 | EXPORT_SYMBOL_GPL(tpm_show_pubek); | 780 | EXPORT_SYMBOL_GPL(tpm_show_pubek); |
254 | 781 | ||
255 | #define CAP_VER_RESULT_SIZE 18 | 782 | #define CAP_VERSION_1_1 6 |
783 | #define CAP_VERSION_1_2 0x1A | ||
784 | #define CAP_VERSION_IDX 13 | ||
256 | static const u8 cap_version[] = { | 785 | static const u8 cap_version[] = { |
257 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 786 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
258 | 0, 0, 0, 18, /* length */ | 787 | 0, 0, 0, 18, /* length */ |
259 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | 788 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ |
260 | 0, 0, 0, 6, | 789 | 0, 0, 0, 0, |
261 | 0, 0, 0, 0 | 790 | 0, 0, 0, 0 |
262 | }; | 791 | }; |
263 | 792 | ||
264 | #define CAP_MANUFACTURER_RESULT_SIZE 18 | ||
265 | static const u8 cap_manufacturer[] = { | ||
266 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
267 | 0, 0, 0, 22, /* length */ | ||
268 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | ||
269 | 0, 0, 0, 5, | ||
270 | 0, 0, 0, 4, | ||
271 | 0, 0, 1, 3 | ||
272 | }; | ||
273 | |||
274 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | 793 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, |
275 | char *buf) | 794 | char *buf) |
276 | { | 795 | { |
277 | u8 data[sizeof(cap_manufacturer)]; | 796 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; |
278 | ssize_t len; | 797 | ssize_t rc; |
279 | char *str = buf; | 798 | char *str = buf; |
280 | 799 | ||
281 | struct tpm_chip *chip = dev_get_drvdata(dev); | 800 | struct tpm_chip *chip = dev_get_drvdata(dev); |
282 | if (chip == NULL) | 801 | if (chip == NULL) |
283 | return -ENODEV; | 802 | return -ENODEV; |
284 | 803 | ||
285 | memcpy(data, cap_manufacturer, sizeof(cap_manufacturer)); | 804 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
805 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
806 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | ||
286 | 807 | ||
287 | if ((len = tpm_transmit(chip, data, sizeof(data))) < | 808 | rc = transmit_cmd(chip, data, sizeof(data), |
288 | CAP_MANUFACTURER_RESULT_SIZE) | 809 | "attempting to determine the manufacturer"); |
289 | return len; | 810 | if (rc) |
811 | return 0; | ||
290 | 812 | ||
291 | str += sprintf(str, "Manufacturer: 0x%x\n", | 813 | str += sprintf(str, "Manufacturer: 0x%x\n", |
292 | be32_to_cpu(*((__be32 *) (data + 14)))); | 814 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); |
293 | 815 | ||
294 | memcpy(data, cap_version, sizeof(cap_version)); | 816 | memcpy(data, cap_version, sizeof(cap_version)); |
817 | data[CAP_VERSION_IDX] = CAP_VERSION_1_1; | ||
818 | rc = transmit_cmd(chip, data, sizeof(data), | ||
819 | "attempting to determine the 1.1 version"); | ||
820 | if (rc) | ||
821 | goto out; | ||
295 | 822 | ||
296 | if ((len = tpm_transmit(chip, data, sizeof(data))) < | 823 | str += sprintf(str, |
297 | CAP_VER_RESULT_SIZE) | 824 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
298 | return len; | 825 | (int) data[14], (int) data[15], (int) data[16], |
299 | 826 | (int) data[17]); | |
300 | str += | ||
301 | sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", | ||
302 | (int) data[14], (int) data[15], (int) data[16], | ||
303 | (int) data[17]); | ||
304 | 827 | ||
828 | out: | ||
305 | return str - buf; | 829 | return str - buf; |
306 | } | 830 | } |
307 | EXPORT_SYMBOL_GPL(tpm_show_caps); | 831 | EXPORT_SYMBOL_GPL(tpm_show_caps); |
308 | 832 | ||
833 | ssize_t tpm_show_caps_1_2(struct device * dev, | ||
834 | struct device_attribute * attr, char *buf) | ||
835 | { | ||
836 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; | ||
837 | ssize_t len; | ||
838 | char *str = buf; | ||
839 | |||
840 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
841 | if (chip == NULL) | ||
842 | return -ENODEV; | ||
843 | |||
844 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
845 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
846 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | ||
847 | |||
848 | if ((len = tpm_transmit(chip, data, sizeof(data))) <= | ||
849 | TPM_ERROR_SIZE) { | ||
850 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | ||
851 | "attempting to determine the manufacturer\n", | ||
852 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | str += sprintf(str, "Manufacturer: 0x%x\n", | ||
857 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); | ||
858 | |||
859 | memcpy(data, cap_version, sizeof(cap_version)); | ||
860 | data[CAP_VERSION_IDX] = CAP_VERSION_1_2; | ||
861 | |||
862 | if ((len = tpm_transmit(chip, data, sizeof(data))) <= | ||
863 | TPM_ERROR_SIZE) { | ||
864 | dev_err(chip->dev, "A TPM error (%d) occurred " | ||
865 | "attempting to determine the 1.2 version\n", | ||
866 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | ||
867 | goto out; | ||
868 | } | ||
869 | str += sprintf(str, | ||
870 | "TCG version: %d.%d\nFirmware version: %d.%d\n", | ||
871 | (int) data[16], (int) data[17], (int) data[18], | ||
872 | (int) data[19]); | ||
873 | |||
874 | out: | ||
875 | return str - buf; | ||
876 | } | ||
877 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); | ||
878 | |||
309 | ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | 879 | ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, |
310 | const char *buf, size_t count) | 880 | const char *buf, size_t count) |
311 | { | 881 | { |
@@ -313,7 +883,7 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | |||
313 | if (chip == NULL) | 883 | if (chip == NULL) |
314 | return 0; | 884 | return 0; |
315 | 885 | ||
316 | chip->vendor->cancel(chip); | 886 | chip->vendor.cancel(chip); |
317 | return count; | 887 | return count; |
318 | } | 888 | } |
319 | EXPORT_SYMBOL_GPL(tpm_store_cancel); | 889 | EXPORT_SYMBOL_GPL(tpm_store_cancel); |
@@ -329,7 +899,7 @@ int tpm_open(struct inode *inode, struct file *file) | |||
329 | spin_lock(&driver_lock); | 899 | spin_lock(&driver_lock); |
330 | 900 | ||
331 | list_for_each_entry(pos, &tpm_chip_list, list) { | 901 | list_for_each_entry(pos, &tpm_chip_list, list) { |
332 | if (pos->vendor->miscdev.minor == minor) { | 902 | if (pos->vendor.miscdev.minor == minor) { |
333 | chip = pos; | 903 | chip = pos; |
334 | break; | 904 | break; |
335 | } | 905 | } |
@@ -387,7 +957,7 @@ int tpm_release(struct inode *inode, struct file *file) | |||
387 | EXPORT_SYMBOL_GPL(tpm_release); | 957 | EXPORT_SYMBOL_GPL(tpm_release); |
388 | 958 | ||
389 | ssize_t tpm_write(struct file *file, const char __user *buf, | 959 | ssize_t tpm_write(struct file *file, const char __user *buf, |
390 | size_t size, loff_t * off) | 960 | size_t size, loff_t *off) |
391 | { | 961 | { |
392 | struct tpm_chip *chip = file->private_data; | 962 | struct tpm_chip *chip = file->private_data; |
393 | int in_size = size, out_size; | 963 | int in_size = size, out_size; |
@@ -419,11 +989,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf, | |||
419 | 989 | ||
420 | return in_size; | 990 | return in_size; |
421 | } | 991 | } |
422 | |||
423 | EXPORT_SYMBOL_GPL(tpm_write); | 992 | EXPORT_SYMBOL_GPL(tpm_write); |
424 | 993 | ||
425 | ssize_t tpm_read(struct file * file, char __user *buf, | 994 | ssize_t tpm_read(struct file *file, char __user *buf, |
426 | size_t size, loff_t * off) | 995 | size_t size, loff_t *off) |
427 | { | 996 | { |
428 | struct tpm_chip *chip = file->private_data; | 997 | struct tpm_chip *chip = file->private_data; |
429 | int ret_size; | 998 | int ret_size; |
@@ -462,14 +1031,13 @@ void tpm_remove_hardware(struct device *dev) | |||
462 | spin_unlock(&driver_lock); | 1031 | spin_unlock(&driver_lock); |
463 | 1032 | ||
464 | dev_set_drvdata(dev, NULL); | 1033 | dev_set_drvdata(dev, NULL); |
465 | misc_deregister(&chip->vendor->miscdev); | 1034 | misc_deregister(&chip->vendor.miscdev); |
466 | kfree(chip->vendor->miscdev.name); | 1035 | kfree(chip->vendor.miscdev.name); |
467 | 1036 | ||
468 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); | 1037 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); |
469 | tpm_bios_log_teardown(chip->bios_dir); | 1038 | tpm_bios_log_teardown(chip->bios_dir); |
470 | 1039 | ||
471 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= | 1040 | clear_bit(chip->dev_num, dev_mask); |
472 | ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); | ||
473 | 1041 | ||
474 | kfree(chip); | 1042 | kfree(chip); |
475 | 1043 | ||
@@ -520,18 +1088,18 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); | |||
520 | * upon errant exit from this function specific probe function should call | 1088 | * upon errant exit from this function specific probe function should call |
521 | * pci_disable_device | 1089 | * pci_disable_device |
522 | */ | 1090 | */ |
523 | int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) | 1091 | struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific |
1092 | *entry) | ||
524 | { | 1093 | { |
525 | #define DEVNAME_SIZE 7 | 1094 | #define DEVNAME_SIZE 7 |
526 | 1095 | ||
527 | char *devname; | 1096 | char *devname; |
528 | struct tpm_chip *chip; | 1097 | struct tpm_chip *chip; |
529 | int i, j; | ||
530 | 1098 | ||
531 | /* Driver specific per-device data */ | 1099 | /* Driver specific per-device data */ |
532 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1100 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
533 | if (chip == NULL) | 1101 | if (chip == NULL) |
534 | return -ENOMEM; | 1102 | return NULL; |
535 | 1103 | ||
536 | init_MUTEX(&chip->buffer_mutex); | 1104 | init_MUTEX(&chip->buffer_mutex); |
537 | init_MUTEX(&chip->tpm_mutex); | 1105 | init_MUTEX(&chip->tpm_mutex); |
@@ -543,45 +1111,37 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) | |||
543 | chip->user_read_timer.function = user_reader_timeout; | 1111 | chip->user_read_timer.function = user_reader_timeout; |
544 | chip->user_read_timer.data = (unsigned long) chip; | 1112 | chip->user_read_timer.data = (unsigned long) chip; |
545 | 1113 | ||
546 | chip->vendor = entry; | 1114 | memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); |
547 | |||
548 | chip->dev_num = -1; | ||
549 | 1115 | ||
550 | for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++) | 1116 | chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); |
551 | for (j = 0; j < 8 * sizeof(int); j++) | ||
552 | if ((dev_mask[i] & (1 << j)) == 0) { | ||
553 | chip->dev_num = | ||
554 | i * TPM_NUM_MASK_ENTRIES + j; | ||
555 | dev_mask[i] |= 1 << j; | ||
556 | goto dev_num_search_complete; | ||
557 | } | ||
558 | 1117 | ||
559 | dev_num_search_complete: | 1118 | if (chip->dev_num >= TPM_NUM_DEVICES) { |
560 | if (chip->dev_num < 0) { | ||
561 | dev_err(dev, "No available tpm device numbers\n"); | 1119 | dev_err(dev, "No available tpm device numbers\n"); |
562 | kfree(chip); | 1120 | kfree(chip); |
563 | return -ENODEV; | 1121 | return NULL; |
564 | } else if (chip->dev_num == 0) | 1122 | } else if (chip->dev_num == 0) |
565 | chip->vendor->miscdev.minor = TPM_MINOR; | 1123 | chip->vendor.miscdev.minor = TPM_MINOR; |
566 | else | 1124 | else |
567 | chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR; | 1125 | chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; |
1126 | |||
1127 | set_bit(chip->dev_num, dev_mask); | ||
568 | 1128 | ||
569 | devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); | 1129 | devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); |
570 | scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); | 1130 | scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); |
571 | chip->vendor->miscdev.name = devname; | 1131 | chip->vendor.miscdev.name = devname; |
572 | 1132 | ||
573 | chip->vendor->miscdev.dev = dev; | 1133 | chip->vendor.miscdev.dev = dev; |
574 | chip->dev = get_device(dev); | 1134 | chip->dev = get_device(dev); |
575 | 1135 | ||
576 | if (misc_register(&chip->vendor->miscdev)) { | 1136 | if (misc_register(&chip->vendor.miscdev)) { |
577 | dev_err(chip->dev, | 1137 | dev_err(chip->dev, |
578 | "unable to misc_register %s, minor %d\n", | 1138 | "unable to misc_register %s, minor %d\n", |
579 | chip->vendor->miscdev.name, | 1139 | chip->vendor.miscdev.name, |
580 | chip->vendor->miscdev.minor); | 1140 | chip->vendor.miscdev.minor); |
581 | put_device(dev); | 1141 | put_device(dev); |
1142 | clear_bit(chip->dev_num, dev_mask); | ||
582 | kfree(chip); | 1143 | kfree(chip); |
583 | dev_mask[i] &= !(1 << j); | 1144 | return NULL; |
584 | return -ENODEV; | ||
585 | } | 1145 | } |
586 | 1146 | ||
587 | spin_lock(&driver_lock); | 1147 | spin_lock(&driver_lock); |
@@ -592,11 +1152,11 @@ dev_num_search_complete: | |||
592 | 1152 | ||
593 | spin_unlock(&driver_lock); | 1153 | spin_unlock(&driver_lock); |
594 | 1154 | ||
595 | sysfs_create_group(&dev->kobj, chip->vendor->attr_group); | 1155 | sysfs_create_group(&dev->kobj, chip->vendor.attr_group); |
596 | 1156 | ||
597 | chip->bios_dir = tpm_bios_log_setup(devname); | 1157 | chip->bios_dir = tpm_bios_log_setup(devname); |
598 | 1158 | ||
599 | return 0; | 1159 | return chip; |
600 | } | 1160 | } |
601 | EXPORT_SYMBOL_GPL(tpm_register_hardware); | 1161 | EXPORT_SYMBOL_GPL(tpm_register_hardware); |
602 | 1162 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index dec0224b4478..54a4c804e25f 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -42,18 +42,30 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, | |||
42 | char *); | 42 | char *); |
43 | extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, | 43 | extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, |
44 | char *); | 44 | char *); |
45 | extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr, | ||
46 | char *); | ||
45 | extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, | 47 | extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, |
46 | const char *, size_t); | 48 | const char *, size_t); |
49 | extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr, | ||
50 | char *); | ||
51 | extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr, | ||
52 | char *); | ||
53 | extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr, | ||
54 | char *); | ||
55 | extern ssize_t tpm_show_temp_deactivated(struct device *, | ||
56 | struct device_attribute *attr, char *); | ||
47 | 57 | ||
48 | struct tpm_chip; | 58 | struct tpm_chip; |
49 | 59 | ||
50 | struct tpm_vendor_specific { | 60 | struct tpm_vendor_specific { |
51 | u8 req_complete_mask; | 61 | const u8 req_complete_mask; |
52 | u8 req_complete_val; | 62 | const u8 req_complete_val; |
53 | u8 req_canceled; | 63 | const u8 req_canceled; |
54 | void __iomem *iobase; /* ioremapped address */ | 64 | void __iomem *iobase; /* ioremapped address */ |
55 | unsigned long base; /* TPM base address */ | 65 | unsigned long base; /* TPM base address */ |
56 | 66 | ||
67 | int irq; | ||
68 | |||
57 | int region_size; | 69 | int region_size; |
58 | int have_region; | 70 | int have_region; |
59 | 71 | ||
@@ -63,6 +75,13 @@ struct tpm_vendor_specific { | |||
63 | u8 (*status) (struct tpm_chip *); | 75 | u8 (*status) (struct tpm_chip *); |
64 | struct miscdevice miscdev; | 76 | struct miscdevice miscdev; |
65 | struct attribute_group *attr_group; | 77 | struct attribute_group *attr_group; |
78 | struct list_head list; | ||
79 | int locality; | ||
80 | unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ | ||
81 | unsigned long duration[3]; /* jiffies */ | ||
82 | |||
83 | wait_queue_head_t read_queue; | ||
84 | wait_queue_head_t int_queue; | ||
66 | }; | 85 | }; |
67 | 86 | ||
68 | struct tpm_chip { | 87 | struct tpm_chip { |
@@ -81,13 +100,15 @@ struct tpm_chip { | |||
81 | struct work_struct work; | 100 | struct work_struct work; |
82 | struct semaphore tpm_mutex; /* tpm is processing */ | 101 | struct semaphore tpm_mutex; /* tpm is processing */ |
83 | 102 | ||
84 | struct tpm_vendor_specific *vendor; | 103 | struct tpm_vendor_specific vendor; |
85 | 104 | ||
86 | struct dentry **bios_dir; | 105 | struct dentry **bios_dir; |
87 | 106 | ||
88 | struct list_head list; | 107 | struct list_head list; |
89 | }; | 108 | }; |
90 | 109 | ||
110 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) | ||
111 | |||
91 | static inline int tpm_read_index(int base, int index) | 112 | static inline int tpm_read_index(int base, int index) |
92 | { | 113 | { |
93 | outb(index, base); | 114 | outb(index, base); |
@@ -100,8 +121,12 @@ static inline void tpm_write_index(int base, int index, int value) | |||
100 | outb(value & 0xFF, base+1); | 121 | outb(value & 0xFF, base+1); |
101 | } | 122 | } |
102 | 123 | ||
103 | extern int tpm_register_hardware(struct device *, | 124 | extern void tpm_get_timeouts(struct tpm_chip *); |
104 | struct tpm_vendor_specific *); | 125 | extern void tpm_gen_interrupt(struct tpm_chip *); |
126 | extern void tpm_continue_selftest(struct tpm_chip *); | ||
127 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); | ||
128 | extern struct tpm_chip* tpm_register_hardware(struct device *, | ||
129 | const struct tpm_vendor_specific *); | ||
105 | extern int tpm_open(struct inode *, struct file *); | 130 | extern int tpm_open(struct inode *, struct file *); |
106 | extern int tpm_release(struct inode *, struct file *); | 131 | extern int tpm_release(struct inode *, struct file *); |
107 | extern ssize_t tpm_write(struct file *, const char __user *, size_t, | 132 | extern ssize_t tpm_write(struct file *, const char __user *, size_t, |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index ff3654964fe3..58a258cec153 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
47 | return -EIO; | 47 | return -EIO; |
48 | 48 | ||
49 | for (i = 0; i < 6; i++) { | 49 | for (i = 0; i < 6; i++) { |
50 | status = ioread8(chip->vendor->iobase + 1); | 50 | status = ioread8(chip->vendor.iobase + 1); |
51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
52 | dev_err(chip->dev, "error reading header\n"); | 52 | dev_err(chip->dev, "error reading header\n"); |
53 | return -EIO; | 53 | return -EIO; |
54 | } | 54 | } |
55 | *buf++ = ioread8(chip->vendor->iobase); | 55 | *buf++ = ioread8(chip->vendor.iobase); |
56 | } | 56 | } |
57 | 57 | ||
58 | /* size of the data received */ | 58 | /* size of the data received */ |
@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
63 | dev_err(chip->dev, | 63 | dev_err(chip->dev, |
64 | "Recv size(%d) less than available space\n", size); | 64 | "Recv size(%d) less than available space\n", size); |
65 | for (; i < size; i++) { /* clear the waiting data anyway */ | 65 | for (; i < size; i++) { /* clear the waiting data anyway */ |
66 | status = ioread8(chip->vendor->iobase + 1); | 66 | status = ioread8(chip->vendor.iobase + 1); |
67 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 67 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
68 | dev_err(chip->dev, "error reading data\n"); | 68 | dev_err(chip->dev, "error reading data\n"); |
69 | return -EIO; | 69 | return -EIO; |
@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
74 | 74 | ||
75 | /* read all the data available */ | 75 | /* read all the data available */ |
76 | for (; i < size; i++) { | 76 | for (; i < size; i++) { |
77 | status = ioread8(chip->vendor->iobase + 1); | 77 | status = ioread8(chip->vendor.iobase + 1); |
78 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 78 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
79 | dev_err(chip->dev, "error reading data\n"); | 79 | dev_err(chip->dev, "error reading data\n"); |
80 | return -EIO; | 80 | return -EIO; |
81 | } | 81 | } |
82 | *buf++ = ioread8(chip->vendor->iobase); | 82 | *buf++ = ioread8(chip->vendor.iobase); |
83 | } | 83 | } |
84 | 84 | ||
85 | /* make sure data available is gone */ | 85 | /* make sure data available is gone */ |
86 | status = ioread8(chip->vendor->iobase + 1); | 86 | status = ioread8(chip->vendor.iobase + 1); |
87 | 87 | ||
88 | if (status & ATML_STATUS_DATA_AVAIL) { | 88 | if (status & ATML_STATUS_DATA_AVAIL) { |
89 | dev_err(chip->dev, "data available is stuck\n"); | 89 | dev_err(chip->dev, "data available is stuck\n"); |
@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
100 | dev_dbg(chip->dev, "tpm_atml_send:\n"); | 100 | dev_dbg(chip->dev, "tpm_atml_send:\n"); |
101 | for (i = 0; i < count; i++) { | 101 | for (i = 0; i < count; i++) { |
102 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); | 102 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); |
103 | iowrite8(buf[i], chip->vendor->iobase); | 103 | iowrite8(buf[i], chip->vendor.iobase); |
104 | } | 104 | } |
105 | 105 | ||
106 | return count; | 106 | return count; |
@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
108 | 108 | ||
109 | static void tpm_atml_cancel(struct tpm_chip *chip) | 109 | static void tpm_atml_cancel(struct tpm_chip *chip) |
110 | { | 110 | { |
111 | iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1); | 111 | iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1); |
112 | } | 112 | } |
113 | 113 | ||
114 | static u8 tpm_atml_status(struct tpm_chip *chip) | 114 | static u8 tpm_atml_status(struct tpm_chip *chip) |
115 | { | 115 | { |
116 | return ioread8(chip->vendor->iobase + 1); | 116 | return ioread8(chip->vendor.iobase + 1); |
117 | } | 117 | } |
118 | 118 | ||
119 | static struct file_operations atmel_ops = { | 119 | static struct file_operations atmel_ops = { |
@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] = { | |||
140 | 140 | ||
141 | static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; | 141 | static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; |
142 | 142 | ||
143 | static struct tpm_vendor_specific tpm_atmel = { | 143 | static const struct tpm_vendor_specific tpm_atmel = { |
144 | .recv = tpm_atml_recv, | 144 | .recv = tpm_atml_recv, |
145 | .send = tpm_atml_send, | 145 | .send = tpm_atml_send, |
146 | .cancel = tpm_atml_cancel, | 146 | .cancel = tpm_atml_cancel, |
@@ -159,10 +159,10 @@ static void atml_plat_remove(void) | |||
159 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); | 159 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); |
160 | 160 | ||
161 | if (chip) { | 161 | if (chip) { |
162 | if (chip->vendor->have_region) | 162 | if (chip->vendor.have_region) |
163 | atmel_release_region(chip->vendor->base, | 163 | atmel_release_region(chip->vendor.base, |
164 | chip->vendor->region_size); | 164 | chip->vendor.region_size); |
165 | atmel_put_base_addr(chip->vendor); | 165 | atmel_put_base_addr(chip->vendor.iobase); |
166 | tpm_remove_hardware(chip->dev); | 166 | tpm_remove_hardware(chip->dev); |
167 | platform_device_unregister(pdev); | 167 | platform_device_unregister(pdev); |
168 | } | 168 | } |
@@ -179,18 +179,22 @@ static struct device_driver atml_drv = { | |||
179 | static int __init init_atmel(void) | 179 | static int __init init_atmel(void) |
180 | { | 180 | { |
181 | int rc = 0; | 181 | int rc = 0; |
182 | void __iomem *iobase = NULL; | ||
183 | int have_region, region_size; | ||
184 | unsigned long base; | ||
185 | struct tpm_chip *chip; | ||
182 | 186 | ||
183 | driver_register(&atml_drv); | 187 | driver_register(&atml_drv); |
184 | 188 | ||
185 | if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) { | 189 | if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) { |
186 | rc = -ENODEV; | 190 | rc = -ENODEV; |
187 | goto err_unreg_drv; | 191 | goto err_unreg_drv; |
188 | } | 192 | } |
189 | 193 | ||
190 | tpm_atmel.have_region = | 194 | have_region = |
191 | (atmel_request_region | 195 | (atmel_request_region |
192 | (tpm_atmel.base, tpm_atmel.region_size, | 196 | (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; |
193 | "tpm_atmel0") == NULL) ? 0 : 1; | 197 | |
194 | 198 | ||
195 | if (IS_ERR | 199 | if (IS_ERR |
196 | (pdev = | 200 | (pdev = |
@@ -199,17 +203,25 @@ static int __init init_atmel(void) | |||
199 | goto err_rel_reg; | 203 | goto err_rel_reg; |
200 | } | 204 | } |
201 | 205 | ||
202 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) | 206 | if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) { |
207 | rc = -ENODEV; | ||
203 | goto err_unreg_dev; | 208 | goto err_unreg_dev; |
209 | } | ||
210 | |||
211 | chip->vendor.iobase = iobase; | ||
212 | chip->vendor.base = base; | ||
213 | chip->vendor.have_region = have_region; | ||
214 | chip->vendor.region_size = region_size; | ||
215 | |||
204 | return 0; | 216 | return 0; |
205 | 217 | ||
206 | err_unreg_dev: | 218 | err_unreg_dev: |
207 | platform_device_unregister(pdev); | 219 | platform_device_unregister(pdev); |
208 | err_rel_reg: | 220 | err_rel_reg: |
209 | atmel_put_base_addr(&tpm_atmel); | 221 | atmel_put_base_addr(iobase); |
210 | if (tpm_atmel.have_region) | 222 | if (have_region) |
211 | atmel_release_region(tpm_atmel.base, | 223 | atmel_release_region(base, |
212 | tpm_atmel.region_size); | 224 | region_size); |
213 | err_unreg_drv: | 225 | err_unreg_drv: |
214 | driver_unregister(&atml_drv); | 226 | driver_unregister(&atml_drv); |
215 | return rc; | 227 | return rc; |
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index d3478aaadd77..2e68eeb8a2cd 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h | |||
@@ -28,13 +28,12 @@ | |||
28 | #define atmel_request_region request_mem_region | 28 | #define atmel_request_region request_mem_region |
29 | #define atmel_release_region release_mem_region | 29 | #define atmel_release_region release_mem_region |
30 | 30 | ||
31 | static inline void atmel_put_base_addr(struct tpm_vendor_specific | 31 | static inline void atmel_put_base_addr(void __iomem *iobase) |
32 | *vendor) | ||
33 | { | 32 | { |
34 | iounmap(vendor->iobase); | 33 | iounmap(iobase); |
35 | } | 34 | } |
36 | 35 | ||
37 | static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor) | 36 | static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) |
38 | { | 37 | { |
39 | struct device_node *dn; | 38 | struct device_node *dn; |
40 | unsigned long address, size; | 39 | unsigned long address, size; |
@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor) | |||
71 | else | 70 | else |
72 | size = reg[naddrc]; | 71 | size = reg[naddrc]; |
73 | 72 | ||
74 | vendor->base = address; | 73 | *base = address; |
75 | vendor->region_size = size; | 74 | *region_size = size; |
76 | return ioremap(vendor->base, vendor->region_size); | 75 | return ioremap(*base, *region_size); |
77 | } | 76 | } |
78 | #else | 77 | #else |
79 | #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) | 78 | #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) |
@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void) | |||
106 | return 0; | 105 | return 0; |
107 | } | 106 | } |
108 | 107 | ||
109 | static inline void atmel_put_base_addr(struct tpm_vendor_specific | 108 | static inline void atmel_put_base_addr(void __iomem *iobase) |
110 | *vendor) | ||
111 | { | 109 | { |
112 | } | 110 | } |
113 | 111 | ||
114 | /* Determine where to talk to device */ | 112 | /* Determine where to talk to device */ |
115 | static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific | 113 | static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) |
116 | *vendor) | ||
117 | { | 114 | { |
118 | int lo, hi; | 115 | int lo, hi; |
119 | 116 | ||
@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific | |||
123 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | 120 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); |
124 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | 121 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); |
125 | 122 | ||
126 | vendor->base = (hi << 8) | lo; | 123 | *base = (hi << 8) | lo; |
127 | vendor->region_size = 2; | 124 | *region_size = 2; |
128 | 125 | ||
129 | return ioport_map(vendor->base, vendor->region_size); | 126 | return ioport_map(*base, *region_size); |
130 | } | 127 | } |
131 | #endif | 128 | #endif |
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 537aa45d8c67..e45f0d3d12de 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -29,6 +29,11 @@ | |||
29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | 29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ |
30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | 30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ |
31 | 31 | ||
32 | enum bios_platform_class { | ||
33 | BIOS_CLIENT = 0x00, | ||
34 | BIOS_SERVER = 0x01, | ||
35 | }; | ||
36 | |||
32 | struct tpm_bios_log { | 37 | struct tpm_bios_log { |
33 | void *bios_event_log; | 38 | void *bios_event_log; |
34 | void *bios_event_log_end; | 39 | void *bios_event_log_end; |
@@ -36,9 +41,18 @@ struct tpm_bios_log { | |||
36 | 41 | ||
37 | struct acpi_tcpa { | 42 | struct acpi_tcpa { |
38 | struct acpi_table_header hdr; | 43 | struct acpi_table_header hdr; |
39 | u16 reserved; | 44 | u16 platform_class; |
40 | u32 log_max_len __attribute__ ((packed)); | 45 | union { |
41 | u32 log_start_addr __attribute__ ((packed)); | 46 | struct client_hdr { |
47 | u32 log_max_len __attribute__ ((packed)); | ||
48 | u64 log_start_addr __attribute__ ((packed)); | ||
49 | } client; | ||
50 | struct server_hdr { | ||
51 | u16 reserved; | ||
52 | u64 log_max_len __attribute__ ((packed)); | ||
53 | u64 log_start_addr __attribute__ ((packed)); | ||
54 | } server; | ||
55 | }; | ||
42 | }; | 56 | }; |
43 | 57 | ||
44 | struct tcpa_event { | 58 | struct tcpa_event { |
@@ -120,6 +134,7 @@ static const char* tcpa_pc_event_id_strings[] = { | |||
120 | "S-CRTM Version", | 134 | "S-CRTM Version", |
121 | "S-CRTM Contents", | 135 | "S-CRTM Contents", |
122 | "S-CRTM POST Contents", | 136 | "S-CRTM POST Contents", |
137 | "POST Contents", | ||
123 | }; | 138 | }; |
124 | 139 | ||
125 | /* returns pointer to start of pos. entry of tcg log */ | 140 | /* returns pointer to start of pos. entry of tcg log */ |
@@ -306,6 +321,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) | |||
306 | /* 5th: delimiter */ | 321 | /* 5th: delimiter */ |
307 | seq_putc(m, '\0'); | 322 | seq_putc(m, '\0'); |
308 | 323 | ||
324 | kfree(eventname); | ||
309 | return 0; | 325 | return 0; |
310 | } | 326 | } |
311 | 327 | ||
@@ -353,6 +369,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | |||
353 | /* 4th: eventname <= max + \'0' delimiter */ | 369 | /* 4th: eventname <= max + \'0' delimiter */ |
354 | seq_printf(m, " %s\n", eventname); | 370 | seq_printf(m, " %s\n", eventname); |
355 | 371 | ||
372 | kfree(eventname); | ||
356 | return 0; | 373 | return 0; |
357 | } | 374 | } |
358 | 375 | ||
@@ -376,6 +393,7 @@ static int read_log(struct tpm_bios_log *log) | |||
376 | struct acpi_tcpa *buff; | 393 | struct acpi_tcpa *buff; |
377 | acpi_status status; | 394 | acpi_status status; |
378 | struct acpi_table_header *virt; | 395 | struct acpi_table_header *virt; |
396 | u64 len, start; | ||
379 | 397 | ||
380 | if (log->bios_event_log != NULL) { | 398 | if (log->bios_event_log != NULL) { |
381 | printk(KERN_ERR | 399 | printk(KERN_ERR |
@@ -396,27 +414,37 @@ static int read_log(struct tpm_bios_log *log) | |||
396 | return -EIO; | 414 | return -EIO; |
397 | } | 415 | } |
398 | 416 | ||
399 | if (buff->log_max_len == 0) { | 417 | switch(buff->platform_class) { |
418 | case BIOS_SERVER: | ||
419 | len = buff->server.log_max_len; | ||
420 | start = buff->server.log_start_addr; | ||
421 | break; | ||
422 | case BIOS_CLIENT: | ||
423 | default: | ||
424 | len = buff->client.log_max_len; | ||
425 | start = buff->client.log_start_addr; | ||
426 | break; | ||
427 | } | ||
428 | if (!len) { | ||
400 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); | 429 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); |
401 | return -EIO; | 430 | return -EIO; |
402 | } | 431 | } |
403 | 432 | ||
404 | /* malloc EventLog space */ | 433 | /* malloc EventLog space */ |
405 | log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); | 434 | log->bios_event_log = kmalloc(len, GFP_KERNEL); |
406 | if (!log->bios_event_log) { | 435 | if (!log->bios_event_log) { |
407 | printk | 436 | printk("%s: ERROR - Not enough Memory for BIOS measurements\n", |
408 | ("%s: ERROR - Not enough Memory for BIOS measurements\n", | 437 | __func__); |
409 | __func__); | ||
410 | return -ENOMEM; | 438 | return -ENOMEM; |
411 | } | 439 | } |
412 | 440 | ||
413 | log->bios_event_log_end = log->bios_event_log + buff->log_max_len; | 441 | log->bios_event_log_end = log->bios_event_log + len; |
414 | 442 | ||
415 | acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt); | 443 | acpi_os_map_memory(start, len, (void *) &virt); |
416 | 444 | ||
417 | memcpy(log->bios_event_log, virt, buff->log_max_len); | 445 | memcpy(log->bios_event_log, virt, len); |
418 | 446 | ||
419 | acpi_os_unmap_memory(virt, buff->log_max_len); | 447 | acpi_os_unmap_memory(virt, len); |
420 | return 0; | 448 | return 0; |
421 | } | 449 | } |
422 | 450 | ||
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 24095f6ee6da..adfff21beb21 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * License. | 15 | * License. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | ||
18 | #include <linux/pnp.h> | 19 | #include <linux/pnp.h> |
19 | #include "tpm.h" | 20 | #include "tpm.h" |
20 | 21 | ||
@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo) | |||
104 | 105 | ||
105 | if (clear_wrfifo) { | 106 | if (clear_wrfifo) { |
106 | for (i = 0; i < 4096; i++) { | 107 | for (i = 0; i < 4096; i++) { |
107 | status = inb(chip->vendor->base + WRFIFO); | 108 | status = inb(chip->vendor.base + WRFIFO); |
108 | if (status == 0xff) { | 109 | if (status == 0xff) { |
109 | if (check == 5) | 110 | if (check == 5) |
110 | break; | 111 | break; |
@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo) | |||
124 | */ | 125 | */ |
125 | i = 0; | 126 | i = 0; |
126 | do { | 127 | do { |
127 | status = inb(chip->vendor->base + RDFIFO); | 128 | status = inb(chip->vendor.base + RDFIFO); |
128 | status = inb(chip->vendor->base + STAT); | 129 | status = inb(chip->vendor.base + STAT); |
129 | i++; | 130 | i++; |
130 | if (i == TPM_MAX_TRIES) | 131 | if (i == TPM_MAX_TRIES) |
131 | return -EIO; | 132 | return -EIO; |
@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) | |||
138 | int status; | 139 | int status; |
139 | int i; | 140 | int i; |
140 | for (i = 0; i < TPM_MAX_TRIES; i++) { | 141 | for (i = 0; i < TPM_MAX_TRIES; i++) { |
141 | status = inb(chip->vendor->base + STAT); | 142 | status = inb(chip->vendor.base + STAT); |
142 | /* check the status-register if wait_for_bit is set */ | 143 | /* check the status-register if wait_for_bit is set */ |
143 | if (status & 1 << wait_for_bit) | 144 | if (status & 1 << wait_for_bit) |
144 | break; | 145 | break; |
@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) | |||
157 | static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) | 158 | static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) |
158 | { | 159 | { |
159 | wait(chip, STAT_XFE); | 160 | wait(chip, STAT_XFE); |
160 | outb(sendbyte, chip->vendor->base + WRFIFO); | 161 | outb(sendbyte, chip->vendor.base + WRFIFO); |
161 | } | 162 | } |
162 | 163 | ||
163 | /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more | 164 | /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more |
@@ -204,7 +205,7 @@ recv_begin: | |||
204 | ret = wait(chip, STAT_RDA); | 205 | ret = wait(chip, STAT_RDA); |
205 | if (ret) | 206 | if (ret) |
206 | return -EIO; | 207 | return -EIO; |
207 | buf[i] = inb(chip->vendor->base + RDFIFO); | 208 | buf[i] = inb(chip->vendor.base + RDFIFO); |
208 | } | 209 | } |
209 | 210 | ||
210 | if (buf[0] != TPM_VL_VER) { | 211 | if (buf[0] != TPM_VL_VER) { |
@@ -219,7 +220,7 @@ recv_begin: | |||
219 | 220 | ||
220 | for (i = 0; i < size; i++) { | 221 | for (i = 0; i < size; i++) { |
221 | wait(chip, STAT_RDA); | 222 | wait(chip, STAT_RDA); |
222 | buf[i] = inb(chip->vendor->base + RDFIFO); | 223 | buf[i] = inb(chip->vendor.base + RDFIFO); |
223 | } | 224 | } |
224 | 225 | ||
225 | if ((size == 0x6D00) && (buf[1] == 0x80)) { | 226 | if ((size == 0x6D00) && (buf[1] == 0x80)) { |
@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
268 | u8 count_high, count_low, count_4, count_3, count_2, count_1; | 269 | u8 count_high, count_low, count_4, count_3, count_2, count_1; |
269 | 270 | ||
270 | /* Disabling Reset, LP and IRQC */ | 271 | /* Disabling Reset, LP and IRQC */ |
271 | outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD); | 272 | outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD); |
272 | 273 | ||
273 | ret = empty_fifo(chip, 1); | 274 | ret = empty_fifo(chip, 1); |
274 | if (ret) { | 275 | if (ret) { |
@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip) | |||
319 | 320 | ||
320 | static u8 tpm_inf_status(struct tpm_chip *chip) | 321 | static u8 tpm_inf_status(struct tpm_chip *chip) |
321 | { | 322 | { |
322 | return inb(chip->vendor->base + STAT); | 323 | return inb(chip->vendor.base + STAT); |
323 | } | 324 | } |
324 | 325 | ||
325 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | 326 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); |
@@ -346,7 +347,7 @@ static struct file_operations inf_ops = { | |||
346 | .release = tpm_release, | 347 | .release = tpm_release, |
347 | }; | 348 | }; |
348 | 349 | ||
349 | static struct tpm_vendor_specific tpm_inf = { | 350 | static const struct tpm_vendor_specific tpm_inf = { |
350 | .recv = tpm_inf_recv, | 351 | .recv = tpm_inf_recv, |
351 | .send = tpm_inf_send, | 352 | .send = tpm_inf_send, |
352 | .cancel = tpm_inf_cancel, | 353 | .cancel = tpm_inf_cancel, |
@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
375 | int version[2]; | 376 | int version[2]; |
376 | int productid[2]; | 377 | int productid[2]; |
377 | char chipname[20]; | 378 | char chipname[20]; |
379 | struct tpm_chip *chip; | ||
378 | 380 | ||
379 | /* read IO-ports through PnP */ | 381 | /* read IO-ports through PnP */ |
380 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && | 382 | if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && |
@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
395 | goto err_last; | 397 | goto err_last; |
396 | } | 398 | } |
397 | /* publish my base address and request region */ | 399 | /* publish my base address and request region */ |
398 | tpm_inf.base = TPM_INF_BASE; | ||
399 | if (request_region | 400 | if (request_region |
400 | (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { | 401 | (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { |
401 | rc = -EINVAL; | 402 | rc = -EINVAL; |
402 | goto err_last; | 403 | goto err_last; |
403 | } | 404 | } |
404 | if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN, | 405 | if (request_region |
405 | "tpm_infineon0") == NULL) { | 406 | (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) { |
406 | rc = -EINVAL; | 407 | rc = -EINVAL; |
407 | goto err_last; | 408 | goto err_last; |
408 | } | 409 | } |
@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
442 | 443 | ||
443 | /* configure TPM with IO-ports */ | 444 | /* configure TPM with IO-ports */ |
444 | outb(IOLIMH, TPM_INF_ADDR); | 445 | outb(IOLIMH, TPM_INF_ADDR); |
445 | outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); | 446 | outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA); |
446 | outb(IOLIML, TPM_INF_ADDR); | 447 | outb(IOLIML, TPM_INF_ADDR); |
447 | outb((tpm_inf.base & 0xff), TPM_INF_DATA); | 448 | outb((TPM_INF_BASE & 0xff), TPM_INF_DATA); |
448 | 449 | ||
449 | /* control if IO-ports are set correctly */ | 450 | /* control if IO-ports are set correctly */ |
450 | outb(IOLIMH, TPM_INF_ADDR); | 451 | outb(IOLIMH, TPM_INF_ADDR); |
@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
452 | outb(IOLIML, TPM_INF_ADDR); | 453 | outb(IOLIML, TPM_INF_ADDR); |
453 | iol = inb(TPM_INF_DATA); | 454 | iol = inb(TPM_INF_DATA); |
454 | 455 | ||
455 | if ((ioh << 8 | iol) != tpm_inf.base) { | 456 | if ((ioh << 8 | iol) != TPM_INF_BASE) { |
456 | dev_err(&dev->dev, | 457 | dev_err(&dev->dev, |
457 | "Could not set IO-ports to 0x%lx\n", | 458 | "Could not set IO-ports to 0x%x\n", |
458 | tpm_inf.base); | 459 | TPM_INF_BASE); |
459 | rc = -EIO; | 460 | rc = -EIO; |
460 | goto err_release_region; | 461 | goto err_release_region; |
461 | } | 462 | } |
@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
466 | outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); | 467 | outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); |
467 | 468 | ||
468 | /* disable RESET, LP and IRQC */ | 469 | /* disable RESET, LP and IRQC */ |
469 | outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); | 470 | outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD); |
470 | 471 | ||
471 | /* Finally, we're done, print some infos */ | 472 | /* Finally, we're done, print some infos */ |
472 | dev_info(&dev->dev, "TPM found: " | 473 | dev_info(&dev->dev, "TPM found: " |
473 | "config base 0x%x, " | 474 | "config base 0x%x, " |
474 | "io base 0x%x, " | 475 | "io base 0x%x, " |
475 | "chip version %02x%02x, " | 476 | "chip version 0x%02x%02x, " |
476 | "vendor id %x%x (Infineon), " | 477 | "vendor id 0x%x%x (Infineon), " |
477 | "product id %02x%02x" | 478 | "product id 0x%02x%02x" |
478 | "%s\n", | 479 | "%s\n", |
479 | TPM_INF_ADDR, | 480 | TPM_INF_ADDR, |
480 | TPM_INF_BASE, | 481 | TPM_INF_BASE, |
@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
482 | vendorid[0], vendorid[1], | 483 | vendorid[0], vendorid[1], |
483 | productid[0], productid[1], chipname); | 484 | productid[0], productid[1], chipname); |
484 | 485 | ||
485 | rc = tpm_register_hardware(&dev->dev, &tpm_inf); | 486 | if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) { |
486 | if (rc < 0) { | ||
487 | rc = -ENODEV; | ||
488 | goto err_release_region; | 487 | goto err_release_region; |
489 | } | 488 | } |
489 | chip->vendor.base = TPM_INF_BASE; | ||
490 | return 0; | 490 | return 0; |
491 | } else { | 491 | } else { |
492 | rc = -ENODEV; | 492 | rc = -ENODEV; |
@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, | |||
494 | } | 494 | } |
495 | 495 | ||
496 | err_release_region: | 496 | err_release_region: |
497 | release_region(tpm_inf.base, TPM_INF_PORT_LEN); | 497 | release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); |
498 | release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); | 498 | release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); |
499 | 499 | ||
500 | err_last: | 500 | err_last: |
@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) | |||
506 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 506 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
507 | 507 | ||
508 | if (chip) { | 508 | if (chip) { |
509 | release_region(chip->vendor->base, TPM_INF_PORT_LEN); | 509 | release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); |
510 | release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); | ||
510 | tpm_remove_hardware(chip->dev); | 511 | tpm_remove_hardware(chip->dev); |
511 | } | 512 | } |
512 | } | 513 | } |
@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = { | |||
520 | }, | 521 | }, |
521 | .id_table = tpm_pnp_tbl, | 522 | .id_table = tpm_pnp_tbl, |
522 | .probe = tpm_inf_pnp_probe, | 523 | .probe = tpm_inf_pnp_probe, |
523 | .remove = tpm_inf_pnp_remove, | 524 | .remove = __devexit_p(tpm_inf_pnp_remove), |
524 | }; | 525 | }; |
525 | 526 | ||
526 | static int __init init_inf(void) | 527 | static int __init init_inf(void) |
@@ -538,5 +539,5 @@ module_exit(cleanup_inf); | |||
538 | 539 | ||
539 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); | 540 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); |
540 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); | 541 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); |
541 | MODULE_VERSION("1.7"); | 542 | MODULE_VERSION("1.8"); |
542 | MODULE_LICENSE("GPL"); | 543 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 680a8e331887..4c8bc06c7d95 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | |||
71 | unsigned long stop; | 71 | unsigned long stop; |
72 | 72 | ||
73 | /* status immediately available check */ | 73 | /* status immediately available check */ |
74 | *data = inb(chip->vendor->base + NSC_STATUS); | 74 | *data = inb(chip->vendor.base + NSC_STATUS); |
75 | if ((*data & mask) == val) | 75 | if ((*data & mask) == val) |
76 | return 0; | 76 | return 0; |
77 | 77 | ||
@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | |||
79 | stop = jiffies + 10 * HZ; | 79 | stop = jiffies + 10 * HZ; |
80 | do { | 80 | do { |
81 | msleep(TPM_TIMEOUT); | 81 | msleep(TPM_TIMEOUT); |
82 | *data = inb(chip->vendor->base + 1); | 82 | *data = inb(chip->vendor.base + 1); |
83 | if ((*data & mask) == val) | 83 | if ((*data & mask) == val) |
84 | return 0; | 84 | return 0; |
85 | } | 85 | } |
@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) | |||
94 | unsigned long stop; | 94 | unsigned long stop; |
95 | 95 | ||
96 | /* status immediately available check */ | 96 | /* status immediately available check */ |
97 | status = inb(chip->vendor->base + NSC_STATUS); | 97 | status = inb(chip->vendor.base + NSC_STATUS); |
98 | if (status & NSC_STATUS_OBF) | 98 | if (status & NSC_STATUS_OBF) |
99 | status = inb(chip->vendor->base + NSC_DATA); | 99 | status = inb(chip->vendor.base + NSC_DATA); |
100 | if (status & NSC_STATUS_RDY) | 100 | if (status & NSC_STATUS_RDY) |
101 | return 0; | 101 | return 0; |
102 | 102 | ||
@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) | |||
104 | stop = jiffies + 100; | 104 | stop = jiffies + 100; |
105 | do { | 105 | do { |
106 | msleep(TPM_TIMEOUT); | 106 | msleep(TPM_TIMEOUT); |
107 | status = inb(chip->vendor->base + NSC_STATUS); | 107 | status = inb(chip->vendor.base + NSC_STATUS); |
108 | if (status & NSC_STATUS_OBF) | 108 | if (status & NSC_STATUS_OBF) |
109 | status = inb(chip->vendor->base + NSC_DATA); | 109 | status = inb(chip->vendor.base + NSC_DATA); |
110 | if (status & NSC_STATUS_RDY) | 110 | if (status & NSC_STATUS_RDY) |
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
132 | return -EIO; | 132 | return -EIO; |
133 | } | 133 | } |
134 | if ((data = | 134 | if ((data = |
135 | inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) { | 135 | inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { |
136 | dev_err(chip->dev, "not in normal mode (0x%x)\n", | 136 | dev_err(chip->dev, "not in normal mode (0x%x)\n", |
137 | data); | 137 | data); |
138 | return -EIO; | 138 | return -EIO; |
@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
148 | } | 148 | } |
149 | if (data & NSC_STATUS_F0) | 149 | if (data & NSC_STATUS_F0) |
150 | break; | 150 | break; |
151 | *p = inb(chip->vendor->base + NSC_DATA); | 151 | *p = inb(chip->vendor.base + NSC_DATA); |
152 | } | 152 | } |
153 | 153 | ||
154 | if ((data & NSC_STATUS_F0) == 0 && | 154 | if ((data & NSC_STATUS_F0) == 0 && |
@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) | |||
156 | dev_err(chip->dev, "F0 not set\n"); | 156 | dev_err(chip->dev, "F0 not set\n"); |
157 | return -EIO; | 157 | return -EIO; |
158 | } | 158 | } |
159 | if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) { | 159 | if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { |
160 | dev_err(chip->dev, | 160 | dev_err(chip->dev, |
161 | "expected end of command(0x%x)\n", data); | 161 | "expected end of command(0x%x)\n", data); |
162 | return -EIO; | 162 | return -EIO; |
@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
182 | * fix it. Not sure why this is needed, we followed the flow | 182 | * fix it. Not sure why this is needed, we followed the flow |
183 | * chart in the manual to the letter. | 183 | * chart in the manual to the letter. |
184 | */ | 184 | */ |
185 | outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); | 185 | outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); |
186 | 186 | ||
187 | if (nsc_wait_for_ready(chip) != 0) | 187 | if (nsc_wait_for_ready(chip) != 0) |
188 | return -EIO; | 188 | return -EIO; |
@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
192 | return -EIO; | 192 | return -EIO; |
193 | } | 193 | } |
194 | 194 | ||
195 | outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND); | 195 | outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); |
196 | if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { | 196 | if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { |
197 | dev_err(chip->dev, "IBR timeout\n"); | 197 | dev_err(chip->dev, "IBR timeout\n"); |
198 | return -EIO; | 198 | return -EIO; |
@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) | |||
204 | "IBF timeout (while writing data)\n"); | 204 | "IBF timeout (while writing data)\n"); |
205 | return -EIO; | 205 | return -EIO; |
206 | } | 206 | } |
207 | outb(buf[i], chip->vendor->base + NSC_DATA); | 207 | outb(buf[i], chip->vendor.base + NSC_DATA); |
208 | } | 208 | } |
209 | 209 | ||
210 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { | 210 | if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { |
211 | dev_err(chip->dev, "IBF timeout\n"); | 211 | dev_err(chip->dev, "IBF timeout\n"); |
212 | return -EIO; | 212 | return -EIO; |
213 | } | 213 | } |
214 | outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND); | 214 | outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); |
215 | 215 | ||
216 | return count; | 216 | return count; |
217 | } | 217 | } |
218 | 218 | ||
219 | static void tpm_nsc_cancel(struct tpm_chip *chip) | 219 | static void tpm_nsc_cancel(struct tpm_chip *chip) |
220 | { | 220 | { |
221 | outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); | 221 | outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); |
222 | } | 222 | } |
223 | 223 | ||
224 | static u8 tpm_nsc_status(struct tpm_chip *chip) | 224 | static u8 tpm_nsc_status(struct tpm_chip *chip) |
225 | { | 225 | { |
226 | return inb(chip->vendor->base + NSC_STATUS); | 226 | return inb(chip->vendor.base + NSC_STATUS); |
227 | } | 227 | } |
228 | 228 | ||
229 | static struct file_operations nsc_ops = { | 229 | static struct file_operations nsc_ops = { |
@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = { | |||
250 | 250 | ||
251 | static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; | 251 | static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; |
252 | 252 | ||
253 | static struct tpm_vendor_specific tpm_nsc = { | 253 | static const struct tpm_vendor_specific tpm_nsc = { |
254 | .recv = tpm_nsc_recv, | 254 | .recv = tpm_nsc_recv, |
255 | .send = tpm_nsc_send, | 255 | .send = tpm_nsc_send, |
256 | .cancel = tpm_nsc_cancel, | 256 | .cancel = tpm_nsc_cancel, |
@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(struct device *dev) | |||
268 | { | 268 | { |
269 | struct tpm_chip *chip = dev_get_drvdata(dev); | 269 | struct tpm_chip *chip = dev_get_drvdata(dev); |
270 | if ( chip ) { | 270 | if ( chip ) { |
271 | release_region(chip->vendor->base, 2); | 271 | release_region(chip->vendor.base, 2); |
272 | tpm_remove_hardware(chip->dev); | 272 | tpm_remove_hardware(chip->dev); |
273 | } | 273 | } |
274 | } | 274 | } |
@@ -286,7 +286,8 @@ static int __init init_nsc(void) | |||
286 | int rc = 0; | 286 | int rc = 0; |
287 | int lo, hi; | 287 | int lo, hi; |
288 | int nscAddrBase = TPM_ADDR; | 288 | int nscAddrBase = TPM_ADDR; |
289 | 289 | struct tpm_chip *chip; | |
290 | unsigned long base; | ||
290 | 291 | ||
291 | /* verify that it is a National part (SID) */ | 292 | /* verify that it is a National part (SID) */ |
292 | if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { | 293 | if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { |
@@ -300,7 +301,7 @@ static int __init init_nsc(void) | |||
300 | 301 | ||
301 | hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); | 302 | hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); |
302 | lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); | 303 | lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); |
303 | tpm_nsc.base = (hi<<8) | lo; | 304 | base = (hi<<8) | lo; |
304 | 305 | ||
305 | /* enable the DPM module */ | 306 | /* enable the DPM module */ |
306 | tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); | 307 | tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); |
@@ -320,13 +321,15 @@ static int __init init_nsc(void) | |||
320 | if ((rc = platform_device_register(pdev)) < 0) | 321 | if ((rc = platform_device_register(pdev)) < 0) |
321 | goto err_free_dev; | 322 | goto err_free_dev; |
322 | 323 | ||
323 | if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) { | 324 | if (request_region(base, 2, "tpm_nsc0") == NULL ) { |
324 | rc = -EBUSY; | 325 | rc = -EBUSY; |
325 | goto err_unreg_dev; | 326 | goto err_unreg_dev; |
326 | } | 327 | } |
327 | 328 | ||
328 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) | 329 | if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { |
330 | rc = -ENODEV; | ||
329 | goto err_rel_reg; | 331 | goto err_rel_reg; |
332 | } | ||
330 | 333 | ||
331 | dev_dbg(&pdev->dev, "NSC TPM detected\n"); | 334 | dev_dbg(&pdev->dev, "NSC TPM detected\n"); |
332 | dev_dbg(&pdev->dev, | 335 | dev_dbg(&pdev->dev, |
@@ -361,10 +364,12 @@ static int __init init_nsc(void) | |||
361 | "NSC TPM revision %d\n", | 364 | "NSC TPM revision %d\n", |
362 | tpm_read_index(nscAddrBase, 0x27) & 0x1F); | 365 | tpm_read_index(nscAddrBase, 0x27) & 0x1F); |
363 | 366 | ||
367 | chip->vendor.base = base; | ||
368 | |||
364 | return 0; | 369 | return 0; |
365 | 370 | ||
366 | err_rel_reg: | 371 | err_rel_reg: |
367 | release_region(tpm_nsc.base, 2); | 372 | release_region(base, 2); |
368 | err_unreg_dev: | 373 | err_unreg_dev: |
369 | platform_device_unregister(pdev); | 374 | platform_device_unregister(pdev); |
370 | err_free_dev: | 375 | err_free_dev: |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c new file mode 100644 index 000000000000..b9cae9a238bb --- /dev/null +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -0,0 +1,669 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 IBM Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Leendert van Doorn <leendert@watson.ibm.com> | ||
6 | * Kylene Hall <kjhall@us.ibm.com> | ||
7 | * | ||
8 | * Device driver for TCG/TCPA TPM (trusted platform module). | ||
9 | * Specifications at www.trustedcomputinggroup.org | ||
10 | * | ||
11 | * This device driver implements the TPM interface as defined in | ||
12 | * the TCG TPM Interface Spec version 1.2, revision 1.0. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License as | ||
16 | * published by the Free Software Foundation, version 2 of the | ||
17 | * License. | ||
18 | */ | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/moduleparam.h> | ||
22 | #include <linux/pnp.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/wait.h> | ||
25 | #include "tpm.h" | ||
26 | |||
27 | #define TPM_HEADER_SIZE 10 | ||
28 | |||
29 | enum tis_access { | ||
30 | TPM_ACCESS_VALID = 0x80, | ||
31 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, | ||
32 | TPM_ACCESS_REQUEST_PENDING = 0x04, | ||
33 | TPM_ACCESS_REQUEST_USE = 0x02, | ||
34 | }; | ||
35 | |||
36 | enum tis_status { | ||
37 | TPM_STS_VALID = 0x80, | ||
38 | TPM_STS_COMMAND_READY = 0x40, | ||
39 | TPM_STS_GO = 0x20, | ||
40 | TPM_STS_DATA_AVAIL = 0x10, | ||
41 | TPM_STS_DATA_EXPECT = 0x08, | ||
42 | }; | ||
43 | |||
44 | enum tis_int_flags { | ||
45 | TPM_GLOBAL_INT_ENABLE = 0x80000000, | ||
46 | TPM_INTF_BURST_COUNT_STATIC = 0x100, | ||
47 | TPM_INTF_CMD_READY_INT = 0x080, | ||
48 | TPM_INTF_INT_EDGE_FALLING = 0x040, | ||
49 | TPM_INTF_INT_EDGE_RISING = 0x020, | ||
50 | TPM_INTF_INT_LEVEL_LOW = 0x010, | ||
51 | TPM_INTF_INT_LEVEL_HIGH = 0x008, | ||
52 | TPM_INTF_LOCALITY_CHANGE_INT = 0x004, | ||
53 | TPM_INTF_STS_VALID_INT = 0x002, | ||
54 | TPM_INTF_DATA_AVAIL_INT = 0x001, | ||
55 | }; | ||
56 | |||
57 | enum tis_defaults { | ||
58 | TIS_MEM_BASE = 0xFED4000, | ||
59 | TIS_MEM_LEN = 0x5000, | ||
60 | TIS_SHORT_TIMEOUT = 750, /* ms */ | ||
61 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ | ||
62 | }; | ||
63 | |||
64 | #define TPM_ACCESS(l) (0x0000 | ((l) << 12)) | ||
65 | #define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) | ||
66 | #define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) | ||
67 | #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) | ||
68 | #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) | ||
69 | #define TPM_STS(l) (0x0018 | ((l) << 12)) | ||
70 | #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) | ||
71 | |||
72 | #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) | ||
73 | #define TPM_RID(l) (0x0F04 | ((l) << 12)) | ||
74 | |||
75 | static LIST_HEAD(tis_chips); | ||
76 | static DEFINE_SPINLOCK(tis_lock); | ||
77 | |||
78 | static int check_locality(struct tpm_chip *chip, int l) | ||
79 | { | ||
80 | if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & | ||
81 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | ||
82 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) | ||
83 | return chip->vendor.locality = l; | ||
84 | |||
85 | return -1; | ||
86 | } | ||
87 | |||
88 | static void release_locality(struct tpm_chip *chip, int l, int force) | ||
89 | { | ||
90 | if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & | ||
91 | (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == | ||
92 | (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) | ||
93 | iowrite8(TPM_ACCESS_ACTIVE_LOCALITY, | ||
94 | chip->vendor.iobase + TPM_ACCESS(l)); | ||
95 | } | ||
96 | |||
97 | static int request_locality(struct tpm_chip *chip, int l) | ||
98 | { | ||
99 | unsigned long stop; | ||
100 | long rc; | ||
101 | |||
102 | if (check_locality(chip, l) >= 0) | ||
103 | return l; | ||
104 | |||
105 | iowrite8(TPM_ACCESS_REQUEST_USE, | ||
106 | chip->vendor.iobase + TPM_ACCESS(l)); | ||
107 | |||
108 | if (chip->vendor.irq) { | ||
109 | rc = wait_event_interruptible_timeout(chip->vendor.int_queue, | ||
110 | (check_locality | ||
111 | (chip, l) >= 0), | ||
112 | chip->vendor.timeout_a); | ||
113 | if (rc > 0) | ||
114 | return l; | ||
115 | |||
116 | } else { | ||
117 | /* wait for burstcount */ | ||
118 | stop = jiffies + chip->vendor.timeout_a; | ||
119 | do { | ||
120 | if (check_locality(chip, l) >= 0) | ||
121 | return l; | ||
122 | msleep(TPM_TIMEOUT); | ||
123 | } | ||
124 | while (time_before(jiffies, stop)); | ||
125 | } | ||
126 | return -1; | ||
127 | } | ||
128 | |||
129 | static u8 tpm_tis_status(struct tpm_chip *chip) | ||
130 | { | ||
131 | return ioread8(chip->vendor.iobase + | ||
132 | TPM_STS(chip->vendor.locality)); | ||
133 | } | ||
134 | |||
135 | static void tpm_tis_ready(struct tpm_chip *chip) | ||
136 | { | ||
137 | /* this causes the current command to be aborted */ | ||
138 | iowrite8(TPM_STS_COMMAND_READY, | ||
139 | chip->vendor.iobase + TPM_STS(chip->vendor.locality)); | ||
140 | } | ||
141 | |||
142 | static int get_burstcount(struct tpm_chip *chip) | ||
143 | { | ||
144 | unsigned long stop; | ||
145 | int burstcnt; | ||
146 | |||
147 | /* wait for burstcount */ | ||
148 | /* which timeout value, spec has 2 answers (c & d) */ | ||
149 | stop = jiffies + chip->vendor.timeout_d; | ||
150 | do { | ||
151 | burstcnt = ioread8(chip->vendor.iobase + | ||
152 | TPM_STS(chip->vendor.locality) + 1); | ||
153 | burstcnt += ioread8(chip->vendor.iobase + | ||
154 | TPM_STS(chip->vendor.locality) + | ||
155 | 2) << 8; | ||
156 | if (burstcnt) | ||
157 | return burstcnt; | ||
158 | msleep(TPM_TIMEOUT); | ||
159 | } while (time_before(jiffies, stop)); | ||
160 | return -EBUSY; | ||
161 | } | ||
162 | |||
163 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
164 | wait_queue_head_t *queue) | ||
165 | { | ||
166 | unsigned long stop; | ||
167 | long rc; | ||
168 | u8 status; | ||
169 | |||
170 | /* check current status */ | ||
171 | status = tpm_tis_status(chip); | ||
172 | if ((status & mask) == mask) | ||
173 | return 0; | ||
174 | |||
175 | if (chip->vendor.irq) { | ||
176 | rc = wait_event_interruptible_timeout(*queue, | ||
177 | ((tpm_tis_status | ||
178 | (chip) & mask) == | ||
179 | mask), timeout); | ||
180 | if (rc > 0) | ||
181 | return 0; | ||
182 | } else { | ||
183 | stop = jiffies + timeout; | ||
184 | do { | ||
185 | msleep(TPM_TIMEOUT); | ||
186 | status = tpm_tis_status(chip); | ||
187 | if ((status & mask) == mask) | ||
188 | return 0; | ||
189 | } while (time_before(jiffies, stop)); | ||
190 | } | ||
191 | return -ETIME; | ||
192 | } | ||
193 | |||
194 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | ||
195 | { | ||
196 | int size = 0, burstcnt; | ||
197 | while (size < count && | ||
198 | wait_for_stat(chip, | ||
199 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
200 | chip->vendor.timeout_c, | ||
201 | &chip->vendor.read_queue) | ||
202 | == 0) { | ||
203 | burstcnt = get_burstcount(chip); | ||
204 | for (; burstcnt > 0 && size < count; burstcnt--) | ||
205 | buf[size++] = ioread8(chip->vendor.iobase + | ||
206 | TPM_DATA_FIFO(chip->vendor. | ||
207 | locality)); | ||
208 | } | ||
209 | return size; | ||
210 | } | ||
211 | |||
212 | static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | ||
213 | { | ||
214 | int size = 0; | ||
215 | int expected, status; | ||
216 | |||
217 | if (count < TPM_HEADER_SIZE) { | ||
218 | size = -EIO; | ||
219 | goto out; | ||
220 | } | ||
221 | |||
222 | /* read first 10 bytes, including tag, paramsize, and result */ | ||
223 | if ((size = | ||
224 | recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { | ||
225 | dev_err(chip->dev, "Unable to read header\n"); | ||
226 | goto out; | ||
227 | } | ||
228 | |||
229 | expected = be32_to_cpu(*(__be32 *) (buf + 2)); | ||
230 | if (expected > count) { | ||
231 | size = -EIO; | ||
232 | goto out; | ||
233 | } | ||
234 | |||
235 | if ((size += | ||
236 | recv_data(chip, &buf[TPM_HEADER_SIZE], | ||
237 | expected - TPM_HEADER_SIZE)) < expected) { | ||
238 | dev_err(chip->dev, "Unable to read remainder of result\n"); | ||
239 | size = -ETIME; | ||
240 | goto out; | ||
241 | } | ||
242 | |||
243 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | ||
244 | &chip->vendor.int_queue); | ||
245 | status = tpm_tis_status(chip); | ||
246 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | ||
247 | dev_err(chip->dev, "Error left over data\n"); | ||
248 | size = -EIO; | ||
249 | goto out; | ||
250 | } | ||
251 | |||
252 | out: | ||
253 | tpm_tis_ready(chip); | ||
254 | release_locality(chip, chip->vendor.locality, 0); | ||
255 | return size; | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | * If interrupts are used (signaled by an irq set in the vendor structure) | ||
260 | * tpm.c can skip polling for the data to be available as the interrupt is | ||
261 | * waited for here | ||
262 | */ | ||
263 | static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | ||
264 | { | ||
265 | int rc, status, burstcnt; | ||
266 | size_t count = 0; | ||
267 | u32 ordinal; | ||
268 | |||
269 | if (request_locality(chip, 0) < 0) | ||
270 | return -EBUSY; | ||
271 | |||
272 | status = tpm_tis_status(chip); | ||
273 | if ((status & TPM_STS_COMMAND_READY) == 0) { | ||
274 | tpm_tis_ready(chip); | ||
275 | if (wait_for_stat | ||
276 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, | ||
277 | &chip->vendor.int_queue) < 0) { | ||
278 | rc = -ETIME; | ||
279 | goto out_err; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | while (count < len - 1) { | ||
284 | burstcnt = get_burstcount(chip); | ||
285 | for (; burstcnt > 0 && count < len - 1; burstcnt--) { | ||
286 | iowrite8(buf[count], chip->vendor.iobase + | ||
287 | TPM_DATA_FIFO(chip->vendor.locality)); | ||
288 | count++; | ||
289 | } | ||
290 | |||
291 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | ||
292 | &chip->vendor.int_queue); | ||
293 | status = tpm_tis_status(chip); | ||
294 | if ((status & TPM_STS_DATA_EXPECT) == 0) { | ||
295 | rc = -EIO; | ||
296 | goto out_err; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | /* write last byte */ | ||
301 | iowrite8(buf[count], | ||
302 | chip->vendor.iobase + | ||
303 | TPM_DATA_FIFO(chip->vendor.locality)); | ||
304 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | ||
305 | &chip->vendor.int_queue); | ||
306 | status = tpm_tis_status(chip); | ||
307 | if ((status & TPM_STS_DATA_EXPECT) != 0) { | ||
308 | rc = -EIO; | ||
309 | goto out_err; | ||
310 | } | ||
311 | |||
312 | /* go and do it */ | ||
313 | iowrite8(TPM_STS_GO, | ||
314 | chip->vendor.iobase + TPM_STS(chip->vendor.locality)); | ||
315 | |||
316 | if (chip->vendor.irq) { | ||
317 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | ||
318 | if (wait_for_stat | ||
319 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
320 | tpm_calc_ordinal_duration(chip, ordinal), | ||
321 | &chip->vendor.read_queue) < 0) { | ||
322 | rc = -ETIME; | ||
323 | goto out_err; | ||
324 | } | ||
325 | } | ||
326 | return len; | ||
327 | out_err: | ||
328 | tpm_tis_ready(chip); | ||
329 | release_locality(chip, chip->vendor.locality, 0); | ||
330 | return rc; | ||
331 | } | ||
332 | |||
333 | static struct file_operations tis_ops = { | ||
334 | .owner = THIS_MODULE, | ||
335 | .llseek = no_llseek, | ||
336 | .open = tpm_open, | ||
337 | .read = tpm_read, | ||
338 | .write = tpm_write, | ||
339 | .release = tpm_release, | ||
340 | }; | ||
341 | |||
342 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
343 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
344 | static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); | ||
345 | static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); | ||
346 | static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); | ||
347 | static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, | ||
348 | NULL); | ||
349 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); | ||
350 | static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); | ||
351 | |||
352 | static struct attribute *tis_attrs[] = { | ||
353 | &dev_attr_pubek.attr, | ||
354 | &dev_attr_pcrs.attr, | ||
355 | &dev_attr_enabled.attr, | ||
356 | &dev_attr_active.attr, | ||
357 | &dev_attr_owned.attr, | ||
358 | &dev_attr_temp_deactivated.attr, | ||
359 | &dev_attr_caps.attr, | ||
360 | &dev_attr_cancel.attr, NULL, | ||
361 | }; | ||
362 | |||
363 | static struct attribute_group tis_attr_grp = { | ||
364 | .attrs = tis_attrs | ||
365 | }; | ||
366 | |||
367 | static struct tpm_vendor_specific tpm_tis = { | ||
368 | .status = tpm_tis_status, | ||
369 | .recv = tpm_tis_recv, | ||
370 | .send = tpm_tis_send, | ||
371 | .cancel = tpm_tis_ready, | ||
372 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
373 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
374 | .req_canceled = TPM_STS_COMMAND_READY, | ||
375 | .attr_group = &tis_attr_grp, | ||
376 | .miscdev = { | ||
377 | .fops = &tis_ops,}, | ||
378 | }; | ||
379 | |||
380 | static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs) | ||
381 | { | ||
382 | struct tpm_chip *chip = (struct tpm_chip *) dev_id; | ||
383 | u32 interrupt; | ||
384 | |||
385 | interrupt = ioread32(chip->vendor.iobase + | ||
386 | TPM_INT_STATUS(chip->vendor.locality)); | ||
387 | |||
388 | if (interrupt == 0) | ||
389 | return IRQ_NONE; | ||
390 | |||
391 | chip->vendor.irq = irq; | ||
392 | |||
393 | /* Clear interrupts handled with TPM_EOI */ | ||
394 | iowrite32(interrupt, | ||
395 | chip->vendor.iobase + | ||
396 | TPM_INT_STATUS(chip->vendor.locality)); | ||
397 | return IRQ_HANDLED; | ||
398 | } | ||
399 | |||
400 | static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
401 | { | ||
402 | struct tpm_chip *chip = (struct tpm_chip *) dev_id; | ||
403 | u32 interrupt; | ||
404 | int i; | ||
405 | |||
406 | interrupt = ioread32(chip->vendor.iobase + | ||
407 | TPM_INT_STATUS(chip->vendor.locality)); | ||
408 | |||
409 | if (interrupt == 0) | ||
410 | return IRQ_NONE; | ||
411 | |||
412 | if (interrupt & TPM_INTF_DATA_AVAIL_INT) | ||
413 | wake_up_interruptible(&chip->vendor.read_queue); | ||
414 | if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) | ||
415 | for (i = 0; i < 5; i++) | ||
416 | if (check_locality(chip, i) >= 0) | ||
417 | break; | ||
418 | if (interrupt & | ||
419 | (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | | ||
420 | TPM_INTF_CMD_READY_INT)) | ||
421 | wake_up_interruptible(&chip->vendor.int_queue); | ||
422 | |||
423 | /* Clear interrupts handled with TPM_EOI */ | ||
424 | iowrite32(interrupt, | ||
425 | chip->vendor.iobase + | ||
426 | TPM_INT_STATUS(chip->vendor.locality)); | ||
427 | return IRQ_HANDLED; | ||
428 | } | ||
429 | |||
430 | static int interrupts = 1; | ||
431 | module_param(interrupts, bool, 0444); | ||
432 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | ||
433 | |||
434 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | ||
435 | const struct pnp_device_id *pnp_id) | ||
436 | { | ||
437 | u32 vendor, intfcaps, intmask; | ||
438 | int rc, i; | ||
439 | unsigned long start, len; | ||
440 | struct tpm_chip *chip; | ||
441 | |||
442 | start = pnp_mem_start(pnp_dev, 0); | ||
443 | len = pnp_mem_len(pnp_dev, 0); | ||
444 | |||
445 | if (!start) | ||
446 | start = TIS_MEM_BASE; | ||
447 | if (!len) | ||
448 | len = TIS_MEM_LEN; | ||
449 | |||
450 | if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis))) | ||
451 | return -ENODEV; | ||
452 | |||
453 | chip->vendor.iobase = ioremap(start, len); | ||
454 | if (!chip->vendor.iobase) { | ||
455 | rc = -EIO; | ||
456 | goto out_err; | ||
457 | } | ||
458 | |||
459 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); | ||
460 | if ((vendor & 0xFFFF) == 0xFFFF) { | ||
461 | rc = -ENODEV; | ||
462 | goto out_err; | ||
463 | } | ||
464 | |||
465 | /* Default timeouts */ | ||
466 | chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
467 | chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); | ||
468 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
469 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
470 | |||
471 | dev_info(&pnp_dev->dev, | ||
472 | "1.2 TPM (device-id 0x%X, rev-id %d)\n", | ||
473 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); | ||
474 | |||
475 | /* Figure out the capabilities */ | ||
476 | intfcaps = | ||
477 | ioread32(chip->vendor.iobase + | ||
478 | TPM_INTF_CAPS(chip->vendor.locality)); | ||
479 | dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n", | ||
480 | intfcaps); | ||
481 | if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) | ||
482 | dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n"); | ||
483 | if (intfcaps & TPM_INTF_CMD_READY_INT) | ||
484 | dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n"); | ||
485 | if (intfcaps & TPM_INTF_INT_EDGE_FALLING) | ||
486 | dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n"); | ||
487 | if (intfcaps & TPM_INTF_INT_EDGE_RISING) | ||
488 | dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n"); | ||
489 | if (intfcaps & TPM_INTF_INT_LEVEL_LOW) | ||
490 | dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n"); | ||
491 | if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) | ||
492 | dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n"); | ||
493 | if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) | ||
494 | dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n"); | ||
495 | if (intfcaps & TPM_INTF_STS_VALID_INT) | ||
496 | dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n"); | ||
497 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) | ||
498 | dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n"); | ||
499 | |||
500 | if (request_locality(chip, 0) != 0) { | ||
501 | rc = -ENODEV; | ||
502 | goto out_err; | ||
503 | } | ||
504 | |||
505 | /* INTERRUPT Setup */ | ||
506 | init_waitqueue_head(&chip->vendor.read_queue); | ||
507 | init_waitqueue_head(&chip->vendor.int_queue); | ||
508 | |||
509 | intmask = | ||
510 | ioread32(chip->vendor.iobase + | ||
511 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
512 | |||
513 | intmask |= TPM_INTF_CMD_READY_INT | ||
514 | | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT | ||
515 | | TPM_INTF_STS_VALID_INT; | ||
516 | |||
517 | iowrite32(intmask, | ||
518 | chip->vendor.iobase + | ||
519 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
520 | if (interrupts) { | ||
521 | chip->vendor.irq = | ||
522 | ioread8(chip->vendor.iobase + | ||
523 | TPM_INT_VECTOR(chip->vendor.locality)); | ||
524 | |||
525 | for (i = 3; i < 16 && chip->vendor.irq == 0; i++) { | ||
526 | iowrite8(i, chip->vendor.iobase + | ||
527 | TPM_INT_VECTOR(chip->vendor.locality)); | ||
528 | if (request_irq | ||
529 | (i, tis_int_probe, SA_SHIRQ, | ||
530 | chip->vendor.miscdev.name, chip) != 0) { | ||
531 | dev_info(chip->dev, | ||
532 | "Unable to request irq: %d for probe\n", | ||
533 | i); | ||
534 | continue; | ||
535 | } | ||
536 | |||
537 | /* Clear all existing */ | ||
538 | iowrite32(ioread32 | ||
539 | (chip->vendor.iobase + | ||
540 | TPM_INT_STATUS(chip->vendor.locality)), | ||
541 | chip->vendor.iobase + | ||
542 | TPM_INT_STATUS(chip->vendor.locality)); | ||
543 | |||
544 | /* Turn on */ | ||
545 | iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, | ||
546 | chip->vendor.iobase + | ||
547 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
548 | |||
549 | /* Generate Interrupts */ | ||
550 | tpm_gen_interrupt(chip); | ||
551 | |||
552 | /* Turn off */ | ||
553 | iowrite32(intmask, | ||
554 | chip->vendor.iobase + | ||
555 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
556 | free_irq(i, chip); | ||
557 | } | ||
558 | } | ||
559 | if (chip->vendor.irq) { | ||
560 | iowrite8(chip->vendor.irq, | ||
561 | chip->vendor.iobase + | ||
562 | TPM_INT_VECTOR(chip->vendor.locality)); | ||
563 | if (request_irq | ||
564 | (chip->vendor.irq, tis_int_handler, SA_SHIRQ, | ||
565 | chip->vendor.miscdev.name, chip) != 0) { | ||
566 | dev_info(chip->dev, | ||
567 | "Unable to request irq: %d for use\n", | ||
568 | chip->vendor.irq); | ||
569 | chip->vendor.irq = 0; | ||
570 | } else { | ||
571 | /* Clear all existing */ | ||
572 | iowrite32(ioread32 | ||
573 | (chip->vendor.iobase + | ||
574 | TPM_INT_STATUS(chip->vendor.locality)), | ||
575 | chip->vendor.iobase + | ||
576 | TPM_INT_STATUS(chip->vendor.locality)); | ||
577 | |||
578 | /* Turn on */ | ||
579 | iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, | ||
580 | chip->vendor.iobase + | ||
581 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
582 | } | ||
583 | } | ||
584 | |||
585 | INIT_LIST_HEAD(&chip->vendor.list); | ||
586 | spin_lock(&tis_lock); | ||
587 | list_add(&chip->vendor.list, &tis_chips); | ||
588 | spin_unlock(&tis_lock); | ||
589 | |||
590 | tpm_get_timeouts(chip); | ||
591 | tpm_continue_selftest(chip); | ||
592 | |||
593 | return 0; | ||
594 | out_err: | ||
595 | if (chip->vendor.iobase) | ||
596 | iounmap(chip->vendor.iobase); | ||
597 | tpm_remove_hardware(chip->dev); | ||
598 | return rc; | ||
599 | } | ||
600 | |||
601 | static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) | ||
602 | { | ||
603 | return tpm_pm_suspend(&dev->dev, msg); | ||
604 | } | ||
605 | |||
606 | static int tpm_tis_pnp_resume(struct pnp_dev *dev) | ||
607 | { | ||
608 | return tpm_pm_resume(&dev->dev); | ||
609 | } | ||
610 | |||
611 | static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { | ||
612 | {"PNP0C31", 0}, /* TPM */ | ||
613 | {"ATM1200", 0}, /* Atmel */ | ||
614 | {"IFX0102", 0}, /* Infineon */ | ||
615 | {"BCM0101", 0}, /* Broadcom */ | ||
616 | {"NSC1200", 0}, /* National */ | ||
617 | /* Add new here */ | ||
618 | {"", 0}, /* User Specified */ | ||
619 | {"", 0} /* Terminator */ | ||
620 | }; | ||
621 | |||
622 | static struct pnp_driver tis_pnp_driver = { | ||
623 | .name = "tpm_tis", | ||
624 | .id_table = tpm_pnp_tbl, | ||
625 | .probe = tpm_tis_pnp_init, | ||
626 | .suspend = tpm_tis_pnp_suspend, | ||
627 | .resume = tpm_tis_pnp_resume, | ||
628 | }; | ||
629 | |||
630 | #define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 | ||
631 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | ||
632 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | ||
633 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | ||
634 | |||
635 | static int __init init_tis(void) | ||
636 | { | ||
637 | return pnp_register_driver(&tis_pnp_driver); | ||
638 | } | ||
639 | |||
640 | static void __exit cleanup_tis(void) | ||
641 | { | ||
642 | struct tpm_vendor_specific *i, *j; | ||
643 | struct tpm_chip *chip; | ||
644 | spin_lock(&tis_lock); | ||
645 | list_for_each_entry_safe(i, j, &tis_chips, list) { | ||
646 | chip = to_tpm_chip(i); | ||
647 | iowrite32(~TPM_GLOBAL_INT_ENABLE & | ||
648 | ioread32(chip->vendor.iobase + | ||
649 | TPM_INT_ENABLE(chip->vendor. | ||
650 | locality)), | ||
651 | chip->vendor.iobase + | ||
652 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
653 | release_locality(chip, chip->vendor.locality, 1); | ||
654 | if (chip->vendor.irq) | ||
655 | free_irq(chip->vendor.irq, chip); | ||
656 | iounmap(i->iobase); | ||
657 | list_del(&i->list); | ||
658 | tpm_remove_hardware(chip->dev); | ||
659 | } | ||
660 | spin_unlock(&tis_lock); | ||
661 | pnp_unregister_driver(&tis_pnp_driver); | ||
662 | } | ||
663 | |||
664 | module_init(init_tis); | ||
665 | module_exit(cleanup_tis); | ||
666 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); | ||
667 | MODULE_DESCRIPTION("TPM Driver"); | ||
668 | MODULE_VERSION("2.0"); | ||
669 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 1dca3cf42a54..2e4abdc26367 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c | |||
@@ -350,11 +350,11 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) | |||
350 | return 0; | 350 | return 0; |
351 | bail2: | 351 | bail2: |
352 | serio_close(serio); | 352 | serio_close(serio); |
353 | serio_set_drvdata(serio, NULL); | ||
353 | bail1: | 354 | bail1: |
354 | input_free_device(kbd->dev); | 355 | input_free_device(kbd->dev); |
355 | bail0: | 356 | bail0: |
356 | kfree(kbd); | 357 | kfree(kbd); |
357 | serio_set_drvdata(serio, NULL); | ||
358 | return -EIO; | 358 | return -EIO; |
359 | } | 359 | } |
360 | 360 | ||
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index f86ed6af3aa2..eb41aba3ddef 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Tilman Schmidt <tilman@imap.cc>, | 5 | * Tilman Schmidt <tilman@imap.cc>, |
6 | * Stefan Eilers. | 6 | * Stefan Eilers. |
7 | * | 7 | * |
8 | * Based on usb-gigaset.c. | ||
9 | * | ||
10 | * ===================================================================== | 8 | * ===================================================================== |
11 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License as | 10 | * modify it under the terms of the GNU General Public License as |
@@ -46,19 +44,20 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); | |||
46 | #define GIGASET_DEVFSNAME "gig/bas/" | 44 | #define GIGASET_DEVFSNAME "gig/bas/" |
47 | #define GIGASET_DEVNAME "ttyGB" | 45 | #define GIGASET_DEVNAME "ttyGB" |
48 | 46 | ||
49 | #define IF_WRITEBUF 256 //FIXME | 47 | /* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ |
48 | #define IF_WRITEBUF 264 | ||
50 | 49 | ||
51 | /* Values for the Gigaset 307x */ | 50 | /* Values for the Gigaset 307x */ |
52 | #define USB_GIGA_VENDOR_ID 0x0681 | 51 | #define USB_GIGA_VENDOR_ID 0x0681 |
53 | #define USB_GIGA_PRODUCT_ID 0x0001 | 52 | #define USB_3070_PRODUCT_ID 0x0001 |
54 | #define USB_4175_PRODUCT_ID 0x0002 | 53 | #define USB_3075_PRODUCT_ID 0x0002 |
55 | #define USB_SX303_PRODUCT_ID 0x0021 | 54 | #define USB_SX303_PRODUCT_ID 0x0021 |
56 | #define USB_SX353_PRODUCT_ID 0x0022 | 55 | #define USB_SX353_PRODUCT_ID 0x0022 |
57 | 56 | ||
58 | /* table of devices that work with this driver */ | 57 | /* table of devices that work with this driver */ |
59 | static struct usb_device_id gigaset_table [] = { | 58 | static struct usb_device_id gigaset_table [] = { |
60 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) }, | 59 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, |
61 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) }, | 60 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, |
62 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, | 61 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, |
63 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) }, | 62 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) }, |
64 | { } /* Terminating entry */ | 63 | { } /* Terminating entry */ |
@@ -77,6 +76,10 @@ static int gigaset_probe(struct usb_interface *interface, | |||
77 | /* Function will be called if the device is unplugged */ | 76 | /* Function will be called if the device is unplugged */ |
78 | static void gigaset_disconnect(struct usb_interface *interface); | 77 | static void gigaset_disconnect(struct usb_interface *interface); |
79 | 78 | ||
79 | static void read_ctrl_callback(struct urb *, struct pt_regs *); | ||
80 | static void stopurbs(struct bas_bc_state *); | ||
81 | static int atwrite_submit(struct cardstate *, unsigned char *, int); | ||
82 | static int start_cbsend(struct cardstate *); | ||
80 | 83 | ||
81 | /*==============================================================================*/ | 84 | /*==============================================================================*/ |
82 | 85 | ||
@@ -111,12 +114,14 @@ struct bas_cardstate { | |||
111 | }; | 114 | }; |
112 | 115 | ||
113 | /* status of direct USB connection to 307x base (bits in basstate) */ | 116 | /* status of direct USB connection to 307x base (bits in basstate) */ |
114 | #define BS_ATOPEN 0x001 | 117 | #define BS_ATOPEN 0x001 /* AT channel open */ |
115 | #define BS_B1OPEN 0x002 | 118 | #define BS_B1OPEN 0x002 /* B channel 1 open */ |
116 | #define BS_B2OPEN 0x004 | 119 | #define BS_B2OPEN 0x004 /* B channel 2 open */ |
117 | #define BS_ATREADY 0x008 | 120 | #define BS_ATREADY 0x008 /* base ready for AT command */ |
118 | #define BS_INIT 0x010 | 121 | #define BS_INIT 0x010 /* base has signalled INIT_OK */ |
119 | #define BS_ATTIMER 0x020 | 122 | #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ |
123 | #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ | ||
124 | #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ | ||
120 | 125 | ||
121 | 126 | ||
122 | static struct gigaset_driver *driver = NULL; | 127 | static struct gigaset_driver *driver = NULL; |
@@ -130,6 +135,47 @@ static struct usb_driver gigaset_usb_driver = { | |||
130 | .id_table = gigaset_table, | 135 | .id_table = gigaset_table, |
131 | }; | 136 | }; |
132 | 137 | ||
138 | /* get message text for usb_submit_urb return code | ||
139 | */ | ||
140 | static char *get_usb_rcmsg(int rc) | ||
141 | { | ||
142 | static char unkmsg[28]; | ||
143 | |||
144 | switch (rc) { | ||
145 | case 0: | ||
146 | return "success"; | ||
147 | case -ENOMEM: | ||
148 | return "out of memory"; | ||
149 | case -ENODEV: | ||
150 | return "device not present"; | ||
151 | case -ENOENT: | ||
152 | return "endpoint not present"; | ||
153 | case -ENXIO: | ||
154 | return "URB type not supported"; | ||
155 | case -EINVAL: | ||
156 | return "invalid argument"; | ||
157 | case -EAGAIN: | ||
158 | return "start frame too early or too much scheduled"; | ||
159 | case -EFBIG: | ||
160 | return "too many isochronous frames requested"; | ||
161 | case -EPIPE: | ||
162 | return "endpoint stalled"; | ||
163 | case -EMSGSIZE: | ||
164 | return "invalid packet size"; | ||
165 | case -ENOSPC: | ||
166 | return "would overcommit USB bandwidth"; | ||
167 | case -ESHUTDOWN: | ||
168 | return "device shut down"; | ||
169 | case -EPERM: | ||
170 | return "reject flag set"; | ||
171 | case -EHOSTUNREACH: | ||
172 | return "device suspended"; | ||
173 | default: | ||
174 | snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc); | ||
175 | return unkmsg; | ||
176 | } | ||
177 | } | ||
178 | |||
133 | /* get message text for USB status code | 179 | /* get message text for USB status code |
134 | */ | 180 | */ |
135 | static char *get_usb_statmsg(int status) | 181 | static char *get_usb_statmsg(int status) |
@@ -140,43 +186,37 @@ static char *get_usb_statmsg(int status) | |||
140 | case 0: | 186 | case 0: |
141 | return "success"; | 187 | return "success"; |
142 | case -ENOENT: | 188 | case -ENOENT: |
143 | return "canceled"; | 189 | return "unlinked (sync)"; |
144 | case -ECONNRESET: | ||
145 | return "canceled (async)"; | ||
146 | case -EINPROGRESS: | 190 | case -EINPROGRESS: |
147 | return "pending"; | 191 | return "pending"; |
148 | case -EPROTO: | 192 | case -EPROTO: |
149 | return "bit stuffing or unknown USB error"; | 193 | return "bit stuffing error, timeout, or unknown USB error"; |
150 | case -EILSEQ: | 194 | case -EILSEQ: |
151 | return "Illegal byte sequence (CRC mismatch)"; | 195 | return "CRC mismatch, timeout, or unknown USB error"; |
152 | case -EPIPE: | ||
153 | return "babble detect or endpoint stalled"; | ||
154 | case -ENOSR: | ||
155 | return "buffer error"; | ||
156 | case -ETIMEDOUT: | 196 | case -ETIMEDOUT: |
157 | return "timed out"; | 197 | return "timed out"; |
158 | case -ENODEV: | 198 | case -EPIPE: |
159 | return "device not present"; | 199 | return "endpoint stalled"; |
200 | case -ECOMM: | ||
201 | return "IN buffer overrun"; | ||
202 | case -ENOSR: | ||
203 | return "OUT buffer underrun"; | ||
204 | case -EOVERFLOW: | ||
205 | return "too much data"; | ||
160 | case -EREMOTEIO: | 206 | case -EREMOTEIO: |
161 | return "short packet detected"; | 207 | return "short packet detected"; |
208 | case -ENODEV: | ||
209 | return "device removed"; | ||
162 | case -EXDEV: | 210 | case -EXDEV: |
163 | return "partial isochronous transfer"; | 211 | return "partial isochronous transfer"; |
164 | case -EINVAL: | 212 | case -EINVAL: |
165 | return "invalid argument"; | 213 | return "invalid argument"; |
166 | case -ENXIO: | 214 | case -ECONNRESET: |
167 | return "URB already queued"; | 215 | return "unlinked (async)"; |
168 | case -EAGAIN: | ||
169 | return "isochronous start frame too early or too much scheduled"; | ||
170 | case -EFBIG: | ||
171 | return "too many isochronous frames requested"; | ||
172 | case -EMSGSIZE: | ||
173 | return "endpoint message size zero"; | ||
174 | case -ESHUTDOWN: | 216 | case -ESHUTDOWN: |
175 | return "endpoint shutdown"; | 217 | return "device shut down"; |
176 | case -EBUSY: | ||
177 | return "another request pending"; | ||
178 | default: | 218 | default: |
179 | snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status); | 219 | snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status); |
180 | return unkmsg; | 220 | return unkmsg; |
181 | } | 221 | } |
182 | } | 222 | } |
@@ -277,18 +317,17 @@ static inline void error_hangup(struct bc_state *bcs) | |||
277 | gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", | 317 | gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", |
278 | __func__, bcs->channel); | 318 | __func__, bcs->channel); |
279 | 319 | ||
280 | if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { | 320 | if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) |
281 | //FIXME what should we do? | 321 | dev_err(cs->dev, "event queue full\n"); |
282 | return; | ||
283 | } | ||
284 | 322 | ||
285 | gigaset_schedule_event(cs); | 323 | gigaset_schedule_event(cs); |
286 | } | 324 | } |
287 | 325 | ||
288 | /* error_reset | 326 | /* error_reset |
289 | * reset Gigaset device because of an unrecoverable error | 327 | * reset Gigaset device because of an unrecoverable error |
290 | * This function may be called from any context and takes care of scheduling | 328 | * This function may be called from any context, and should take care of |
291 | * the necessary actions for execution outside of interrupt context. | 329 | * scheduling the necessary actions for execution outside of interrupt context. |
330 | * Right now, it just generates a kernel message calling for help. | ||
292 | * argument: | 331 | * argument: |
293 | * controller state structure | 332 | * controller state structure |
294 | */ | 333 | */ |
@@ -364,36 +403,38 @@ static void cmd_in_timeout(unsigned long data) | |||
364 | { | 403 | { |
365 | struct cardstate *cs = (struct cardstate *) data; | 404 | struct cardstate *cs = (struct cardstate *) data; |
366 | struct bas_cardstate *ucs = cs->hw.bas; | 405 | struct bas_cardstate *ucs = cs->hw.bas; |
367 | unsigned long flags; | ||
368 | 406 | ||
369 | spin_lock_irqsave(&cs->lock, flags); | ||
370 | if (unlikely(!cs->connected)) { | ||
371 | gig_dbg(DEBUG_USBREQ, "%s: disconnected", __func__); | ||
372 | spin_unlock_irqrestore(&cs->lock, flags); | ||
373 | return; | ||
374 | } | ||
375 | if (!ucs->rcvbuf_size) { | 407 | if (!ucs->rcvbuf_size) { |
376 | gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); | 408 | gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); |
377 | spin_unlock_irqrestore(&cs->lock, flags); | ||
378 | return; | 409 | return; |
379 | } | 410 | } |
380 | spin_unlock_irqrestore(&cs->lock, flags); | ||
381 | 411 | ||
382 | dev_err(cs->dev, "timeout reading AT response\n"); | 412 | dev_err(cs->dev, "timeout reading AT response\n"); |
383 | error_reset(cs); //FIXME retry? | 413 | error_reset(cs); //FIXME retry? |
384 | } | 414 | } |
385 | 415 | ||
416 | /* set/clear bits in base connection state, return previous state | ||
417 | */ | ||
418 | inline static int update_basstate(struct bas_cardstate *ucs, | ||
419 | int set, int clear) | ||
420 | { | ||
421 | unsigned long flags; | ||
422 | int state; | ||
386 | 423 | ||
387 | static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs); | 424 | spin_lock_irqsave(&ucs->lock, flags); |
425 | state = atomic_read(&ucs->basstate); | ||
426 | atomic_set(&ucs->basstate, (state & ~clear) | set); | ||
427 | spin_unlock_irqrestore(&ucs->lock, flags); | ||
428 | return state; | ||
429 | } | ||
388 | 430 | ||
389 | /* atread_submit | 431 | /* atread_submit |
390 | * submit an HD_READ_ATMESSAGE command URB | 432 | * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout |
391 | * parameters: | 433 | * parameters: |
392 | * cs controller state structure | 434 | * cs controller state structure |
393 | * timeout timeout in 1/10 sec., 0: none | 435 | * timeout timeout in 1/10 sec., 0: none |
394 | * return value: | 436 | * return value: |
395 | * 0 on success | 437 | * 0 on success |
396 | * -EINVAL if a NULL pointer is encountered somewhere | ||
397 | * -EBUSY if another request is pending | 438 | * -EBUSY if another request is pending |
398 | * any URB submission error code | 439 | * any URB submission error code |
399 | */ | 440 | */ |
@@ -405,7 +446,7 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
405 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", | 446 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", |
406 | ucs->rcvbuf_size); | 447 | ucs->rcvbuf_size); |
407 | 448 | ||
408 | if (ucs->urb_cmd_in->status == -EINPROGRESS) { | 449 | if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) { |
409 | dev_err(cs->dev, | 450 | dev_err(cs->dev, |
410 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); | 451 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); |
411 | return -EBUSY; | 452 | return -EBUSY; |
@@ -423,6 +464,7 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
423 | read_ctrl_callback, cs->inbuf); | 464 | read_ctrl_callback, cs->inbuf); |
424 | 465 | ||
425 | if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { | 466 | if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { |
467 | update_basstate(ucs, 0, BS_ATRDPEND); | ||
426 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", | 468 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", |
427 | get_usb_statmsg(ret)); | 469 | get_usb_statmsg(ret)); |
428 | return ret; | 470 | return ret; |
@@ -438,26 +480,6 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
438 | return 0; | 480 | return 0; |
439 | } | 481 | } |
440 | 482 | ||
441 | static void stopurbs(struct bas_bc_state *); | ||
442 | static int start_cbsend(struct cardstate *); | ||
443 | |||
444 | /* set/clear bits in base connection state | ||
445 | */ | ||
446 | inline static void update_basstate(struct bas_cardstate *ucs, | ||
447 | int set, int clear) | ||
448 | { | ||
449 | unsigned long flags; | ||
450 | int state; | ||
451 | |||
452 | spin_lock_irqsave(&ucs->lock, flags); | ||
453 | state = atomic_read(&ucs->basstate); | ||
454 | state &= ~clear; | ||
455 | state |= set; | ||
456 | atomic_set(&ucs->basstate, state); | ||
457 | spin_unlock_irqrestore(&ucs->lock, flags); | ||
458 | } | ||
459 | |||
460 | |||
461 | /* read_int_callback | 483 | /* read_int_callback |
462 | * USB completion handler for interrupt pipe input | 484 | * USB completion handler for interrupt pipe input |
463 | * called by the USB subsystem in interrupt context | 485 | * called by the USB subsystem in interrupt context |
@@ -471,20 +493,25 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
471 | struct bas_cardstate *ucs = cs->hw.bas; | 493 | struct bas_cardstate *ucs = cs->hw.bas; |
472 | struct bc_state *bcs; | 494 | struct bc_state *bcs; |
473 | unsigned long flags; | 495 | unsigned long flags; |
474 | int status; | 496 | int rc; |
475 | unsigned l; | 497 | unsigned l; |
476 | int channel; | 498 | int channel; |
477 | 499 | ||
478 | switch (urb->status) { | 500 | switch (urb->status) { |
479 | case 0: /* success */ | 501 | case 0: /* success */ |
480 | break; | 502 | break; |
481 | case -ENOENT: /* canceled */ | 503 | case -ENOENT: /* cancelled */ |
482 | case -ECONNRESET: /* canceled (async) */ | 504 | case -ECONNRESET: /* cancelled (async) */ |
483 | case -EINPROGRESS: /* pending */ | 505 | case -EINPROGRESS: /* pending */ |
484 | /* ignore silently */ | 506 | /* ignore silently */ |
485 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 507 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
486 | __func__, get_usb_statmsg(urb->status)); | 508 | __func__, get_usb_statmsg(urb->status)); |
487 | return; | 509 | return; |
510 | case -ENODEV: /* device removed */ | ||
511 | case -ESHUTDOWN: /* device shut down */ | ||
512 | //FIXME use this as disconnect indicator? | ||
513 | gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); | ||
514 | return; | ||
488 | default: /* severe trouble */ | 515 | default: /* severe trouble */ |
489 | dev_warn(cs->dev, "interrupt read: %s\n", | 516 | dev_warn(cs->dev, "interrupt read: %s\n", |
490 | get_usb_statmsg(urb->status)); | 517 | get_usb_statmsg(urb->status)); |
@@ -492,6 +519,13 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
492 | goto resubmit; | 519 | goto resubmit; |
493 | } | 520 | } |
494 | 521 | ||
522 | /* drop incomplete packets even if the missing bytes wouldn't matter */ | ||
523 | if (unlikely(urb->actual_length < 3)) { | ||
524 | dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n", | ||
525 | urb->actual_length); | ||
526 | goto resubmit; | ||
527 | } | ||
528 | |||
495 | l = (unsigned) ucs->int_in_buf[1] + | 529 | l = (unsigned) ucs->int_in_buf[1] + |
496 | (((unsigned) ucs->int_in_buf[2]) << 8); | 530 | (((unsigned) ucs->int_in_buf[2]) << 8); |
497 | 531 | ||
@@ -558,25 +592,28 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
558 | } | 592 | } |
559 | spin_lock_irqsave(&cs->lock, flags); | 593 | spin_lock_irqsave(&cs->lock, flags); |
560 | if (ucs->rcvbuf_size) { | 594 | if (ucs->rcvbuf_size) { |
561 | spin_unlock_irqrestore(&cs->lock, flags); | 595 | /* throw away previous buffer - we have no queue */ |
562 | dev_err(cs->dev, | 596 | dev_err(cs->dev, |
563 | "receive AT data overrun, %d bytes lost\n", l); | 597 | "receive AT data overrun, %d bytes lost\n", |
564 | error_reset(cs); //FIXME reschedule | 598 | ucs->rcvbuf_size); |
565 | break; | 599 | kfree(ucs->rcvbuf); |
600 | ucs->rcvbuf_size = 0; | ||
566 | } | 601 | } |
567 | if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { | 602 | if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { |
568 | spin_unlock_irqrestore(&cs->lock, flags); | 603 | spin_unlock_irqrestore(&cs->lock, flags); |
569 | dev_err(cs->dev, "out of memory, %d bytes lost\n", l); | 604 | dev_err(cs->dev, "out of memory receiving AT data\n"); |
570 | error_reset(cs); //FIXME reschedule | 605 | error_reset(cs); |
571 | break; | 606 | break; |
572 | } | 607 | } |
573 | ucs->rcvbuf_size = l; | 608 | ucs->rcvbuf_size = l; |
574 | ucs->retry_cmd_in = 0; | 609 | ucs->retry_cmd_in = 0; |
575 | if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) { | 610 | if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) { |
576 | kfree(ucs->rcvbuf); | 611 | kfree(ucs->rcvbuf); |
577 | ucs->rcvbuf = NULL; | 612 | ucs->rcvbuf = NULL; |
578 | ucs->rcvbuf_size = 0; | 613 | ucs->rcvbuf_size = 0; |
579 | error_reset(cs); //FIXME reschedule | 614 | if (rc != -ENODEV) |
615 | //FIXME corrective action? | ||
616 | error_reset(cs); | ||
580 | } | 617 | } |
581 | spin_unlock_irqrestore(&cs->lock, flags); | 618 | spin_unlock_irqrestore(&cs->lock, flags); |
582 | break; | 619 | break; |
@@ -598,12 +635,10 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) | |||
598 | check_pending(ucs); | 635 | check_pending(ucs); |
599 | 636 | ||
600 | resubmit: | 637 | resubmit: |
601 | spin_lock_irqsave(&cs->lock, flags); | 638 | rc = usb_submit_urb(urb, SLAB_ATOMIC); |
602 | status = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; | 639 | if (unlikely(rc != 0 && rc != -ENODEV)) { |
603 | spin_unlock_irqrestore(&cs->lock, flags); | ||
604 | if (unlikely(status)) { | ||
605 | dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", | 640 | dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", |
606 | get_usb_statmsg(status)); | 641 | get_usb_rcmsg(rc)); |
607 | error_reset(cs); | 642 | error_reset(cs); |
608 | } | 643 | } |
609 | } | 644 | } |
@@ -622,18 +657,12 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
622 | struct bas_cardstate *ucs = cs->hw.bas; | 657 | struct bas_cardstate *ucs = cs->hw.bas; |
623 | int have_data = 0; | 658 | int have_data = 0; |
624 | unsigned numbytes; | 659 | unsigned numbytes; |
625 | unsigned long flags; | 660 | int rc; |
626 | 661 | ||
627 | spin_lock_irqsave(&cs->lock, flags); | 662 | update_basstate(ucs, 0, BS_ATRDPEND); |
628 | if (unlikely(!cs->connected)) { | ||
629 | warn("%s: disconnected", __func__); | ||
630 | spin_unlock_irqrestore(&cs->lock, flags); | ||
631 | return; | ||
632 | } | ||
633 | 663 | ||
634 | if (!ucs->rcvbuf_size) { | 664 | if (!ucs->rcvbuf_size) { |
635 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); | 665 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); |
636 | spin_unlock_irqrestore(&cs->lock, flags); | ||
637 | return; | 666 | return; |
638 | } | 667 | } |
639 | 668 | ||
@@ -666,9 +695,11 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
666 | } | 695 | } |
667 | break; | 696 | break; |
668 | 697 | ||
669 | case -ENOENT: /* canceled */ | 698 | case -ENOENT: /* cancelled */ |
670 | case -ECONNRESET: /* canceled (async) */ | 699 | case -ECONNRESET: /* cancelled (async) */ |
671 | case -EINPROGRESS: /* pending */ | 700 | case -EINPROGRESS: /* pending */ |
701 | case -ENODEV: /* device removed */ | ||
702 | case -ESHUTDOWN: /* device shut down */ | ||
672 | /* no action necessary */ | 703 | /* no action necessary */ |
673 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 704 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
674 | __func__, get_usb_statmsg(urb->status)); | 705 | __func__, get_usb_statmsg(urb->status)); |
@@ -681,11 +712,11 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
681 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | 712 | if (ucs->retry_cmd_in++ < BAS_RETRY) { |
682 | dev_notice(cs->dev, "control read: retry %d\n", | 713 | dev_notice(cs->dev, "control read: retry %d\n", |
683 | ucs->retry_cmd_in); | 714 | ucs->retry_cmd_in); |
684 | if (atread_submit(cs, BAS_TIMEOUT) >= 0) { | 715 | rc = atread_submit(cs, BAS_TIMEOUT); |
685 | /* resubmitted - bypass regular exit block */ | 716 | if (rc >= 0 || rc == -ENODEV) |
686 | spin_unlock_irqrestore(&cs->lock, flags); | 717 | /* resubmitted or disconnected */ |
718 | /* - bypass regular exit block */ | ||
687 | return; | 719 | return; |
688 | } | ||
689 | } else { | 720 | } else { |
690 | dev_err(cs->dev, | 721 | dev_err(cs->dev, |
691 | "control read: giving up after %d tries\n", | 722 | "control read: giving up after %d tries\n", |
@@ -697,7 +728,6 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
697 | kfree(ucs->rcvbuf); | 728 | kfree(ucs->rcvbuf); |
698 | ucs->rcvbuf = NULL; | 729 | ucs->rcvbuf = NULL; |
699 | ucs->rcvbuf_size = 0; | 730 | ucs->rcvbuf_size = 0; |
700 | spin_unlock_irqrestore(&cs->lock, flags); | ||
701 | if (have_data) { | 731 | if (have_data) { |
702 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); | 732 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); |
703 | gigaset_schedule_event(cs); | 733 | gigaset_schedule_event(cs); |
@@ -719,8 +749,11 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) | |||
719 | int i, rc; | 749 | int i, rc; |
720 | 750 | ||
721 | /* status codes not worth bothering the tasklet with */ | 751 | /* status codes not worth bothering the tasklet with */ |
722 | if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || | 752 | if (unlikely(urb->status == -ENOENT || |
723 | urb->status == -EINPROGRESS)) { | 753 | urb->status == -ECONNRESET || |
754 | urb->status == -EINPROGRESS || | ||
755 | urb->status == -ENODEV || | ||
756 | urb->status == -ESHUTDOWN)) { | ||
724 | gig_dbg(DEBUG_ISO, "%s: %s", | 757 | gig_dbg(DEBUG_ISO, "%s: %s", |
725 | __func__, get_usb_statmsg(urb->status)); | 758 | __func__, get_usb_statmsg(urb->status)); |
726 | return; | 759 | return; |
@@ -740,9 +773,9 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) | |||
740 | for (i = 0; i < BAS_NUMFRAMES; i++) { | 773 | for (i = 0; i < BAS_NUMFRAMES; i++) { |
741 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; | 774 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; |
742 | if (unlikely(urb->iso_frame_desc[i].status != 0 && | 775 | if (unlikely(urb->iso_frame_desc[i].status != 0 && |
743 | urb->iso_frame_desc[i].status != -EINPROGRESS)) { | 776 | urb->iso_frame_desc[i].status != |
777 | -EINPROGRESS)) | ||
744 | ubc->loststatus = urb->iso_frame_desc[i].status; | 778 | ubc->loststatus = urb->iso_frame_desc[i].status; |
745 | } | ||
746 | urb->iso_frame_desc[i].status = 0; | 779 | urb->iso_frame_desc[i].status = 0; |
747 | urb->iso_frame_desc[i].actual_length = 0; | 780 | urb->iso_frame_desc[i].actual_length = 0; |
748 | } | 781 | } |
@@ -754,10 +787,10 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) | |||
754 | gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", | 787 | gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", |
755 | __func__); | 788 | __func__); |
756 | rc = usb_submit_urb(urb, SLAB_ATOMIC); | 789 | rc = usb_submit_urb(urb, SLAB_ATOMIC); |
757 | if (unlikely(rc != 0)) { | 790 | if (unlikely(rc != 0 && rc != -ENODEV)) { |
758 | dev_err(bcs->cs->dev, | 791 | dev_err(bcs->cs->dev, |
759 | "could not resubmit isochronous read " | 792 | "could not resubmit isochronous read " |
760 | "URB: %s\n", get_usb_statmsg(rc)); | 793 | "URB: %s\n", get_usb_rcmsg(rc)); |
761 | dump_urb(DEBUG_ISO, "isoc read", urb); | 794 | dump_urb(DEBUG_ISO, "isoc read", urb); |
762 | error_hangup(bcs); | 795 | error_hangup(bcs); |
763 | } | 796 | } |
@@ -780,8 +813,11 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs) | |||
780 | unsigned long flags; | 813 | unsigned long flags; |
781 | 814 | ||
782 | /* status codes not worth bothering the tasklet with */ | 815 | /* status codes not worth bothering the tasklet with */ |
783 | if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || | 816 | if (unlikely(urb->status == -ENOENT || |
784 | urb->status == -EINPROGRESS)) { | 817 | urb->status == -ECONNRESET || |
818 | urb->status == -EINPROGRESS || | ||
819 | urb->status == -ENODEV || | ||
820 | urb->status == -ESHUTDOWN)) { | ||
785 | gig_dbg(DEBUG_ISO, "%s: %s", | 821 | gig_dbg(DEBUG_ISO, "%s: %s", |
786 | __func__, get_usb_statmsg(urb->status)); | 822 | __func__, get_usb_statmsg(urb->status)); |
787 | return; | 823 | return; |
@@ -822,7 +858,6 @@ static int starturbs(struct bc_state *bcs) | |||
822 | for (k = 0; k < BAS_INURBS; k++) { | 858 | for (k = 0; k < BAS_INURBS; k++) { |
823 | urb = ubc->isoinurbs[k]; | 859 | urb = ubc->isoinurbs[k]; |
824 | if (!urb) { | 860 | if (!urb) { |
825 | dev_err(bcs->cs->dev, "isoinurbs[%d]==NULL\n", k); | ||
826 | rc = -EFAULT; | 861 | rc = -EFAULT; |
827 | goto error; | 862 | goto error; |
828 | } | 863 | } |
@@ -844,12 +879,8 @@ static int starturbs(struct bc_state *bcs) | |||
844 | } | 879 | } |
845 | 880 | ||
846 | dump_urb(DEBUG_ISO, "Initial isoc read", urb); | 881 | dump_urb(DEBUG_ISO, "Initial isoc read", urb); |
847 | if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { | 882 | if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) |
848 | dev_err(bcs->cs->dev, | ||
849 | "could not submit isochronous read URB %d: %s\n", | ||
850 | k, get_usb_statmsg(rc)); | ||
851 | goto error; | 883 | goto error; |
852 | } | ||
853 | } | 884 | } |
854 | 885 | ||
855 | /* initialize L2 transmission */ | 886 | /* initialize L2 transmission */ |
@@ -859,7 +890,6 @@ static int starturbs(struct bc_state *bcs) | |||
859 | for (k = 0; k < BAS_OUTURBS; ++k) { | 890 | for (k = 0; k < BAS_OUTURBS; ++k) { |
860 | urb = ubc->isoouturbs[k].urb; | 891 | urb = ubc->isoouturbs[k].urb; |
861 | if (!urb) { | 892 | if (!urb) { |
862 | dev_err(bcs->cs->dev, "isoouturbs[%d].urb==NULL\n", k); | ||
863 | rc = -EFAULT; | 893 | rc = -EFAULT; |
864 | goto error; | 894 | goto error; |
865 | } | 895 | } |
@@ -885,12 +915,8 @@ static int starturbs(struct bc_state *bcs) | |||
885 | for (k = 0; k < 2; ++k) { | 915 | for (k = 0; k < 2; ++k) { |
886 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); | 916 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); |
887 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC); | 917 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC); |
888 | if (rc != 0) { | 918 | if (rc != 0) |
889 | dev_err(bcs->cs->dev, | ||
890 | "could not submit isochronous write URB %d: %s\n", | ||
891 | k, get_usb_statmsg(rc)); | ||
892 | goto error; | 919 | goto error; |
893 | } | ||
894 | } | 920 | } |
895 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); | 921 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); |
896 | ubc->isooutfree = &ubc->isoouturbs[2]; | 922 | ubc->isooutfree = &ubc->isoouturbs[2]; |
@@ -916,15 +942,15 @@ static void stopurbs(struct bas_bc_state *ubc) | |||
916 | for (k = 0; k < BAS_INURBS; ++k) { | 942 | for (k = 0; k < BAS_INURBS; ++k) { |
917 | rc = usb_unlink_urb(ubc->isoinurbs[k]); | 943 | rc = usb_unlink_urb(ubc->isoinurbs[k]); |
918 | gig_dbg(DEBUG_ISO, | 944 | gig_dbg(DEBUG_ISO, |
919 | "%s: isoc input URB %d unlinked, result = %d", | 945 | "%s: isoc input URB %d unlinked, result = %s", |
920 | __func__, k, rc); | 946 | __func__, k, get_usb_rcmsg(rc)); |
921 | } | 947 | } |
922 | 948 | ||
923 | for (k = 0; k < BAS_OUTURBS; ++k) { | 949 | for (k = 0; k < BAS_OUTURBS; ++k) { |
924 | rc = usb_unlink_urb(ubc->isoouturbs[k].urb); | 950 | rc = usb_unlink_urb(ubc->isoouturbs[k].urb); |
925 | gig_dbg(DEBUG_ISO, | 951 | gig_dbg(DEBUG_ISO, |
926 | "%s: isoc output URB %d unlinked, result = %d", | 952 | "%s: isoc output URB %d unlinked, result = %s", |
927 | __func__, k, rc); | 953 | __func__, k, get_usb_rcmsg(rc)); |
928 | } | 954 | } |
929 | } | 955 | } |
930 | 956 | ||
@@ -934,7 +960,7 @@ static void stopurbs(struct bas_bc_state *ubc) | |||
934 | /* submit_iso_write_urb | 960 | /* submit_iso_write_urb |
935 | * fill and submit the next isochronous write URB | 961 | * fill and submit the next isochronous write URB |
936 | * parameters: | 962 | * parameters: |
937 | * bcs B channel state structure | 963 | * ucx context structure containing URB |
938 | * return value: | 964 | * return value: |
939 | * number of frames submitted in URB | 965 | * number of frames submitted in URB |
940 | * 0 if URB not submitted because no data available (isooutbuf busy) | 966 | * 0 if URB not submitted because no data available (isooutbuf busy) |
@@ -946,7 +972,6 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
946 | struct bas_bc_state *ubc = ucx->bcs->hw.bas; | 972 | struct bas_bc_state *ubc = ucx->bcs->hw.bas; |
947 | struct usb_iso_packet_descriptor *ifd; | 973 | struct usb_iso_packet_descriptor *ifd; |
948 | int corrbytes, nframe, rc; | 974 | int corrbytes, nframe, rc; |
949 | unsigned long flags; | ||
950 | 975 | ||
951 | /* urb->dev is clobbered by USB subsystem */ | 976 | /* urb->dev is clobbered by USB subsystem */ |
952 | urb->dev = ucx->bcs->cs->hw.bas->udev; | 977 | urb->dev = ucx->bcs->cs->hw.bas->udev; |
@@ -992,20 +1017,22 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
992 | ifd->status = 0; | 1017 | ifd->status = 0; |
993 | ifd->actual_length = 0; | 1018 | ifd->actual_length = 0; |
994 | } | 1019 | } |
995 | if ((urb->number_of_packets = nframe) > 0) { | 1020 | if (unlikely(nframe == 0)) |
996 | spin_lock_irqsave(&ucx->bcs->cs->lock, flags); | 1021 | return 0; /* no data to send */ |
997 | rc = ucx->bcs->cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; | 1022 | urb->number_of_packets = nframe; |
998 | spin_unlock_irqrestore(&ucx->bcs->cs->lock, flags); | ||
999 | 1023 | ||
1000 | if (rc) { | 1024 | rc = usb_submit_urb(urb, SLAB_ATOMIC); |
1025 | if (unlikely(rc)) { | ||
1026 | if (rc == -ENODEV) | ||
1027 | /* device removed - give up silently */ | ||
1028 | gig_dbg(DEBUG_ISO, "%s: disconnected", __func__); | ||
1029 | else | ||
1001 | dev_err(ucx->bcs->cs->dev, | 1030 | dev_err(ucx->bcs->cs->dev, |
1002 | "could not submit isochronous write URB: %s\n", | 1031 | "could not submit isochronous write URB: %s\n", |
1003 | get_usb_statmsg(rc)); | 1032 | get_usb_rcmsg(rc)); |
1004 | dump_urb(DEBUG_ISO, "isoc write", urb); | 1033 | return rc; |
1005 | return rc; | ||
1006 | } | ||
1007 | ++ubc->numsub; | ||
1008 | } | 1034 | } |
1035 | ++ubc->numsub; | ||
1009 | return nframe; | 1036 | return nframe; |
1010 | } | 1037 | } |
1011 | 1038 | ||
@@ -1028,6 +1055,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1028 | int i; | 1055 | int i; |
1029 | struct sk_buff *skb; | 1056 | struct sk_buff *skb; |
1030 | int len; | 1057 | int len; |
1058 | int rc; | ||
1031 | 1059 | ||
1032 | /* loop while completed URBs arrive in time */ | 1060 | /* loop while completed URBs arrive in time */ |
1033 | for (;;) { | 1061 | for (;;) { |
@@ -1057,7 +1085,8 @@ static void write_iso_tasklet(unsigned long data) | |||
1057 | ubc->isooutfree = NULL; | 1085 | ubc->isooutfree = NULL; |
1058 | spin_unlock_irqrestore(&ubc->isooutlock, flags); | 1086 | spin_unlock_irqrestore(&ubc->isooutlock, flags); |
1059 | if (next) { | 1087 | if (next) { |
1060 | if (submit_iso_write_urb(next) <= 0) { | 1088 | rc = submit_iso_write_urb(next); |
1089 | if (unlikely(rc <= 0 && rc != -ENODEV)) { | ||
1061 | /* could not submit URB, put it back */ | 1090 | /* could not submit URB, put it back */ |
1062 | spin_lock_irqsave(&ubc->isooutlock, flags); | 1091 | spin_lock_irqsave(&ubc->isooutlock, flags); |
1063 | if (ubc->isooutfree == NULL) { | 1092 | if (ubc->isooutfree == NULL) { |
@@ -1077,17 +1106,18 @@ static void write_iso_tasklet(unsigned long data) | |||
1077 | /* process completed URB */ | 1106 | /* process completed URB */ |
1078 | urb = done->urb; | 1107 | urb = done->urb; |
1079 | switch (urb->status) { | 1108 | switch (urb->status) { |
1109 | case -EXDEV: /* partial completion */ | ||
1110 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", | ||
1111 | __func__); | ||
1112 | /* fall through - what's the difference anyway? */ | ||
1080 | case 0: /* normal completion */ | 1113 | case 0: /* normal completion */ |
1081 | break; | 1114 | /* inspect individual frames |
1082 | case -EXDEV: /* inspect individual frames */ | 1115 | * assumptions (for lack of documentation): |
1083 | /* assumptions (for lack of documentation): | 1116 | * - actual_length bytes of first frame in error are |
1084 | * - actual_length bytes of the frame in error are | ||
1085 | * successfully sent | 1117 | * successfully sent |
1086 | * - all following frames are not sent at all | 1118 | * - all following frames are not sent at all |
1087 | */ | 1119 | */ |
1088 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", | 1120 | offset = done->limit; /* default (no error) */ |
1089 | __func__); | ||
1090 | offset = done->limit; /* just in case */ | ||
1091 | for (i = 0; i < BAS_NUMFRAMES; i++) { | 1121 | for (i = 0; i < BAS_NUMFRAMES; i++) { |
1092 | ifd = &urb->iso_frame_desc[i]; | 1122 | ifd = &urb->iso_frame_desc[i]; |
1093 | if (ifd->status || | 1123 | if (ifd->status || |
@@ -1122,7 +1152,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1122 | } | 1152 | } |
1123 | #endif | 1153 | #endif |
1124 | break; | 1154 | break; |
1125 | case -EPIPE: //FIXME is this the code for "underrun"? | 1155 | case -EPIPE: /* stall - probably underrun */ |
1126 | dev_err(cs->dev, "isochronous write stalled\n"); | 1156 | dev_err(cs->dev, "isochronous write stalled\n"); |
1127 | error_hangup(bcs); | 1157 | error_hangup(bcs); |
1128 | break; | 1158 | break; |
@@ -1142,7 +1172,8 @@ static void write_iso_tasklet(unsigned long data) | |||
1142 | spin_unlock_irqrestore(&ubc->isooutlock, flags); | 1172 | spin_unlock_irqrestore(&ubc->isooutlock, flags); |
1143 | if (next) { | 1173 | if (next) { |
1144 | /* only one URB still active - resubmit one */ | 1174 | /* only one URB still active - resubmit one */ |
1145 | if (submit_iso_write_urb(next) <= 0) { | 1175 | rc = submit_iso_write_urb(next); |
1176 | if (unlikely(rc <= 0 && rc != -ENODEV)) { | ||
1146 | /* couldn't submit */ | 1177 | /* couldn't submit */ |
1147 | error_hangup(bcs); | 1178 | error_hangup(bcs); |
1148 | } | 1179 | } |
@@ -1222,10 +1253,9 @@ static void read_iso_tasklet(unsigned long data) | |||
1222 | break; | 1253 | break; |
1223 | case -ENOENT: | 1254 | case -ENOENT: |
1224 | case -ECONNRESET: | 1255 | case -ECONNRESET: |
1225 | gig_dbg(DEBUG_ISO, "%s: URB canceled", __func__); | 1256 | case -EINPROGRESS: |
1226 | continue; /* -> skip */ | 1257 | gig_dbg(DEBUG_ISO, "%s: %s", |
1227 | case -EINPROGRESS: /* huh? */ | 1258 | __func__, get_usb_statmsg(urb->status)); |
1228 | gig_dbg(DEBUG_ISO, "%s: URB still pending", __func__); | ||
1229 | continue; /* -> skip */ | 1259 | continue; /* -> skip */ |
1230 | case -EPIPE: | 1260 | case -EPIPE: |
1231 | dev_err(cs->dev, "isochronous read stalled\n"); | 1261 | dev_err(cs->dev, "isochronous read stalled\n"); |
@@ -1290,13 +1320,11 @@ static void read_iso_tasklet(unsigned long data) | |||
1290 | urb->dev = bcs->cs->hw.bas->udev; | 1320 | urb->dev = bcs->cs->hw.bas->udev; |
1291 | urb->transfer_flags = URB_ISO_ASAP; | 1321 | urb->transfer_flags = URB_ISO_ASAP; |
1292 | urb->number_of_packets = BAS_NUMFRAMES; | 1322 | urb->number_of_packets = BAS_NUMFRAMES; |
1293 | spin_lock_irqsave(&cs->lock, flags); | 1323 | rc = usb_submit_urb(urb, SLAB_ATOMIC); |
1294 | rc = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; | 1324 | if (unlikely(rc != 0 && rc != -ENODEV)) { |
1295 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1296 | if (rc) { | ||
1297 | dev_err(cs->dev, | 1325 | dev_err(cs->dev, |
1298 | "could not resubmit isochronous read URB: %s\n", | 1326 | "could not resubmit isochronous read URB: %s\n", |
1299 | get_usb_statmsg(rc)); | 1327 | get_usb_rcmsg(rc)); |
1300 | dump_urb(DEBUG_ISO, "resubmit iso read", urb); | 1328 | dump_urb(DEBUG_ISO, "resubmit iso read", urb); |
1301 | error_hangup(bcs); | 1329 | error_hangup(bcs); |
1302 | } | 1330 | } |
@@ -1397,7 +1425,6 @@ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) | |||
1397 | * timeout timeout in seconds (0: no timeout) | 1425 | * timeout timeout in seconds (0: no timeout) |
1398 | * return value: | 1426 | * return value: |
1399 | * 0 on success | 1427 | * 0 on success |
1400 | * -EINVAL if a NULL pointer is encountered somewhere | ||
1401 | * -EBUSY if another request is pending | 1428 | * -EBUSY if another request is pending |
1402 | * any URB submission error code | 1429 | * any URB submission error code |
1403 | */ | 1430 | */ |
@@ -1418,12 +1445,6 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1418 | req, ucs->pending); | 1445 | req, ucs->pending); |
1419 | return -EBUSY; | 1446 | return -EBUSY; |
1420 | } | 1447 | } |
1421 | if (ucs->urb_ctrl->status == -EINPROGRESS) { | ||
1422 | spin_unlock_irqrestore(&ucs->lock, flags); | ||
1423 | dev_err(bcs->cs->dev, | ||
1424 | "could not submit request 0x%02x: URB busy\n", req); | ||
1425 | return -EBUSY; | ||
1426 | } | ||
1427 | 1448 | ||
1428 | ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ; | 1449 | ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ; |
1429 | ucs->dr_ctrl.bRequest = req; | 1450 | ucs->dr_ctrl.bRequest = req; |
@@ -1465,22 +1486,36 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1465 | static int gigaset_init_bchannel(struct bc_state *bcs) | 1486 | static int gigaset_init_bchannel(struct bc_state *bcs) |
1466 | { | 1487 | { |
1467 | int req, ret; | 1488 | int req, ret; |
1489 | unsigned long flags; | ||
1490 | |||
1491 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
1492 | if (unlikely(!bcs->cs->connected)) { | ||
1493 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | ||
1494 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1495 | return -ENODEV; | ||
1496 | } | ||
1468 | 1497 | ||
1469 | if ((ret = starturbs(bcs)) < 0) { | 1498 | if ((ret = starturbs(bcs)) < 0) { |
1470 | dev_err(bcs->cs->dev, | 1499 | dev_err(bcs->cs->dev, |
1471 | "could not start isochronous I/O for channel %d\n", | 1500 | "could not start isochronous I/O for channel B%d: %s\n", |
1472 | bcs->channel + 1); | 1501 | bcs->channel + 1, |
1473 | error_hangup(bcs); | 1502 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); |
1503 | if (ret != -ENODEV) | ||
1504 | error_hangup(bcs); | ||
1505 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1474 | return ret; | 1506 | return ret; |
1475 | } | 1507 | } |
1476 | 1508 | ||
1477 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; | 1509 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; |
1478 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { | 1510 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { |
1479 | dev_err(bcs->cs->dev, "could not open channel %d: %s\n", | 1511 | dev_err(bcs->cs->dev, "could not open channel B%d\n", |
1480 | bcs->channel + 1, get_usb_statmsg(ret)); | 1512 | bcs->channel + 1); |
1481 | stopurbs(bcs->hw.bas); | 1513 | stopurbs(bcs->hw.bas); |
1482 | error_hangup(bcs); | 1514 | if (ret != -ENODEV) |
1515 | error_hangup(bcs); | ||
1483 | } | 1516 | } |
1517 | |||
1518 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1484 | return ret; | 1519 | return ret; |
1485 | } | 1520 | } |
1486 | 1521 | ||
@@ -1497,19 +1532,30 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1497 | static int gigaset_close_bchannel(struct bc_state *bcs) | 1532 | static int gigaset_close_bchannel(struct bc_state *bcs) |
1498 | { | 1533 | { |
1499 | int req, ret; | 1534 | int req, ret; |
1535 | unsigned long flags; | ||
1536 | |||
1537 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
1538 | if (unlikely(!bcs->cs->connected)) { | ||
1539 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1540 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | ||
1541 | return -ENODEV; | ||
1542 | } | ||
1500 | 1543 | ||
1501 | if (!(atomic_read(&bcs->cs->hw.bas->basstate) & | 1544 | if (!(atomic_read(&bcs->cs->hw.bas->basstate) & |
1502 | (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { | 1545 | (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { |
1503 | /* channel not running: just signal common.c */ | 1546 | /* channel not running: just signal common.c */ |
1547 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1504 | gigaset_bchannel_down(bcs); | 1548 | gigaset_bchannel_down(bcs); |
1505 | return 0; | 1549 | return 0; |
1506 | } | 1550 | } |
1507 | 1551 | ||
1552 | /* channel running: tell device to close it */ | ||
1508 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; | 1553 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; |
1509 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) | 1554 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) |
1510 | dev_err(bcs->cs->dev, | 1555 | dev_err(bcs->cs->dev, "closing channel B%d failed\n", |
1511 | "could not submit HD_CLOSE_BxCHANNEL request: %s\n", | 1556 | bcs->channel + 1); |
1512 | get_usb_statmsg(ret)); | 1557 | |
1558 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
1513 | return ret; | 1559 | return ret; |
1514 | } | 1560 | } |
1515 | 1561 | ||
@@ -1545,8 +1591,6 @@ static void complete_cb(struct cardstate *cs) | |||
1545 | kfree(cb); | 1591 | kfree(cb); |
1546 | } | 1592 | } |
1547 | 1593 | ||
1548 | static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len); | ||
1549 | |||
1550 | /* write_command_callback | 1594 | /* write_command_callback |
1551 | * USB completion handler for AT command transmission | 1595 | * USB completion handler for AT command transmission |
1552 | * called by the USB subsystem in interrupt context | 1596 | * called by the USB subsystem in interrupt context |
@@ -1560,13 +1604,17 @@ static void write_command_callback(struct urb *urb, struct pt_regs *regs) | |||
1560 | struct bas_cardstate *ucs = cs->hw.bas; | 1604 | struct bas_cardstate *ucs = cs->hw.bas; |
1561 | unsigned long flags; | 1605 | unsigned long flags; |
1562 | 1606 | ||
1607 | update_basstate(ucs, 0, BS_ATWRPEND); | ||
1608 | |||
1563 | /* check status */ | 1609 | /* check status */ |
1564 | switch (urb->status) { | 1610 | switch (urb->status) { |
1565 | case 0: /* normal completion */ | 1611 | case 0: /* normal completion */ |
1566 | break; | 1612 | break; |
1567 | case -ENOENT: /* canceled */ | 1613 | case -ENOENT: /* cancelled */ |
1568 | case -ECONNRESET: /* canceled (async) */ | 1614 | case -ECONNRESET: /* cancelled (async) */ |
1569 | case -EINPROGRESS: /* pending */ | 1615 | case -EINPROGRESS: /* pending */ |
1616 | case -ENODEV: /* device removed */ | ||
1617 | case -ESHUTDOWN: /* device shut down */ | ||
1570 | /* ignore silently */ | 1618 | /* ignore silently */ |
1571 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 1619 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
1572 | __func__, get_usb_statmsg(urb->status)); | 1620 | __func__, get_usb_statmsg(urb->status)); |
@@ -1627,19 +1675,17 @@ static void atrdy_timeout(unsigned long data) | |||
1627 | * len length of command to send | 1675 | * len length of command to send |
1628 | * return value: | 1676 | * return value: |
1629 | * 0 on success | 1677 | * 0 on success |
1630 | * -EFAULT if a NULL pointer is encountered somewhere | ||
1631 | * -EBUSY if another request is pending | 1678 | * -EBUSY if another request is pending |
1632 | * any URB submission error code | 1679 | * any URB submission error code |
1633 | */ | 1680 | */ |
1634 | static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) | 1681 | static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) |
1635 | { | 1682 | { |
1636 | struct bas_cardstate *ucs = cs->hw.bas; | 1683 | struct bas_cardstate *ucs = cs->hw.bas; |
1637 | unsigned long flags; | 1684 | int rc; |
1638 | int ret; | ||
1639 | 1685 | ||
1640 | gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); | 1686 | gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); |
1641 | 1687 | ||
1642 | if (ucs->urb_cmd_out->status == -EINPROGRESS) { | 1688 | if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) { |
1643 | dev_err(cs->dev, | 1689 | dev_err(cs->dev, |
1644 | "could not submit HD_WRITE_ATMESSAGE: URB busy\n"); | 1690 | "could not submit HD_WRITE_ATMESSAGE: URB busy\n"); |
1645 | return -EBUSY; | 1691 | return -EBUSY; |
@@ -1654,29 +1700,22 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) | |||
1654 | usb_sndctrlpipe(ucs->udev, 0), | 1700 | usb_sndctrlpipe(ucs->udev, 0), |
1655 | (unsigned char*) &ucs->dr_cmd_out, buf, len, | 1701 | (unsigned char*) &ucs->dr_cmd_out, buf, len, |
1656 | write_command_callback, cs); | 1702 | write_command_callback, cs); |
1657 | 1703 | rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC); | |
1658 | spin_lock_irqsave(&cs->lock, flags); | 1704 | if (unlikely(rc)) { |
1659 | ret = cs->connected ? usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC) : -ENODEV; | 1705 | update_basstate(ucs, 0, BS_ATWRPEND); |
1660 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1661 | |||
1662 | if (ret) { | ||
1663 | dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", | 1706 | dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", |
1664 | get_usb_statmsg(ret)); | 1707 | get_usb_rcmsg(rc)); |
1665 | return ret; | 1708 | return rc; |
1666 | } | 1709 | } |
1667 | 1710 | ||
1668 | /* submitted successfully */ | 1711 | /* submitted successfully, start timeout if necessary */ |
1669 | update_basstate(ucs, 0, BS_ATREADY); | 1712 | if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) { |
1670 | |||
1671 | /* start timeout if necessary */ | ||
1672 | if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) { | ||
1673 | gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", | 1713 | gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", |
1674 | ATRDY_TIMEOUT); | 1714 | ATRDY_TIMEOUT); |
1675 | ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10; | 1715 | ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10; |
1676 | ucs->timer_atrdy.data = (unsigned long) cs; | 1716 | ucs->timer_atrdy.data = (unsigned long) cs; |
1677 | ucs->timer_atrdy.function = atrdy_timeout; | 1717 | ucs->timer_atrdy.function = atrdy_timeout; |
1678 | add_timer(&ucs->timer_atrdy); | 1718 | add_timer(&ucs->timer_atrdy); |
1679 | update_basstate(ucs, BS_ATTIMER, 0); | ||
1680 | } | 1719 | } |
1681 | return 0; | 1720 | return 0; |
1682 | } | 1721 | } |
@@ -1702,7 +1741,6 @@ static int start_cbsend(struct cardstate *cs) | |||
1702 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); | 1741 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); |
1703 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); | 1742 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); |
1704 | if (rc < 0) { | 1743 | if (rc < 0) { |
1705 | dev_err(cs->dev, "could not open AT channel\n"); | ||
1706 | /* flush command queue */ | 1744 | /* flush command queue */ |
1707 | spin_lock_irqsave(&cs->cmdlock, flags); | 1745 | spin_lock_irqsave(&cs->cmdlock, flags); |
1708 | while (cs->cmdbuf != NULL) | 1746 | while (cs->cmdbuf != NULL) |
@@ -1786,8 +1824,14 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1786 | cs->lastcmdbuf = cb; | 1824 | cs->lastcmdbuf = cb; |
1787 | spin_unlock_irqrestore(&cs->cmdlock, flags); | 1825 | spin_unlock_irqrestore(&cs->cmdlock, flags); |
1788 | 1826 | ||
1827 | spin_lock_irqsave(&cs->lock, flags); | ||
1828 | if (unlikely(!cs->connected)) { | ||
1829 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1830 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | ||
1831 | return -ENODEV; | ||
1832 | } | ||
1789 | status = start_cbsend(cs); | 1833 | status = start_cbsend(cs); |
1790 | 1834 | spin_unlock_irqrestore(&cs->lock, flags); | |
1791 | return status < 0 ? status : len; | 1835 | return status < 0 ? status : len; |
1792 | } | 1836 | } |
1793 | 1837 | ||
@@ -1849,12 +1893,32 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) | |||
1849 | */ | 1893 | */ |
1850 | static int gigaset_freebcshw(struct bc_state *bcs) | 1894 | static int gigaset_freebcshw(struct bc_state *bcs) |
1851 | { | 1895 | { |
1852 | if (!bcs->hw.bas) | 1896 | struct bas_bc_state *ubc = bcs->hw.bas; |
1897 | int i; | ||
1898 | |||
1899 | if (!ubc) | ||
1853 | return 0; | 1900 | return 0; |
1854 | 1901 | ||
1855 | if (bcs->hw.bas->isooutbuf) | 1902 | /* kill URBs and tasklets before freeing - better safe than sorry */ |
1856 | kfree(bcs->hw.bas->isooutbuf); | 1903 | atomic_set(&ubc->running, 0); |
1857 | kfree(bcs->hw.bas); | 1904 | for (i = 0; i < BAS_OUTURBS; ++i) |
1905 | if (ubc->isoouturbs[i].urb) { | ||
1906 | gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d", | ||
1907 | __func__, i); | ||
1908 | usb_kill_urb(ubc->isoouturbs[i].urb); | ||
1909 | usb_free_urb(ubc->isoouturbs[i].urb); | ||
1910 | } | ||
1911 | for (i = 0; i < BAS_INURBS; ++i) | ||
1912 | if (ubc->isoinurbs[i]) { | ||
1913 | gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d", | ||
1914 | __func__, i); | ||
1915 | usb_kill_urb(ubc->isoinurbs[i]); | ||
1916 | usb_free_urb(ubc->isoinurbs[i]); | ||
1917 | } | ||
1918 | tasklet_kill(&ubc->sent_tasklet); | ||
1919 | tasklet_kill(&ubc->rcvd_tasklet); | ||
1920 | kfree(ubc->isooutbuf); | ||
1921 | kfree(ubc); | ||
1858 | bcs->hw.bas = NULL; | 1922 | bcs->hw.bas = NULL; |
1859 | return 1; | 1923 | return 1; |
1860 | } | 1924 | } |
@@ -1931,13 +1995,9 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) | |||
1931 | 1995 | ||
1932 | static void gigaset_freecshw(struct cardstate *cs) | 1996 | static void gigaset_freecshw(struct cardstate *cs) |
1933 | { | 1997 | { |
1934 | struct bas_cardstate *ucs = cs->hw.bas; | 1998 | /* timers, URBs and rcvbuf are disposed of in disconnect */ |
1935 | |||
1936 | del_timer(&ucs->timer_ctrl); | ||
1937 | del_timer(&ucs->timer_atrdy); | ||
1938 | del_timer(&ucs->timer_cmd_in); | ||
1939 | |||
1940 | kfree(cs->hw.bas); | 1999 | kfree(cs->hw.bas); |
2000 | cs->hw.bas = NULL; | ||
1941 | } | 2001 | } |
1942 | 2002 | ||
1943 | static int gigaset_initcshw(struct cardstate *cs) | 2003 | static int gigaset_initcshw(struct cardstate *cs) |
@@ -2041,23 +2101,13 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2041 | struct bas_bc_state *ubc; | 2101 | struct bas_bc_state *ubc; |
2042 | struct usb_endpoint_descriptor *endpoint; | 2102 | struct usb_endpoint_descriptor *endpoint; |
2043 | int i, j; | 2103 | int i, j; |
2044 | int ret; | 2104 | int rc; |
2045 | 2105 | ||
2046 | gig_dbg(DEBUG_ANY, | 2106 | gig_dbg(DEBUG_ANY, |
2047 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", | 2107 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", |
2048 | __func__, le16_to_cpu(udev->descriptor.idVendor), | 2108 | __func__, le16_to_cpu(udev->descriptor.idVendor), |
2049 | le16_to_cpu(udev->descriptor.idProduct)); | 2109 | le16_to_cpu(udev->descriptor.idProduct)); |
2050 | 2110 | ||
2051 | /* See if the device offered us matches what we can accept */ | ||
2052 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_GIGA_VENDOR_ID) || | ||
2053 | (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID && | ||
2054 | le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID && | ||
2055 | le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID && | ||
2056 | le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) { | ||
2057 | gig_dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__); | ||
2058 | return -ENODEV; | ||
2059 | } | ||
2060 | |||
2061 | /* set required alternate setting */ | 2111 | /* set required alternate setting */ |
2062 | hostif = interface->cur_altsetting; | 2112 | hostif = interface->cur_altsetting; |
2063 | if (hostif->desc.bAlternateSetting != 3) { | 2113 | if (hostif->desc.bAlternateSetting != 3) { |
@@ -2105,45 +2155,22 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2105 | * - three for the different uses of the default control pipe | 2155 | * - three for the different uses of the default control pipe |
2106 | * - three for each isochronous pipe | 2156 | * - three for each isochronous pipe |
2107 | */ | 2157 | */ |
2108 | ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL); | 2158 | if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) || |
2109 | if (!ucs->urb_int_in) { | 2159 | !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) || |
2110 | dev_err(cs->dev, "no free urbs available\n"); | 2160 | !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) || |
2111 | goto error; | 2161 | !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL))) |
2112 | } | 2162 | goto allocerr; |
2113 | ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL); | ||
2114 | if (!ucs->urb_cmd_in) { | ||
2115 | dev_err(cs->dev, "no free urbs available\n"); | ||
2116 | goto error; | ||
2117 | } | ||
2118 | ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL); | ||
2119 | if (!ucs->urb_cmd_out) { | ||
2120 | dev_err(cs->dev, "no free urbs available\n"); | ||
2121 | goto error; | ||
2122 | } | ||
2123 | ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL); | ||
2124 | if (!ucs->urb_ctrl) { | ||
2125 | dev_err(cs->dev, "no free urbs available\n"); | ||
2126 | goto error; | ||
2127 | } | ||
2128 | 2163 | ||
2129 | for (j = 0; j < 2; ++j) { | 2164 | for (j = 0; j < 2; ++j) { |
2130 | ubc = cs->bcs[j].hw.bas; | 2165 | ubc = cs->bcs[j].hw.bas; |
2131 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2166 | for (i = 0; i < BAS_OUTURBS; ++i) |
2132 | ubc->isoouturbs[i].urb = | 2167 | if (!(ubc->isoouturbs[i].urb = |
2133 | usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); | 2168 | usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL))) |
2134 | if (!ubc->isoouturbs[i].urb) { | 2169 | goto allocerr; |
2135 | dev_err(cs->dev, "no free urbs available\n"); | 2170 | for (i = 0; i < BAS_INURBS; ++i) |
2136 | goto error; | 2171 | if (!(ubc->isoinurbs[i] = |
2137 | } | 2172 | usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL))) |
2138 | } | 2173 | goto allocerr; |
2139 | for (i = 0; i < BAS_INURBS; ++i) { | ||
2140 | ubc->isoinurbs[i] = | ||
2141 | usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); | ||
2142 | if (!ubc->isoinurbs[i]) { | ||
2143 | dev_err(cs->dev, "no free urbs available\n"); | ||
2144 | goto error; | ||
2145 | } | ||
2146 | } | ||
2147 | } | 2174 | } |
2148 | 2175 | ||
2149 | ucs->rcvbuf = NULL; | 2176 | ucs->rcvbuf = NULL; |
@@ -2156,15 +2183,14 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2156 | (endpoint->bEndpointAddress) & 0x0f), | 2183 | (endpoint->bEndpointAddress) & 0x0f), |
2157 | ucs->int_in_buf, 3, read_int_callback, cs, | 2184 | ucs->int_in_buf, 3, read_int_callback, cs, |
2158 | endpoint->bInterval); | 2185 | endpoint->bInterval); |
2159 | ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL); | 2186 | if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) { |
2160 | if (ret) { | ||
2161 | dev_err(cs->dev, "could not submit interrupt URB: %s\n", | 2187 | dev_err(cs->dev, "could not submit interrupt URB: %s\n", |
2162 | get_usb_statmsg(ret)); | 2188 | get_usb_rcmsg(rc)); |
2163 | goto error; | 2189 | goto error; |
2164 | } | 2190 | } |
2165 | 2191 | ||
2166 | /* tell the device that the driver is ready */ | 2192 | /* tell the device that the driver is ready */ |
2167 | if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) | 2193 | if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) |
2168 | goto error; | 2194 | goto error; |
2169 | 2195 | ||
2170 | /* tell common part that the device is ready */ | 2196 | /* tell common part that the device is ready */ |
@@ -2179,6 +2205,8 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2179 | 2205 | ||
2180 | return 0; | 2206 | return 0; |
2181 | 2207 | ||
2208 | allocerr: | ||
2209 | dev_err(cs->dev, "could not allocate URBs\n"); | ||
2182 | error: | 2210 | error: |
2183 | freeurbs(cs); | 2211 | freeurbs(cs); |
2184 | usb_set_intfdata(interface, NULL); | 2212 | usb_set_intfdata(interface, NULL); |
@@ -2193,19 +2221,34 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
2193 | { | 2221 | { |
2194 | struct cardstate *cs; | 2222 | struct cardstate *cs; |
2195 | struct bas_cardstate *ucs; | 2223 | struct bas_cardstate *ucs; |
2224 | int j; | ||
2196 | 2225 | ||
2197 | cs = usb_get_intfdata(interface); | 2226 | cs = usb_get_intfdata(interface); |
2198 | 2227 | ||
2199 | ucs = cs->hw.bas; | 2228 | ucs = cs->hw.bas; |
2200 | 2229 | ||
2201 | dev_info(cs->dev, "disconnecting Gigaset base\n"); | 2230 | dev_info(cs->dev, "disconnecting Gigaset base\n"); |
2231 | |||
2232 | /* mark base as not ready, all channels disconnected */ | ||
2233 | atomic_set(&ucs->basstate, 0); | ||
2234 | |||
2235 | /* tell LL all channels are down */ | ||
2236 | //FIXME shouldn't gigaset_stop() do this? | ||
2237 | for (j = 0; j < 2; ++j) | ||
2238 | gigaset_bchannel_down(cs->bcs + j); | ||
2239 | |||
2240 | /* stop driver (common part) */ | ||
2202 | gigaset_stop(cs); | 2241 | gigaset_stop(cs); |
2242 | |||
2243 | /* stop timers and URBs, free ressources */ | ||
2244 | del_timer_sync(&ucs->timer_ctrl); | ||
2245 | del_timer_sync(&ucs->timer_atrdy); | ||
2246 | del_timer_sync(&ucs->timer_cmd_in); | ||
2203 | freeurbs(cs); | 2247 | freeurbs(cs); |
2204 | usb_set_intfdata(interface, NULL); | 2248 | usb_set_intfdata(interface, NULL); |
2205 | kfree(ucs->rcvbuf); | 2249 | kfree(ucs->rcvbuf); |
2206 | ucs->rcvbuf = NULL; | 2250 | ucs->rcvbuf = NULL; |
2207 | ucs->rcvbuf_size = 0; | 2251 | ucs->rcvbuf_size = 0; |
2208 | atomic_set(&ucs->basstate, 0); | ||
2209 | usb_put_dev(ucs->udev); | 2252 | usb_put_dev(ucs->udev); |
2210 | ucs->interface = NULL; | 2253 | ucs->interface = NULL; |
2211 | ucs->udev = NULL; | 2254 | ucs->udev = NULL; |
@@ -2277,6 +2320,8 @@ error: if (cardstate) | |||
2277 | */ | 2320 | */ |
2278 | static void __exit bas_gigaset_exit(void) | 2321 | static void __exit bas_gigaset_exit(void) |
2279 | { | 2322 | { |
2323 | struct bas_cardstate *ucs = cardstate->hw.bas; | ||
2324 | |||
2280 | gigaset_blockdriver(driver); /* => probe will fail | 2325 | gigaset_blockdriver(driver); /* => probe will fail |
2281 | * => no gigaset_start any more | 2326 | * => no gigaset_start any more |
2282 | */ | 2327 | */ |
@@ -2284,14 +2329,26 @@ static void __exit bas_gigaset_exit(void) | |||
2284 | gigaset_shutdown(cardstate); | 2329 | gigaset_shutdown(cardstate); |
2285 | /* from now on, no isdn callback should be possible */ | 2330 | /* from now on, no isdn callback should be possible */ |
2286 | 2331 | ||
2287 | if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) { | 2332 | /* close all still open channels */ |
2288 | gig_dbg(DEBUG_ANY, "closing AT channel"); | 2333 | if (atomic_read(&ucs->basstate) & BS_B1OPEN) { |
2289 | if (req_submit(cardstate->bcs, | 2334 | gig_dbg(DEBUG_INIT, "closing B1 channel"); |
2290 | HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) { | 2335 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), |
2291 | /* successfully submitted */ | 2336 | HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0, |
2292 | //FIXME wait for completion? | 2337 | NULL, 0, BAS_TIMEOUT); |
2293 | } | 2338 | } |
2339 | if (atomic_read(&ucs->basstate) & BS_B2OPEN) { | ||
2340 | gig_dbg(DEBUG_INIT, "closing B2 channel"); | ||
2341 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | ||
2342 | HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0, | ||
2343 | NULL, 0, BAS_TIMEOUT); | ||
2344 | } | ||
2345 | if (atomic_read(&ucs->basstate) & BS_ATOPEN) { | ||
2346 | gig_dbg(DEBUG_INIT, "closing AT channel"); | ||
2347 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | ||
2348 | HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0, | ||
2349 | NULL, 0, BAS_TIMEOUT); | ||
2294 | } | 2350 | } |
2351 | atomic_set(&ucs->basstate, 0); | ||
2295 | 2352 | ||
2296 | /* deregister this driver with the USB subsystem */ | 2353 | /* deregister this driver with the USB subsystem */ |
2297 | usb_deregister(&gigaset_usb_driver); | 2354 | usb_deregister(&gigaset_usb_driver); |
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 749b3da1236e..e55767b2ccd3 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -781,8 +781,7 @@ error: if (cs) | |||
781 | } | 781 | } |
782 | EXPORT_SYMBOL_GPL(gigaset_initcs); | 782 | EXPORT_SYMBOL_GPL(gigaset_initcs); |
783 | 783 | ||
784 | /* ReInitialize the b-channel structure */ | 784 | /* ReInitialize the b-channel structure on hangup */ |
785 | /* e.g. called on hangup, disconnect */ | ||
786 | void gigaset_bcs_reinit(struct bc_state *bcs) | 785 | void gigaset_bcs_reinit(struct bc_state *bcs) |
787 | { | 786 | { |
788 | struct sk_buff *skb; | 787 | struct sk_buff *skb; |
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 1ba3424a286b..18e05c09b71c 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
@@ -373,6 +373,9 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */ | |||
373 | 373 | ||
374 | {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, | 374 | {EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, |
375 | 375 | ||
376 | /* B channel closed (general case) */ | ||
377 | {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME | ||
378 | |||
376 | /* misc. */ | 379 | /* misc. */ |
377 | {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME | 380 | {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME |
378 | 381 | ||
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 9d21ba8757b0..22b9693f7c0a 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -75,7 +75,7 @@ extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ | |||
75 | * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and | 75 | * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and |
76 | * DEBUG_INTR. | 76 | * DEBUG_INTR. |
77 | */ | 77 | */ |
78 | enum debuglevel { /* up to 24 bits (atomic_t) */ | 78 | enum debuglevel { |
79 | DEBUG_REG = 0x0002, /* serial port I/O register operations */ | 79 | DEBUG_REG = 0x0002, /* serial port I/O register operations */ |
80 | DEBUG_OPEN = 0x0004, /* open/close serial port */ | 80 | DEBUG_OPEN = 0x0004, /* open/close serial port */ |
81 | DEBUG_INTR = 0x0008, /* interrupt processing */ | 81 | DEBUG_INTR = 0x0008, /* interrupt processing */ |
@@ -141,7 +141,7 @@ enum debuglevel { /* up to 24 bits (atomic_t) */ | |||
141 | printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \ | 141 | printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \ |
142 | ## arg); \ | 142 | ## arg); \ |
143 | } while (0) | 143 | } while (0) |
144 | #define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) | 144 | #define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) |
145 | 145 | ||
146 | #else | 146 | #else |
147 | 147 | ||
@@ -627,8 +627,7 @@ struct gigaset_ops { | |||
627 | /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ | 627 | /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ |
628 | int (*freebcshw)(struct bc_state *bcs); | 628 | int (*freebcshw)(struct bc_state *bcs); |
629 | 629 | ||
630 | /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting | 630 | /* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */ |
631 | bcs->hw.xxx */ | ||
632 | void (*reinitbcshw)(struct bc_state *bcs); | 631 | void (*reinitbcshw)(struct bc_state *bcs); |
633 | 632 | ||
634 | /* Called by gigaset_initcs() for setting up cs->hw.xxx */ | 633 | /* Called by gigaset_initcs() for setting up cs->hw.xxx */ |
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 0815dbfb8291..1654fa413575 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c | |||
@@ -73,7 +73,7 @@ static int writebuf_from_LL(int driverID, int channel, int ack, | |||
73 | len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); | 73 | len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); |
74 | 74 | ||
75 | /* pass to device-specific module */ | 75 | /* pass to device-specific module */ |
76 | return cs->ops->send_skb(bcs, skb); //FIXME cs->ops->send_skb() must handle !cs->connected correctly | 76 | return cs->ops->send_skb(bcs, skb); |
77 | } | 77 | } |
78 | 78 | ||
79 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | 79 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) |
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 45f017ed6e8c..8667daaa1a82 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c | |||
@@ -992,14 +992,18 @@ int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb) | |||
992 | int len = skb->len; | 992 | int len = skb->len; |
993 | unsigned long flags; | 993 | unsigned long flags; |
994 | 994 | ||
995 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
996 | if (!bcs->cs->connected) { | ||
997 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
998 | return -ENODEV; | ||
999 | } | ||
1000 | |||
995 | skb_queue_tail(&bcs->squeue, skb); | 1001 | skb_queue_tail(&bcs->squeue, skb); |
996 | gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d", | 1002 | gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d", |
997 | __func__, skb_queue_len(&bcs->squeue)); | 1003 | __func__, skb_queue_len(&bcs->squeue)); |
998 | 1004 | ||
999 | /* tasklet submits URB if necessary */ | 1005 | /* tasklet submits URB if necessary */ |
1000 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1006 | tasklet_schedule(&bcs->hw.bas->sent_tasklet); |
1001 | if (bcs->cs->connected) | ||
1002 | tasklet_schedule(&bcs->hw.bas->sent_tasklet); | ||
1003 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1007 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
1004 | 1008 | ||
1005 | return len; /* ok so far */ | 1009 | return len; /* ok so far */ |
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 5ebfd1d138da..5282fec17075 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c | |||
@@ -627,8 +627,8 @@ thermostat_init(void) | |||
627 | if(therm_type == ADT7460) | 627 | if(therm_type == ADT7460) |
628 | device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed); | 628 | device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed); |
629 | 629 | ||
630 | #ifndef CONFIG_I2C_KEYWEST | 630 | #ifndef CONFIG_I2C_POWERMAC |
631 | request_module("i2c-keywest"); | 631 | request_module("i2c-powermac"); |
632 | #endif | 632 | #endif |
633 | 633 | ||
634 | return i2c_add_driver(&thermostat_driver); | 634 | return i2c_add_driver(&thermostat_driver); |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 506e777c5f06..d090df413049 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -1639,6 +1639,7 @@ static struct pcmcia_device_id pcnet_ids[] = { | |||
1639 | PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), | 1639 | PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), |
1640 | PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), | 1640 | PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), |
1641 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), | 1641 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), |
1642 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d), | ||
1642 | PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), | 1643 | PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), |
1643 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), | 1644 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), |
1644 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), | 1645 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 2d520e4b0276..b7d77638ba8c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h | |||
@@ -213,6 +213,14 @@ static inline | |||
213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) | 213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) |
214 | { | 214 | { |
215 | } | 215 | } |
216 | static inline | ||
217 | void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) | ||
218 | { | ||
219 | } | ||
220 | static inline | ||
221 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) | ||
222 | { | ||
223 | } | ||
216 | 224 | ||
217 | #endif /* CONFIG_BCM43XX_DMA */ | 225 | #endif /* CONFIG_BCM43XX_DMA */ |
218 | #endif /* BCM43xx_DMA_H_ */ | 226 | #endif /* BCM43xx_DMA_H_ */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index c59ddd40680d..0aa1bd269a25 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "bcm43xx_pio.h" | 27 | #include "bcm43xx_pio.h" |
28 | #include "bcm43xx_main.h" | 28 | #include "bcm43xx_main.h" |
29 | #include "bcm43xx_xmit.h" | 29 | #include "bcm43xx_xmit.h" |
30 | #include "bcm43xx_power.h" | ||
30 | 31 | ||
31 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
32 | 33 | ||
@@ -44,10 +45,10 @@ static void tx_octet(struct bcm43xx_pioqueue *queue, | |||
44 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 45 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
45 | octet); | 46 | octet); |
46 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 47 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
47 | BCM43xx_PIO_TXCTL_WRITEHI); | 48 | BCM43xx_PIO_TXCTL_WRITELO); |
48 | } else { | 49 | } else { |
49 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 50 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
50 | BCM43xx_PIO_TXCTL_WRITEHI); | 51 | BCM43xx_PIO_TXCTL_WRITELO); |
51 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 52 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
52 | octet); | 53 | octet); |
53 | } | 54 | } |
@@ -103,7 +104,7 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
103 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 104 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
104 | skb->data[skb->len - 1]); | 105 | skb->data[skb->len - 1]); |
105 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 106 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
106 | BCM43xx_PIO_TXCTL_WRITEHI | | 107 | BCM43xx_PIO_TXCTL_WRITELO | |
107 | BCM43xx_PIO_TXCTL_COMPLETE); | 108 | BCM43xx_PIO_TXCTL_COMPLETE); |
108 | } else { | 109 | } else { |
109 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 110 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
@@ -112,9 +113,10 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
112 | } | 113 | } |
113 | 114 | ||
114 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | 115 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, |
115 | int packetindex) | 116 | struct bcm43xx_pio_txpacket *packet) |
116 | { | 117 | { |
117 | u16 cookie = 0x0000; | 118 | u16 cookie = 0x0000; |
119 | int packetindex; | ||
118 | 120 | ||
119 | /* We use the upper 4 bits for the PIO | 121 | /* We use the upper 4 bits for the PIO |
120 | * controller ID and the lower 12 bits | 122 | * controller ID and the lower 12 bits |
@@ -135,6 +137,7 @@ static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | |||
135 | default: | 137 | default: |
136 | assert(0); | 138 | assert(0); |
137 | } | 139 | } |
140 | packetindex = pio_txpacket_getindex(packet); | ||
138 | assert(((u16)packetindex & 0xF000) == 0x0000); | 141 | assert(((u16)packetindex & 0xF000) == 0x0000); |
139 | cookie |= (u16)packetindex; | 142 | cookie |= (u16)packetindex; |
140 | 143 | ||
@@ -184,7 +187,7 @@ static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, | |||
184 | bcm43xx_generate_txhdr(queue->bcm, | 187 | bcm43xx_generate_txhdr(queue->bcm, |
185 | &txhdr, skb->data, skb->len, | 188 | &txhdr, skb->data, skb->len, |
186 | (packet->xmitted_frags == 0), | 189 | (packet->xmitted_frags == 0), |
187 | generate_cookie(queue, pio_txpacket_getindex(packet))); | 190 | generate_cookie(queue, packet)); |
188 | 191 | ||
189 | tx_start(queue); | 192 | tx_start(queue); |
190 | octets = skb->len + sizeof(txhdr); | 193 | octets = skb->len + sizeof(txhdr); |
@@ -241,7 +244,7 @@ static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) | |||
241 | queue->tx_devq_packets++; | 244 | queue->tx_devq_packets++; |
242 | queue->tx_devq_used += octets; | 245 | queue->tx_devq_used += octets; |
243 | 246 | ||
244 | assert(packet->xmitted_frags <= packet->txb->nr_frags); | 247 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
245 | packet->xmitted_frags++; | 248 | packet->xmitted_frags++; |
246 | packet->xmitted_octets += octets; | 249 | packet->xmitted_octets += octets; |
247 | } | 250 | } |
@@ -257,8 +260,14 @@ static void tx_tasklet(unsigned long d) | |||
257 | unsigned long flags; | 260 | unsigned long flags; |
258 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; | 261 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; |
259 | int err; | 262 | int err; |
263 | u16 txctl; | ||
260 | 264 | ||
261 | bcm43xx_lock_mmio(bcm, flags); | 265 | bcm43xx_lock_mmio(bcm, flags); |
266 | |||
267 | txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
268 | if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) | ||
269 | goto out_unlock; | ||
270 | |||
262 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { | 271 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { |
263 | assert(packet->xmitted_frags < packet->txb->nr_frags); | 272 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
264 | if (packet->xmitted_frags == 0) { | 273 | if (packet->xmitted_frags == 0) { |
@@ -288,6 +297,7 @@ static void tx_tasklet(unsigned long d) | |||
288 | next_packet: | 297 | next_packet: |
289 | continue; | 298 | continue; |
290 | } | 299 | } |
300 | out_unlock: | ||
291 | bcm43xx_unlock_mmio(bcm, flags); | 301 | bcm43xx_unlock_mmio(bcm, flags); |
292 | } | 302 | } |
293 | 303 | ||
@@ -330,12 +340,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, | |||
330 | (unsigned long)queue); | 340 | (unsigned long)queue); |
331 | 341 | ||
332 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); | 342 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); |
333 | value |= BCM43xx_SBF_XFER_REG_BYTESWAP; | 343 | value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP; |
334 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); | 344 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); |
335 | 345 | ||
336 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); | 346 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); |
347 | if (qsize == 0) { | ||
348 | printk(KERN_ERR PFX "ERROR: This card does not support PIO " | ||
349 | "operation mode. Please use DMA mode " | ||
350 | "(module parameter pio=0).\n"); | ||
351 | goto err_freequeue; | ||
352 | } | ||
337 | if (qsize <= BCM43xx_PIO_TXQADJUST) { | 353 | if (qsize <= BCM43xx_PIO_TXQADJUST) { |
338 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize); | 354 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", |
355 | qsize); | ||
339 | goto err_freequeue; | 356 | goto err_freequeue; |
340 | } | 357 | } |
341 | qsize -= BCM43xx_PIO_TXQADJUST; | 358 | qsize -= BCM43xx_PIO_TXQADJUST; |
@@ -444,15 +461,10 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
444 | { | 461 | { |
445 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; | 462 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; |
446 | struct bcm43xx_pio_txpacket *packet; | 463 | struct bcm43xx_pio_txpacket *packet; |
447 | u16 tmp; | ||
448 | 464 | ||
449 | assert(!queue->tx_suspended); | 465 | assert(!queue->tx_suspended); |
450 | assert(!list_empty(&queue->txfree)); | 466 | assert(!list_empty(&queue->txfree)); |
451 | 467 | ||
452 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
453 | if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) | ||
454 | return -EBUSY; | ||
455 | |||
456 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); | 468 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); |
457 | packet->txb = txb; | 469 | packet->txb = txb; |
458 | packet->xmitted_frags = 0; | 470 | packet->xmitted_frags = 0; |
@@ -462,7 +474,7 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
462 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); | 474 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); |
463 | 475 | ||
464 | /* Suspend TX, if we are out of packets in the "free" queue. */ | 476 | /* Suspend TX, if we are out of packets in the "free" queue. */ |
465 | if (unlikely(list_empty(&queue->txfree))) { | 477 | if (list_empty(&queue->txfree)) { |
466 | netif_stop_queue(queue->bcm->net_dev); | 478 | netif_stop_queue(queue->bcm->net_dev); |
467 | queue->tx_suspended = 1; | 479 | queue->tx_suspended = 1; |
468 | } | 480 | } |
@@ -480,15 +492,15 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
480 | 492 | ||
481 | queue = parse_cookie(bcm, status->cookie, &packet); | 493 | queue = parse_cookie(bcm, status->cookie, &packet); |
482 | assert(queue); | 494 | assert(queue); |
483 | //TODO | 495 | |
484 | if (!queue) | ||
485 | return; | ||
486 | free_txpacket(packet, 1); | 496 | free_txpacket(packet, 1); |
487 | if (unlikely(queue->tx_suspended)) { | 497 | if (queue->tx_suspended) { |
488 | queue->tx_suspended = 0; | 498 | queue->tx_suspended = 0; |
489 | netif_wake_queue(queue->bcm->net_dev); | 499 | netif_wake_queue(queue->bcm->net_dev); |
490 | } | 500 | } |
491 | /* If there are packets on the txqueue, poke the tasklet. */ | 501 | /* If there are packets on the txqueue, poke the tasklet |
502 | * to transmit them. | ||
503 | */ | ||
492 | if (!list_empty(&queue->txqueue)) | 504 | if (!list_empty(&queue->txqueue)) |
493 | tasklet_schedule(&queue->txtask); | 505 | tasklet_schedule(&queue->txtask); |
494 | } | 506 | } |
@@ -519,12 +531,9 @@ void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | |||
519 | int i, preamble_readwords; | 531 | int i, preamble_readwords; |
520 | struct sk_buff *skb; | 532 | struct sk_buff *skb; |
521 | 533 | ||
522 | return; | ||
523 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); | 534 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); |
524 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { | 535 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) |
525 | dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk. | ||
526 | return; | 536 | return; |
527 | } | ||
528 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, | 537 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, |
529 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); | 538 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); |
530 | 539 | ||
@@ -538,8 +547,7 @@ return; | |||
538 | return; | 547 | return; |
539 | data_ready: | 548 | data_ready: |
540 | 549 | ||
541 | //FIXME: endianess in this function. | 550 | len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
542 | len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | ||
543 | if (unlikely(len > 0x700)) { | 551 | if (unlikely(len > 0x700)) { |
544 | pio_rx_error(queue, 0, "len > 0x700"); | 552 | pio_rx_error(queue, 0, "len > 0x700"); |
545 | return; | 553 | return; |
@@ -555,7 +563,7 @@ data_ready: | |||
555 | preamble_readwords = 18 / sizeof(u16); | 563 | preamble_readwords = 18 / sizeof(u16); |
556 | for (i = 0; i < preamble_readwords; i++) { | 564 | for (i = 0; i < preamble_readwords; i++) { |
557 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 565 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
558 | preamble[i + 1] = cpu_to_be16(tmp);//FIXME? | 566 | preamble[i + 1] = cpu_to_le16(tmp); |
559 | } | 567 | } |
560 | rxhdr = (struct bcm43xx_rxhdr *)preamble; | 568 | rxhdr = (struct bcm43xx_rxhdr *)preamble; |
561 | rxflags2 = le16_to_cpu(rxhdr->flags2); | 569 | rxflags2 = le16_to_cpu(rxhdr->flags2); |
@@ -591,16 +599,40 @@ data_ready: | |||
591 | } | 599 | } |
592 | skb_put(skb, len); | 600 | skb_put(skb, len); |
593 | for (i = 0; i < len - 1; i += 2) { | 601 | for (i = 0; i < len - 1; i += 2) { |
594 | tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | 602 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
595 | *((u16 *)(skb->data + i)) = tmp; | 603 | *((u16 *)(skb->data + i)) = cpu_to_le16(tmp); |
596 | } | 604 | } |
597 | if (len % 2) { | 605 | if (len % 2) { |
598 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 606 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
599 | skb->data[len - 1] = (tmp & 0x00FF); | 607 | skb->data[len - 1] = (tmp & 0x00FF); |
608 | /* The specs say the following is required, but | ||
609 | * it is wrong and corrupts the PLCP. If we don't do | ||
610 | * this, the PLCP seems to be correct. So ifdef it out for now. | ||
611 | */ | ||
612 | #if 0 | ||
600 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) | 613 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) |
601 | skb->data[0x20] = (tmp & 0xFF00) >> 8; | 614 | skb->data[2] = (tmp & 0xFF00) >> 8; |
602 | else | 615 | else |
603 | skb->data[0x1E] = (tmp & 0xFF00) >> 8; | 616 | skb->data[0] = (tmp & 0xFF00) >> 8; |
617 | #endif | ||
604 | } | 618 | } |
619 | skb_trim(skb, len - IEEE80211_FCS_LEN); | ||
605 | bcm43xx_rx(queue->bcm, skb, rxhdr); | 620 | bcm43xx_rx(queue->bcm, skb, rxhdr); |
606 | } | 621 | } |
622 | |||
623 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
624 | { | ||
625 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1); | ||
626 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
627 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
628 | | BCM43xx_PIO_TXCTL_SUSPEND); | ||
629 | } | ||
630 | |||
631 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
632 | { | ||
633 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
634 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
635 | & ~BCM43xx_PIO_TXCTL_SUSPEND); | ||
636 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); | ||
637 | tasklet_schedule(&queue->txtask); | ||
638 | } | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index 970627bc1769..dfc78209e3a3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h | |||
@@ -14,8 +14,8 @@ | |||
14 | #define BCM43xx_PIO_RXCTL 0x08 | 14 | #define BCM43xx_PIO_RXCTL 0x08 |
15 | #define BCM43xx_PIO_RXDATA 0x0A | 15 | #define BCM43xx_PIO_RXDATA 0x0A |
16 | 16 | ||
17 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0) | 17 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 0) |
18 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 1) | 18 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1) |
19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) | 19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) |
20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) | 20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) |
21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) | 21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) |
@@ -95,6 +95,7 @@ void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, | |||
95 | u16 offset, u16 value) | 95 | u16 offset, u16 value) |
96 | { | 96 | { |
97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); | 97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); |
98 | mmiowb(); | ||
98 | } | 99 | } |
99 | 100 | ||
100 | 101 | ||
@@ -107,6 +108,9 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
107 | struct bcm43xx_xmitstatus *status); | 108 | struct bcm43xx_xmitstatus *status); |
108 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); | 109 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); |
109 | 110 | ||
111 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); | ||
112 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); | ||
113 | |||
110 | #else /* CONFIG_BCM43XX_PIO */ | 114 | #else /* CONFIG_BCM43XX_PIO */ |
111 | 115 | ||
112 | static inline | 116 | static inline |
@@ -133,6 +137,14 @@ static inline | |||
133 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | 137 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) |
134 | { | 138 | { |
135 | } | 139 | } |
140 | static inline | ||
141 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
142 | { | ||
143 | } | ||
144 | static inline | ||
145 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
146 | { | ||
147 | } | ||
136 | 148 | ||
137 | #endif /* CONFIG_BCM43XX_PIO */ | 149 | #endif /* CONFIG_BCM43XX_PIO */ |
138 | #endif /* BCM43xx_PIO_H_ */ | 150 | #endif /* BCM43xx_PIO_H_ */ |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 8b37e824dfcb..8399de581893 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -1860,7 +1860,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1860 | memset(&iwe, 0, sizeof(iwe)); | 1860 | memset(&iwe, 0, sizeof(iwe)); |
1861 | iwe.cmd = SIOCGIWFREQ; | 1861 | iwe.cmd = SIOCGIWFREQ; |
1862 | if (scan) { | 1862 | if (scan) { |
1863 | chan = scan->chid; | 1863 | chan = le16_to_cpu(scan->chid); |
1864 | } else if (bss) { | 1864 | } else if (bss) { |
1865 | chan = bss->chan; | 1865 | chan = bss->chan; |
1866 | } else { | 1866 | } else { |
@@ -1868,7 +1868,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1868 | } | 1868 | } |
1869 | 1869 | ||
1870 | if (chan > 0) { | 1870 | if (chan > 0) { |
1871 | iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000; | 1871 | iwe.u.freq.m = freq_list[chan - 1] * 100000; |
1872 | iwe.u.freq.e = 1; | 1872 | iwe.u.freq.e = 1; |
1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, |
1874 | IW_EV_FREQ_LEN); | 1874 | IW_EV_FREQ_LEN); |
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 4e53be9c03ab..bbeabe3fc4c6 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c | |||
@@ -535,7 +535,7 @@ pdcs_auto_read(struct subsystem *entry, char *buf, int knob) | |||
535 | { | 535 | { |
536 | char *out = buf; | 536 | char *out = buf; |
537 | struct pdcspath_entry *pathentry; | 537 | struct pdcspath_entry *pathentry; |
538 | 538 | ||
539 | if (!entry || !buf) | 539 | if (!entry || !buf) |
540 | return -EINVAL; | 540 | return -EINVAL; |
541 | 541 | ||
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 42b32ff2fca6..278f325021ee 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c | |||
@@ -178,6 +178,11 @@ extern struct proc_dir_entry * proc_mckinley_root; | |||
178 | #define ROPE6_CTL 0x230 | 178 | #define ROPE6_CTL 0x230 |
179 | #define ROPE7_CTL 0x238 | 179 | #define ROPE7_CTL 0x238 |
180 | 180 | ||
181 | #define IOC_ROPE0_CFG 0x500 /* pluto only */ | ||
182 | #define IOC_ROPE_AO 0x10 /* Allow "Relaxed Ordering" */ | ||
183 | |||
184 | |||
185 | |||
181 | #define HF_ENABLE 0x40 | 186 | #define HF_ENABLE 0x40 |
182 | 187 | ||
183 | 188 | ||
@@ -1759,19 +1764,33 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, | |||
1759 | 1764 | ||
1760 | sba_dev->num_ioc = num_ioc; | 1765 | sba_dev->num_ioc = num_ioc; |
1761 | for (i = 0; i < num_ioc; i++) { | 1766 | for (i = 0; i < num_ioc; i++) { |
1762 | /* | 1767 | unsigned long ioc_hpa = sba_dev->ioc[i].ioc_hpa; |
1763 | ** Make sure the box crashes if we get any errors on a rope. | 1768 | unsigned int j; |
1764 | */ | 1769 | |
1765 | WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL); | 1770 | for (j=0; j < sizeof(u64) * ROPES_PER_IOC; j+=sizeof(u64)) { |
1766 | WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL); | 1771 | |
1767 | WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL); | 1772 | /* |
1768 | WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL); | 1773 | * Clear ROPE(N)_CONFIG AO bit. |
1769 | WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL); | 1774 | * Disables "NT Ordering" (~= !"Relaxed Ordering") |
1770 | WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL); | 1775 | * Overrides bit 1 in DMA Hint Sets. |
1771 | WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL); | 1776 | * Improves netperf UDP_STREAM by ~10% for bcm5701. |
1772 | WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); | 1777 | */ |
1773 | 1778 | if (IS_PLUTO(sba_dev->iodc)) { | |
1774 | /* flush out the writes */ | 1779 | unsigned long rope_cfg, cfg_val; |
1780 | |||
1781 | rope_cfg = ioc_hpa + IOC_ROPE0_CFG + j; | ||
1782 | cfg_val = READ_REG(rope_cfg); | ||
1783 | cfg_val &= ~IOC_ROPE_AO; | ||
1784 | WRITE_REG(cfg_val, rope_cfg); | ||
1785 | } | ||
1786 | |||
1787 | /* | ||
1788 | ** Make sure the box crashes on rope errors. | ||
1789 | */ | ||
1790 | WRITE_REG(HF_ENABLE, ioc_hpa + ROPE0_CTL + j); | ||
1791 | } | ||
1792 | |||
1793 | /* flush out the last writes */ | ||
1775 | READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); | 1794 | READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); |
1776 | 1795 | ||
1777 | DBG_INIT(" ioc[%d] ROPE_CFG 0x%Lx ROPE_DBG 0x%Lx\n", | 1796 | DBG_INIT(" ioc[%d] ROPE_CFG 0x%Lx ROPE_DBG 0x%Lx\n", |
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 719b863bc20e..828eb45062de 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c | |||
@@ -155,7 +155,7 @@ superio_init(struct pci_dev *pcidev) | |||
155 | struct pci_dev *pdev = sio->lio_pdev; | 155 | struct pci_dev *pdev = sio->lio_pdev; |
156 | u16 word; | 156 | u16 word; |
157 | 157 | ||
158 | if (sio->suckyio_irq_enabled) | 158 | if (sio->suckyio_irq_enabled) |
159 | return; | 159 | return; |
160 | 160 | ||
161 | BUG_ON(!pdev); | 161 | BUG_ON(!pdev); |
@@ -194,7 +194,7 @@ superio_init(struct pci_dev *pcidev) | |||
194 | request_region (sio->acpi_base, 0x1f, "acpi"); | 194 | request_region (sio->acpi_base, 0x1f, "acpi"); |
195 | 195 | ||
196 | /* Enable the legacy I/O function */ | 196 | /* Enable the legacy I/O function */ |
197 | pci_read_config_word (pdev, PCI_COMMAND, &word); | 197 | pci_read_config_word (pdev, PCI_COMMAND, &word); |
198 | word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; | 198 | word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; |
199 | pci_write_config_word (pdev, PCI_COMMAND, word); | 199 | pci_write_config_word (pdev, PCI_COMMAND, word); |
200 | 200 | ||
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index cba6c9eef28e..61cb4b29f55c 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -250,7 +250,7 @@ config M32R_CFC_NUM | |||
250 | 250 | ||
251 | config PCMCIA_VRC4171 | 251 | config PCMCIA_VRC4171 |
252 | tristate "NEC VRC4171 Card Controllers support" | 252 | tristate "NEC VRC4171 Card Controllers support" |
253 | depends on VRC4171 && PCMCIA | 253 | depends on CPU_VR41XX && ISA && PCMCIA |
254 | 254 | ||
255 | config PCMCIA_VRC4173 | 255 | config PCMCIA_VRC4173 |
256 | tristate "NEC VRC4173 CARDU support" | 256 | tristate "NEC VRC4173 CARDU support" |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index ae10d1eed65e..48d3b3d30c21 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -236,11 +236,11 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) | |||
236 | /** | 236 | /** |
237 | * pcmcia_load_firmware - load CIS from userspace if device-provided is broken | 237 | * pcmcia_load_firmware - load CIS from userspace if device-provided is broken |
238 | * @dev - the pcmcia device which needs a CIS override | 238 | * @dev - the pcmcia device which needs a CIS override |
239 | * @filename - requested filename in /lib/firmware/cis/ | 239 | * @filename - requested filename in /lib/firmware/ |
240 | * | 240 | * |
241 | * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if | 241 | * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if |
242 | * the one provided by the card is broken. The firmware files reside in | 242 | * the one provided by the card is broken. The firmware files reside in |
243 | * /lib/firmware/cis/ in userspace. | 243 | * /lib/firmware/ in userspace. |
244 | */ | 244 | */ |
245 | static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | 245 | static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) |
246 | { | 246 | { |
@@ -298,9 +298,6 @@ static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filenam | |||
298 | * | 298 | * |
299 | * Registers a PCMCIA driver with the PCMCIA bus core. | 299 | * Registers a PCMCIA driver with the PCMCIA bus core. |
300 | */ | 300 | */ |
301 | static int pcmcia_device_probe(struct device *dev); | ||
302 | static int pcmcia_device_remove(struct device * dev); | ||
303 | |||
304 | int pcmcia_register_driver(struct pcmcia_driver *driver) | 301 | int pcmcia_register_driver(struct pcmcia_driver *driver) |
305 | { | 302 | { |
306 | if (!driver) | 303 | if (!driver) |
@@ -400,7 +397,7 @@ static int pcmcia_device_probe(struct device * dev) | |||
400 | * call which will then check whether there are two | 397 | * call which will then check whether there are two |
401 | * pseudo devices, and if not, add the second one. | 398 | * pseudo devices, and if not, add the second one. |
402 | */ | 399 | */ |
403 | did = (struct pcmcia_device_id *) p_dev->dev.driver_data; | 400 | did = p_dev->dev.driver_data; |
404 | if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && | 401 | if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && |
405 | (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) | 402 | (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) |
406 | pcmcia_add_pseudo_device(p_dev->socket); | 403 | pcmcia_add_pseudo_device(p_dev->socket); |
@@ -448,7 +445,6 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le | |||
448 | return; | 445 | return; |
449 | } | 446 | } |
450 | 447 | ||
451 | |||
452 | static int pcmcia_device_remove(struct device * dev) | 448 | static int pcmcia_device_remove(struct device * dev) |
453 | { | 449 | { |
454 | struct pcmcia_device *p_dev; | 450 | struct pcmcia_device *p_dev; |
@@ -463,7 +459,7 @@ static int pcmcia_device_remove(struct device * dev) | |||
463 | * pseudo multi-function card, we need to unbind | 459 | * pseudo multi-function card, we need to unbind |
464 | * all devices | 460 | * all devices |
465 | */ | 461 | */ |
466 | did = (struct pcmcia_device_id *) p_dev->dev.driver_data; | 462 | did = p_dev->dev.driver_data; |
467 | if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && | 463 | if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && |
468 | (p_dev->socket->device_count != 0) && | 464 | (p_dev->socket->device_count != 0) && |
469 | (p_dev->device_no == 0)) | 465 | (p_dev->device_no == 0)) |
@@ -476,6 +472,8 @@ static int pcmcia_device_remove(struct device * dev) | |||
476 | if (p_drv->remove) | 472 | if (p_drv->remove) |
477 | p_drv->remove(p_dev); | 473 | p_drv->remove(p_dev); |
478 | 474 | ||
475 | p_dev->dev_node = NULL; | ||
476 | |||
479 | /* check for proper unloading */ | 477 | /* check for proper unloading */ |
480 | if (p_dev->_irq || p_dev->_io || p_dev->_locked) | 478 | if (p_dev->_irq || p_dev->_io || p_dev->_locked) |
481 | printk(KERN_INFO "pcmcia: driver %s did not release config properly\n", | 479 | printk(KERN_INFO "pcmcia: driver %s did not release config properly\n", |
@@ -628,7 +626,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
628 | } | 626 | } |
629 | 627 | ||
630 | /* Add to the list in pcmcia_bus_socket */ | 628 | /* Add to the list in pcmcia_bus_socket */ |
631 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); | 629 | list_add(&p_dev->socket_device_list, &s->devices_list); |
632 | 630 | ||
633 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 631 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
634 | 632 | ||
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 45063b4e5b78..3131bb0a0095 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -88,7 +88,6 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, | |||
88 | } | 88 | } |
89 | if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { | 89 | if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { |
90 | *base = s->io_offset | (*base & 0x0fff); | 90 | *base = s->io_offset | (*base & 0x0fff); |
91 | s->io[0].res->flags = (s->io[0].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); | ||
92 | return 0; | 91 | return 0; |
93 | } | 92 | } |
94 | /* Check for an already-allocated window that must conflict with | 93 | /* Check for an already-allocated window that must conflict with |
@@ -209,7 +208,6 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, | |||
209 | if (!(s->state & SOCKET_PRESENT)) | 208 | if (!(s->state & SOCKET_PRESENT)) |
210 | return CS_NO_CARD; | 209 | return CS_NO_CARD; |
211 | 210 | ||
212 | config->Function = p_dev->func; | ||
213 | 211 | ||
214 | #ifdef CONFIG_CARDBUS | 212 | #ifdef CONFIG_CARDBUS |
215 | if (s->state & SOCKET_CARDBUS) { | 213 | if (s->state & SOCKET_CARDBUS) { |
@@ -223,14 +221,22 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, | |||
223 | config->AssignedIRQ = s->irq.AssignedIRQ; | 221 | config->AssignedIRQ = s->irq.AssignedIRQ; |
224 | if (config->AssignedIRQ) | 222 | if (config->AssignedIRQ) |
225 | config->Attributes |= CONF_ENABLE_IRQ; | 223 | config->Attributes |= CONF_ENABLE_IRQ; |
226 | config->BasePort1 = s->io[0].res->start; | 224 | if (s->io[0].res) { |
227 | config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1; | 225 | config->BasePort1 = s->io[0].res->start; |
226 | config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1; | ||
227 | } | ||
228 | } | 228 | } |
229 | return CS_SUCCESS; | 229 | return CS_SUCCESS; |
230 | } | 230 | } |
231 | #endif | 231 | #endif |
232 | 232 | ||
233 | c = (p_dev) ? p_dev->function_config : NULL; | 233 | if (p_dev) { |
234 | c = p_dev->function_config; | ||
235 | config->Function = p_dev->func; | ||
236 | } else { | ||
237 | c = NULL; | ||
238 | config->Function = 0; | ||
239 | } | ||
234 | 240 | ||
235 | if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { | 241 | if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { |
236 | config->Attributes = 0; | 242 | config->Attributes = 0; |
@@ -947,7 +953,5 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) { | |||
947 | pcmcia_release_irq(p_dev, &p_dev->irq); | 953 | pcmcia_release_irq(p_dev, &p_dev->irq); |
948 | if (&p_dev->win) | 954 | if (&p_dev->win) |
949 | pcmcia_release_window(p_dev->win); | 955 | pcmcia_release_window(p_dev->win); |
950 | |||
951 | p_dev->dev_node = NULL; | ||
952 | } | 956 | } |
953 | EXPORT_SYMBOL(pcmcia_disable_device); | 957 | EXPORT_SYMBOL(pcmcia_disable_device); |