diff options
Diffstat (limited to 'drivers/net/wireless/orinoco_cs.c')
-rw-r--r-- | drivers/net/wireless/orinoco_cs.c | 145 |
1 files changed, 79 insertions, 66 deletions
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index dc1128a00971..1d66050e3d6a 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -465,6 +465,83 @@ orinoco_cs_release(dev_link_t *link) | |||
465 | ioport_unmap(priv->hw.iobase); | 465 | ioport_unmap(priv->hw.iobase); |
466 | } /* orinoco_cs_release */ | 466 | } /* orinoco_cs_release */ |
467 | 467 | ||
468 | static int orinoco_cs_suspend(struct pcmcia_device *p_dev) | ||
469 | { | ||
470 | dev_link_t *link = dev_to_instance(p_dev); | ||
471 | struct net_device *dev = link->priv; | ||
472 | struct orinoco_private *priv = netdev_priv(dev); | ||
473 | struct orinoco_pccard *card = priv->card; | ||
474 | int err = 0; | ||
475 | unsigned long flags; | ||
476 | |||
477 | link->state |= DEV_SUSPEND; | ||
478 | if (link->state & DEV_CONFIG) { | ||
479 | /* This is probably racy, but I can't think of | ||
480 | a better way, short of rewriting the PCMCIA | ||
481 | layer to not suck :-( */ | ||
482 | if (! test_bit(0, &card->hard_reset_in_progress)) { | ||
483 | spin_lock_irqsave(&priv->lock, flags); | ||
484 | |||
485 | err = __orinoco_down(dev); | ||
486 | if (err) | ||
487 | printk(KERN_WARNING "%s: Error %d downing interface\n", | ||
488 | dev->name, err); | ||
489 | |||
490 | netif_device_detach(dev); | ||
491 | priv->hw_unavailable++; | ||
492 | |||
493 | spin_unlock_irqrestore(&priv->lock, flags); | ||
494 | } | ||
495 | |||
496 | pcmcia_release_configuration(link->handle); | ||
497 | } | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int orinoco_cs_resume(struct pcmcia_device *p_dev) | ||
503 | { | ||
504 | dev_link_t *link = dev_to_instance(p_dev); | ||
505 | struct net_device *dev = link->priv; | ||
506 | struct orinoco_private *priv = netdev_priv(dev); | ||
507 | struct orinoco_pccard *card = priv->card; | ||
508 | int err = 0; | ||
509 | unsigned long flags; | ||
510 | |||
511 | link->state &= ~DEV_SUSPEND; | ||
512 | if (link->state & DEV_CONFIG) { | ||
513 | /* FIXME: should we double check that this is | ||
514 | * the same card as we had before */ | ||
515 | pcmcia_request_configuration(link->handle, &link->conf); | ||
516 | |||
517 | if (! test_bit(0, &card->hard_reset_in_progress)) { | ||
518 | err = orinoco_reinit_firmware(dev); | ||
519 | if (err) { | ||
520 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", | ||
521 | dev->name, err); | ||
522 | return -EIO; | ||
523 | } | ||
524 | |||
525 | spin_lock_irqsave(&priv->lock, flags); | ||
526 | |||
527 | netif_device_attach(dev); | ||
528 | priv->hw_unavailable--; | ||
529 | |||
530 | if (priv->open && ! priv->hw_unavailable) { | ||
531 | err = __orinoco_up(dev); | ||
532 | if (err) | ||
533 | printk(KERN_ERR "%s: Error %d restarting card\n", | ||
534 | dev->name, err); | ||
535 | } | ||
536 | |||
537 | spin_unlock_irqrestore(&priv->lock, flags); | ||
538 | } | ||
539 | } | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | |||
468 | /* | 545 | /* |
469 | * The card status event handler. Mostly, this schedules other stuff | 546 | * The card status event handler. Mostly, this schedules other stuff |
470 | * to run after an event is received. | 547 | * to run after an event is received. |
@@ -476,9 +553,7 @@ orinoco_cs_event(event_t event, int priority, | |||
476 | dev_link_t *link = args->client_data; | 553 | dev_link_t *link = args->client_data; |
477 | struct net_device *dev = link->priv; | 554 | struct net_device *dev = link->priv; |
478 | struct orinoco_private *priv = netdev_priv(dev); | 555 | struct orinoco_private *priv = netdev_priv(dev); |
479 | struct orinoco_pccard *card = priv->card; | ||
480 | int err = 0; | 556 | int err = 0; |
481 | unsigned long flags; | ||
482 | 557 | ||
483 | switch (event) { | 558 | switch (event) { |
484 | case CS_EVENT_CARD_REMOVAL: | 559 | case CS_EVENT_CARD_REMOVAL: |
@@ -497,70 +572,6 @@ orinoco_cs_event(event_t event, int priority, | |||
497 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 572 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
498 | orinoco_cs_config(link); | 573 | orinoco_cs_config(link); |
499 | break; | 574 | break; |
500 | |||
501 | case CS_EVENT_PM_SUSPEND: | ||
502 | link->state |= DEV_SUSPEND; | ||
503 | /* Fall through... */ | ||
504 | case CS_EVENT_RESET_PHYSICAL: | ||
505 | /* Mark the device as stopped, to block IO until later */ | ||
506 | if (link->state & DEV_CONFIG) { | ||
507 | /* This is probably racy, but I can't think of | ||
508 | a better way, short of rewriting the PCMCIA | ||
509 | layer to not suck :-( */ | ||
510 | if (! test_bit(0, &card->hard_reset_in_progress)) { | ||
511 | spin_lock_irqsave(&priv->lock, flags); | ||
512 | |||
513 | err = __orinoco_down(dev); | ||
514 | if (err) | ||
515 | printk(KERN_WARNING "%s: %s: Error %d downing interface\n", | ||
516 | dev->name, | ||
517 | event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL", | ||
518 | err); | ||
519 | |||
520 | netif_device_detach(dev); | ||
521 | priv->hw_unavailable++; | ||
522 | |||
523 | spin_unlock_irqrestore(&priv->lock, flags); | ||
524 | } | ||
525 | |||
526 | pcmcia_release_configuration(link->handle); | ||
527 | } | ||
528 | break; | ||
529 | |||
530 | case CS_EVENT_PM_RESUME: | ||
531 | link->state &= ~DEV_SUSPEND; | ||
532 | /* Fall through... */ | ||
533 | case CS_EVENT_CARD_RESET: | ||
534 | if (link->state & DEV_CONFIG) { | ||
535 | /* FIXME: should we double check that this is | ||
536 | * the same card as we had before */ | ||
537 | pcmcia_request_configuration(link->handle, &link->conf); | ||
538 | |||
539 | if (! test_bit(0, &card->hard_reset_in_progress)) { | ||
540 | err = orinoco_reinit_firmware(dev); | ||
541 | if (err) { | ||
542 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", | ||
543 | dev->name, err); | ||
544 | break; | ||
545 | } | ||
546 | |||
547 | spin_lock_irqsave(&priv->lock, flags); | ||
548 | |||
549 | netif_device_attach(dev); | ||
550 | priv->hw_unavailable--; | ||
551 | |||
552 | if (priv->open && ! priv->hw_unavailable) { | ||
553 | err = __orinoco_up(dev); | ||
554 | if (err) | ||
555 | printk(KERN_ERR "%s: Error %d restarting card\n", | ||
556 | dev->name, err); | ||
557 | |||
558 | } | ||
559 | |||
560 | spin_unlock_irqrestore(&priv->lock, flags); | ||
561 | } | ||
562 | } | ||
563 | break; | ||
564 | } | 575 | } |
565 | 576 | ||
566 | return err; | 577 | return err; |
@@ -669,6 +680,8 @@ static struct pcmcia_driver orinoco_driver = { | |||
669 | .detach = orinoco_cs_detach, | 680 | .detach = orinoco_cs_detach, |
670 | .event = orinoco_cs_event, | 681 | .event = orinoco_cs_event, |
671 | .id_table = orinoco_cs_ids, | 682 | .id_table = orinoco_cs_ids, |
683 | .suspend = orinoco_cs_suspend, | ||
684 | .resume = orinoco_cs_resume, | ||
672 | }; | 685 | }; |
673 | 686 | ||
674 | static int __init | 687 | static int __init |