diff options
| author | Dominik Brodowski <linux@dominikbrodowski.net> | 2006-01-27 13:15:02 -0500 |
|---|---|---|
| committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2006-03-01 04:52:11 -0500 |
| commit | 82d56e6d2e616bee0e712330bad06b634f007a46 (patch) | |
| tree | e18a81cbe959428aa75e1d99e0760ce827d2c366 | |
| parent | 96789ac4b3943fec27fb6bf2713633b01a3903ad (diff) | |
[PATCH] pcmcia: properly handle pseudo multi-function devices
The second pseudo multi-function device of a PCMCIA card may only be
configured once the first one is initialized. Therefore, delay the
registration of the second device until the first one is initialized.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net
| -rw-r--r-- | drivers/pcmcia/ds.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 0a424a4e8187..54ad93daca3c 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -352,11 +352,20 @@ static void pcmcia_release_dev(struct device *dev) | |||
| 352 | kfree(p_dev); | 352 | kfree(p_dev); |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | static void pcmcia_add_pseudo_device(struct pcmcia_socket *s) | ||
| 356 | { | ||
| 357 | if (!s->pcmcia_state.device_add_pending) { | ||
| 358 | s->pcmcia_state.device_add_pending = 1; | ||
| 359 | schedule_work(&s->device_add); | ||
| 360 | } | ||
| 361 | return; | ||
| 362 | } | ||
| 355 | 363 | ||
| 356 | static int pcmcia_device_probe(struct device * dev) | 364 | static int pcmcia_device_probe(struct device * dev) |
| 357 | { | 365 | { |
| 358 | struct pcmcia_device *p_dev; | 366 | struct pcmcia_device *p_dev; |
| 359 | struct pcmcia_driver *p_drv; | 367 | struct pcmcia_driver *p_drv; |
| 368 | struct pcmcia_device_id *did; | ||
| 360 | struct pcmcia_socket *s; | 369 | struct pcmcia_socket *s; |
| 361 | int ret = 0; | 370 | int ret = 0; |
| 362 | 371 | ||
| @@ -392,6 +401,19 @@ static int pcmcia_device_probe(struct device * dev) | |||
| 392 | } | 401 | } |
| 393 | 402 | ||
| 394 | ret = p_drv->probe(p_dev); | 403 | ret = p_drv->probe(p_dev); |
| 404 | if (ret) | ||
| 405 | goto put_module; | ||
| 406 | |||
| 407 | /* handle pseudo multifunction devices: | ||
| 408 | * there are at most two pseudo multifunction devices. | ||
| 409 | * if we're matching against the first, schedule a | ||
| 410 | * call which will then check whether there are two | ||
| 411 | * pseudo devices, and if not, add the second one. | ||
| 412 | */ | ||
| 413 | did = (struct pcmcia_device_id *) p_dev->dev.driver_data; | ||
| 414 | if ((did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && | ||
| 415 | (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) | ||
| 416 | pcmcia_add_pseudo_device(p_dev->socket); | ||
| 395 | 417 | ||
| 396 | put_module: | 418 | put_module: |
| 397 | if (ret) | 419 | if (ret) |
| @@ -660,15 +682,6 @@ static void pcmcia_delayed_add_pseudo_device(void *data) | |||
| 660 | s->pcmcia_state.device_add_pending = 0; | 682 | s->pcmcia_state.device_add_pending = 0; |
| 661 | } | 683 | } |
| 662 | 684 | ||
| 663 | static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) | ||
| 664 | { | ||
| 665 | if (!s->pcmcia_state.device_add_pending) { | ||
| 666 | s->pcmcia_state.device_add_pending = 1; | ||
| 667 | schedule_work(&s->device_add); | ||
| 668 | } | ||
| 669 | return; | ||
| 670 | } | ||
| 671 | |||
| 672 | static int pcmcia_requery(struct device *dev, void * _data) | 685 | static int pcmcia_requery(struct device *dev, void * _data) |
| 673 | { | 686 | { |
| 674 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 687 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
| @@ -755,15 +768,6 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
| 755 | } | 768 | } |
| 756 | 769 | ||
| 757 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { | 770 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { |
| 758 | /* handle pseudo multifunction devices: | ||
| 759 | * there are at most two pseudo multifunction devices. | ||
| 760 | * if we're matching against the first, schedule a | ||
| 761 | * call which will then check whether there are two | ||
| 762 | * pseudo devices, and if not, add the second one. | ||
| 763 | */ | ||
| 764 | if (dev->device_no == 0) | ||
| 765 | pcmcia_add_pseudo_device(dev->socket); | ||
| 766 | |||
| 767 | if (dev->device_no != did->device_no) | 771 | if (dev->device_no != did->device_no) |
| 768 | return 0; | 772 | return 0; |
| 769 | } | 773 | } |
