diff options
Diffstat (limited to 'drivers/pcmcia/ds.c')
-rw-r--r-- | drivers/pcmcia/ds.c | 123 |
1 files changed, 41 insertions, 82 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 85e2cb2b9e91..f796dcd64dcb 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -75,7 +75,7 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644); | |||
75 | 75 | ||
76 | spinlock_t pcmcia_dev_list_lock; | 76 | spinlock_t pcmcia_dev_list_lock; |
77 | 77 | ||
78 | static int unbind_request(struct pcmcia_bus_socket *s); | 78 | static int unbind_request(struct pcmcia_socket *s); |
79 | 79 | ||
80 | /*====================================================================*/ | 80 | /*====================================================================*/ |
81 | 81 | ||
@@ -313,24 +313,6 @@ static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filenam | |||
313 | /*======================================================================*/ | 313 | /*======================================================================*/ |
314 | 314 | ||
315 | 315 | ||
316 | void pcmcia_release_bus_socket(struct kref *refcount) | ||
317 | { | ||
318 | struct pcmcia_bus_socket *s = container_of(refcount, struct pcmcia_bus_socket, refcount); | ||
319 | pcmcia_put_socket(s->parent); | ||
320 | kfree(s); | ||
321 | } | ||
322 | |||
323 | void pcmcia_put_bus_socket(struct pcmcia_bus_socket *s) | ||
324 | { | ||
325 | kref_put(&s->refcount, pcmcia_release_bus_socket); | ||
326 | } | ||
327 | |||
328 | struct pcmcia_bus_socket *pcmcia_get_bus_socket(struct pcmcia_bus_socket *s) | ||
329 | { | ||
330 | kref_get(&s->refcount); | ||
331 | return (s); | ||
332 | } | ||
333 | |||
334 | /** | 316 | /** |
335 | * pcmcia_register_driver - register a PCMCIA driver with the bus core | 317 | * pcmcia_register_driver - register a PCMCIA driver with the bus core |
336 | * | 318 | * |
@@ -387,7 +369,7 @@ static void pcmcia_release_dev(struct device *dev) | |||
387 | { | 369 | { |
388 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 370 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
389 | ds_dbg(1, "releasing dev %p\n", p_dev); | 371 | ds_dbg(1, "releasing dev %p\n", p_dev); |
390 | pcmcia_put_bus_socket(p_dev->socket->pcmcia); | 372 | pcmcia_put_socket(p_dev->socket); |
391 | kfree(p_dev); | 373 | kfree(p_dev); |
392 | } | 374 | } |
393 | 375 | ||
@@ -522,12 +504,12 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
522 | */ | 504 | */ |
523 | static DECLARE_MUTEX(device_add_lock); | 505 | static DECLARE_MUTEX(device_add_lock); |
524 | 506 | ||
525 | struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned int function) | 507 | struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) |
526 | { | 508 | { |
527 | struct pcmcia_device *p_dev; | 509 | struct pcmcia_device *p_dev; |
528 | unsigned long flags; | 510 | unsigned long flags; |
529 | 511 | ||
530 | s = pcmcia_get_bus_socket(s); | 512 | s = pcmcia_get_socket(s); |
531 | if (!s) | 513 | if (!s) |
532 | return NULL; | 514 | return NULL; |
533 | 515 | ||
@@ -542,18 +524,18 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned i | |||
542 | goto err_put; | 524 | goto err_put; |
543 | memset(p_dev, 0, sizeof(struct pcmcia_device)); | 525 | memset(p_dev, 0, sizeof(struct pcmcia_device)); |
544 | 526 | ||
545 | p_dev->socket = s->parent; | 527 | p_dev->socket = s; |
546 | p_dev->device_no = (s->device_count++); | 528 | p_dev->device_no = (s->device_count++); |
547 | p_dev->func = function; | 529 | p_dev->func = function; |
548 | 530 | ||
549 | p_dev->dev.bus = &pcmcia_bus_type; | 531 | p_dev->dev.bus = &pcmcia_bus_type; |
550 | p_dev->dev.parent = s->parent->dev.dev; | 532 | p_dev->dev.parent = s->dev.dev; |
551 | p_dev->dev.release = pcmcia_release_dev; | 533 | p_dev->dev.release = pcmcia_release_dev; |
552 | sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); | 534 | sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); |
553 | 535 | ||
554 | /* compat */ | 536 | /* compat */ |
555 | p_dev->client.client_magic = CLIENT_MAGIC; | 537 | p_dev->client.client_magic = CLIENT_MAGIC; |
556 | p_dev->client.Socket = s->parent; | 538 | p_dev->client.Socket = s; |
557 | p_dev->client.Function = function; | 539 | p_dev->client.Function = function; |
558 | p_dev->client.state = CLIENT_UNBOUND; | 540 | p_dev->client.state = CLIENT_UNBOUND; |
559 | 541 | ||
@@ -581,7 +563,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned i | |||
581 | s->device_count--; | 563 | s->device_count--; |
582 | err_put: | 564 | err_put: |
583 | up(&device_add_lock); | 565 | up(&device_add_lock); |
584 | pcmcia_put_bus_socket(s); | 566 | pcmcia_put_socket(s); |
585 | 567 | ||
586 | return NULL; | 568 | return NULL; |
587 | } | 569 | } |
@@ -612,7 +594,7 @@ static int pcmcia_card_add(struct pcmcia_socket *s) | |||
612 | /* this doesn't handle multifunction devices on one pcmcia function | 594 | /* this doesn't handle multifunction devices on one pcmcia function |
613 | * yet. */ | 595 | * yet. */ |
614 | for (i=0; i < no_funcs; i++) | 596 | for (i=0; i < no_funcs; i++) |
615 | pcmcia_device_add(s->pcmcia, i); | 597 | pcmcia_device_add(s, i); |
616 | 598 | ||
617 | return (ret); | 599 | return (ret); |
618 | } | 600 | } |
@@ -620,12 +602,12 @@ static int pcmcia_card_add(struct pcmcia_socket *s) | |||
620 | 602 | ||
621 | static void pcmcia_delayed_add_pseudo_device(void *data) | 603 | static void pcmcia_delayed_add_pseudo_device(void *data) |
622 | { | 604 | { |
623 | struct pcmcia_bus_socket *s = data; | 605 | struct pcmcia_socket *s = data; |
624 | pcmcia_device_add(s, 0); | 606 | pcmcia_device_add(s, 0); |
625 | s->pcmcia_state.device_add_pending = 0; | 607 | s->pcmcia_state.device_add_pending = 0; |
626 | } | 608 | } |
627 | 609 | ||
628 | static inline void pcmcia_add_pseudo_device(struct pcmcia_bus_socket *s) | 610 | static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) |
629 | { | 611 | { |
630 | if (!s->pcmcia_state.device_add_pending) { | 612 | if (!s->pcmcia_state.device_add_pending) { |
631 | schedule_work(&s->device_add); | 613 | schedule_work(&s->device_add); |
@@ -650,7 +632,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt) | |||
650 | 632 | ||
651 | /* must be called with skt_sem held */ | 633 | /* must be called with skt_sem held */ |
652 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 634 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
653 | if (list_empty(&skt->pcmcia->devices_list)) | 635 | if (list_empty(&skt->devices_list)) |
654 | no_devices=1; | 636 | no_devices=1; |
655 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 637 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
656 | 638 | ||
@@ -727,7 +709,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
727 | * pseudo devices, and if not, add the second one. | 709 | * pseudo devices, and if not, add the second one. |
728 | */ | 710 | */ |
729 | if (dev->device_no == 0) | 711 | if (dev->device_no == 0) |
730 | pcmcia_add_pseudo_device(dev->socket->pcmcia); | 712 | pcmcia_add_pseudo_device(dev->socket); |
731 | 713 | ||
732 | if (dev->device_no != did->device_no) | 714 | if (dev->device_no != did->device_no) |
733 | return 0; | 715 | return 0; |
@@ -947,21 +929,13 @@ static int send_event_callback(struct device *dev, void * _data) | |||
947 | 929 | ||
948 | static int send_event(struct pcmcia_socket *s, event_t event, int priority) | 930 | static int send_event(struct pcmcia_socket *s, event_t event, int priority) |
949 | { | 931 | { |
950 | int ret = 0; | ||
951 | struct send_event_data private; | 932 | struct send_event_data private; |
952 | struct pcmcia_bus_socket *skt = pcmcia_get_bus_socket(s->pcmcia); | ||
953 | |||
954 | if (!skt) | ||
955 | return 0; | ||
956 | 933 | ||
957 | private.skt = s; | 934 | private.skt = s; |
958 | private.event = event; | 935 | private.event = event; |
959 | private.priority = priority; | 936 | private.priority = priority; |
960 | 937 | ||
961 | ret = bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback); | 938 | return bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback); |
962 | |||
963 | pcmcia_put_bus_socket(skt); | ||
964 | return ret; | ||
965 | } /* send_event */ | 939 | } /* send_event */ |
966 | 940 | ||
967 | 941 | ||
@@ -972,25 +946,25 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority) | |||
972 | 946 | ||
973 | static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | 947 | static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) |
974 | { | 948 | { |
975 | struct pcmcia_bus_socket *s = skt->pcmcia; | 949 | struct pcmcia_socket *s = pcmcia_get_socket(skt); |
976 | int ret = 0; | 950 | int ret = 0; |
977 | 951 | ||
978 | ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n", | 952 | ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n", |
979 | event, priority, s); | 953 | event, priority, skt); |
980 | 954 | ||
981 | switch (event) { | 955 | switch (event) { |
982 | 956 | ||
983 | case CS_EVENT_CARD_REMOVAL: | 957 | case CS_EVENT_CARD_REMOVAL: |
984 | s->pcmcia_state.present = 0; | 958 | s->pcmcia_state.present = 0; |
985 | send_event(skt, event, priority); | 959 | send_event(skt, event, priority); |
986 | unbind_request(s); | 960 | unbind_request(skt); |
987 | handle_event(s, event); | 961 | handle_event(skt, event); |
988 | break; | 962 | break; |
989 | 963 | ||
990 | case CS_EVENT_CARD_INSERTION: | 964 | case CS_EVENT_CARD_INSERTION: |
991 | s->pcmcia_state.present = 1; | 965 | s->pcmcia_state.present = 1; |
992 | pcmcia_card_add(skt); | 966 | pcmcia_card_add(skt); |
993 | handle_event(s, event); | 967 | handle_event(skt, event); |
994 | break; | 968 | break; |
995 | 969 | ||
996 | case CS_EVENT_EJECTION_REQUEST: | 970 | case CS_EVENT_EJECTION_REQUEST: |
@@ -998,11 +972,13 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
998 | break; | 972 | break; |
999 | 973 | ||
1000 | default: | 974 | default: |
1001 | handle_event(s, event); | 975 | handle_event(skt, event); |
1002 | send_event(skt, event, priority); | 976 | send_event(skt, event, priority); |
1003 | break; | 977 | break; |
1004 | } | 978 | } |
1005 | 979 | ||
980 | pcmcia_put_socket(s); | ||
981 | |||
1006 | return 0; | 982 | return 0; |
1007 | } /* ds_event */ | 983 | } /* ds_event */ |
1008 | 984 | ||
@@ -1011,8 +987,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1011 | int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | 987 | int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) |
1012 | { | 988 | { |
1013 | client_t *client = NULL; | 989 | client_t *client = NULL; |
1014 | struct pcmcia_socket *s; | 990 | struct pcmcia_socket *s = NULL; |
1015 | struct pcmcia_bus_socket *skt = NULL; | ||
1016 | struct pcmcia_device *p_dev = NULL; | 991 | struct pcmcia_device *p_dev = NULL; |
1017 | 992 | ||
1018 | /* Look for unbound client with matching dev_info */ | 993 | /* Look for unbound client with matching dev_info */ |
@@ -1023,14 +998,11 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | |||
1023 | if (s->state & SOCKET_CARDBUS) | 998 | if (s->state & SOCKET_CARDBUS) |
1024 | continue; | 999 | continue; |
1025 | 1000 | ||
1026 | skt = s->pcmcia; | 1001 | s = pcmcia_get_socket(s); |
1027 | if (!skt) | 1002 | if (!s) |
1028 | continue; | ||
1029 | skt = pcmcia_get_bus_socket(skt); | ||
1030 | if (!skt) | ||
1031 | continue; | 1003 | continue; |
1032 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 1004 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
1033 | list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) { | 1005 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { |
1034 | struct pcmcia_driver *p_drv; | 1006 | struct pcmcia_driver *p_drv; |
1035 | p_dev = pcmcia_get_dev(p_dev); | 1007 | p_dev = pcmcia_get_dev(p_dev); |
1036 | if (!p_dev) | 1008 | if (!p_dev) |
@@ -1049,14 +1021,14 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | |||
1049 | pcmcia_put_dev(p_dev); | 1021 | pcmcia_put_dev(p_dev); |
1050 | } | 1022 | } |
1051 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 1023 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
1052 | pcmcia_put_bus_socket(skt); | 1024 | pcmcia_put_socket(s); |
1053 | } | 1025 | } |
1054 | found: | 1026 | found: |
1055 | up_read(&pcmcia_socket_list_rwsem); | 1027 | up_read(&pcmcia_socket_list_rwsem); |
1056 | if (!p_dev || !client) | 1028 | if (!p_dev || !client) |
1057 | return -ENODEV; | 1029 | return -ENODEV; |
1058 | 1030 | ||
1059 | pcmcia_put_bus_socket(skt); /* safe, as we already hold a reference from bind_device */ | 1031 | pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */ |
1060 | 1032 | ||
1061 | *handle = client; | 1033 | *handle = client; |
1062 | client->state &= ~CLIENT_UNBOUND; | 1034 | client->state &= ~CLIENT_UNBOUND; |
@@ -1106,12 +1078,12 @@ EXPORT_SYMBOL(pcmcia_register_client); | |||
1106 | /* unbind _all_ devices attached to a given pcmcia_bus_socket. The | 1078 | /* unbind _all_ devices attached to a given pcmcia_bus_socket. The |
1107 | * drivers have been called with EVENT_CARD_REMOVAL before. | 1079 | * drivers have been called with EVENT_CARD_REMOVAL before. |
1108 | */ | 1080 | */ |
1109 | static int unbind_request(struct pcmcia_bus_socket *s) | 1081 | static int unbind_request(struct pcmcia_socket *s) |
1110 | { | 1082 | { |
1111 | struct pcmcia_device *p_dev; | 1083 | struct pcmcia_device *p_dev; |
1112 | unsigned long flags; | 1084 | unsigned long flags; |
1113 | 1085 | ||
1114 | ds_dbg(2, "unbind_request(%d)\n", s->parent->sock); | 1086 | ds_dbg(2, "unbind_request(%d)\n", s->sock); |
1115 | 1087 | ||
1116 | s->device_count = 0; | 1088 | s->device_count = 0; |
1117 | 1089 | ||
@@ -1176,24 +1148,14 @@ static struct pcmcia_callback pcmcia_bus_callback = { | |||
1176 | static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) | 1148 | static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) |
1177 | { | 1149 | { |
1178 | struct pcmcia_socket *socket = class_get_devdata(class_dev); | 1150 | struct pcmcia_socket *socket = class_get_devdata(class_dev); |
1179 | struct pcmcia_bus_socket *s; | ||
1180 | int ret; | 1151 | int ret; |
1181 | 1152 | ||
1182 | s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL); | 1153 | socket = pcmcia_get_socket(socket); |
1183 | if(!s) | 1154 | if (!socket) { |
1184 | return -ENOMEM; | ||
1185 | memset(s, 0, sizeof(struct pcmcia_bus_socket)); | ||
1186 | |||
1187 | /* get reference to parent socket */ | ||
1188 | s->parent = pcmcia_get_socket(socket); | ||
1189 | if (!s->parent) { | ||
1190 | printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket); | 1155 | printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket); |
1191 | kfree (s); | ||
1192 | return -ENODEV; | 1156 | return -ENODEV; |
1193 | } | 1157 | } |
1194 | 1158 | ||
1195 | kref_init(&s->refcount); | ||
1196 | |||
1197 | /* | 1159 | /* |
1198 | * Ugly. But we want to wait for the socket threads to have started up. | 1160 | * Ugly. But we want to wait for the socket threads to have started up. |
1199 | * We really should let the drivers themselves drive some of this.. | 1161 | * We really should let the drivers themselves drive some of this.. |
@@ -1201,19 +1163,17 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) | |||
1201 | msleep(250); | 1163 | msleep(250); |
1202 | 1164 | ||
1203 | #ifdef CONFIG_PCMCIA_IOCTL | 1165 | #ifdef CONFIG_PCMCIA_IOCTL |
1204 | init_waitqueue_head(&s->queue); | 1166 | init_waitqueue_head(&socket->queue); |
1205 | #endif | 1167 | #endif |
1206 | INIT_LIST_HEAD(&s->devices_list); | 1168 | INIT_LIST_HEAD(&socket->devices_list); |
1207 | INIT_WORK(&s->device_add, pcmcia_delayed_add_pseudo_device, s); | 1169 | INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device, socket); |
1208 | 1170 | memset(&socket->pcmcia_state, 0, sizeof(u8)); | |
1209 | /* Set up hotline to Card Services */ | 1171 | socket->device_count = 0; |
1210 | socket->pcmcia = s; | ||
1211 | 1172 | ||
1212 | ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback); | 1173 | ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback); |
1213 | if (ret) { | 1174 | if (ret) { |
1214 | printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket); | 1175 | printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket); |
1215 | pcmcia_put_bus_socket(s); | 1176 | pcmcia_put_socket(socket); |
1216 | socket->pcmcia = NULL; | ||
1217 | return (ret); | 1177 | return (ret); |
1218 | } | 1178 | } |
1219 | 1179 | ||
@@ -1224,14 +1184,13 @@ static void pcmcia_bus_remove_socket(struct class_device *class_dev) | |||
1224 | { | 1184 | { |
1225 | struct pcmcia_socket *socket = class_get_devdata(class_dev); | 1185 | struct pcmcia_socket *socket = class_get_devdata(class_dev); |
1226 | 1186 | ||
1227 | if (!socket || !socket->pcmcia) | 1187 | if (!socket) |
1228 | return; | 1188 | return; |
1229 | 1189 | ||
1190 | socket->pcmcia_state.dead = 1; | ||
1230 | pccard_register_pcmcia(socket, NULL); | 1191 | pccard_register_pcmcia(socket, NULL); |
1231 | 1192 | ||
1232 | socket->pcmcia->pcmcia_state.dead = 1; | 1193 | pcmcia_put_socket(socket); |
1233 | pcmcia_put_bus_socket(socket->pcmcia); | ||
1234 | socket->pcmcia = NULL; | ||
1235 | 1194 | ||
1236 | return; | 1195 | return; |
1237 | } | 1196 | } |