aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2006-01-05 18:02:03 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2006-01-05 18:02:03 -0500
commit8e9e793d68fcda6cc84c18cedf85ca0f91d801a8 (patch)
tree3dcceaaa676f1221e532e24106bb661143733eaf /drivers/pcmcia
parent98e4c28b7ec390c2dad6a4c69d69629c0f7e8b10 (diff)
[PATCH] pcmcia: merge suspend into device model
Merge the suspend and resume methods for 16-bit PCMCIA cards into the device model -- for both runtime power management and suspend to ram/disk. Bugfix in ds.c by Richard Purdie Signed-Off-By: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/cs.c14
-rw-r--r--drivers/pcmcia/cs_internal.h2
-rw-r--r--drivers/pcmcia/ds.c94
3 files changed, 99 insertions, 11 deletions
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
148int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); 150int 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
925static 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
940static 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
955static 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
966static 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
979static 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
985static 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 */
1167EXPORT_SYMBOL(pcmcia_deregister_client); 1236EXPORT_SYMBOL(pcmcia_deregister_client);
1168 1237
1238
1169static struct pcmcia_callback pcmcia_bus_callback = { 1239static 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
1175static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, 1247static 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