diff options
Diffstat (limited to 'drivers/net/wireless/spectrum_cs.c')
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 96 |
1 files changed, 53 insertions, 43 deletions
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index b1bbc8e8e91f..3938a5735659 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 | |||
952 | static int | ||
953 | spectrum_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 | |||
982 | static int | ||
983 | spectrum_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 | }; |