aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/pcmcia/synclink_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/pcmcia/synclink_cs.c')
-rw-r--r--drivers/char/pcmcia/synclink_cs.c132
1 files changed, 40 insertions, 92 deletions
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
487static void mgslpc_config(dev_link_t *link); 487static void mgslpc_config(dev_link_t *link);
488static void mgslpc_release(u_long arg); 488static void mgslpc_release(u_long arg);
489static int mgslpc_event(event_t event, int priority, 489static void mgslpc_detach(struct pcmcia_device *p_dev);
490 event_callback_args_t *args);
491static dev_link_t *mgslpc_attach(void);
492static void mgslpc_detach(dev_link_t *);
493
494static dev_info_t dev_info = "synclink_cs";
495static 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
542static dev_link_t *mgslpc_attach(void) 536static 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
743static void mgslpc_detach(dev_link_t *link) 724static 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
776static int mgslpc_event(event_t event, int priority, 739static 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
752static 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
818static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, 766static 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
3100static struct tty_operations mgslpc_ops = { 3049static 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
3144static int __init synclink_cs_init(void) 3092static int __init synclink_cs_init(void)