diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2009-10-18 13:48:39 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2009-11-08 12:06:53 -0500 |
commit | af757923a92e6e9dbfdb6b0264be14c564e1c466 (patch) | |
tree | 1b761e436301a5e73ab57e9f063213a3316542aa | |
parent | aaa8cfdada648a6bae32f62df76cc60137a2b323 (diff) |
ipwireless: make more use of pcmcia_loop_config()
Within the pcmcia_loop_config() callback, we already have all
tuple data available we need. Also add a fix to release the IO
resource (at least within pcmcia_loop_config() error path).
CC: Jiri Kosina <jkosina@suse.cz>
CC: David Sterba <dsterba@suse.cz>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r-- | drivers/char/pcmcia/ipwireless/main.c | 213 |
1 files changed, 99 insertions, 114 deletions
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 263a18f381b3..0f4674959917 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c | |||
@@ -79,12 +79,18 @@ static void signalled_reboot_callback(void *callback_data) | |||
79 | schedule_work(&ipw->work_reboot); | 79 | schedule_work(&ipw->work_reboot); |
80 | } | 80 | } |
81 | 81 | ||
82 | static int ipwireless_ioprobe(struct pcmcia_device *p_dev, | 82 | static int ipwireless_probe(struct pcmcia_device *p_dev, |
83 | cistpl_cftable_entry_t *cfg, | 83 | cistpl_cftable_entry_t *cfg, |
84 | cistpl_cftable_entry_t *dflt, | 84 | cistpl_cftable_entry_t *dflt, |
85 | unsigned int vcc, | 85 | unsigned int vcc, |
86 | void *priv_data) | 86 | void *priv_data) |
87 | { | 87 | { |
88 | struct ipw_dev *ipw = priv_data; | ||
89 | struct resource *io_resource; | ||
90 | memreq_t memreq_attr_memory; | ||
91 | memreq_t memreq_common_memory; | ||
92 | int ret; | ||
93 | |||
88 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | 94 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; |
89 | p_dev->io.BasePort1 = cfg->io.win[0].base; | 95 | p_dev->io.BasePort1 = cfg->io.win[0].base; |
90 | p_dev->io.NumPorts1 = cfg->io.win[0].len; | 96 | p_dev->io.NumPorts1 = cfg->io.win[0].len; |
@@ -95,133 +101,118 @@ static int ipwireless_ioprobe(struct pcmcia_device *p_dev, | |||
95 | /* 0x40 causes it to generate level mode interrupts. */ | 101 | /* 0x40 causes it to generate level mode interrupts. */ |
96 | /* 0x04 enables IREQ pin. */ | 102 | /* 0x04 enables IREQ pin. */ |
97 | p_dev->conf.ConfigIndex = cfg->index | 0x44; | 103 | p_dev->conf.ConfigIndex = cfg->index | 0x44; |
98 | return pcmcia_request_io(p_dev, &p_dev->io); | 104 | ret = pcmcia_request_io(p_dev, &p_dev->io); |
99 | } | 105 | if (ret) |
106 | return ret; | ||
100 | 107 | ||
101 | static int config_ipwireless(struct ipw_dev *ipw) | 108 | io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1, |
102 | { | 109 | IPWIRELESS_PCCARD_NAME); |
103 | struct pcmcia_device *link = ipw->link; | ||
104 | int ret = 0; | ||
105 | tuple_t tuple; | ||
106 | unsigned short buf[64]; | ||
107 | cisparse_t parse; | ||
108 | memreq_t memreq_attr_memory; | ||
109 | memreq_t memreq_common_memory; | ||
110 | 110 | ||
111 | ipw->is_v2_card = 0; | 111 | if (cfg->mem.nwin == 0) |
112 | return 0; | ||
112 | 113 | ||
113 | tuple.Attributes = 0; | 114 | ipw->request_common_memory.Attributes = |
114 | tuple.TupleData = (cisdata_t *) buf; | 115 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; |
115 | tuple.TupleDataMax = sizeof(buf); | 116 | ipw->request_common_memory.Base = cfg->mem.win[0].host_addr; |
116 | tuple.TupleOffset = 0; | 117 | ipw->request_common_memory.Size = cfg->mem.win[0].len; |
118 | if (ipw->request_common_memory.Size < 0x1000) | ||
119 | ipw->request_common_memory.Size = 0x1000; | ||
120 | ipw->request_common_memory.AccessSpeed = 0; | ||
121 | |||
122 | ret = pcmcia_request_window(&p_dev, &ipw->request_common_memory, | ||
123 | &ipw->handle_common_memory); | ||
117 | 124 | ||
118 | ret = pcmcia_loop_config(link, ipwireless_ioprobe, NULL); | ||
119 | if (ret != 0) { | 125 | if (ret != 0) { |
120 | cs_error(link, RequestIO, ret); | 126 | cs_error(p_dev, RequestWindow, ret); |
121 | goto exit0; | 127 | goto exit1; |
122 | } | 128 | } |
123 | 129 | ||
124 | link->conf.Attributes = CONF_ENABLE_IRQ; | 130 | memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr; |
125 | link->conf.IntType = INT_MEMORY_AND_IO; | 131 | memreq_common_memory.Page = 0; |
126 | |||
127 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; | ||
128 | link->irq.Handler = ipwireless_interrupt; | ||
129 | link->irq.Instance = ipw->hardware; | ||
130 | 132 | ||
131 | request_region(link->io.BasePort1, link->io.NumPorts1, | 133 | ret = pcmcia_map_mem_page(ipw->handle_common_memory, |
132 | IPWIRELESS_PCCARD_NAME); | 134 | &memreq_common_memory); |
133 | |||
134 | /* memory settings */ | ||
135 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
136 | 135 | ||
137 | ret = pcmcia_get_first_tuple(link, &tuple); | ||
138 | if (ret != 0) { | 136 | if (ret != 0) { |
139 | cs_error(link, GetFirstTuple, ret); | 137 | cs_error(p_dev, MapMemPage, ret); |
140 | goto exit1; | 138 | goto exit2; |
141 | } | 139 | } |
142 | 140 | ||
143 | ret = pcmcia_get_tuple_data(link, &tuple); | 141 | ipw->is_v2_card = cfg->mem.win[0].len == 0x100; |
144 | 142 | ||
145 | if (ret != 0) { | 143 | ipw->common_memory = ioremap(ipw->request_common_memory.Base, |
146 | cs_error(link, GetTupleData, ret); | 144 | ipw->request_common_memory.Size); |
147 | goto exit1; | 145 | request_mem_region(ipw->request_common_memory.Base, |
148 | } | 146 | ipw->request_common_memory.Size, |
147 | IPWIRELESS_PCCARD_NAME); | ||
148 | |||
149 | ipw->request_attr_memory.Attributes = | ||
150 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; | ||
151 | ipw->request_attr_memory.Base = 0; | ||
152 | ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ | ||
153 | ipw->request_attr_memory.AccessSpeed = 0; | ||
149 | 154 | ||
150 | ret = pcmcia_parse_tuple(&tuple, &parse); | 155 | ret = pcmcia_request_window(&p_dev, &ipw->request_attr_memory, |
156 | &ipw->handle_attr_memory); | ||
151 | 157 | ||
152 | if (ret != 0) { | 158 | if (ret != 0) { |
153 | cs_error(link, ParseTuple, ret); | 159 | cs_error(p_dev, RequestWindow, ret); |
154 | goto exit1; | 160 | goto exit2; |
155 | } | 161 | } |
156 | 162 | ||
157 | if (parse.cftable_entry.mem.nwin > 0) { | 163 | memreq_attr_memory.CardOffset = 0; |
158 | ipw->request_common_memory.Attributes = | 164 | memreq_attr_memory.Page = 0; |
159 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; | ||
160 | ipw->request_common_memory.Base = | ||
161 | parse.cftable_entry.mem.win[0].host_addr; | ||
162 | ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; | ||
163 | if (ipw->request_common_memory.Size < 0x1000) | ||
164 | ipw->request_common_memory.Size = 0x1000; | ||
165 | ipw->request_common_memory.AccessSpeed = 0; | ||
166 | |||
167 | ret = pcmcia_request_window(&link, &ipw->request_common_memory, | ||
168 | &ipw->handle_common_memory); | ||
169 | |||
170 | if (ret != 0) { | ||
171 | cs_error(link, RequestWindow, ret); | ||
172 | goto exit1; | ||
173 | } | ||
174 | 165 | ||
175 | memreq_common_memory.CardOffset = | 166 | ret = pcmcia_map_mem_page(ipw->handle_attr_memory, |
176 | parse.cftable_entry.mem.win[0].card_addr; | 167 | &memreq_attr_memory); |
177 | memreq_common_memory.Page = 0; | ||
178 | 168 | ||
179 | ret = pcmcia_map_mem_page(ipw->handle_common_memory, | 169 | if (ret != 0) { |
180 | &memreq_common_memory); | 170 | cs_error(p_dev, MapMemPage, ret); |
171 | goto exit3; | ||
172 | } | ||
181 | 173 | ||
182 | if (ret != 0) { | 174 | ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, |
183 | cs_error(link, MapMemPage, ret); | 175 | ipw->request_attr_memory.Size); |
184 | goto exit1; | 176 | request_mem_region(ipw->request_attr_memory.Base, |
185 | } | 177 | ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME); |
186 | 178 | ||
187 | ipw->is_v2_card = | 179 | return 0; |
188 | parse.cftable_entry.mem.win[0].len == 0x100; | ||
189 | 180 | ||
190 | ipw->common_memory = ioremap(ipw->request_common_memory.Base, | 181 | exit3: |
182 | pcmcia_release_window(ipw->handle_attr_memory); | ||
183 | exit2: | ||
184 | if (ipw->common_memory) { | ||
185 | release_mem_region(ipw->request_common_memory.Base, | ||
191 | ipw->request_common_memory.Size); | 186 | ipw->request_common_memory.Size); |
192 | request_mem_region(ipw->request_common_memory.Base, | 187 | iounmap(ipw->common_memory); |
193 | ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); | 188 | pcmcia_release_window(ipw->handle_common_memory); |
194 | 189 | } else | |
195 | ipw->request_attr_memory.Attributes = | 190 | pcmcia_release_window(ipw->handle_common_memory); |
196 | WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; | 191 | exit1: |
197 | ipw->request_attr_memory.Base = 0; | 192 | release_resource(io_resource); |
198 | ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ | 193 | pcmcia_disable_device(p_dev); |
199 | ipw->request_attr_memory.AccessSpeed = 0; | 194 | return -1; |
200 | 195 | } | |
201 | ret = pcmcia_request_window(&link, &ipw->request_attr_memory, | ||
202 | &ipw->handle_attr_memory); | ||
203 | 196 | ||
204 | if (ret != 0) { | 197 | static int config_ipwireless(struct ipw_dev *ipw) |
205 | cs_error(link, RequestWindow, ret); | 198 | { |
206 | goto exit2; | 199 | struct pcmcia_device *link = ipw->link; |
207 | } | 200 | int ret = 0; |
208 | 201 | ||
209 | memreq_attr_memory.CardOffset = 0; | 202 | ipw->is_v2_card = 0; |
210 | memreq_attr_memory.Page = 0; | ||
211 | 203 | ||
212 | ret = pcmcia_map_mem_page(ipw->handle_attr_memory, | 204 | ret = pcmcia_loop_config(link, ipwireless_probe, ipw); |
213 | &memreq_attr_memory); | 205 | if (ret != 0) { |
206 | cs_error(link, RequestIO, ret); | ||
207 | return ret; | ||
208 | } | ||
214 | 209 | ||
215 | if (ret != 0) { | 210 | link->conf.Attributes = CONF_ENABLE_IRQ; |
216 | cs_error(link, MapMemPage, ret); | 211 | link->conf.IntType = INT_MEMORY_AND_IO; |
217 | goto exit2; | ||
218 | } | ||
219 | 212 | ||
220 | ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, | 213 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; |
221 | ipw->request_attr_memory.Size); | 214 | link->irq.Handler = ipwireless_interrupt; |
222 | request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, | 215 | link->irq.Instance = ipw->hardware; |
223 | IPWIRELESS_PCCARD_NAME); | ||
224 | } | ||
225 | 216 | ||
226 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); | 217 | INIT_WORK(&ipw->work_reboot, signalled_reboot_work); |
227 | 218 | ||
@@ -234,7 +225,7 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
234 | 225 | ||
235 | if (ret != 0) { | 226 | if (ret != 0) { |
236 | cs_error(link, RequestIRQ, ret); | 227 | cs_error(link, RequestIRQ, ret); |
237 | goto exit3; | 228 | goto exit; |
238 | } | 229 | } |
239 | 230 | ||
240 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", | 231 | printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", |
@@ -257,12 +248,12 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
257 | 248 | ||
258 | ipw->network = ipwireless_network_create(ipw->hardware); | 249 | ipw->network = ipwireless_network_create(ipw->hardware); |
259 | if (!ipw->network) | 250 | if (!ipw->network) |
260 | goto exit3; | 251 | goto exit; |
261 | 252 | ||
262 | ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, | 253 | ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, |
263 | ipw->nodes); | 254 | ipw->nodes); |
264 | if (!ipw->tty) | 255 | if (!ipw->tty) |
265 | goto exit3; | 256 | goto exit; |
266 | 257 | ||
267 | ipwireless_init_hardware_v2_v3(ipw->hardware); | 258 | ipwireless_init_hardware_v2_v3(ipw->hardware); |
268 | 259 | ||
@@ -274,33 +265,27 @@ static int config_ipwireless(struct ipw_dev *ipw) | |||
274 | 265 | ||
275 | if (ret != 0) { | 266 | if (ret != 0) { |
276 | cs_error(link, RequestConfiguration, ret); | 267 | cs_error(link, RequestConfiguration, ret); |
277 | goto exit4; | 268 | goto exit; |
278 | } | 269 | } |
279 | 270 | ||
280 | link->dev_node = &ipw->nodes[0]; | 271 | link->dev_node = &ipw->nodes[0]; |
281 | 272 | ||
282 | return 0; | 273 | return 0; |
283 | 274 | ||
284 | exit4: | 275 | exit: |
285 | pcmcia_disable_device(link); | ||
286 | exit3: | ||
287 | if (ipw->attr_memory) { | 276 | if (ipw->attr_memory) { |
288 | release_mem_region(ipw->request_attr_memory.Base, | 277 | release_mem_region(ipw->request_attr_memory.Base, |
289 | ipw->request_attr_memory.Size); | 278 | ipw->request_attr_memory.Size); |
290 | iounmap(ipw->attr_memory); | 279 | iounmap(ipw->attr_memory); |
291 | pcmcia_release_window(ipw->handle_attr_memory); | 280 | pcmcia_release_window(ipw->handle_attr_memory); |
292 | pcmcia_disable_device(link); | ||
293 | } | 281 | } |
294 | exit2: | ||
295 | if (ipw->common_memory) { | 282 | if (ipw->common_memory) { |
296 | release_mem_region(ipw->request_common_memory.Base, | 283 | release_mem_region(ipw->request_common_memory.Base, |
297 | ipw->request_common_memory.Size); | 284 | ipw->request_common_memory.Size); |
298 | iounmap(ipw->common_memory); | 285 | iounmap(ipw->common_memory); |
299 | pcmcia_release_window(ipw->handle_common_memory); | 286 | pcmcia_release_window(ipw->handle_common_memory); |
300 | } | 287 | } |
301 | exit1: | ||
302 | pcmcia_disable_device(link); | 288 | pcmcia_disable_device(link); |
303 | exit0: | ||
304 | return -1; | 289 | return -1; |
305 | } | 290 | } |
306 | 291 | ||