aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-02 06:28:04 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-01-17 12:30:09 -0500
commit904e377744bfdcea276c27167fa6a609929f39dc (patch)
tree4dc05b84992a2c35a1933b5b12b44391e0cd4e08 /drivers/pcmcia
parentfa0b3bc504ff813cc05988bb30bbb6c6a0263eb4 (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.c24
-rw-r--r--drivers/pcmcia/cs.c4
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c3
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
322void destroy_cis_cache(struct pcmcia_socket *s) 329void 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}
339EXPORT_SYMBOL(destroy_cis_cache); 340EXPORT_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
1649done: 1653done:
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))