aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2009-10-18 13:48:39 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2009-11-08 12:06:53 -0500
commitaf757923a92e6e9dbfdb6b0264be14c564e1c466 (patch)
tree1b761e436301a5e73ab57e9f063213a3316542aa
parentaaa8cfdada648a6bae32f62df76cc60137a2b323 (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.c213
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
82static int ipwireless_ioprobe(struct pcmcia_device *p_dev, 82static 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
101static 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, 181exit3:
182 pcmcia_release_window(ipw->handle_attr_memory);
183exit2:
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; 191exit1:
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) { 197static 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
284exit4: 275exit:
285 pcmcia_disable_device(link);
286exit3:
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 }
294exit2:
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 }
301exit1:
302 pcmcia_disable_device(link); 288 pcmcia_disable_device(link);
303exit0:
304 return -1; 289 return -1;
305} 290}
306 291