Commit 904e3777 authored by Dominik Brodowski's avatar Dominik Brodowski

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: default avatarWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent fa0b3bc5
...@@ -319,22 +319,23 @@ remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len) ...@@ -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) void destroy_cis_cache(struct pcmcia_socket *s)
{ {
struct list_head *l, *n; struct list_head *l, *n;
struct cis_cache_entry *cis;
list_for_each_safe(l, n, &s->cis_cache) { 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); list_del(&cis->node);
kfree(cis); 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); EXPORT_SYMBOL(destroy_cis_cache);
...@@ -1596,6 +1597,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) ...@@ -1596,6 +1597,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
if (!s) if (!s)
return -EINVAL; return -EINVAL;
/* We do not want to validate the CIS cache... */
destroy_cis_cache(s);
tuple = kmalloc(sizeof(*tuple), GFP_KERNEL); tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
if (tuple == NULL) { if (tuple == NULL) {
dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n"); 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,6 +1651,10 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
count = 0; count = 0;
done: done:
/* invalidate CIS cache on failure */
if (!dev_ok || !ident_ok || !count)
destroy_cis_cache(s);
if (info) if (info)
*info = count; *info = count;
kfree(tuple); kfree(tuple);
......
...@@ -407,6 +407,8 @@ static void socket_shutdown(struct pcmcia_socket *s) ...@@ -407,6 +407,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
s->irq.AssignedIRQ = s->irq.Config = 0; s->irq.AssignedIRQ = s->irq.Config = 0;
s->lock_count = 0; s->lock_count = 0;
destroy_cis_cache(s); destroy_cis_cache(s);
kfree(s->fake_cis);
s->fake_cis = NULL;
#ifdef CONFIG_CARDBUS #ifdef CONFIG_CARDBUS
cb_free(s); cb_free(s);
#endif #endif
...@@ -577,6 +579,8 @@ static int socket_late_resume(struct pcmcia_socket *skt) ...@@ -577,6 +579,8 @@ static int socket_late_resume(struct pcmcia_socket *skt)
dev_dbg(&skt->dev, "cis mismatch - different card\n"); dev_dbg(&skt->dev, "cis mismatch - different card\n");
socket_remove_drivers(skt); socket_remove_drivers(skt);
destroy_cis_cache(skt); destroy_cis_cache(skt);
kfree(skt->fake_cis);
skt->fake_cis = NULL;
/* /*
* Workaround: give DS time to schedule removal. * Workaround: give DS time to schedule removal.
* Remove me once the 100ms delay is eliminated * Remove me once the 100ms delay is eliminated
......
...@@ -281,10 +281,9 @@ static int readable(struct pcmcia_socket *s, struct resource *res, ...@@ -281,10 +281,9 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
s->cis_virt = ioremap(res->start, s->map_size); s->cis_virt = ioremap(res->start, s->map_size);
if (s->cis_virt) { if (s->cis_virt) {
ret = pccard_validate_cis(s, count); ret = pccard_validate_cis(s, count);
/* invalidate mapping and CIS cache */ /* invalidate mapping */
iounmap(s->cis_virt); iounmap(s->cis_virt);
s->cis_virt = NULL; s->cis_virt = NULL;
destroy_cis_cache(s);
} }
s->cis_mem.res = NULL; s->cis_mem.res = NULL;
if ((ret != 0) || (*count == 0)) if ((ret != 0) || (*count == 0))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment