aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2006-01-15 03:32:39 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2006-03-31 10:15:50 -0500
commit5f2a71fcb7995633b335a1e380ac63a968e61320 (patch)
treed47f4227d314fc9f298b75c217fa78440004e6e7 /drivers/pcmcia
parent1de9cedfbdff1d8adb662cd3afc5bda66e393351 (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.c71
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);
494int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) 493int 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);
523int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) 520int 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 */
931EXPORT_SYMBOL(pcmcia_request_window); 927EXPORT_SYMBOL(pcmcia_request_window);
928
929void 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}
942EXPORT_SYMBOL(pcmcia_disable_device);