diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-01-16 02:32:56 -0500 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-02-17 11:48:19 -0500 |
commit | 3d3de32fad19e37695e6649136e4cb17f9d46329 (patch) | |
tree | 3ffb845c1296737ad4740143e46b47092daa07c8 /drivers/pcmcia | |
parent | e6e4f397e5d0970ee1bb7a5591ac93b37cfa524a (diff) |
pcmcia: add locking to struct pcmcia_socket->pcmcia_state()
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/ds.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index bcb9ef103427..0eb242cbed17 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -649,10 +649,17 @@ static void pcmcia_delayed_add_device(struct work_struct *work) | |||
649 | { | 649 | { |
650 | struct pcmcia_socket *s = | 650 | struct pcmcia_socket *s = |
651 | container_of(work, struct pcmcia_socket, device_add); | 651 | container_of(work, struct pcmcia_socket, device_add); |
652 | dev_dbg(&s->dev, "adding additional device to %d\n", s->sock); | 652 | u8 mfc_pfc; |
653 | pcmcia_device_add(s, s->pcmcia_state.mfc_pfc); | 653 | unsigned long flags; |
654 | |||
655 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
656 | mfc_pfc = s->pcmcia_state.mfc_pfc; | ||
654 | s->pcmcia_state.device_add_pending = 0; | 657 | s->pcmcia_state.device_add_pending = 0; |
655 | s->pcmcia_state.mfc_pfc = 0; | 658 | s->pcmcia_state.mfc_pfc = 0; |
659 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
660 | |||
661 | dev_dbg(&s->dev, "adding additional device to %d\n", s->sock); | ||
662 | pcmcia_device_add(s, mfc_pfc); | ||
656 | } | 663 | } |
657 | 664 | ||
658 | static int pcmcia_requery(struct device *dev, void * _data) | 665 | static int pcmcia_requery(struct device *dev, void * _data) |
@@ -761,8 +768,13 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | |||
761 | 768 | ||
762 | if (old_funcs > no_funcs) | 769 | if (old_funcs > no_funcs) |
763 | pcmcia_card_remove(s, dev); | 770 | pcmcia_card_remove(s, dev); |
764 | else if (no_funcs > old_funcs) | 771 | else if (no_funcs > old_funcs) { |
772 | unsigned long flags; | ||
773 | |||
774 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
765 | pcmcia_add_device_later(s, 1); | 775 | pcmcia_add_device_later(s, 1); |
776 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
777 | } | ||
766 | } | 778 | } |
767 | release: | 779 | release: |
768 | release_firmware(fw); | 780 | release_firmware(fw); |
@@ -1236,6 +1248,7 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt) | |||
1236 | static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | 1248 | static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) |
1237 | { | 1249 | { |
1238 | struct pcmcia_socket *s = pcmcia_get_socket(skt); | 1250 | struct pcmcia_socket *s = pcmcia_get_socket(skt); |
1251 | unsigned long flags; | ||
1239 | 1252 | ||
1240 | if (!s) { | 1253 | if (!s) { |
1241 | dev_printk(KERN_ERR, &skt->dev, | 1254 | dev_printk(KERN_ERR, &skt->dev, |
@@ -1249,7 +1262,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1249 | 1262 | ||
1250 | switch (event) { | 1263 | switch (event) { |
1251 | case CS_EVENT_CARD_REMOVAL: | 1264 | case CS_EVENT_CARD_REMOVAL: |
1265 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
1252 | s->pcmcia_state.present = 0; | 1266 | s->pcmcia_state.present = 0; |
1267 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
1253 | pcmcia_card_remove(skt, NULL); | 1268 | pcmcia_card_remove(skt, NULL); |
1254 | handle_event(skt, event); | 1269 | handle_event(skt, event); |
1255 | mutex_lock(&s->ops_mutex); | 1270 | mutex_lock(&s->ops_mutex); |
@@ -1258,7 +1273,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1258 | break; | 1273 | break; |
1259 | 1274 | ||
1260 | case CS_EVENT_CARD_INSERTION: | 1275 | case CS_EVENT_CARD_INSERTION: |
1276 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
1261 | s->pcmcia_state.present = 1; | 1277 | s->pcmcia_state.present = 1; |
1278 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
1262 | mutex_lock(&s->ops_mutex); | 1279 | mutex_lock(&s->ops_mutex); |
1263 | destroy_cis_cache(s); /* to be on the safe side... */ | 1280 | destroy_cis_cache(s); /* to be on the safe side... */ |
1264 | mutex_unlock(&s->ops_mutex); | 1281 | mutex_unlock(&s->ops_mutex); |
@@ -1304,14 +1321,19 @@ struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) | |||
1304 | { | 1321 | { |
1305 | struct pcmcia_device *p_dev; | 1322 | struct pcmcia_device *p_dev; |
1306 | struct pcmcia_device *ret = NULL; | 1323 | struct pcmcia_device *ret = NULL; |
1324 | unsigned long flags; | ||
1307 | 1325 | ||
1308 | p_dev = pcmcia_get_dev(_p_dev); | 1326 | p_dev = pcmcia_get_dev(_p_dev); |
1309 | if (!p_dev) | 1327 | if (!p_dev) |
1310 | return NULL; | 1328 | return NULL; |
1311 | 1329 | ||
1330 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
1312 | if (!p_dev->socket->pcmcia_state.present) | 1331 | if (!p_dev->socket->pcmcia_state.present) |
1313 | goto out; | 1332 | goto out; |
1314 | 1333 | ||
1334 | if (p_dev->socket->pcmcia_state.dead) | ||
1335 | goto out; | ||
1336 | |||
1315 | if (p_dev->_removed) | 1337 | if (p_dev->_removed) |
1316 | goto out; | 1338 | goto out; |
1317 | 1339 | ||
@@ -1320,6 +1342,7 @@ struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) | |||
1320 | 1342 | ||
1321 | ret = p_dev; | 1343 | ret = p_dev; |
1322 | out: | 1344 | out: |
1345 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
1323 | pcmcia_put_dev(p_dev); | 1346 | pcmcia_put_dev(p_dev); |
1324 | return ret; | 1347 | return ret; |
1325 | } | 1348 | } |
@@ -1383,11 +1406,15 @@ static void pcmcia_bus_remove_socket(struct device *dev, | |||
1383 | struct class_interface *class_intf) | 1406 | struct class_interface *class_intf) |
1384 | { | 1407 | { |
1385 | struct pcmcia_socket *socket = dev_get_drvdata(dev); | 1408 | struct pcmcia_socket *socket = dev_get_drvdata(dev); |
1409 | unsigned long flags; | ||
1386 | 1410 | ||
1387 | if (!socket) | 1411 | if (!socket) |
1388 | return; | 1412 | return; |
1389 | 1413 | ||
1414 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
1390 | socket->pcmcia_state.dead = 1; | 1415 | socket->pcmcia_state.dead = 1; |
1416 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
1417 | |||
1391 | pccard_register_pcmcia(socket, NULL); | 1418 | pccard_register_pcmcia(socket, NULL); |
1392 | 1419 | ||
1393 | /* unregister any unbound devices */ | 1420 | /* unregister any unbound devices */ |