aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-17 13:30:53 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-02-17 11:48:26 -0500
commitaf461fc1875b6ec18e23b5f670af36c4ed35c84e (patch)
treefa09a446c94d533c169b9e28e97c0e8c03d36912
parentf971dbd5da4e2fbf756d07b938a9c65a9c75178b (diff)
pcmcia: delay re-scanning and re-querying of PCMCIA bus
After a CIS update -- or the finalization of the resource database --, proceed with the re-scanning or re-querying of PCMCIA cards only in a separate thread to avoid deadlocks. Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--drivers/pcmcia/cistpl.c10
-rw-r--r--drivers/pcmcia/cs.c8
-rw-r--r--drivers/pcmcia/cs_internal.h3
-rw-r--r--drivers/pcmcia/ds.c80
-rw-r--r--drivers/pcmcia/socket_sysfs.c11
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 */
788void pcmcia_parse_uevents(struct pcmcia_socket *s, u_int events) 794void 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
133struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt); 134struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt);
134void pcmcia_put_socket(struct pcmcia_socket *skt); 135void 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
663static int pcmcia_requery(struct device *dev, void * _data) 671static 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
674static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis) 682static 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);
1359static struct pcmcia_callback pcmcia_bus_callback = { 1375static 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}