aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/cs.c')
-rw-r--r--drivers/pcmcia/cs.c177
1 files changed, 58 insertions, 119 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 7ba45b0cca6b..823ecda32216 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -505,7 +505,10 @@ static int socket_insert(struct pcmcia_socket *skt)
505 dev_dbg(&skt->dev, "insert\n"); 505 dev_dbg(&skt->dev, "insert\n");
506 506
507 mutex_lock(&skt->ops_mutex); 507 mutex_lock(&skt->ops_mutex);
508 WARN_ON(skt->state & SOCKET_INUSE); 508 if (skt->state & SOCKET_INUSE) {
509 mutex_unlock(&skt->ops_mutex);
510 return -EINVAL;
511 }
509 skt->state |= SOCKET_INUSE; 512 skt->state |= SOCKET_INUSE;
510 513
511 ret = socket_setup(skt, setup_delay); 514 ret = socket_setup(skt, setup_delay);
@@ -682,16 +685,19 @@ static int pccardd(void *__skt)
682 for (;;) { 685 for (;;) {
683 unsigned long flags; 686 unsigned long flags;
684 unsigned int events; 687 unsigned int events;
688 unsigned int sysfs_events;
685 689
686 set_current_state(TASK_INTERRUPTIBLE); 690 set_current_state(TASK_INTERRUPTIBLE);
687 691
688 spin_lock_irqsave(&skt->thread_lock, flags); 692 spin_lock_irqsave(&skt->thread_lock, flags);
689 events = skt->thread_events; 693 events = skt->thread_events;
690 skt->thread_events = 0; 694 skt->thread_events = 0;
695 sysfs_events = skt->sysfs_events;
696 skt->sysfs_events = 0;
691 spin_unlock_irqrestore(&skt->thread_lock, flags); 697 spin_unlock_irqrestore(&skt->thread_lock, flags);
692 698
699 mutex_lock(&skt->skt_mutex);
693 if (events) { 700 if (events) {
694 mutex_lock(&skt->skt_mutex);
695 if (events & SS_DETECT) 701 if (events & SS_DETECT)
696 socket_detect_change(skt); 702 socket_detect_change(skt);
697 if (events & SS_BATDEAD) 703 if (events & SS_BATDEAD)
@@ -700,10 +706,34 @@ static int pccardd(void *__skt)
700 send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW); 706 send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
701 if (events & SS_READY) 707 if (events & SS_READY)
702 send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW); 708 send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
703 mutex_unlock(&skt->skt_mutex);
704 continue;
705 } 709 }
706 710
711 if (sysfs_events) {
712 if (sysfs_events & PCMCIA_UEVENT_EJECT)
713 socket_remove(skt);
714 if (sysfs_events & PCMCIA_UEVENT_INSERT)
715 socket_insert(skt);
716 if ((sysfs_events & PCMCIA_UEVENT_RESUME) &&
717 !(skt->state & SOCKET_CARDBUS)) {
718 ret = socket_resume(skt);
719 if (!ret && skt->callback)
720 skt->callback->resume(skt);
721 }
722 if ((sysfs_events & PCMCIA_UEVENT_SUSPEND) &&
723 !(skt->state & SOCKET_CARDBUS)) {
724 if (skt->callback)
725 ret = skt->callback->suspend(skt);
726 else
727 ret = 0;
728 if (!ret)
729 socket_suspend(skt);
730 }
731 }
732 mutex_unlock(&skt->skt_mutex);
733
734 if (events || sysfs_events)
735 continue;
736
707 if (kthread_should_stop()) 737 if (kthread_should_stop())
708 break; 738 break;
709 739
@@ -745,6 +775,30 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
745} /* pcmcia_parse_events */ 775} /* pcmcia_parse_events */
746EXPORT_SYMBOL(pcmcia_parse_events); 776EXPORT_SYMBOL(pcmcia_parse_events);
747 777
778/**
779 * pcmcia_parse_uevents() - tell pccardd to issue manual commands
780 * @s: the PCMCIA socket we wan't to command
781 * @events: events to pass to pccardd
782 *
783 * userspace-issued insert, eject, suspend and resume commands must be
784 * handled by pccardd to avoid any sysfs-related deadlocks. Valid events
785 * are PCMCIA_UEVENT_EJECT (for eject), PCMCIA_UEVENT__INSERT (for insert),
786 * PCMCIA_UEVENT_RESUME (for resume) and PCMCIA_UEVENT_SUSPEND (for suspend).
787 */
788void pcmcia_parse_uevents(struct pcmcia_socket *s, u_int events)
789{
790 unsigned long flags;
791 dev_dbg(&s->dev, "parse_uevents: events %08x\n", events);
792 if (s->thread) {
793 spin_lock_irqsave(&s->thread_lock, flags);
794 s->sysfs_events |= events;
795 spin_unlock_irqrestore(&s->thread_lock, flags);
796
797 wake_up_process(s->thread);
798 }
799}
800EXPORT_SYMBOL(pcmcia_parse_uevents);
801
748 802
749/* register pcmcia_callback */ 803/* register pcmcia_callback */
750int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) 804int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
@@ -828,121 +882,6 @@ int pcmcia_reset_card(struct pcmcia_socket *skt)
828EXPORT_SYMBOL(pcmcia_reset_card); 882EXPORT_SYMBOL(pcmcia_reset_card);
829 883
830 884
831/* These shut down or wake up a socket. They are sort of user
832 * initiated versions of the APM suspend and resume actions.
833 */
834int pcmcia_suspend_card(struct pcmcia_socket *skt)
835{
836 int ret;
837
838 dev_dbg(&skt->dev, "suspending socket\n");
839
840 mutex_lock(&skt->skt_mutex);
841 do {
842 if (!(skt->state & SOCKET_PRESENT)) {
843 ret = -ENODEV;
844 break;
845 }
846 if (skt->state & SOCKET_CARDBUS) {
847 ret = -EPERM;
848 break;
849 }
850 if (skt->callback) {
851 ret = skt->callback->suspend(skt);
852 if (ret)
853 break;
854 }
855 ret = socket_suspend(skt);
856 } while (0);
857 mutex_unlock(&skt->skt_mutex);
858
859 return ret;
860} /* suspend_card */
861EXPORT_SYMBOL(pcmcia_suspend_card);
862
863
864int pcmcia_resume_card(struct pcmcia_socket *skt)
865{
866 int ret;
867
868 dev_dbg(&skt->dev, "waking up socket\n");
869
870 mutex_lock(&skt->skt_mutex);
871 do {
872 if (!(skt->state & SOCKET_PRESENT)) {
873 ret = -ENODEV;
874 break;
875 }
876 if (skt->state & SOCKET_CARDBUS) {
877 ret = -EPERM;
878 break;
879 }
880 ret = socket_resume(skt);
881 if (!ret && skt->callback)
882 skt->callback->resume(skt);
883 } while (0);
884 mutex_unlock(&skt->skt_mutex);
885
886 return ret;
887} /* resume_card */
888EXPORT_SYMBOL(pcmcia_resume_card);
889
890
891/* These handle user requests to eject or insert a card. */
892int pcmcia_eject_card(struct pcmcia_socket *skt)
893{
894 int ret;
895
896 dev_dbg(&skt->dev, "user eject request\n");
897
898 mutex_lock(&skt->skt_mutex);
899 do {
900 if (!(skt->state & SOCKET_PRESENT)) {
901 ret = -ENODEV;
902 break;
903 }
904
905 ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);
906 if (ret != 0) {
907 ret = -EINVAL;
908 break;
909 }
910
911 socket_remove(skt);
912 ret = 0;
913 } while (0);
914 mutex_unlock(&skt->skt_mutex);
915
916 return ret;
917} /* eject_card */
918EXPORT_SYMBOL(pcmcia_eject_card);
919
920
921int pcmcia_insert_card(struct pcmcia_socket *skt)
922{
923 int ret;
924
925 dev_dbg(&skt->dev, "user insert request\n");
926
927 mutex_lock(&skt->skt_mutex);
928 do {
929 if (skt->state & SOCKET_PRESENT) {
930 ret = -EBUSY;
931 break;
932 }
933 if (socket_insert(skt) == -ENODEV) {
934 ret = -ENODEV;
935 break;
936 }
937 ret = 0;
938 } while (0);
939 mutex_unlock(&skt->skt_mutex);
940
941 return ret;
942} /* insert_card */
943EXPORT_SYMBOL(pcmcia_insert_card);
944
945
946static int pcmcia_socket_uevent(struct device *dev, 885static int pcmcia_socket_uevent(struct device *dev,
947 struct kobj_uevent_env *env) 886 struct kobj_uevent_env *env)
948{ 887{