diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 3 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 4 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 74 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_iodyn.c | 5 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_mgr.c | 3 | ||||
-rw-r--r-- | 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 37d38b5a1972..da055dc14d98 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 028c97353b92..55570d9e1e4c 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 01f8e56c8d2f..d48437f83acf 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 3b1dce2df26a..8510c35d2952 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 b433a7995651..4e80421fd908 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 c17a17d9f9b5..96f348b35fde 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; } } |