aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-11-14 15:21:18 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2006-01-05 17:59:02 -0500
commit98e4c28b7ec390c2dad6a4c69d69629c0f7e8b10 (patch)
treeb3d46f0643352e541d6a39e6da09059687cf713d /drivers/net/wireless
parent63e7ebd06402951bc8863ba5b7bc9b9f42044849 (diff)
[PATCH] pcmcia: new suspend core
Move the suspend and resume methods out of the event handler, and into special functions. Also use these functions for pre- and post-reset, as almost all drivers already do, and the remaining ones can easily be converted. Bugfix to include/pcmcia/ds.c Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/airo_cs.c50
-rw-r--r--drivers/net/wireless/atmel_cs.c50
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c88
-rw-r--r--drivers/net/wireless/netwave_cs.c57
-rw-r--r--drivers/net/wireless/orinoco_cs.c145
-rw-r--r--drivers/net/wireless/ray_cs.c59
-rw-r--r--drivers/net/wireless/spectrum_cs.c96
-rw-r--r--drivers/net/wireless/wavelan_cs.c92
-rw-r--r--drivers/net/wireless/wl3501_cs.c61
9 files changed, 403 insertions, 295 deletions
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index e328547599d..80c9de749b5 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -492,6 +492,35 @@ static void airo_release(dev_link_t *link)
492 link->state &= ~DEV_CONFIG; 492 link->state &= ~DEV_CONFIG;
493} 493}
494 494
495static int airo_suspend(struct pcmcia_device *p_dev)
496{
497 dev_link_t *link = dev_to_instance(p_dev);
498 local_info_t *local = link->priv;
499
500 link->state |= DEV_SUSPEND;
501 if (link->state & DEV_CONFIG) {
502 netif_device_detach(local->eth_dev);
503 pcmcia_release_configuration(link->handle);
504 }
505
506 return 0;
507}
508
509static int airo_resume(struct pcmcia_device *p_dev)
510{
511 dev_link_t *link = dev_to_instance(p_dev);
512 local_info_t *local = link->priv;
513
514 link->state &= ~DEV_SUSPEND;
515 if (link->state & DEV_CONFIG) {
516 pcmcia_request_configuration(link->handle, &link->conf);
517 reset_airo_card(local->eth_dev);
518 netif_device_attach(local->eth_dev);
519 }
520
521 return 0;
522}
523
495/*====================================================================== 524/*======================================================================
496 525
497 The card status event handler. Mostly, this schedules other 526 The card status event handler. Mostly, this schedules other
@@ -524,25 +553,6 @@ static int airo_event(event_t event, int priority,
524 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 553 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
525 airo_config(link); 554 airo_config(link);
526 break; 555 break;
527 case CS_EVENT_PM_SUSPEND:
528 link->state |= DEV_SUSPEND;
529 /* Fall through... */
530 case CS_EVENT_RESET_PHYSICAL:
531 if (link->state & DEV_CONFIG) {
532 netif_device_detach(local->eth_dev);
533 pcmcia_release_configuration(link->handle);
534 }
535 break;
536 case CS_EVENT_PM_RESUME:
537 link->state &= ~DEV_SUSPEND;
538 /* Fall through... */
539 case CS_EVENT_CARD_RESET:
540 if (link->state & DEV_CONFIG) {
541 pcmcia_request_configuration(link->handle, &link->conf);
542 reset_airo_card(local->eth_dev);
543 netif_device_attach(local->eth_dev);
544 }
545 break;
546 } 556 }
547 return 0; 557 return 0;
548} /* airo_event */ 558} /* airo_event */
@@ -565,6 +575,8 @@ static struct pcmcia_driver airo_driver = {
565 .event = airo_event, 575 .event = airo_event,
566 .detach = airo_detach, 576 .detach = airo_detach,
567 .id_table = airo_ids, 577 .id_table = airo_ids,
578 .suspend = airo_suspend,
579 .resume = airo_resume,
568}; 580};
569 581
570static int airo_cs_init(void) 582static int airo_cs_init(void)
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 17d1fd90f83..598a9cd0f83 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -477,6 +477,35 @@ static void atmel_release(dev_link_t *link)
477 link->state &= ~DEV_CONFIG; 477 link->state &= ~DEV_CONFIG;
478} 478}
479 479
480static int atmel_suspend(struct pcmcia_device *dev)
481{
482 dev_link_t *link = dev_to_instance(dev);
483 local_info_t *local = link->priv;
484
485 link->state |= DEV_SUSPEND;
486 if (link->state & DEV_CONFIG) {
487 netif_device_detach(local->eth_dev);
488 pcmcia_release_configuration(link->handle);
489 }
490
491 return 0;
492}
493
494static int atmel_resume(struct pcmcia_device *dev)
495{
496 dev_link_t *link = dev_to_instance(dev);
497 local_info_t *local = link->priv;
498
499 link->state &= ~DEV_SUSPEND;
500 if (link->state & DEV_CONFIG) {
501 pcmcia_request_configuration(link->handle, &link->conf);
502 atmel_open(local->eth_dev);
503 netif_device_attach(local->eth_dev);
504 }
505
506 return 0;
507}
508
480/*====================================================================== 509/*======================================================================
481 510
482 The card status event handler. Mostly, this schedules other 511 The card status event handler. Mostly, this schedules other
@@ -509,25 +538,6 @@ static int atmel_event(event_t event, int priority,
509 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 538 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
510 atmel_config(link); 539 atmel_config(link);
511 break; 540 break;
512 case CS_EVENT_PM_SUSPEND:
513 link->state |= DEV_SUSPEND;
514 /* Fall through... */
515 case CS_EVENT_RESET_PHYSICAL:
516 if (link->state & DEV_CONFIG) {
517 netif_device_detach(local->eth_dev);
518 pcmcia_release_configuration(link->handle);
519 }
520 break;
521 case CS_EVENT_PM_RESUME:
522 link->state &= ~DEV_SUSPEND;
523 /* Fall through... */
524 case CS_EVENT_CARD_RESET:
525 if (link->state & DEV_CONFIG) {
526 pcmcia_request_configuration(link->handle, &link->conf);
527 atmel_open(local->eth_dev);
528 netif_device_attach(local->eth_dev);
529 }
530 break;
531 } 541 }
532 return 0; 542 return 0;
533} /* atmel_event */ 543} /* atmel_event */
@@ -585,6 +595,8 @@ static struct pcmcia_driver atmel_driver = {
585 .event = atmel_event, 595 .event = atmel_event,
586 .detach = atmel_detach, 596 .detach = atmel_detach,
587 .id_table = atmel_ids, 597 .id_table = atmel_ids,
598 .suspend = atmel_suspend,
599 .resume = atmel_resume,
588}; 600};
589 601
590static int atmel_cs_init(void) 602static int atmel_cs_init(void)
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 2643976a667..ba4a7da98cc 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -846,20 +846,64 @@ static void prism2_release(u_long arg)
846 PDEBUG(DEBUG_FLOW, "release - done\n"); 846 PDEBUG(DEBUG_FLOW, "release - done\n");
847} 847}
848 848
849static int hostap_cs_suspend(struct pcmcia_device *p_dev)
850{
851 dev_link_t *link = dev_to_instance(p_dev);
852 struct net_device *dev = (struct net_device *) link->priv;
853 int dev_open = 0;
849 854
850static int prism2_event(event_t event, int priority, 855 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
851 event_callback_args_t *args) 856
857 link->state |= DEV_SUSPEND;
858
859 if (link->state & DEV_CONFIG) {
860 struct hostap_interface *iface = netdev_priv(dev);
861 if (iface && iface->local)
862 dev_open = iface->local->num_dev_open > 0;
863 if (dev_open) {
864 netif_stop_queue(dev);
865 netif_device_detach(dev);
866 }
867 prism2_suspend(dev);
868 pcmcia_release_configuration(link->handle);
869 }
870
871 return 0;
872}
873
874static int hostap_cs_resume(struct pcmcia_device *p_dev)
852{ 875{
853 dev_link_t *link = args->client_data; 876 dev_link_t *link = dev_to_instance(p_dev);
854 struct net_device *dev = (struct net_device *) link->priv; 877 struct net_device *dev = (struct net_device *) link->priv;
855 int dev_open = 0; 878 int dev_open = 0;
856 879
880 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
881
882 link->state &= ~DEV_SUSPEND;
857 if (link->state & DEV_CONFIG) { 883 if (link->state & DEV_CONFIG) {
858 struct hostap_interface *iface = netdev_priv(dev); 884 struct hostap_interface *iface = netdev_priv(dev);
859 if (iface && iface->local) 885 if (iface && iface->local)
860 dev_open = iface->local->num_dev_open > 0; 886 dev_open = iface->local->num_dev_open > 0;
887
888 pcmcia_request_configuration(link->handle, &link->conf);
889
890 prism2_hw_shutdown(dev, 1);
891 prism2_hw_config(dev, dev_open ? 0 : 1);
892 if (dev_open) {
893 netif_device_attach(dev);
894 netif_start_queue(dev);
895 }
861 } 896 }
862 897
898 return 0;
899}
900
901static int prism2_event(event_t event, int priority,
902 event_callback_args_t *args)
903{
904 dev_link_t *link = args->client_data;
905 struct net_device *dev = (struct net_device *) link->priv;
906
863 switch (event) { 907 switch (event) {
864 case CS_EVENT_CARD_INSERTION: 908 case CS_EVENT_CARD_INSERTION:
865 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_INSERTION\n", dev_info); 909 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_INSERTION\n", dev_info);
@@ -879,42 +923,6 @@ static int prism2_event(event_t event, int priority,
879 } 923 }
880 break; 924 break;
881 925
882 case CS_EVENT_PM_SUSPEND:
883 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
884 link->state |= DEV_SUSPEND;
885 /* fall through */
886
887 case CS_EVENT_RESET_PHYSICAL:
888 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
889 if (link->state & DEV_CONFIG) {
890 if (dev_open) {
891 netif_stop_queue(dev);
892 netif_device_detach(dev);
893 }
894 prism2_suspend(dev);
895 pcmcia_release_configuration(link->handle);
896 }
897 break;
898
899 case CS_EVENT_PM_RESUME:
900 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
901 link->state &= ~DEV_SUSPEND;
902 /* fall through */
903
904 case CS_EVENT_CARD_RESET:
905 PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_RESET\n", dev_info);
906 if (link->state & DEV_CONFIG) {
907 pcmcia_request_configuration(link->handle,
908 &link->conf);
909 prism2_hw_shutdown(dev, 1);
910 prism2_hw_config(dev, dev_open ? 0 : 1);
911 if (dev_open) {
912 netif_device_attach(dev);
913 netif_start_queue(dev);
914 }
915 }
916 break;
917
918 default: 926 default:
919 PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n", 927 PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
920 dev_info, event); 928 dev_info, event);
@@ -987,6 +995,8 @@ static struct pcmcia_driver hostap_driver = {
987 .owner = THIS_MODULE, 995 .owner = THIS_MODULE,
988 .event = prism2_event, 996 .event = prism2_event,
989 .id_table = hostap_cs_ids, 997 .id_table = hostap_cs_ids,
998 .suspend = hostap_cs_suspend,
999 .resume = hostap_cs_resume,
990}; 1000};
991 1001
992static int __init init_prism2_pccard(void) 1002static int __init init_prism2_pccard(void)
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 92793b958e3..7ab2d70ffdd 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -935,6 +935,39 @@ static void netwave_release(dev_link_t *link)
935 link->state &= ~DEV_CONFIG; 935 link->state &= ~DEV_CONFIG;
936} 936}
937 937
938static int netwave_suspend(struct pcmcia_device *p_dev)
939{
940 dev_link_t *link = dev_to_instance(p_dev);
941 struct net_device *dev = link->priv;
942
943 link->state |= DEV_SUSPEND;
944 if (link->state & DEV_CONFIG) {
945 if (link->open)
946 netif_device_detach(dev);
947 pcmcia_release_configuration(link->handle);
948 }
949
950 return 0;
951}
952
953static int netwave_resume(struct pcmcia_device *p_dev)
954{
955 dev_link_t *link = dev_to_instance(p_dev);
956 struct net_device *dev = link->priv;
957
958 link->state &= ~DEV_SUSPEND;
959 if (link->state & DEV_CONFIG) {
960 pcmcia_request_configuration(link->handle, &link->conf);
961 if (link->open) {
962 netwave_reset(dev);
963 netif_device_attach(dev);
964 }
965 }
966
967 return 0;
968}
969
970
938/* 971/*
939 * Function netwave_event (event, priority, args) 972 * Function netwave_event (event, priority, args)
940 * 973 *
@@ -973,28 +1006,6 @@ static int netwave_event(event_t event, int priority,
973 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 1006 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
974 netwave_pcmcia_config( link); 1007 netwave_pcmcia_config( link);
975 break; 1008 break;
976 case CS_EVENT_PM_SUSPEND:
977 link->state |= DEV_SUSPEND;
978 /* Fall through... */
979 case CS_EVENT_RESET_PHYSICAL:
980 if (link->state & DEV_CONFIG) {
981 if (link->open)
982 netif_device_detach(dev);
983 pcmcia_release_configuration(link->handle);
984 }
985 break;
986 case CS_EVENT_PM_RESUME:
987 link->state &= ~DEV_SUSPEND;
988 /* Fall through... */
989 case CS_EVENT_CARD_RESET:
990 if (link->state & DEV_CONFIG) {
991 pcmcia_request_configuration(link->handle, &link->conf);
992 if (link->open) {
993 netwave_reset(dev);
994 netif_device_attach(dev);
995 }
996 }
997 break;
998 } 1009 }
999 return 0; 1010 return 0;
1000} /* netwave_event */ 1011} /* netwave_event */
@@ -1495,6 +1506,8 @@ static struct pcmcia_driver netwave_driver = {
1495 .event = netwave_event, 1506 .event = netwave_event,
1496 .detach = netwave_detach, 1507 .detach = netwave_detach,
1497 .id_table = netwave_ids, 1508 .id_table = netwave_ids,
1509 .suspend = netwave_suspend,
1510 .resume = netwave_resume,
1498}; 1511};
1499 1512
1500static int __init init_netwave_cs(void) 1513static int __init init_netwave_cs(void)
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index dc1128a0097..1d66050e3d6 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
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 70fd6fd8feb..c2cb6c8e6d7 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -891,6 +891,40 @@ static void ray_release(dev_link_t *link)
891 DEBUG(2,"ray_release ending\n"); 891 DEBUG(2,"ray_release ending\n");
892} 892}
893 893
894static int ray_suspend(struct pcmcia_device *p_dev)
895{
896 dev_link_t *link = dev_to_instance(p_dev);
897 struct net_device *dev = link->priv;
898
899 link->state |= DEV_SUSPEND;
900 if (link->state & DEV_CONFIG) {
901 if (link->open)
902 netif_device_detach(dev);
903
904 pcmcia_release_configuration(link->handle);
905 }
906
907
908 return 0;
909}
910
911static int ray_resume(struct pcmcia_device *p_dev)
912{
913 dev_link_t *link = dev_to_instance(p_dev);
914 struct net_device *dev = link->priv;
915
916 link->state &= ~DEV_SUSPEND;
917 if (link->state & DEV_CONFIG) {
918 pcmcia_request_configuration(link->handle, &link->conf);
919 if (link->open) {
920 ray_reset(dev);
921 netif_device_attach(dev);
922 }
923 }
924
925 return 0;
926}
927
894/*============================================================================= 928/*=============================================================================
895 The card status event handler. Mostly, this schedules other 929 The card status event handler. Mostly, this schedules other
896 stuff to run after an event is received. A CARD_REMOVAL event 930 stuff to run after an event is received. A CARD_REMOVAL event
@@ -923,29 +957,6 @@ static int ray_event(event_t event, int priority,
923 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 957 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
924 ray_config(link); 958 ray_config(link);
925 break; 959 break;
926 case CS_EVENT_PM_SUSPEND:
927 link->state |= DEV_SUSPEND;
928 /* Fall through... */
929 case CS_EVENT_RESET_PHYSICAL:
930 if (link->state & DEV_CONFIG) {
931 if (link->open)
932 netif_device_detach(dev);
933
934 pcmcia_release_configuration(link->handle);
935 }
936 break;
937 case CS_EVENT_PM_RESUME:
938 link->state &= ~DEV_SUSPEND;
939 /* Fall through... */
940 case CS_EVENT_CARD_RESET:
941 if (link->state & DEV_CONFIG) {
942 pcmcia_request_configuration(link->handle, &link->conf);
943 if (link->open) {
944 ray_reset(dev);
945 netif_device_attach(dev);
946 }
947 }
948 break;
949 } 960 }
950 return 0; 961 return 0;
951 DEBUG(2,"ray_event ending\n"); 962 DEBUG(2,"ray_event ending\n");
@@ -2949,6 +2960,8 @@ static struct pcmcia_driver ray_driver = {
2949 .event = ray_event, 2960 .event = ray_event,
2950 .detach = ray_detach, 2961 .detach = ray_detach,
2951 .id_table = ray_ids, 2962 .id_table = ray_ids,
2963 .suspend = ray_suspend,
2964 .resume = ray_resume,
2952}; 2965};
2953 2966
2954static int __init init_ray_cs(void) 2967static int __init init_ray_cs(void)
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index b1bbc8e8e91..3938a573565 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -948,6 +948,56 @@ spectrum_cs_release(dev_link_t *link)
948 ioport_unmap(priv->hw.iobase); 948 ioport_unmap(priv->hw.iobase);
949} /* spectrum_cs_release */ 949} /* spectrum_cs_release */
950 950
951
952static int
953spectrum_cs_suspend(struct pcmcia_device *p_dev)
954{
955 dev_link_t *link = dev_to_instance(p_dev);
956 struct net_device *dev = link->priv;
957 struct orinoco_private *priv = netdev_priv(dev);
958 unsigned long flags;
959 int err = 0;
960
961 link->state |= DEV_SUSPEND;
962 /* Mark the device as stopped, to block IO until later */
963 if (link->state & DEV_CONFIG) {
964 spin_lock_irqsave(&priv->lock, flags);
965
966 err = __orinoco_down(dev);
967 if (err)
968 printk(KERN_WARNING "%s: Error %d downing interface\n",
969 dev->name, err);
970
971 netif_device_detach(dev);
972 priv->hw_unavailable++;
973
974 spin_unlock_irqrestore(&priv->lock, flags);
975
976 pcmcia_release_configuration(link->handle);
977 }
978
979 return 0;
980}
981
982static int
983spectrum_cs_resume(struct pcmcia_device *p_dev)
984{
985 dev_link_t *link = dev_to_instance(p_dev);
986 struct net_device *dev = link->priv;
987 struct orinoco_private *priv = netdev_priv(dev);
988
989 link->state &= ~DEV_SUSPEND;
990 if (link->state & DEV_CONFIG) {
991 /* FIXME: should we double check that this is
992 * the same card as we had before */
993 pcmcia_request_configuration(link->handle, &link->conf);
994 netif_device_attach(dev);
995 priv->hw_unavailable--;
996 schedule_work(&priv->reset_work);
997 }
998 return 0;
999}
1000
951/* 1001/*
952 * The card status event handler. Mostly, this schedules other stuff 1002 * The card status event handler. Mostly, this schedules other stuff
953 * to run after an event is received. 1003 * to run after an event is received.
@@ -959,8 +1009,6 @@ spectrum_cs_event(event_t event, int priority,
959 dev_link_t *link = args->client_data; 1009 dev_link_t *link = args->client_data;
960 struct net_device *dev = link->priv; 1010 struct net_device *dev = link->priv;
961 struct orinoco_private *priv = netdev_priv(dev); 1011 struct orinoco_private *priv = netdev_priv(dev);
962 int err = 0;
963 unsigned long flags;
964 1012
965 switch (event) { 1013 switch (event) {
966 case CS_EVENT_CARD_REMOVAL: 1014 case CS_EVENT_CARD_REMOVAL:
@@ -980,49 +1028,9 @@ spectrum_cs_event(event_t event, int priority,
980 spectrum_cs_config(link); 1028 spectrum_cs_config(link);
981 break; 1029 break;
982 1030
983 case CS_EVENT_PM_SUSPEND:
984 link->state |= DEV_SUSPEND;
985 /* Fall through... */
986 case CS_EVENT_RESET_PHYSICAL:
987 /* Mark the device as stopped, to block IO until later */
988 if (link->state & DEV_CONFIG) {
989 /* This is probably racy, but I can't think of
990 a better way, short of rewriting the PCMCIA
991 layer to not suck :-( */
992 spin_lock_irqsave(&priv->lock, flags);
993
994 err = __orinoco_down(dev);
995 if (err)
996 printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
997 dev->name,
998 event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
999 err);
1000
1001 netif_device_detach(dev);
1002 priv->hw_unavailable++;
1003
1004 spin_unlock_irqrestore(&priv->lock, flags);
1005
1006 pcmcia_release_configuration(link->handle);
1007 }
1008 break;
1009
1010 case CS_EVENT_PM_RESUME:
1011 link->state &= ~DEV_SUSPEND;
1012 /* Fall through... */
1013 case CS_EVENT_CARD_RESET:
1014 if (link->state & DEV_CONFIG) {
1015 /* FIXME: should we double check that this is
1016 * the same card as we had before */
1017 pcmcia_request_configuration(link->handle, &link->conf);
1018 netif_device_attach(dev);
1019 priv->hw_unavailable--;
1020 schedule_work(&priv->reset_work);
1021 }
1022 break;
1023 } 1031 }
1024 1032
1025 return err; 1033 return 0;
1026} /* spectrum_cs_event */ 1034} /* spectrum_cs_event */
1027 1035
1028/********************************************************************/ 1036/********************************************************************/
@@ -1050,6 +1058,8 @@ static struct pcmcia_driver orinoco_driver = {
1050 }, 1058 },
1051 .attach = spectrum_cs_attach, 1059 .attach = spectrum_cs_attach,
1052 .detach = spectrum_cs_detach, 1060 .detach = spectrum_cs_detach,
1061 .suspend = spectrum_cs_suspend,
1062 .resume = spectrum_cs_resume,
1053 .event = spectrum_cs_event, 1063 .event = spectrum_cs_event,
1054 .id_table = spectrum_cs_ids, 1064 .id_table = spectrum_cs_ids,
1055}; 1065};
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index c822cad3333..3e3532830c2 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -4775,6 +4775,56 @@ wavelan_detach(dev_link_t * link)
4775#endif 4775#endif
4776} 4776}
4777 4777
4778static int wavelan_suspend(struct pcmcia_device *p_dev)
4779{
4780 dev_link_t *link = dev_to_instance(p_dev);
4781 struct net_device * dev = (struct net_device *) link->priv;
4782
4783 /* NB: wavelan_close will be called, but too late, so we are
4784 * obliged to close nicely the wavelan here. David, could you
4785 * close the device before suspending them ? And, by the way,
4786 * could you, on resume, add a "route add -net ..." after the
4787 * ifconfig up ? Thanks... */
4788
4789 /* Stop receiving new messages and wait end of transmission */
4790 wv_ru_stop(dev);
4791
4792 /* Power down the module */
4793 hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
4794
4795 /* The card is now suspended */
4796 link->state |= DEV_SUSPEND;
4797
4798 if(link->state & DEV_CONFIG)
4799 {
4800 if(link->open)
4801 netif_device_detach(dev);
4802 pcmcia_release_configuration(link->handle);
4803 }
4804
4805 return 0;
4806}
4807
4808static int wavelan_resume(struct pcmcia_device *p_dev)
4809{
4810 dev_link_t *link = dev_to_instance(p_dev);
4811 struct net_device * dev = (struct net_device *) link->priv;
4812
4813 link->state &= ~DEV_SUSPEND;
4814 if(link->state & DEV_CONFIG)
4815 {
4816 pcmcia_request_configuration(link->handle, &link->conf);
4817 if(link->open) /* If RESET -> True, If RESUME -> False ? */
4818 {
4819 wv_hw_reset(dev);
4820 netif_device_attach(dev);
4821 }
4822 }
4823
4824 return 0;
4825}
4826
4827
4778/*------------------------------------------------------------------*/ 4828/*------------------------------------------------------------------*/
4779/* 4829/*
4780 * The card status event handler. Mostly, this schedules other stuff 4830 * The card status event handler. Mostly, this schedules other stuff
@@ -4832,46 +4882,6 @@ wavelan_event(event_t event, /* The event received */
4832 else 4882 else
4833 dev->irq = 0; 4883 dev->irq = 0;
4834 break; 4884 break;
4835
4836 case CS_EVENT_PM_SUSPEND:
4837 /* NB: wavelan_close will be called, but too late, so we are
4838 * obliged to close nicely the wavelan here. David, could you
4839 * close the device before suspending them ? And, by the way,
4840 * could you, on resume, add a "route add -net ..." after the
4841 * ifconfig up ? Thanks... */
4842
4843 /* Stop receiving new messages and wait end of transmission */
4844 wv_ru_stop(dev);
4845
4846 /* Power down the module */
4847 hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
4848
4849 /* The card is now suspended */
4850 link->state |= DEV_SUSPEND;
4851 /* Fall through... */
4852 case CS_EVENT_RESET_PHYSICAL:
4853 if(link->state & DEV_CONFIG)
4854 {
4855 if(link->open)
4856 netif_device_detach(dev);
4857 pcmcia_release_configuration(link->handle);
4858 }
4859 break;
4860
4861 case CS_EVENT_PM_RESUME:
4862 link->state &= ~DEV_SUSPEND;
4863 /* Fall through... */
4864 case CS_EVENT_CARD_RESET:
4865 if(link->state & DEV_CONFIG)
4866 {
4867 pcmcia_request_configuration(link->handle, &link->conf);
4868 if(link->open) /* If RESET -> True, If RESUME -> False ? */
4869 {
4870 wv_hw_reset(dev);
4871 netif_device_attach(dev);
4872 }
4873 }
4874 break;
4875 } 4885 }
4876 4886
4877#ifdef DEBUG_CALLBACK_TRACE 4887#ifdef DEBUG_CALLBACK_TRACE
@@ -4898,6 +4908,8 @@ static struct pcmcia_driver wavelan_driver = {
4898 .event = wavelan_event, 4908 .event = wavelan_event,
4899 .detach = wavelan_detach, 4909 .detach = wavelan_detach,
4900 .id_table = wavelan_ids, 4910 .id_table = wavelan_ids,
4911 .suspend = wavelan_suspend,
4912 .resume = wavelan_resume,
4901}; 4913};
4902 4914
4903static int __init 4915static int __init
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 978fdc60678..75114318457 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -2173,6 +2173,41 @@ static void wl3501_release(dev_link_t *link)
2173 link->state &= ~DEV_CONFIG; 2173 link->state &= ~DEV_CONFIG;
2174} 2174}
2175 2175
2176static int wl3501_suspend(struct pcmcia_device *p_dev)
2177{
2178 dev_link_t *link = dev_to_instance(p_dev);
2179 struct net_device *dev = link->priv;
2180
2181 link->state |= DEV_SUSPEND;
2182
2183 wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
2184 if (link->state & DEV_CONFIG) {
2185 if (link->open)
2186 netif_device_detach(dev);
2187 pcmcia_release_configuration(link->handle);
2188 }
2189
2190 return 0;
2191}
2192
2193static int wl3501_resume(struct pcmcia_device *p_dev)
2194{
2195 dev_link_t *link = dev_to_instance(p_dev);
2196 struct net_device *dev = link->priv;
2197
2198 wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
2199 if (link->state & DEV_CONFIG) {
2200 pcmcia_request_configuration(link->handle, &link->conf);
2201 if (link->open) {
2202 wl3501_reset(dev);
2203 netif_device_attach(dev);
2204 }
2205 }
2206
2207 return 0;
2208}
2209
2210
2176/** 2211/**
2177 * wl3501_event - The card status event handler 2212 * wl3501_event - The card status event handler
2178 * @event - event 2213 * @event - event
@@ -2206,30 +2241,6 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
2206 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 2241 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
2207 wl3501_config(link); 2242 wl3501_config(link);
2208 break; 2243 break;
2209 case CS_EVENT_PM_SUSPEND:
2210 link->state |= DEV_SUSPEND;
2211 wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
2212 /* Fall through... */
2213 case CS_EVENT_RESET_PHYSICAL:
2214 if (link->state & DEV_CONFIG) {
2215 if (link->open)
2216 netif_device_detach(dev);
2217 pcmcia_release_configuration(link->handle);
2218 }
2219 break;
2220 case CS_EVENT_PM_RESUME:
2221 link->state &= ~DEV_SUSPEND;
2222 wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
2223 /* Fall through... */
2224 case CS_EVENT_CARD_RESET:
2225 if (link->state & DEV_CONFIG) {
2226 pcmcia_request_configuration(link->handle, &link->conf);
2227 if (link->open) {
2228 wl3501_reset(dev);
2229 netif_device_attach(dev);
2230 }
2231 }
2232 break;
2233 } 2244 }
2234 return 0; 2245 return 0;
2235} 2246}
@@ -2249,6 +2260,8 @@ static struct pcmcia_driver wl3501_driver = {
2249 .event = wl3501_event, 2260 .event = wl3501_event,
2250 .detach = wl3501_detach, 2261 .detach = wl3501_detach,
2251 .id_table = wl3501_ids, 2262 .id_table = wl3501_ids,
2263 .suspend = wl3501_suspend,
2264 .resume = wl3501_resume,
2252}; 2265};
2253 2266
2254static int __init wl3501_init_module(void) 2267static int __init wl3501_init_module(void)