diff options
-rw-r--r-- | drivers/base/power/runtime.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/cs.c | 14 | ||||
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 2 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 94 |
4 files changed, 100 insertions, 11 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 4bafef83e79f..96370ec1d673 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -62,6 +62,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state) | |||
62 | up(&dpm_sem); | 62 | up(&dpm_sem); |
63 | return error; | 63 | return error; |
64 | } | 64 | } |
65 | EXPORT_SYMBOL(dpm_runtime_suspend); | ||
65 | 66 | ||
66 | 67 | ||
67 | #if 0 | 68 | #if 0 |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 7cf09084ef61..83d2753814c2 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -780,8 +780,13 @@ int pccard_reset_card(struct pcmcia_socket *skt) | |||
780 | ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW); | 780 | ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW); |
781 | if (ret == 0) { | 781 | if (ret == 0) { |
782 | send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); | 782 | send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); |
783 | if (socket_reset(skt) == CS_SUCCESS) | 783 | if (skt->callback) |
784 | skt->callback->suspend(skt); | ||
785 | if (socket_reset(skt) == CS_SUCCESS) { | ||
784 | send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); | 786 | send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); |
787 | if (skt->callback) | ||
788 | skt->callback->resume(skt); | ||
789 | } | ||
785 | } | 790 | } |
786 | 791 | ||
787 | ret = CS_SUCCESS; | 792 | ret = CS_SUCCESS; |
@@ -812,6 +817,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt) | |||
812 | ret = CS_UNSUPPORTED_FUNCTION; | 817 | ret = CS_UNSUPPORTED_FUNCTION; |
813 | break; | 818 | break; |
814 | } | 819 | } |
820 | if (skt->callback) { | ||
821 | ret = skt->callback->suspend(skt); | ||
822 | if (ret) | ||
823 | break; | ||
824 | } | ||
815 | ret = socket_suspend(skt); | 825 | ret = socket_suspend(skt); |
816 | } while (0); | 826 | } while (0); |
817 | up(&skt->skt_sem); | 827 | up(&skt->skt_sem); |
@@ -838,6 +848,8 @@ int pcmcia_resume_card(struct pcmcia_socket *skt) | |||
838 | break; | 848 | break; |
839 | } | 849 | } |
840 | ret = socket_resume(skt); | 850 | ret = socket_resume(skt); |
851 | if (!ret && skt->callback) | ||
852 | skt->callback->resume(skt); | ||
841 | } while (0); | 853 | } while (0); |
842 | up(&skt->skt_sem); | 854 | up(&skt->skt_sem); |
843 | 855 | ||
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 634426b78f2c..7b37eba35bf1 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -143,6 +143,8 @@ struct pcmcia_callback{ | |||
143 | struct module *owner; | 143 | struct module *owner; |
144 | int (*event) (struct pcmcia_socket *s, event_t event, int priority); | 144 | int (*event) (struct pcmcia_socket *s, event_t event, int priority); |
145 | void (*requery) (struct pcmcia_socket *s); | 145 | void (*requery) (struct pcmcia_socket *s); |
146 | int (*suspend) (struct pcmcia_socket *s); | ||
147 | int (*resume) (struct pcmcia_socket *s); | ||
146 | }; | 148 | }; |
147 | 149 | ||
148 | int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); | 150 | int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a802c65c3534..5223395b246a 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -920,6 +920,78 @@ static struct device_attribute pcmcia_dev_attrs[] = { | |||
920 | __ATTR_NULL, | 920 | __ATTR_NULL, |
921 | }; | 921 | }; |
922 | 922 | ||
923 | /* PM support, also needed for reset */ | ||
924 | |||
925 | static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) | ||
926 | { | ||
927 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
928 | struct pcmcia_driver *p_drv = NULL; | ||
929 | |||
930 | if (dev->driver) | ||
931 | p_drv = to_pcmcia_drv(dev->driver); | ||
932 | |||
933 | if (p_drv && p_drv->suspend) | ||
934 | return p_drv->suspend(p_dev); | ||
935 | |||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | |||
940 | static int pcmcia_dev_resume(struct device * dev) | ||
941 | { | ||
942 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
943 | struct pcmcia_driver *p_drv = NULL; | ||
944 | |||
945 | if (dev->driver) | ||
946 | p_drv = to_pcmcia_drv(dev->driver); | ||
947 | |||
948 | if (p_drv && p_drv->resume) | ||
949 | return p_drv->resume(p_dev); | ||
950 | |||
951 | return 0; | ||
952 | } | ||
953 | |||
954 | |||
955 | static int pcmcia_bus_suspend_callback(struct device *dev, void * _data) | ||
956 | { | ||
957 | struct pcmcia_socket *skt = _data; | ||
958 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
959 | |||
960 | if (p_dev->socket != skt) | ||
961 | return 0; | ||
962 | |||
963 | return dpm_runtime_suspend(dev, PMSG_SUSPEND); | ||
964 | } | ||
965 | |||
966 | static int pcmcia_bus_resume_callback(struct device *dev, void * _data) | ||
967 | { | ||
968 | struct pcmcia_socket *skt = _data; | ||
969 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
970 | |||
971 | if (p_dev->socket != skt) | ||
972 | return 0; | ||
973 | |||
974 | dpm_runtime_resume(dev); | ||
975 | |||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static int pcmcia_bus_resume(struct pcmcia_socket *skt) | ||
980 | { | ||
981 | bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback); | ||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | static int pcmcia_bus_suspend(struct pcmcia_socket *skt) | ||
986 | { | ||
987 | if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt, | ||
988 | pcmcia_bus_suspend_callback)) { | ||
989 | pcmcia_bus_resume(skt); | ||
990 | return -EIO; | ||
991 | } | ||
992 | return 0; | ||
993 | } | ||
994 | |||
923 | 995 | ||
924 | /*====================================================================== | 996 | /*====================================================================== |
925 | 997 | ||
@@ -951,16 +1023,6 @@ static int send_event_callback(struct device *dev, void * _data) | |||
951 | if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE)) | 1023 | if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE)) |
952 | return 0; | 1024 | return 0; |
953 | 1025 | ||
954 | if ((data->event == CS_EVENT_PM_SUSPEND) || | ||
955 | (data->event == CS_EVENT_RESET_PHYSICAL)) { | ||
956 | if (p_drv->suspend) | ||
957 | return p_drv->suspend(p_dev); | ||
958 | } else if ((data->event == CS_EVENT_PM_RESUME) || | ||
959 | (data->event == CS_EVENT_CARD_RESET)) { | ||
960 | if (p_drv->resume) | ||
961 | return p_drv->resume(p_dev); | ||
962 | } | ||
963 | |||
964 | if (p_drv->event) | 1026 | if (p_drv->event) |
965 | return p_drv->event(data->event, data->priority, | 1027 | return p_drv->event(data->event, data->priority, |
966 | &p_dev->event_callback_args); | 1028 | &p_dev->event_callback_args); |
@@ -1012,6 +1074,13 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1012 | ret = send_event(skt, event, priority); | 1074 | ret = send_event(skt, event, priority); |
1013 | break; | 1075 | break; |
1014 | 1076 | ||
1077 | case CS_EVENT_PM_SUSPEND: | ||
1078 | case CS_EVENT_PM_RESUME: | ||
1079 | case CS_EVENT_RESET_PHYSICAL: | ||
1080 | case CS_EVENT_CARD_RESET: | ||
1081 | handle_event(skt, event); | ||
1082 | break; | ||
1083 | |||
1015 | default: | 1084 | default: |
1016 | handle_event(skt, event); | 1085 | handle_event(skt, event); |
1017 | send_event(skt, event, priority); | 1086 | send_event(skt, event, priority); |
@@ -1166,10 +1235,13 @@ int pcmcia_deregister_client(struct pcmcia_device *p_dev) | |||
1166 | } /* deregister_client */ | 1235 | } /* deregister_client */ |
1167 | EXPORT_SYMBOL(pcmcia_deregister_client); | 1236 | EXPORT_SYMBOL(pcmcia_deregister_client); |
1168 | 1237 | ||
1238 | |||
1169 | static struct pcmcia_callback pcmcia_bus_callback = { | 1239 | static struct pcmcia_callback pcmcia_bus_callback = { |
1170 | .owner = THIS_MODULE, | 1240 | .owner = THIS_MODULE, |
1171 | .event = ds_event, | 1241 | .event = ds_event, |
1172 | .requery = pcmcia_bus_rescan, | 1242 | .requery = pcmcia_bus_rescan, |
1243 | .suspend = pcmcia_bus_suspend, | ||
1244 | .resume = pcmcia_bus_resume, | ||
1173 | }; | 1245 | }; |
1174 | 1246 | ||
1175 | static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, | 1247 | static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, |
@@ -1238,6 +1310,8 @@ struct bus_type pcmcia_bus_type = { | |||
1238 | .uevent = pcmcia_bus_uevent, | 1310 | .uevent = pcmcia_bus_uevent, |
1239 | .match = pcmcia_bus_match, | 1311 | .match = pcmcia_bus_match, |
1240 | .dev_attrs = pcmcia_dev_attrs, | 1312 | .dev_attrs = pcmcia_dev_attrs, |
1313 | .suspend = pcmcia_dev_suspend, | ||
1314 | .resume = pcmcia_dev_resume, | ||
1241 | }; | 1315 | }; |
1242 | 1316 | ||
1243 | 1317 | ||