diff options
Diffstat (limited to 'drivers/pcmcia/ds.c')
-rw-r--r-- | drivers/pcmcia/ds.c | 184 |
1 files changed, 84 insertions, 100 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index eac961463be2..55570d9e1e4c 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
11 | * | 11 | * |
12 | * (C) 1999 David A. Hinds | 12 | * (C) 1999 David A. Hinds |
13 | * (C) 2003 - 2006 Dominik Brodowski | 13 | * (C) 2003 - 2010 Dominik Brodowski |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | 28 | ||
29 | #include <pcmcia/cs_types.h> | ||
30 | #include <pcmcia/cs.h> | 29 | #include <pcmcia/cs.h> |
31 | #include <pcmcia/cistpl.h> | 30 | #include <pcmcia/cistpl.h> |
32 | #include <pcmcia/ds.h> | 31 | #include <pcmcia/ds.h> |
@@ -213,7 +212,7 @@ EXPORT_SYMBOL(pcmcia_unregister_driver); | |||
213 | 212 | ||
214 | /* pcmcia_device handling */ | 213 | /* pcmcia_device handling */ |
215 | 214 | ||
216 | struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev) | 215 | static struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev) |
217 | { | 216 | { |
218 | struct device *tmp_dev; | 217 | struct device *tmp_dev; |
219 | tmp_dev = get_device(&p_dev->dev); | 218 | tmp_dev = get_device(&p_dev->dev); |
@@ -222,7 +221,7 @@ struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev) | |||
222 | return to_pcmcia_dev(tmp_dev); | 221 | return to_pcmcia_dev(tmp_dev); |
223 | } | 222 | } |
224 | 223 | ||
225 | void pcmcia_put_dev(struct pcmcia_device *p_dev) | 224 | static void pcmcia_put_dev(struct pcmcia_device *p_dev) |
226 | { | 225 | { |
227 | if (p_dev) | 226 | if (p_dev) |
228 | put_device(&p_dev->dev); | 227 | put_device(&p_dev->dev); |
@@ -294,7 +293,7 @@ static int pcmcia_device_probe(struct device *dev) | |||
294 | } | 293 | } |
295 | 294 | ||
296 | mutex_lock(&s->ops_mutex); | 295 | mutex_lock(&s->ops_mutex); |
297 | if ((s->pcmcia_state.has_pfc) && | 296 | if ((s->pcmcia_pfc) && |
298 | (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) | 297 | (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) |
299 | pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY); | 298 | pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY); |
300 | mutex_unlock(&s->ops_mutex); | 299 | mutex_unlock(&s->ops_mutex); |
@@ -359,7 +358,7 @@ static int pcmcia_device_remove(struct device *dev) | |||
359 | * pseudo multi-function card, we need to unbind | 358 | * pseudo multi-function card, we need to unbind |
360 | * all devices | 359 | * all devices |
361 | */ | 360 | */ |
362 | if ((p_dev->socket->pcmcia_state.has_pfc) && | 361 | if ((p_dev->socket->pcmcia_pfc) && |
363 | (p_dev->socket->device_count > 0) && | 362 | (p_dev->socket->device_count > 0) && |
364 | (p_dev->device_no == 0)) | 363 | (p_dev->device_no == 0)) |
365 | pcmcia_card_remove(p_dev->socket, p_dev); | 364 | pcmcia_card_remove(p_dev->socket, p_dev); |
@@ -477,7 +476,8 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
477 | } | 476 | } |
478 | 477 | ||
479 | 478 | ||
480 | struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) | 479 | static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, |
480 | unsigned int function) | ||
481 | { | 481 | { |
482 | struct pcmcia_device *p_dev, *tmp_dev; | 482 | struct pcmcia_device *p_dev, *tmp_dev; |
483 | int i; | 483 | int i; |
@@ -531,7 +531,6 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu | |||
531 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) | 531 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) |
532 | if (p_dev->func == tmp_dev->func) { | 532 | if (p_dev->func == tmp_dev->func) { |
533 | p_dev->function_config = tmp_dev->function_config; | 533 | p_dev->function_config = tmp_dev->function_config; |
534 | p_dev->io = tmp_dev->io; | ||
535 | p_dev->irq = tmp_dev->irq; | 534 | p_dev->irq = tmp_dev->irq; |
536 | kref_get(&p_dev->function_config->ref); | 535 | kref_get(&p_dev->function_config->ref); |
537 | } | 536 | } |
@@ -544,15 +543,29 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu | |||
544 | "IRQ setup failed -- device might not work\n"); | 543 | "IRQ setup failed -- device might not work\n"); |
545 | 544 | ||
546 | if (!p_dev->function_config) { | 545 | if (!p_dev->function_config) { |
546 | config_t *c; | ||
547 | dev_dbg(&p_dev->dev, "creating config_t\n"); | 547 | dev_dbg(&p_dev->dev, "creating config_t\n"); |
548 | p_dev->function_config = kzalloc(sizeof(struct config_t), | 548 | c = kzalloc(sizeof(struct config_t), GFP_KERNEL); |
549 | GFP_KERNEL); | 549 | if (!c) { |
550 | if (!p_dev->function_config) { | ||
551 | mutex_unlock(&s->ops_mutex); | 550 | mutex_unlock(&s->ops_mutex); |
552 | goto err_unreg; | 551 | goto err_unreg; |
553 | } | 552 | } |
554 | kref_init(&p_dev->function_config->ref); | 553 | p_dev->function_config = c; |
554 | kref_init(&c->ref); | ||
555 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
556 | c->io[i].name = p_dev->devname; | ||
557 | c->io[i].flags = IORESOURCE_IO; | ||
558 | } | ||
559 | for (i = 0; i< MAX_WIN; i++) { | ||
560 | c->mem[i].name = p_dev->devname; | ||
561 | c->mem[i].flags = IORESOURCE_MEM; | ||
562 | } | ||
555 | } | 563 | } |
564 | for (i = 0; i < MAX_IO_WIN; i++) | ||
565 | p_dev->resource[i] = &p_dev->function_config->io[i]; | ||
566 | for (; i < (MAX_IO_WIN + MAX_WIN); i++) | ||
567 | p_dev->resource[i] = &p_dev->function_config->mem[i-MAX_IO_WIN]; | ||
568 | |||
556 | mutex_unlock(&s->ops_mutex); | 569 | mutex_unlock(&s->ops_mutex); |
557 | 570 | ||
558 | dev_printk(KERN_NOTICE, &p_dev->dev, | 571 | dev_printk(KERN_NOTICE, &p_dev->dev, |
@@ -680,7 +693,7 @@ static void pcmcia_requery(struct pcmcia_socket *s) | |||
680 | * call pcmcia_device_add() -- which will fail if both | 693 | * call pcmcia_device_add() -- which will fail if both |
681 | * devices are already registered. */ | 694 | * devices are already registered. */ |
682 | mutex_lock(&s->ops_mutex); | 695 | mutex_lock(&s->ops_mutex); |
683 | has_pfc = s->pcmcia_state.has_pfc; | 696 | has_pfc = s->pcmcia_pfc; |
684 | mutex_unlock(&s->ops_mutex); | 697 | mutex_unlock(&s->ops_mutex); |
685 | if (has_pfc) | 698 | if (has_pfc) |
686 | pcmcia_device_add(s, 0); | 699 | pcmcia_device_add(s, 0); |
@@ -812,7 +825,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
812 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { | 825 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { |
813 | dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n"); | 826 | dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n"); |
814 | mutex_lock(&dev->socket->ops_mutex); | 827 | mutex_lock(&dev->socket->ops_mutex); |
815 | dev->socket->pcmcia_state.has_pfc = 1; | 828 | dev->socket->pcmcia_pfc = 1; |
816 | mutex_unlock(&dev->socket->ops_mutex); | 829 | mutex_unlock(&dev->socket->ops_mutex); |
817 | if (dev->device_no != did->device_no) | 830 | if (dev->device_no != did->device_no) |
818 | return 0; | 831 | return 0; |
@@ -826,7 +839,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
826 | 839 | ||
827 | /* if this is a pseudo-multi-function device, | 840 | /* if this is a pseudo-multi-function device, |
828 | * we need explicit matches */ | 841 | * we need explicit matches */ |
829 | if (dev->socket->pcmcia_state.has_pfc) | 842 | if (dev->socket->pcmcia_pfc) |
830 | return 0; | 843 | return 0; |
831 | if (dev->device_no) | 844 | if (dev->device_no) |
832 | return 0; | 845 | return 0; |
@@ -885,14 +898,6 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv) | |||
885 | } | 898 | } |
886 | mutex_unlock(&p_drv->dynids.lock); | 899 | mutex_unlock(&p_drv->dynids.lock); |
887 | 900 | ||
888 | #ifdef CONFIG_PCMCIA_IOCTL | ||
889 | /* matching by cardmgr */ | ||
890 | if (p_dev->cardmgr == p_drv) { | ||
891 | dev_dbg(dev, "cardmgr matched to %s\n", drv->name); | ||
892 | return 1; | ||
893 | } | ||
894 | #endif | ||
895 | |||
896 | while (did && did->match_flags) { | 901 | while (did && did->match_flags) { |
897 | dev_dbg(dev, "trying to match to %s\n", drv->name); | 902 | dev_dbg(dev, "trying to match to %s\n", drv->name); |
898 | if (pcmcia_devmatch(p_dev, did)) { | 903 | if (pcmcia_devmatch(p_dev, did)) { |
@@ -1006,6 +1011,18 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]); | |||
1006 | pcmcia_device_stringattr(prod_id3, prod_id[2]); | 1011 | pcmcia_device_stringattr(prod_id3, prod_id[2]); |
1007 | pcmcia_device_stringattr(prod_id4, prod_id[3]); | 1012 | pcmcia_device_stringattr(prod_id4, prod_id[3]); |
1008 | 1013 | ||
1014 | static ssize_t pcmcia_show_resources(struct device *dev, | ||
1015 | struct device_attribute *attr, char *buf) | ||
1016 | { | ||
1017 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
1018 | char *str = buf; | ||
1019 | int i; | ||
1020 | |||
1021 | for (i = 0; i < PCMCIA_NUM_RESOURCES; i++) | ||
1022 | str += sprintf(str, "%pr\n", p_dev->resource[i]); | ||
1023 | |||
1024 | return str - buf; | ||
1025 | } | ||
1009 | 1026 | ||
1010 | static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf) | 1027 | static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf) |
1011 | { | 1028 | { |
@@ -1076,6 +1093,7 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | |||
1076 | static struct device_attribute pcmcia_dev_attrs[] = { | 1093 | static struct device_attribute pcmcia_dev_attrs[] = { |
1077 | __ATTR(function, 0444, func_show, NULL), | 1094 | __ATTR(function, 0444, func_show, NULL), |
1078 | __ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state), | 1095 | __ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state), |
1096 | __ATTR(resources, 0444, pcmcia_show_resources, NULL), | ||
1079 | __ATTR_RO(func_id), | 1097 | __ATTR_RO(func_id), |
1080 | __ATTR_RO(manf_id), | 1098 | __ATTR_RO(manf_id), |
1081 | __ATTR_RO(card_id), | 1099 | __ATTR_RO(card_id), |
@@ -1215,86 +1233,57 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt) | |||
1215 | return 0; | 1233 | return 0; |
1216 | } | 1234 | } |
1217 | 1235 | ||
1236 | static int pcmcia_bus_remove(struct pcmcia_socket *skt) | ||
1237 | { | ||
1238 | atomic_set(&skt->present, 0); | ||
1239 | pcmcia_card_remove(skt, NULL); | ||
1218 | 1240 | ||
1219 | /*====================================================================== | 1241 | mutex_lock(&skt->ops_mutex); |
1242 | destroy_cis_cache(skt); | ||
1243 | pcmcia_cleanup_irq(skt); | ||
1244 | mutex_unlock(&skt->ops_mutex); | ||
1220 | 1245 | ||
1221 | The card status event handler. | 1246 | return 0; |
1247 | } | ||
1222 | 1248 | ||
1223 | ======================================================================*/ | 1249 | static int pcmcia_bus_add(struct pcmcia_socket *skt) |
1250 | { | ||
1251 | atomic_set(&skt->present, 1); | ||
1224 | 1252 | ||
1225 | /* Normally, the event is passed to individual drivers after | 1253 | mutex_lock(&skt->ops_mutex); |
1226 | * informing userspace. Only for CS_EVENT_CARD_REMOVAL this | 1254 | skt->pcmcia_pfc = 0; |
1227 | * is inversed to maintain historic compatibility. | 1255 | destroy_cis_cache(skt); /* to be on the safe side... */ |
1228 | */ | 1256 | mutex_unlock(&skt->ops_mutex); |
1229 | 1257 | ||
1230 | static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | 1258 | pcmcia_card_add(skt); |
1231 | { | ||
1232 | struct pcmcia_socket *s = pcmcia_get_socket(skt); | ||
1233 | 1259 | ||
1234 | if (!s) { | 1260 | return 0; |
1235 | dev_printk(KERN_ERR, &skt->dev, | 1261 | } |
1236 | "PCMCIA obtaining reference to socket " \ | ||
1237 | "failed, event 0x%x lost!\n", event); | ||
1238 | return -ENODEV; | ||
1239 | } | ||
1240 | 1262 | ||
1241 | dev_dbg(&skt->dev, "ds_event(0x%06x, %d, 0x%p)\n", | 1263 | static int pcmcia_bus_early_resume(struct pcmcia_socket *skt) |
1242 | event, priority, skt); | 1264 | { |
1265 | if (!verify_cis_cache(skt)) { | ||
1266 | pcmcia_put_socket(skt); | ||
1267 | return 0; | ||
1268 | } | ||
1243 | 1269 | ||
1244 | switch (event) { | 1270 | dev_dbg(&skt->dev, "cis mismatch - different card\n"); |
1245 | case CS_EVENT_CARD_REMOVAL: | ||
1246 | atomic_set(&skt->present, 0); | ||
1247 | pcmcia_card_remove(skt, NULL); | ||
1248 | handle_event(skt, event); | ||
1249 | mutex_lock(&s->ops_mutex); | ||
1250 | destroy_cis_cache(s); | ||
1251 | pcmcia_cleanup_irq(s); | ||
1252 | mutex_unlock(&s->ops_mutex); | ||
1253 | break; | ||
1254 | 1271 | ||
1255 | case CS_EVENT_CARD_INSERTION: | 1272 | /* first, remove the card */ |
1256 | atomic_set(&skt->present, 1); | 1273 | pcmcia_bus_remove(skt); |
1257 | mutex_lock(&s->ops_mutex); | ||
1258 | s->pcmcia_state.has_pfc = 0; | ||
1259 | destroy_cis_cache(s); /* to be on the safe side... */ | ||
1260 | mutex_unlock(&s->ops_mutex); | ||
1261 | pcmcia_card_add(skt); | ||
1262 | handle_event(skt, event); | ||
1263 | break; | ||
1264 | |||
1265 | case CS_EVENT_EJECTION_REQUEST: | ||
1266 | break; | ||
1267 | |||
1268 | case CS_EVENT_PM_RESUME: | ||
1269 | if (verify_cis_cache(skt) != 0) { | ||
1270 | dev_dbg(&skt->dev, "cis mismatch - different card\n"); | ||
1271 | /* first, remove the card */ | ||
1272 | ds_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); | ||
1273 | mutex_lock(&s->ops_mutex); | ||
1274 | destroy_cis_cache(skt); | ||
1275 | kfree(skt->fake_cis); | ||
1276 | skt->fake_cis = NULL; | ||
1277 | s->functions = 0; | ||
1278 | mutex_unlock(&s->ops_mutex); | ||
1279 | /* now, add the new card */ | ||
1280 | ds_event(skt, CS_EVENT_CARD_INSERTION, | ||
1281 | CS_EVENT_PRI_LOW); | ||
1282 | } | ||
1283 | handle_event(skt, event); | ||
1284 | break; | ||
1285 | 1274 | ||
1286 | case CS_EVENT_PM_SUSPEND: | 1275 | mutex_lock(&skt->ops_mutex); |
1287 | case CS_EVENT_RESET_PHYSICAL: | 1276 | destroy_cis_cache(skt); |
1288 | case CS_EVENT_CARD_RESET: | 1277 | kfree(skt->fake_cis); |
1289 | default: | 1278 | skt->fake_cis = NULL; |
1290 | handle_event(skt, event); | 1279 | skt->functions = 0; |
1291 | break; | 1280 | mutex_unlock(&skt->ops_mutex); |
1292 | } | ||
1293 | 1281 | ||
1294 | pcmcia_put_socket(s); | 1282 | /* now, add the new card */ |
1283 | pcmcia_bus_add(skt); | ||
1284 | return 0; | ||
1285 | } | ||
1295 | 1286 | ||
1296 | return 0; | ||
1297 | } /* ds_event */ | ||
1298 | 1287 | ||
1299 | /* | 1288 | /* |
1300 | * NOTE: This is racy. There's no guarantee the card will still be | 1289 | * NOTE: This is racy. There's no guarantee the card will still be |
@@ -1323,10 +1312,12 @@ EXPORT_SYMBOL(pcmcia_dev_present); | |||
1323 | 1312 | ||
1324 | static struct pcmcia_callback pcmcia_bus_callback = { | 1313 | static struct pcmcia_callback pcmcia_bus_callback = { |
1325 | .owner = THIS_MODULE, | 1314 | .owner = THIS_MODULE, |
1326 | .event = ds_event, | 1315 | .add = pcmcia_bus_add, |
1316 | .remove = pcmcia_bus_remove, | ||
1327 | .requery = pcmcia_requery, | 1317 | .requery = pcmcia_requery, |
1328 | .validate = pccard_validate_cis, | 1318 | .validate = pccard_validate_cis, |
1329 | .suspend = pcmcia_bus_suspend, | 1319 | .suspend = pcmcia_bus_suspend, |
1320 | .early_resume = pcmcia_bus_early_resume, | ||
1330 | .resume = pcmcia_bus_resume, | 1321 | .resume = pcmcia_bus_resume, |
1331 | }; | 1322 | }; |
1332 | 1323 | ||
@@ -1350,11 +1341,8 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, | |||
1350 | return ret; | 1341 | return ret; |
1351 | } | 1342 | } |
1352 | 1343 | ||
1353 | #ifdef CONFIG_PCMCIA_IOCTL | ||
1354 | init_waitqueue_head(&socket->queue); | ||
1355 | #endif | ||
1356 | INIT_LIST_HEAD(&socket->devices_list); | 1344 | INIT_LIST_HEAD(&socket->devices_list); |
1357 | memset(&socket->pcmcia_state, 0, sizeof(u8)); | 1345 | socket->pcmcia_pfc = 0; |
1358 | socket->device_count = 0; | 1346 | socket->device_count = 0; |
1359 | atomic_set(&socket->present, 0); | 1347 | atomic_set(&socket->present, 0); |
1360 | 1348 | ||
@@ -1429,8 +1417,6 @@ static int __init init_pcmcia_bus(void) | |||
1429 | return ret; | 1417 | return ret; |
1430 | } | 1418 | } |
1431 | 1419 | ||
1432 | pcmcia_setup_ioctl(); | ||
1433 | |||
1434 | return 0; | 1420 | return 0; |
1435 | } | 1421 | } |
1436 | fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that | 1422 | fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that |
@@ -1439,8 +1425,6 @@ fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that | |||
1439 | 1425 | ||
1440 | static void __exit exit_pcmcia_bus(void) | 1426 | static void __exit exit_pcmcia_bus(void) |
1441 | { | 1427 | { |
1442 | pcmcia_cleanup_ioctl(); | ||
1443 | |||
1444 | class_interface_unregister(&pcmcia_bus_interface); | 1428 | class_interface_unregister(&pcmcia_bus_interface); |
1445 | 1429 | ||
1446 | bus_unregister(&pcmcia_bus_type); | 1430 | bus_unregister(&pcmcia_bus_type); |