diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2006-01-15 03:32:39 -0500 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2006-03-31 10:15:50 -0500 |
commit | 5f2a71fcb7995633b335a1e380ac63a968e61320 (patch) | |
tree | d47f4227d314fc9f298b75c217fa78440004e6e7 /drivers/pcmcia | |
parent | 1de9cedfbdff1d8adb662cd3afc5bda66e393351 (diff) |
[PATCH] pcmcia: add pcmcia_disable_device
pcmcia_disable_device(struct pcmcia_device *p_dev) performs the necessary
cleanups upon device or driver removal: it calls the appropriate
pcmcia_release_* functions, and can replace (most) of the current drivers'
_release() functions.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 71 |
1 files changed, 41 insertions, 30 deletions
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index dbd5571064d1..555c8698ebd9 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -451,20 +451,20 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
451 | { | 451 | { |
452 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 452 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
453 | struct pcmcia_socket *s = p_dev->socket; | 453 | struct pcmcia_socket *s = p_dev->socket; |
454 | config_t *c = p_dev->function_config; | ||
454 | int i; | 455 | int i; |
455 | 456 | ||
456 | if (!(p_dev->state & CLIENT_CONFIG_LOCKED)) | 457 | if (p_dev->state & CLIENT_CONFIG_LOCKED) { |
457 | return CS_BAD_HANDLE; | 458 | p_dev->state &= ~CLIENT_CONFIG_LOCKED; |
458 | p_dev->state &= ~CLIENT_CONFIG_LOCKED; | ||
459 | |||
460 | if (!(p_dev->state & CLIENT_STALE)) { | ||
461 | config_t *c = p_dev->function_config; | ||
462 | if (--(s->lock_count) == 0) { | 459 | if (--(s->lock_count) == 0) { |
463 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ | 460 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ |
464 | s->socket.Vpp = 0; | 461 | s->socket.Vpp = 0; |
465 | s->socket.io_irq = 0; | 462 | s->socket.io_irq = 0; |
466 | s->ops->set_socket(s, &s->socket); | 463 | s->ops->set_socket(s, &s->socket); |
467 | } | 464 | } |
465 | } | ||
466 | if (c->state & CONFIG_LOCKED) { | ||
467 | c->state &= ~CONFIG_LOCKED; | ||
468 | if (c->state & CONFIG_IO_REQ) | 468 | if (c->state & CONFIG_IO_REQ) |
469 | for (i = 0; i < MAX_IO_WIN; i++) { | 469 | for (i = 0; i < MAX_IO_WIN; i++) { |
470 | if (!s->io[i].res) | 470 | if (!s->io[i].res) |
@@ -475,7 +475,6 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
475 | io.map = i; | 475 | io.map = i; |
476 | s->ops->set_io_map(s, &io); | 476 | s->ops->set_io_map(s, &io); |
477 | } | 477 | } |
478 | c->state &= ~CONFIG_LOCKED; | ||
479 | } | 478 | } |
480 | 479 | ||
481 | return CS_SUCCESS; | 480 | return CS_SUCCESS; |
@@ -494,22 +493,20 @@ EXPORT_SYMBOL(pcmcia_release_configuration); | |||
494 | int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | 493 | int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) |
495 | { | 494 | { |
496 | struct pcmcia_socket *s = p_dev->socket; | 495 | struct pcmcia_socket *s = p_dev->socket; |
496 | config_t *c = p_dev->function_config; | ||
497 | 497 | ||
498 | if (!(p_dev->state & CLIENT_IO_REQ)) | 498 | if (!(p_dev->state & CLIENT_IO_REQ)) |
499 | return CS_BAD_HANDLE; | 499 | return CS_BAD_HANDLE; |
500 | |||
500 | p_dev->state &= ~CLIENT_IO_REQ; | 501 | p_dev->state &= ~CLIENT_IO_REQ; |
501 | 502 | ||
502 | if (!(p_dev->state & CLIENT_STALE)) { | 503 | if ((c->io.BasePort1 != req->BasePort1) || |
503 | config_t *c = p_dev->function_config; | 504 | (c->io.NumPorts1 != req->NumPorts1) || |
504 | if (c->state & CONFIG_LOCKED) | 505 | (c->io.BasePort2 != req->BasePort2) || |
505 | return CS_CONFIGURATION_LOCKED; | 506 | (c->io.NumPorts2 != req->NumPorts2)) |
506 | if ((c->io.BasePort1 != req->BasePort1) || | 507 | return CS_BAD_ARGS; |
507 | (c->io.NumPorts1 != req->NumPorts1) || | 508 | |
508 | (c->io.BasePort2 != req->BasePort2) || | 509 | c->state &= ~CONFIG_IO_REQ; |
509 | (c->io.NumPorts2 != req->NumPorts2)) | ||
510 | return CS_BAD_ARGS; | ||
511 | c->state &= ~CONFIG_IO_REQ; | ||
512 | } | ||
513 | 510 | ||
514 | release_io_space(s, req->BasePort1, req->NumPorts1); | 511 | release_io_space(s, req->BasePort1, req->NumPorts1); |
515 | if (req->NumPorts2) | 512 | if (req->NumPorts2) |
@@ -523,22 +520,21 @@ EXPORT_SYMBOL(pcmcia_release_io); | |||
523 | int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | 520 | int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) |
524 | { | 521 | { |
525 | struct pcmcia_socket *s = p_dev->socket; | 522 | struct pcmcia_socket *s = p_dev->socket; |
523 | config_t *c= p_dev->function_config; | ||
524 | |||
526 | if (!(p_dev->state & CLIENT_IRQ_REQ)) | 525 | if (!(p_dev->state & CLIENT_IRQ_REQ)) |
527 | return CS_BAD_HANDLE; | 526 | return CS_BAD_HANDLE; |
528 | p_dev->state &= ~CLIENT_IRQ_REQ; | 527 | p_dev->state &= ~CLIENT_IRQ_REQ; |
529 | 528 | ||
530 | if (!(p_dev->state & CLIENT_STALE)) { | 529 | if (c->state & CONFIG_LOCKED) |
531 | config_t *c= p_dev->function_config; | 530 | return CS_CONFIGURATION_LOCKED; |
532 | if (c->state & CONFIG_LOCKED) | 531 | if (c->irq.Attributes != req->Attributes) |
533 | return CS_CONFIGURATION_LOCKED; | 532 | return CS_BAD_ATTRIBUTE; |
534 | if (c->irq.Attributes != req->Attributes) | 533 | if (s->irq.AssignedIRQ != req->AssignedIRQ) |
535 | return CS_BAD_ATTRIBUTE; | 534 | return CS_BAD_IRQ; |
536 | if (s->irq.AssignedIRQ != req->AssignedIRQ) | 535 | if (--s->irq.Config == 0) { |
537 | return CS_BAD_IRQ; | 536 | c->state &= ~CONFIG_IRQ_REQ; |
538 | if (--s->irq.Config == 0) { | 537 | s->irq.AssignedIRQ = 0; |
539 | c->state &= ~CONFIG_IRQ_REQ; | ||
540 | s->irq.AssignedIRQ = 0; | ||
541 | } | ||
542 | } | 538 | } |
543 | 539 | ||
544 | if (req->Attributes & IRQ_HANDLE_PRESENT) { | 540 | if (req->Attributes & IRQ_HANDLE_PRESENT) { |
@@ -929,3 +925,18 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h | |||
929 | return CS_SUCCESS; | 925 | return CS_SUCCESS; |
930 | } /* pcmcia_request_window */ | 926 | } /* pcmcia_request_window */ |
931 | EXPORT_SYMBOL(pcmcia_request_window); | 927 | EXPORT_SYMBOL(pcmcia_request_window); |
928 | |||
929 | void pcmcia_disable_device(struct pcmcia_device *p_dev) { | ||
930 | if (!p_dev->instance) | ||
931 | return; | ||
932 | |||
933 | pcmcia_release_configuration(p_dev); | ||
934 | pcmcia_release_io(p_dev, &p_dev->instance->io); | ||
935 | pcmcia_release_irq(p_dev, &p_dev->instance->irq); | ||
936 | if (&p_dev->instance->win) | ||
937 | pcmcia_release_window(p_dev->instance->win); | ||
938 | |||
939 | p_dev->instance->dev = NULL; | ||
940 | p_dev->instance->state &= ~DEV_CONFIG; | ||
941 | } | ||
942 | EXPORT_SYMBOL(pcmcia_disable_device); | ||