};
static DECLARE_MUTEX(rsrc_sem);
+static unsigned int rsrc_mem_probe;
+#define MEM_PROBE_LOW (1 << 0)
+#define MEM_PROBE_HIGH (1 << 1)
#ifdef CONFIG_PCMCIA_PROBE
{
int ret = -1;
- s->cis_mem.sys_start = res->start;
- s->cis_mem.sys_stop = res->end;
s->cis_mem.res = res;
s->cis_virt = ioremap(res->start, s->map_size);
if (s->cis_virt) {
s->cis_virt = NULL;
destroy_cis_cache(s);
}
- s->cis_mem.sys_start = 0;
- s->cis_mem.sys_stop = 0;
s->cis_mem.res = NULL;
if ((ret != 0) || (info->Chains == 0))
return 0;
{
pccard_mem_map map;
int i, a = 0, b = -1, d;
- void *virt;
+ void __iomem *virt;
virt = ioremap(res->start, s->map_size);
if (virt) {
map.map = 0;
map.flags = MAP_ACTIVE;
map.speed = 0;
- map.sys_start = res->start;
- map.sys_stop = res->end;
map.res = res;
map.card_start = 0;
s->ops->set_mem_map(s, &map);
return do_mem_probe(m->base, m->num, s);
}
-static void validate_mem(struct pcmcia_socket *s)
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{
resource_map_t *m, mm;
static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
- static int hi = 0, lo = 0;
u_long b, i, ok = 0;
- int force_low = !(s->features & SS_CAP_PAGE_REGS);
- down(&rsrc_sem);
/* We do up to four passes through the list */
- if (!force_low) {
- if (hi++ || (inv_probe(mem_db.next, s) > 0))
- goto out;
+ if (probe_mask & MEM_PROBE_HIGH) {
+ if (inv_probe(mem_db.next, s) > 0)
+ return;
printk(KERN_NOTICE "cs: warning: no high memory space "
"available!\n");
}
- if (lo++)
- goto out;
+ if ((probe_mask & MEM_PROBE_LOW) == 0)
+ return;
for (m = mem_db.next; m != &mem_db; m = mm.next) {
mm = *m;
/* Only probe < 1 MB */
}
}
}
- out:
- up(&rsrc_sem);
}
#else /* CONFIG_PCMCIA_PROBE */
-static void validate_mem(struct pcmcia_socket *s)
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{
- resource_map_t *m, mm;
- static int done = 0;
+ resource_map_t *m, mm;
- if (done++ == 0) {
- down(&rsrc_sem);
for (m = mem_db.next; m != &mem_db; m = mm.next) {
- mm = *m;
- if (do_mem_probe(mm.base, mm.num, s))
- break;
+ mm = *m;
+ if (do_mem_probe(mm.base, mm.num, s))
+ break;
}
- up(&rsrc_sem);
- }
}
#endif /* CONFIG_PCMCIA_PROBE */
+/*
+ * Locking note: this is the only place where we take
+ * both rsrc_sem and skt_sem.
+ */
void pcmcia_validate_mem(struct pcmcia_socket *s)
{
- down(&s->skt_sem);
+ if (probe_mem) {
+ unsigned int probe_mask;
+
+ down(&rsrc_sem);
+
+ probe_mask = MEM_PROBE_LOW;
+ if (s->features & SS_CAP_PAGE_REGS)
+ probe_mask = MEM_PROBE_HIGH;
+
+ if (probe_mask & ~rsrc_mem_probe) {
+ rsrc_mem_probe |= probe_mask;
- if (probe_mem && s->state & SOCKET_PRESENT)
- validate_mem(s);
+ down(&s->skt_sem);
- up(&s->skt_sem);
+ if (s->state & SOCKET_PRESENT)
+ validate_mem(s, probe_mask);
+
+ up(&s->skt_sem);
+ }
+
+ up(&rsrc_sem);
+ }
}
EXPORT_SYMBOL(pcmcia_validate_mem);