diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/Kconfig | 22 | ||||
-rw-r--r-- | drivers/pcmcia/Makefile | 9 | ||||
-rw-r--r-- | drivers/pcmcia/bfin_cf_pcmcia.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/cardbus.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/cistpl.c | 121 | ||||
-rw-r--r-- | drivers/pcmcia/cs.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 22 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 34 | ||||
-rw-r--r-- | drivers/pcmcia/omap_cf.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_cis.c | 356 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_ioctl.c | 23 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 634 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_iodyn.c | 172 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_mgr.c | 112 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 164 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 7 |
16 files changed, 893 insertions, 789 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index a44733d44ca1..d0f5ad306078 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -49,26 +49,6 @@ config PCMCIA_LOAD_CIS | |||
49 | 49 | ||
50 | If unsure, say Y. | 50 | If unsure, say Y. |
51 | 51 | ||
52 | config PCMCIA_IOCTL | ||
53 | bool "PCMCIA control ioctl (obsolete)" | ||
54 | depends on PCMCIA && ARM && !SMP && !PREEMPT | ||
55 | default y | ||
56 | help | ||
57 | If you say Y here, the deprecated ioctl interface to the PCMCIA | ||
58 | subsystem will be built. It is needed by the deprecated pcmcia-cs | ||
59 | tools (cardmgr, cardctl) to function properly. | ||
60 | |||
61 | You should use the new pcmciautils package instead (see | ||
62 | <file:Documentation/Changes> for location and details). | ||
63 | |||
64 | This config option will most likely be removed from kernel 2.6.35, | ||
65 | the associated code from kernel 2.6.36. | ||
66 | |||
67 | As the PCMCIA ioctl is not locking safe, it depends on !SMP and | ||
68 | !PREEMPT. | ||
69 | |||
70 | If unsure, say N. | ||
71 | |||
72 | config CARDBUS | 52 | config CARDBUS |
73 | bool "32-bit CardBus support" | 53 | bool "32-bit CardBus support" |
74 | depends on PCI | 54 | depends on PCI |
@@ -318,7 +298,7 @@ config ELECTRA_CF | |||
318 | PA Semi Electra eval board. | 298 | PA Semi Electra eval board. |
319 | 299 | ||
320 | config PCCARD_NONSTATIC | 300 | config PCCARD_NONSTATIC |
321 | tristate | 301 | bool |
322 | 302 | ||
323 | config PCCARD_IODYN | 303 | config PCCARD_IODYN |
324 | bool | 304 | bool |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 4dae3613c458..d006e8beab9c 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -2,15 +2,18 @@ | |||
2 | # Makefile for the kernel pcmcia subsystem (c/o David Hinds) | 2 | # Makefile for the kernel pcmcia subsystem (c/o David Hinds) |
3 | # | 3 | # |
4 | 4 | ||
5 | pcmcia_core-y += cs.o rsrc_mgr.o socket_sysfs.o | 5 | pcmcia_core-y += cs.o socket_sysfs.o |
6 | pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o | 6 | pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o |
7 | obj-$(CONFIG_PCCARD) += pcmcia_core.o | 7 | obj-$(CONFIG_PCCARD) += pcmcia_core.o |
8 | 8 | ||
9 | pcmcia-y += ds.o pcmcia_resource.o cistpl.o | 9 | pcmcia-y += ds.o pcmcia_resource.o cistpl.o pcmcia_cis.o |
10 | pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o | 10 | pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o |
11 | obj-$(CONFIG_PCMCIA) += pcmcia.o | 11 | obj-$(CONFIG_PCMCIA) += pcmcia.o |
12 | 12 | ||
13 | obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o | 13 | pcmcia_rsrc-y += rsrc_mgr.o |
14 | pcmcia_rsrc-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o | ||
15 | pcmcia_rsrc-$(CONFIG_PCCARD_IODYN) += rsrc_iodyn.o | ||
16 | obj-$(CONFIG_PCCARD) += pcmcia_rsrc.o | ||
14 | 17 | ||
15 | 18 | ||
16 | # socket drivers | 19 | # socket drivers |
diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c index 9e84d039de41..eae9cbe37a3e 100644 --- a/drivers/pcmcia/bfin_cf_pcmcia.c +++ b/drivers/pcmcia/bfin_cf_pcmcia.c | |||
@@ -113,7 +113,7 @@ static int bfin_cf_get_status(struct pcmcia_socket *s, u_int *sp) | |||
113 | 113 | ||
114 | if (bfin_cf_present(cf->cd_pfx)) { | 114 | if (bfin_cf_present(cf->cd_pfx)) { |
115 | *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD; | 115 | *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD; |
116 | s->irq.AssignedIRQ = 0; | 116 | s->pcmcia_irq = 0; |
117 | s->pci_irq = cf->irq; | 117 | s->pci_irq = cf->irq; |
118 | 118 | ||
119 | } else | 119 | } else |
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index e6ab2a47d8cb..9a58862f1401 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c | |||
@@ -94,7 +94,6 @@ int __ref cb_alloc(struct pcmcia_socket *s) | |||
94 | pci_enable_bridges(bus); | 94 | pci_enable_bridges(bus); |
95 | pci_bus_add_devices(bus); | 95 | pci_bus_add_devices(bus); |
96 | 96 | ||
97 | s->irq.AssignedIRQ = s->pci_irq; | ||
98 | return 0; | 97 | return 0; |
99 | } | 98 | } |
100 | 99 | ||
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 854959cada3a..60d428be0b07 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -129,6 +129,8 @@ static void __iomem *set_cis_map(struct pcmcia_socket *s, | |||
129 | 129 | ||
130 | /** | 130 | /** |
131 | * pcmcia_read_cis_mem() - low-level function to read CIS memory | 131 | * pcmcia_read_cis_mem() - low-level function to read CIS memory |
132 | * | ||
133 | * must be called with ops_mutex held | ||
132 | */ | 134 | */ |
133 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | 135 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, |
134 | u_int len, void *ptr) | 136 | u_int len, void *ptr) |
@@ -138,7 +140,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
138 | 140 | ||
139 | dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); | 141 | dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); |
140 | 142 | ||
141 | mutex_lock(&s->ops_mutex); | ||
142 | if (attr & IS_INDIRECT) { | 143 | if (attr & IS_INDIRECT) { |
143 | /* Indirect accesses use a bunch of special registers at fixed | 144 | /* Indirect accesses use a bunch of special registers at fixed |
144 | locations in common memory */ | 145 | locations in common memory */ |
@@ -153,7 +154,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
153 | if (!sys) { | 154 | if (!sys) { |
154 | dev_dbg(&s->dev, "could not map memory\n"); | 155 | dev_dbg(&s->dev, "could not map memory\n"); |
155 | memset(ptr, 0xff, len); | 156 | memset(ptr, 0xff, len); |
156 | mutex_unlock(&s->ops_mutex); | ||
157 | return -1; | 157 | return -1; |
158 | } | 158 | } |
159 | 159 | ||
@@ -184,7 +184,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
184 | if (!sys) { | 184 | if (!sys) { |
185 | dev_dbg(&s->dev, "could not map memory\n"); | 185 | dev_dbg(&s->dev, "could not map memory\n"); |
186 | memset(ptr, 0xff, len); | 186 | memset(ptr, 0xff, len); |
187 | mutex_unlock(&s->ops_mutex); | ||
188 | return -1; | 187 | return -1; |
189 | } | 188 | } |
190 | end = sys + s->map_size; | 189 | end = sys + s->map_size; |
@@ -198,7 +197,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
198 | addr = 0; | 197 | addr = 0; |
199 | } | 198 | } |
200 | } | 199 | } |
201 | mutex_unlock(&s->ops_mutex); | ||
202 | dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n", | 200 | dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n", |
203 | *(u_char *)(ptr+0), *(u_char *)(ptr+1), | 201 | *(u_char *)(ptr+0), *(u_char *)(ptr+1), |
204 | *(u_char *)(ptr+2), *(u_char *)(ptr+3)); | 202 | *(u_char *)(ptr+2), *(u_char *)(ptr+3)); |
@@ -209,7 +207,8 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
209 | /** | 207 | /** |
210 | * pcmcia_write_cis_mem() - low-level function to write CIS memory | 208 | * pcmcia_write_cis_mem() - low-level function to write CIS memory |
211 | * | 209 | * |
212 | * Probably only useful for writing one-byte registers. | 210 | * Probably only useful for writing one-byte registers. Must be called |
211 | * with ops_mutex held. | ||
213 | */ | 212 | */ |
214 | void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | 213 | void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, |
215 | u_int len, void *ptr) | 214 | u_int len, void *ptr) |
@@ -220,7 +219,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
220 | dev_dbg(&s->dev, | 219 | dev_dbg(&s->dev, |
221 | "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); | 220 | "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); |
222 | 221 | ||
223 | mutex_lock(&s->ops_mutex); | ||
224 | if (attr & IS_INDIRECT) { | 222 | if (attr & IS_INDIRECT) { |
225 | /* Indirect accesses use a bunch of special registers at fixed | 223 | /* Indirect accesses use a bunch of special registers at fixed |
226 | locations in common memory */ | 224 | locations in common memory */ |
@@ -234,7 +232,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
234 | ((cis_width) ? MAP_16BIT : 0)); | 232 | ((cis_width) ? MAP_16BIT : 0)); |
235 | if (!sys) { | 233 | if (!sys) { |
236 | dev_dbg(&s->dev, "could not map memory\n"); | 234 | dev_dbg(&s->dev, "could not map memory\n"); |
237 | mutex_unlock(&s->ops_mutex); | ||
238 | return; /* FIXME: Error */ | 235 | return; /* FIXME: Error */ |
239 | } | 236 | } |
240 | 237 | ||
@@ -260,7 +257,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
260 | sys = set_cis_map(s, card_offset, flags); | 257 | sys = set_cis_map(s, card_offset, flags); |
261 | if (!sys) { | 258 | if (!sys) { |
262 | dev_dbg(&s->dev, "could not map memory\n"); | 259 | dev_dbg(&s->dev, "could not map memory\n"); |
263 | mutex_unlock(&s->ops_mutex); | ||
264 | return; /* FIXME: error */ | 260 | return; /* FIXME: error */ |
265 | } | 261 | } |
266 | 262 | ||
@@ -275,7 +271,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
275 | addr = 0; | 271 | addr = 0; |
276 | } | 272 | } |
277 | } | 273 | } |
278 | mutex_unlock(&s->ops_mutex); | ||
279 | } | 274 | } |
280 | 275 | ||
281 | 276 | ||
@@ -314,7 +309,6 @@ static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, | |||
314 | return 0; | 309 | return 0; |
315 | } | 310 | } |
316 | } | 311 | } |
317 | mutex_unlock(&s->ops_mutex); | ||
318 | 312 | ||
319 | ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); | 313 | ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); |
320 | 314 | ||
@@ -326,11 +320,11 @@ static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, | |||
326 | cis->len = len; | 320 | cis->len = len; |
327 | cis->attr = attr; | 321 | cis->attr = attr; |
328 | memcpy(cis->cache, ptr, len); | 322 | memcpy(cis->cache, ptr, len); |
329 | mutex_lock(&s->ops_mutex); | ||
330 | list_add(&cis->node, &s->cis_cache); | 323 | list_add(&cis->node, &s->cis_cache); |
331 | mutex_unlock(&s->ops_mutex); | ||
332 | } | 324 | } |
333 | } | 325 | } |
326 | mutex_unlock(&s->ops_mutex); | ||
327 | |||
334 | return ret; | 328 | return ret; |
335 | } | 329 | } |
336 | 330 | ||
@@ -386,6 +380,7 @@ int verify_cis_cache(struct pcmcia_socket *s) | |||
386 | "no memory for verifying CIS\n"); | 380 | "no memory for verifying CIS\n"); |
387 | return -ENOMEM; | 381 | return -ENOMEM; |
388 | } | 382 | } |
383 | mutex_lock(&s->ops_mutex); | ||
389 | list_for_each_entry(cis, &s->cis_cache, node) { | 384 | list_for_each_entry(cis, &s->cis_cache, node) { |
390 | int len = cis->len; | 385 | int len = cis->len; |
391 | 386 | ||
@@ -395,10 +390,12 @@ int verify_cis_cache(struct pcmcia_socket *s) | |||
395 | ret = pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); | 390 | ret = pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); |
396 | if (ret || memcmp(buf, cis->cache, len) != 0) { | 391 | if (ret || memcmp(buf, cis->cache, len) != 0) { |
397 | kfree(buf); | 392 | kfree(buf); |
393 | mutex_unlock(&s->ops_mutex); | ||
398 | return -1; | 394 | return -1; |
399 | } | 395 | } |
400 | } | 396 | } |
401 | kfree(buf); | 397 | kfree(buf); |
398 | mutex_unlock(&s->ops_mutex); | ||
402 | return 0; | 399 | return 0; |
403 | } | 400 | } |
404 | 401 | ||
@@ -1362,106 +1359,6 @@ EXPORT_SYMBOL(pcmcia_parse_tuple); | |||
1362 | 1359 | ||
1363 | 1360 | ||
1364 | /** | 1361 | /** |
1365 | * pccard_read_tuple() - internal CIS tuple access | ||
1366 | * @s: the struct pcmcia_socket where the card is inserted | ||
1367 | * @function: the device function we loop for | ||
1368 | * @code: which CIS code shall we look for? | ||
1369 | * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) | ||
1370 | * | ||
1371 | * pccard_read_tuple() reads out one tuple and attempts to parse it | ||
1372 | */ | ||
1373 | int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, | ||
1374 | cisdata_t code, void *parse) | ||
1375 | { | ||
1376 | tuple_t tuple; | ||
1377 | cisdata_t *buf; | ||
1378 | int ret; | ||
1379 | |||
1380 | buf = kmalloc(256, GFP_KERNEL); | ||
1381 | if (buf == NULL) { | ||
1382 | dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); | ||
1383 | return -ENOMEM; | ||
1384 | } | ||
1385 | tuple.DesiredTuple = code; | ||
1386 | tuple.Attributes = 0; | ||
1387 | if (function == BIND_FN_ALL) | ||
1388 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
1389 | ret = pccard_get_first_tuple(s, function, &tuple); | ||
1390 | if (ret != 0) | ||
1391 | goto done; | ||
1392 | tuple.TupleData = buf; | ||
1393 | tuple.TupleOffset = 0; | ||
1394 | tuple.TupleDataMax = 255; | ||
1395 | ret = pccard_get_tuple_data(s, &tuple); | ||
1396 | if (ret != 0) | ||
1397 | goto done; | ||
1398 | ret = pcmcia_parse_tuple(&tuple, parse); | ||
1399 | done: | ||
1400 | kfree(buf); | ||
1401 | return ret; | ||
1402 | } | ||
1403 | |||
1404 | |||
1405 | /** | ||
1406 | * pccard_loop_tuple() - loop over tuples in the CIS | ||
1407 | * @s: the struct pcmcia_socket where the card is inserted | ||
1408 | * @function: the device function we loop for | ||
1409 | * @code: which CIS code shall we look for? | ||
1410 | * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) | ||
1411 | * @priv_data: private data to be passed to the loop_tuple function. | ||
1412 | * @loop_tuple: function to call for each CIS entry of type @function. IT | ||
1413 | * gets passed the raw tuple, the paresed tuple (if @parse is | ||
1414 | * set) and @priv_data. | ||
1415 | * | ||
1416 | * pccard_loop_tuple() loops over all CIS entries of type @function, and | ||
1417 | * calls the @loop_tuple function for each entry. If the call to @loop_tuple | ||
1418 | * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. | ||
1419 | */ | ||
1420 | int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, | ||
1421 | cisdata_t code, cisparse_t *parse, void *priv_data, | ||
1422 | int (*loop_tuple) (tuple_t *tuple, | ||
1423 | cisparse_t *parse, | ||
1424 | void *priv_data)) | ||
1425 | { | ||
1426 | tuple_t tuple; | ||
1427 | cisdata_t *buf; | ||
1428 | int ret; | ||
1429 | |||
1430 | buf = kzalloc(256, GFP_KERNEL); | ||
1431 | if (buf == NULL) { | ||
1432 | dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); | ||
1433 | return -ENOMEM; | ||
1434 | } | ||
1435 | |||
1436 | tuple.TupleData = buf; | ||
1437 | tuple.TupleDataMax = 255; | ||
1438 | tuple.TupleOffset = 0; | ||
1439 | tuple.DesiredTuple = code; | ||
1440 | tuple.Attributes = 0; | ||
1441 | |||
1442 | ret = pccard_get_first_tuple(s, function, &tuple); | ||
1443 | while (!ret) { | ||
1444 | if (pccard_get_tuple_data(s, &tuple)) | ||
1445 | goto next_entry; | ||
1446 | |||
1447 | if (parse) | ||
1448 | if (pcmcia_parse_tuple(&tuple, parse)) | ||
1449 | goto next_entry; | ||
1450 | |||
1451 | ret = loop_tuple(&tuple, parse, priv_data); | ||
1452 | if (!ret) | ||
1453 | break; | ||
1454 | |||
1455 | next_entry: | ||
1456 | ret = pccard_get_next_tuple(s, function, &tuple); | ||
1457 | } | ||
1458 | |||
1459 | kfree(buf); | ||
1460 | return ret; | ||
1461 | } | ||
1462 | |||
1463 | |||
1464 | /** | ||
1465 | * pccard_validate_cis() - check whether card has a sensible CIS | 1362 | * pccard_validate_cis() - check whether card has a sensible CIS |
1466 | * @s: the struct pcmcia_socket we are to check | 1363 | * @s: the struct pcmcia_socket we are to check |
1467 | * @info: returns the number of tuples in the (valid) CIS, or 0 | 1364 | * @info: returns the number of tuples in the (valid) CIS, or 0 |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index c3383750e333..976d80706eae 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -337,7 +337,6 @@ static void socket_shutdown(struct pcmcia_socket *s) | |||
337 | s->socket = dead_socket; | 337 | s->socket = dead_socket; |
338 | s->ops->init(s); | 338 | s->ops->init(s); |
339 | s->ops->set_socket(s, &s->socket); | 339 | s->ops->set_socket(s, &s->socket); |
340 | s->irq.AssignedIRQ = s->irq.Config = 0; | ||
341 | s->lock_count = 0; | 340 | s->lock_count = 0; |
342 | kfree(s->fake_cis); | 341 | kfree(s->fake_cis); |
343 | s->fake_cis = NULL; | 342 | s->fake_cis = NULL; |
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index f95864c2191e..4126a75445ea 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -52,13 +52,11 @@ struct cis_cache_entry { | |||
52 | 52 | ||
53 | struct pccard_resource_ops { | 53 | struct pccard_resource_ops { |
54 | int (*validate_mem) (struct pcmcia_socket *s); | 54 | int (*validate_mem) (struct pcmcia_socket *s); |
55 | int (*adjust_io_region) (struct resource *res, | 55 | int (*find_io) (struct pcmcia_socket *s, |
56 | unsigned long r_start, | 56 | unsigned int attr, |
57 | unsigned long r_end, | 57 | unsigned int *base, |
58 | struct pcmcia_socket *s); | 58 | unsigned int num, |
59 | struct resource* (*find_io) (unsigned long base, int num, | 59 | unsigned int align); |
60 | unsigned long align, | ||
61 | struct pcmcia_socket *s); | ||
62 | struct resource* (*find_mem) (unsigned long base, unsigned long num, | 60 | struct resource* (*find_mem) (unsigned long base, unsigned long num, |
63 | unsigned long align, int low, | 61 | unsigned long align, int low, |
64 | struct pcmcia_socket *s); | 62 | struct pcmcia_socket *s); |
@@ -89,6 +87,14 @@ struct pccard_resource_ops { | |||
89 | 87 | ||
90 | 88 | ||
91 | /* | 89 | /* |
90 | * Stuff internal to module "pcmcia_rsrc": | ||
91 | */ | ||
92 | extern int static_init(struct pcmcia_socket *s); | ||
93 | extern struct resource *pcmcia_make_resource(unsigned long start, | ||
94 | unsigned long end, | ||
95 | int flags, const char *name); | ||
96 | |||
97 | /* | ||
92 | * Stuff internal to module "pcmcia_core": | 98 | * Stuff internal to module "pcmcia_core": |
93 | */ | 99 | */ |
94 | 100 | ||
@@ -149,6 +155,8 @@ extern struct resource *pcmcia_find_mem_region(u_long base, | |||
149 | int low, | 155 | int low, |
150 | struct pcmcia_socket *s); | 156 | struct pcmcia_socket *s); |
151 | 157 | ||
158 | void pcmcia_cleanup_irq(struct pcmcia_socket *s); | ||
159 | int pcmcia_setup_irq(struct pcmcia_device *p_dev); | ||
152 | 160 | ||
153 | /* cistpl.c */ | 161 | /* cistpl.c */ |
154 | extern struct bin_attribute pccard_cis_attr; | 162 | extern struct bin_attribute pccard_cis_attr; |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 041eee43fd8d..7ef7adee5e4f 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -371,8 +371,6 @@ static int pcmcia_device_remove(struct device *dev) | |||
371 | if (p_drv->remove) | 371 | if (p_drv->remove) |
372 | p_drv->remove(p_dev); | 372 | p_drv->remove(p_dev); |
373 | 373 | ||
374 | p_dev->dev_node = NULL; | ||
375 | |||
376 | /* check for proper unloading */ | 374 | /* check for proper unloading */ |
377 | if (p_dev->_irq || p_dev->_io || p_dev->_locked) | 375 | if (p_dev->_irq || p_dev->_io || p_dev->_locked) |
378 | dev_printk(KERN_INFO, dev, | 376 | dev_printk(KERN_INFO, dev, |
@@ -479,15 +477,6 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
479 | } | 477 | } |
480 | 478 | ||
481 | 479 | ||
482 | /* device_add_lock is needed to avoid double registration by cardmgr and kernel. | ||
483 | * Serializes pcmcia_device_add; will most likely be removed in future. | ||
484 | * | ||
485 | * While it has the caveat that adding new PCMCIA devices inside(!) device_register() | ||
486 | * won't work, this doesn't matter much at the moment: the driver core doesn't | ||
487 | * support it either. | ||
488 | */ | ||
489 | static DEFINE_MUTEX(device_add_lock); | ||
490 | |||
491 | struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) | 480 | struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) |
492 | { | 481 | { |
493 | struct pcmcia_device *p_dev, *tmp_dev; | 482 | struct pcmcia_device *p_dev, *tmp_dev; |
@@ -497,8 +486,6 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu | |||
497 | if (!s) | 486 | if (!s) |
498 | return NULL; | 487 | return NULL; |
499 | 488 | ||
500 | mutex_lock(&device_add_lock); | ||
501 | |||
502 | pr_debug("adding device to %d, function %d\n", s->sock, function); | 489 | pr_debug("adding device to %d, function %d\n", s->sock, function); |
503 | 490 | ||
504 | p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL); | 491 | p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL); |
@@ -538,8 +525,8 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu | |||
538 | 525 | ||
539 | /* | 526 | /* |
540 | * p_dev->function_config must be the same for all card functions. | 527 | * p_dev->function_config must be the same for all card functions. |
541 | * Note that this is serialized by the device_add_lock, so that | 528 | * Note that this is serialized by ops_mutex, so that only one |
542 | * only one such struct will be created. | 529 | * such struct will be created. |
543 | */ | 530 | */ |
544 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) | 531 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) |
545 | if (p_dev->func == tmp_dev->func) { | 532 | if (p_dev->func == tmp_dev->func) { |
@@ -552,28 +539,31 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu | |||
552 | /* Add to the list in pcmcia_bus_socket */ | 539 | /* Add to the list in pcmcia_bus_socket */ |
553 | list_add(&p_dev->socket_device_list, &s->devices_list); | 540 | list_add(&p_dev->socket_device_list, &s->devices_list); |
554 | 541 | ||
555 | mutex_unlock(&s->ops_mutex); | 542 | if (pcmcia_setup_irq(p_dev)) |
543 | dev_warn(&p_dev->dev, | ||
544 | "IRQ setup failed -- device might not work\n"); | ||
556 | 545 | ||
557 | if (!p_dev->function_config) { | 546 | if (!p_dev->function_config) { |
558 | dev_dbg(&p_dev->dev, "creating config_t\n"); | 547 | dev_dbg(&p_dev->dev, "creating config_t\n"); |
559 | p_dev->function_config = kzalloc(sizeof(struct config_t), | 548 | p_dev->function_config = kzalloc(sizeof(struct config_t), |
560 | GFP_KERNEL); | 549 | GFP_KERNEL); |
561 | if (!p_dev->function_config) | 550 | if (!p_dev->function_config) { |
551 | mutex_unlock(&s->ops_mutex); | ||
562 | goto err_unreg; | 552 | goto err_unreg; |
553 | } | ||
563 | kref_init(&p_dev->function_config->ref); | 554 | kref_init(&p_dev->function_config->ref); |
564 | } | 555 | } |
556 | mutex_unlock(&s->ops_mutex); | ||
565 | 557 | ||
566 | dev_printk(KERN_NOTICE, &p_dev->dev, | 558 | dev_printk(KERN_NOTICE, &p_dev->dev, |
567 | "pcmcia: registering new device %s\n", | 559 | "pcmcia: registering new device %s (IRQ: %d)\n", |
568 | p_dev->devname); | 560 | p_dev->devname, p_dev->irq); |
569 | 561 | ||
570 | pcmcia_device_query(p_dev); | 562 | pcmcia_device_query(p_dev); |
571 | 563 | ||
572 | if (device_register(&p_dev->dev)) | 564 | if (device_register(&p_dev->dev)) |
573 | goto err_unreg; | 565 | goto err_unreg; |
574 | 566 | ||
575 | mutex_unlock(&device_add_lock); | ||
576 | |||
577 | return p_dev; | 567 | return p_dev; |
578 | 568 | ||
579 | err_unreg: | 569 | err_unreg: |
@@ -591,7 +581,6 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu | |||
591 | kfree(p_dev->devname); | 581 | kfree(p_dev->devname); |
592 | kfree(p_dev); | 582 | kfree(p_dev); |
593 | err_put: | 583 | err_put: |
594 | mutex_unlock(&device_add_lock); | ||
595 | pcmcia_put_socket(s); | 584 | pcmcia_put_socket(s); |
596 | 585 | ||
597 | return NULL; | 586 | return NULL; |
@@ -1258,6 +1247,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1258 | handle_event(skt, event); | 1247 | handle_event(skt, event); |
1259 | mutex_lock(&s->ops_mutex); | 1248 | mutex_lock(&s->ops_mutex); |
1260 | destroy_cis_cache(s); | 1249 | destroy_cis_cache(s); |
1250 | pcmcia_cleanup_irq(s); | ||
1261 | mutex_unlock(&s->ops_mutex); | 1251 | mutex_unlock(&s->ops_mutex); |
1262 | break; | 1252 | break; |
1263 | 1253 | ||
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index a7cfc7964c7c..0ad06a3bd562 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c | |||
@@ -117,7 +117,7 @@ static int omap_cf_get_status(struct pcmcia_socket *s, u_int *sp) | |||
117 | 117 | ||
118 | *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD; | 118 | *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD; |
119 | cf = container_of(s, struct omap_cf_socket, socket); | 119 | cf = container_of(s, struct omap_cf_socket, socket); |
120 | s->irq.AssignedIRQ = 0; | 120 | s->pcmcia_irq = 0; |
121 | s->pci_irq = cf->irq; | 121 | s->pci_irq = cf->irq; |
122 | } else | 122 | } else |
123 | *sp = 0; | 123 | *sp = 0; |
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c new file mode 100644 index 000000000000..4a65eaf96b0a --- /dev/null +++ b/drivers/pcmcia/pcmcia_cis.c | |||
@@ -0,0 +1,356 @@ | |||
1 | /* | ||
2 | * PCMCIA high-level CIS access functions | ||
3 | * | ||
4 | * The initial developer of the original code is David A. Hinds | ||
5 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
7 | * | ||
8 | * Copyright (C) 1999 David A. Hinds | ||
9 | * Copyright (C) 2004-2009 Dominik Brodowski | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | |||
22 | #include <pcmcia/cs_types.h> | ||
23 | #include <pcmcia/cisreg.h> | ||
24 | #include <pcmcia/cistpl.h> | ||
25 | #include <pcmcia/ss.h> | ||
26 | #include <pcmcia/cs.h> | ||
27 | #include <pcmcia/ds.h> | ||
28 | #include "cs_internal.h" | ||
29 | |||
30 | |||
31 | /** | ||
32 | * pccard_read_tuple() - internal CIS tuple access | ||
33 | * @s: the struct pcmcia_socket where the card is inserted | ||
34 | * @function: the device function we loop for | ||
35 | * @code: which CIS code shall we look for? | ||
36 | * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) | ||
37 | * | ||
38 | * pccard_read_tuple() reads out one tuple and attempts to parse it | ||
39 | */ | ||
40 | int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, | ||
41 | cisdata_t code, void *parse) | ||
42 | { | ||
43 | tuple_t tuple; | ||
44 | cisdata_t *buf; | ||
45 | int ret; | ||
46 | |||
47 | buf = kmalloc(256, GFP_KERNEL); | ||
48 | if (buf == NULL) { | ||
49 | dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); | ||
50 | return -ENOMEM; | ||
51 | } | ||
52 | tuple.DesiredTuple = code; | ||
53 | tuple.Attributes = 0; | ||
54 | if (function == BIND_FN_ALL) | ||
55 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
56 | ret = pccard_get_first_tuple(s, function, &tuple); | ||
57 | if (ret != 0) | ||
58 | goto done; | ||
59 | tuple.TupleData = buf; | ||
60 | tuple.TupleOffset = 0; | ||
61 | tuple.TupleDataMax = 255; | ||
62 | ret = pccard_get_tuple_data(s, &tuple); | ||
63 | if (ret != 0) | ||
64 | goto done; | ||
65 | ret = pcmcia_parse_tuple(&tuple, parse); | ||
66 | done: | ||
67 | kfree(buf); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | |||
72 | /** | ||
73 | * pccard_loop_tuple() - loop over tuples in the CIS | ||
74 | * @s: the struct pcmcia_socket where the card is inserted | ||
75 | * @function: the device function we loop for | ||
76 | * @code: which CIS code shall we look for? | ||
77 | * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) | ||
78 | * @priv_data: private data to be passed to the loop_tuple function. | ||
79 | * @loop_tuple: function to call for each CIS entry of type @function. IT | ||
80 | * gets passed the raw tuple, the paresed tuple (if @parse is | ||
81 | * set) and @priv_data. | ||
82 | * | ||
83 | * pccard_loop_tuple() loops over all CIS entries of type @function, and | ||
84 | * calls the @loop_tuple function for each entry. If the call to @loop_tuple | ||
85 | * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. | ||
86 | */ | ||
87 | int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, | ||
88 | cisdata_t code, cisparse_t *parse, void *priv_data, | ||
89 | int (*loop_tuple) (tuple_t *tuple, | ||
90 | cisparse_t *parse, | ||
91 | void *priv_data)) | ||
92 | { | ||
93 | tuple_t tuple; | ||
94 | cisdata_t *buf; | ||
95 | int ret; | ||
96 | |||
97 | buf = kzalloc(256, GFP_KERNEL); | ||
98 | if (buf == NULL) { | ||
99 | dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); | ||
100 | return -ENOMEM; | ||
101 | } | ||
102 | |||
103 | tuple.TupleData = buf; | ||
104 | tuple.TupleDataMax = 255; | ||
105 | tuple.TupleOffset = 0; | ||
106 | tuple.DesiredTuple = code; | ||
107 | tuple.Attributes = 0; | ||
108 | |||
109 | ret = pccard_get_first_tuple(s, function, &tuple); | ||
110 | while (!ret) { | ||
111 | if (pccard_get_tuple_data(s, &tuple)) | ||
112 | goto next_entry; | ||
113 | |||
114 | if (parse) | ||
115 | if (pcmcia_parse_tuple(&tuple, parse)) | ||
116 | goto next_entry; | ||
117 | |||
118 | ret = loop_tuple(&tuple, parse, priv_data); | ||
119 | if (!ret) | ||
120 | break; | ||
121 | |||
122 | next_entry: | ||
123 | ret = pccard_get_next_tuple(s, function, &tuple); | ||
124 | } | ||
125 | |||
126 | kfree(buf); | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | struct pcmcia_cfg_mem { | ||
131 | struct pcmcia_device *p_dev; | ||
132 | void *priv_data; | ||
133 | int (*conf_check) (struct pcmcia_device *p_dev, | ||
134 | cistpl_cftable_entry_t *cfg, | ||
135 | cistpl_cftable_entry_t *dflt, | ||
136 | unsigned int vcc, | ||
137 | void *priv_data); | ||
138 | cisparse_t parse; | ||
139 | cistpl_cftable_entry_t dflt; | ||
140 | }; | ||
141 | |||
142 | /** | ||
143 | * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config() | ||
144 | * | ||
145 | * pcmcia_do_loop_config() is the internal callback for the call from | ||
146 | * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred | ||
147 | * by a struct pcmcia_cfg_mem. | ||
148 | */ | ||
149 | static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) | ||
150 | { | ||
151 | cistpl_cftable_entry_t *cfg = &parse->cftable_entry; | ||
152 | struct pcmcia_cfg_mem *cfg_mem = priv; | ||
153 | |||
154 | /* default values */ | ||
155 | cfg_mem->p_dev->conf.ConfigIndex = cfg->index; | ||
156 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
157 | cfg_mem->dflt = *cfg; | ||
158 | |||
159 | return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, | ||
160 | cfg_mem->p_dev->socket->socket.Vcc, | ||
161 | cfg_mem->priv_data); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * pcmcia_loop_config() - loop over configuration options | ||
166 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
167 | * @conf_check: function to call for each configuration option. | ||
168 | * It gets passed the struct pcmcia_device, the CIS data | ||
169 | * describing the configuration option, and private data | ||
170 | * being passed to pcmcia_loop_config() | ||
171 | * @priv_data: private data to be passed to the conf_check function. | ||
172 | * | ||
173 | * pcmcia_loop_config() loops over all configuration options, and calls | ||
174 | * the driver-specific conf_check() for each one, checking whether | ||
175 | * it is a valid one. Returns 0 on success or errorcode otherwise. | ||
176 | */ | ||
177 | int pcmcia_loop_config(struct pcmcia_device *p_dev, | ||
178 | int (*conf_check) (struct pcmcia_device *p_dev, | ||
179 | cistpl_cftable_entry_t *cfg, | ||
180 | cistpl_cftable_entry_t *dflt, | ||
181 | unsigned int vcc, | ||
182 | void *priv_data), | ||
183 | void *priv_data) | ||
184 | { | ||
185 | struct pcmcia_cfg_mem *cfg_mem; | ||
186 | int ret; | ||
187 | |||
188 | cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL); | ||
189 | if (cfg_mem == NULL) | ||
190 | return -ENOMEM; | ||
191 | |||
192 | cfg_mem->p_dev = p_dev; | ||
193 | cfg_mem->conf_check = conf_check; | ||
194 | cfg_mem->priv_data = priv_data; | ||
195 | |||
196 | ret = pccard_loop_tuple(p_dev->socket, p_dev->func, | ||
197 | CISTPL_CFTABLE_ENTRY, &cfg_mem->parse, | ||
198 | cfg_mem, pcmcia_do_loop_config); | ||
199 | |||
200 | kfree(cfg_mem); | ||
201 | return ret; | ||
202 | } | ||
203 | EXPORT_SYMBOL(pcmcia_loop_config); | ||
204 | |||
205 | |||
206 | struct pcmcia_loop_mem { | ||
207 | struct pcmcia_device *p_dev; | ||
208 | void *priv_data; | ||
209 | int (*loop_tuple) (struct pcmcia_device *p_dev, | ||
210 | tuple_t *tuple, | ||
211 | void *priv_data); | ||
212 | }; | ||
213 | |||
214 | /** | ||
215 | * pcmcia_do_loop_tuple() - internal helper for pcmcia_loop_config() | ||
216 | * | ||
217 | * pcmcia_do_loop_tuple() is the internal callback for the call from | ||
218 | * pcmcia_loop_tuple() to pccard_loop_tuple(). Data is transferred | ||
219 | * by a struct pcmcia_cfg_mem. | ||
220 | */ | ||
221 | static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv) | ||
222 | { | ||
223 | struct pcmcia_loop_mem *loop = priv; | ||
224 | |||
225 | return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data); | ||
226 | }; | ||
227 | |||
228 | /** | ||
229 | * pcmcia_loop_tuple() - loop over tuples in the CIS | ||
230 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
231 | * @code: which CIS code shall we look for? | ||
232 | * @priv_data: private data to be passed to the loop_tuple function. | ||
233 | * @loop_tuple: function to call for each CIS entry of type @function. IT | ||
234 | * gets passed the raw tuple and @priv_data. | ||
235 | * | ||
236 | * pcmcia_loop_tuple() loops over all CIS entries of type @function, and | ||
237 | * calls the @loop_tuple function for each entry. If the call to @loop_tuple | ||
238 | * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. | ||
239 | */ | ||
240 | int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code, | ||
241 | int (*loop_tuple) (struct pcmcia_device *p_dev, | ||
242 | tuple_t *tuple, | ||
243 | void *priv_data), | ||
244 | void *priv_data) | ||
245 | { | ||
246 | struct pcmcia_loop_mem loop = { | ||
247 | .p_dev = p_dev, | ||
248 | .loop_tuple = loop_tuple, | ||
249 | .priv_data = priv_data}; | ||
250 | |||
251 | return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL, | ||
252 | &loop, pcmcia_do_loop_tuple); | ||
253 | } | ||
254 | EXPORT_SYMBOL(pcmcia_loop_tuple); | ||
255 | |||
256 | |||
257 | struct pcmcia_loop_get { | ||
258 | size_t len; | ||
259 | cisdata_t **buf; | ||
260 | }; | ||
261 | |||
262 | /** | ||
263 | * pcmcia_do_get_tuple() - internal helper for pcmcia_get_tuple() | ||
264 | * | ||
265 | * pcmcia_do_get_tuple() is the internal callback for the call from | ||
266 | * pcmcia_get_tuple() to pcmcia_loop_tuple(). As we're only interested in | ||
267 | * the first tuple, return 0 unconditionally. Create a memory buffer large | ||
268 | * enough to hold the content of the tuple, and fill it with the tuple data. | ||
269 | * The caller is responsible to free the buffer. | ||
270 | */ | ||
271 | static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, | ||
272 | void *priv) | ||
273 | { | ||
274 | struct pcmcia_loop_get *get = priv; | ||
275 | |||
276 | *get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL); | ||
277 | if (*get->buf) { | ||
278 | get->len = tuple->TupleDataLen; | ||
279 | memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen); | ||
280 | } else | ||
281 | dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n"); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /** | ||
286 | * pcmcia_get_tuple() - get first tuple from CIS | ||
287 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
288 | * @code: which CIS code shall we look for? | ||
289 | * @buf: pointer to store the buffer to. | ||
290 | * | ||
291 | * pcmcia_get_tuple() gets the content of the first CIS entry of type @code. | ||
292 | * It returns the buffer length (or zero). The caller is responsible to free | ||
293 | * the buffer passed in @buf. | ||
294 | */ | ||
295 | size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code, | ||
296 | unsigned char **buf) | ||
297 | { | ||
298 | struct pcmcia_loop_get get = { | ||
299 | .len = 0, | ||
300 | .buf = buf, | ||
301 | }; | ||
302 | |||
303 | *get.buf = NULL; | ||
304 | pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get); | ||
305 | |||
306 | return get.len; | ||
307 | } | ||
308 | EXPORT_SYMBOL(pcmcia_get_tuple); | ||
309 | |||
310 | |||
311 | /** | ||
312 | * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis() | ||
313 | * | ||
314 | * pcmcia_do_get_mac() is the internal callback for the call from | ||
315 | * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the | ||
316 | * tuple contains a proper LAN_NODE_ID of length 6, and copy the data | ||
317 | * to struct net_device->dev_addr[i]. | ||
318 | */ | ||
319 | static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple, | ||
320 | void *priv) | ||
321 | { | ||
322 | struct net_device *dev = priv; | ||
323 | int i; | ||
324 | |||
325 | if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) | ||
326 | return -EINVAL; | ||
327 | if (tuple->TupleDataLen < ETH_ALEN + 2) { | ||
328 | dev_warn(&p_dev->dev, "Invalid CIS tuple length for " | ||
329 | "LAN_NODE_ID\n"); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
333 | if (tuple->TupleData[1] != ETH_ALEN) { | ||
334 | dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n"); | ||
335 | return -EINVAL; | ||
336 | } | ||
337 | for (i = 0; i < 6; i++) | ||
338 | dev->dev_addr[i] = tuple->TupleData[i+2]; | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE | ||
344 | * @p_dev: the struct pcmcia_device for which we want the address. | ||
345 | * @dev: a properly prepared struct net_device to store the info to. | ||
346 | * | ||
347 | * pcmcia_get_mac_from_cis() reads out the hardware MAC address from | ||
348 | * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which | ||
349 | * must be set up properly by the driver (see examples!). | ||
350 | */ | ||
351 | int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev) | ||
352 | { | ||
353 | return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev); | ||
354 | } | ||
355 | EXPORT_SYMBOL(pcmcia_get_mac_from_cis); | ||
356 | |||
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 7631faa0cadd..ef0c5f133691 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c | |||
@@ -301,7 +301,9 @@ static int pccard_get_status(struct pcmcia_socket *s, | |||
301 | (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { | 301 | (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { |
302 | u_char reg; | 302 | u_char reg; |
303 | if (c->CardValues & PRESENT_PIN_REPLACE) { | 303 | if (c->CardValues & PRESENT_PIN_REPLACE) { |
304 | mutex_lock(&s->ops_mutex); | ||
304 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); | 305 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); |
306 | mutex_unlock(&s->ops_mutex); | ||
305 | status->CardState |= | 307 | status->CardState |= |
306 | (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; | 308 | (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; |
307 | status->CardState |= | 309 | status->CardState |= |
@@ -315,7 +317,9 @@ static int pccard_get_status(struct pcmcia_socket *s, | |||
315 | status->CardState |= CS_EVENT_READY_CHANGE; | 317 | status->CardState |= CS_EVENT_READY_CHANGE; |
316 | } | 318 | } |
317 | if (c->CardValues & PRESENT_EXT_STATUS) { | 319 | if (c->CardValues & PRESENT_EXT_STATUS) { |
320 | mutex_lock(&s->ops_mutex); | ||
318 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); | 321 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); |
322 | mutex_unlock(&s->ops_mutex); | ||
319 | status->CardState |= | 323 | status->CardState |= |
320 | (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; | 324 | (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; |
321 | } | 325 | } |
@@ -351,7 +355,7 @@ static int pccard_get_configuration_info(struct pcmcia_socket *s, | |||
351 | if (s->state & SOCKET_CARDBUS_CONFIG) { | 355 | if (s->state & SOCKET_CARDBUS_CONFIG) { |
352 | config->Attributes = CONF_VALID_CLIENT; | 356 | config->Attributes = CONF_VALID_CLIENT; |
353 | config->IntType = INT_CARDBUS; | 357 | config->IntType = INT_CARDBUS; |
354 | config->AssignedIRQ = s->irq.AssignedIRQ; | 358 | config->AssignedIRQ = s->pcmcia_irq; |
355 | if (config->AssignedIRQ) | 359 | if (config->AssignedIRQ) |
356 | config->Attributes |= CONF_ENABLE_IRQ; | 360 | config->Attributes |= CONF_ENABLE_IRQ; |
357 | if (s->io[0].res) { | 361 | if (s->io[0].res) { |
@@ -391,7 +395,7 @@ static int pccard_get_configuration_info(struct pcmcia_socket *s, | |||
391 | config->ExtStatus = c->ExtStatus; | 395 | config->ExtStatus = c->ExtStatus; |
392 | config->Present = config->CardValues = c->CardValues; | 396 | config->Present = config->CardValues = c->CardValues; |
393 | config->IRQAttributes = c->irq.Attributes; | 397 | config->IRQAttributes = c->irq.Attributes; |
394 | config->AssignedIRQ = s->irq.AssignedIRQ; | 398 | config->AssignedIRQ = s->pcmcia_irq; |
395 | config->BasePort1 = c->io.BasePort1; | 399 | config->BasePort1 = c->io.BasePort1; |
396 | config->NumPorts1 = c->io.NumPorts1; | 400 | config->NumPorts1 = c->io.NumPorts1; |
397 | config->Attributes1 = c->io.Attributes1; | 401 | config->Attributes1 = c->io.Attributes1; |
@@ -571,7 +575,6 @@ static struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s) | |||
571 | 575 | ||
572 | static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first) | 576 | static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first) |
573 | { | 577 | { |
574 | dev_node_t *node; | ||
575 | struct pcmcia_device *p_dev; | 578 | struct pcmcia_device *p_dev; |
576 | struct pcmcia_driver *p_drv; | 579 | struct pcmcia_driver *p_drv; |
577 | int ret = 0; | 580 | int ret = 0; |
@@ -633,21 +636,13 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int | |||
633 | goto err_put; | 636 | goto err_put; |
634 | } | 637 | } |
635 | 638 | ||
636 | if (first) | 639 | if (!first) { |
637 | node = p_dev->dev_node; | ||
638 | else | ||
639 | for (node = p_dev->dev_node; node; node = node->next) | ||
640 | if (node == bind_info->next) | ||
641 | break; | ||
642 | if (!node) { | ||
643 | ret = -ENODEV; | 640 | ret = -ENODEV; |
644 | goto err_put; | 641 | goto err_put; |
645 | } | 642 | } |
646 | 643 | ||
647 | strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN); | 644 | strlcpy(bind_info->name, dev_name(&p_dev->dev), DEV_NAME_LEN); |
648 | bind_info->major = node->major; | 645 | bind_info->next = NULL; |
649 | bind_info->minor = node->minor; | ||
650 | bind_info->next = node->next; | ||
651 | 646 | ||
652 | err_put: | 647 | err_put: |
653 | pcmcia_put_dev(p_dev); | 648 | pcmcia_put_dev(p_dev); |
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 7c3d03bb4f30..29f91fac1dff 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | 25 | ||
26 | #include <asm/irq.h> | ||
27 | |||
26 | #include <pcmcia/cs_types.h> | 28 | #include <pcmcia/cs_types.h> |
27 | #include <pcmcia/ss.h> | 29 | #include <pcmcia/ss.h> |
28 | #include <pcmcia/cs.h> | 30 | #include <pcmcia/cs.h> |
@@ -38,29 +40,6 @@ static int io_speed; | |||
38 | module_param(io_speed, int, 0444); | 40 | module_param(io_speed, int, 0444); |
39 | 41 | ||
40 | 42 | ||
41 | #ifdef CONFIG_PCMCIA_PROBE | ||
42 | #include <asm/irq.h> | ||
43 | /* mask of IRQs already reserved by other cards, we should avoid using them */ | ||
44 | static u8 pcmcia_used_irq[NR_IRQS]; | ||
45 | #endif | ||
46 | |||
47 | static int pcmcia_adjust_io_region(struct resource *res, unsigned long start, | ||
48 | unsigned long end, struct pcmcia_socket *s) | ||
49 | { | ||
50 | if (s->resource_ops->adjust_io_region) | ||
51 | return s->resource_ops->adjust_io_region(res, start, end, s); | ||
52 | return -ENOMEM; | ||
53 | } | ||
54 | |||
55 | static struct resource *pcmcia_find_io_region(unsigned long base, int num, | ||
56 | unsigned long align, | ||
57 | struct pcmcia_socket *s) | ||
58 | { | ||
59 | if (s->resource_ops->find_io) | ||
60 | return s->resource_ops->find_io(base, num, align, s); | ||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | int pcmcia_validate_mem(struct pcmcia_socket *s) | 43 | int pcmcia_validate_mem(struct pcmcia_socket *s) |
65 | { | 44 | { |
66 | if (s->resource_ops->validate_mem) | 45 | if (s->resource_ops->validate_mem) |
@@ -86,8 +65,7 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, | |||
86 | static int alloc_io_space(struct pcmcia_socket *s, u_int attr, | 65 | static int alloc_io_space(struct pcmcia_socket *s, u_int attr, |
87 | unsigned int *base, unsigned int num, u_int lines) | 66 | unsigned int *base, unsigned int num, u_int lines) |
88 | { | 67 | { |
89 | int i; | 68 | unsigned int align; |
90 | unsigned int try, align; | ||
91 | 69 | ||
92 | align = (*base) ? (lines ? 1<<lines : 0) : 1; | 70 | align = (*base) ? (lines ? 1<<lines : 0) : 1; |
93 | if (align && (align < num)) { | 71 | if (align && (align < num)) { |
@@ -104,50 +82,8 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, | |||
104 | *base, align); | 82 | *base, align); |
105 | align = 0; | 83 | align = 0; |
106 | } | 84 | } |
107 | if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { | 85 | |
108 | *base = s->io_offset | (*base & 0x0fff); | 86 | return s->resource_ops->find_io(s, attr, base, num, align); |
109 | return 0; | ||
110 | } | ||
111 | /* Check for an already-allocated window that must conflict with | ||
112 | * what was asked for. It is a hack because it does not catch all | ||
113 | * potential conflicts, just the most obvious ones. | ||
114 | */ | ||
115 | for (i = 0; i < MAX_IO_WIN; i++) | ||
116 | if ((s->io[i].res) && *base && | ||
117 | ((s->io[i].res->start & (align-1)) == *base)) | ||
118 | return 1; | ||
119 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
120 | if (!s->io[i].res) { | ||
121 | s->io[i].res = pcmcia_find_io_region(*base, num, align, s); | ||
122 | if (s->io[i].res) { | ||
123 | *base = s->io[i].res->start; | ||
124 | s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); | ||
125 | s->io[i].InUse = num; | ||
126 | break; | ||
127 | } else | ||
128 | return 1; | ||
129 | } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS)) | ||
130 | continue; | ||
131 | /* Try to extend top of window */ | ||
132 | try = s->io[i].res->end + 1; | ||
133 | if ((*base == 0) || (*base == try)) | ||
134 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, | ||
135 | s->io[i].res->end + num, s) == 0) { | ||
136 | *base = try; | ||
137 | s->io[i].InUse += num; | ||
138 | break; | ||
139 | } | ||
140 | /* Try to extend bottom of window */ | ||
141 | try = s->io[i].res->start - num; | ||
142 | if ((*base == 0) || (*base == try)) | ||
143 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, | ||
144 | s->io[i].res->end, s) == 0) { | ||
145 | *base = try; | ||
146 | s->io[i].InUse += num; | ||
147 | break; | ||
148 | } | ||
149 | } | ||
150 | return (i == MAX_IO_WIN); | ||
151 | } /* alloc_io_space */ | 87 | } /* alloc_io_space */ |
152 | 88 | ||
153 | 89 | ||
@@ -187,6 +123,7 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
187 | config_t *c; | 123 | config_t *c; |
188 | int addr; | 124 | int addr; |
189 | u_char val; | 125 | u_char val; |
126 | int ret = 0; | ||
190 | 127 | ||
191 | if (!p_dev || !p_dev->function_config) | 128 | if (!p_dev || !p_dev->function_config) |
192 | return -EINVAL; | 129 | return -EINVAL; |
@@ -203,11 +140,10 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
203 | } | 140 | } |
204 | 141 | ||
205 | addr = (c->ConfigBase + reg->Offset) >> 1; | 142 | addr = (c->ConfigBase + reg->Offset) >> 1; |
206 | mutex_unlock(&s->ops_mutex); | ||
207 | 143 | ||
208 | switch (reg->Action) { | 144 | switch (reg->Action) { |
209 | case CS_READ: | 145 | case CS_READ: |
210 | pcmcia_read_cis_mem(s, 1, addr, 1, &val); | 146 | ret = pcmcia_read_cis_mem(s, 1, addr, 1, &val); |
211 | reg->Value = val; | 147 | reg->Value = val; |
212 | break; | 148 | break; |
213 | case CS_WRITE: | 149 | case CS_WRITE: |
@@ -216,10 +152,11 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
216 | break; | 152 | break; |
217 | default: | 153 | default: |
218 | dev_dbg(&s->dev, "Invalid conf register request\n"); | 154 | dev_dbg(&s->dev, "Invalid conf register request\n"); |
219 | return -EINVAL; | 155 | ret = -EINVAL; |
220 | break; | 156 | break; |
221 | } | 157 | } |
222 | return 0; | 158 | mutex_unlock(&s->ops_mutex); |
159 | return ret; | ||
223 | } /* pcmcia_access_configuration_register */ | 160 | } /* pcmcia_access_configuration_register */ |
224 | EXPORT_SYMBOL(pcmcia_access_configuration_register); | 161 | EXPORT_SYMBOL(pcmcia_access_configuration_register); |
225 | 162 | ||
@@ -275,19 +212,9 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
275 | goto unlock; | 212 | goto unlock; |
276 | } | 213 | } |
277 | 214 | ||
278 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { | 215 | if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { |
279 | if (mod->Attributes & CONF_ENABLE_IRQ) { | 216 | dev_dbg(&s->dev, |
280 | c->Attributes |= CONF_ENABLE_IRQ; | 217 | "changing Vcc or IRQ is not allowed at this time\n"); |
281 | s->socket.io_irq = s->irq.AssignedIRQ; | ||
282 | } else { | ||
283 | c->Attributes &= ~CONF_ENABLE_IRQ; | ||
284 | s->socket.io_irq = 0; | ||
285 | } | ||
286 | s->ops->set_socket(s, &s->socket); | ||
287 | } | ||
288 | |||
289 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) { | ||
290 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); | ||
291 | ret = -EINVAL; | 218 | ret = -EINVAL; |
292 | goto unlock; | 219 | goto unlock; |
293 | } | 220 | } |
@@ -422,52 +349,6 @@ out: | |||
422 | } /* pcmcia_release_io */ | 349 | } /* pcmcia_release_io */ |
423 | 350 | ||
424 | 351 | ||
425 | static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | ||
426 | { | ||
427 | struct pcmcia_socket *s = p_dev->socket; | ||
428 | config_t *c; | ||
429 | int ret = -EINVAL; | ||
430 | |||
431 | mutex_lock(&s->ops_mutex); | ||
432 | |||
433 | c = p_dev->function_config; | ||
434 | |||
435 | if (!p_dev->_irq) | ||
436 | goto out; | ||
437 | |||
438 | p_dev->_irq = 0; | ||
439 | |||
440 | if (c->state & CONFIG_LOCKED) | ||
441 | goto out; | ||
442 | |||
443 | if (c->irq.Attributes != req->Attributes) { | ||
444 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); | ||
445 | goto out; | ||
446 | } | ||
447 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { | ||
448 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); | ||
449 | goto out; | ||
450 | } | ||
451 | if (--s->irq.Config == 0) { | ||
452 | c->state &= ~CONFIG_IRQ_REQ; | ||
453 | s->irq.AssignedIRQ = 0; | ||
454 | } | ||
455 | |||
456 | if (req->Handler) | ||
457 | free_irq(req->AssignedIRQ, p_dev->priv); | ||
458 | |||
459 | #ifdef CONFIG_PCMCIA_PROBE | ||
460 | pcmcia_used_irq[req->AssignedIRQ]--; | ||
461 | #endif | ||
462 | ret = 0; | ||
463 | |||
464 | out: | ||
465 | mutex_unlock(&s->ops_mutex); | ||
466 | |||
467 | return ret; | ||
468 | } /* pcmcia_release_irq */ | ||
469 | |||
470 | |||
471 | int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) | 352 | int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) |
472 | { | 353 | { |
473 | struct pcmcia_socket *s = p_dev->socket; | 354 | struct pcmcia_socket *s = p_dev->socket; |
@@ -551,12 +432,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
551 | if (req->Attributes & CONF_ENABLE_SPKR) | 432 | if (req->Attributes & CONF_ENABLE_SPKR) |
552 | s->socket.flags |= SS_SPKR_ENA; | 433 | s->socket.flags |= SS_SPKR_ENA; |
553 | if (req->Attributes & CONF_ENABLE_IRQ) | 434 | if (req->Attributes & CONF_ENABLE_IRQ) |
554 | s->socket.io_irq = s->irq.AssignedIRQ; | 435 | s->socket.io_irq = s->pcmcia_irq; |
555 | else | 436 | else |
556 | s->socket.io_irq = 0; | 437 | s->socket.io_irq = 0; |
557 | s->ops->set_socket(s, &s->socket); | 438 | s->ops->set_socket(s, &s->socket); |
558 | s->lock_count++; | 439 | s->lock_count++; |
559 | mutex_unlock(&s->ops_mutex); | ||
560 | 440 | ||
561 | /* Set up CIS configuration registers */ | 441 | /* Set up CIS configuration registers */ |
562 | base = c->ConfigBase = req->ConfigBase; | 442 | base = c->ConfigBase = req->ConfigBase; |
@@ -574,9 +454,9 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
574 | if (req->Present & PRESENT_IOBASE_0) | 454 | if (req->Present & PRESENT_IOBASE_0) |
575 | c->Option |= COR_ADDR_DECODE; | 455 | c->Option |= COR_ADDR_DECODE; |
576 | } | 456 | } |
577 | if (c->state & CONFIG_IRQ_REQ) | 457 | if ((req->Attributes & CONF_ENABLE_IRQ) && |
578 | if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) | 458 | !(req->Attributes & CONF_ENABLE_PULSE_IRQ)) |
579 | c->Option |= COR_LEVEL_REQ; | 459 | c->Option |= COR_LEVEL_REQ; |
580 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); | 460 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); |
581 | mdelay(40); | 461 | mdelay(40); |
582 | } | 462 | } |
@@ -605,7 +485,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
605 | 485 | ||
606 | /* Configure I/O windows */ | 486 | /* Configure I/O windows */ |
607 | if (c->state & CONFIG_IO_REQ) { | 487 | if (c->state & CONFIG_IO_REQ) { |
608 | mutex_lock(&s->ops_mutex); | ||
609 | iomap.speed = io_speed; | 488 | iomap.speed = io_speed; |
610 | for (i = 0; i < MAX_IO_WIN; i++) | 489 | for (i = 0; i < MAX_IO_WIN; i++) |
611 | if (s->io[i].res) { | 490 | if (s->io[i].res) { |
@@ -624,11 +503,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
624 | s->ops->set_io_map(s, &iomap); | 503 | s->ops->set_io_map(s, &iomap); |
625 | s->io[i].Config++; | 504 | s->io[i].Config++; |
626 | } | 505 | } |
627 | mutex_unlock(&s->ops_mutex); | ||
628 | } | 506 | } |
629 | 507 | ||
630 | c->state |= CONFIG_LOCKED; | 508 | c->state |= CONFIG_LOCKED; |
631 | p_dev->_locked = 1; | 509 | p_dev->_locked = 1; |
510 | mutex_unlock(&s->ops_mutex); | ||
632 | return 0; | 511 | return 0; |
633 | } /* pcmcia_request_configuration */ | 512 | } /* pcmcia_request_configuration */ |
634 | EXPORT_SYMBOL(pcmcia_request_configuration); | 513 | EXPORT_SYMBOL(pcmcia_request_configuration); |
@@ -706,137 +585,176 @@ out: | |||
706 | EXPORT_SYMBOL(pcmcia_request_io); | 585 | EXPORT_SYMBOL(pcmcia_request_io); |
707 | 586 | ||
708 | 587 | ||
709 | /** pcmcia_request_irq | 588 | /** |
589 | * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device | ||
710 | * | 590 | * |
711 | * Request_irq() reserves an irq for this client. | 591 | * pcmcia_request_irq() is a wrapper around request_irq which will allow |
592 | * the PCMCIA core to clean up the registration in pcmcia_disable_device(). | ||
593 | * Drivers are free to use request_irq() directly, but then they need to | ||
594 | * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ | ||
595 | * handlers are allowed. | ||
596 | */ | ||
597 | int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev, | ||
598 | irq_handler_t handler) | ||
599 | { | ||
600 | int ret; | ||
601 | |||
602 | if (!p_dev->irq) | ||
603 | return -EINVAL; | ||
604 | |||
605 | ret = request_irq(p_dev->irq, handler, IRQF_SHARED, | ||
606 | p_dev->devname, p_dev->priv); | ||
607 | if (!ret) | ||
608 | p_dev->_irq = 1; | ||
609 | |||
610 | return ret; | ||
611 | } | ||
612 | EXPORT_SYMBOL(pcmcia_request_irq); | ||
613 | |||
614 | |||
615 | /** | ||
616 | * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first | ||
712 | * | 617 | * |
713 | * Also, since Linux only reserves irq's when they are actually | 618 | * pcmcia_request_exclusive_irq() is a wrapper around request_irq which |
714 | * hooked, we don't guarantee that an irq will still be available | 619 | * attempts first to request an exclusive IRQ. If it fails, it also accepts |
715 | * when the configuration is locked. Now that I think about it, | 620 | * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for |
716 | * there might be a way to fix this using a dummy handler. | 621 | * IRQ sharing and either use request_irq directly (then they need to call |
622 | * free_irq themselves, too), or the pcmcia_request_irq() function. | ||
717 | */ | 623 | */ |
624 | int __must_check | ||
625 | __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, | ||
626 | irq_handler_t handler) | ||
627 | { | ||
628 | int ret; | ||
629 | |||
630 | if (!p_dev->irq) | ||
631 | return -EINVAL; | ||
632 | |||
633 | ret = request_irq(p_dev->irq, handler, 0, p_dev->devname, p_dev->priv); | ||
634 | if (ret) { | ||
635 | ret = pcmcia_request_irq(p_dev, handler); | ||
636 | dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: " | ||
637 | "request for exclusive IRQ could not be fulfilled.\n"); | ||
638 | dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver " | ||
639 | "needs updating to supported shared IRQ lines.\n"); | ||
640 | } | ||
641 | if (ret) | ||
642 | dev_printk(KERN_INFO, &p_dev->dev, "request_irq() failed\n"); | ||
643 | else | ||
644 | p_dev->_irq = 1; | ||
645 | |||
646 | return ret; | ||
647 | } /* pcmcia_request_exclusive_irq */ | ||
648 | EXPORT_SYMBOL(__pcmcia_request_exclusive_irq); | ||
649 | |||
718 | 650 | ||
719 | #ifdef CONFIG_PCMCIA_PROBE | 651 | #ifdef CONFIG_PCMCIA_PROBE |
652 | |||
653 | /* mask of IRQs already reserved by other cards, we should avoid using them */ | ||
654 | static u8 pcmcia_used_irq[NR_IRQS]; | ||
655 | |||
720 | static irqreturn_t test_action(int cpl, void *dev_id) | 656 | static irqreturn_t test_action(int cpl, void *dev_id) |
721 | { | 657 | { |
722 | return IRQ_NONE; | 658 | return IRQ_NONE; |
723 | } | 659 | } |
724 | #endif | ||
725 | 660 | ||
726 | int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | 661 | /** |
662 | * pcmcia_setup_isa_irq() - determine whether an ISA IRQ can be used | ||
663 | * @p_dev - the associated PCMCIA device | ||
664 | * | ||
665 | * locking note: must be called with ops_mutex locked. | ||
666 | */ | ||
667 | static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type) | ||
727 | { | 668 | { |
728 | struct pcmcia_socket *s = p_dev->socket; | 669 | struct pcmcia_socket *s = p_dev->socket; |
729 | config_t *c; | 670 | unsigned int try, irq; |
730 | int ret = -EINVAL, irq = 0; | 671 | u32 mask = s->irq_mask; |
731 | int type; | 672 | int ret = -ENODEV; |
732 | 673 | ||
733 | mutex_lock(&s->ops_mutex); | 674 | for (try = 0; try < 64; try++) { |
675 | irq = try % 32; | ||
734 | 676 | ||
735 | if (!(s->state & SOCKET_PRESENT)) { | 677 | /* marked as available by driver, not blocked by userspace? */ |
736 | dev_dbg(&s->dev, "No card present\n"); | 678 | if (!((mask >> irq) & 1)) |
737 | goto out; | 679 | continue; |
738 | } | 680 | |
739 | c = p_dev->function_config; | 681 | /* avoid an IRQ which is already used by another PCMCIA card */ |
740 | if (c->state & CONFIG_LOCKED) { | 682 | if ((try < 32) && pcmcia_used_irq[irq]) |
741 | dev_dbg(&s->dev, "Configuration is locked\n"); | 683 | continue; |
742 | goto out; | 684 | |
743 | } | 685 | /* register the correct driver, if possible, to check whether |
744 | if (c->state & CONFIG_IRQ_REQ) { | 686 | * registering a dummy handle works, i.e. if the IRQ isn't |
745 | dev_dbg(&s->dev, "IRQ already configured\n"); | 687 | * marked as used by the kernel resource management core */ |
746 | goto out; | 688 | ret = request_irq(irq, test_action, type, p_dev->devname, |
689 | p_dev); | ||
690 | if (!ret) { | ||
691 | free_irq(irq, p_dev); | ||
692 | p_dev->irq = s->pcmcia_irq = irq; | ||
693 | pcmcia_used_irq[irq]++; | ||
694 | break; | ||
695 | } | ||
747 | } | 696 | } |
748 | 697 | ||
749 | /* Decide what type of interrupt we are registering */ | 698 | return ret; |
750 | type = 0; | 699 | } |
751 | if (s->functions > 1) /* All of this ought to be handled higher up */ | ||
752 | type = IRQF_SHARED; | ||
753 | else if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) | ||
754 | type = IRQF_SHARED; | ||
755 | else | ||
756 | printk(KERN_WARNING "pcmcia: Driver needs updating to support IRQ sharing.\n"); | ||
757 | 700 | ||
758 | /* If the interrupt is already assigned, it must be the same */ | 701 | void pcmcia_cleanup_irq(struct pcmcia_socket *s) |
759 | if (s->irq.AssignedIRQ != 0) | 702 | { |
760 | irq = s->irq.AssignedIRQ; | 703 | pcmcia_used_irq[s->pcmcia_irq]--; |
704 | s->pcmcia_irq = 0; | ||
705 | } | ||
761 | 706 | ||
762 | #ifdef CONFIG_PCMCIA_PROBE | 707 | #else /* CONFIG_PCMCIA_PROBE */ |
763 | if (!irq) { | ||
764 | int try; | ||
765 | u32 mask = s->irq_mask; | ||
766 | void *data = p_dev; /* something unique to this device */ | ||
767 | 708 | ||
768 | for (try = 0; try < 64; try++) { | 709 | static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type) |
769 | irq = try % 32; | 710 | { |
711 | return -EINVAL; | ||
712 | } | ||
770 | 713 | ||
771 | /* marked as available by driver, and not blocked by userspace? */ | 714 | void pcmcia_cleanup_irq(struct pcmcia_socket *s) |
772 | if (!((mask >> irq) & 1)) | 715 | { |
773 | continue; | 716 | s->pcmcia_irq = 0; |
717 | return; | ||
718 | } | ||
774 | 719 | ||
775 | /* avoid an IRQ which is already used by a PCMCIA card */ | 720 | #endif /* CONFIG_PCMCIA_PROBE */ |
776 | if ((try < 32) && pcmcia_used_irq[irq]) | ||
777 | continue; | ||
778 | 721 | ||
779 | /* register the correct driver, if possible, of check whether | ||
780 | * registering a dummy handle works, i.e. if the IRQ isn't | ||
781 | * marked as used by the kernel resource management core */ | ||
782 | ret = request_irq(irq, | ||
783 | (req->Handler) ? req->Handler : test_action, | ||
784 | type, | ||
785 | p_dev->devname, | ||
786 | (req->Handler) ? p_dev->priv : data); | ||
787 | if (!ret) { | ||
788 | if (!req->Handler) | ||
789 | free_irq(irq, data); | ||
790 | break; | ||
791 | } | ||
792 | } | ||
793 | } | ||
794 | #endif | ||
795 | /* only assign PCI irq if no IRQ already assigned */ | ||
796 | if (ret && !s->irq.AssignedIRQ) { | ||
797 | if (!s->pci_irq) { | ||
798 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); | ||
799 | goto out; | ||
800 | } | ||
801 | type = IRQF_SHARED; | ||
802 | irq = s->pci_irq; | ||
803 | } | ||
804 | 722 | ||
805 | if (ret && req->Handler) { | 723 | /** |
806 | ret = request_irq(irq, req->Handler, type, | 724 | * pcmcia_setup_irq() - determine IRQ to be used for device |
807 | p_dev->devname, p_dev->priv); | 725 | * @p_dev - the associated PCMCIA device |
808 | if (ret) { | 726 | * |
809 | dev_printk(KERN_INFO, &s->dev, | 727 | * locking note: must be called with ops_mutex locked. |
810 | "request_irq() failed\n"); | 728 | */ |
811 | goto out; | 729 | int pcmcia_setup_irq(struct pcmcia_device *p_dev) |
812 | } | 730 | { |
813 | } | 731 | struct pcmcia_socket *s = p_dev->socket; |
814 | 732 | ||
815 | /* Make sure the fact the request type was overridden is passed back */ | 733 | if (p_dev->irq) |
816 | if (type == IRQF_SHARED && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) { | 734 | return 0; |
817 | req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING; | 735 | |
818 | dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: " | 736 | /* already assigned? */ |
819 | "request for exclusive IRQ could not be fulfilled.\n"); | 737 | if (s->pcmcia_irq) { |
820 | dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver " | 738 | p_dev->irq = s->pcmcia_irq; |
821 | "needs updating to supported shared IRQ lines.\n"); | 739 | return 0; |
822 | } | 740 | } |
823 | c->irq.Attributes = req->Attributes; | ||
824 | s->irq.AssignedIRQ = req->AssignedIRQ = irq; | ||
825 | s->irq.Config++; | ||
826 | 741 | ||
827 | c->state |= CONFIG_IRQ_REQ; | 742 | /* prefer an exclusive ISA irq */ |
828 | p_dev->_irq = 1; | 743 | if (!pcmcia_setup_isa_irq(p_dev, 0)) |
744 | return 0; | ||
829 | 745 | ||
830 | #ifdef CONFIG_PCMCIA_PROBE | 746 | /* but accept a shared ISA irq */ |
831 | pcmcia_used_irq[irq]++; | 747 | if (!pcmcia_setup_isa_irq(p_dev, IRQF_SHARED)) |
832 | #endif | 748 | return 0; |
833 | 749 | ||
834 | ret = 0; | 750 | /* but use the PCI irq otherwise */ |
835 | out: | 751 | if (s->pci_irq) { |
836 | mutex_unlock(&s->ops_mutex); | 752 | p_dev->irq = s->pcmcia_irq = s->pci_irq; |
837 | return ret; | 753 | return 0; |
838 | } /* pcmcia_request_irq */ | 754 | } |
839 | EXPORT_SYMBOL(pcmcia_request_irq); | 755 | |
756 | return -EINVAL; | ||
757 | } | ||
840 | 758 | ||
841 | 759 | ||
842 | /** pcmcia_request_window | 760 | /** pcmcia_request_window |
@@ -939,237 +857,9 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) | |||
939 | { | 857 | { |
940 | pcmcia_release_configuration(p_dev); | 858 | pcmcia_release_configuration(p_dev); |
941 | pcmcia_release_io(p_dev, &p_dev->io); | 859 | pcmcia_release_io(p_dev, &p_dev->io); |
942 | pcmcia_release_irq(p_dev, &p_dev->irq); | 860 | if (p_dev->_irq) |
861 | free_irq(p_dev->irq, p_dev->priv); | ||
943 | if (p_dev->win) | 862 | if (p_dev->win) |
944 | pcmcia_release_window(p_dev, p_dev->win); | 863 | pcmcia_release_window(p_dev, p_dev->win); |
945 | } | 864 | } |
946 | EXPORT_SYMBOL(pcmcia_disable_device); | 865 | EXPORT_SYMBOL(pcmcia_disable_device); |
947 | |||
948 | |||
949 | struct pcmcia_cfg_mem { | ||
950 | struct pcmcia_device *p_dev; | ||
951 | void *priv_data; | ||
952 | int (*conf_check) (struct pcmcia_device *p_dev, | ||
953 | cistpl_cftable_entry_t *cfg, | ||
954 | cistpl_cftable_entry_t *dflt, | ||
955 | unsigned int vcc, | ||
956 | void *priv_data); | ||
957 | cisparse_t parse; | ||
958 | cistpl_cftable_entry_t dflt; | ||
959 | }; | ||
960 | |||
961 | /** | ||
962 | * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config() | ||
963 | * | ||
964 | * pcmcia_do_loop_config() is the internal callback for the call from | ||
965 | * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred | ||
966 | * by a struct pcmcia_cfg_mem. | ||
967 | */ | ||
968 | static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) | ||
969 | { | ||
970 | cistpl_cftable_entry_t *cfg = &parse->cftable_entry; | ||
971 | struct pcmcia_cfg_mem *cfg_mem = priv; | ||
972 | |||
973 | /* default values */ | ||
974 | cfg_mem->p_dev->conf.ConfigIndex = cfg->index; | ||
975 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
976 | cfg_mem->dflt = *cfg; | ||
977 | |||
978 | return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, | ||
979 | cfg_mem->p_dev->socket->socket.Vcc, | ||
980 | cfg_mem->priv_data); | ||
981 | } | ||
982 | |||
983 | /** | ||
984 | * pcmcia_loop_config() - loop over configuration options | ||
985 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
986 | * @conf_check: function to call for each configuration option. | ||
987 | * It gets passed the struct pcmcia_device, the CIS data | ||
988 | * describing the configuration option, and private data | ||
989 | * being passed to pcmcia_loop_config() | ||
990 | * @priv_data: private data to be passed to the conf_check function. | ||
991 | * | ||
992 | * pcmcia_loop_config() loops over all configuration options, and calls | ||
993 | * the driver-specific conf_check() for each one, checking whether | ||
994 | * it is a valid one. Returns 0 on success or errorcode otherwise. | ||
995 | */ | ||
996 | int pcmcia_loop_config(struct pcmcia_device *p_dev, | ||
997 | int (*conf_check) (struct pcmcia_device *p_dev, | ||
998 | cistpl_cftable_entry_t *cfg, | ||
999 | cistpl_cftable_entry_t *dflt, | ||
1000 | unsigned int vcc, | ||
1001 | void *priv_data), | ||
1002 | void *priv_data) | ||
1003 | { | ||
1004 | struct pcmcia_cfg_mem *cfg_mem; | ||
1005 | int ret; | ||
1006 | |||
1007 | cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL); | ||
1008 | if (cfg_mem == NULL) | ||
1009 | return -ENOMEM; | ||
1010 | |||
1011 | cfg_mem->p_dev = p_dev; | ||
1012 | cfg_mem->conf_check = conf_check; | ||
1013 | cfg_mem->priv_data = priv_data; | ||
1014 | |||
1015 | ret = pccard_loop_tuple(p_dev->socket, p_dev->func, | ||
1016 | CISTPL_CFTABLE_ENTRY, &cfg_mem->parse, | ||
1017 | cfg_mem, pcmcia_do_loop_config); | ||
1018 | |||
1019 | kfree(cfg_mem); | ||
1020 | return ret; | ||
1021 | } | ||
1022 | EXPORT_SYMBOL(pcmcia_loop_config); | ||
1023 | |||
1024 | |||
1025 | struct pcmcia_loop_mem { | ||
1026 | struct pcmcia_device *p_dev; | ||
1027 | void *priv_data; | ||
1028 | int (*loop_tuple) (struct pcmcia_device *p_dev, | ||
1029 | tuple_t *tuple, | ||
1030 | void *priv_data); | ||
1031 | }; | ||
1032 | |||
1033 | /** | ||
1034 | * pcmcia_do_loop_tuple() - internal helper for pcmcia_loop_config() | ||
1035 | * | ||
1036 | * pcmcia_do_loop_tuple() is the internal callback for the call from | ||
1037 | * pcmcia_loop_tuple() to pccard_loop_tuple(). Data is transferred | ||
1038 | * by a struct pcmcia_cfg_mem. | ||
1039 | */ | ||
1040 | static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv) | ||
1041 | { | ||
1042 | struct pcmcia_loop_mem *loop = priv; | ||
1043 | |||
1044 | return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data); | ||
1045 | }; | ||
1046 | |||
1047 | /** | ||
1048 | * pcmcia_loop_tuple() - loop over tuples in the CIS | ||
1049 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
1050 | * @code: which CIS code shall we look for? | ||
1051 | * @priv_data: private data to be passed to the loop_tuple function. | ||
1052 | * @loop_tuple: function to call for each CIS entry of type @function. IT | ||
1053 | * gets passed the raw tuple and @priv_data. | ||
1054 | * | ||
1055 | * pcmcia_loop_tuple() loops over all CIS entries of type @function, and | ||
1056 | * calls the @loop_tuple function for each entry. If the call to @loop_tuple | ||
1057 | * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. | ||
1058 | */ | ||
1059 | int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code, | ||
1060 | int (*loop_tuple) (struct pcmcia_device *p_dev, | ||
1061 | tuple_t *tuple, | ||
1062 | void *priv_data), | ||
1063 | void *priv_data) | ||
1064 | { | ||
1065 | struct pcmcia_loop_mem loop = { | ||
1066 | .p_dev = p_dev, | ||
1067 | .loop_tuple = loop_tuple, | ||
1068 | .priv_data = priv_data}; | ||
1069 | |||
1070 | return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL, | ||
1071 | &loop, pcmcia_do_loop_tuple); | ||
1072 | } | ||
1073 | EXPORT_SYMBOL(pcmcia_loop_tuple); | ||
1074 | |||
1075 | |||
1076 | struct pcmcia_loop_get { | ||
1077 | size_t len; | ||
1078 | cisdata_t **buf; | ||
1079 | }; | ||
1080 | |||
1081 | /** | ||
1082 | * pcmcia_do_get_tuple() - internal helper for pcmcia_get_tuple() | ||
1083 | * | ||
1084 | * pcmcia_do_get_tuple() is the internal callback for the call from | ||
1085 | * pcmcia_get_tuple() to pcmcia_loop_tuple(). As we're only interested in | ||
1086 | * the first tuple, return 0 unconditionally. Create a memory buffer large | ||
1087 | * enough to hold the content of the tuple, and fill it with the tuple data. | ||
1088 | * The caller is responsible to free the buffer. | ||
1089 | */ | ||
1090 | static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, | ||
1091 | void *priv) | ||
1092 | { | ||
1093 | struct pcmcia_loop_get *get = priv; | ||
1094 | |||
1095 | *get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL); | ||
1096 | if (*get->buf) { | ||
1097 | get->len = tuple->TupleDataLen; | ||
1098 | memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen); | ||
1099 | } else | ||
1100 | dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n"); | ||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | /** | ||
1105 | * pcmcia_get_tuple() - get first tuple from CIS | ||
1106 | * @p_dev: the struct pcmcia_device which we need to loop for. | ||
1107 | * @code: which CIS code shall we look for? | ||
1108 | * @buf: pointer to store the buffer to. | ||
1109 | * | ||
1110 | * pcmcia_get_tuple() gets the content of the first CIS entry of type @code. | ||
1111 | * It returns the buffer length (or zero). The caller is responsible to free | ||
1112 | * the buffer passed in @buf. | ||
1113 | */ | ||
1114 | size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code, | ||
1115 | unsigned char **buf) | ||
1116 | { | ||
1117 | struct pcmcia_loop_get get = { | ||
1118 | .len = 0, | ||
1119 | .buf = buf, | ||
1120 | }; | ||
1121 | |||
1122 | *get.buf = NULL; | ||
1123 | pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get); | ||
1124 | |||
1125 | return get.len; | ||
1126 | } | ||
1127 | EXPORT_SYMBOL(pcmcia_get_tuple); | ||
1128 | |||
1129 | |||
1130 | /** | ||
1131 | * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis() | ||
1132 | * | ||
1133 | * pcmcia_do_get_mac() is the internal callback for the call from | ||
1134 | * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the | ||
1135 | * tuple contains a proper LAN_NODE_ID of length 6, and copy the data | ||
1136 | * to struct net_device->dev_addr[i]. | ||
1137 | */ | ||
1138 | static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple, | ||
1139 | void *priv) | ||
1140 | { | ||
1141 | struct net_device *dev = priv; | ||
1142 | int i; | ||
1143 | |||
1144 | if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) | ||
1145 | return -EINVAL; | ||
1146 | if (tuple->TupleDataLen < ETH_ALEN + 2) { | ||
1147 | dev_warn(&p_dev->dev, "Invalid CIS tuple length for " | ||
1148 | "LAN_NODE_ID\n"); | ||
1149 | return -EINVAL; | ||
1150 | } | ||
1151 | |||
1152 | if (tuple->TupleData[1] != ETH_ALEN) { | ||
1153 | dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n"); | ||
1154 | return -EINVAL; | ||
1155 | } | ||
1156 | for (i = 0; i < 6; i++) | ||
1157 | dev->dev_addr[i] = tuple->TupleData[i+2]; | ||
1158 | return 0; | ||
1159 | } | ||
1160 | |||
1161 | /** | ||
1162 | * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE | ||
1163 | * @p_dev: the struct pcmcia_device for which we want the address. | ||
1164 | * @dev: a properly prepared struct net_device to store the info to. | ||
1165 | * | ||
1166 | * pcmcia_get_mac_from_cis() reads out the hardware MAC address from | ||
1167 | * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which | ||
1168 | * must be set up properly by the driver (see examples!). | ||
1169 | */ | ||
1170 | int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev) | ||
1171 | { | ||
1172 | return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev); | ||
1173 | } | ||
1174 | EXPORT_SYMBOL(pcmcia_get_mac_from_cis); | ||
1175 | |||
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c new file mode 100644 index 000000000000..d0bf35021065 --- /dev/null +++ b/drivers/pcmcia/rsrc_iodyn.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * rsrc_iodyn.c -- Resource management routines for MEM-static sockets. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * The initial developer of the original code is David A. Hinds | ||
9 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
11 | * | ||
12 | * (C) 1999 David A. Hinds | ||
13 | */ | ||
14 | |||
15 | #include <linux/slab.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | |||
19 | #include <pcmcia/cs_types.h> | ||
20 | #include <pcmcia/ss.h> | ||
21 | #include <pcmcia/cs.h> | ||
22 | #include <pcmcia/cistpl.h> | ||
23 | #include "cs_internal.h" | ||
24 | |||
25 | |||
26 | struct pcmcia_align_data { | ||
27 | unsigned long mask; | ||
28 | unsigned long offset; | ||
29 | }; | ||
30 | |||
31 | static resource_size_t pcmcia_align(void *align_data, | ||
32 | const struct resource *res, | ||
33 | resource_size_t size, resource_size_t align) | ||
34 | { | ||
35 | struct pcmcia_align_data *data = align_data; | ||
36 | resource_size_t start; | ||
37 | |||
38 | start = (res->start & ~data->mask) + data->offset; | ||
39 | if (start < res->start) | ||
40 | start += data->mask + 1; | ||
41 | |||
42 | #ifdef CONFIG_X86 | ||
43 | if (res->flags & IORESOURCE_IO) { | ||
44 | if (start & 0x300) | ||
45 | start = (start + 0x3ff) & ~0x3ff; | ||
46 | } | ||
47 | #endif | ||
48 | |||
49 | #ifdef CONFIG_M68K | ||
50 | if (res->flags & IORESOURCE_IO) { | ||
51 | if ((res->start + size - 1) >= 1024) | ||
52 | start = res->end; | ||
53 | } | ||
54 | #endif | ||
55 | |||
56 | return start; | ||
57 | } | ||
58 | |||
59 | |||
60 | static struct resource *__iodyn_find_io_region(struct pcmcia_socket *s, | ||
61 | unsigned long base, int num, | ||
62 | unsigned long align) | ||
63 | { | ||
64 | struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, | ||
65 | dev_name(&s->dev)); | ||
66 | struct pcmcia_align_data data; | ||
67 | unsigned long min = base; | ||
68 | int ret; | ||
69 | |||
70 | data.mask = align - 1; | ||
71 | data.offset = base & data.mask; | ||
72 | |||
73 | #ifdef CONFIG_PCI | ||
74 | if (s->cb_dev) { | ||
75 | ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, | ||
76 | min, 0, pcmcia_align, &data); | ||
77 | } else | ||
78 | #endif | ||
79 | ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, | ||
80 | 1, pcmcia_align, &data); | ||
81 | |||
82 | if (ret != 0) { | ||
83 | kfree(res); | ||
84 | res = NULL; | ||
85 | } | ||
86 | return res; | ||
87 | } | ||
88 | |||
89 | static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | ||
90 | unsigned int *base, unsigned int num, | ||
91 | unsigned int align) | ||
92 | { | ||
93 | int i, ret = 0; | ||
94 | |||
95 | /* Check for an already-allocated window that must conflict with | ||
96 | * what was asked for. It is a hack because it does not catch all | ||
97 | * potential conflicts, just the most obvious ones. | ||
98 | */ | ||
99 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
100 | if (!s->io[i].res) | ||
101 | continue; | ||
102 | |||
103 | if (!*base) | ||
104 | continue; | ||
105 | |||
106 | if ((s->io[i].res->start & (align-1)) == *base) | ||
107 | return -EBUSY; | ||
108 | } | ||
109 | |||
110 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
111 | struct resource *res = s->io[i].res; | ||
112 | unsigned int try; | ||
113 | |||
114 | if (res && (res->flags & IORESOURCE_BITS) != | ||
115 | (attr & IORESOURCE_BITS)) | ||
116 | continue; | ||
117 | |||
118 | if (!res) { | ||
119 | if (align == 0) | ||
120 | align = 0x10000; | ||
121 | |||
122 | res = s->io[i].res = __iodyn_find_io_region(s, *base, | ||
123 | num, align); | ||
124 | if (!res) | ||
125 | return -EINVAL; | ||
126 | |||
127 | *base = res->start; | ||
128 | s->io[i].res->flags = | ||
129 | ((res->flags & ~IORESOURCE_BITS) | | ||
130 | (attr & IORESOURCE_BITS)); | ||
131 | s->io[i].InUse = num; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /* Try to extend top of window */ | ||
136 | try = res->end + 1; | ||
137 | if ((*base == 0) || (*base == try)) { | ||
138 | if (adjust_resource(s->io[i].res, res->start, | ||
139 | res->end - res->start + num + 1)) | ||
140 | continue; | ||
141 | *base = try; | ||
142 | s->io[i].InUse += num; | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | /* Try to extend bottom of window */ | ||
147 | try = res->start - num; | ||
148 | if ((*base == 0) || (*base == try)) { | ||
149 | if (adjust_resource(s->io[i].res, | ||
150 | res->start - num, | ||
151 | res->end - res->start + num + 1)) | ||
152 | continue; | ||
153 | *base = try; | ||
154 | s->io[i].InUse += num; | ||
155 | return 0; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
162 | |||
163 | struct pccard_resource_ops pccard_iodyn_ops = { | ||
164 | .validate_mem = NULL, | ||
165 | .find_io = iodyn_find_io, | ||
166 | .find_mem = NULL, | ||
167 | .add_io = NULL, | ||
168 | .add_mem = NULL, | ||
169 | .init = static_init, | ||
170 | .exit = NULL, | ||
171 | }; | ||
172 | EXPORT_SYMBOL(pccard_iodyn_ops); | ||
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index ffa5f3cae57b..142efac3c387 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <pcmcia/cistpl.h> | 22 | #include <pcmcia/cistpl.h> |
23 | #include "cs_internal.h" | 23 | #include "cs_internal.h" |
24 | 24 | ||
25 | static int static_init(struct pcmcia_socket *s) | 25 | int static_init(struct pcmcia_socket *s) |
26 | { | 26 | { |
27 | /* the good thing about SS_CAP_STATIC_MAP sockets is | 27 | /* the good thing about SS_CAP_STATIC_MAP sockets is |
28 | * that they don't need a resource database */ | 28 | * that they don't need a resource database */ |
@@ -32,118 +32,44 @@ static int static_init(struct pcmcia_socket *s) | |||
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | 35 | struct resource *pcmcia_make_resource(unsigned long start, unsigned long end, | |
36 | struct pccard_resource_ops pccard_static_ops = { | 36 | int flags, const char *name) |
37 | .validate_mem = NULL, | ||
38 | .adjust_io_region = NULL, | ||
39 | .find_io = NULL, | ||
40 | .find_mem = NULL, | ||
41 | .add_io = NULL, | ||
42 | .add_mem = NULL, | ||
43 | .init = static_init, | ||
44 | .exit = NULL, | ||
45 | }; | ||
46 | EXPORT_SYMBOL(pccard_static_ops); | ||
47 | |||
48 | |||
49 | #ifdef CONFIG_PCCARD_IODYN | ||
50 | |||
51 | static struct resource * | ||
52 | make_resource(unsigned long b, unsigned long n, int flags, char *name) | ||
53 | { | 37 | { |
54 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); | 38 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); |
55 | 39 | ||
56 | if (res) { | 40 | if (res) { |
57 | res->name = name; | 41 | res->name = name; |
58 | res->start = b; | 42 | res->start = start; |
59 | res->end = b + n - 1; | 43 | res->end = start + end - 1; |
60 | res->flags = flags; | 44 | res->flags = flags; |
61 | } | 45 | } |
62 | return res; | 46 | return res; |
63 | } | 47 | } |
64 | 48 | ||
65 | struct pcmcia_align_data { | 49 | static int static_find_io(struct pcmcia_socket *s, unsigned int attr, |
66 | unsigned long mask; | 50 | unsigned int *base, unsigned int num, |
67 | unsigned long offset; | 51 | unsigned int align) |
68 | }; | ||
69 | |||
70 | static resource_size_t pcmcia_align(void *align_data, | ||
71 | const struct resource *res, | ||
72 | resource_size_t size, resource_size_t align) | ||
73 | { | 52 | { |
74 | struct pcmcia_align_data *data = align_data; | 53 | if (!s->io_offset) |
75 | resource_size_t start; | 54 | return -EINVAL; |
55 | *base = s->io_offset | (*base & 0x0fff); | ||
76 | 56 | ||
77 | start = (res->start & ~data->mask) + data->offset; | 57 | return 0; |
78 | if (start < res->start) | ||
79 | start += data->mask + 1; | ||
80 | |||
81 | #ifdef CONFIG_X86 | ||
82 | if (res->flags & IORESOURCE_IO) { | ||
83 | if (start & 0x300) | ||
84 | start = (start + 0x3ff) & ~0x3ff; | ||
85 | } | ||
86 | #endif | ||
87 | |||
88 | #ifdef CONFIG_M68K | ||
89 | if (res->flags & IORESOURCE_IO) { | ||
90 | if ((res->start + size - 1) >= 1024) | ||
91 | start = res->end; | ||
92 | } | ||
93 | #endif | ||
94 | |||
95 | return start; | ||
96 | } | ||
97 | |||
98 | |||
99 | static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start, | ||
100 | unsigned long r_end, struct pcmcia_socket *s) | ||
101 | { | ||
102 | return adjust_resource(res, r_start, r_end - r_start + 1); | ||
103 | } | 58 | } |
104 | 59 | ||
105 | 60 | ||
106 | static struct resource *iodyn_find_io_region(unsigned long base, int num, | 61 | struct pccard_resource_ops pccard_static_ops = { |
107 | unsigned long align, struct pcmcia_socket *s) | ||
108 | { | ||
109 | struct resource *res = make_resource(0, num, IORESOURCE_IO, | ||
110 | dev_name(&s->dev)); | ||
111 | struct pcmcia_align_data data; | ||
112 | unsigned long min = base; | ||
113 | int ret; | ||
114 | |||
115 | if (align == 0) | ||
116 | align = 0x10000; | ||
117 | |||
118 | data.mask = align - 1; | ||
119 | data.offset = base & data.mask; | ||
120 | |||
121 | #ifdef CONFIG_PCI | ||
122 | if (s->cb_dev) { | ||
123 | ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, | ||
124 | min, 0, pcmcia_align, &data); | ||
125 | } else | ||
126 | #endif | ||
127 | ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, | ||
128 | 1, pcmcia_align, &data); | ||
129 | |||
130 | if (ret != 0) { | ||
131 | kfree(res); | ||
132 | res = NULL; | ||
133 | } | ||
134 | return res; | ||
135 | } | ||
136 | |||
137 | struct pccard_resource_ops pccard_iodyn_ops = { | ||
138 | .validate_mem = NULL, | 62 | .validate_mem = NULL, |
139 | .adjust_io_region = iodyn_adjust_io_region, | 63 | .find_io = static_find_io, |
140 | .find_io = iodyn_find_io_region, | ||
141 | .find_mem = NULL, | 64 | .find_mem = NULL, |
142 | .add_io = NULL, | 65 | .add_io = NULL, |
143 | .add_mem = NULL, | 66 | .add_mem = NULL, |
144 | .init = static_init, | 67 | .init = static_init, |
145 | .exit = NULL, | 68 | .exit = NULL, |
146 | }; | 69 | }; |
147 | EXPORT_SYMBOL(pccard_iodyn_ops); | 70 | EXPORT_SYMBOL(pccard_static_ops); |
71 | |||
148 | 72 | ||
149 | #endif /* CONFIG_PCCARD_IODYN */ | 73 | MODULE_AUTHOR("David A. Hinds, Dominik Brodowski"); |
74 | MODULE_LICENSE("GPL"); | ||
75 | MODULE_ALIAS("rsrc_nonstatic"); | ||
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index a6eb7b59ba9f..dcd1a4ad3d63 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
@@ -34,8 +34,10 @@ | |||
34 | #include <pcmcia/cistpl.h> | 34 | #include <pcmcia/cistpl.h> |
35 | #include "cs_internal.h" | 35 | #include "cs_internal.h" |
36 | 36 | ||
37 | /* moved to rsrc_mgr.c | ||
37 | MODULE_AUTHOR("David A. Hinds, Dominik Brodowski"); | 38 | MODULE_AUTHOR("David A. Hinds, Dominik Brodowski"); |
38 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | */ | ||
39 | 41 | ||
40 | /* Parameters that can be set with 'insmod' */ | 42 | /* Parameters that can be set with 'insmod' */ |
41 | 43 | ||
@@ -70,27 +72,13 @@ struct socket_data { | |||
70 | ======================================================================*/ | 72 | ======================================================================*/ |
71 | 73 | ||
72 | static struct resource * | 74 | static struct resource * |
73 | make_resource(resource_size_t b, resource_size_t n, int flags, const char *name) | ||
74 | { | ||
75 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); | ||
76 | |||
77 | if (res) { | ||
78 | res->name = name; | ||
79 | res->start = b; | ||
80 | res->end = b + n - 1; | ||
81 | res->flags = flags; | ||
82 | } | ||
83 | return res; | ||
84 | } | ||
85 | |||
86 | static struct resource * | ||
87 | claim_region(struct pcmcia_socket *s, resource_size_t base, | 75 | claim_region(struct pcmcia_socket *s, resource_size_t base, |
88 | resource_size_t size, int type, char *name) | 76 | resource_size_t size, int type, char *name) |
89 | { | 77 | { |
90 | struct resource *res, *parent; | 78 | struct resource *res, *parent; |
91 | 79 | ||
92 | parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource; | 80 | parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource; |
93 | res = make_resource(base, size, type | IORESOURCE_BUSY, name); | 81 | res = pcmcia_make_resource(base, size, type | IORESOURCE_BUSY, name); |
94 | 82 | ||
95 | if (res) { | 83 | if (res) { |
96 | #ifdef CONFIG_PCI | 84 | #ifdef CONFIG_PCI |
@@ -661,8 +649,9 @@ pcmcia_align(void *align_data, const struct resource *res, | |||
661 | * Adjust an existing IO region allocation, but making sure that we don't | 649 | * Adjust an existing IO region allocation, but making sure that we don't |
662 | * encroach outside the resources which the user supplied. | 650 | * encroach outside the resources which the user supplied. |
663 | */ | 651 | */ |
664 | static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start, | 652 | static int __nonstatic_adjust_io_region(struct pcmcia_socket *s, |
665 | unsigned long r_end, struct pcmcia_socket *s) | 653 | unsigned long r_start, |
654 | unsigned long r_end) | ||
666 | { | 655 | { |
667 | struct resource_map *m; | 656 | struct resource_map *m; |
668 | struct socket_data *s_data = s->resource_data; | 657 | struct socket_data *s_data = s->resource_data; |
@@ -675,8 +664,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
675 | if (start > r_start || r_end > end) | 664 | if (start > r_start || r_end > end) |
676 | continue; | 665 | continue; |
677 | 666 | ||
678 | ret = adjust_resource(res, r_start, r_end - r_start + 1); | 667 | ret = 0; |
679 | break; | ||
680 | } | 668 | } |
681 | 669 | ||
682 | return ret; | 670 | return ret; |
@@ -695,18 +683,17 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
695 | 683 | ||
696 | ======================================================================*/ | 684 | ======================================================================*/ |
697 | 685 | ||
698 | static struct resource *nonstatic_find_io_region(unsigned long base, int num, | 686 | static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s, |
699 | unsigned long align, struct pcmcia_socket *s) | 687 | unsigned long base, int num, |
688 | unsigned long align) | ||
700 | { | 689 | { |
701 | struct resource *res = make_resource(0, num, IORESOURCE_IO, dev_name(&s->dev)); | 690 | struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, |
691 | dev_name(&s->dev)); | ||
702 | struct socket_data *s_data = s->resource_data; | 692 | struct socket_data *s_data = s->resource_data; |
703 | struct pcmcia_align_data data; | 693 | struct pcmcia_align_data data; |
704 | unsigned long min = base; | 694 | unsigned long min = base; |
705 | int ret; | 695 | int ret; |
706 | 696 | ||
707 | if (align == 0) | ||
708 | align = 0x10000; | ||
709 | |||
710 | data.mask = align - 1; | 697 | data.mask = align - 1; |
711 | data.offset = base & data.mask; | 698 | data.offset = base & data.mask; |
712 | data.map = &s_data->io_db; | 699 | data.map = &s_data->io_db; |
@@ -727,10 +714,97 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, | |||
727 | return res; | 714 | return res; |
728 | } | 715 | } |
729 | 716 | ||
717 | static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | ||
718 | unsigned int *base, unsigned int num, | ||
719 | unsigned int align) | ||
720 | { | ||
721 | int i, ret = 0; | ||
722 | |||
723 | /* Check for an already-allocated window that must conflict with | ||
724 | * what was asked for. It is a hack because it does not catch all | ||
725 | * potential conflicts, just the most obvious ones. | ||
726 | */ | ||
727 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
728 | if (!s->io[i].res) | ||
729 | continue; | ||
730 | |||
731 | if (!*base) | ||
732 | continue; | ||
733 | |||
734 | if ((s->io[i].res->start & (align-1)) == *base) | ||
735 | return -EBUSY; | ||
736 | } | ||
737 | |||
738 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
739 | struct resource *res = s->io[i].res; | ||
740 | unsigned int try; | ||
741 | |||
742 | if (res && (res->flags & IORESOURCE_BITS) != | ||
743 | (attr & IORESOURCE_BITS)) | ||
744 | continue; | ||
745 | |||
746 | if (!res) { | ||
747 | if (align == 0) | ||
748 | align = 0x10000; | ||
749 | |||
750 | res = s->io[i].res = __nonstatic_find_io_region(s, | ||
751 | *base, num, | ||
752 | align); | ||
753 | if (!res) | ||
754 | return -EINVAL; | ||
755 | |||
756 | *base = res->start; | ||
757 | s->io[i].res->flags = | ||
758 | ((res->flags & ~IORESOURCE_BITS) | | ||
759 | (attr & IORESOURCE_BITS)); | ||
760 | s->io[i].InUse = num; | ||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | /* Try to extend top of window */ | ||
765 | try = res->end + 1; | ||
766 | if ((*base == 0) || (*base == try)) { | ||
767 | ret = __nonstatic_adjust_io_region(s, res->start, | ||
768 | res->end + num); | ||
769 | if (!ret) { | ||
770 | ret = adjust_resource(s->io[i].res, res->start, | ||
771 | res->end - res->start + num + 1); | ||
772 | if (ret) | ||
773 | continue; | ||
774 | *base = try; | ||
775 | s->io[i].InUse += num; | ||
776 | return 0; | ||
777 | } | ||
778 | } | ||
779 | |||
780 | /* Try to extend bottom of window */ | ||
781 | try = res->start - num; | ||
782 | if ((*base == 0) || (*base == try)) { | ||
783 | ret = __nonstatic_adjust_io_region(s, | ||
784 | res->start - num, | ||
785 | res->end); | ||
786 | if (!ret) { | ||
787 | ret = adjust_resource(s->io[i].res, | ||
788 | res->start - num, | ||
789 | res->end - res->start + num + 1); | ||
790 | if (ret) | ||
791 | continue; | ||
792 | *base = try; | ||
793 | s->io[i].InUse += num; | ||
794 | return 0; | ||
795 | } | ||
796 | } | ||
797 | } | ||
798 | |||
799 | return -EINVAL; | ||
800 | } | ||
801 | |||
802 | |||
730 | static struct resource *nonstatic_find_mem_region(u_long base, u_long num, | 803 | static struct resource *nonstatic_find_mem_region(u_long base, u_long num, |
731 | u_long align, int low, struct pcmcia_socket *s) | 804 | u_long align, int low, struct pcmcia_socket *s) |
732 | { | 805 | { |
733 | struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev)); | 806 | struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_MEM, |
807 | dev_name(&s->dev)); | ||
734 | struct socket_data *s_data = s->resource_data; | 808 | struct socket_data *s_data = s->resource_data; |
735 | struct pcmcia_align_data data; | 809 | struct pcmcia_align_data data; |
736 | unsigned long min, max; | 810 | unsigned long min, max; |
@@ -861,23 +935,42 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) | |||
861 | return -ENODEV; | 935 | return -ENODEV; |
862 | 936 | ||
863 | #if defined(CONFIG_X86) | 937 | #if defined(CONFIG_X86) |
864 | /* If this is the root bus, the risk of hitting | 938 | /* If this is the root bus, the risk of hitting some strange |
865 | * some strange system devices which aren't protected | 939 | * system devices is too high: If a driver isn't loaded, the |
866 | * by either ACPI resource tables or properly requested | 940 | * resources are not claimed; even if a driver is loaded, it |
867 | * resources is too big. Therefore, don't do auto-adding | 941 | * may not request all resources or even the wrong one. We |
868 | * of resources at the moment. | 942 | * can neither trust the rest of the kernel nor ACPI/PNP and |
943 | * CRS parsing to get it right. Therefore, use several | ||
944 | * safeguards: | ||
945 | * | ||
946 | * - Do not auto-add resources if the CardBus bridge is on | ||
947 | * the PCI root bus | ||
948 | * | ||
949 | * - Avoid any I/O ports < 0x100. | ||
950 | * | ||
951 | * - On PCI-PCI bridges, only use resources which are set up | ||
952 | * exclusively for the secondary PCI bus: the risk of hitting | ||
953 | * system devices is quite low, as they usually aren't | ||
954 | * connected to the secondary PCI bus. | ||
869 | */ | 955 | */ |
870 | if (s->cb_dev->bus->number == 0) | 956 | if (s->cb_dev->bus->number == 0) |
871 | return -EINVAL; | 957 | return -EINVAL; |
872 | #endif | ||
873 | 958 | ||
959 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { | ||
960 | res = s->cb_dev->bus->resource[i]; | ||
961 | #else | ||
874 | pci_bus_for_each_resource(s->cb_dev->bus, res, i) { | 962 | pci_bus_for_each_resource(s->cb_dev->bus, res, i) { |
963 | #endif | ||
875 | if (!res) | 964 | if (!res) |
876 | continue; | 965 | continue; |
877 | 966 | ||
878 | if (res->flags & IORESOURCE_IO) { | 967 | if (res->flags & IORESOURCE_IO) { |
968 | /* safeguard against the root resource, where the | ||
969 | * risk of hitting any other device would be too | ||
970 | * high */ | ||
879 | if (res == &ioport_resource) | 971 | if (res == &ioport_resource) |
880 | continue; | 972 | continue; |
973 | |||
881 | dev_printk(KERN_INFO, &s->cb_dev->dev, | 974 | dev_printk(KERN_INFO, &s->cb_dev->dev, |
882 | "pcmcia: parent PCI bridge window: %pR\n", | 975 | "pcmcia: parent PCI bridge window: %pR\n", |
883 | res); | 976 | res); |
@@ -887,8 +980,12 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) | |||
887 | } | 980 | } |
888 | 981 | ||
889 | if (res->flags & IORESOURCE_MEM) { | 982 | if (res->flags & IORESOURCE_MEM) { |
983 | /* safeguard against the root resource, where the | ||
984 | * risk of hitting any other device would be too | ||
985 | * high */ | ||
890 | if (res == &iomem_resource) | 986 | if (res == &iomem_resource) |
891 | continue; | 987 | continue; |
988 | |||
892 | dev_printk(KERN_INFO, &s->cb_dev->dev, | 989 | dev_printk(KERN_INFO, &s->cb_dev->dev, |
893 | "pcmcia: parent PCI bridge window: %pR\n", | 990 | "pcmcia: parent PCI bridge window: %pR\n", |
894 | res); | 991 | res); |
@@ -956,8 +1053,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s) | |||
956 | 1053 | ||
957 | struct pccard_resource_ops pccard_nonstatic_ops = { | 1054 | struct pccard_resource_ops pccard_nonstatic_ops = { |
958 | .validate_mem = pcmcia_nonstatic_validate_mem, | 1055 | .validate_mem = pcmcia_nonstatic_validate_mem, |
959 | .adjust_io_region = nonstatic_adjust_io_region, | 1056 | .find_io = nonstatic_find_io, |
960 | .find_io = nonstatic_find_io_region, | ||
961 | .find_mem = nonstatic_find_mem_region, | 1057 | .find_mem = nonstatic_find_mem_region, |
962 | .add_io = adjust_io, | 1058 | .add_io = adjust_io, |
963 | .add_mem = adjust_memory, | 1059 | .add_mem = adjust_memory, |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 83ace277426c..424e576f3acb 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -1303,13 +1303,6 @@ static int yenta_dev_suspend_noirq(struct device *dev) | |||
1303 | pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]); | 1303 | pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]); |
1304 | pci_disable_device(pdev); | 1304 | pci_disable_device(pdev); |
1305 | 1305 | ||
1306 | /* | ||
1307 | * Some laptops (IBM T22) do not like us putting the Cardbus | ||
1308 | * bridge into D3. At a guess, some other laptop will | ||
1309 | * probably require this, so leave it commented out for now. | ||
1310 | */ | ||
1311 | /* pci_set_power_state(dev, 3); */ | ||
1312 | |||
1313 | return 0; | 1306 | return 0; |
1314 | } | 1307 | } |
1315 | 1308 | ||