aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/orinoco_cs.c')
-rw-r--r--drivers/net/wireless/orinoco_cs.c145
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
468static 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
502static 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
674static int __init 687static int __init