diff options
Diffstat (limited to 'drivers/pcmcia/ds.c')
-rw-r--r-- | drivers/pcmcia/ds.c | 54 |
1 files changed, 18 insertions, 36 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4014cf8e4a2..508f94a2a78 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -335,7 +335,6 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le | |||
335 | 335 | ||
336 | mutex_lock(&s->ops_mutex); | 336 | mutex_lock(&s->ops_mutex); |
337 | list_del(&p_dev->socket_device_list); | 337 | list_del(&p_dev->socket_device_list); |
338 | p_dev->_removed = 1; | ||
339 | mutex_unlock(&s->ops_mutex); | 338 | mutex_unlock(&s->ops_mutex); |
340 | 339 | ||
341 | dev_dbg(&p_dev->dev, "unregistering device\n"); | 340 | dev_dbg(&p_dev->dev, "unregistering device\n"); |
@@ -654,14 +653,7 @@ static int pcmcia_requery_callback(struct device *dev, void * _data) | |||
654 | 653 | ||
655 | static void pcmcia_requery(struct pcmcia_socket *s) | 654 | static void pcmcia_requery(struct pcmcia_socket *s) |
656 | { | 655 | { |
657 | int present, has_pfc; | 656 | int has_pfc; |
658 | |||
659 | mutex_lock(&s->ops_mutex); | ||
660 | present = s->pcmcia_state.present; | ||
661 | mutex_unlock(&s->ops_mutex); | ||
662 | |||
663 | if (!present) | ||
664 | return; | ||
665 | 657 | ||
666 | if (s->functions == 0) { | 658 | if (s->functions == 0) { |
667 | pcmcia_card_add(s); | 659 | pcmcia_card_add(s); |
@@ -828,11 +820,12 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
828 | } | 820 | } |
829 | 821 | ||
830 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { | 822 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { |
831 | if (dev->device_no != did->device_no) | 823 | dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n"); |
832 | return 0; | ||
833 | mutex_lock(&dev->socket->ops_mutex); | 824 | mutex_lock(&dev->socket->ops_mutex); |
834 | dev->socket->pcmcia_state.has_pfc = 1; | 825 | dev->socket->pcmcia_state.has_pfc = 1; |
835 | mutex_unlock(&dev->socket->ops_mutex); | 826 | mutex_unlock(&dev->socket->ops_mutex); |
827 | if (dev->device_no != did->device_no) | ||
828 | return 0; | ||
836 | } | 829 | } |
837 | 830 | ||
838 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { | 831 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { |
@@ -843,7 +836,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
843 | 836 | ||
844 | /* if this is a pseudo-multi-function device, | 837 | /* if this is a pseudo-multi-function device, |
845 | * we need explicit matches */ | 838 | * we need explicit matches */ |
846 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) | 839 | if (dev->socket->pcmcia_state.has_pfc) |
847 | return 0; | 840 | return 0; |
848 | if (dev->device_no) | 841 | if (dev->device_no) |
849 | return 0; | 842 | return 0; |
@@ -1260,9 +1253,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1260 | 1253 | ||
1261 | switch (event) { | 1254 | switch (event) { |
1262 | case CS_EVENT_CARD_REMOVAL: | 1255 | case CS_EVENT_CARD_REMOVAL: |
1263 | mutex_lock(&s->ops_mutex); | 1256 | atomic_set(&skt->present, 0); |
1264 | s->pcmcia_state.present = 0; | ||
1265 | mutex_unlock(&s->ops_mutex); | ||
1266 | pcmcia_card_remove(skt, NULL); | 1257 | pcmcia_card_remove(skt, NULL); |
1267 | handle_event(skt, event); | 1258 | handle_event(skt, event); |
1268 | mutex_lock(&s->ops_mutex); | 1259 | mutex_lock(&s->ops_mutex); |
@@ -1271,9 +1262,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1271 | break; | 1262 | break; |
1272 | 1263 | ||
1273 | case CS_EVENT_CARD_INSERTION: | 1264 | case CS_EVENT_CARD_INSERTION: |
1265 | atomic_set(&skt->present, 1); | ||
1274 | mutex_lock(&s->ops_mutex); | 1266 | mutex_lock(&s->ops_mutex); |
1275 | s->pcmcia_state.has_pfc = 0; | 1267 | s->pcmcia_state.has_pfc = 0; |
1276 | s->pcmcia_state.present = 1; | ||
1277 | destroy_cis_cache(s); /* to be on the safe side... */ | 1268 | destroy_cis_cache(s); /* to be on the safe side... */ |
1278 | mutex_unlock(&s->ops_mutex); | 1269 | mutex_unlock(&s->ops_mutex); |
1279 | pcmcia_card_add(skt); | 1270 | pcmcia_card_add(skt); |
@@ -1313,7 +1304,13 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1313 | return 0; | 1304 | return 0; |
1314 | } /* ds_event */ | 1305 | } /* ds_event */ |
1315 | 1306 | ||
1316 | 1307 | /* | |
1308 | * NOTE: This is racy. There's no guarantee the card will still be | ||
1309 | * physically present, even if the call to this function returns | ||
1310 | * non-NULL. Furthermore, the device driver most likely is unbound | ||
1311 | * almost immediately, so the timeframe where pcmcia_dev_present | ||
1312 | * returns NULL is probably really really small. | ||
1313 | */ | ||
1317 | struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) | 1314 | struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) |
1318 | { | 1315 | { |
1319 | struct pcmcia_device *p_dev; | 1316 | struct pcmcia_device *p_dev; |
@@ -1323,22 +1320,9 @@ struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) | |||
1323 | if (!p_dev) | 1320 | if (!p_dev) |
1324 | return NULL; | 1321 | return NULL; |
1325 | 1322 | ||
1326 | mutex_lock(&p_dev->socket->ops_mutex); | 1323 | if (atomic_read(&p_dev->socket->present) != 0) |
1327 | if (!p_dev->socket->pcmcia_state.present) | 1324 | ret = p_dev; |
1328 | goto out; | ||
1329 | |||
1330 | if (p_dev->socket->pcmcia_state.dead) | ||
1331 | goto out; | ||
1332 | 1325 | ||
1333 | if (p_dev->_removed) | ||
1334 | goto out; | ||
1335 | |||
1336 | if (p_dev->suspended) | ||
1337 | goto out; | ||
1338 | |||
1339 | ret = p_dev; | ||
1340 | out: | ||
1341 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
1342 | pcmcia_put_dev(p_dev); | 1326 | pcmcia_put_dev(p_dev); |
1343 | return ret; | 1327 | return ret; |
1344 | } | 1328 | } |
@@ -1388,6 +1372,8 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, | |||
1388 | return ret; | 1372 | return ret; |
1389 | } | 1373 | } |
1390 | 1374 | ||
1375 | atomic_set(&socket->present, 0); | ||
1376 | |||
1391 | return 0; | 1377 | return 0; |
1392 | } | 1378 | } |
1393 | 1379 | ||
@@ -1399,10 +1385,6 @@ static void pcmcia_bus_remove_socket(struct device *dev, | |||
1399 | if (!socket) | 1385 | if (!socket) |
1400 | return; | 1386 | return; |
1401 | 1387 | ||
1402 | mutex_lock(&socket->ops_mutex); | ||
1403 | socket->pcmcia_state.dead = 1; | ||
1404 | mutex_unlock(&socket->ops_mutex); | ||
1405 | |||
1406 | pccard_register_pcmcia(socket, NULL); | 1388 | pccard_register_pcmcia(socket, NULL); |
1407 | 1389 | ||
1408 | /* unregister any unbound devices */ | 1390 | /* unregister any unbound devices */ |