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.c112
1 files changed, 57 insertions, 55 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index a30aa74304a2..613f2f1fbfdd 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -309,41 +309,6 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
309} 309}
310EXPORT_SYMBOL(pcmcia_get_socket_by_nr); 310EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
311 311
312
313/**
314 * socket_setup() and shutdown_socket() are called by the main event
315 * handler when card insertion and removal events are received.
316 * socket_setup() turns on socket power and resets the socket, in two stages.
317 * shutdown_socket() unconfigures a socket and turns off socket power.
318 */
319static void shutdown_socket(struct pcmcia_socket *s)
320{
321 cs_dbg(s, 1, "shutdown_socket\n");
322
323 /* Blank out the socket state */
324 s->socket = dead_socket;
325 s->ops->init(s);
326 s->ops->set_socket(s, &s->socket);
327 s->irq.AssignedIRQ = s->irq.Config = 0;
328 s->lock_count = 0;
329 destroy_cis_cache(s);
330#ifdef CONFIG_CARDBUS
331 cb_free(s);
332#endif
333 s->functions = 0;
334 kfree(s->config);
335 s->config = NULL;
336
337 {
338 int status;
339 s->ops->get_status(s, &status);
340 if (status & SS_POWERON) {
341 printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
342 }
343 }
344} /* shutdown_socket */
345
346
347/** 312/**
348 * The central event handler. Send_event() sends an event to the 313 * The central event handler. Send_event() sends an event to the
349 * 16-bit subsystem, which then calls the relevant device drivers. 314 * 16-bit subsystem, which then calls the relevant device drivers.
@@ -383,17 +348,6 @@ static void socket_remove_drivers(struct pcmcia_socket *skt)
383 send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); 348 send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
384} 349}
385 350
386static void socket_shutdown(struct pcmcia_socket *skt)
387{
388 cs_dbg(skt, 4, "shutdown\n");
389
390 socket_remove_drivers(skt);
391 skt->state &= SOCKET_INUSE|SOCKET_PRESENT;
392 msleep(shutdown_delay * 10);
393 skt->state &= SOCKET_INUSE;
394 shutdown_socket(skt);
395}
396
397static int socket_reset(struct pcmcia_socket *skt) 351static int socket_reset(struct pcmcia_socket *skt)
398{ 352{
399 int status, i; 353 int status, i;
@@ -424,6 +378,45 @@ static int socket_reset(struct pcmcia_socket *skt)
424 return CS_GENERAL_FAILURE; 378 return CS_GENERAL_FAILURE;
425} 379}
426 380
381/**
382 * socket_setup() and socket_shutdown() are called by the main event handler
383 * when card insertion and removal events are received.
384 * socket_setup() turns on socket power and resets the socket, in two stages.
385 * socket_shutdown() unconfigures a socket and turns off socket power.
386 */
387static void socket_shutdown(struct pcmcia_socket *s)
388{
389 int status;
390
391 cs_dbg(s, 4, "shutdown\n");
392
393 socket_remove_drivers(s);
394 s->state &= SOCKET_INUSE | SOCKET_PRESENT;
395 msleep(shutdown_delay * 10);
396 s->state &= SOCKET_INUSE;
397
398 /* Blank out the socket state */
399 s->socket = dead_socket;
400 s->ops->init(s);
401 s->ops->set_socket(s, &s->socket);
402 s->irq.AssignedIRQ = s->irq.Config = 0;
403 s->lock_count = 0;
404 destroy_cis_cache(s);
405#ifdef CONFIG_CARDBUS
406 cb_free(s);
407#endif
408 s->functions = 0;
409 kfree(s->config);
410 s->config = NULL;
411
412 s->ops->get_status(s, &status);
413 if (status & SS_POWERON) {
414 printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
415 }
416
417 cs_socket_put(s);
418}
419
427static int socket_setup(struct pcmcia_socket *skt, int initial_delay) 420static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
428{ 421{
429 int status, i; 422 int status, i;
@@ -529,7 +522,6 @@ static int socket_insert(struct pcmcia_socket *skt)
529 send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); 522 send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
530 } else { 523 } else {
531 socket_shutdown(skt); 524 socket_shutdown(skt);
532 cs_socket_put(skt);
533 } 525 }
534 526
535 return ret; 527 return ret;
@@ -593,7 +585,6 @@ static int socket_resume(struct pcmcia_socket *skt)
593 } 585 }
594 } else { 586 } else {
595 socket_shutdown(skt); 587 socket_shutdown(skt);
596 cs_socket_put(skt);
597 } 588 }
598 589
599 skt->state &= ~SOCKET_SUSPEND; 590 skt->state &= ~SOCKET_SUSPEND;
@@ -605,7 +596,6 @@ static void socket_remove(struct pcmcia_socket *skt)
605{ 596{
606 printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock); 597 printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock);
607 socket_shutdown(skt); 598 socket_shutdown(skt);
608 cs_socket_put(skt);
609} 599}
610 600
611/* 601/*
@@ -780,8 +770,13 @@ int pccard_reset_card(struct pcmcia_socket *skt)
780 ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW); 770 ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
781 if (ret == 0) { 771 if (ret == 0) {
782 send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); 772 send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
783 if (socket_reset(skt) == CS_SUCCESS) 773 if (skt->callback)
774 skt->callback->suspend(skt);
775 if (socket_reset(skt) == CS_SUCCESS) {
784 send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); 776 send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
777 if (skt->callback)
778 skt->callback->resume(skt);
779 }
785 } 780 }
786 781
787 ret = CS_SUCCESS; 782 ret = CS_SUCCESS;
@@ -812,6 +807,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
812 ret = CS_UNSUPPORTED_FUNCTION; 807 ret = CS_UNSUPPORTED_FUNCTION;
813 break; 808 break;
814 } 809 }
810 if (skt->callback) {
811 ret = skt->callback->suspend(skt);
812 if (ret)
813 break;
814 }
815 ret = socket_suspend(skt); 815 ret = socket_suspend(skt);
816 } while (0); 816 } while (0);
817 up(&skt->skt_sem); 817 up(&skt->skt_sem);
@@ -838,6 +838,8 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
838 break; 838 break;
839 } 839 }
840 ret = socket_resume(skt); 840 ret = socket_resume(skt);
841 if (!ret && skt->callback)
842 skt->callback->resume(skt);
841 } while (0); 843 } while (0);
842 up(&skt->skt_sem); 844 up(&skt->skt_sem);
843 845
@@ -901,14 +903,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
901EXPORT_SYMBOL(pcmcia_insert_card); 903EXPORT_SYMBOL(pcmcia_insert_card);
902 904
903 905
904static int pcmcia_socket_hotplug(struct class_device *dev, char **envp, 906static int pcmcia_socket_uevent(struct class_device *dev, char **envp,
905 int num_envp, char *buffer, int buffer_size) 907 int num_envp, char *buffer, int buffer_size)
906{ 908{
907 struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); 909 struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
908 int i = 0, length = 0; 910 int i = 0, length = 0;
909 911
910 if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, 912 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
911 &length, "SOCKET_NO=%u", s->sock)) 913 &length, "SOCKET_NO=%u", s->sock))
912 return -ENOMEM; 914 return -ENOMEM;
913 915
914 envp[i] = NULL; 916 envp[i] = NULL;
@@ -927,7 +929,7 @@ static void pcmcia_release_socket_class(struct class *data)
927 929
928struct class pcmcia_socket_class = { 930struct class pcmcia_socket_class = {
929 .name = "pcmcia_socket", 931 .name = "pcmcia_socket",
930 .hotplug = pcmcia_socket_hotplug, 932 .uevent = pcmcia_socket_uevent,
931 .release = pcmcia_release_socket, 933 .release = pcmcia_release_socket,
932 .class_release = pcmcia_release_socket_class, 934 .class_release = pcmcia_release_socket_class,
933}; 935};