diff options
Diffstat (limited to 'drivers/pcmcia/cs.c')
-rw-r--r-- | drivers/pcmcia/cs.c | 112 |
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 | } |
310 | EXPORT_SYMBOL(pcmcia_get_socket_by_nr); | 310 | EXPORT_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 | */ | ||
319 | static 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 | ||
386 | static 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 | |||
397 | static int socket_reset(struct pcmcia_socket *skt) | 351 | static 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 | */ | ||
387 | static 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 | |||
427 | static int socket_setup(struct pcmcia_socket *skt, int initial_delay) | 420 | static 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) | |||
901 | EXPORT_SYMBOL(pcmcia_insert_card); | 903 | EXPORT_SYMBOL(pcmcia_insert_card); |
902 | 904 | ||
903 | 905 | ||
904 | static int pcmcia_socket_hotplug(struct class_device *dev, char **envp, | 906 | static 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 | ||
928 | struct class pcmcia_socket_class = { | 930 | struct 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 | }; |