aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pcmcia/cs_internal.h3
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/pcmcia/pcmcia_resource.c74
-rw-r--r--drivers/pcmcia/rsrc_iodyn.c5
-rw-r--r--drivers/pcmcia/rsrc_mgr.c3
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c5
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
59static 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) {
103static 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
88static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, 88static 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
48static int static_find_io(struct pcmcia_socket *s, unsigned int attr, 48static 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
719static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr, 719static 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 }