};
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
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);