diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2005-11-14 15:21:18 -0500 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2006-01-05 17:59:02 -0500 |
commit | 98e4c28b7ec390c2dad6a4c69d69629c0f7e8b10 (patch) | |
tree | b3d46f0643352e541d6a39e6da09059687cf713d | |
parent | 63e7ebd06402951bc8863ba5b7bc9b9f42044849 (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>
45 files changed, 1431 insertions, 991 deletions
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt index 403e7b4dcdd4..5c822f54d46c 100644 --- a/Documentation/pcmcia/driver-changes.txt +++ b/Documentation/pcmcia/driver-changes.txt | |||
@@ -1,5 +1,11 @@ | |||
1 | This file details changes in 2.6 which affect PCMCIA card driver authors: | 1 | This file details changes in 2.6 which affect PCMCIA card driver authors: |
2 | 2 | ||
3 | * Move suspend, resume and reset out of event handler (as of 2.6.16) | ||
4 | int (*suspend) (struct pcmcia_device *dev); | ||
5 | int (*resume) (struct pcmcia_device *dev); | ||
6 | should be initialized in struct pcmcia_driver, and handle | ||
7 | (SUSPEND == RESET_PHYSICAL) and (RESUME == CARD_RESET) events | ||
8 | |||
3 | * event handler initialization in struct pcmcia_driver (as of 2.6.13) | 9 | * event handler initialization in struct pcmcia_driver (as of 2.6.13) |
4 | The event handler is notified of all events, and must be initialized | 10 | The event handler is notified of all events, and must be initialized |
5 | as the event() callback in the driver's struct pcmcia_driver. | 11 | as the event() callback in the driver's struct pcmcia_driver. |
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index f36c563d72c4..5b24131e5430 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c | |||
@@ -1045,6 +1045,27 @@ static void bluecard_release(dev_link_t *link) | |||
1045 | link->state &= ~DEV_CONFIG; | 1045 | link->state &= ~DEV_CONFIG; |
1046 | } | 1046 | } |
1047 | 1047 | ||
1048 | static int bluecard_suspend(struct pcmcia_device *dev) | ||
1049 | { | ||
1050 | dev_link_t *link = dev_to_instance(dev); | ||
1051 | |||
1052 | link->state |= DEV_SUSPEND; | ||
1053 | if (link->state & DEV_CONFIG) | ||
1054 | pcmcia_release_configuration(link->handle); | ||
1055 | |||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | static int bluecard_resume(struct pcmcia_device *dev) | ||
1060 | { | ||
1061 | dev_link_t *link = dev_to_instance(dev); | ||
1062 | |||
1063 | link->state &= ~DEV_SUSPEND; | ||
1064 | if (DEV_OK(link)) | ||
1065 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1066 | |||
1067 | return 0; | ||
1068 | } | ||
1048 | 1069 | ||
1049 | static int bluecard_event(event_t event, int priority, event_callback_args_t *args) | 1070 | static int bluecard_event(event_t event, int priority, event_callback_args_t *args) |
1050 | { | 1071 | { |
@@ -1063,20 +1084,6 @@ static int bluecard_event(event_t event, int priority, event_callback_args_t *ar | |||
1063 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 1084 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
1064 | bluecard_config(link); | 1085 | bluecard_config(link); |
1065 | break; | 1086 | break; |
1066 | case CS_EVENT_PM_SUSPEND: | ||
1067 | link->state |= DEV_SUSPEND; | ||
1068 | /* Fall through... */ | ||
1069 | case CS_EVENT_RESET_PHYSICAL: | ||
1070 | if (link->state & DEV_CONFIG) | ||
1071 | pcmcia_release_configuration(link->handle); | ||
1072 | break; | ||
1073 | case CS_EVENT_PM_RESUME: | ||
1074 | link->state &= ~DEV_SUSPEND; | ||
1075 | /* Fall through... */ | ||
1076 | case CS_EVENT_CARD_RESET: | ||
1077 | if (DEV_OK(link)) | ||
1078 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1079 | break; | ||
1080 | } | 1087 | } |
1081 | 1088 | ||
1082 | return 0; | 1089 | return 0; |
@@ -1099,6 +1106,8 @@ static struct pcmcia_driver bluecard_driver = { | |||
1099 | .event = bluecard_event, | 1106 | .event = bluecard_event, |
1100 | .detach = bluecard_detach, | 1107 | .detach = bluecard_detach, |
1101 | .id_table = bluecard_ids, | 1108 | .id_table = bluecard_ids, |
1109 | .suspend = bluecard_suspend, | ||
1110 | .resume = bluecard_resume, | ||
1102 | }; | 1111 | }; |
1103 | 1112 | ||
1104 | static int __init init_bluecard_cs(void) | 1113 | static int __init init_bluecard_cs(void) |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index d2a0add19cc8..1d524baa24a0 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -891,6 +891,27 @@ static void bt3c_release(dev_link_t *link) | |||
891 | link->state &= ~DEV_CONFIG; | 891 | link->state &= ~DEV_CONFIG; |
892 | } | 892 | } |
893 | 893 | ||
894 | static int bt3c_suspend(struct pcmcia_device *dev) | ||
895 | { | ||
896 | dev_link_t *link = dev_to_instance(dev); | ||
897 | |||
898 | link->state |= DEV_SUSPEND; | ||
899 | if (link->state & DEV_CONFIG) | ||
900 | pcmcia_release_configuration(link->handle); | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | static int bt3c_resume(struct pcmcia_device *dev) | ||
906 | { | ||
907 | dev_link_t *link = dev_to_instance(dev); | ||
908 | |||
909 | link->state &= ~DEV_SUSPEND; | ||
910 | if (DEV_OK(link)) | ||
911 | pcmcia_request_configuration(link->handle, &link->conf); | ||
912 | |||
913 | return 0; | ||
914 | } | ||
894 | 915 | ||
895 | static int bt3c_event(event_t event, int priority, event_callback_args_t *args) | 916 | static int bt3c_event(event_t event, int priority, event_callback_args_t *args) |
896 | { | 917 | { |
@@ -909,20 +930,6 @@ static int bt3c_event(event_t event, int priority, event_callback_args_t *args) | |||
909 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 930 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
910 | bt3c_config(link); | 931 | bt3c_config(link); |
911 | break; | 932 | break; |
912 | case CS_EVENT_PM_SUSPEND: | ||
913 | link->state |= DEV_SUSPEND; | ||
914 | /* Fall through... */ | ||
915 | case CS_EVENT_RESET_PHYSICAL: | ||
916 | if (link->state & DEV_CONFIG) | ||
917 | pcmcia_release_configuration(link->handle); | ||
918 | break; | ||
919 | case CS_EVENT_PM_RESUME: | ||
920 | link->state &= ~DEV_SUSPEND; | ||
921 | /* Fall through... */ | ||
922 | case CS_EVENT_CARD_RESET: | ||
923 | if (DEV_OK(link)) | ||
924 | pcmcia_request_configuration(link->handle, &link->conf); | ||
925 | break; | ||
926 | } | 933 | } |
927 | 934 | ||
928 | return 0; | 935 | return 0; |
@@ -943,6 +950,8 @@ static struct pcmcia_driver bt3c_driver = { | |||
943 | .event = bt3c_event, | 950 | .event = bt3c_event, |
944 | .detach = bt3c_detach, | 951 | .detach = bt3c_detach, |
945 | .id_table = bt3c_ids, | 952 | .id_table = bt3c_ids, |
953 | .suspend = bt3c_suspend, | ||
954 | .resume = bt3c_resume, | ||
946 | }; | 955 | }; |
947 | 956 | ||
948 | static int __init init_bt3c_cs(void) | 957 | static int __init init_bt3c_cs(void) |
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 529a28a3209d..1828ba6ca25e 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -811,6 +811,28 @@ static void btuart_release(dev_link_t *link) | |||
811 | link->state &= ~DEV_CONFIG; | 811 | link->state &= ~DEV_CONFIG; |
812 | } | 812 | } |
813 | 813 | ||
814 | static int btuart_suspend(struct pcmcia_device *dev) | ||
815 | { | ||
816 | dev_link_t *link = dev_to_instance(dev); | ||
817 | |||
818 | link->state |= DEV_SUSPEND; | ||
819 | if (link->state & DEV_CONFIG) | ||
820 | pcmcia_release_configuration(link->handle); | ||
821 | |||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | static int btuart_resume(struct pcmcia_device *dev) | ||
826 | { | ||
827 | dev_link_t *link = dev_to_instance(dev); | ||
828 | |||
829 | link->state &= ~DEV_SUSPEND; | ||
830 | if (DEV_OK(link)) | ||
831 | pcmcia_request_configuration(link->handle, &link->conf); | ||
832 | |||
833 | return 0; | ||
834 | } | ||
835 | |||
814 | 836 | ||
815 | static int btuart_event(event_t event, int priority, event_callback_args_t *args) | 837 | static int btuart_event(event_t event, int priority, event_callback_args_t *args) |
816 | { | 838 | { |
@@ -829,20 +851,6 @@ static int btuart_event(event_t event, int priority, event_callback_args_t *args | |||
829 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 851 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
830 | btuart_config(link); | 852 | btuart_config(link); |
831 | break; | 853 | break; |
832 | case CS_EVENT_PM_SUSPEND: | ||
833 | link->state |= DEV_SUSPEND; | ||
834 | /* Fall through... */ | ||
835 | case CS_EVENT_RESET_PHYSICAL: | ||
836 | if (link->state & DEV_CONFIG) | ||
837 | pcmcia_release_configuration(link->handle); | ||
838 | break; | ||
839 | case CS_EVENT_PM_RESUME: | ||
840 | link->state &= ~DEV_SUSPEND; | ||
841 | /* Fall through... */ | ||
842 | case CS_EVENT_CARD_RESET: | ||
843 | if (DEV_OK(link)) | ||
844 | pcmcia_request_configuration(link->handle, &link->conf); | ||
845 | break; | ||
846 | } | 854 | } |
847 | 855 | ||
848 | return 0; | 856 | return 0; |
@@ -863,6 +871,8 @@ static struct pcmcia_driver btuart_driver = { | |||
863 | .event = btuart_event, | 871 | .event = btuart_event, |
864 | .detach = btuart_detach, | 872 | .detach = btuart_detach, |
865 | .id_table = btuart_ids, | 873 | .id_table = btuart_ids, |
874 | .suspend = btuart_suspend, | ||
875 | .resume = btuart_resume, | ||
866 | }; | 876 | }; |
867 | 877 | ||
868 | static int __init init_btuart_cs(void) | 878 | static int __init init_btuart_cs(void) |
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index dec5980a1cd6..9f9d3f91f455 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -763,6 +763,27 @@ static void dtl1_release(dev_link_t *link) | |||
763 | link->state &= ~DEV_CONFIG; | 763 | link->state &= ~DEV_CONFIG; |
764 | } | 764 | } |
765 | 765 | ||
766 | static int dtl1_suspend(struct pcmcia_device *dev) | ||
767 | { | ||
768 | dev_link_t *link = dev_to_instance(dev); | ||
769 | |||
770 | link->state |= DEV_SUSPEND; | ||
771 | if (link->state & DEV_CONFIG) | ||
772 | pcmcia_release_configuration(link->handle); | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int dtl1_resume(struct pcmcia_device *dev) | ||
778 | { | ||
779 | dev_link_t *link = dev_to_instance(dev); | ||
780 | |||
781 | link->state &= ~DEV_SUSPEND; | ||
782 | if (DEV_OK(link)) | ||
783 | pcmcia_request_configuration(link->handle, &link->conf); | ||
784 | |||
785 | return 0; | ||
786 | } | ||
766 | 787 | ||
767 | static int dtl1_event(event_t event, int priority, event_callback_args_t *args) | 788 | static int dtl1_event(event_t event, int priority, event_callback_args_t *args) |
768 | { | 789 | { |
@@ -781,20 +802,6 @@ static int dtl1_event(event_t event, int priority, event_callback_args_t *args) | |||
781 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 802 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
782 | dtl1_config(link); | 803 | dtl1_config(link); |
783 | break; | 804 | break; |
784 | case CS_EVENT_PM_SUSPEND: | ||
785 | link->state |= DEV_SUSPEND; | ||
786 | /* Fall through... */ | ||
787 | case CS_EVENT_RESET_PHYSICAL: | ||
788 | if (link->state & DEV_CONFIG) | ||
789 | pcmcia_release_configuration(link->handle); | ||
790 | break; | ||
791 | case CS_EVENT_PM_RESUME: | ||
792 | link->state &= ~DEV_SUSPEND; | ||
793 | /* Fall through... */ | ||
794 | case CS_EVENT_CARD_RESET: | ||
795 | if (DEV_OK(link)) | ||
796 | pcmcia_request_configuration(link->handle, &link->conf); | ||
797 | break; | ||
798 | } | 805 | } |
799 | 806 | ||
800 | return 0; | 807 | return 0; |
@@ -816,6 +823,8 @@ static struct pcmcia_driver dtl1_driver = { | |||
816 | .event = dtl1_event, | 823 | .event = dtl1_event, |
817 | .detach = dtl1_detach, | 824 | .detach = dtl1_detach, |
818 | .id_table = dtl1_ids, | 825 | .id_table = dtl1_ids, |
826 | .suspend = dtl1_suspend, | ||
827 | .resume = dtl1_resume, | ||
819 | }; | 828 | }; |
820 | 829 | ||
821 | static int __init init_dtl1_cs(void) | 830 | static int __init init_dtl1_cs(void) |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 61681c9f3f72..05e93054c98c 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -1893,33 +1893,6 @@ static int cm4000_event(event_t event, int priority, | |||
1893 | link->state &= ~DEV_PRESENT; | 1893 | link->state &= ~DEV_PRESENT; |
1894 | stop_monitor(dev); | 1894 | stop_monitor(dev); |
1895 | break; | 1895 | break; |
1896 | case CS_EVENT_PM_SUSPEND: | ||
1897 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | ||
1898 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
1899 | link->state |= DEV_SUSPEND; | ||
1900 | /* fall-through */ | ||
1901 | case CS_EVENT_RESET_PHYSICAL: | ||
1902 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
1903 | if (link->state & DEV_CONFIG) { | ||
1904 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
1905 | pcmcia_release_configuration(link->handle); | ||
1906 | } | ||
1907 | stop_monitor(dev); | ||
1908 | break; | ||
1909 | case CS_EVENT_PM_RESUME: | ||
1910 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
1911 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
1912 | link->state &= ~DEV_SUSPEND; | ||
1913 | /* fall-through */ | ||
1914 | case CS_EVENT_CARD_RESET: | ||
1915 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
1916 | if ((link->state & DEV_CONFIG)) { | ||
1917 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
1918 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1919 | } | ||
1920 | if (link->open) | ||
1921 | start_monitor(dev); | ||
1922 | break; | ||
1923 | default: | 1896 | default: |
1924 | DEBUGP(5, dev, "unknown event %.2x\n", event); | 1897 | DEBUGP(5, dev, "unknown event %.2x\n", event); |
1925 | break; | 1898 | break; |
@@ -1928,6 +1901,38 @@ static int cm4000_event(event_t event, int priority, | |||
1928 | return CS_SUCCESS; | 1901 | return CS_SUCCESS; |
1929 | } | 1902 | } |
1930 | 1903 | ||
1904 | static int cm4000_suspend(struct pcmcia_device *p_dev) | ||
1905 | { | ||
1906 | dev_link_t *link = dev_to_instance(p_dev); | ||
1907 | struct cm4000_dev *dev; | ||
1908 | |||
1909 | dev = link->priv; | ||
1910 | |||
1911 | link->state |= DEV_SUSPEND; | ||
1912 | if (link->state & DEV_CONFIG) | ||
1913 | pcmcia_release_configuration(link->handle); | ||
1914 | stop_monitor(dev); | ||
1915 | |||
1916 | return 0; | ||
1917 | } | ||
1918 | |||
1919 | static int cm4000_resume(struct pcmcia_device *p_dev) | ||
1920 | { | ||
1921 | dev_link_t *link = dev_to_instance(p_dev); | ||
1922 | struct cm4000_dev *dev; | ||
1923 | |||
1924 | dev = link->priv; | ||
1925 | |||
1926 | link->state &= ~DEV_SUSPEND; | ||
1927 | if (link->state & DEV_CONFIG) | ||
1928 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1929 | |||
1930 | if (link->open) | ||
1931 | start_monitor(dev); | ||
1932 | |||
1933 | return 0; | ||
1934 | } | ||
1935 | |||
1931 | static void cm4000_release(dev_link_t *link) | 1936 | static void cm4000_release(dev_link_t *link) |
1932 | { | 1937 | { |
1933 | cmm_cm4000_release(link->priv); /* delay release until device closed */ | 1938 | cmm_cm4000_release(link->priv); /* delay release until device closed */ |
@@ -2044,6 +2049,8 @@ static struct pcmcia_driver cm4000_driver = { | |||
2044 | }, | 2049 | }, |
2045 | .attach = cm4000_attach, | 2050 | .attach = cm4000_attach, |
2046 | .detach = cm4000_detach, | 2051 | .detach = cm4000_detach, |
2052 | .suspend = cm4000_suspend, | ||
2053 | .resume = cm4000_resume, | ||
2047 | .event = cm4000_event, | 2054 | .event = cm4000_event, |
2048 | .id_table = cm4000_ids, | 2055 | .id_table = cm4000_ids, |
2049 | }; | 2056 | }; |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 4c698d908ffa..3622fd39c47b 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -656,31 +656,7 @@ static int reader_event(event_t event, int priority, | |||
656 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | 656 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); |
657 | link->state &= ~DEV_PRESENT; | 657 | link->state &= ~DEV_PRESENT; |
658 | break; | 658 | break; |
659 | case CS_EVENT_PM_SUSPEND: | 659 | |
660 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | ||
661 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
662 | link->state |= DEV_SUSPEND; | ||
663 | |||
664 | case CS_EVENT_RESET_PHYSICAL: | ||
665 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
666 | if (link->state & DEV_CONFIG) { | ||
667 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
668 | pcmcia_release_configuration(link->handle); | ||
669 | } | ||
670 | break; | ||
671 | case CS_EVENT_PM_RESUME: | ||
672 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
673 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
674 | link->state &= ~DEV_SUSPEND; | ||
675 | |||
676 | case CS_EVENT_CARD_RESET: | ||
677 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
678 | if ((link->state & DEV_CONFIG)) { | ||
679 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
680 | pcmcia_request_configuration(link->handle, | ||
681 | &link->conf); | ||
682 | } | ||
683 | break; | ||
684 | default: | 660 | default: |
685 | DEBUGP(5, dev, "reader_event: unknown event %.2x\n", | 661 | DEBUGP(5, dev, "reader_event: unknown event %.2x\n", |
686 | event); | 662 | event); |
@@ -690,6 +666,28 @@ static int reader_event(event_t event, int priority, | |||
690 | return CS_SUCCESS; | 666 | return CS_SUCCESS; |
691 | } | 667 | } |
692 | 668 | ||
669 | static int reader_suspend(struct pcmcia_device *p_dev) | ||
670 | { | ||
671 | dev_link_t *link = dev_to_instance(p_dev); | ||
672 | |||
673 | link->state |= DEV_SUSPEND; | ||
674 | if (link->state & DEV_CONFIG) | ||
675 | pcmcia_release_configuration(link->handle); | ||
676 | |||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | static int reader_resume(struct pcmcia_device *p_dev) | ||
681 | { | ||
682 | dev_link_t *link = dev_to_instance(p_dev); | ||
683 | |||
684 | link->state &= ~DEV_SUSPEND; | ||
685 | if (link->state & DEV_CONFIG) | ||
686 | pcmcia_request_configuration(link->handle, &link->conf); | ||
687 | |||
688 | return 0; | ||
689 | } | ||
690 | |||
693 | static void reader_release(dev_link_t *link) | 691 | static void reader_release(dev_link_t *link) |
694 | { | 692 | { |
695 | cm4040_reader_release(link->priv); | 693 | cm4040_reader_release(link->priv); |
@@ -806,6 +804,8 @@ static struct pcmcia_driver reader_driver = { | |||
806 | }, | 804 | }, |
807 | .attach = reader_attach, | 805 | .attach = reader_attach, |
808 | .detach = reader_detach, | 806 | .detach = reader_detach, |
807 | .suspend = reader_suspend, | ||
808 | .resume = reader_resume, | ||
809 | .event = reader_event, | 809 | .event = reader_event, |
810 | .id_table = cm4040_ids, | 810 | .id_table = cm4040_ids, |
811 | }; | 811 | }; |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 2c326ea53421..776103e56042 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -773,11 +773,37 @@ static void mgslpc_detach(dev_link_t *link) | |||
773 | mgslpc_remove_device((MGSLPC_INFO *)link->priv); | 773 | mgslpc_remove_device((MGSLPC_INFO *)link->priv); |
774 | } | 774 | } |
775 | 775 | ||
776 | static int mgslpc_suspend(struct pcmcia_device *dev) | ||
777 | { | ||
778 | dev_link_t *link = dev_to_instance(dev); | ||
779 | MGSLPC_INFO *info = link->priv; | ||
780 | |||
781 | link->state |= DEV_SUSPEND; | ||
782 | info->stop = 1; | ||
783 | if (link->state & DEV_CONFIG) | ||
784 | pcmcia_release_configuration(link->handle); | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | |||
789 | static int mgslpc_resume(struct pcmcia_device *dev) | ||
790 | { | ||
791 | dev_link_t *link = dev_to_instance(dev); | ||
792 | MGSLPC_INFO *info = link->priv; | ||
793 | |||
794 | link->state &= ~DEV_SUSPEND; | ||
795 | if (link->state & DEV_CONFIG) | ||
796 | pcmcia_request_configuration(link->handle, &link->conf); | ||
797 | info->stop = 0; | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | |||
776 | static int mgslpc_event(event_t event, int priority, | 803 | static int mgslpc_event(event_t event, int priority, |
777 | event_callback_args_t *args) | 804 | event_callback_args_t *args) |
778 | { | 805 | { |
779 | dev_link_t *link = args->client_data; | 806 | dev_link_t *link = args->client_data; |
780 | MGSLPC_INFO *info = link->priv; | ||
781 | 807 | ||
782 | if (debug_level >= DEBUG_LEVEL_INFO) | 808 | if (debug_level >= DEBUG_LEVEL_INFO) |
783 | printk("mgslpc_event(0x%06x)\n", event); | 809 | printk("mgslpc_event(0x%06x)\n", event); |
@@ -794,23 +820,6 @@ static int mgslpc_event(event_t event, int priority, | |||
794 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 820 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
795 | mgslpc_config(link); | 821 | mgslpc_config(link); |
796 | break; | 822 | break; |
797 | case CS_EVENT_PM_SUSPEND: | ||
798 | link->state |= DEV_SUSPEND; | ||
799 | /* Fall through... */ | ||
800 | case CS_EVENT_RESET_PHYSICAL: | ||
801 | /* Mark the device as stopped, to block IO until later */ | ||
802 | info->stop = 1; | ||
803 | if (link->state & DEV_CONFIG) | ||
804 | pcmcia_release_configuration(link->handle); | ||
805 | break; | ||
806 | case CS_EVENT_PM_RESUME: | ||
807 | link->state &= ~DEV_SUSPEND; | ||
808 | /* Fall through... */ | ||
809 | case CS_EVENT_CARD_RESET: | ||
810 | if (link->state & DEV_CONFIG) | ||
811 | pcmcia_request_configuration(link->handle, &link->conf); | ||
812 | info->stop = 0; | ||
813 | break; | ||
814 | } | 823 | } |
815 | return 0; | 824 | return 0; |
816 | } | 825 | } |
@@ -3095,6 +3104,8 @@ static struct pcmcia_driver mgslpc_driver = { | |||
3095 | .event = mgslpc_event, | 3104 | .event = mgslpc_event, |
3096 | .detach = mgslpc_detach, | 3105 | .detach = mgslpc_detach, |
3097 | .id_table = mgslpc_ids, | 3106 | .id_table = mgslpc_ids, |
3107 | .suspend = mgslpc_suspend, | ||
3108 | .resume = mgslpc_resume, | ||
3098 | }; | 3109 | }; |
3099 | 3110 | ||
3100 | static struct tty_operations mgslpc_ops = { | 3111 | static struct tty_operations mgslpc_ops = { |
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index ef79805218e4..982b74af8c29 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c | |||
@@ -406,6 +406,28 @@ void ide_release(dev_link_t *link) | |||
406 | 406 | ||
407 | } /* ide_release */ | 407 | } /* ide_release */ |
408 | 408 | ||
409 | static int ide_suspend(struct pcmcia_device *dev) | ||
410 | { | ||
411 | dev_link_t *link = dev_to_instance(dev); | ||
412 | |||
413 | link->state |= DEV_SUSPEND; | ||
414 | if (link->state & DEV_CONFIG) | ||
415 | pcmcia_release_configuration(link->handle); | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int ide_resume(struct pcmcia_device *dev) | ||
421 | { | ||
422 | dev_link_t *link = dev_to_instance(dev); | ||
423 | |||
424 | link->state &= ~DEV_SUSPEND; | ||
425 | if (DEV_OK(link)) | ||
426 | pcmcia_request_configuration(link->handle, &link->conf); | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
409 | /*====================================================================== | 431 | /*====================================================================== |
410 | 432 | ||
411 | The card status event handler. Mostly, this schedules other | 433 | The card status event handler. Mostly, this schedules other |
@@ -432,20 +454,6 @@ int ide_event(event_t event, int priority, | |||
432 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 454 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
433 | ide_config(link); | 455 | ide_config(link); |
434 | break; | 456 | break; |
435 | case CS_EVENT_PM_SUSPEND: | ||
436 | link->state |= DEV_SUSPEND; | ||
437 | /* Fall through... */ | ||
438 | case CS_EVENT_RESET_PHYSICAL: | ||
439 | if (link->state & DEV_CONFIG) | ||
440 | pcmcia_release_configuration(link->handle); | ||
441 | break; | ||
442 | case CS_EVENT_PM_RESUME: | ||
443 | link->state &= ~DEV_SUSPEND; | ||
444 | /* Fall through... */ | ||
445 | case CS_EVENT_CARD_RESET: | ||
446 | if (DEV_OK(link)) | ||
447 | pcmcia_request_configuration(link->handle, &link->conf); | ||
448 | break; | ||
449 | } | 457 | } |
450 | return 0; | 458 | return 0; |
451 | } /* ide_event */ | 459 | } /* ide_event */ |
@@ -498,6 +506,8 @@ static struct pcmcia_driver ide_cs_driver = { | |||
498 | .event = ide_event, | 506 | .event = ide_event, |
499 | .detach = ide_detach, | 507 | .detach = ide_detach, |
500 | .id_table = ide_ids, | 508 | .id_table = ide_ids, |
509 | .suspend = ide_suspend, | ||
510 | .resume = ide_resume, | ||
501 | }; | 511 | }; |
502 | 512 | ||
503 | static int __init init_ide_cs(void) | 513 | static int __init init_ide_cs(void) |
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 27391c32f3eb..6d9816e10ecb 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c | |||
@@ -430,6 +430,28 @@ static void avmcs_release(dev_link_t *link) | |||
430 | 430 | ||
431 | } /* avmcs_release */ | 431 | } /* avmcs_release */ |
432 | 432 | ||
433 | static int avmcs_suspend(struct pcmcia_device *dev) | ||
434 | { | ||
435 | dev_link_t *link = dev_to_instance(dev); | ||
436 | |||
437 | link->state |= DEV_SUSPEND; | ||
438 | if (link->state & DEV_CONFIG) | ||
439 | pcmcia_release_configuration(link->handle); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static int avmcs_resume(struct pcmcia_device *dev) | ||
445 | { | ||
446 | dev_link_t *link = dev_to_instance(dev); | ||
447 | |||
448 | link->state &= ~DEV_SUSPEND; | ||
449 | if (link->state & DEV_CONFIG) | ||
450 | pcmcia_request_configuration(link->handle, &link->conf); | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
433 | /*====================================================================== | 455 | /*====================================================================== |
434 | 456 | ||
435 | The card status event handler. Mostly, this schedules other | 457 | The card status event handler. Mostly, this schedules other |
@@ -459,20 +481,6 @@ static int avmcs_event(event_t event, int priority, | |||
459 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 481 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
460 | avmcs_config(link); | 482 | avmcs_config(link); |
461 | break; | 483 | break; |
462 | case CS_EVENT_PM_SUSPEND: | ||
463 | link->state |= DEV_SUSPEND; | ||
464 | /* Fall through... */ | ||
465 | case CS_EVENT_RESET_PHYSICAL: | ||
466 | if (link->state & DEV_CONFIG) | ||
467 | pcmcia_release_configuration(link->handle); | ||
468 | break; | ||
469 | case CS_EVENT_PM_RESUME: | ||
470 | link->state &= ~DEV_SUSPEND; | ||
471 | /* Fall through... */ | ||
472 | case CS_EVENT_CARD_RESET: | ||
473 | if (link->state & DEV_CONFIG) | ||
474 | pcmcia_request_configuration(link->handle, &link->conf); | ||
475 | break; | ||
476 | } | 484 | } |
477 | return 0; | 485 | return 0; |
478 | } /* avmcs_event */ | 486 | } /* avmcs_event */ |
@@ -494,6 +502,8 @@ static struct pcmcia_driver avmcs_driver = { | |||
494 | .event = avmcs_event, | 502 | .event = avmcs_event, |
495 | .detach = avmcs_detach, | 503 | .detach = avmcs_detach, |
496 | .id_table = avmcs_ids, | 504 | .id_table = avmcs_ids, |
505 | .suspend= avmcs_suspend, | ||
506 | .resume = avmcs_resume, | ||
497 | }; | 507 | }; |
498 | 508 | ||
499 | static int __init avmcs_init(void) | 509 | static int __init avmcs_init(void) |
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 5f5a5ae740d2..433cec4269a3 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c | |||
@@ -445,6 +445,28 @@ static void avma1cs_release(dev_link_t *link) | |||
445 | avma1cs_detach(link); | 445 | avma1cs_detach(link); |
446 | } /* avma1cs_release */ | 446 | } /* avma1cs_release */ |
447 | 447 | ||
448 | static int avma1cs_suspend(struct pcmcia_device *dev) | ||
449 | { | ||
450 | dev_link_t *link = dev_to_instance(dev); | ||
451 | |||
452 | link->state |= DEV_SUSPEND; | ||
453 | if (link->state & DEV_CONFIG) | ||
454 | pcmcia_release_configuration(link->handle); | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static int avma1cs_resume(struct pcmcia_device *dev) | ||
460 | { | ||
461 | dev_link_t *link = dev_to_instance(dev); | ||
462 | |||
463 | link->state &= ~DEV_SUSPEND; | ||
464 | if (link->state & DEV_CONFIG) | ||
465 | pcmcia_request_configuration(link->handle, &link->conf); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
448 | /*====================================================================== | 470 | /*====================================================================== |
449 | 471 | ||
450 | The card status event handler. Mostly, this schedules other | 472 | The card status event handler. Mostly, this schedules other |
@@ -475,20 +497,6 @@ static int avma1cs_event(event_t event, int priority, | |||
475 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 497 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
476 | avma1cs_config(link); | 498 | avma1cs_config(link); |
477 | break; | 499 | break; |
478 | case CS_EVENT_PM_SUSPEND: | ||
479 | link->state |= DEV_SUSPEND; | ||
480 | /* Fall through... */ | ||
481 | case CS_EVENT_RESET_PHYSICAL: | ||
482 | if (link->state & DEV_CONFIG) | ||
483 | pcmcia_release_configuration(link->handle); | ||
484 | break; | ||
485 | case CS_EVENT_PM_RESUME: | ||
486 | link->state &= ~DEV_SUSPEND; | ||
487 | /* Fall through... */ | ||
488 | case CS_EVENT_CARD_RESET: | ||
489 | if (link->state & DEV_CONFIG) | ||
490 | pcmcia_request_configuration(link->handle, &link->conf); | ||
491 | break; | ||
492 | } | 500 | } |
493 | return 0; | 501 | return 0; |
494 | } /* avma1cs_event */ | 502 | } /* avma1cs_event */ |
@@ -509,6 +517,8 @@ static struct pcmcia_driver avma1cs_driver = { | |||
509 | .event = avma1cs_event, | 517 | .event = avma1cs_event, |
510 | .detach = avma1cs_detach, | 518 | .detach = avma1cs_detach, |
511 | .id_table = avma1cs_ids, | 519 | .id_table = avma1cs_ids, |
520 | .suspend = avma1cs_suspend, | ||
521 | .resume = avma1cs_resume, | ||
512 | }; | 522 | }; |
513 | 523 | ||
514 | /*====================================================================*/ | 524 | /*====================================================================*/ |
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 6fc6868de0b0..0cbe04593d87 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c | |||
@@ -447,6 +447,32 @@ static void elsa_cs_release(dev_link_t *link) | |||
447 | link->state &= ~DEV_CONFIG; | 447 | link->state &= ~DEV_CONFIG; |
448 | } /* elsa_cs_release */ | 448 | } /* elsa_cs_release */ |
449 | 449 | ||
450 | static int elsa_suspend(struct pcmcia_device *p_dev) | ||
451 | { | ||
452 | dev_link_t *link = dev_to_instance(p_dev); | ||
453 | local_info_t *dev = link->priv; | ||
454 | |||
455 | link->state |= DEV_SUSPEND; | ||
456 | dev->busy = 1; | ||
457 | if (link->state & DEV_CONFIG) | ||
458 | pcmcia_release_configuration(link->handle); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | static int elsa_resume(struct pcmcia_device *p_dev) | ||
464 | { | ||
465 | dev_link_t *link = dev_to_instance(p_dev); | ||
466 | local_info_t *dev = link->priv; | ||
467 | |||
468 | link->state &= ~DEV_SUSPEND; | ||
469 | if (link->state & DEV_CONFIG) | ||
470 | pcmcia_request_configuration(link->handle, &link->conf); | ||
471 | dev->busy = 0; | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
450 | /*====================================================================== | 476 | /*====================================================================== |
451 | 477 | ||
452 | The card status event handler. Mostly, this schedules other | 478 | The card status event handler. Mostly, this schedules other |
@@ -465,7 +491,6 @@ static int elsa_cs_event(event_t event, int priority, | |||
465 | event_callback_args_t *args) | 491 | event_callback_args_t *args) |
466 | { | 492 | { |
467 | dev_link_t *link = args->client_data; | 493 | dev_link_t *link = args->client_data; |
468 | local_info_t *dev = link->priv; | ||
469 | 494 | ||
470 | DEBUG(1, "elsa_cs_event(%d)\n", event); | 495 | DEBUG(1, "elsa_cs_event(%d)\n", event); |
471 | 496 | ||
@@ -481,23 +506,6 @@ static int elsa_cs_event(event_t event, int priority, | |||
481 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 506 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
482 | elsa_cs_config(link); | 507 | elsa_cs_config(link); |
483 | break; | 508 | break; |
484 | case CS_EVENT_PM_SUSPEND: | ||
485 | link->state |= DEV_SUSPEND; | ||
486 | /* Fall through... */ | ||
487 | case CS_EVENT_RESET_PHYSICAL: | ||
488 | /* Mark the device as stopped, to block IO until later */ | ||
489 | dev->busy = 1; | ||
490 | if (link->state & DEV_CONFIG) | ||
491 | pcmcia_release_configuration(link->handle); | ||
492 | break; | ||
493 | case CS_EVENT_PM_RESUME: | ||
494 | link->state &= ~DEV_SUSPEND; | ||
495 | /* Fall through... */ | ||
496 | case CS_EVENT_CARD_RESET: | ||
497 | if (link->state & DEV_CONFIG) | ||
498 | pcmcia_request_configuration(link->handle, &link->conf); | ||
499 | dev->busy = 0; | ||
500 | break; | ||
501 | } | 509 | } |
502 | return 0; | 510 | return 0; |
503 | } /* elsa_cs_event */ | 511 | } /* elsa_cs_event */ |
@@ -518,6 +526,8 @@ static struct pcmcia_driver elsa_cs_driver = { | |||
518 | .event = elsa_cs_event, | 526 | .event = elsa_cs_event, |
519 | .detach = elsa_cs_detach, | 527 | .detach = elsa_cs_detach, |
520 | .id_table = elsa_ids, | 528 | .id_table = elsa_ids, |
529 | .suspend = elsa_suspend, | ||
530 | .resume = elsa_resume, | ||
521 | }; | 531 | }; |
522 | 532 | ||
523 | static int __init init_elsa_cs(void) | 533 | static int __init init_elsa_cs(void) |
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index dc334aab433e..27dce7c7b760 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -553,6 +553,32 @@ static void sedlbauer_release(dev_link_t *link) | |||
553 | 553 | ||
554 | } /* sedlbauer_release */ | 554 | } /* sedlbauer_release */ |
555 | 555 | ||
556 | static int sedlbauer_suspend(struct pcmcia_device *p_dev) | ||
557 | { | ||
558 | dev_link_t *link = dev_to_instance(p_dev); | ||
559 | local_info_t *dev = link->priv; | ||
560 | |||
561 | link->state |= DEV_SUSPEND; | ||
562 | dev->stop = 1; | ||
563 | if (link->state & DEV_CONFIG) | ||
564 | pcmcia_release_configuration(link->handle); | ||
565 | |||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | static int sedlbauer_resume(struct pcmcia_device *p_dev) | ||
570 | { | ||
571 | dev_link_t *link = dev_to_instance(p_dev); | ||
572 | local_info_t *dev = link->priv; | ||
573 | |||
574 | link->state &= ~DEV_SUSPEND; | ||
575 | if (link->state & DEV_CONFIG) | ||
576 | pcmcia_request_configuration(link->handle, &link->conf); | ||
577 | dev->stop = 0; | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
556 | /*====================================================================== | 582 | /*====================================================================== |
557 | 583 | ||
558 | The card status event handler. Mostly, this schedules other | 584 | The card status event handler. Mostly, this schedules other |
@@ -569,7 +595,6 @@ static int sedlbauer_event(event_t event, int priority, | |||
569 | event_callback_args_t *args) | 595 | event_callback_args_t *args) |
570 | { | 596 | { |
571 | dev_link_t *link = args->client_data; | 597 | dev_link_t *link = args->client_data; |
572 | local_info_t *dev = link->priv; | ||
573 | 598 | ||
574 | DEBUG(1, "sedlbauer_event(0x%06x)\n", event); | 599 | DEBUG(1, "sedlbauer_event(0x%06x)\n", event); |
575 | 600 | ||
@@ -585,27 +610,6 @@ static int sedlbauer_event(event_t event, int priority, | |||
585 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 610 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
586 | sedlbauer_config(link); | 611 | sedlbauer_config(link); |
587 | break; | 612 | break; |
588 | case CS_EVENT_PM_SUSPEND: | ||
589 | link->state |= DEV_SUSPEND; | ||
590 | /* Fall through... */ | ||
591 | case CS_EVENT_RESET_PHYSICAL: | ||
592 | /* Mark the device as stopped, to block IO until later */ | ||
593 | dev->stop = 1; | ||
594 | if (link->state & DEV_CONFIG) | ||
595 | pcmcia_release_configuration(link->handle); | ||
596 | break; | ||
597 | case CS_EVENT_PM_RESUME: | ||
598 | link->state &= ~DEV_SUSPEND; | ||
599 | /* Fall through... */ | ||
600 | case CS_EVENT_CARD_RESET: | ||
601 | if (link->state & DEV_CONFIG) | ||
602 | pcmcia_request_configuration(link->handle, &link->conf); | ||
603 | dev->stop = 0; | ||
604 | /* | ||
605 | In a normal driver, additional code may go here to restore | ||
606 | the device state and restart IO. | ||
607 | */ | ||
608 | break; | ||
609 | } | 613 | } |
610 | return 0; | 614 | return 0; |
611 | } /* sedlbauer_event */ | 615 | } /* sedlbauer_event */ |
@@ -631,6 +635,8 @@ static struct pcmcia_driver sedlbauer_driver = { | |||
631 | .event = sedlbauer_event, | 635 | .event = sedlbauer_event, |
632 | .detach = sedlbauer_detach, | 636 | .detach = sedlbauer_detach, |
633 | .id_table = sedlbauer_ids, | 637 | .id_table = sedlbauer_ids, |
638 | .suspend = sedlbauer_suspend, | ||
639 | .resume = sedlbauer_resume, | ||
634 | }; | 640 | }; |
635 | 641 | ||
636 | static int __init init_sedlbauer_cs(void) | 642 | static int __init init_sedlbauer_cs(void) |
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 0ddef1bf778b..70213bc1d30c 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c | |||
@@ -428,6 +428,32 @@ static void teles_cs_release(dev_link_t *link) | |||
428 | link->state &= ~DEV_CONFIG; | 428 | link->state &= ~DEV_CONFIG; |
429 | } /* teles_cs_release */ | 429 | } /* teles_cs_release */ |
430 | 430 | ||
431 | static int teles_suspend(struct pcmcia_device *p_dev) | ||
432 | { | ||
433 | dev_link_t *link = dev_to_instance(p_dev); | ||
434 | local_info_t *dev = link->priv; | ||
435 | |||
436 | link->state |= DEV_SUSPEND; | ||
437 | dev->busy = 1; | ||
438 | if (link->state & DEV_CONFIG) | ||
439 | pcmcia_release_configuration(link->handle); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static int teles_resume(struct pcmcia_device *p_dev) | ||
445 | { | ||
446 | dev_link_t *link = dev_to_instance(p_dev); | ||
447 | local_info_t *dev = link->priv; | ||
448 | |||
449 | link->state &= ~DEV_SUSPEND; | ||
450 | if (link->state & DEV_CONFIG) | ||
451 | pcmcia_request_configuration(link->handle, &link->conf); | ||
452 | dev->busy = 0; | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
431 | /*====================================================================== | 457 | /*====================================================================== |
432 | 458 | ||
433 | The card status event handler. Mostly, this schedules other | 459 | The card status event handler. Mostly, this schedules other |
@@ -446,7 +472,6 @@ static int teles_cs_event(event_t event, int priority, | |||
446 | event_callback_args_t *args) | 472 | event_callback_args_t *args) |
447 | { | 473 | { |
448 | dev_link_t *link = args->client_data; | 474 | dev_link_t *link = args->client_data; |
449 | local_info_t *dev = link->priv; | ||
450 | 475 | ||
451 | DEBUG(1, "teles_cs_event(%d)\n", event); | 476 | DEBUG(1, "teles_cs_event(%d)\n", event); |
452 | 477 | ||
@@ -462,23 +487,6 @@ static int teles_cs_event(event_t event, int priority, | |||
462 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 487 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
463 | teles_cs_config(link); | 488 | teles_cs_config(link); |
464 | break; | 489 | break; |
465 | case CS_EVENT_PM_SUSPEND: | ||
466 | link->state |= DEV_SUSPEND; | ||
467 | /* Fall through... */ | ||
468 | case CS_EVENT_RESET_PHYSICAL: | ||
469 | /* Mark the device as stopped, to block IO until later */ | ||
470 | dev->busy = 1; | ||
471 | if (link->state & DEV_CONFIG) | ||
472 | pcmcia_release_configuration(link->handle); | ||
473 | break; | ||
474 | case CS_EVENT_PM_RESUME: | ||
475 | link->state &= ~DEV_SUSPEND; | ||
476 | /* Fall through... */ | ||
477 | case CS_EVENT_CARD_RESET: | ||
478 | if (link->state & DEV_CONFIG) | ||
479 | pcmcia_request_configuration(link->handle, &link->conf); | ||
480 | dev->busy = 0; | ||
481 | break; | ||
482 | } | 490 | } |
483 | return 0; | 491 | return 0; |
484 | } /* teles_cs_event */ | 492 | } /* teles_cs_event */ |
@@ -498,6 +506,8 @@ static struct pcmcia_driver teles_cs_driver = { | |||
498 | .event = teles_cs_event, | 506 | .event = teles_cs_event, |
499 | .detach = teles_detach, | 507 | .detach = teles_detach, |
500 | .id_table = teles_ids, | 508 | .id_table = teles_ids, |
509 | .suspend = teles_suspend, | ||
510 | .resume = teles_resume, | ||
501 | }; | 511 | }; |
502 | 512 | ||
503 | static int __init init_teles_cs(void) | 513 | static int __init init_teles_cs(void) |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index af24216a0626..86443cf44dc6 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -691,6 +691,24 @@ static void pcmciamtd_config(dev_link_t *link) | |||
691 | } | 691 | } |
692 | 692 | ||
693 | 693 | ||
694 | static int pcmciamtd_suspend(struct pcmcia_device *dev) | ||
695 | { | ||
696 | DEBUG(2, "EVENT_PM_RESUME"); | ||
697 | |||
698 | /* get_lock(link); */ | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static int pcmciamtd_resume(struct pcmcia_device *dev) | ||
704 | { | ||
705 | DEBUG(2, "EVENT_PM_SUSPEND"); | ||
706 | |||
707 | /* free_lock(link); */ | ||
708 | |||
709 | return 0; | ||
710 | } | ||
711 | |||
694 | /* The card status event handler. Mostly, this schedules other | 712 | /* The card status event handler. Mostly, this schedules other |
695 | * stuff to run after an event is received. A CARD_REMOVAL event | 713 | * stuff to run after an event is received. A CARD_REMOVAL event |
696 | * also sets some flags to discourage the driver from trying | 714 | * also sets some flags to discourage the driver from trying |
@@ -721,22 +739,6 @@ static int pcmciamtd_event(event_t event, int priority, | |||
721 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 739 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
722 | pcmciamtd_config(link); | 740 | pcmciamtd_config(link); |
723 | break; | 741 | break; |
724 | case CS_EVENT_PM_SUSPEND: | ||
725 | DEBUG(2, "EVENT_PM_SUSPEND"); | ||
726 | link->state |= DEV_SUSPEND; | ||
727 | /* Fall through... */ | ||
728 | case CS_EVENT_RESET_PHYSICAL: | ||
729 | DEBUG(2, "EVENT_RESET_PHYSICAL"); | ||
730 | /* get_lock(link); */ | ||
731 | break; | ||
732 | case CS_EVENT_PM_RESUME: | ||
733 | DEBUG(2, "EVENT_PM_RESUME"); | ||
734 | link->state &= ~DEV_SUSPEND; | ||
735 | /* Fall through... */ | ||
736 | case CS_EVENT_CARD_RESET: | ||
737 | DEBUG(2, "EVENT_CARD_RESET"); | ||
738 | /* free_lock(link); */ | ||
739 | break; | ||
740 | default: | 742 | default: |
741 | DEBUG(2, "Unknown event %d", event); | 743 | DEBUG(2, "Unknown event %d", event); |
742 | } | 744 | } |
@@ -848,6 +850,8 @@ static struct pcmcia_driver pcmciamtd_driver = { | |||
848 | .detach = pcmciamtd_detach, | 850 | .detach = pcmciamtd_detach, |
849 | .owner = THIS_MODULE, | 851 | .owner = THIS_MODULE, |
850 | .id_table = pcmciamtd_ids, | 852 | .id_table = pcmciamtd_ids, |
853 | .suspend = pcmciamtd_suspend, | ||
854 | .resume = pcmciamtd_resume, | ||
851 | }; | 855 | }; |
852 | 856 | ||
853 | 857 | ||
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 71fd41122c91..80414a77fe75 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c | |||
@@ -547,6 +547,38 @@ static void tc574_release(dev_link_t *link) | |||
547 | link->state &= ~DEV_CONFIG; | 547 | link->state &= ~DEV_CONFIG; |
548 | } | 548 | } |
549 | 549 | ||
550 | static int tc574_suspend(struct pcmcia_device *p_dev) | ||
551 | { | ||
552 | dev_link_t *link = dev_to_instance(p_dev); | ||
553 | struct net_device *dev = link->priv; | ||
554 | |||
555 | link->state |= DEV_SUSPEND; | ||
556 | if (link->state & DEV_CONFIG) { | ||
557 | if (link->open) | ||
558 | netif_device_detach(dev); | ||
559 | pcmcia_release_configuration(link->handle); | ||
560 | } | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static int tc574_resume(struct pcmcia_device *p_dev) | ||
566 | { | ||
567 | dev_link_t *link = dev_to_instance(p_dev); | ||
568 | struct net_device *dev = link->priv; | ||
569 | |||
570 | link->state &= ~DEV_SUSPEND; | ||
571 | if (link->state & DEV_CONFIG) { | ||
572 | pcmcia_request_configuration(link->handle, &link->conf); | ||
573 | if (link->open) { | ||
574 | tc574_reset(dev); | ||
575 | netif_device_attach(dev); | ||
576 | } | ||
577 | } | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
550 | /* | 582 | /* |
551 | The card status event handler. Mostly, this schedules other | 583 | The card status event handler. Mostly, this schedules other |
552 | stuff to run after an event is received. A CARD_REMOVAL event | 584 | stuff to run after an event is received. A CARD_REMOVAL event |
@@ -572,28 +604,6 @@ static int tc574_event(event_t event, int priority, | |||
572 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 604 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
573 | tc574_config(link); | 605 | tc574_config(link); |
574 | break; | 606 | break; |
575 | case CS_EVENT_PM_SUSPEND: | ||
576 | link->state |= DEV_SUSPEND; | ||
577 | /* Fall through... */ | ||
578 | case CS_EVENT_RESET_PHYSICAL: | ||
579 | if (link->state & DEV_CONFIG) { | ||
580 | if (link->open) | ||
581 | netif_device_detach(dev); | ||
582 | pcmcia_release_configuration(link->handle); | ||
583 | } | ||
584 | break; | ||
585 | case CS_EVENT_PM_RESUME: | ||
586 | link->state &= ~DEV_SUSPEND; | ||
587 | /* Fall through... */ | ||
588 | case CS_EVENT_CARD_RESET: | ||
589 | if (link->state & DEV_CONFIG) { | ||
590 | pcmcia_request_configuration(link->handle, &link->conf); | ||
591 | if (link->open) { | ||
592 | tc574_reset(dev); | ||
593 | netif_device_attach(dev); | ||
594 | } | ||
595 | } | ||
596 | break; | ||
597 | } | 607 | } |
598 | return 0; | 608 | return 0; |
599 | } /* tc574_event */ | 609 | } /* tc574_event */ |
@@ -1296,6 +1306,8 @@ static struct pcmcia_driver tc574_driver = { | |||
1296 | .event = tc574_event, | 1306 | .event = tc574_event, |
1297 | .detach = tc574_detach, | 1307 | .detach = tc574_detach, |
1298 | .id_table = tc574_ids, | 1308 | .id_table = tc574_ids, |
1309 | .suspend = tc574_suspend, | ||
1310 | .resume = tc574_resume, | ||
1299 | }; | 1311 | }; |
1300 | 1312 | ||
1301 | static int __init init_tc574(void) | 1313 | static int __init init_tc574(void) |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index d83fdd8c1943..bbda681ac102 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -421,6 +421,38 @@ static void tc589_release(dev_link_t *link) | |||
421 | link->state &= ~DEV_CONFIG; | 421 | link->state &= ~DEV_CONFIG; |
422 | } | 422 | } |
423 | 423 | ||
424 | static int tc589_suspend(struct pcmcia_device *p_dev) | ||
425 | { | ||
426 | dev_link_t *link = dev_to_instance(p_dev); | ||
427 | struct net_device *dev = link->priv; | ||
428 | |||
429 | link->state |= DEV_SUSPEND; | ||
430 | if (link->state & DEV_CONFIG) { | ||
431 | if (link->open) | ||
432 | netif_device_detach(dev); | ||
433 | pcmcia_release_configuration(link->handle); | ||
434 | } | ||
435 | |||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static int tc589_resume(struct pcmcia_device *p_dev) | ||
440 | { | ||
441 | dev_link_t *link = dev_to_instance(p_dev); | ||
442 | struct net_device *dev = link->priv; | ||
443 | |||
444 | link->state &= ~DEV_SUSPEND; | ||
445 | if (link->state & DEV_CONFIG) { | ||
446 | pcmcia_request_configuration(link->handle, &link->conf); | ||
447 | if (link->open) { | ||
448 | tc589_reset(dev); | ||
449 | netif_device_attach(dev); | ||
450 | } | ||
451 | } | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
424 | /*====================================================================== | 456 | /*====================================================================== |
425 | 457 | ||
426 | The card status event handler. Mostly, this schedules other | 458 | The card status event handler. Mostly, this schedules other |
@@ -448,28 +480,6 @@ static int tc589_event(event_t event, int priority, | |||
448 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 480 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
449 | tc589_config(link); | 481 | tc589_config(link); |
450 | break; | 482 | break; |
451 | case CS_EVENT_PM_SUSPEND: | ||
452 | link->state |= DEV_SUSPEND; | ||
453 | /* Fall through... */ | ||
454 | case CS_EVENT_RESET_PHYSICAL: | ||
455 | if (link->state & DEV_CONFIG) { | ||
456 | if (link->open) | ||
457 | netif_device_detach(dev); | ||
458 | pcmcia_release_configuration(link->handle); | ||
459 | } | ||
460 | break; | ||
461 | case CS_EVENT_PM_RESUME: | ||
462 | link->state &= ~DEV_SUSPEND; | ||
463 | /* Fall through... */ | ||
464 | case CS_EVENT_CARD_RESET: | ||
465 | if (link->state & DEV_CONFIG) { | ||
466 | pcmcia_request_configuration(link->handle, &link->conf); | ||
467 | if (link->open) { | ||
468 | tc589_reset(dev); | ||
469 | netif_device_attach(dev); | ||
470 | } | ||
471 | } | ||
472 | break; | ||
473 | } | 483 | } |
474 | return 0; | 484 | return 0; |
475 | } /* tc589_event */ | 485 | } /* tc589_event */ |
@@ -1071,6 +1081,8 @@ static struct pcmcia_driver tc589_driver = { | |||
1071 | .event = tc589_event, | 1081 | .event = tc589_event, |
1072 | .detach = tc589_detach, | 1082 | .detach = tc589_detach, |
1073 | .id_table = tc589_ids, | 1083 | .id_table = tc589_ids, |
1084 | .suspend = tc589_suspend, | ||
1085 | .resume = tc589_resume, | ||
1074 | }; | 1086 | }; |
1075 | 1087 | ||
1076 | static int __init init_tc589(void) | 1088 | static int __init init_tc589(void) |
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 8bb4e85689ea..6c6b25265659 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -490,6 +490,40 @@ static void axnet_release(dev_link_t *link) | |||
490 | link->state &= ~DEV_CONFIG; | 490 | link->state &= ~DEV_CONFIG; |
491 | } | 491 | } |
492 | 492 | ||
493 | static int axnet_suspend(struct pcmcia_device *p_dev) | ||
494 | { | ||
495 | dev_link_t *link = dev_to_instance(p_dev); | ||
496 | struct net_device *dev = link->priv; | ||
497 | |||
498 | link->state |= DEV_SUSPEND; | ||
499 | if (link->state & DEV_CONFIG) { | ||
500 | if (link->open) | ||
501 | netif_device_detach(dev); | ||
502 | pcmcia_release_configuration(link->handle); | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int axnet_resume(struct pcmcia_device *p_dev) | ||
509 | { | ||
510 | dev_link_t *link = dev_to_instance(p_dev); | ||
511 | struct net_device *dev = link->priv; | ||
512 | |||
513 | link->state &= ~DEV_SUSPEND; | ||
514 | if (link->state & DEV_CONFIG) { | ||
515 | pcmcia_request_configuration(link->handle, &link->conf); | ||
516 | if (link->open) { | ||
517 | axnet_reset_8390(dev); | ||
518 | AX88190_init(dev, 1); | ||
519 | netif_device_attach(dev); | ||
520 | } | ||
521 | } | ||
522 | |||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | |||
493 | /*====================================================================== | 527 | /*====================================================================== |
494 | 528 | ||
495 | The card status event handler. Mostly, this schedules other | 529 | The card status event handler. Mostly, this schedules other |
@@ -517,29 +551,6 @@ static int axnet_event(event_t event, int priority, | |||
517 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 551 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
518 | axnet_config(link); | 552 | axnet_config(link); |
519 | break; | 553 | break; |
520 | case CS_EVENT_PM_SUSPEND: | ||
521 | link->state |= DEV_SUSPEND; | ||
522 | /* Fall through... */ | ||
523 | case CS_EVENT_RESET_PHYSICAL: | ||
524 | if (link->state & DEV_CONFIG) { | ||
525 | if (link->open) | ||
526 | netif_device_detach(dev); | ||
527 | pcmcia_release_configuration(link->handle); | ||
528 | } | ||
529 | break; | ||
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 | pcmcia_request_configuration(link->handle, &link->conf); | ||
536 | if (link->open) { | ||
537 | axnet_reset_8390(dev); | ||
538 | AX88190_init(dev, 1); | ||
539 | netif_device_attach(dev); | ||
540 | } | ||
541 | } | ||
542 | break; | ||
543 | } | 554 | } |
544 | return 0; | 555 | return 0; |
545 | } /* axnet_event */ | 556 | } /* axnet_event */ |
@@ -881,6 +892,8 @@ static struct pcmcia_driver axnet_cs_driver = { | |||
881 | .event = axnet_event, | 892 | .event = axnet_event, |
882 | .detach = axnet_detach, | 893 | .detach = axnet_detach, |
883 | .id_table = axnet_ids, | 894 | .id_table = axnet_ids, |
895 | .suspend = axnet_suspend, | ||
896 | .resume = axnet_resume, | ||
884 | }; | 897 | }; |
885 | 898 | ||
886 | static int __init init_axnet_cs(void) | 899 | static int __init init_axnet_cs(void) |
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index b9355d9498a3..68612222de6e 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c | |||
@@ -421,6 +421,42 @@ static void com20020_release(dev_link_t *link) | |||
421 | link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); | 421 | link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); |
422 | } | 422 | } |
423 | 423 | ||
424 | static int com20020_suspend(struct pcmcia_device *p_dev) | ||
425 | { | ||
426 | dev_link_t *link = dev_to_instance(p_dev); | ||
427 | com20020_dev_t *info = link->priv; | ||
428 | struct net_device *dev = info->dev; | ||
429 | |||
430 | link->state |= DEV_SUSPEND; | ||
431 | if (link->state & DEV_CONFIG) { | ||
432 | if (link->open) { | ||
433 | netif_device_detach(dev); | ||
434 | } | ||
435 | pcmcia_release_configuration(link->handle); | ||
436 | } | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int com20020_resume(struct pcmcia_device *p_dev) | ||
442 | { | ||
443 | dev_link_t *link = dev_to_instance(p_dev); | ||
444 | com20020_dev_t *info = link->priv; | ||
445 | struct net_device *dev = info->dev; | ||
446 | |||
447 | link->state &= ~DEV_SUSPEND; | ||
448 | if (link->state & DEV_CONFIG) { | ||
449 | pcmcia_request_configuration(link->handle, &link->conf); | ||
450 | if (link->open) { | ||
451 | int ioaddr = dev->base_addr; | ||
452 | struct arcnet_local *lp = dev->priv; | ||
453 | ARCRESET; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
424 | /*====================================================================== | 460 | /*====================================================================== |
425 | 461 | ||
426 | The card status event handler. Mostly, this schedules other | 462 | The card status event handler. Mostly, this schedules other |
@@ -449,30 +485,6 @@ static int com20020_event(event_t event, int priority, | |||
449 | link->state |= DEV_PRESENT; | 485 | link->state |= DEV_PRESENT; |
450 | com20020_config(link); | 486 | com20020_config(link); |
451 | break; | 487 | break; |
452 | case CS_EVENT_PM_SUSPEND: | ||
453 | link->state |= DEV_SUSPEND; | ||
454 | /* Fall through... */ | ||
455 | case CS_EVENT_RESET_PHYSICAL: | ||
456 | if (link->state & DEV_CONFIG) { | ||
457 | if (link->open) { | ||
458 | netif_device_detach(dev); | ||
459 | } | ||
460 | pcmcia_release_configuration(link->handle); | ||
461 | } | ||
462 | break; | ||
463 | case CS_EVENT_PM_RESUME: | ||
464 | link->state &= ~DEV_SUSPEND; | ||
465 | /* Fall through... */ | ||
466 | case CS_EVENT_CARD_RESET: | ||
467 | if (link->state & DEV_CONFIG) { | ||
468 | pcmcia_request_configuration(link->handle, &link->conf); | ||
469 | if (link->open) { | ||
470 | int ioaddr = dev->base_addr; | ||
471 | struct arcnet_local *lp = dev->priv; | ||
472 | ARCRESET; | ||
473 | } | ||
474 | } | ||
475 | break; | ||
476 | } | 488 | } |
477 | return 0; | 489 | return 0; |
478 | } /* com20020_event */ | 490 | } /* com20020_event */ |
@@ -492,6 +504,8 @@ static struct pcmcia_driver com20020_cs_driver = { | |||
492 | .event = com20020_event, | 504 | .event = com20020_event, |
493 | .detach = com20020_detach, | 505 | .detach = com20020_detach, |
494 | .id_table = com20020_ids, | 506 | .id_table = com20020_ids, |
507 | .suspend = com20020_suspend, | ||
508 | .resume = com20020_resume, | ||
495 | }; | 509 | }; |
496 | 510 | ||
497 | static int __init init_com20020_cs(void) | 511 | static int __init init_com20020_cs(void) |
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 356f50909222..388ecade13de 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c | |||
@@ -713,6 +713,39 @@ static void fmvj18x_release(dev_link_t *link) | |||
713 | link->state &= ~DEV_CONFIG; | 713 | link->state &= ~DEV_CONFIG; |
714 | } | 714 | } |
715 | 715 | ||
716 | static int fmvj18x_suspend(struct pcmcia_device *p_dev) | ||
717 | { | ||
718 | dev_link_t *link = dev_to_instance(p_dev); | ||
719 | struct net_device *dev = link->priv; | ||
720 | |||
721 | link->state |= DEV_SUSPEND; | ||
722 | if (link->state & DEV_CONFIG) { | ||
723 | if (link->open) | ||
724 | netif_device_detach(dev); | ||
725 | pcmcia_release_configuration(link->handle); | ||
726 | } | ||
727 | |||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static int fmvj18x_resume(struct pcmcia_device *p_dev) | ||
733 | { | ||
734 | dev_link_t *link = dev_to_instance(p_dev); | ||
735 | struct net_device *dev = link->priv; | ||
736 | |||
737 | link->state &= ~DEV_SUSPEND; | ||
738 | if (link->state & DEV_CONFIG) { | ||
739 | pcmcia_request_configuration(link->handle, &link->conf); | ||
740 | if (link->open) { | ||
741 | fjn_reset(dev); | ||
742 | netif_device_attach(dev); | ||
743 | } | ||
744 | } | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
716 | /*====================================================================*/ | 749 | /*====================================================================*/ |
717 | 750 | ||
718 | static int fmvj18x_event(event_t event, int priority, | 751 | static int fmvj18x_event(event_t event, int priority, |
@@ -733,28 +766,6 @@ static int fmvj18x_event(event_t event, int priority, | |||
733 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 766 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
734 | fmvj18x_config(link); | 767 | fmvj18x_config(link); |
735 | break; | 768 | break; |
736 | case CS_EVENT_PM_SUSPEND: | ||
737 | link->state |= DEV_SUSPEND; | ||
738 | /* Fall through... */ | ||
739 | case CS_EVENT_RESET_PHYSICAL: | ||
740 | if (link->state & DEV_CONFIG) { | ||
741 | if (link->open) | ||
742 | netif_device_detach(dev); | ||
743 | pcmcia_release_configuration(link->handle); | ||
744 | } | ||
745 | break; | ||
746 | case CS_EVENT_PM_RESUME: | ||
747 | link->state &= ~DEV_SUSPEND; | ||
748 | /* Fall through... */ | ||
749 | case CS_EVENT_CARD_RESET: | ||
750 | if (link->state & DEV_CONFIG) { | ||
751 | pcmcia_request_configuration(link->handle, &link->conf); | ||
752 | if (link->open) { | ||
753 | fjn_reset(dev); | ||
754 | netif_device_attach(dev); | ||
755 | } | ||
756 | } | ||
757 | break; | ||
758 | } | 769 | } |
759 | return 0; | 770 | return 0; |
760 | } /* fmvj18x_event */ | 771 | } /* fmvj18x_event */ |
@@ -793,6 +804,8 @@ static struct pcmcia_driver fmvj18x_cs_driver = { | |||
793 | .event = fmvj18x_event, | 804 | .event = fmvj18x_event, |
794 | .detach = fmvj18x_detach, | 805 | .detach = fmvj18x_detach, |
795 | .id_table = fmvj18x_ids, | 806 | .id_table = fmvj18x_ids, |
807 | .suspend = fmvj18x_suspend, | ||
808 | .resume = fmvj18x_resume, | ||
796 | }; | 809 | }; |
797 | 810 | ||
798 | static int __init init_fmvj18x_cs(void) | 811 | static int __init init_fmvj18x_cs(void) |
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index b6c140eb9799..3a7218e51b73 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c | |||
@@ -401,6 +401,41 @@ static void ibmtr_release(dev_link_t *link) | |||
401 | link->state &= ~DEV_CONFIG; | 401 | link->state &= ~DEV_CONFIG; |
402 | } | 402 | } |
403 | 403 | ||
404 | static int ibmtr_suspend(struct pcmcia_device *p_dev) | ||
405 | { | ||
406 | dev_link_t *link = dev_to_instance(p_dev); | ||
407 | ibmtr_dev_t *info = link->priv; | ||
408 | struct net_device *dev = info->dev; | ||
409 | |||
410 | link->state |= DEV_SUSPEND; | ||
411 | if (link->state & DEV_CONFIG) { | ||
412 | if (link->open) | ||
413 | netif_device_detach(dev); | ||
414 | pcmcia_release_configuration(link->handle); | ||
415 | } | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int ibmtr_resume(struct pcmcia_device *p_dev) | ||
421 | { | ||
422 | dev_link_t *link = dev_to_instance(p_dev); | ||
423 | ibmtr_dev_t *info = link->priv; | ||
424 | struct net_device *dev = info->dev; | ||
425 | |||
426 | link->state &= ~DEV_SUSPEND; | ||
427 | if (link->state & DEV_CONFIG) { | ||
428 | pcmcia_request_configuration(link->handle, &link->conf); | ||
429 | if (link->open) { | ||
430 | ibmtr_probe(dev); /* really? */ | ||
431 | netif_device_attach(dev); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | |||
404 | /*====================================================================== | 439 | /*====================================================================== |
405 | 440 | ||
406 | The card status event handler. Mostly, this schedules other | 441 | The card status event handler. Mostly, this schedules other |
@@ -433,28 +468,6 @@ static int ibmtr_event(event_t event, int priority, | |||
433 | link->state |= DEV_PRESENT; | 468 | link->state |= DEV_PRESENT; |
434 | ibmtr_config(link); | 469 | ibmtr_config(link); |
435 | break; | 470 | break; |
436 | case CS_EVENT_PM_SUSPEND: | ||
437 | link->state |= DEV_SUSPEND; | ||
438 | /* Fall through... */ | ||
439 | case CS_EVENT_RESET_PHYSICAL: | ||
440 | if (link->state & DEV_CONFIG) { | ||
441 | if (link->open) | ||
442 | netif_device_detach(dev); | ||
443 | pcmcia_release_configuration(link->handle); | ||
444 | } | ||
445 | break; | ||
446 | case CS_EVENT_PM_RESUME: | ||
447 | link->state &= ~DEV_SUSPEND; | ||
448 | /* Fall through... */ | ||
449 | case CS_EVENT_CARD_RESET: | ||
450 | if (link->state & DEV_CONFIG) { | ||
451 | pcmcia_request_configuration(link->handle, &link->conf); | ||
452 | if (link->open) { | ||
453 | ibmtr_probe(dev); /* really? */ | ||
454 | netif_device_attach(dev); | ||
455 | } | ||
456 | } | ||
457 | break; | ||
458 | } | 471 | } |
459 | return 0; | 472 | return 0; |
460 | } /* ibmtr_event */ | 473 | } /* ibmtr_event */ |
@@ -518,6 +531,8 @@ static struct pcmcia_driver ibmtr_cs_driver = { | |||
518 | .event = ibmtr_event, | 531 | .event = ibmtr_event, |
519 | .detach = ibmtr_detach, | 532 | .detach = ibmtr_detach, |
520 | .id_table = ibmtr_ids, | 533 | .id_table = ibmtr_ids, |
534 | .suspend = ibmtr_suspend, | ||
535 | .resume = ibmtr_resume, | ||
521 | }; | 536 | }; |
522 | 537 | ||
523 | static int __init init_ibmtr_cs(void) | 538 | static int __init init_ibmtr_cs(void) |
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 980d7e5d66cb..fa4921f8b9fc 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
@@ -801,6 +801,39 @@ static void nmclan_release(dev_link_t *link) | |||
801 | link->state &= ~DEV_CONFIG; | 801 | link->state &= ~DEV_CONFIG; |
802 | } | 802 | } |
803 | 803 | ||
804 | static int nmclan_suspend(struct pcmcia_device *p_dev) | ||
805 | { | ||
806 | dev_link_t *link = dev_to_instance(p_dev); | ||
807 | struct net_device *dev = link->priv; | ||
808 | |||
809 | link->state |= DEV_SUSPEND; | ||
810 | if (link->state & DEV_CONFIG) { | ||
811 | if (link->open) | ||
812 | netif_device_detach(dev); | ||
813 | pcmcia_release_configuration(link->handle); | ||
814 | } | ||
815 | |||
816 | |||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | static int nmclan_resume(struct pcmcia_device *p_dev) | ||
821 | { | ||
822 | dev_link_t *link = dev_to_instance(p_dev); | ||
823 | struct net_device *dev = link->priv; | ||
824 | |||
825 | link->state &= ~DEV_SUSPEND; | ||
826 | if (link->state & DEV_CONFIG) { | ||
827 | pcmcia_request_configuration(link->handle, &link->conf); | ||
828 | if (link->open) { | ||
829 | nmclan_reset(dev); | ||
830 | netif_device_attach(dev); | ||
831 | } | ||
832 | } | ||
833 | |||
834 | return 0; | ||
835 | } | ||
836 | |||
804 | /* ---------------------------------------------------------------------------- | 837 | /* ---------------------------------------------------------------------------- |
805 | nmclan_event | 838 | nmclan_event |
806 | The card status event handler. Mostly, this schedules other | 839 | The card status event handler. Mostly, this schedules other |
@@ -826,28 +859,6 @@ static int nmclan_event(event_t event, int priority, | |||
826 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 859 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
827 | nmclan_config(link); | 860 | nmclan_config(link); |
828 | break; | 861 | break; |
829 | case CS_EVENT_PM_SUSPEND: | ||
830 | link->state |= DEV_SUSPEND; | ||
831 | /* Fall through... */ | ||
832 | case CS_EVENT_RESET_PHYSICAL: | ||
833 | if (link->state & DEV_CONFIG) { | ||
834 | if (link->open) | ||
835 | netif_device_detach(dev); | ||
836 | pcmcia_release_configuration(link->handle); | ||
837 | } | ||
838 | break; | ||
839 | case CS_EVENT_PM_RESUME: | ||
840 | link->state &= ~DEV_SUSPEND; | ||
841 | /* Fall through... */ | ||
842 | case CS_EVENT_CARD_RESET: | ||
843 | if (link->state & DEV_CONFIG) { | ||
844 | pcmcia_request_configuration(link->handle, &link->conf); | ||
845 | if (link->open) { | ||
846 | nmclan_reset(dev); | ||
847 | netif_device_attach(dev); | ||
848 | } | ||
849 | } | ||
850 | break; | ||
851 | case CS_EVENT_RESET_REQUEST: | 862 | case CS_EVENT_RESET_REQUEST: |
852 | return 1; | 863 | return 1; |
853 | break; | 864 | break; |
@@ -1685,6 +1696,8 @@ static struct pcmcia_driver nmclan_cs_driver = { | |||
1685 | .event = nmclan_event, | 1696 | .event = nmclan_event, |
1686 | .detach = nmclan_detach, | 1697 | .detach = nmclan_detach, |
1687 | .id_table = nmclan_ids, | 1698 | .id_table = nmclan_ids, |
1699 | .suspend = nmclan_suspend, | ||
1700 | .resume = nmclan_resume, | ||
1688 | }; | 1701 | }; |
1689 | 1702 | ||
1690 | static int __init init_nmclan_cs(void) | 1703 | static int __init init_nmclan_cs(void) |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 818c185d6438..7db4d6f3db45 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -780,6 +780,39 @@ static void pcnet_release(dev_link_t *link) | |||
780 | 780 | ||
781 | ======================================================================*/ | 781 | ======================================================================*/ |
782 | 782 | ||
783 | static int pcnet_suspend(struct pcmcia_device *p_dev) | ||
784 | { | ||
785 | dev_link_t *link = dev_to_instance(p_dev); | ||
786 | struct net_device *dev = link->priv; | ||
787 | |||
788 | link->state |= DEV_SUSPEND; | ||
789 | if (link->state & DEV_CONFIG) { | ||
790 | if (link->open) | ||
791 | netif_device_detach(dev); | ||
792 | pcmcia_release_configuration(link->handle); | ||
793 | } | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | static int pcnet_resume(struct pcmcia_device *p_dev) | ||
799 | { | ||
800 | dev_link_t *link = dev_to_instance(p_dev); | ||
801 | struct net_device *dev = link->priv; | ||
802 | |||
803 | link->state &= ~DEV_SUSPEND; | ||
804 | if (link->state & DEV_CONFIG) { | ||
805 | pcmcia_request_configuration(link->handle, &link->conf); | ||
806 | if (link->open) { | ||
807 | pcnet_reset_8390(dev); | ||
808 | NS8390_init(dev, 1); | ||
809 | netif_device_attach(dev); | ||
810 | } | ||
811 | } | ||
812 | |||
813 | return 0; | ||
814 | } | ||
815 | |||
783 | static int pcnet_event(event_t event, int priority, | 816 | static int pcnet_event(event_t event, int priority, |
784 | event_callback_args_t *args) | 817 | event_callback_args_t *args) |
785 | { | 818 | { |
@@ -798,29 +831,6 @@ static int pcnet_event(event_t event, int priority, | |||
798 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 831 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
799 | pcnet_config(link); | 832 | pcnet_config(link); |
800 | break; | 833 | break; |
801 | case CS_EVENT_PM_SUSPEND: | ||
802 | link->state |= DEV_SUSPEND; | ||
803 | /* Fall through... */ | ||
804 | case CS_EVENT_RESET_PHYSICAL: | ||
805 | if (link->state & DEV_CONFIG) { | ||
806 | if (link->open) | ||
807 | netif_device_detach(dev); | ||
808 | pcmcia_release_configuration(link->handle); | ||
809 | } | ||
810 | break; | ||
811 | case CS_EVENT_PM_RESUME: | ||
812 | link->state &= ~DEV_SUSPEND; | ||
813 | /* Fall through... */ | ||
814 | case CS_EVENT_CARD_RESET: | ||
815 | if (link->state & DEV_CONFIG) { | ||
816 | pcmcia_request_configuration(link->handle, &link->conf); | ||
817 | if (link->open) { | ||
818 | pcnet_reset_8390(dev); | ||
819 | NS8390_init(dev, 1); | ||
820 | netif_device_attach(dev); | ||
821 | } | ||
822 | } | ||
823 | break; | ||
824 | } | 834 | } |
825 | return 0; | 835 | return 0; |
826 | } /* pcnet_event */ | 836 | } /* pcnet_event */ |
@@ -1849,6 +1859,8 @@ static struct pcmcia_driver pcnet_driver = { | |||
1849 | .detach = pcnet_detach, | 1859 | .detach = pcnet_detach, |
1850 | .owner = THIS_MODULE, | 1860 | .owner = THIS_MODULE, |
1851 | .id_table = pcnet_ids, | 1861 | .id_table = pcnet_ids, |
1862 | .suspend = pcnet_suspend, | ||
1863 | .resume = pcnet_resume, | ||
1852 | }; | 1864 | }; |
1853 | 1865 | ||
1854 | static int __init init_pcnet_cs(void) | 1866 | static int __init init_pcnet_cs(void) |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index c7cca842e5ee..7c61ec90c2c3 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -895,6 +895,62 @@ free_cfg_mem: | |||
895 | return rc; | 895 | return rc; |
896 | } | 896 | } |
897 | 897 | ||
898 | static int smc91c92_suspend(struct pcmcia_device *p_dev) | ||
899 | { | ||
900 | dev_link_t *link = dev_to_instance(p_dev); | ||
901 | struct net_device *dev = link->priv; | ||
902 | |||
903 | link->state |= DEV_SUSPEND; | ||
904 | if (link->state & DEV_CONFIG) { | ||
905 | if (link->open) | ||
906 | netif_device_detach(dev); | ||
907 | pcmcia_release_configuration(link->handle); | ||
908 | } | ||
909 | |||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | static int smc91c92_resume(struct pcmcia_device *p_dev) | ||
914 | { | ||
915 | dev_link_t *link = dev_to_instance(p_dev); | ||
916 | struct net_device *dev = link->priv; | ||
917 | struct smc_private *smc = netdev_priv(dev); | ||
918 | int i; | ||
919 | |||
920 | link->state &= ~DEV_SUSPEND; | ||
921 | if (link->state & DEV_CONFIG) { | ||
922 | if ((smc->manfid == MANFID_MEGAHERTZ) && | ||
923 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | ||
924 | mhz_3288_power(link); | ||
925 | pcmcia_request_configuration(link->handle, &link->conf); | ||
926 | if (smc->manfid == MANFID_MOTOROLA) | ||
927 | mot_config(link); | ||
928 | if ((smc->manfid == MANFID_OSITECH) && | ||
929 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
930 | /* Power up the card and enable interrupts */ | ||
931 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); | ||
932 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); | ||
933 | } | ||
934 | if (((smc->manfid == MANFID_OSITECH) && | ||
935 | (smc->cardid == PRODID_OSITECH_SEVEN)) || | ||
936 | ((smc->manfid == MANFID_PSION) && | ||
937 | (smc->cardid == PRODID_PSION_NET100))) { | ||
938 | /* Download the Seven of Diamonds firmware */ | ||
939 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
940 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
941 | udelay(50); | ||
942 | } | ||
943 | } | ||
944 | if (link->open) { | ||
945 | smc_reset(dev); | ||
946 | netif_device_attach(dev); | ||
947 | } | ||
948 | } | ||
949 | |||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | |||
898 | /*====================================================================== | 954 | /*====================================================================== |
899 | 955 | ||
900 | This verifies that the chip is some SMC91cXX variant, and returns | 956 | This verifies that the chip is some SMC91cXX variant, and returns |
@@ -935,14 +991,12 @@ static int check_sig(dev_link_t *link) | |||
935 | } | 991 | } |
936 | 992 | ||
937 | if (width) { | 993 | if (width) { |
938 | event_callback_args_t args; | ||
939 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); | 994 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); |
940 | args.client_data = link; | 995 | smc91c92_suspend(link->handle); |
941 | smc91c92_event(CS_EVENT_RESET_PHYSICAL, 0, &args); | ||
942 | pcmcia_release_io(link->handle, &link->io); | 996 | pcmcia_release_io(link->handle, &link->io); |
943 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 997 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
944 | pcmcia_request_io(link->handle, &link->io); | 998 | pcmcia_request_io(link->handle, &link->io); |
945 | smc91c92_event(CS_EVENT_CARD_RESET, 0, &args); | 999 | smc91c92_resume(link->handle); |
946 | return check_sig(link); | 1000 | return check_sig(link); |
947 | } | 1001 | } |
948 | return -ENODEV; | 1002 | return -ENODEV; |
@@ -1184,8 +1238,6 @@ static int smc91c92_event(event_t event, int priority, | |||
1184 | { | 1238 | { |
1185 | dev_link_t *link = args->client_data; | 1239 | dev_link_t *link = args->client_data; |
1186 | struct net_device *dev = link->priv; | 1240 | struct net_device *dev = link->priv; |
1187 | struct smc_private *smc = netdev_priv(dev); | ||
1188 | int i; | ||
1189 | 1241 | ||
1190 | DEBUG(1, "smc91c92_event(0x%06x)\n", event); | 1242 | DEBUG(1, "smc91c92_event(0x%06x)\n", event); |
1191 | 1243 | ||
@@ -1199,49 +1251,6 @@ static int smc91c92_event(event_t event, int priority, | |||
1199 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 1251 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
1200 | smc91c92_config(link); | 1252 | smc91c92_config(link); |
1201 | break; | 1253 | break; |
1202 | case CS_EVENT_PM_SUSPEND: | ||
1203 | link->state |= DEV_SUSPEND; | ||
1204 | /* Fall through... */ | ||
1205 | case CS_EVENT_RESET_PHYSICAL: | ||
1206 | if (link->state & DEV_CONFIG) { | ||
1207 | if (link->open) | ||
1208 | netif_device_detach(dev); | ||
1209 | pcmcia_release_configuration(link->handle); | ||
1210 | } | ||
1211 | break; | ||
1212 | case CS_EVENT_PM_RESUME: | ||
1213 | link->state &= ~DEV_SUSPEND; | ||
1214 | /* Fall through... */ | ||
1215 | case CS_EVENT_CARD_RESET: | ||
1216 | if (link->state & DEV_CONFIG) { | ||
1217 | if ((smc->manfid == MANFID_MEGAHERTZ) && | ||
1218 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | ||
1219 | mhz_3288_power(link); | ||
1220 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1221 | if (smc->manfid == MANFID_MOTOROLA) | ||
1222 | mot_config(link); | ||
1223 | if ((smc->manfid == MANFID_OSITECH) && | ||
1224 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
1225 | /* Power up the card and enable interrupts */ | ||
1226 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); | ||
1227 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); | ||
1228 | } | ||
1229 | if (((smc->manfid == MANFID_OSITECH) && | ||
1230 | (smc->cardid == PRODID_OSITECH_SEVEN)) || | ||
1231 | ((smc->manfid == MANFID_PSION) && | ||
1232 | (smc->cardid == PRODID_PSION_NET100))) { | ||
1233 | /* Download the Seven of Diamonds firmware */ | ||
1234 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
1235 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
1236 | udelay(50); | ||
1237 | } | ||
1238 | } | ||
1239 | if (link->open) { | ||
1240 | smc_reset(dev); | ||
1241 | netif_device_attach(dev); | ||
1242 | } | ||
1243 | } | ||
1244 | break; | ||
1245 | } | 1254 | } |
1246 | return 0; | 1255 | return 0; |
1247 | } /* smc91c92_event */ | 1256 | } /* smc91c92_event */ |
@@ -2364,6 +2373,8 @@ static struct pcmcia_driver smc91c92_cs_driver = { | |||
2364 | .event = smc91c92_event, | 2373 | .event = smc91c92_event, |
2365 | .detach = smc91c92_detach, | 2374 | .detach = smc91c92_detach, |
2366 | .id_table = smc91c92_ids, | 2375 | .id_table = smc91c92_ids, |
2376 | .suspend = smc91c92_suspend, | ||
2377 | .resume = smc91c92_resume, | ||
2367 | }; | 2378 | }; |
2368 | 2379 | ||
2369 | static int __init init_smc91c92_cs(void) | 2380 | static int __init init_smc91c92_cs(void) |
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index ce143f08638a..917e50ac37f3 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c | |||
@@ -1157,6 +1157,41 @@ xirc2ps_release(dev_link_t *link) | |||
1157 | 1157 | ||
1158 | /*====================================================================*/ | 1158 | /*====================================================================*/ |
1159 | 1159 | ||
1160 | |||
1161 | static int xirc2ps_suspend(struct pcmcia_device *p_dev) | ||
1162 | { | ||
1163 | dev_link_t *link = dev_to_instance(p_dev); | ||
1164 | struct net_device *dev = link->priv; | ||
1165 | |||
1166 | link->state |= DEV_SUSPEND; | ||
1167 | if (link->state & DEV_CONFIG) { | ||
1168 | if (link->open) { | ||
1169 | netif_device_detach(dev); | ||
1170 | do_powerdown(dev); | ||
1171 | } | ||
1172 | pcmcia_release_configuration(link->handle); | ||
1173 | } | ||
1174 | |||
1175 | return 0; | ||
1176 | } | ||
1177 | |||
1178 | static int xirc2ps_resume(struct pcmcia_device *p_dev) | ||
1179 | { | ||
1180 | dev_link_t *link = dev_to_instance(p_dev); | ||
1181 | struct net_device *dev = link->priv; | ||
1182 | |||
1183 | link->state &= ~DEV_SUSPEND; | ||
1184 | if (link->state & DEV_CONFIG) { | ||
1185 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1186 | if (link->open) { | ||
1187 | do_reset(dev,1); | ||
1188 | netif_device_attach(dev); | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | return 0; | ||
1193 | } | ||
1194 | |||
1160 | /**************** | 1195 | /**************** |
1161 | * The card status event handler. Mostly, this schedules other | 1196 | * The card status event handler. Mostly, this schedules other |
1162 | * stuff to run after an event is received. A CARD_REMOVAL event | 1197 | * stuff to run after an event is received. A CARD_REMOVAL event |
@@ -1191,30 +1226,6 @@ xirc2ps_event(event_t event, int priority, | |||
1191 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 1226 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
1192 | xirc2ps_config(link); | 1227 | xirc2ps_config(link); |
1193 | break; | 1228 | break; |
1194 | case CS_EVENT_PM_SUSPEND: | ||
1195 | link->state |= DEV_SUSPEND; | ||
1196 | /* Fall through... */ | ||
1197 | case CS_EVENT_RESET_PHYSICAL: | ||
1198 | if (link->state & DEV_CONFIG) { | ||
1199 | if (link->open) { | ||
1200 | netif_device_detach(dev); | ||
1201 | do_powerdown(dev); | ||
1202 | } | ||
1203 | pcmcia_release_configuration(link->handle); | ||
1204 | } | ||
1205 | break; | ||
1206 | case CS_EVENT_PM_RESUME: | ||
1207 | link->state &= ~DEV_SUSPEND; | ||
1208 | /* Fall through... */ | ||
1209 | case CS_EVENT_CARD_RESET: | ||
1210 | if (link->state & DEV_CONFIG) { | ||
1211 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1212 | if (link->open) { | ||
1213 | do_reset(dev,1); | ||
1214 | netif_device_attach(dev); | ||
1215 | } | ||
1216 | } | ||
1217 | break; | ||
1218 | } | 1229 | } |
1219 | return 0; | 1230 | return 0; |
1220 | } /* xirc2ps_event */ | 1231 | } /* xirc2ps_event */ |
@@ -2013,6 +2024,8 @@ static struct pcmcia_driver xirc2ps_cs_driver = { | |||
2013 | .event = xirc2ps_event, | 2024 | .event = xirc2ps_event, |
2014 | .detach = xirc2ps_detach, | 2025 | .detach = xirc2ps_detach, |
2015 | .id_table = xirc2ps_ids, | 2026 | .id_table = xirc2ps_ids, |
2027 | .suspend = xirc2ps_suspend, | ||
2028 | .resume = xirc2ps_resume, | ||
2016 | }; | 2029 | }; |
2017 | 2030 | ||
2018 | static int __init | 2031 | static int __init |
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index e328547599dc..80c9de749b52 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 | ||
495 | static 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 | |||
509 | static 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 | ||
570 | static int airo_cs_init(void) | 582 | static int airo_cs_init(void) |
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 17d1fd90f832..598a9cd0f83e 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 | ||
480 | static 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 | |||
494 | static 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 | ||
590 | static int atmel_cs_init(void) | 602 | static int atmel_cs_init(void) |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 2643976a6677..ba4a7da98ccd 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 | ||
849 | static 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 | ||
850 | static 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 | |||
874 | static 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 | |||
901 | static 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 | ||
992 | static int __init init_prism2_pccard(void) | 1002 | static int __init init_prism2_pccard(void) |
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 92793b958e32..7ab2d70ffddf 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 | ||
938 | static 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 | |||
953 | static 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 | ||
1500 | static int __init init_netwave_cs(void) | 1513 | static int __init init_netwave_cs(void) |
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 | ||
468 | static 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 | |||
502 | static 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 | ||
674 | static int __init | 687 | static int __init |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 70fd6fd8feb9..c2cb6c8e6d7c 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 | ||
894 | static 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 | |||
911 | static 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 | ||
2954 | static int __init init_ray_cs(void) | 2967 | static int __init init_ray_cs(void) |
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 | }; |
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index c822cad3333f..3e3532830c26 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 | ||
4778 | static 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 | |||
4808 | static 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 | ||
4903 | static int __init | 4915 | static int __init |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 978fdc606781..75114318457e 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 | ||
2176 | static 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 | |||
2193 | static 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 | ||
2254 | static int __init wl3501_init_module(void) | 2267 | static int __init wl3501_init_module(void) |
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 24e6aacddb74..4c89853785ed 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c | |||
@@ -325,6 +325,28 @@ void parport_cs_release(dev_link_t *link) | |||
325 | 325 | ||
326 | } /* parport_cs_release */ | 326 | } /* parport_cs_release */ |
327 | 327 | ||
328 | static int parport_suspend(struct pcmcia_device *dev) | ||
329 | { | ||
330 | dev_link_t *link = dev_to_instance(dev); | ||
331 | |||
332 | link->state |= DEV_SUSPEND; | ||
333 | if (link->state & DEV_CONFIG) | ||
334 | pcmcia_release_configuration(link->handle); | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static int parport_resume(struct pcmcia_device *dev) | ||
340 | { | ||
341 | dev_link_t *link = dev_to_instance(dev); | ||
342 | |||
343 | link->state &= ~DEV_SUSPEND; | ||
344 | if (DEV_OK(link)) | ||
345 | pcmcia_request_configuration(link->handle, &link->conf); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
328 | /*====================================================================== | 350 | /*====================================================================== |
329 | 351 | ||
330 | The card status event handler. Mostly, this schedules other | 352 | The card status event handler. Mostly, this schedules other |
@@ -349,20 +371,6 @@ int parport_event(event_t event, int priority, | |||
349 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 371 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
350 | parport_config(link); | 372 | parport_config(link); |
351 | break; | 373 | break; |
352 | case CS_EVENT_PM_SUSPEND: | ||
353 | link->state |= DEV_SUSPEND; | ||
354 | /* Fall through... */ | ||
355 | case CS_EVENT_RESET_PHYSICAL: | ||
356 | if (link->state & DEV_CONFIG) | ||
357 | pcmcia_release_configuration(link->handle); | ||
358 | break; | ||
359 | case CS_EVENT_PM_RESUME: | ||
360 | link->state &= ~DEV_SUSPEND; | ||
361 | /* Fall through... */ | ||
362 | case CS_EVENT_CARD_RESET: | ||
363 | if (DEV_OK(link)) | ||
364 | pcmcia_request_configuration(link->handle, &link->conf); | ||
365 | break; | ||
366 | } | 374 | } |
367 | return 0; | 375 | return 0; |
368 | } /* parport_event */ | 376 | } /* parport_event */ |
@@ -383,7 +391,8 @@ static struct pcmcia_driver parport_cs_driver = { | |||
383 | .event = parport_event, | 391 | .event = parport_event, |
384 | .detach = parport_detach, | 392 | .detach = parport_detach, |
385 | .id_table = parport_ids, | 393 | .id_table = parport_ids, |
386 | 394 | .suspend = parport_suspend, | |
395 | .resume = parport_resume, | ||
387 | }; | 396 | }; |
388 | 397 | ||
389 | static int __init init_parport_cs(void) | 398 | static int __init init_parport_cs(void) |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index b120794c03a9..a802c65c3534 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -951,6 +951,16 @@ static int send_event_callback(struct device *dev, void * _data) | |||
951 | if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE)) | 951 | if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE)) |
952 | return 0; | 952 | return 0; |
953 | 953 | ||
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 | |||
954 | if (p_drv->event) | 964 | if (p_drv->event) |
955 | return p_drv->event(data->event, data->priority, | 965 | return p_drv->event(data->event, data->priority, |
956 | &p_dev->event_callback_args); | 966 | &p_dev->event_callback_args); |
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 7c5306499832..82988a3e35ec 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c | |||
@@ -272,11 +272,37 @@ static void aha152x_release_cs(dev_link_t *link) | |||
272 | link->state &= ~DEV_CONFIG; | 272 | link->state &= ~DEV_CONFIG; |
273 | } | 273 | } |
274 | 274 | ||
275 | static int aha152x_suspend(struct pcmcia_device *dev) | ||
276 | { | ||
277 | dev_link_t *link = dev_to_instance(dev); | ||
278 | |||
279 | link->state |= DEV_SUSPEND; | ||
280 | if (link->state & DEV_CONFIG) | ||
281 | pcmcia_release_configuration(link->handle); | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int aha152x_resume(struct pcmcia_device *dev) | ||
287 | { | ||
288 | dev_link_t *link = dev_to_instance(dev); | ||
289 | scsi_info_t *info = link->priv; | ||
290 | |||
291 | link->state &= ~DEV_SUSPEND; | ||
292 | if (link->state & DEV_CONFIG) { | ||
293 | Scsi_Cmnd tmp; | ||
294 | pcmcia_request_configuration(link->handle, &link->conf); | ||
295 | tmp.device->host = info->host; | ||
296 | aha152x_host_reset(&tmp); | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
275 | static int aha152x_event(event_t event, int priority, | 302 | static int aha152x_event(event_t event, int priority, |
276 | event_callback_args_t *args) | 303 | event_callback_args_t *args) |
277 | { | 304 | { |
278 | dev_link_t *link = args->client_data; | 305 | dev_link_t *link = args->client_data; |
279 | scsi_info_t *info = link->priv; | ||
280 | 306 | ||
281 | DEBUG(0, "aha152x_event(0x%06x)\n", event); | 307 | DEBUG(0, "aha152x_event(0x%06x)\n", event); |
282 | 308 | ||
@@ -290,24 +316,6 @@ static int aha152x_event(event_t event, int priority, | |||
290 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 316 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
291 | aha152x_config_cs(link); | 317 | aha152x_config_cs(link); |
292 | break; | 318 | break; |
293 | case CS_EVENT_PM_SUSPEND: | ||
294 | link->state |= DEV_SUSPEND; | ||
295 | /* Fall through... */ | ||
296 | case CS_EVENT_RESET_PHYSICAL: | ||
297 | if (link->state & DEV_CONFIG) | ||
298 | pcmcia_release_configuration(link->handle); | ||
299 | break; | ||
300 | case CS_EVENT_PM_RESUME: | ||
301 | link->state &= ~DEV_SUSPEND; | ||
302 | /* Fall through... */ | ||
303 | case CS_EVENT_CARD_RESET: | ||
304 | if (link->state & DEV_CONFIG) { | ||
305 | Scsi_Cmnd tmp; | ||
306 | pcmcia_request_configuration(link->handle, &link->conf); | ||
307 | tmp.device->host = info->host; | ||
308 | aha152x_host_reset(&tmp); | ||
309 | } | ||
310 | break; | ||
311 | } | 319 | } |
312 | return 0; | 320 | return 0; |
313 | } | 321 | } |
@@ -331,6 +339,8 @@ static struct pcmcia_driver aha152x_cs_driver = { | |||
331 | .event = aha152x_event, | 339 | .event = aha152x_event, |
332 | .detach = aha152x_detach, | 340 | .detach = aha152x_detach, |
333 | .id_table = aha152x_ids, | 341 | .id_table = aha152x_ids, |
342 | .suspend = aha152x_suspend, | ||
343 | .resume = aha152x_resume, | ||
334 | }; | 344 | }; |
335 | 345 | ||
336 | static int __init init_aha152x_cs(void) | 346 | static int __init init_aha152x_cs(void) |
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index db8f5cd85ffe..9e1d68c14694 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c | |||
@@ -256,6 +256,30 @@ static void fdomain_release(dev_link_t *link) | |||
256 | 256 | ||
257 | /*====================================================================*/ | 257 | /*====================================================================*/ |
258 | 258 | ||
259 | static int fdomain_suspend(struct pcmcia_device *dev) | ||
260 | { | ||
261 | dev_link_t *link = dev_to_instance(dev); | ||
262 | |||
263 | link->state |= DEV_SUSPEND; | ||
264 | if (link->state & DEV_CONFIG) | ||
265 | pcmcia_release_configuration(link->handle); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int fdomain_resume(struct pcmcia_device *dev) | ||
271 | { | ||
272 | dev_link_t *link = dev_to_instance(dev); | ||
273 | |||
274 | link->state &= ~DEV_SUSPEND; | ||
275 | if (link->state & DEV_CONFIG) { | ||
276 | pcmcia_request_configuration(link->handle, &link->conf); | ||
277 | fdomain_16x0_bus_reset(NULL); | ||
278 | } | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
259 | static int fdomain_event(event_t event, int priority, | 283 | static int fdomain_event(event_t event, int priority, |
260 | event_callback_args_t *args) | 284 | event_callback_args_t *args) |
261 | { | 285 | { |
@@ -273,22 +297,6 @@ static int fdomain_event(event_t event, int priority, | |||
273 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 297 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
274 | fdomain_config(link); | 298 | fdomain_config(link); |
275 | break; | 299 | break; |
276 | case CS_EVENT_PM_SUSPEND: | ||
277 | link->state |= DEV_SUSPEND; | ||
278 | /* Fall through... */ | ||
279 | case CS_EVENT_RESET_PHYSICAL: | ||
280 | if (link->state & DEV_CONFIG) | ||
281 | pcmcia_release_configuration(link->handle); | ||
282 | break; | ||
283 | case CS_EVENT_PM_RESUME: | ||
284 | link->state &= ~DEV_SUSPEND; | ||
285 | /* Fall through... */ | ||
286 | case CS_EVENT_CARD_RESET: | ||
287 | if (link->state & DEV_CONFIG) { | ||
288 | pcmcia_request_configuration(link->handle, &link->conf); | ||
289 | fdomain_16x0_bus_reset(NULL); | ||
290 | } | ||
291 | break; | ||
292 | } | 300 | } |
293 | return 0; | 301 | return 0; |
294 | } /* fdomain_event */ | 302 | } /* fdomain_event */ |
@@ -311,6 +319,8 @@ static struct pcmcia_driver fdomain_cs_driver = { | |||
311 | .event = fdomain_event, | 319 | .event = fdomain_event, |
312 | .detach = fdomain_detach, | 320 | .detach = fdomain_detach, |
313 | .id_table = fdomain_ids, | 321 | .id_table = fdomain_ids, |
322 | .suspend = fdomain_suspend, | ||
323 | .resume = fdomain_resume, | ||
314 | }; | 324 | }; |
315 | 325 | ||
316 | static int __init init_fdomain_cs(void) | 326 | static int __init init_fdomain_cs(void) |
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 050ea13ff80b..870e87180d12 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c | |||
@@ -2021,6 +2021,59 @@ static void nsp_cs_release(dev_link_t *link) | |||
2021 | #endif | 2021 | #endif |
2022 | } /* nsp_cs_release */ | 2022 | } /* nsp_cs_release */ |
2023 | 2023 | ||
2024 | static int nsp_cs_suspend(struct pcmcia_device *dev) | ||
2025 | { | ||
2026 | dev_link_t *link = dev_to_instance(dev); | ||
2027 | scsi_info_t *info = link->priv; | ||
2028 | nsp_hw_data *data; | ||
2029 | |||
2030 | link->state |= DEV_SUSPEND; | ||
2031 | |||
2032 | nsp_dbg(NSP_DEBUG_INIT, "event: suspend"); | ||
2033 | |||
2034 | if (info->host != NULL) { | ||
2035 | nsp_msg(KERN_INFO, "clear SDTR status"); | ||
2036 | |||
2037 | data = (nsp_hw_data *)info->host->hostdata; | ||
2038 | |||
2039 | nsphw_init_sync(data); | ||
2040 | } | ||
2041 | |||
2042 | info->stop = 1; | ||
2043 | |||
2044 | if (link->state & DEV_CONFIG) | ||
2045 | pcmcia_release_configuration(link->handle); | ||
2046 | |||
2047 | return 0; | ||
2048 | } | ||
2049 | |||
2050 | static int nsp_cs_resume(struct pcmcia_device *dev) | ||
2051 | { | ||
2052 | dev_link_t *link = dev_to_instance(dev); | ||
2053 | scsi_info_t *info = link->priv; | ||
2054 | nsp_hw_data *data; | ||
2055 | |||
2056 | nsp_dbg(NSP_DEBUG_INIT, "event: resume"); | ||
2057 | |||
2058 | link->state &= ~DEV_SUSPEND; | ||
2059 | |||
2060 | if (link->state & DEV_CONFIG) | ||
2061 | pcmcia_request_configuration(link->handle, &link->conf); | ||
2062 | |||
2063 | info->stop = 0; | ||
2064 | |||
2065 | if (info->host != NULL) { | ||
2066 | nsp_msg(KERN_INFO, "reset host and bus"); | ||
2067 | |||
2068 | data = (nsp_hw_data *)info->host->hostdata; | ||
2069 | |||
2070 | nsphw_init (data); | ||
2071 | nsp_bus_reset(data); | ||
2072 | } | ||
2073 | |||
2074 | return 0; | ||
2075 | } | ||
2076 | |||
2024 | /*====================================================================== | 2077 | /*====================================================================== |
2025 | 2078 | ||
2026 | The card status event handler. Mostly, this schedules other | 2079 | The card status event handler. Mostly, this schedules other |
@@ -2039,8 +2092,6 @@ static int nsp_cs_event(event_t event, | |||
2039 | event_callback_args_t *args) | 2092 | event_callback_args_t *args) |
2040 | { | 2093 | { |
2041 | dev_link_t *link = args->client_data; | 2094 | dev_link_t *link = args->client_data; |
2042 | scsi_info_t *info = link->priv; | ||
2043 | nsp_hw_data *data; | ||
2044 | 2095 | ||
2045 | nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event); | 2096 | nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event); |
2046 | 2097 | ||
@@ -2062,51 +2113,6 @@ static int nsp_cs_event(event_t event, | |||
2062 | #endif | 2113 | #endif |
2063 | nsp_cs_config(link); | 2114 | nsp_cs_config(link); |
2064 | break; | 2115 | break; |
2065 | |||
2066 | case CS_EVENT_PM_SUSPEND: | ||
2067 | nsp_dbg(NSP_DEBUG_INIT, "event: suspend"); | ||
2068 | link->state |= DEV_SUSPEND; | ||
2069 | /* Fall through... */ | ||
2070 | case CS_EVENT_RESET_PHYSICAL: | ||
2071 | /* Mark the device as stopped, to block IO until later */ | ||
2072 | nsp_dbg(NSP_DEBUG_INIT, "event: reset physical"); | ||
2073 | |||
2074 | if (info->host != NULL) { | ||
2075 | nsp_msg(KERN_INFO, "clear SDTR status"); | ||
2076 | |||
2077 | data = (nsp_hw_data *)info->host->hostdata; | ||
2078 | |||
2079 | nsphw_init_sync(data); | ||
2080 | } | ||
2081 | |||
2082 | info->stop = 1; | ||
2083 | if (link->state & DEV_CONFIG) { | ||
2084 | pcmcia_release_configuration(link->handle); | ||
2085 | } | ||
2086 | break; | ||
2087 | |||
2088 | case CS_EVENT_PM_RESUME: | ||
2089 | nsp_dbg(NSP_DEBUG_INIT, "event: resume"); | ||
2090 | link->state &= ~DEV_SUSPEND; | ||
2091 | /* Fall through... */ | ||
2092 | case CS_EVENT_CARD_RESET: | ||
2093 | nsp_dbg(NSP_DEBUG_INIT, "event: reset"); | ||
2094 | if (link->state & DEV_CONFIG) { | ||
2095 | pcmcia_request_configuration(link->handle, &link->conf); | ||
2096 | } | ||
2097 | info->stop = 0; | ||
2098 | |||
2099 | if (info->host != NULL) { | ||
2100 | nsp_msg(KERN_INFO, "reset host and bus"); | ||
2101 | |||
2102 | data = (nsp_hw_data *)info->host->hostdata; | ||
2103 | |||
2104 | nsphw_init (data); | ||
2105 | nsp_bus_reset(data); | ||
2106 | } | ||
2107 | |||
2108 | break; | ||
2109 | |||
2110 | default: | 2116 | default: |
2111 | nsp_dbg(NSP_DEBUG_INIT, "event: unknown"); | 2117 | nsp_dbg(NSP_DEBUG_INIT, "event: unknown"); |
2112 | break; | 2118 | break; |
@@ -2140,6 +2146,8 @@ static struct pcmcia_driver nsp_driver = { | |||
2140 | .event = nsp_cs_event, | 2146 | .event = nsp_cs_event, |
2141 | .detach = nsp_cs_detach, | 2147 | .detach = nsp_cs_detach, |
2142 | .id_table = nsp_cs_ids, | 2148 | .id_table = nsp_cs_ids, |
2149 | .suspend = nsp_cs_suspend, | ||
2150 | .resume = nsp_cs_resume, | ||
2143 | }; | 2151 | }; |
2144 | #endif | 2152 | #endif |
2145 | 2153 | ||
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index bb091a45a880..2541a999a0e5 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c | |||
@@ -349,6 +349,40 @@ static void qlogic_release(dev_link_t *link) | |||
349 | 349 | ||
350 | /*====================================================================*/ | 350 | /*====================================================================*/ |
351 | 351 | ||
352 | static int qlogic_suspend(struct pcmcia_device *dev) | ||
353 | { | ||
354 | dev_link_t *link = dev_to_instance(dev); | ||
355 | |||
356 | link->state |= DEV_SUSPEND; | ||
357 | if (link->state & DEV_CONFIG) | ||
358 | pcmcia_release_configuration(link->handle); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int qlogic_resume(struct pcmcia_device *dev) | ||
364 | { | ||
365 | dev_link_t *link = dev_to_instance(dev); | ||
366 | |||
367 | link->state &= ~DEV_SUSPEND; | ||
368 | if (link->state & DEV_CONFIG) { | ||
369 | scsi_info_t *info = link->priv; | ||
370 | |||
371 | pcmcia_request_configuration(link->handle, &link->conf); | ||
372 | if ((info->manf_id == MANFID_MACNICA) || | ||
373 | (info->manf_id == MANFID_PIONEER) || | ||
374 | (info->manf_id == 0x0098)) { | ||
375 | outb(0x80, link->io.BasePort1 + 0xd); | ||
376 | outb(0x24, link->io.BasePort1 + 0x9); | ||
377 | outb(0x04, link->io.BasePort1 + 0xd); | ||
378 | } | ||
379 | /* Ugggglllyyyy!!! */ | ||
380 | qlogicfas408_bus_reset(NULL); | ||
381 | } | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
352 | static int qlogic_event(event_t event, int priority, event_callback_args_t * args) | 386 | static int qlogic_event(event_t event, int priority, event_callback_args_t * args) |
353 | { | 387 | { |
354 | dev_link_t *link = args->client_data; | 388 | dev_link_t *link = args->client_data; |
@@ -365,29 +399,6 @@ static int qlogic_event(event_t event, int priority, event_callback_args_t * arg | |||
365 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 399 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
366 | qlogic_config(link); | 400 | qlogic_config(link); |
367 | break; | 401 | break; |
368 | case CS_EVENT_PM_SUSPEND: | ||
369 | link->state |= DEV_SUSPEND; | ||
370 | /* Fall through... */ | ||
371 | case CS_EVENT_RESET_PHYSICAL: | ||
372 | if (link->state & DEV_CONFIG) | ||
373 | pcmcia_release_configuration(link->handle); | ||
374 | break; | ||
375 | case CS_EVENT_PM_RESUME: | ||
376 | link->state &= ~DEV_SUSPEND; | ||
377 | /* Fall through... */ | ||
378 | case CS_EVENT_CARD_RESET: | ||
379 | if (link->state & DEV_CONFIG) { | ||
380 | scsi_info_t *info = link->priv; | ||
381 | pcmcia_request_configuration(link->handle, &link->conf); | ||
382 | if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { | ||
383 | outb(0x80, link->io.BasePort1 + 0xd); | ||
384 | outb(0x24, link->io.BasePort1 + 0x9); | ||
385 | outb(0x04, link->io.BasePort1 + 0xd); | ||
386 | } | ||
387 | /* Ugggglllyyyy!!! */ | ||
388 | qlogicfas408_bus_reset(NULL); | ||
389 | } | ||
390 | break; | ||
391 | } | 402 | } |
392 | return 0; | 403 | return 0; |
393 | } /* qlogic_event */ | 404 | } /* qlogic_event */ |
@@ -423,6 +434,8 @@ static struct pcmcia_driver qlogic_cs_driver = { | |||
423 | .event = qlogic_event, | 434 | .event = qlogic_event, |
424 | .detach = qlogic_detach, | 435 | .detach = qlogic_detach, |
425 | .id_table = qlogic_ids, | 436 | .id_table = qlogic_ids, |
437 | .suspend = qlogic_suspend, | ||
438 | .resume = qlogic_resume, | ||
426 | }; | 439 | }; |
427 | 440 | ||
428 | static int __init init_qlogic_cs(void) | 441 | static int __init init_qlogic_cs(void) |
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 98b64b2aa8ee..c4e3e2294c66 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c | |||
@@ -872,11 +872,48 @@ cs_failed: | |||
872 | return; | 872 | return; |
873 | } /* SYM53C500_config */ | 873 | } /* SYM53C500_config */ |
874 | 874 | ||
875 | static int sym53c500_suspend(struct pcmcia_device *dev) | ||
876 | { | ||
877 | dev_link_t *link = dev_to_instance(dev); | ||
878 | |||
879 | link->state |= DEV_SUSPEND; | ||
880 | if (link->state & DEV_CONFIG) | ||
881 | pcmcia_release_configuration(link->handle); | ||
882 | |||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | static int sym53c500_resume(struct pcmcia_device *dev) | ||
887 | { | ||
888 | dev_link_t *link = dev_to_instance(dev); | ||
889 | struct scsi_info_t *info = link->priv; | ||
890 | |||
891 | link->state &= ~DEV_SUSPEND; | ||
892 | if (link->state & DEV_CONFIG) { | ||
893 | pcmcia_request_configuration(link->handle, &link->conf); | ||
894 | |||
895 | /* See earlier comment about manufacturer IDs. */ | ||
896 | if ((info->manf_id == MANFID_MACNICA) || | ||
897 | (info->manf_id == MANFID_PIONEER) || | ||
898 | (info->manf_id == 0x0098)) { | ||
899 | outb(0x80, link->io.BasePort1 + 0xd); | ||
900 | outb(0x24, link->io.BasePort1 + 0x9); | ||
901 | outb(0x04, link->io.BasePort1 + 0xd); | ||
902 | } | ||
903 | /* | ||
904 | * If things don't work after a "resume", | ||
905 | * this is a good place to start looking. | ||
906 | */ | ||
907 | SYM53C500_int_host_reset(link->io.BasePort1); | ||
908 | } | ||
909 | |||
910 | return 0; | ||
911 | } | ||
912 | |||
875 | static int | 913 | static int |
876 | SYM53C500_event(event_t event, int priority, event_callback_args_t *args) | 914 | SYM53C500_event(event_t event, int priority, event_callback_args_t *args) |
877 | { | 915 | { |
878 | dev_link_t *link = args->client_data; | 916 | dev_link_t *link = args->client_data; |
879 | struct scsi_info_t *info = link->priv; | ||
880 | 917 | ||
881 | DEBUG(1, "SYM53C500_event(0x%06x)\n", event); | 918 | DEBUG(1, "SYM53C500_event(0x%06x)\n", event); |
882 | 919 | ||
@@ -890,34 +927,6 @@ SYM53C500_event(event_t event, int priority, event_callback_args_t *args) | |||
890 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 927 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
891 | SYM53C500_config(link); | 928 | SYM53C500_config(link); |
892 | break; | 929 | break; |
893 | case CS_EVENT_PM_SUSPEND: | ||
894 | link->state |= DEV_SUSPEND; | ||
895 | /* Fall through... */ | ||
896 | case CS_EVENT_RESET_PHYSICAL: | ||
897 | if (link->state & DEV_CONFIG) | ||
898 | pcmcia_release_configuration(link->handle); | ||
899 | break; | ||
900 | case CS_EVENT_PM_RESUME: | ||
901 | link->state &= ~DEV_SUSPEND; | ||
902 | /* Fall through... */ | ||
903 | case CS_EVENT_CARD_RESET: | ||
904 | if (link->state & DEV_CONFIG) { | ||
905 | pcmcia_request_configuration(link->handle, &link->conf); | ||
906 | /* See earlier comment about manufacturer IDs. */ | ||
907 | if ((info->manf_id == MANFID_MACNICA) || | ||
908 | (info->manf_id == MANFID_PIONEER) || | ||
909 | (info->manf_id == 0x0098)) { | ||
910 | outb(0x80, link->io.BasePort1 + 0xd); | ||
911 | outb(0x24, link->io.BasePort1 + 0x9); | ||
912 | outb(0x04, link->io.BasePort1 + 0xd); | ||
913 | } | ||
914 | /* | ||
915 | * If things don't work after a "resume", | ||
916 | * this is a good place to start looking. | ||
917 | */ | ||
918 | SYM53C500_int_host_reset(link->io.BasePort1); | ||
919 | } | ||
920 | break; | ||
921 | } | 930 | } |
922 | return 0; | 931 | return 0; |
923 | } /* SYM53C500_event */ | 932 | } /* SYM53C500_event */ |
@@ -1012,6 +1021,8 @@ static struct pcmcia_driver sym53c500_cs_driver = { | |||
1012 | .event = SYM53C500_event, | 1021 | .event = SYM53C500_event, |
1013 | .detach = SYM53C500_detach, | 1022 | .detach = SYM53C500_detach, |
1014 | .id_table = sym53c500_ids, | 1023 | .id_table = sym53c500_ids, |
1024 | .suspend = sym53c500_suspend, | ||
1025 | .resume = sym53c500_resume, | ||
1015 | }; | 1026 | }; |
1016 | 1027 | ||
1017 | static int __init | 1028 | static int __init |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 7ce0c7e66d37..3487ee9eab1d 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -159,8 +159,9 @@ static void serial_remove(dev_link_t *link) | |||
159 | } | 159 | } |
160 | } | 160 | } |
161 | 161 | ||
162 | static void serial_suspend(dev_link_t *link) | 162 | static int serial_suspend(struct pcmcia_device *dev) |
163 | { | 163 | { |
164 | dev_link_t *link = dev_to_instance(dev); | ||
164 | link->state |= DEV_SUSPEND; | 165 | link->state |= DEV_SUSPEND; |
165 | 166 | ||
166 | if (link->state & DEV_CONFIG) { | 167 | if (link->state & DEV_CONFIG) { |
@@ -173,10 +174,13 @@ static void serial_suspend(dev_link_t *link) | |||
173 | if (!info->slave) | 174 | if (!info->slave) |
174 | pcmcia_release_configuration(link->handle); | 175 | pcmcia_release_configuration(link->handle); |
175 | } | 176 | } |
177 | |||
178 | return 0; | ||
176 | } | 179 | } |
177 | 180 | ||
178 | static void serial_resume(dev_link_t *link) | 181 | static int serial_resume(struct pcmcia_device *dev) |
179 | { | 182 | { |
183 | dev_link_t *link = dev_to_instance(dev); | ||
180 | link->state &= ~DEV_SUSPEND; | 184 | link->state &= ~DEV_SUSPEND; |
181 | 185 | ||
182 | if (DEV_OK(link)) { | 186 | if (DEV_OK(link)) { |
@@ -189,6 +193,8 @@ static void serial_resume(dev_link_t *link) | |||
189 | for (i = 0; i < info->ndev; i++) | 193 | for (i = 0; i < info->ndev; i++) |
190 | serial8250_resume_port(info->line[i]); | 194 | serial8250_resume_port(info->line[i]); |
191 | } | 195 | } |
196 | |||
197 | return 0; | ||
192 | } | 198 | } |
193 | 199 | ||
194 | /*====================================================================== | 200 | /*====================================================================== |
@@ -731,7 +737,6 @@ static int | |||
731 | serial_event(event_t event, int priority, event_callback_args_t * args) | 737 | serial_event(event_t event, int priority, event_callback_args_t * args) |
732 | { | 738 | { |
733 | dev_link_t *link = args->client_data; | 739 | dev_link_t *link = args->client_data; |
734 | struct serial_info *info = link->priv; | ||
735 | 740 | ||
736 | DEBUG(1, "serial_event(0x%06x)\n", event); | 741 | DEBUG(1, "serial_event(0x%06x)\n", event); |
737 | 742 | ||
@@ -744,24 +749,6 @@ serial_event(event_t event, int priority, event_callback_args_t * args) | |||
744 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 749 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
745 | serial_config(link); | 750 | serial_config(link); |
746 | break; | 751 | break; |
747 | |||
748 | case CS_EVENT_PM_SUSPEND: | ||
749 | serial_suspend(link); | ||
750 | break; | ||
751 | |||
752 | case CS_EVENT_RESET_PHYSICAL: | ||
753 | if ((link->state & DEV_CONFIG) && !info->slave) | ||
754 | pcmcia_release_configuration(link->handle); | ||
755 | break; | ||
756 | |||
757 | case CS_EVENT_PM_RESUME: | ||
758 | serial_resume(link); | ||
759 | break; | ||
760 | |||
761 | case CS_EVENT_CARD_RESET: | ||
762 | if (DEV_OK(link) && !info->slave) | ||
763 | pcmcia_request_configuration(link->handle, &link->conf); | ||
764 | break; | ||
765 | } | 752 | } |
766 | return 0; | 753 | return 0; |
767 | } | 754 | } |
@@ -881,6 +868,8 @@ static struct pcmcia_driver serial_cs_driver = { | |||
881 | .event = serial_event, | 868 | .event = serial_event, |
882 | .detach = serial_detach, | 869 | .detach = serial_detach, |
883 | .id_table = serial_ids, | 870 | .id_table = serial_ids, |
871 | .suspend = serial_suspend, | ||
872 | .resume = serial_resume, | ||
884 | }; | 873 | }; |
885 | 874 | ||
886 | static int __init init_serial_cs(void) | 875 | static int __init init_serial_cs(void) |
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 57c0c6e3fbed..7cca46be0c0f 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c | |||
@@ -255,6 +255,28 @@ static void ixj_cs_release(dev_link_t *link) | |||
255 | link->state &= ~DEV_CONFIG; | 255 | link->state &= ~DEV_CONFIG; |
256 | } | 256 | } |
257 | 257 | ||
258 | static int ixj_suspend(struct pcmcia_device *dev) | ||
259 | { | ||
260 | dev_link_t *link = dev_to_instance(dev); | ||
261 | |||
262 | link->state |= DEV_SUSPEND; | ||
263 | if (link->state & DEV_CONFIG) | ||
264 | pcmcia_release_configuration(link->handle); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static int ixj_resume(struct pcmcia_device *dev) | ||
270 | { | ||
271 | dev_link_t *link = dev_to_instance(dev); | ||
272 | |||
273 | link->state &= ~DEV_SUSPEND; | ||
274 | if (DEV_OK(link)) | ||
275 | pcmcia_request_configuration(link->handle, &link->conf); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
258 | static int ixj_event(event_t event, int priority, event_callback_args_t * args) | 280 | static int ixj_event(event_t event, int priority, event_callback_args_t * args) |
259 | { | 281 | { |
260 | dev_link_t *link = args->client_data; | 282 | dev_link_t *link = args->client_data; |
@@ -271,20 +293,6 @@ static int ixj_event(event_t event, int priority, event_callback_args_t * args) | |||
271 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 293 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
272 | ixj_config(link); | 294 | ixj_config(link); |
273 | break; | 295 | break; |
274 | case CS_EVENT_PM_SUSPEND: | ||
275 | link->state |= DEV_SUSPEND; | ||
276 | /* Fall through... */ | ||
277 | case CS_EVENT_RESET_PHYSICAL: | ||
278 | if (link->state & DEV_CONFIG) | ||
279 | pcmcia_release_configuration(link->handle); | ||
280 | break; | ||
281 | case CS_EVENT_PM_RESUME: | ||
282 | link->state &= ~DEV_SUSPEND; | ||
283 | /* Fall through... */ | ||
284 | case CS_EVENT_CARD_RESET: | ||
285 | if (DEV_OK(link)) | ||
286 | pcmcia_request_configuration(link->handle, &link->conf); | ||
287 | break; | ||
288 | } | 296 | } |
289 | return 0; | 297 | return 0; |
290 | } | 298 | } |
@@ -304,6 +312,8 @@ static struct pcmcia_driver ixj_driver = { | |||
304 | .event = ixj_event, | 312 | .event = ixj_event, |
305 | .detach = ixj_detach, | 313 | .detach = ixj_detach, |
306 | .id_table = ixj_ids, | 314 | .id_table = ixj_ids, |
315 | .suspend = ixj_suspend, | ||
316 | .resume = ixj_resume, | ||
307 | }; | 317 | }; |
308 | 318 | ||
309 | static int __init ixj_pcmcia_init(void) | 319 | static int __init ixj_pcmcia_init(void) |
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 5056b7459994..cb8c2bdbbd04 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c | |||
@@ -323,6 +323,28 @@ cs_failed: | |||
323 | } | 323 | } |
324 | } | 324 | } |
325 | 325 | ||
326 | static int sl811_suspend(struct pcmcia_device *dev) | ||
327 | { | ||
328 | dev_link_t *link = dev_to_instance(dev); | ||
329 | |||
330 | link->state |= DEV_SUSPEND; | ||
331 | if (link->state & DEV_CONFIG) | ||
332 | pcmcia_release_configuration(link->handle); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int sl811_resume(struct pcmcia_device *dev) | ||
338 | { | ||
339 | dev_link_t *link = dev_to_instance(dev); | ||
340 | |||
341 | link->state &= ~DEV_SUSPEND; | ||
342 | if (link->state & DEV_CONFIG) | ||
343 | pcmcia_request_configuration(link->handle, &link->conf); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
326 | static int | 348 | static int |
327 | sl811_cs_event(event_t event, int priority, event_callback_args_t *args) | 349 | sl811_cs_event(event_t event, int priority, event_callback_args_t *args) |
328 | { | 350 | { |
@@ -341,23 +363,6 @@ sl811_cs_event(event_t event, int priority, event_callback_args_t *args) | |||
341 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 363 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
342 | sl811_cs_config(link); | 364 | sl811_cs_config(link); |
343 | break; | 365 | break; |
344 | |||
345 | case CS_EVENT_PM_SUSPEND: | ||
346 | link->state |= DEV_SUSPEND; | ||
347 | /* Fall through... */ | ||
348 | case CS_EVENT_RESET_PHYSICAL: | ||
349 | if (link->state & DEV_CONFIG) | ||
350 | pcmcia_release_configuration(link->handle); | ||
351 | break; | ||
352 | |||
353 | case CS_EVENT_PM_RESUME: | ||
354 | link->state &= ~DEV_SUSPEND; | ||
355 | /* Fall through... */ | ||
356 | case CS_EVENT_CARD_RESET: | ||
357 | if (link->state & DEV_CONFIG) | ||
358 | pcmcia_request_configuration(link->handle, &link->conf); | ||
359 | DBG(0, "reset sl811-hcd here?\n"); | ||
360 | break; | ||
361 | } | 366 | } |
362 | return 0; | 367 | return 0; |
363 | } | 368 | } |
@@ -417,6 +422,8 @@ static struct pcmcia_driver sl811_cs_driver = { | |||
417 | .event = sl811_cs_event, | 422 | .event = sl811_cs_event, |
418 | .detach = sl811_cs_detach, | 423 | .detach = sl811_cs_detach, |
419 | .id_table = sl811_ids, | 424 | .id_table = sl811_ids, |
425 | .suspend = sl811_suspend, | ||
426 | .resume = sl811_resume, | ||
420 | }; | 427 | }; |
421 | 428 | ||
422 | /*====================================================================*/ | 429 | /*====================================================================*/ |
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index cb8b6e6ce66c..020055199008 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h | |||
@@ -137,6 +137,10 @@ struct pcmcia_driver { | |||
137 | int (*event) (event_t event, int priority, | 137 | int (*event) (event_t event, int priority, |
138 | event_callback_args_t *); | 138 | event_callback_args_t *); |
139 | void (*detach)(dev_link_t *); | 139 | void (*detach)(dev_link_t *); |
140 | |||
141 | int (*suspend) (struct pcmcia_device *dev); | ||
142 | int (*resume) (struct pcmcia_device *dev); | ||
143 | |||
140 | struct module *owner; | 144 | struct module *owner; |
141 | struct pcmcia_device_id *id_table; | 145 | struct pcmcia_device_id *id_table; |
142 | struct device_driver drv; | 146 | struct device_driver drv; |
@@ -193,6 +197,8 @@ struct pcmcia_device { | |||
193 | #define handle_to_pdev(handle) (handle) | 197 | #define handle_to_pdev(handle) (handle) |
194 | #define handle_to_dev(handle) (handle->dev) | 198 | #define handle_to_dev(handle) (handle->dev) |
195 | 199 | ||
200 | #define dev_to_instance(dev) (dev->instance) | ||
201 | |||
196 | /* error reporting */ | 202 | /* error reporting */ |
197 | void cs_error(client_handle_t handle, int func, int ret); | 203 | void cs_error(client_handle_t handle, int func, int ret); |
198 | 204 | ||