diff options
Diffstat (limited to 'drivers/char/pcmcia')
-rw-r--r-- | drivers/char/pcmcia/cm4000_cs.c | 162 | ||||
-rw-r--r-- | drivers/char/pcmcia/cm4040_cs.c | 151 | ||||
-rw-r--r-- | drivers/char/pcmcia/synclink_cs.c | 132 |
3 files changed, 135 insertions, 310 deletions
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 61681c9f3f72..649677b5dc36 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -66,7 +66,6 @@ static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte"; | |||
66 | #define T_100MSEC msecs_to_jiffies(100) | 66 | #define T_100MSEC msecs_to_jiffies(100) |
67 | #define T_500MSEC msecs_to_jiffies(500) | 67 | #define T_500MSEC msecs_to_jiffies(500) |
68 | 68 | ||
69 | static void cm4000_detach(dev_link_t *link); | ||
70 | static void cm4000_release(dev_link_t *link); | 69 | static void cm4000_release(dev_link_t *link); |
71 | 70 | ||
72 | static int major; /* major number we get from the kernel */ | 71 | static int major; /* major number we get from the kernel */ |
@@ -156,7 +155,6 @@ struct cm4000_dev { | |||
156 | /*sbuf*/ 512*sizeof(char) - \ | 155 | /*sbuf*/ 512*sizeof(char) - \ |
157 | /*queue*/ 4*sizeof(wait_queue_head_t)) | 156 | /*queue*/ 4*sizeof(wait_queue_head_t)) |
158 | 157 | ||
159 | static dev_info_t dev_info = MODULE_NAME; | ||
160 | static dev_link_t *dev_table[CM4000_MAX_DEV]; | 158 | static dev_link_t *dev_table[CM4000_MAX_DEV]; |
161 | 159 | ||
162 | /* This table doesn't use spaces after the comma between fields and thus | 160 | /* This table doesn't use spaces after the comma between fields and thus |
@@ -1864,68 +1862,36 @@ cs_release: | |||
1864 | link->state &= ~DEV_CONFIG_PENDING; | 1862 | link->state &= ~DEV_CONFIG_PENDING; |
1865 | } | 1863 | } |
1866 | 1864 | ||
1867 | static int cm4000_event(event_t event, int priority, | 1865 | static int cm4000_suspend(struct pcmcia_device *p_dev) |
1868 | event_callback_args_t *args) | ||
1869 | { | 1866 | { |
1870 | dev_link_t *link; | 1867 | dev_link_t *link = dev_to_instance(p_dev); |
1871 | struct cm4000_dev *dev; | 1868 | struct cm4000_dev *dev; |
1872 | int devno; | ||
1873 | 1869 | ||
1874 | link = args->client_data; | ||
1875 | dev = link->priv; | 1870 | dev = link->priv; |
1876 | 1871 | ||
1877 | DEBUGP(3, dev, "-> cm4000_event\n"); | 1872 | link->state |= DEV_SUSPEND; |
1878 | for (devno = 0; devno < CM4000_MAX_DEV; devno++) | 1873 | if (link->state & DEV_CONFIG) |
1879 | if (dev_table[devno] == link) | 1874 | pcmcia_release_configuration(link->handle); |
1880 | break; | 1875 | stop_monitor(dev); |
1881 | 1876 | ||
1882 | if (devno == CM4000_MAX_DEV) | 1877 | return 0; |
1883 | return CS_BAD_ADAPTER; | 1878 | } |
1884 | 1879 | ||
1885 | switch (event) { | 1880 | static int cm4000_resume(struct pcmcia_device *p_dev) |
1886 | case CS_EVENT_CARD_INSERTION: | 1881 | { |
1887 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | 1882 | dev_link_t *link = dev_to_instance(p_dev); |
1888 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 1883 | struct cm4000_dev *dev; |
1889 | cm4000_config(link, devno); | 1884 | |
1890 | break; | 1885 | dev = link->priv; |
1891 | case CS_EVENT_CARD_REMOVAL: | 1886 | |
1892 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | 1887 | link->state &= ~DEV_SUSPEND; |
1893 | link->state &= ~DEV_PRESENT; | 1888 | if (link->state & DEV_CONFIG) |
1894 | stop_monitor(dev); | 1889 | pcmcia_request_configuration(link->handle, &link->conf); |
1895 | break; | 1890 | |
1896 | case CS_EVENT_PM_SUSPEND: | 1891 | if (link->open) |
1897 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | 1892 | start_monitor(dev); |
1898 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | 1893 | |
1899 | link->state |= DEV_SUSPEND; | 1894 | return 0; |
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: | ||
1924 | DEBUGP(5, dev, "unknown event %.2x\n", event); | ||
1925 | break; | ||
1926 | } | ||
1927 | DEBUGP(3, dev, "<- cm4000_event\n"); | ||
1928 | return CS_SUCCESS; | ||
1929 | } | 1895 | } |
1930 | 1896 | ||
1931 | static void cm4000_release(dev_link_t *link) | 1897 | static void cm4000_release(dev_link_t *link) |
@@ -1935,11 +1901,10 @@ static void cm4000_release(dev_link_t *link) | |||
1935 | pcmcia_release_io(link->handle, &link->io); | 1901 | pcmcia_release_io(link->handle, &link->io); |
1936 | } | 1902 | } |
1937 | 1903 | ||
1938 | static dev_link_t *cm4000_attach(void) | 1904 | static int cm4000_attach(struct pcmcia_device *p_dev) |
1939 | { | 1905 | { |
1940 | struct cm4000_dev *dev; | 1906 | struct cm4000_dev *dev; |
1941 | dev_link_t *link; | 1907 | dev_link_t *link; |
1942 | client_reg_t client_reg; | ||
1943 | int i; | 1908 | int i; |
1944 | 1909 | ||
1945 | for (i = 0; i < CM4000_MAX_DEV; i++) | 1910 | for (i = 0; i < CM4000_MAX_DEV; i++) |
@@ -1948,76 +1913,55 @@ static dev_link_t *cm4000_attach(void) | |||
1948 | 1913 | ||
1949 | if (i == CM4000_MAX_DEV) { | 1914 | if (i == CM4000_MAX_DEV) { |
1950 | printk(KERN_NOTICE MODULE_NAME ": all devices in use\n"); | 1915 | printk(KERN_NOTICE MODULE_NAME ": all devices in use\n"); |
1951 | return NULL; | 1916 | return -ENODEV; |
1952 | } | 1917 | } |
1953 | 1918 | ||
1954 | /* create a new cm4000_cs device */ | 1919 | /* create a new cm4000_cs device */ |
1955 | dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL); | 1920 | dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL); |
1956 | if (dev == NULL) | 1921 | if (dev == NULL) |
1957 | return NULL; | 1922 | return -ENOMEM; |
1958 | 1923 | ||
1959 | link = &dev->link; | 1924 | link = &dev->link; |
1960 | link->priv = dev; | 1925 | link->priv = dev; |
1961 | link->conf.IntType = INT_MEMORY_AND_IO; | 1926 | link->conf.IntType = INT_MEMORY_AND_IO; |
1962 | dev_table[i] = link; | 1927 | dev_table[i] = link; |
1963 | 1928 | ||
1964 | /* register with card services */ | ||
1965 | client_reg.dev_info = &dev_info; | ||
1966 | client_reg.EventMask = | ||
1967 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
1968 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
1969 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
1970 | client_reg.Version = 0x0210; | ||
1971 | client_reg.event_callback_args.client_data = link; | ||
1972 | |||
1973 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
1974 | if (i) { | ||
1975 | cs_error(link->handle, RegisterClient, i); | ||
1976 | cm4000_detach(link); | ||
1977 | return NULL; | ||
1978 | } | ||
1979 | |||
1980 | init_waitqueue_head(&dev->devq); | 1929 | init_waitqueue_head(&dev->devq); |
1981 | init_waitqueue_head(&dev->ioq); | 1930 | init_waitqueue_head(&dev->ioq); |
1982 | init_waitqueue_head(&dev->atrq); | 1931 | init_waitqueue_head(&dev->atrq); |
1983 | init_waitqueue_head(&dev->readq); | 1932 | init_waitqueue_head(&dev->readq); |
1984 | 1933 | ||
1985 | return link; | 1934 | link->handle = p_dev; |
1986 | } | 1935 | p_dev->instance = link; |
1987 | |||
1988 | static void cm4000_detach_by_devno(int devno, dev_link_t * link) | ||
1989 | { | ||
1990 | struct cm4000_dev *dev = link->priv; | ||
1991 | |||
1992 | DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno); | ||
1993 | |||
1994 | if (link->state & DEV_CONFIG) { | ||
1995 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | ||
1996 | cm4000_release(link); | ||
1997 | } | ||
1998 | 1936 | ||
1999 | if (link->handle) { | 1937 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
2000 | pcmcia_deregister_client(link->handle); | 1938 | cm4000_config(link, i); |
2001 | } | ||
2002 | 1939 | ||
2003 | dev_table[devno] = NULL; | 1940 | return 0; |
2004 | kfree(dev); | ||
2005 | return; | ||
2006 | } | 1941 | } |
2007 | 1942 | ||
2008 | static void cm4000_detach(dev_link_t * link) | 1943 | static void cm4000_detach(struct pcmcia_device *p_dev) |
2009 | { | 1944 | { |
2010 | int i; | 1945 | dev_link_t *link = dev_to_instance(p_dev); |
1946 | struct cm4000_dev *dev = link->priv; | ||
1947 | int devno; | ||
2011 | 1948 | ||
2012 | /* find device */ | 1949 | /* find device */ |
2013 | for (i = 0; i < CM4000_MAX_DEV; i++) | 1950 | for (devno = 0; devno < CM4000_MAX_DEV; devno++) |
2014 | if (dev_table[i] == link) | 1951 | if (dev_table[devno] == link) |
2015 | break; | 1952 | break; |
2016 | 1953 | if (devno == CM4000_MAX_DEV) | |
2017 | if (i == CM4000_MAX_DEV) | ||
2018 | return; | 1954 | return; |
2019 | 1955 | ||
2020 | cm4000_detach_by_devno(i, link); | 1956 | link->state &= ~DEV_PRESENT; |
1957 | stop_monitor(dev); | ||
1958 | |||
1959 | if (link->state & DEV_CONFIG) | ||
1960 | cm4000_release(link); | ||
1961 | |||
1962 | dev_table[devno] = NULL; | ||
1963 | kfree(dev); | ||
1964 | |||
2021 | return; | 1965 | return; |
2022 | } | 1966 | } |
2023 | 1967 | ||
@@ -2042,9 +1986,10 @@ static struct pcmcia_driver cm4000_driver = { | |||
2042 | .drv = { | 1986 | .drv = { |
2043 | .name = "cm4000_cs", | 1987 | .name = "cm4000_cs", |
2044 | }, | 1988 | }, |
2045 | .attach = cm4000_attach, | 1989 | .probe = cm4000_attach, |
2046 | .detach = cm4000_detach, | 1990 | .remove = cm4000_detach, |
2047 | .event = cm4000_event, | 1991 | .suspend = cm4000_suspend, |
1992 | .resume = cm4000_resume, | ||
2048 | .id_table = cm4000_ids, | 1993 | .id_table = cm4000_ids, |
2049 | }; | 1994 | }; |
2050 | 1995 | ||
@@ -2064,13 +2009,8 @@ static int __init cmm_init(void) | |||
2064 | 2009 | ||
2065 | static void __exit cmm_exit(void) | 2010 | static void __exit cmm_exit(void) |
2066 | { | 2011 | { |
2067 | int i; | ||
2068 | |||
2069 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | 2012 | printk(KERN_INFO MODULE_NAME ": unloading\n"); |
2070 | pcmcia_unregister_driver(&cm4000_driver); | 2013 | pcmcia_unregister_driver(&cm4000_driver); |
2071 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
2072 | if (dev_table[i]) | ||
2073 | cm4000_detach_by_devno(i, dev_table[i]); | ||
2074 | unregister_chrdev(major, DEVICE_NAME); | 2014 | unregister_chrdev(major, DEVICE_NAME); |
2075 | }; | 2015 | }; |
2076 | 2016 | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 4c698d908ffa..46eb371bf17e 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -65,7 +65,6 @@ static char *version = | |||
65 | #define POLL_PERIOD msecs_to_jiffies(10) | 65 | #define POLL_PERIOD msecs_to_jiffies(10) |
66 | 66 | ||
67 | static void reader_release(dev_link_t *link); | 67 | static void reader_release(dev_link_t *link); |
68 | static void reader_detach(dev_link_t *link); | ||
69 | 68 | ||
70 | static int major; | 69 | static int major; |
71 | 70 | ||
@@ -86,7 +85,6 @@ struct reader_dev { | |||
86 | struct timer_list poll_timer; | 85 | struct timer_list poll_timer; |
87 | }; | 86 | }; |
88 | 87 | ||
89 | static dev_info_t dev_info = MODULE_NAME; | ||
90 | static dev_link_t *dev_table[CM_MAX_DEV]; | 88 | static dev_link_t *dev_table[CM_MAX_DEV]; |
91 | 89 | ||
92 | #ifndef PCMCIA_DEBUG | 90 | #ifndef PCMCIA_DEBUG |
@@ -629,65 +627,26 @@ cs_release: | |||
629 | link->state &= ~DEV_CONFIG_PENDING; | 627 | link->state &= ~DEV_CONFIG_PENDING; |
630 | } | 628 | } |
631 | 629 | ||
632 | static int reader_event(event_t event, int priority, | 630 | static int reader_suspend(struct pcmcia_device *p_dev) |
633 | event_callback_args_t *args) | ||
634 | { | 631 | { |
635 | dev_link_t *link; | 632 | dev_link_t *link = dev_to_instance(p_dev); |
636 | struct reader_dev *dev; | ||
637 | int devno; | ||
638 | 633 | ||
639 | link = args->client_data; | 634 | link->state |= DEV_SUSPEND; |
640 | dev = link->priv; | 635 | if (link->state & DEV_CONFIG) |
641 | DEBUGP(3, dev, "-> reader_event\n"); | 636 | pcmcia_release_configuration(link->handle); |
642 | for (devno = 0; devno < CM_MAX_DEV; devno++) { | ||
643 | if (dev_table[devno] == link) | ||
644 | break; | ||
645 | } | ||
646 | if (devno == CM_MAX_DEV) | ||
647 | return CS_BAD_ADAPTER; | ||
648 | 637 | ||
649 | switch (event) { | 638 | return 0; |
650 | case CS_EVENT_CARD_INSERTION: | 639 | } |
651 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | 640 | |
652 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 641 | static int reader_resume(struct pcmcia_device *p_dev) |
653 | reader_config(link, devno); | 642 | { |
654 | break; | 643 | dev_link_t *link = dev_to_instance(p_dev); |
655 | case CS_EVENT_CARD_REMOVAL: | 644 | |
656 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | 645 | link->state &= ~DEV_SUSPEND; |
657 | link->state &= ~DEV_PRESENT; | 646 | if (link->state & DEV_CONFIG) |
658 | break; | 647 | pcmcia_request_configuration(link->handle, &link->conf); |
659 | case CS_EVENT_PM_SUSPEND: | 648 | |
660 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | 649 | return 0; |
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: | ||
685 | DEBUGP(5, dev, "reader_event: unknown event %.2x\n", | ||
686 | event); | ||
687 | break; | ||
688 | } | ||
689 | DEBUGP(3, dev, "<- reader_event\n"); | ||
690 | return CS_SUCCESS; | ||
691 | } | 650 | } |
692 | 651 | ||
693 | static void reader_release(dev_link_t *link) | 652 | static void reader_release(dev_link_t *link) |
@@ -697,11 +656,10 @@ static void reader_release(dev_link_t *link) | |||
697 | pcmcia_release_io(link->handle, &link->io); | 656 | pcmcia_release_io(link->handle, &link->io); |
698 | } | 657 | } |
699 | 658 | ||
700 | static dev_link_t *reader_attach(void) | 659 | static int reader_attach(struct pcmcia_device *p_dev) |
701 | { | 660 | { |
702 | struct reader_dev *dev; | 661 | struct reader_dev *dev; |
703 | dev_link_t *link; | 662 | dev_link_t *link; |
704 | client_reg_t client_reg; | ||
705 | int i; | 663 | int i; |
706 | 664 | ||
707 | for (i = 0; i < CM_MAX_DEV; i++) { | 665 | for (i = 0; i < CM_MAX_DEV; i++) { |
@@ -710,11 +668,11 @@ static dev_link_t *reader_attach(void) | |||
710 | } | 668 | } |
711 | 669 | ||
712 | if (i == CM_MAX_DEV) | 670 | if (i == CM_MAX_DEV) |
713 | return NULL; | 671 | return -ENODEV; |
714 | 672 | ||
715 | dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL); | 673 | dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL); |
716 | if (dev == NULL) | 674 | if (dev == NULL) |
717 | return NULL; | 675 | return -ENOMEM; |
718 | 676 | ||
719 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | 677 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; |
720 | dev->buffer_status = 0; | 678 | dev->buffer_status = 0; |
@@ -725,20 +683,6 @@ static dev_link_t *reader_attach(void) | |||
725 | link->conf.IntType = INT_MEMORY_AND_IO; | 683 | link->conf.IntType = INT_MEMORY_AND_IO; |
726 | dev_table[i] = link; | 684 | dev_table[i] = link; |
727 | 685 | ||
728 | client_reg.dev_info = &dev_info; | ||
729 | client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; | ||
730 | client_reg.EventMask= | ||
731 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
732 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
733 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
734 | client_reg.Version = 0x0210; | ||
735 | client_reg.event_callback_args.client_data = link; | ||
736 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
737 | if (i) { | ||
738 | cs_error(link->handle, RegisterClient, i); | ||
739 | reader_detach(link); | ||
740 | return NULL; | ||
741 | } | ||
742 | init_waitqueue_head(&dev->devq); | 686 | init_waitqueue_head(&dev->devq); |
743 | init_waitqueue_head(&dev->poll_wait); | 687 | init_waitqueue_head(&dev->poll_wait); |
744 | init_waitqueue_head(&dev->read_wait); | 688 | init_waitqueue_head(&dev->read_wait); |
@@ -746,39 +690,37 @@ static dev_link_t *reader_attach(void) | |||
746 | init_timer(&dev->poll_timer); | 690 | init_timer(&dev->poll_timer); |
747 | dev->poll_timer.function = &cm4040_do_poll; | 691 | dev->poll_timer.function = &cm4040_do_poll; |
748 | 692 | ||
749 | return link; | 693 | link->handle = p_dev; |
750 | } | 694 | p_dev->instance = link; |
751 | |||
752 | static void reader_detach_by_devno(int devno, dev_link_t *link) | ||
753 | { | ||
754 | struct reader_dev *dev = link->priv; | ||
755 | 695 | ||
756 | if (link->state & DEV_CONFIG) { | 696 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
757 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | 697 | reader_config(link, i); |
758 | reader_release(link); | ||
759 | } | ||
760 | 698 | ||
761 | pcmcia_deregister_client(link->handle); | 699 | return 0; |
762 | dev_table[devno] = NULL; | ||
763 | DEBUGP(5, dev, "freeing dev=%p\n", dev); | ||
764 | cm4040_stop_poll(dev); | ||
765 | kfree(dev); | ||
766 | return; | ||
767 | } | 700 | } |
768 | 701 | ||
769 | static void reader_detach(dev_link_t *link) | 702 | static void reader_detach(struct pcmcia_device *p_dev) |
770 | { | 703 | { |
771 | int i; | 704 | dev_link_t *link = dev_to_instance(p_dev); |
705 | struct reader_dev *dev = link->priv; | ||
706 | int devno; | ||
772 | 707 | ||
773 | /* find device */ | 708 | /* find device */ |
774 | for (i = 0; i < CM_MAX_DEV; i++) { | 709 | for (devno = 0; devno < CM_MAX_DEV; devno++) { |
775 | if (dev_table[i] == link) | 710 | if (dev_table[devno] == link) |
776 | break; | 711 | break; |
777 | } | 712 | } |
778 | if (i == CM_MAX_DEV) | 713 | if (devno == CM_MAX_DEV) |
779 | return; | 714 | return; |
780 | 715 | ||
781 | reader_detach_by_devno(i, link); | 716 | link->state &= ~DEV_PRESENT; |
717 | |||
718 | if (link->state & DEV_CONFIG) | ||
719 | reader_release(link); | ||
720 | |||
721 | dev_table[devno] = NULL; | ||
722 | kfree(dev); | ||
723 | |||
782 | return; | 724 | return; |
783 | } | 725 | } |
784 | 726 | ||
@@ -804,9 +746,10 @@ static struct pcmcia_driver reader_driver = { | |||
804 | .drv = { | 746 | .drv = { |
805 | .name = "cm4040_cs", | 747 | .name = "cm4040_cs", |
806 | }, | 748 | }, |
807 | .attach = reader_attach, | 749 | .probe = reader_attach, |
808 | .detach = reader_detach, | 750 | .remove = reader_detach, |
809 | .event = reader_event, | 751 | .suspend = reader_suspend, |
752 | .resume = reader_resume, | ||
810 | .id_table = cm4040_ids, | 753 | .id_table = cm4040_ids, |
811 | }; | 754 | }; |
812 | 755 | ||
@@ -825,14 +768,8 @@ static int __init cm4040_init(void) | |||
825 | 768 | ||
826 | static void __exit cm4040_exit(void) | 769 | static void __exit cm4040_exit(void) |
827 | { | 770 | { |
828 | int i; | ||
829 | |||
830 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | 771 | printk(KERN_INFO MODULE_NAME ": unloading\n"); |
831 | pcmcia_unregister_driver(&reader_driver); | 772 | pcmcia_unregister_driver(&reader_driver); |
832 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
833 | if (dev_table[i]) | ||
834 | reader_detach_by_devno(i, dev_table[i]); | ||
835 | } | ||
836 | unregister_chrdev(major, DEVICE_NAME); | 773 | unregister_chrdev(major, DEVICE_NAME); |
837 | } | 774 | } |
838 | 775 | ||
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 2c326ea53421..cf45b100eff1 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -486,13 +486,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); | |||
486 | 486 | ||
487 | static void mgslpc_config(dev_link_t *link); | 487 | static void mgslpc_config(dev_link_t *link); |
488 | static void mgslpc_release(u_long arg); | 488 | static void mgslpc_release(u_long arg); |
489 | static int mgslpc_event(event_t event, int priority, | 489 | static void mgslpc_detach(struct pcmcia_device *p_dev); |
490 | event_callback_args_t *args); | ||
491 | static dev_link_t *mgslpc_attach(void); | ||
492 | static void mgslpc_detach(dev_link_t *); | ||
493 | |||
494 | static dev_info_t dev_info = "synclink_cs"; | ||
495 | static dev_link_t *dev_list = NULL; | ||
496 | 490 | ||
497 | /* | 491 | /* |
498 | * 1st function defined in .text section. Calling this function in | 492 | * 1st function defined in .text section. Calling this function in |
@@ -539,12 +533,10 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
539 | } | 533 | } |
540 | } | 534 | } |
541 | 535 | ||
542 | static dev_link_t *mgslpc_attach(void) | 536 | static int mgslpc_attach(struct pcmcia_device *p_dev) |
543 | { | 537 | { |
544 | MGSLPC_INFO *info; | 538 | MGSLPC_INFO *info; |
545 | dev_link_t *link; | 539 | dev_link_t *link; |
546 | client_reg_t client_reg; | ||
547 | int ret; | ||
548 | 540 | ||
549 | if (debug_level >= DEBUG_LEVEL_INFO) | 541 | if (debug_level >= DEBUG_LEVEL_INFO) |
550 | printk("mgslpc_attach\n"); | 542 | printk("mgslpc_attach\n"); |
@@ -552,7 +544,7 @@ static dev_link_t *mgslpc_attach(void) | |||
552 | info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); | 544 | info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); |
553 | if (!info) { | 545 | if (!info) { |
554 | printk("Error can't allocate device instance data\n"); | 546 | printk("Error can't allocate device instance data\n"); |
555 | return NULL; | 547 | return -ENOMEM; |
556 | } | 548 | } |
557 | 549 | ||
558 | memset(info, 0, sizeof(MGSLPC_INFO)); | 550 | memset(info, 0, sizeof(MGSLPC_INFO)); |
@@ -587,24 +579,15 @@ static dev_link_t *mgslpc_attach(void) | |||
587 | link->conf.Vcc = 50; | 579 | link->conf.Vcc = 50; |
588 | link->conf.IntType = INT_MEMORY_AND_IO; | 580 | link->conf.IntType = INT_MEMORY_AND_IO; |
589 | 581 | ||
590 | /* Register with Card Services */ | 582 | link->handle = p_dev; |
591 | link->next = dev_list; | 583 | p_dev->instance = link; |
592 | dev_list = link; | ||
593 | |||
594 | client_reg.dev_info = &dev_info; | ||
595 | client_reg.Version = 0x0210; | ||
596 | client_reg.event_callback_args.client_data = link; | ||
597 | 584 | ||
598 | ret = pcmcia_register_client(&link->handle, &client_reg); | 585 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
599 | if (ret != CS_SUCCESS) { | 586 | mgslpc_config(link); |
600 | cs_error(link->handle, RegisterClient, ret); | ||
601 | mgslpc_detach(link); | ||
602 | return NULL; | ||
603 | } | ||
604 | 587 | ||
605 | mgslpc_add_device(info); | 588 | mgslpc_add_device(info); |
606 | 589 | ||
607 | return link; | 590 | return 0; |
608 | } | 591 | } |
609 | 592 | ||
610 | /* Card has been inserted. | 593 | /* Card has been inserted. |
@@ -736,85 +719,50 @@ static void mgslpc_release(u_long arg) | |||
736 | pcmcia_release_io(link->handle, &link->io); | 719 | pcmcia_release_io(link->handle, &link->io); |
737 | if (link->irq.AssignedIRQ) | 720 | if (link->irq.AssignedIRQ) |
738 | pcmcia_release_irq(link->handle, &link->irq); | 721 | pcmcia_release_irq(link->handle, &link->irq); |
739 | if (link->state & DEV_STALE_LINK) | ||
740 | mgslpc_detach(link); | ||
741 | } | 722 | } |
742 | 723 | ||
743 | static void mgslpc_detach(dev_link_t *link) | 724 | static void mgslpc_detach(struct pcmcia_device *p_dev) |
744 | { | 725 | { |
745 | dev_link_t **linkp; | 726 | dev_link_t *link = dev_to_instance(p_dev); |
746 | 727 | ||
747 | if (debug_level >= DEBUG_LEVEL_INFO) | 728 | if (debug_level >= DEBUG_LEVEL_INFO) |
748 | printk("mgslpc_detach(0x%p)\n", link); | 729 | printk("mgslpc_detach(0x%p)\n", link); |
749 | |||
750 | /* find device */ | ||
751 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
752 | if (*linkp == link) break; | ||
753 | if (*linkp == NULL) | ||
754 | return; | ||
755 | 730 | ||
756 | if (link->state & DEV_CONFIG) { | 731 | if (link->state & DEV_CONFIG) { |
757 | /* device is configured/active, mark it so when | 732 | ((MGSLPC_INFO *)link->priv)->stop = 1; |
758 | * release() is called a proper detach() occurs. | 733 | mgslpc_release((u_long)link); |
759 | */ | ||
760 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
761 | printk(KERN_DEBUG "synclinkpc: detach postponed, '%s' " | ||
762 | "still locked\n", link->dev->dev_name); | ||
763 | link->state |= DEV_STALE_LINK; | ||
764 | return; | ||
765 | } | 734 | } |
766 | 735 | ||
767 | /* Break the link with Card Services */ | ||
768 | if (link->handle) | ||
769 | pcmcia_deregister_client(link->handle); | ||
770 | |||
771 | /* Unlink device structure, and free it */ | ||
772 | *linkp = link->next; | ||
773 | mgslpc_remove_device((MGSLPC_INFO *)link->priv); | 736 | mgslpc_remove_device((MGSLPC_INFO *)link->priv); |
774 | } | 737 | } |
775 | 738 | ||
776 | static int mgslpc_event(event_t event, int priority, | 739 | static int mgslpc_suspend(struct pcmcia_device *dev) |
777 | event_callback_args_t *args) | ||
778 | { | 740 | { |
779 | dev_link_t *link = args->client_data; | 741 | dev_link_t *link = dev_to_instance(dev); |
780 | MGSLPC_INFO *info = link->priv; | 742 | MGSLPC_INFO *info = link->priv; |
781 | 743 | ||
782 | if (debug_level >= DEBUG_LEVEL_INFO) | 744 | link->state |= DEV_SUSPEND; |
783 | printk("mgslpc_event(0x%06x)\n", event); | 745 | info->stop = 1; |
784 | 746 | if (link->state & DEV_CONFIG) | |
785 | switch (event) { | 747 | pcmcia_release_configuration(link->handle); |
786 | case CS_EVENT_CARD_REMOVAL: | 748 | |
787 | link->state &= ~DEV_PRESENT; | 749 | return 0; |
788 | if (link->state & DEV_CONFIG) { | ||
789 | ((MGSLPC_INFO *)link->priv)->stop = 1; | ||
790 | mgslpc_release((u_long)link); | ||
791 | } | ||
792 | break; | ||
793 | case CS_EVENT_CARD_INSERTION: | ||
794 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
795 | mgslpc_config(link); | ||
796 | 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 | } | ||
815 | return 0; | ||
816 | } | 750 | } |
817 | 751 | ||
752 | static int mgslpc_resume(struct pcmcia_device *dev) | ||
753 | { | ||
754 | dev_link_t *link = dev_to_instance(dev); | ||
755 | MGSLPC_INFO *info = link->priv; | ||
756 | |||
757 | link->state &= ~DEV_SUSPEND; | ||
758 | if (link->state & DEV_CONFIG) | ||
759 | pcmcia_request_configuration(link->handle, &link->conf); | ||
760 | info->stop = 0; | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | |||
818 | static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, | 766 | static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, |
819 | char *name, const char *routine) | 767 | char *name, const char *routine) |
820 | { | 768 | { |
@@ -3091,10 +3039,11 @@ static struct pcmcia_driver mgslpc_driver = { | |||
3091 | .drv = { | 3039 | .drv = { |
3092 | .name = "synclink_cs", | 3040 | .name = "synclink_cs", |
3093 | }, | 3041 | }, |
3094 | .attach = mgslpc_attach, | 3042 | .probe = mgslpc_attach, |
3095 | .event = mgslpc_event, | 3043 | .remove = mgslpc_detach, |
3096 | .detach = mgslpc_detach, | ||
3097 | .id_table = mgslpc_ids, | 3044 | .id_table = mgslpc_ids, |
3045 | .suspend = mgslpc_suspend, | ||
3046 | .resume = mgslpc_resume, | ||
3098 | }; | 3047 | }; |
3099 | 3048 | ||
3100 | static struct tty_operations mgslpc_ops = { | 3049 | static struct tty_operations mgslpc_ops = { |
@@ -3138,7 +3087,6 @@ static void synclink_cs_cleanup(void) | |||
3138 | } | 3087 | } |
3139 | 3088 | ||
3140 | pcmcia_unregister_driver(&mgslpc_driver); | 3089 | pcmcia_unregister_driver(&mgslpc_driver); |
3141 | BUG_ON(dev_list != NULL); | ||
3142 | } | 3090 | } |
3143 | 3091 | ||
3144 | static int __init synclink_cs_init(void) | 3092 | static int __init synclink_cs_init(void) |