[PATCH 7/8] pcmcia: validate_mem shouldn't be void

Dominik Brodowski linux at dominikbrodowski.net
Sat Sep 24 15:58:33 EDT 2005


Add a return value to pcmcia_validate_mem. Only if we have enough memory
available to map the CIS, we should proceed in trying to determine
information about the device.

Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>

Index: 2.6.14-rc2/drivers/pcmcia/cs_internal.h
===================================================================
--- 2.6.14-rc2.orig/drivers/pcmcia/cs_internal.h
+++ 2.6.14-rc2/drivers/pcmcia/cs_internal.h
@@ -117,7 +117,7 @@ int verify_cis_cache(struct pcmcia_socke
 int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse);
 
 /* In rsrc_mgr */
-void pcmcia_validate_mem(struct pcmcia_socket *s);
+int pcmcia_validate_mem(struct pcmcia_socket *s);
 struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
 		   struct pcmcia_socket *s);
 int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
Index: 2.6.14-rc2/drivers/pcmcia/ds.c
===================================================================
--- 2.6.14-rc2.orig/drivers/pcmcia/ds.c
+++ 2.6.14-rc2/drivers/pcmcia/ds.c
@@ -635,7 +635,9 @@ static int pcmcia_card_add(struct pcmcia
 	if (!(s->resource_setup_done))
 		return -EAGAIN; /* try again, but later... */
 
-	pcmcia_validate_mem(s);
+	if (pcmcia_validate_mem(s))
+		return -EAGAIN; /* try again, but later... */
+
 	ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
 	if (ret || !cisinfo.Chains) {
 		ds_dbg(0, "invalid CIS or invalid resources\n");
Index: 2.6.14-rc2/drivers/pcmcia/rsrc_mgr.c
===================================================================
--- 2.6.14-rc2.orig/drivers/pcmcia/rsrc_mgr.c
+++ 2.6.14-rc2/drivers/pcmcia/rsrc_mgr.c
@@ -98,10 +98,12 @@ int pcmcia_adjust_resource_info(adjust_t
 }
 EXPORT_SYMBOL(pcmcia_adjust_resource_info);
 
-void pcmcia_validate_mem(struct pcmcia_socket *s)
+int pcmcia_validate_mem(struct pcmcia_socket *s)
 {
 	if (s->resource_ops->validate_mem)
-		s->resource_ops->validate_mem(s);
+		return s->resource_ops->validate_mem(s);
+	/* if there is no callback, we can assume that everything is OK */
+	return 0;
 }
 EXPORT_SYMBOL(pcmcia_validate_mem);
 
Index: 2.6.14-rc2/drivers/pcmcia/rsrc_nonstatic.c
===================================================================
--- 2.6.14-rc2.orig/drivers/pcmcia/rsrc_nonstatic.c
+++ 2.6.14-rc2/drivers/pcmcia/rsrc_nonstatic.c
@@ -407,56 +407,62 @@ static int do_mem_probe(u_long base, u_l
 
 static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
 {
-    struct socket_data *s_data = s->resource_data;
-    u_long ok;
-    if (m == &s_data->mem_db)
-	return 0;
-    ok = inv_probe(m->next, s);
-    if (ok) {
-	if (m->base >= 0x100000)
-	    sub_interval(&s_data->mem_db, m->base, m->num);
-	return ok;
-    }
-    if (m->base < 0x100000)
-	return 0;
-    return do_mem_probe(m->base, m->num, s);
+	struct socket_data *s_data = s->resource_data;
+	u_long ok;
+	if (m == &s_data->mem_db)
+		return 0;
+	ok = inv_probe(m->next, s);
+	if (ok) {
+		if (m->base >= 0x100000)
+			sub_interval(&s_data->mem_db, m->base, m->num);
+		return ok;
+	}
+	if (m->base < 0x100000)
+		return 0;
+	return do_mem_probe(m->base, m->num, s);
 }
 
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
-    struct resource_map *m, mm;
-    static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
-    u_long b, i, ok = 0;
-    struct socket_data *s_data = s->resource_data;
-
-    /* We do up to four passes through the list */
-    if (probe_mask & MEM_PROBE_HIGH) {
-	if (inv_probe(s_data->mem_db.next, s) > 0)
-	    return;
-	printk(KERN_NOTICE "cs: warning: no high memory space "
-	       "available!\n");
-    }
-    if ((probe_mask & MEM_PROBE_LOW) == 0)
-	return;
-    for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
-	mm = *m;
-	/* Only probe < 1 MB */
-	if (mm.base >= 0x100000) continue;
-	if ((mm.base | mm.num) & 0xffff) {
-	    ok += do_mem_probe(mm.base, mm.num, s);
-	    continue;
-	}
-	/* Special probe for 64K-aligned block */
-	for (i = 0; i < 4; i++) {
-	    b = order[i] << 12;
-	    if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
-		if (ok >= mem_limit)
-		    sub_interval(&s_data->mem_db, b, 0x10000);
-		else
-		    ok += do_mem_probe(b, 0x10000, s);
-	    }
+	struct resource_map *m, mm;
+	static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
+	unsigned long b, i, ok = 0;
+	struct socket_data *s_data = s->resource_data;
+
+	/* We do up to four passes through the list */
+	if (probe_mask & MEM_PROBE_HIGH) {
+		if (inv_probe(s_data->mem_db.next, s) > 0)
+			return 0;
+		printk(KERN_NOTICE "cs: warning: no high memory space "
+		       "available!\n");
+		return -ENODEV;
+	}
+
+	for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+		mm = *m;
+		/* Only probe < 1 MB */
+		if (mm.base >= 0x100000)
+			continue;
+		if ((mm.base | mm.num) & 0xffff) {
+			ok += do_mem_probe(mm.base, mm.num, s);
+			continue;
+		}
+		/* Special probe for 64K-aligned block */
+		for (i = 0; i < 4; i++) {
+			b = order[i] << 12;
+			if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
+				if (ok >= mem_limit)
+					sub_interval(&s_data->mem_db, b, 0x10000);
+				else
+					ok += do_mem_probe(b, 0x10000, s);
+			}
+		}
 	}
-    }
+
+	if (ok > 0)
+		return 0;
+
+	return -ENODEV;
 }
 
 #else /* CONFIG_PCMCIA_PROBE */
