[PATCH 16/18] pcmcia: insert PCMCIA device resources into resource tree
Dominik Brodowski
linux at dominikbrodowski.net
Thu Aug 5 18:06:52 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 | 4 +-
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, 60 insertions(+), 34 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 028c973..55570d9 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -553,11 +553,11 @@ 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; i++) {
- c->io[i].name = dev_name(&p_dev->dev);
+ c->io[i].name = p_dev->devname;
c->io[i].flags = IORESOURCE_IO;
}
for (i = 0; i< MAX_WIN; i++) {
- c->mem[i].name = dev_name(&p_dev->dev);
+ c->mem[i].name = p_dev->devname;
c->mem[i].flags = 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