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>
This commit is contained in:
@@ -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);
|
||||
|
Reference in New Issue
Block a user