diff options
Diffstat (limited to 'drivers/net/wireless/orinoco_cs.c')
-rw-r--r-- | drivers/net/wireless/orinoco_cs.c | 187 |
1 files changed, 74 insertions, 113 deletions
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index ec6f2a48895b..434f7d7ad841 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -49,7 +49,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket | |||
49 | /* PCMCIA specific device information (goes in the card field of | 49 | /* PCMCIA specific device information (goes in the card field of |
50 | * struct orinoco_private */ | 50 | * struct orinoco_private */ |
51 | struct orinoco_pccard { | 51 | struct orinoco_pccard { |
52 | dev_link_t link; | 52 | struct pcmcia_device *p_dev; |
53 | dev_node_t node; | 53 | dev_node_t node; |
54 | 54 | ||
55 | /* Used to handle hard reset */ | 55 | /* Used to handle hard reset */ |
@@ -63,8 +63,8 @@ struct orinoco_pccard { | |||
63 | /* Function prototypes */ | 63 | /* Function prototypes */ |
64 | /********************************************************************/ | 64 | /********************************************************************/ |
65 | 65 | ||
66 | static void orinoco_cs_config(dev_link_t *link); | 66 | static int orinoco_cs_config(struct pcmcia_device *link); |
67 | static void orinoco_cs_release(dev_link_t *link); | 67 | static void orinoco_cs_release(struct pcmcia_device *link); |
68 | static void orinoco_cs_detach(struct pcmcia_device *p_dev); | 68 | static void orinoco_cs_detach(struct pcmcia_device *p_dev); |
69 | 69 | ||
70 | /********************************************************************/ | 70 | /********************************************************************/ |
@@ -75,13 +75,13 @@ static int | |||
75 | orinoco_cs_hard_reset(struct orinoco_private *priv) | 75 | orinoco_cs_hard_reset(struct orinoco_private *priv) |
76 | { | 76 | { |
77 | struct orinoco_pccard *card = priv->card; | 77 | struct orinoco_pccard *card = priv->card; |
78 | dev_link_t *link = &card->link; | 78 | struct pcmcia_device *link = card->p_dev; |
79 | int err; | 79 | int err; |
80 | 80 | ||
81 | /* We need atomic ops here, because we're not holding the lock */ | 81 | /* We need atomic ops here, because we're not holding the lock */ |
82 | set_bit(0, &card->hard_reset_in_progress); | 82 | set_bit(0, &card->hard_reset_in_progress); |
83 | 83 | ||
84 | err = pcmcia_reset_card(link->handle, NULL); | 84 | err = pcmcia_reset_card(link, NULL); |
85 | if (err) | 85 | if (err) |
86 | return err; | 86 | return err; |
87 | 87 | ||
@@ -104,12 +104,11 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) | |||
104 | * configure the card at this point -- we wait until we receive a card | 104 | * configure the card at this point -- we wait until we receive a card |
105 | * insertion event. */ | 105 | * insertion event. */ |
106 | static int | 106 | static int |
107 | orinoco_cs_attach(struct pcmcia_device *p_dev) | 107 | orinoco_cs_probe(struct pcmcia_device *link) |
108 | { | 108 | { |
109 | struct net_device *dev; | 109 | struct net_device *dev; |
110 | struct orinoco_private *priv; | 110 | struct orinoco_private *priv; |
111 | struct orinoco_pccard *card; | 111 | struct orinoco_pccard *card; |
112 | dev_link_t *link; | ||
113 | 112 | ||
114 | dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); | 113 | dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); |
115 | if (! dev) | 114 | if (! dev) |
@@ -118,7 +117,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) | |||
118 | card = priv->card; | 117 | card = priv->card; |
119 | 118 | ||
120 | /* Link both structures together */ | 119 | /* Link both structures together */ |
121 | link = &card->link; | 120 | card->p_dev = link; |
122 | link->priv = dev; | 121 | link->priv = dev; |
123 | 122 | ||
124 | /* Interrupt setup */ | 123 | /* Interrupt setup */ |
@@ -135,16 +134,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) | |||
135 | link->conf.Attributes = 0; | 134 | link->conf.Attributes = 0; |
136 | link->conf.IntType = INT_MEMORY_AND_IO; | 135 | link->conf.IntType = INT_MEMORY_AND_IO; |
137 | 136 | ||
138 | /* Register with Card Services */ | 137 | return orinoco_cs_config(link); |
139 | link->next = NULL; | ||
140 | |||
141 | link->handle = p_dev; | ||
142 | p_dev->instance = link; | ||
143 | |||
144 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
145 | orinoco_cs_config(link); | ||
146 | |||
147 | return 0; | ||
148 | } /* orinoco_cs_attach */ | 138 | } /* orinoco_cs_attach */ |
149 | 139 | ||
150 | /* | 140 | /* |
@@ -153,16 +143,14 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) | |||
153 | * are freed. Otherwise, the structures will be freed when the device | 143 | * are freed. Otherwise, the structures will be freed when the device |
154 | * is released. | 144 | * is released. |
155 | */ | 145 | */ |
156 | static void orinoco_cs_detach(struct pcmcia_device *p_dev) | 146 | static void orinoco_cs_detach(struct pcmcia_device *link) |
157 | { | 147 | { |
158 | dev_link_t *link = dev_to_instance(p_dev); | ||
159 | struct net_device *dev = link->priv; | 148 | struct net_device *dev = link->priv; |
160 | 149 | ||
161 | if (link->state & DEV_CONFIG) | 150 | orinoco_cs_release(link); |
162 | orinoco_cs_release(link); | ||
163 | 151 | ||
164 | DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); | 152 | DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); |
165 | if (link->dev) { | 153 | if (link->dev_node) { |
166 | DEBUG(0, PFX "About to unregister net device %p\n", | 154 | DEBUG(0, PFX "About to unregister net device %p\n", |
167 | dev); | 155 | dev); |
168 | unregister_netdev(dev); | 156 | unregister_netdev(dev); |
@@ -180,11 +168,10 @@ static void orinoco_cs_detach(struct pcmcia_device *p_dev) | |||
180 | last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ | 168 | last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ |
181 | } while (0) | 169 | } while (0) |
182 | 170 | ||
183 | static void | 171 | static int |
184 | orinoco_cs_config(dev_link_t *link) | 172 | orinoco_cs_config(struct pcmcia_device *link) |
185 | { | 173 | { |
186 | struct net_device *dev = link->priv; | 174 | struct net_device *dev = link->priv; |
187 | client_handle_t handle = link->handle; | ||
188 | struct orinoco_private *priv = netdev_priv(dev); | 175 | struct orinoco_private *priv = netdev_priv(dev); |
189 | struct orinoco_pccard *card = priv->card; | 176 | struct orinoco_pccard *card = priv->card; |
190 | hermes_t *hw = &priv->hw; | 177 | hermes_t *hw = &priv->hw; |
@@ -196,7 +183,7 @@ orinoco_cs_config(dev_link_t *link) | |||
196 | cisparse_t parse; | 183 | cisparse_t parse; |
197 | void __iomem *mem; | 184 | void __iomem *mem; |
198 | 185 | ||
199 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); | 186 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); |
200 | 187 | ||
201 | /* | 188 | /* |
202 | * This reads the card's CONFIG tuple to find its | 189 | * This reads the card's CONFIG tuple to find its |
@@ -207,19 +194,15 @@ orinoco_cs_config(dev_link_t *link) | |||
207 | tuple.TupleData = buf; | 194 | tuple.TupleData = buf; |
208 | tuple.TupleDataMax = sizeof(buf); | 195 | tuple.TupleDataMax = sizeof(buf); |
209 | tuple.TupleOffset = 0; | 196 | tuple.TupleOffset = 0; |
210 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 197 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
211 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 198 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
212 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 199 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
213 | link->conf.ConfigBase = parse.config.base; | 200 | link->conf.ConfigBase = parse.config.base; |
214 | link->conf.Present = parse.config.rmask[0]; | 201 | link->conf.Present = parse.config.rmask[0]; |
215 | 202 | ||
216 | /* Configure card */ | ||
217 | link->state |= DEV_CONFIG; | ||
218 | |||
219 | /* Look up the current Vcc */ | 203 | /* Look up the current Vcc */ |
220 | CS_CHECK(GetConfigurationInfo, | 204 | CS_CHECK(GetConfigurationInfo, |
221 | pcmcia_get_configuration_info(handle, &conf)); | 205 | pcmcia_get_configuration_info(link, &conf)); |
222 | link->conf.Vcc = conf.Vcc; | ||
223 | 206 | ||
224 | /* | 207 | /* |
225 | * In this loop, we scan the CIS for configuration table | 208 | * In this loop, we scan the CIS for configuration table |
@@ -236,13 +219,13 @@ orinoco_cs_config(dev_link_t *link) | |||
236 | * implementation-defined details. | 219 | * implementation-defined details. |
237 | */ | 220 | */ |
238 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 221 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
239 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 222 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
240 | while (1) { | 223 | while (1) { |
241 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 224 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
242 | cistpl_cftable_entry_t dflt = { .index = 0 }; | 225 | cistpl_cftable_entry_t dflt = { .index = 0 }; |
243 | 226 | ||
244 | if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) | 227 | if ( (pcmcia_get_tuple_data(link, &tuple) != 0) |
245 | || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) | 228 | || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) |
246 | goto next_entry; | 229 | goto next_entry; |
247 | 230 | ||
248 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | 231 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) |
@@ -274,10 +257,10 @@ orinoco_cs_config(dev_link_t *link) | |||
274 | } | 257 | } |
275 | 258 | ||
276 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 259 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) |
277 | link->conf.Vpp1 = link->conf.Vpp2 = | 260 | link->conf.Vpp = |
278 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 261 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; |
279 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | 262 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) |
280 | link->conf.Vpp1 = link->conf.Vpp2 = | 263 | link->conf.Vpp = |
281 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | 264 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; |
282 | 265 | ||
283 | /* Do we need to allocate an interrupt? */ | 266 | /* Do we need to allocate an interrupt? */ |
@@ -307,7 +290,7 @@ orinoco_cs_config(dev_link_t *link) | |||
307 | } | 290 | } |
308 | 291 | ||
309 | /* This reserves IO space but doesn't actually enable it */ | 292 | /* This reserves IO space but doesn't actually enable it */ |
310 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 293 | if (pcmcia_request_io(link, &link->io) != 0) |
311 | goto next_entry; | 294 | goto next_entry; |
312 | } | 295 | } |
313 | 296 | ||
@@ -317,9 +300,8 @@ orinoco_cs_config(dev_link_t *link) | |||
317 | break; | 300 | break; |
318 | 301 | ||
319 | next_entry: | 302 | next_entry: |
320 | if (link->io.NumPorts1) | 303 | pcmcia_disable_device(link); |
321 | pcmcia_release_io(link->handle, &link->io); | 304 | last_ret = pcmcia_get_next_tuple(link, &tuple); |
322 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | ||
323 | if (last_ret == CS_NO_MORE_ITEMS) { | 305 | if (last_ret == CS_NO_MORE_ITEMS) { |
324 | printk(KERN_ERR PFX "GetNextTuple(): No matching " | 306 | printk(KERN_ERR PFX "GetNextTuple(): No matching " |
325 | "CIS configuration. Maybe you need the " | 307 | "CIS configuration. Maybe you need the " |
@@ -333,7 +315,7 @@ orinoco_cs_config(dev_link_t *link) | |||
333 | * a handler to the interrupt, unless the 'Handler' member of | 315 | * a handler to the interrupt, unless the 'Handler' member of |
334 | * the irq structure is initialized. | 316 | * the irq structure is initialized. |
335 | */ | 317 | */ |
336 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 318 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
337 | 319 | ||
338 | /* We initialize the hermes structure before completing PCMCIA | 320 | /* We initialize the hermes structure before completing PCMCIA |
339 | * configuration just in case the interrupt handler gets | 321 | * configuration just in case the interrupt handler gets |
@@ -350,7 +332,7 @@ orinoco_cs_config(dev_link_t *link) | |||
350 | * card and host interface into "Memory and IO" mode. | 332 | * card and host interface into "Memory and IO" mode. |
351 | */ | 333 | */ |
352 | CS_CHECK(RequestConfiguration, | 334 | CS_CHECK(RequestConfiguration, |
353 | pcmcia_request_configuration(link->handle, &link->conf)); | 335 | pcmcia_request_configuration(link, &link->conf)); |
354 | 336 | ||
355 | /* Ok, we have the configuration, prepare to register the netdev */ | 337 | /* Ok, we have the configuration, prepare to register the netdev */ |
356 | dev->base_addr = link->io.BasePort1; | 338 | dev->base_addr = link->io.BasePort1; |
@@ -358,7 +340,7 @@ orinoco_cs_config(dev_link_t *link) | |||
358 | SET_MODULE_OWNER(dev); | 340 | SET_MODULE_OWNER(dev); |
359 | card->node.major = card->node.minor = 0; | 341 | card->node.major = card->node.minor = 0; |
360 | 342 | ||
361 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | 343 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
362 | /* Tell the stack we exist */ | 344 | /* Tell the stack we exist */ |
363 | if (register_netdev(dev) != 0) { | 345 | if (register_netdev(dev) != 0) { |
364 | printk(KERN_ERR PFX "register_netdev() failed\n"); | 346 | printk(KERN_ERR PFX "register_netdev() failed\n"); |
@@ -366,20 +348,18 @@ orinoco_cs_config(dev_link_t *link) | |||
366 | } | 348 | } |
367 | 349 | ||
368 | /* At this point, the dev_node_t structure(s) needs to be | 350 | /* At this point, the dev_node_t structure(s) needs to be |
369 | * initialized and arranged in a linked list at link->dev. */ | 351 | * initialized and arranged in a linked list at link->dev_node. */ |
370 | strcpy(card->node.dev_name, dev->name); | 352 | strcpy(card->node.dev_name, dev->name); |
371 | link->dev = &card->node; /* link->dev being non-NULL is also | 353 | link->dev_node = &card->node; /* link->dev_node being non-NULL is also |
372 | used to indicate that the | 354 | used to indicate that the |
373 | net_device has been registered */ | 355 | net_device has been registered */ |
374 | link->state &= ~DEV_CONFIG_PENDING; | ||
375 | 356 | ||
376 | /* Finally, report what we've done */ | 357 | /* Finally, report what we've done */ |
377 | printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", | 358 | printk(KERN_DEBUG "%s: index 0x%02x: ", |
378 | dev->name, link->conf.ConfigIndex, | 359 | dev->name, link->conf.ConfigIndex); |
379 | link->conf.Vcc / 10, link->conf.Vcc % 10); | 360 | if (link->conf.Vpp) |
380 | if (link->conf.Vpp1) | 361 | printk(", Vpp %d.%d", link->conf.Vpp / 10, |
381 | printk(", Vpp %d.%d", link->conf.Vpp1 / 10, | 362 | link->conf.Vpp % 10); |
382 | link->conf.Vpp1 % 10); | ||
383 | printk(", irq %d", link->irq.AssignedIRQ); | 363 | printk(", irq %d", link->irq.AssignedIRQ); |
384 | if (link->io.NumPorts1) | 364 | if (link->io.NumPorts1) |
385 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | 365 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, |
@@ -389,13 +369,14 @@ orinoco_cs_config(dev_link_t *link) | |||
389 | link->io.BasePort2 + link->io.NumPorts2 - 1); | 369 | link->io.BasePort2 + link->io.NumPorts2 - 1); |
390 | printk("\n"); | 370 | printk("\n"); |
391 | 371 | ||
392 | return; | 372 | return 0; |
393 | 373 | ||
394 | cs_failed: | 374 | cs_failed: |
395 | cs_error(link->handle, last_fn, last_ret); | 375 | cs_error(link, last_fn, last_ret); |
396 | 376 | ||
397 | failed: | 377 | failed: |
398 | orinoco_cs_release(link); | 378 | orinoco_cs_release(link); |
379 | return -ENODEV; | ||
399 | } /* orinoco_cs_config */ | 380 | } /* orinoco_cs_config */ |
400 | 381 | ||
401 | /* | 382 | /* |
@@ -404,7 +385,7 @@ orinoco_cs_config(dev_link_t *link) | |||
404 | * still open, this will be postponed until it is closed. | 385 | * still open, this will be postponed until it is closed. |
405 | */ | 386 | */ |
406 | static void | 387 | static void |
407 | orinoco_cs_release(dev_link_t *link) | 388 | orinoco_cs_release(struct pcmcia_device *link) |
408 | { | 389 | { |
409 | struct net_device *dev = link->priv; | 390 | struct net_device *dev = link->priv; |
410 | struct orinoco_private *priv = netdev_priv(dev); | 391 | struct orinoco_private *priv = netdev_priv(dev); |
@@ -416,88 +397,68 @@ orinoco_cs_release(dev_link_t *link) | |||
416 | priv->hw_unavailable++; | 397 | priv->hw_unavailable++; |
417 | spin_unlock_irqrestore(&priv->lock, flags); | 398 | spin_unlock_irqrestore(&priv->lock, flags); |
418 | 399 | ||
419 | /* Don't bother checking to see if these succeed or not */ | 400 | pcmcia_disable_device(link); |
420 | pcmcia_release_configuration(link->handle); | ||
421 | if (link->io.NumPorts1) | ||
422 | pcmcia_release_io(link->handle, &link->io); | ||
423 | if (link->irq.AssignedIRQ) | ||
424 | pcmcia_release_irq(link->handle, &link->irq); | ||
425 | link->state &= ~DEV_CONFIG; | ||
426 | if (priv->hw.iobase) | 401 | if (priv->hw.iobase) |
427 | ioport_unmap(priv->hw.iobase); | 402 | ioport_unmap(priv->hw.iobase); |
428 | } /* orinoco_cs_release */ | 403 | } /* orinoco_cs_release */ |
429 | 404 | ||
430 | static int orinoco_cs_suspend(struct pcmcia_device *p_dev) | 405 | static int orinoco_cs_suspend(struct pcmcia_device *link) |
431 | { | 406 | { |
432 | dev_link_t *link = dev_to_instance(p_dev); | ||
433 | struct net_device *dev = link->priv; | 407 | struct net_device *dev = link->priv; |
434 | struct orinoco_private *priv = netdev_priv(dev); | 408 | struct orinoco_private *priv = netdev_priv(dev); |
435 | struct orinoco_pccard *card = priv->card; | 409 | struct orinoco_pccard *card = priv->card; |
436 | int err = 0; | 410 | int err = 0; |
437 | unsigned long flags; | 411 | unsigned long flags; |
438 | 412 | ||
439 | link->state |= DEV_SUSPEND; | 413 | /* This is probably racy, but I can't think of |
440 | if (link->state & DEV_CONFIG) { | 414 | a better way, short of rewriting the PCMCIA |
441 | /* This is probably racy, but I can't think of | 415 | layer to not suck :-( */ |
442 | a better way, short of rewriting the PCMCIA | 416 | if (! test_bit(0, &card->hard_reset_in_progress)) { |
443 | layer to not suck :-( */ | 417 | spin_lock_irqsave(&priv->lock, flags); |
444 | if (! test_bit(0, &card->hard_reset_in_progress)) { | ||
445 | spin_lock_irqsave(&priv->lock, flags); | ||
446 | 418 | ||
447 | err = __orinoco_down(dev); | 419 | err = __orinoco_down(dev); |
448 | if (err) | 420 | if (err) |
449 | printk(KERN_WARNING "%s: Error %d downing interface\n", | 421 | printk(KERN_WARNING "%s: Error %d downing interface\n", |
450 | dev->name, err); | 422 | dev->name, err); |
451 | 423 | ||
452 | netif_device_detach(dev); | 424 | netif_device_detach(dev); |
453 | priv->hw_unavailable++; | 425 | priv->hw_unavailable++; |
454 | 426 | ||
455 | spin_unlock_irqrestore(&priv->lock, flags); | 427 | spin_unlock_irqrestore(&priv->lock, flags); |
456 | } | ||
457 | |||
458 | pcmcia_release_configuration(link->handle); | ||
459 | } | 428 | } |
460 | 429 | ||
461 | return 0; | 430 | return 0; |
462 | } | 431 | } |
463 | 432 | ||
464 | static int orinoco_cs_resume(struct pcmcia_device *p_dev) | 433 | static int orinoco_cs_resume(struct pcmcia_device *link) |
465 | { | 434 | { |
466 | dev_link_t *link = dev_to_instance(p_dev); | ||
467 | struct net_device *dev = link->priv; | 435 | struct net_device *dev = link->priv; |
468 | struct orinoco_private *priv = netdev_priv(dev); | 436 | struct orinoco_private *priv = netdev_priv(dev); |
469 | struct orinoco_pccard *card = priv->card; | 437 | struct orinoco_pccard *card = priv->card; |
470 | int err = 0; | 438 | int err = 0; |
471 | unsigned long flags; | 439 | unsigned long flags; |
472 | 440 | ||
473 | link->state &= ~DEV_SUSPEND; | 441 | if (! test_bit(0, &card->hard_reset_in_progress)) { |
474 | if (link->state & DEV_CONFIG) { | 442 | err = orinoco_reinit_firmware(dev); |
475 | /* FIXME: should we double check that this is | 443 | if (err) { |
476 | * the same card as we had before */ | 444 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", |
477 | pcmcia_request_configuration(link->handle, &link->conf); | 445 | dev->name, err); |
478 | 446 | return -EIO; | |
479 | if (! test_bit(0, &card->hard_reset_in_progress)) { | 447 | } |
480 | err = orinoco_reinit_firmware(dev); | ||
481 | if (err) { | ||
482 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", | ||
483 | dev->name, err); | ||
484 | return -EIO; | ||
485 | } | ||
486 | |||
487 | spin_lock_irqsave(&priv->lock, flags); | ||
488 | 448 | ||
489 | netif_device_attach(dev); | 449 | spin_lock_irqsave(&priv->lock, flags); |
490 | priv->hw_unavailable--; | ||
491 | 450 | ||
492 | if (priv->open && ! priv->hw_unavailable) { | 451 | netif_device_attach(dev); |
493 | err = __orinoco_up(dev); | 452 | priv->hw_unavailable--; |
494 | if (err) | ||
495 | printk(KERN_ERR "%s: Error %d restarting card\n", | ||
496 | dev->name, err); | ||
497 | } | ||
498 | 453 | ||
499 | spin_unlock_irqrestore(&priv->lock, flags); | 454 | if (priv->open && ! priv->hw_unavailable) { |
455 | err = __orinoco_up(dev); | ||
456 | if (err) | ||
457 | printk(KERN_ERR "%s: Error %d restarting card\n", | ||
458 | dev->name, err); | ||
500 | } | 459 | } |
460 | |||
461 | spin_unlock_irqrestore(&priv->lock, flags); | ||
501 | } | 462 | } |
502 | 463 | ||
503 | return 0; | 464 | return 0; |
@@ -604,7 +565,7 @@ static struct pcmcia_driver orinoco_driver = { | |||
604 | .drv = { | 565 | .drv = { |
605 | .name = DRIVER_NAME, | 566 | .name = DRIVER_NAME, |
606 | }, | 567 | }, |
607 | .probe = orinoco_cs_attach, | 568 | .probe = orinoco_cs_probe, |
608 | .remove = orinoco_cs_detach, | 569 | .remove = orinoco_cs_detach, |
609 | .id_table = orinoco_cs_ids, | 570 | .id_table = orinoco_cs_ids, |
610 | .suspend = orinoco_cs_suspend, | 571 | .suspend = orinoco_cs_suspend, |