pcmcia: insert PCMCIA device resources into resource tree
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@dominikbrodowski.net>
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 @@
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 @@
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 @@
}
+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 @@
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 @@
/* Release system memory */
if (win->res) {
+ release_resource(res);
release_resource(win->res);
kfree(win->res);
win->res = NULL;
@@ -853,6 +866,11 @@
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 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 @@
((res->flags & ~IORESOURCE_BITS) |
(attr & IORESOURCE_BITS));
s->io[i].InUse = num;
+ *parent = res;
return 0;
}
@@ -139,6 +140,7 @@
continue;
*base = try;
s->io[i].InUse += num;
+ *parent = res;
return 0;
}
@@ -151,6 +153,7 @@
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 @@
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 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 @@
((res->flags & ~IORESOURCE_BITS) |
(attr & IORESOURCE_BITS));
s->io[i].InUse = num;
+ *parent = res;
return 0;
}
@@ -775,6 +776,7 @@
continue;
*base = try;
s->io[i].InUse += num;
+ *parent = res;
return 0;
}
}
@@ -793,6 +795,7 @@
continue;
*base = try;
s->io[i].InUse += num;
+ *parent = res;
return 0;
}
}