@@ -478,27 +484,30 @@ static void validate_mem(struct pcmcia_s
 /*
  * Locking note: Must be called with skt_sem held!
  */
-static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
+static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
 {
 	struct socket_data *s_data = s->resource_data;
-	if (probe_mem) {
-		unsigned int probe_mask;
+	unsigned int probe_mask = MEM_PROBE_LOW;
+	int ret = 0;
 
-		down(&rsrc_sem);
+	if (!probe_mem)
+		return 0;
 
-		probe_mask = MEM_PROBE_LOW;
-		if (s->features & SS_CAP_PAGE_REGS)
-			probe_mask = MEM_PROBE_HIGH;
+	down(&rsrc_sem);
+
+	if (s->features & SS_CAP_PAGE_REGS)
+		probe_mask = MEM_PROBE_HIGH;
 
-		if (probe_mask & ~s_data->rsrc_mem_probe) {
+	if (probe_mask & ~s_data->rsrc_mem_probe) {
+		if (s->state & SOCKET_PRESENT)
+			ret = validate_mem(s, probe_mask);
+		if (!ret)
 			s_data->rsrc_mem_probe |= probe_mask;
+	}
 
-			if (s->state & SOCKET_PRESENT)
-				validate_mem(s, probe_mask);
-		}
+	up(&rsrc_sem);
 
-		up(&rsrc_sem);
-	}
+	return ret;
 }
 
 struct pcmcia_align_data {
Index: 2.6.14-rc2/include/pcmcia/ss.h
===================================================================
--- 2.6.14-rc2.orig/include/pcmcia/ss.h
+++ 2.6.14-rc2/include/pcmcia/ss.h
@@ -124,7 +124,7 @@ struct pccard_operations {
 };
 
 struct pccard_resource_ops {
-	void	(*validate_mem)		(struct pcmcia_socket *s);
+	int	(*validate_mem)		(struct pcmcia_socket *s);
 	int	(*adjust_io_region)	(struct resource *res,
 					 unsigned long r_start,
 					 unsigned long r_end,
Index: 2.6.14-rc2/drivers/pcmcia/tcic.c
===================================================================
--- 2.6.14-rc2.orig/drivers/pcmcia/tcic.c
+++ 2.6.14-rc2/drivers/pcmcia/tcic.c
@@ -181,13 +181,6 @@ static void tcic_setl(u_char reg, u_int 
     outw(data >> 16, tcic_base+reg+2);
 }
 
-static u_char tcic_aux_getb(u_short reg)
-{
-    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
-    tcic_setb(TCIC_MODE, mode);
-    return tcic_getb(TCIC_AUX);
-}
-
 static void tcic_aux_setb(u_short reg, u_char data)
 {
     u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;



More information about the linux-pcmcia mailing list