aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/cistpl.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-02 12:28:04 +0100
committerDominik Brodowski <linux@dominikbrodowski.net>2010-01-17 18:30:09 +0100
commit904e377744bfdcea276c27167fa6a609929f39dc (patch)
tree4dc05b84992a2c35a1933b5b12b44391e0cd4e08 /drivers/pcmcia/cistpl.c
parentpcmcia: do not meddle with already assigned resources (diff)
downloadlinux-dev-904e377744bfdcea276c27167fa6a609929f39dc.tar.xz
linux-dev-904e377744bfdcea276c27167fa6a609929f39dc.zip
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/cistpl.c')
-rw-r--r--drivers/pcmcia/cistpl.c24
1 files changed, 16 insertions, 8 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)
}
}
+/**
+ * destroy_cis_cache() - destroy the CIS cache
+ * @s: pcmcia_socket for which CIS cache shall be destroyed
+ *
+ * This destroys the CIS cache but keeps any fake CIS alive.
+ */
+
void destroy_cis_cache(struct pcmcia_socket *s)
{
struct list_head *l, *n;
+ struct cis_cache_entry *cis;
list_for_each_safe(l, n, &s->cis_cache) {
- struct cis_cache_entry *cis = list_entry(l, struct cis_cache_entry, node);
-
+ cis = list_entry(l, struct cis_cache_entry, node);
list_del(&cis->node);
kfree(cis);
}
-
- /*
- * If there was a fake CIS, destroy that as well.
- */
- kfree(s->fake_cis);
- s->fake_cis = NULL;
}
EXPORT_SYMBOL(destroy_cis_cache);
@@ -1596,6 +1597,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
if (!s)
return -EINVAL;
+ /* We do not want to validate the CIS cache... */
+ destroy_cis_cache(s);
+
tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
if (tuple == NULL) {
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)
count = 0;
done:
+ /* invalidate CIS cache on failure */
+ if (!dev_ok || !ident_ok || !count)
+ destroy_cis_cache(s);
+
if (info)
*info = count;
kfree(tuple);