[PATCH 10/11] pcmcia: insert PCMCIA device resources into resource tree

Dominik Brodowski linux at dominikbrodowski.net
Sun Aug 1 08:59:09 EDT 2010


Insert PCMCIA device resources into the resource tree. However, this is
currently only implemented for sockets which do not statically map the
resources.

Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 drivers/pcmcia/cs_internal.h     |    3 +-
 drivers/pcmcia/ds.c              |    2 +-
 drivers/pcmcia/pcmcia_resource.c |   74 +++++++++++++++++++++++--------------
 drivers/pcmcia/rsrc_iodyn.c      |    5 ++-
 drivers/pcmcia/rsrc_mgr.c        |    3 +-
 drivers/pcmcia/rsrc_nonstatic.c  |    5 ++-
 6 files changed, 59 insertions(+), 33 deletions(-)

diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 37d38b5..da055dc 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -62,7 +62,8 @@ struct pccard_resource_ops {
 					 unsigned int attr,
 					 unsigned int *base,
 					 unsigned int num,
-					 unsigned int align);
+					 unsigned int align,
+					 struct resource **parent);
 	struct resource* (*find_mem)	(unsigned long base, unsigned long num,
 					 unsigned long align, int low,
 					 struct pcmcia_socket *s);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 6862e35..5c6e0fa 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -553,7 +553,7 @@ static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
 		p_dev->function_config = c;
 		kref_init(&c->ref);
 		for (i = 0; i < (MAX_IO_WIN + MAX_WIN); i++) {
-			c->io[i].name = dev_name(&p_dev->dev);
+			c->io[i].name = p_dev->devname;
 			c->io[i].flags = i < MAX_IO_WIN ? IORESOURCE_IO :
 				IORESOURCE_MEM;
 		}
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 01f8e56..d48437f 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -56,6 +56,33 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
 }
 
 
+static void release_io_space(struct pcmcia_socket *s, struct resource *res)
+{
+	resource_size_t num = resource_size(res);
+	int i;
+
+	dev_dbg(&s->dev, "release_io_space for %pR\n", res);
+
+	for (i = 0; i < MAX_IO_WIN; i++) {
+		if (!s->io[i].res)
+			continue;
+		if ((s->io[i].res->start <= res->start) &&
+		    (s->io[i].res->end >= res->end)) {
+			s->io[i].InUse -= num;
+			if (res->parent)
+				release_resource(res);
+			res->start = res->end = 0;
+			res->flags = IORESOURCE_IO;
+			/* Free the window if no one else is using it */
+			if (s->io[i].InUse == 0) {
+				release_resource(s->io[i].res);
+				kfree(s->io[i].res);
+				s->io[i].res = NULL;
+			}
+		}
+	}
+} /* release_io_space */
+
 /** alloc_io_space
  *
  * Special stuff for managing IO windows, because they are scarce
@@ -87,43 +114,28 @@ static int alloc_io_space(struct pcmcia_socket *s, struct resource *res,
 		align = 0;
 	}
 
-	ret = s->resource_ops->find_io(s, res->flags, &base, num, align);
+	ret = s->resource_ops->find_io(s, res->flags, &base, num, align,
+				&res->parent);
 	if (ret) {
-		dev_dbg(&s->dev, "alloc_io_space request returned %d", ret);
+		dev_dbg(&s->dev, "alloc_io_space request failed (%d)\n", ret);
 		return -EINVAL;
 	}
 
 	res->start = base;
 	res->end = res->start + num - 1;
-	dev_dbg(&s->dev, "alloc_io_space request returned %pR, %d\n", res, ret);
-	return 0;
-} /* alloc_io_space */
 
