diff options
| -rw-r--r-- | drivers/pcmcia/cistpl.c | 10 | ||||
| -rw-r--r-- | drivers/pcmcia/cs.c | 8 | ||||
| -rw-r--r-- | drivers/pcmcia/cs_internal.h | 3 | ||||
| -rw-r--r-- | drivers/pcmcia/ds.c | 80 | ||||
| -rw-r--r-- | drivers/pcmcia/socket_sysfs.c | 11 |
5 files changed, 59 insertions, 53 deletions
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 14de287a8bf6..17a5da32cce1 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
| @@ -1670,15 +1670,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, | |||
| 1670 | if (error) | 1670 | if (error) |
| 1671 | return -EIO; | 1671 | return -EIO; |
| 1672 | 1672 | ||
| 1673 | mutex_lock(&s->skt_mutex); | 1673 | pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY); |
| 1674 | if ((s->callback) && (s->state & SOCKET_PRESENT) && | ||
| 1675 | !(s->state & SOCKET_CARDBUS)) { | ||
| 1676 | if (try_module_get(s->callback->owner)) { | ||
| 1677 | s->callback->requery(s, 1); | ||
| 1678 | module_put(s->callback->owner); | ||
| 1679 | } | ||
| 1680 | } | ||
| 1681 | mutex_unlock(&s->skt_mutex); | ||
| 1682 | 1674 | ||
| 1683 | return count; | 1675 | return count; |
| 1684 | } | 1676 | } |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 823ecda32216..d529e02c2d54 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
| @@ -728,6 +728,11 @@ static int pccardd(void *__skt) | |||
| 728 | if (!ret) | 728 | if (!ret) |
| 729 | socket_suspend(skt); | 729 | socket_suspend(skt); |
| 730 | } | 730 | } |
| 731 | if ((sysfs_events & PCMCIA_UEVENT_REQUERY) && | ||
| 732 | !(skt->state & SOCKET_CARDBUS)) { | ||
| 733 | if (!ret && skt->callback) | ||
| 734 | skt->callback->requery(skt); | ||
| 735 | } | ||
| 731 | } | 736 | } |
| 732 | mutex_unlock(&skt->skt_mutex); | 737 | mutex_unlock(&skt->skt_mutex); |
| 733 | 738 | ||
| @@ -783,7 +788,8 @@ EXPORT_SYMBOL(pcmcia_parse_events); | |||
| 783 | * userspace-issued insert, eject, suspend and resume commands must be | 788 | * userspace-issued insert, eject, suspend and resume commands must be |
| 784 | * handled by pccardd to avoid any sysfs-related deadlocks. Valid events | 789 | * handled by pccardd to avoid any sysfs-related deadlocks. Valid events |
| 785 | * are PCMCIA_UEVENT_EJECT (for eject), PCMCIA_UEVENT__INSERT (for insert), | 790 | * are PCMCIA_UEVENT_EJECT (for eject), PCMCIA_UEVENT__INSERT (for insert), |
| 786 | * PCMCIA_UEVENT_RESUME (for resume) and PCMCIA_UEVENT_SUSPEND (for suspend). | 791 | * PCMCIA_UEVENT_RESUME (for resume), PCMCIA_UEVENT_SUSPEND (for suspend) |
| 792 | * and PCMCIA_UEVENT_REQUERY (for re-querying the PCMCIA card). | ||
| 787 | */ | 793 | */ |
| 788 | void pcmcia_parse_uevents(struct pcmcia_socket *s, u_int events) | 794 | void pcmcia_parse_uevents(struct pcmcia_socket *s, u_int events) |
| 789 | { | 795 | { |
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 127c97acf849..f95864c2191e 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
| @@ -110,7 +110,7 @@ struct pcmcia_callback{ | |||
| 110 | struct module *owner; | 110 | struct module *owner; |
| 111 | int (*event) (struct pcmcia_socket *s, | 111 | int (*event) (struct pcmcia_socket *s, |
| 112 | event_t event, int priority); | 112 | event_t event, int priority); |
| 113 | void (*requery) (struct pcmcia_socket *s, int new_cis); | 113 | void (*requery) (struct pcmcia_socket *s); |
| 114 | int (*validate) (struct pcmcia_socket *s, unsigned int *i); | 114 | int (*validate) (struct pcmcia_socket *s, unsigned int *i); |
| 115 | int (*suspend) (struct pcmcia_socket *s); | 115 | int (*suspend) (struct pcmcia_socket *s); |
| 116 | int (*resume) (struct pcmcia_socket *s); | 116 | int (*resume) (struct pcmcia_socket *s); |
| @@ -129,6 +129,7 @@ void pcmcia_parse_uevents(struct pcmcia_socket *socket, unsigned int events); | |||
| 129 | #define PCMCIA_UEVENT_INSERT 0x0002 | 129 | #define PCMCIA_UEVENT_INSERT 0x0002 |
| 130 | #define PCMCIA_UEVENT_SUSPEND 0x0004 | 130 | #define PCMCIA_UEVENT_SUSPEND 0x0004 |
| 131 | #define PCMCIA_UEVENT_RESUME 0x0008 | 131 | #define PCMCIA_UEVENT_RESUME 0x0008 |
| 132 | #define PCMCIA_UEVENT_REQUERY 0x0010 | ||
| 132 | 133 | ||
| 133 | struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt); | 134 | struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt); |
| 134 | void pcmcia_put_socket(struct pcmcia_socket *skt); | 135 | void pcmcia_put_socket(struct pcmcia_socket *skt); |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 76a21638291b..5400e20c664e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -432,16 +432,20 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
| 432 | 432 | ||
| 433 | if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, | 433 | if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, |
| 434 | CISTPL_MANFID, &manf_id)) { | 434 | CISTPL_MANFID, &manf_id)) { |
| 435 | mutex_lock(&p_dev->socket->ops_mutex); | ||
| 435 | p_dev->manf_id = manf_id.manf; | 436 | p_dev->manf_id = manf_id.manf; |
| 436 | p_dev->card_id = manf_id.card; | 437 | p_dev->card_id = manf_id.card; |
| 437 | p_dev->has_manf_id = 1; | 438 | p_dev->has_manf_id = 1; |
| 438 | p_dev->has_card_id = 1; | 439 | p_dev->has_card_id = 1; |
| 440 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 439 | } | 441 | } |
| 440 | 442 | ||
| 441 | if (!pccard_read_tuple(p_dev->socket, p_dev->func, | 443 | if (!pccard_read_tuple(p_dev->socket, p_dev->func, |
| 442 | CISTPL_FUNCID, &func_id)) { | 444 | CISTPL_FUNCID, &func_id)) { |
| 445 | mutex_lock(&p_dev->socket->ops_mutex); | ||
| 443 | p_dev->func_id = func_id.func; | 446 | p_dev->func_id = func_id.func; |
| 444 | p_dev->has_func_id = 1; | 447 | p_dev->has_func_id = 1; |
| 448 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 445 | } else { | 449 | } else { |
| 446 | /* rule of thumb: cards with no FUNCID, but with | 450 | /* rule of thumb: cards with no FUNCID, but with |
| 447 | * common memory device geometry information, are | 451 | * common memory device geometry information, are |
| @@ -458,14 +462,17 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
| 458 | dev_dbg(&p_dev->dev, | 462 | dev_dbg(&p_dev->dev, |
| 459 | "mem device geometry probably means " | 463 | "mem device geometry probably means " |
| 460 | "FUNCID_MEMORY\n"); | 464 | "FUNCID_MEMORY\n"); |
| 465 | mutex_lock(&p_dev->socket->ops_mutex); | ||
| 461 | p_dev->func_id = CISTPL_FUNCID_MEMORY; | 466 | p_dev->func_id = CISTPL_FUNCID_MEMORY; |
| 462 | p_dev->has_func_id = 1; | 467 | p_dev->has_func_id = 1; |
| 468 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 463 | } | 469 | } |
| 464 | kfree(devgeo); | 470 | kfree(devgeo); |
| 465 | } | 471 | } |
| 466 | 472 | ||
| 467 | if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1, | 473 | if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1, |
| 468 | vers1)) { | 474 | vers1)) { |
| 475 | mutex_lock(&p_dev->socket->ops_mutex); | ||
| 469 | for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) { | 476 | for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) { |
| 470 | char *tmp; | 477 | char *tmp; |
| 471 | unsigned int length; | 478 | unsigned int length; |
| @@ -484,6 +491,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
| 484 | p_dev->prod_id[i] = strncpy(p_dev->prod_id[i], | 491 | p_dev->prod_id[i] = strncpy(p_dev->prod_id[i], |
| 485 | tmp, length); | 492 | tmp, length); |
| 486 | } | 493 | } |
| 494 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
| 487 | } | 495 | } |
| 488 | 496 | ||
| 489 | kfree(vers1); | 497 | kfree(vers1); |
| @@ -660,7 +668,7 @@ static void pcmcia_delayed_add_device(struct work_struct *work) | |||
| 660 | pcmcia_device_add(s, mfc_pfc); | 668 | pcmcia_device_add(s, mfc_pfc); |
| 661 | } | 669 | } |
| 662 | 670 | ||
| 663 | static int pcmcia_requery(struct device *dev, void * _data) | 671 | static int pcmcia_requery_callback(struct device *dev, void * _data) |
| 664 | { | 672 | { |
| 665 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 673 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
| 666 | if (!p_dev->dev.driver) { | 674 | if (!p_dev->dev.driver) { |
| @@ -671,44 +679,57 @@ static int pcmcia_requery(struct device *dev, void * _data) | |||
| 671 | return 0; | 679 | return 0; |
| 672 | } | 680 | } |
| 673 | 681 | ||
| 674 | static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis) | 682 | static void pcmcia_requery(struct pcmcia_socket *s) |
| 675 | { | 683 | { |
| 676 | int no_devices = 0; | 684 | int present; |
| 677 | int ret = 0; | ||
| 678 | |||
| 679 | /* must be called with skt_mutex held */ | ||
| 680 | dev_dbg(&skt->dev, "re-scanning socket %d\n", skt->sock); | ||
| 681 | 685 | ||
| 682 | mutex_lock(&skt->ops_mutex); | 686 | mutex_lock(&s->ops_mutex); |
| 683 | if (list_empty(&skt->devices_list)) | 687 | present = s->pcmcia_state.present; |
| 684 | no_devices = 1; | 688 | mutex_unlock(&s->ops_mutex); |
| 685 | mutex_unlock(&skt->ops_mutex); | ||
| 686 | 689 | ||
| 687 | /* If this is because of a CIS override, start over */ | 690 | if (!present) |
| 688 | if (new_cis && !no_devices) | 691 | return; |
| 689 | pcmcia_card_remove(skt, NULL); | ||
| 690 | 692 | ||
| 691 | /* if no devices were added for this socket yet because of | 693 | if (s->functions == 0) { |
| 692 | * missing resource information or other trouble, we need to | 694 | pcmcia_card_add(s); |
| 693 | * do this now. */ | 695 | return; |
| 694 | if (no_devices || new_cis) { | ||
| 695 | ret = pcmcia_card_add(skt); | ||
| 696 | if (ret) | ||
| 697 | return; | ||
| 698 | } | 696 | } |
| 699 | 697 | ||
| 700 | /* some device information might have changed because of a CIS | 698 | /* some device information might have changed because of a CIS |
| 701 | * update or because we can finally read it correctly... so | 699 | * update or because we can finally read it correctly... so |
| 702 | * determine it again, overwriting old values if necessary. */ | 700 | * determine it again, overwriting old values if necessary. */ |
| 703 | bus_for_each_dev(&pcmcia_bus_type, NULL, NULL, pcmcia_requery); | 701 | bus_for_each_dev(&pcmcia_bus_type, NULL, NULL, pcmcia_requery_callback); |
| 702 | |||
| 703 | /* if the CIS changed, we need to check whether the number of | ||
| 704 | * functions changed. */ | ||
| 705 | if (s->fake_cis) { | ||
| 706 | int old_funcs, new_funcs; | ||
| 707 | cistpl_longlink_mfc_t mfc; | ||
| 708 | |||
| 709 | /* does this cis override add or remove functions? */ | ||
| 710 | old_funcs = s->functions; | ||
| 711 | |||
| 712 | if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, | ||
| 713 | &mfc)) | ||
| 714 | new_funcs = mfc.nfn; | ||
| 715 | else | ||
| 716 | new_funcs = 1; | ||
| 717 | if (old_funcs > new_funcs) { | ||
| 718 | pcmcia_card_remove(s, NULL); | ||
| 719 | pcmcia_card_add(s); | ||
| 720 | } else if (new_funcs > old_funcs) { | ||
| 721 | s->functions = new_funcs; | ||
| 722 | pcmcia_device_add(s, 1); | ||
| 723 | } | ||
| 724 | } | ||
| 704 | 725 | ||
| 705 | /* we re-scan all devices, not just the ones connected to this | 726 | /* we re-scan all devices, not just the ones connected to this |
| 706 | * socket. This does not matter, though. */ | 727 | * socket. This does not matter, though. */ |
| 707 | ret = bus_rescan_devices(&pcmcia_bus_type); | 728 | if (bus_rescan_devices(&pcmcia_bus_type)) |
| 708 | if (ret) | 729 | dev_warn(&s->dev, "rescanning the bus failed\n"); |
| 709 | printk(KERN_INFO "pcmcia: bus_rescan_devices failed\n"); | ||
| 710 | } | 730 | } |
| 711 | 731 | ||
| 732 | |||
| 712 | #ifdef CONFIG_PCMCIA_LOAD_CIS | 733 | #ifdef CONFIG_PCMCIA_LOAD_CIS |
| 713 | 734 | ||
| 714 | /** | 735 | /** |
| @@ -1085,7 +1106,6 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | |||
| 1085 | struct device_attribute *attr, const char *buf, size_t count) | 1106 | struct device_attribute *attr, const char *buf, size_t count) |
| 1086 | { | 1107 | { |
| 1087 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 1108 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
| 1088 | int ret; | ||
| 1089 | 1109 | ||
| 1090 | if (!count) | 1110 | if (!count) |
| 1091 | return -EINVAL; | 1111 | return -EINVAL; |
| @@ -1093,11 +1113,7 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | |||
| 1093 | mutex_lock(&p_dev->socket->ops_mutex); | 1113 | mutex_lock(&p_dev->socket->ops_mutex); |
| 1094 | p_dev->allow_func_id_match = 1; | 1114 | p_dev->allow_func_id_match = 1; |
| 1095 | mutex_unlock(&p_dev->socket->ops_mutex); | 1115 | mutex_unlock(&p_dev->socket->ops_mutex); |
| 1096 | 1116 | pcmcia_parse_uevents(p_dev->socket, PCMCIA_UEVENT_REQUERY); | |
| 1097 | ret = bus_rescan_devices(&pcmcia_bus_type); | ||
| 1098 | if (ret) | ||
| 1099 | printk(KERN_INFO "pcmcia: bus_rescan_devices failed after " | ||
| 1100 | "allowing func_id matches\n"); | ||
| 1101 | 1117 | ||
| 1102 | return count; | 1118 | return count; |
| 1103 | } | 1119 | } |
| @@ -1359,7 +1375,7 @@ EXPORT_SYMBOL(pcmcia_dev_present); | |||
| 1359 | static struct pcmcia_callback pcmcia_bus_callback = { | 1375 | static struct pcmcia_callback pcmcia_bus_callback = { |
| 1360 | .owner = THIS_MODULE, | 1376 | .owner = THIS_MODULE, |
| 1361 | .event = ds_event, | 1377 | .event = ds_event, |
| 1362 | .requery = pcmcia_bus_rescan, | 1378 | .requery = pcmcia_requery, |
| 1363 | .validate = pccard_validate_cis, | 1379 | .validate = pccard_validate_cis, |
| 1364 | .suspend = pcmcia_bus_suspend, | 1380 | .suspend = pcmcia_bus_suspend, |
| 1365 | .resume = pcmcia_bus_resume, | 1381 | .resume = pcmcia_bus_resume, |
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index fba0e30183f4..08278016e58d 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
| @@ -201,16 +201,7 @@ static ssize_t pccard_store_resource(struct device *dev, | |||
| 201 | s->resource_setup_done = 1; | 201 | s->resource_setup_done = 1; |
| 202 | mutex_unlock(&s->ops_mutex); | 202 | mutex_unlock(&s->ops_mutex); |
| 203 | 203 | ||
| 204 | mutex_lock(&s->skt_mutex); | 204 | pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY); |
| 205 | if ((s->callback) && | ||
| 206 | (s->state & SOCKET_PRESENT) && | ||
| 207 | !(s->state & SOCKET_CARDBUS)) { | ||
| 208 | if (try_module_get(s->callback->owner)) { | ||
| 209 | s->callback->requery(s, 0); | ||
| 210 | module_put(s->callback->owner); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | mutex_unlock(&s->skt_mutex); | ||
| 214 | 205 | ||
| 215 | return count; | 206 | return count; |
| 216 | } | 207 | } |
