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>
This commit is contained in:
parent
fa0b3bc504
commit
904e377744
3 changed files with 21 additions and 10 deletions
|
@ -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);
|
||||
|
|
|
@ -407,6 +407,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
|
|||
s->irq.AssignedIRQ = s->irq.Config = 0;
|
||||
s->lock_count = 0;
|
||||
destroy_cis_cache(s);
|
||||
kfree(s->fake_cis);
|
||||
s->fake_cis = NULL;
|
||||
#ifdef CONFIG_CARDBUS
|
||||
cb_free(s);
|
||||
#endif
|
||||
|
@ -577,6 +579,8 @@ static int socket_late_resume(struct pcmcia_socket *skt)
|
|||
dev_dbg(&skt->dev, "cis mismatch - different card\n");
|
||||
socket_remove_drivers(skt);
|
||||
destroy_cis_cache(skt);
|
||||
kfree(skt->fake_cis);
|
||||
skt->fake_cis = NULL;
|
||||
/*
|
||||
* Workaround: give DS time to schedule removal.
|
||||
* Remove me once the 100ms delay is eliminated
|
||||
|
|
|
@ -281,10 +281,9 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
|
|||
s->cis_virt = ioremap(res->start, s->map_size);
|
||||
if (s->cis_virt) {
|
||||
ret = pccard_validate_cis(s, count);
|
||||
/* invalidate mapping and CIS cache */
|
||||
/* invalidate mapping */
|
||||
iounmap(s->cis_virt);
|
||||
s->cis_virt = NULL;
|
||||
destroy_cis_cache(s);
|
||||
}
|
||||
s->cis_mem.res = NULL;
|
||||
if ((ret != 0) || (*count == 0))
|
||||
|
|
Loading…
Reference in a new issue