diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-03-20 08:10:47 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-05-10 04:23:19 -0400 |
commit | b19a7275dec4b470ea9abaae6129d21a0d75ab2f (patch) | |
tree | 9a3824270dee0494a198f969ae5b8c53e4950165 /drivers/pcmcia/rsrc_iodyn.c | |
parent | 49b1153adfe18a3cce7e70aa26c690f275917cd0 (diff) |
pcmcia: clarify alloc_io_space, move it to resource handlers
Clean up the alloc_io_space() function by moving most of it to
the actual resource_ops. This allows for a bit less re-directions.
Future cleanups will follow, and will make up for the code
duplication currently present between rsrc_iodyn and rsrc_nonstatic
(which are hardly ever built at the same time anyway, therefore no
increase in built size).
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia/rsrc_iodyn.c')
-rw-r--r-- | drivers/pcmcia/rsrc_iodyn.c | 92 |
1 files changed, 78 insertions, 14 deletions
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c index 3fa808b582f6..779137561580 100644 --- a/drivers/pcmcia/rsrc_iodyn.c +++ b/drivers/pcmcia/rsrc_iodyn.c | |||
@@ -56,15 +56,9 @@ static resource_size_t pcmcia_align(void *align_data, | |||
56 | } | 56 | } |
57 | 57 | ||
58 | 58 | ||
59 | static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start, | 59 | static struct resource *__iodyn_find_io_region(struct pcmcia_socket *s, |
60 | unsigned long r_end, struct pcmcia_socket *s) | 60 | unsigned long base, int num, |
61 | { | 61 | unsigned long align) |
62 | return adjust_resource(res, r_start, r_end - r_start + 1); | ||
63 | } | ||
64 | |||
65 | |||
66 | static struct resource *iodyn_find_io_region(unsigned long base, int num, | ||
67 | unsigned long align, struct pcmcia_socket *s) | ||
68 | { | 62 | { |
69 | struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, | 63 | struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO, |
70 | dev_name(&s->dev)); | 64 | dev_name(&s->dev)); |
@@ -72,9 +66,6 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num, | |||
72 | unsigned long min = base; | 66 | unsigned long min = base; |
73 | int ret; | 67 | int ret; |
74 | 68 | ||
75 | if (align == 0) | ||
76 | align = 0x10000; | ||
77 | |||
78 | data.mask = align - 1; | 69 | data.mask = align - 1; |
79 | data.offset = base & data.mask; | 70 | data.offset = base & data.mask; |
80 | 71 | ||
@@ -94,10 +85,83 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num, | |||
94 | return res; | 85 | return res; |
95 | } | 86 | } |
96 | 87 | ||
88 | static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr, | ||
89 | unsigned int *base, unsigned int num, | ||
90 | unsigned int align) | ||
91 | { | ||
92 | int i, ret = 0; | ||
93 | |||
94 | /* Check for an already-allocated window that must conflict with | ||
95 | * what was asked for. It is a hack because it does not catch all | ||
96 | * potential conflicts, just the most obvious ones. | ||
97 | */ | ||
98 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
99 | if (!s->io[i].res) | ||
100 | continue; | ||
101 | |||
102 | if (!*base) | ||
103 | continue; | ||
104 | |||
105 | if ((s->io[i].res->start & (align-1)) == *base) | ||
106 | return -EBUSY; | ||
107 | } | ||
108 | |||
109 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
110 | struct resource *res = s->io[i].res; | ||
111 | unsigned int try; | ||
112 | |||
113 | if (res && (res->flags & IORESOURCE_BITS) != | ||
114 | (attr & IORESOURCE_BITS)) | ||
115 | continue; | ||
116 | |||
117 | if (!res) { | ||
118 | if (align == 0) | ||
119 | align = 0x10000; | ||
120 | |||
121 | res = s->io[i].res = __iodyn_find_io_region(s, *base, | ||
122 | num, align); | ||
123 | if (!res) | ||
124 | return -EINVAL; | ||
125 | |||
126 | *base = res->start; | ||
127 | s->io[i].res->flags = | ||
128 | ((res->flags & ~IORESOURCE_BITS) | | ||
129 | (attr & IORESOURCE_BITS)); | ||
130 | s->io[i].InUse = num; | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | /* Try to extend top of window */ | ||
135 | try = res->end + 1; | ||
136 | if ((*base == 0) || (*base == try)) { | ||
137 | if (adjust_resource(s->io[i].res, res->start, | ||
138 | res->end - res->start + num + 1)) | ||
139 | continue; | ||
140 | *base = try; | ||
141 | s->io[i].InUse += num; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | /* Try to extend bottom of window */ | ||
146 | try = res->start - num; | ||
147 | if ((*base == 0) || (*base == try)) { | ||
148 | if (adjust_resource(s->io[i].res, | ||
149 | res->start - num, | ||
150 | res->end - res->start + num + 1)) | ||
151 | continue; | ||
152 | *base = try; | ||
153 | s->io[i].InUse += num; | ||
154 | return 0; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | return -EINVAL; | ||
159 | } | ||
160 | |||
161 | |||
97 | struct pccard_resource_ops pccard_iodyn_ops = { | 162 | struct pccard_resource_ops pccard_iodyn_ops = { |
98 | .validate_mem = NULL, | 163 | .validate_mem = NULL, |
99 | .adjust_io_region = iodyn_adjust_io_region, | 164 | .find_io = iodyn_find_io, |
100 | .find_io = iodyn_find_io_region, | ||
101 | .find_mem = NULL, | 165 | .find_mem = NULL, |
102 | .add_io = NULL, | 166 | .add_io = NULL, |
103 | .add_mem = NULL, | 167 | .add_mem = NULL, |