diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-01-02 06:28:04 -0500 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-01-17 12:30:09 -0500 |
commit | 904e377744bfdcea276c27167fa6a609929f39dc (patch) | |
tree | 4dc05b84992a2c35a1933b5b12b44391e0cd4e08 /drivers/pcmcia | |
parent | fa0b3bc504ff813cc05988bb30bbb6c6a0263eb4 (diff) |
pcmcia: validate CIS, not CIS cache.
In pccard_validate_cis(), validate the card CIS, not the CIS cache.
Also, destroy the CIS cache if pccard_validate_cis fails.
Furthermore, do not remove the fake CIS in destroy_cis_cache() but
do so explicitely in the code paths where it makes sense.
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cistpl.c | 24 | ||||
-rw-r--r-- | drivers/pcmcia/cs.c | 4 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 3 |
3 files changed, 21 insertions, 10 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 25b1cd219e37..41ec7729eddc 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -319,22 +319,23 @@ remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len) | |||
319 | } | 319 | } |
320 | } | 320 | } |
321 | 321 | ||
322 | /** | ||
323 | * destroy_cis_cache() - destroy the CIS cache | ||
324 | * @s: pcmcia_socket for which CIS cache shall be destroyed | ||
325 | * | ||
326 | * This destroys the CIS cache but keeps any fake CIS alive. | ||
327 | */ | ||
328 | |||
322 | void destroy_cis_cache(struct pcmcia_socket *s) | 329 | void destroy_cis_cache(struct pcmcia_socket *s) |
323 | { | 330 | { |
324 | struct list_head *l, *n; | 331 | struct list_head *l, *n; |
332 | struct cis_cache_entry *cis; | ||
325 | 333 | ||
326 | list_for_each_safe(l, n, &s->cis_cache) { | 334 | list_for_each_safe(l, n, &s->cis_cache) { |
327 | struct cis_cache_entry *cis = list_entry(l, struct cis_cache_entry, node); | 335 | cis = list_entry(l, struct cis_cache_entry, node); |
328 | |||
329 | list_del(&cis->node); | 336 | list_del(&cis->node); |
330 | kfree(cis); | 337 | kfree(cis); |
331 | } | 338 | } |
332 | |||
333 | /* | ||
334 | * If there was a fake CIS, destroy that as well. | ||
335 | */ | ||
336 | kfree(s->fake_cis); | ||
337 | s->fake_cis = NULL; | ||
338 | } | 339 | } |
339 | EXPORT_SYMBOL(destroy_cis_cache); | 340 | EXPORT_SYMBOL(destroy_cis_cache); |
340 | 341 | ||
@@ -1596,6 +1597,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) | |||
1596 | if (!s) | 1597 | if (!s) |
1597 | return -EINVAL; | 1598 | return -EINVAL; |
1598 | 1599 | ||
1600 | /* We do not want to validate the CIS cache... */ | ||
1601 | destroy_cis_cache(s); | ||
1602 | |||
1599 | tuple = kmalloc(sizeof(*tuple), GFP_KERNEL); | 1603 | tuple = kmalloc(sizeof(*tuple), GFP_KERNEL); |
1600 | if (tuple == NULL) { | 1604 | if (tuple == NULL) { |
1601 | dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n"); | 1605 | dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n"); |
@@ -1647,6 +1651,10 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) | |||
1647 | count = 0; | 1651 | count = 0; |
1648 | 1652 | ||
1649 | done: | 1653 | done: |
1654 | /* invalidate CIS cache on failure */ | ||
1655 | if (!dev_ok || !ident_ok || !count) | ||
1656 | destroy_cis_cache(s); | ||
1657 | |||
1650 | if (info) | 1658 | if (info) |
1651 | *info = count; | 1659 | *info = count; |
1652 | kfree(tuple); | 1660 | kfree(tuple); |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 6d6f82b38a68..96d8d25c209d 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -407,6 +407,8 @@ static void socket_shutdown(struct pcmcia_socket *s) | |||
407 | s->irq.AssignedIRQ = s->irq.Config = 0; | 407 | s->irq.AssignedIRQ = s->irq.Config = 0; |
408 | s->lock_count = 0; | 408 | s->lock_count = 0; |
409 | destroy_cis_cache(s); | 409 | destroy_cis_cache(s); |
410 | kfree(s->fake_cis); | ||
411 | s->fake_cis = NULL; | ||
410 | #ifdef CONFIG_CARDBUS | 412 | #ifdef CONFIG_CARDBUS |
411 | cb_free(s); | 413 | cb_free(s); |
412 | #endif | 414 | #endif |
@@ -577,6 +579,8 @@ static int socket_late_resume(struct pcmcia_socket *skt) | |||
577 | dev_dbg(&skt->dev, "cis mismatch - different card\n"); | 579 | dev_dbg(&skt->dev, "cis mismatch - different card\n"); |
578 | socket_remove_drivers(skt); | 580 | socket_remove_drivers(skt); |
579 | destroy_cis_cache(skt); | 581 | destroy_cis_cache(skt); |
582 | kfree(skt->fake_cis); | ||
583 | skt->fake_cis = NULL; | ||
580 | /* | 584 | /* |
581 | * Workaround: give DS time to schedule removal. | 585 | * Workaround: give DS time to schedule removal. |
582 | * Remove me once the 100ms delay is eliminated | 586 | * Remove me once the 100ms delay is eliminated |
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 4f93889301b6..b886385f12e2 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
@@ -281,10 +281,9 @@ static int readable(struct pcmcia_socket *s, struct resource *res, | |||
281 | s->cis_virt = ioremap(res->start, s->map_size); | 281 | s->cis_virt = ioremap(res->start, s->map_size); |
282 | if (s->cis_virt) { | 282 | if (s->cis_virt) { |
283 | ret = pccard_validate_cis(s, count); | 283 | ret = pccard_validate_cis(s, count); |
284 | /* invalidate mapping and CIS cache */ | 284 | /* invalidate mapping */ |
285 | iounmap(s->cis_virt); | 285 | iounmap(s->cis_virt); |
286 | s->cis_virt = NULL; | 286 | s->cis_virt = NULL; |
287 | destroy_cis_cache(s); | ||
288 | } | 287 | } |
289 | s->cis_mem.res = NULL; | 288 | s->cis_mem.res = NULL; |
290 | if ((ret != 0) || (*count == 0)) | 289 | if ((ret != 0) || (*count == 0)) |