Skip to content

Commit

Permalink
pcmcia: insert PCMCIA device resources into resource tree
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dominik Brodowski committed Aug 3, 2010
1 parent 8f677ea commit ad0c7be
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 34 deletions.
3 changes: 2 additions & 1 deletion drivers/pcmcia/cs_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions drivers/pcmcia/ds.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
74 changes: 46 additions & 28 deletions drivers/pcmcia/pcmcia_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */


/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion drivers/pcmcia/rsrc_iodyn.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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;
}
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/pcmcia/rsrc_mgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
5 changes: 4 additions & 1 deletion drivers/pcmcia/rsrc_nonstatic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}
}
Expand All @@ -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;
}
}
Expand Down

0 comments on commit ad0c7be

Please sign in to comment.