-
-static void release_io_space(struct pcmcia_socket *s, struct resource *res)
-{
-	resource_size_t num = resource_size(res);
-	int i;
-
-	dev_dbg(&s->dev, "release_io_space for %pR\n", res);
-
-	for (i = 0; i < MAX_IO_WIN; i++) {
-		if (!s->io[i].res)
-			continue;
-		if ((s->io[i].res->start <= res->start) &&
-		    (s->io[i].res->end >= res->end)) {
-			s->io[i].InUse -= num;
-			res->start = res->end = 0;
-			res->flags = IORESOURCE_IO;
-			/* Free the window if no one else is using it */
-			if (s->io[i].InUse == 0) {
-				release_resource(s->io[i].res);
-				kfree(s->io[i].res);
-				s->io[i].res = NULL;
-			}
+	if (res->parent) {
+		ret = request_resource(res->parent, res);
+		if (ret) {
+			dev_warn(&s->dev,
+				"request_resource %pR failed: %d\n", res, ret);
+			res->parent = NULL;
+			release_io_space(s, res);
 		}
 	}
-} /* release_io_space */
+	dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res);
+	return ret;
+} /* alloc_io_space */
 
 
 /**
@@ -401,6 +413,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
 
 	/* Release system memory */
 	if (win->res) {
+		release_resource(res);
 		release_resource(win->res);
 		kfree(win->res);
 		win->res = NULL;
@@ -853,6 +866,11 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 	res->end = req->Base + req->Size - 1;
 	res->flags &= ~IORESOURCE_BITS;
 	res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2);
+	res->flags |= IORESOURCE_MEM;
+	res->parent = win->res;
+	if (win->res)
+		request_resource(&iomem_resource, res);
+
 	dev_dbg(&s->dev, "request_window results in %pR\n", res);
 
 	mutex_unlock(&s->ops_mutex);
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c
index 3b1dce2..8510c35 100644
--- a/drivers/pcmcia/rsrc_iodyn.c
+++ b/drivers/pcmcia/rsrc_iodyn.c
@@ -87,7 +87,7 @@ static struct resource *__iodyn_find_io_region(struct pcmcia_socket *s,
 
 static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
 			unsigned int *base, unsigned int num,
-			unsigned int align)
+			unsigned int align, struct resource **parent)
 {
 	int i, ret = 0;
 
@@ -128,6 +128,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
 				((res->flags & ~IORESOURCE_BITS) |
 					(attr & IORESOURCE_BITS));
 			s->io[i].InUse = num;
+			*parent = res;
 			return 0;
 		}
 
@@ -139,6 +140,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
 				continue;
 			*base = try;
 			s->io[i].InUse += num;
+			*parent = res;
 			return 0;
 		}
 
@@ -151,6 +153,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
 				continue;
 			*base = try;
 			s->io[i].InUse += num;
+			*parent = res;
 			return 0;
 		}
 	}
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index b433a79..4e80421 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -47,11 +47,12 @@ struct resource *pcmcia_make_resource(unsigned long start, unsigned long end,
 
 static int static_find_io(struct pcmcia_socket *s, unsigned int attr,
 			unsigned int *base, unsigned int num,
-			unsigned int align)
+			unsigned int align, struct resource **parent)
 {
 	if (!s->io_offset)
 		return -EINVAL;
 	*base = s->io_offset | (*base & 0x0fff);
+	*parent = NULL;
 
 	return 0;
 }
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index c17a17d..96f348b 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -718,7 +718,7 @@ static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s,
 
 static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
 			unsigned int *base, unsigned int num,
-			unsigned int align)
+			unsigned int align, struct resource **parent)
 {
 	int i, ret = 0;
 
@@ -760,6 +760,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
 				((res->flags & ~IORESOURCE_BITS) |
 					(attr & IORESOURCE_BITS));
 			s->io[i].InUse = num;
+			*parent = res;
 			return 0;
 		}
 
@@ -775,6 +776,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
 					continue;
 				*base = try;
 				s->io[i].InUse += num;
+				*parent = res;
 				return 0;
 			}
 		}
@@ -793,6 +795,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
 					continue;
 				*base = try;
 				s->io[i].InUse += num;
+				*parent = res;
 				return 0;
 			}
 		}
-- 
1.7.0.4




More information about the linux-pcmcia mailing list