diff options
| -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 { | |||
| 62 | unsigned int attr, | 62 | unsigned int attr, |
| 63 | unsigned int *base, | 63 | unsigned int *base, |
| 64 | unsigned int num, | 64 | unsigned int num, |
| 65 | unsigned int align); | 65 | unsigned int align, |
| 66 | struct resource **parent); | ||
| 66 | struct resource* (*find_mem) (unsigned long base, unsigned long num, | 67 | struct resource* (*find_mem) (unsigned long base, unsigned long num, |
| 67 | unsigned long align, int low, | 68 | unsigned long align, int low, |
| 68 | struct pcmcia_socket *s); | 69 | 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, | |||
| 553 | p_dev->function_config = c; | 553 | p_dev->function_config = c; |
| 554 | kref_init(&c->ref); | 554 | kref_init(&c->ref); |
| 555 | for (i = 0; i < MAX_IO_WIN; i++) { | 555 | for (i = 0; i < MAX_IO_WIN; i++) { |
| 556 | c->io[i].name = dev_name(&p_dev->dev); | 556 | c->io[i].name = p_dev->devname; |
| 557 | c->io[i].flags = IORESOURCE_IO; | 557 | c->io[i].flags = IORESOURCE_IO; |
| 558 | } | 558 | } |
| 559 | for (i = 0; i< MAX_WIN; i++) { | 559 | for (i = 0; i< MAX_WIN; i++) { |
| 560 | c->mem[i].name = dev_name(&p_dev->dev); | 560 | c->mem[i].name = p_dev->devname; |
| 561 | c->mem[i].flags = IORESOURCE_MEM; | 561 | c->mem[i].flags = IORESOURCE_MEM; |
| 562 | } | 562 | } |
| 563 | } | 563 | } |
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, | |||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | 58 | ||
| 59 | static void release_io_space(struct pcmcia_socket *s, struct resource *res) | ||
| 60 | { | ||
| 61 | resource_size_t num = resource_size(res); | ||
| 62 | int i; | ||
| 63 | |||
| 64 | dev_dbg(&s->dev, "release_io_space for %pR\n", res); | ||
| 65 | |||
| 66 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
| 67 | if (!s->io[i].res) | ||
| 68 | continue; | ||
| 69 | if ((s->io[i].res->start <= res->start) && | ||
| 70 | (s->io[i].res->end >= res->end)) { | ||
| 71 | s->io[i].InUse -= num; | ||
| 72 | if (res->parent) | ||
| 73 | release_resource(res); | ||
| 74 | res->start = res->end = 0; | ||
| 75 | res->flags = IORESOURCE_IO; | ||
| 76 | /* Free the window if no one else is using it */ | ||
| 77 | if (s->io[i].InUse == 0) { | ||
| 78 | release_resource(s->io[i].res); | ||
| 79 | kfree(s->io[i].res); | ||
| 80 | s->io[i].res = NULL; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } /* release_io_space */ | ||
| 85 | |||
| 59 | /** alloc_io_space | 86 | /** alloc_io_space |
| 60 | * | 87 | * |
| 61 | * Special stuff for managing IO windows, because they are scarce | 88 | * 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, | |||
| 87 | align = 0; | 114 | align = 0; |
| 88 | } | 115 | } |
| 89 | 116 | ||
| 90 | ret = s->resource_ops->find_io(s, res->flags, &base, num, align); | 117 | ret = s->resource_ops->find_io(s, res->flags, &base, num, align, |
| 118 | &res->parent); | ||
| 91 | if (ret) { | 119 | if (ret) { |
| 92 | dev_dbg(&s->dev, "alloc_io_space request returned %d", ret); | 120 | dev_dbg(&s->dev, "alloc_io_space request failed (%d)\n", ret); |
| 93 | return -EINVAL; | 121 | return -EINVAL; |
| 94 | } | 122 | } |
| 95 | 123 | ||
| 96 | res->start = base; | 124 | res->start = base; |
| 97 | res->end = res->start + num - 1; | 125 | res->end = res->start + num - 1; |
| 98 | dev_dbg(&s->dev, "alloc_io_space request returned %pR, %d\n", res, ret); | ||
| 99 | return 0; | ||
| 100 | } /* alloc_io_space */ | ||
| 101 | 126 | ||
| 102 | 127 | if (res->parent) { | |
| 103 | static void release_io_space(struct pcmcia_socket *s, struct resource *res) | 128 | ret = request_resource(res->parent, res); |
| 104 | { | 129 | if (ret) { |
| 105 | resource_size_t num = resource_size(res); | 130 | dev_warn(&s->dev, |
| 106 | int i; | 131 | "request_resource %pR failed: %d\n", res, ret); |
| 107 | 132 | res->parent = NULL; | |
| 108 | dev_dbg(&s->dev, "release_io_space for %pR\n", res); | 133 | release_io_space(s, res); |
| 109 | |||
| 110 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
| 111 | if (!s->io[i].res) | ||
| 112 | continue; | ||
| 113 | if ((s->io[i].res->start <= res->start) && | ||
| 114 | (s->io[i].res->end >= res->end)) { | ||
| 115 | s->io[i].InUse -= num; | ||
| 116 | res->start = res->end = 0; | ||
| 117 | res->flags = IORESOURCE_IO; | ||
| 118 | /* Free the window if no one else is using it */ | ||
| 119 | if (s->io[i].InUse == 0) { | ||
| 120 | release_resource(s->io[i].res); | ||
| 121 | kfree(s->io[i].res); | ||
| 122 | s->io[i].res = NULL; | ||
| 123 | } | ||
| 124 | } | 134 | } |
| 125 | } | 135 | } |
| 126 | } /* release_io_space */ | 136 | dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res); |
| 137 | return ret; | ||
| 138 | } /* alloc_io_space */ | ||
| 127 | 139 | ||
| 128 | 140 | ||
| 129 | /** | 141 | /** |
| @@ -401,6 +413,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) | |||
| 401 | 413 | ||
| 402 | /* Release system memory */ | 414 | /* Release system memory */ |
| 403 | if (win->res) { | 415 | if (win->res) { |
| 416 | release_resource(res); | ||
| 404 | release_resource(win->res); | 417 | release_resource(win->res); |
| 405 | kfree(win->res); | 418 | kfree(win->res); |
| 406 | win->res = NULL; | 419 | win->res = NULL; |
| @@ -853,6 +866,11 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
| 853 | res->end = req->Base + req->Size - 1; | 866 | res->end = req->Base + req->Size - 1; |
| 854 | res->flags &= ~IORESOURCE_BITS; | 867 | res->flags &= ~IORESOURCE_BITS; |
| 855 | res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2); | 868 | res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2); |
| 869 | res->flags |= IORESOURCE_MEM; | ||
| 870 | res->parent = win->res; | ||
| 871 | if (win->res) | ||
| 872 | request_resource(&iomem_resource, res); | ||
| 873 | |||
| 856 | dev_dbg(&s->dev, "request_window results in %pR\n", res); | 874 | dev_dbg(&s->dev, "request_window results in %pR\n", res); |
| 857 | 875 | ||
| 858 | mutex_unlock(&s->ops_mutex); | 876 | 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, | |||
| 87 | 87 | ||
| 88 | static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | 88 | static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, |
| 89 | unsigned int *base, unsigned int num, | 89 | unsigned int *base, unsigned int num, |
| 90 | unsigned int align) | 90 | unsigned int align, struct resource **parent) |
| 91 | { | 91 | { |
| 92 | int i, ret = 0; | 92 | int i, ret = 0; |
| 93 | 93 | ||
| @@ -128,6 +128,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
| 128 | ((res->flags & ~IORESOURCE_BITS) | | 128 | ((res->flags & ~IORESOURCE_BITS) | |
| 129 | (attr & IORESOURCE_BITS)); | 129 | (attr & IORESOURCE_BITS)); |
| 130 | s->io[i].InUse = num; | 130 | s->io[i].InUse = num; |
| 131 | *parent = res; | ||
| 131 | return 0; | 132 | return 0; |
| 132 | } | 133 | } |
| 133 | 134 | ||
| @@ -139,6 +140,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
| 139 | continue; | 140 | continue; |
| 140 | *base = try; | 141 | *base = try; |
| 141 | s->io[i].InUse += num; | 142 | s->io[i].InUse += num; |
| 143 | *parent = res; | ||
| 142 | return 0; | 144 | return 0; |
| 143 | } | 145 | } |
| 144 | 146 | ||
| @@ -151,6 +153,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
| 151 | continue; | 153 | continue; |
| 152 | *base = try; | 154 | *base = try; |
| 153 | s->io[i].InUse += num; | 155 | s->io[i].InUse += num; |
| 156 | *parent = res; | ||
| 154 | return 0; | 157 | return 0; |
| 155 | } | 158 | } |
| 156 | } | 159 | } |
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, | |||
| 47 | 47 | ||
| 48 | static int static_find_io(struct pcmcia_socket *s, unsigned int attr, | 48 | static int static_find_io(struct pcmcia_socket *s, unsigned int attr, |
| 49 | unsigned int *base, unsigned int num, | 49 | unsigned int *base, unsigned int num, |
| 50 | unsigned int align) | 50 | unsigned int align, struct resource **parent) |
| 51 | { | 51 | { |
| 52 | if (!s->io_offset) | 52 | if (!s->io_offset) |
| 53 | return -EINVAL; | 53 | return -EINVAL; |
| 54 | *base = s->io_offset | (*base & 0x0fff); | 54 | *base = s->io_offset | (*base & 0x0fff); |
| 55 | *parent = NULL; | ||
| 55 | 56 | ||
| 56 | return 0; | 57 | return 0; |
| 57 | } | 58 | } |
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, | |||
| 718 | 718 | ||
| 719 | static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | 719 | static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, |
| 720 | unsigned int *base, unsigned int num, | 720 | unsigned int *base, unsigned int num, |
| 721 | unsigned int align) | 721 | unsigned int align, struct resource **parent) |
| 722 | { | 722 | { |
| 723 | int i, ret = 0; | 723 | int i, ret = 0; |
| 724 | 724 | ||
| @@ -760,6 +760,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
| 760 | ((res->flags & ~IORESOURCE_BITS) | | 760 | ((res->flags & ~IORESOURCE_BITS) | |
| 761 | (attr & IORESOURCE_BITS)); | 761 | (attr & IORESOURCE_BITS)); |
| 762 | s->io[i].InUse = num; | 762 | s->io[i].InUse = num; |
| 763 | *parent = res; | ||
| 763 | return 0; | 764 | return 0; |
| 764 | } | 765 | } |
| 765 | 766 | ||
| @@ -775,6 +776,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
| 775 | continue; | 776 | continue; |
| 776 | *base = try; | 777 | *base = try; |
| 777 | s->io[i].InUse += num; | 778 | s->io[i].InUse += num; |
| 779 | *parent = res; | ||
| 778 | return 0; | 780 | return 0; |
| 779 | } | 781 | } |
| 780 | } | 782 | } |
| @@ -793,6 +795,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, | |||
| 793 | continue; | 795 | continue; |
| 794 | *base = try; | 796 | *base = try; |
| 795 | s->io[i].InUse += num; | 797 | s->io[i].InUse += num; |
| 798 | *parent = res; | ||
| 796 | return 0; | 799 | return 0; |
| 797 | } | 800 | } |
| 798 | } | 801 | } |
