diff options
Diffstat (limited to 'drivers/pcmcia/ds.c')
-rw-r--r-- | drivers/pcmcia/ds.c | 99 |
1 files changed, 44 insertions, 55 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index d5afd557fe37..3e3c6f12bbe6 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -158,17 +158,15 @@ static const lookup_t service_table[] = { | |||
158 | }; | 158 | }; |
159 | 159 | ||
160 | 160 | ||
161 | static int pcmcia_report_error(client_handle_t handle, error_info_t *err) | 161 | static int pcmcia_report_error(struct pcmcia_device *p_dev, error_info_t *err) |
162 | { | 162 | { |
163 | int i; | 163 | int i; |
164 | char *serv; | 164 | char *serv; |
165 | 165 | ||
166 | if (CHECK_HANDLE(handle)) | 166 | if (!p_dev) |
167 | printk(KERN_NOTICE); | 167 | printk(KERN_NOTICE); |
168 | else { | 168 | else |
169 | struct pcmcia_device *p_dev = handle_to_pdev(handle); | ||
170 | printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id); | 169 | printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id); |
171 | } | ||
172 | 170 | ||
173 | for (i = 0; i < ARRAY_SIZE(service_table); i++) | 171 | for (i = 0; i < ARRAY_SIZE(service_table); i++) |
174 | if (service_table[i].key == err->func) | 172 | if (service_table[i].key == err->func) |
@@ -193,10 +191,10 @@ static int pcmcia_report_error(client_handle_t handle, error_info_t *err) | |||
193 | 191 | ||
194 | /*======================================================================*/ | 192 | /*======================================================================*/ |
195 | 193 | ||
196 | void cs_error(client_handle_t handle, int func, int ret) | 194 | void cs_error(struct pcmcia_device *p_dev, int func, int ret) |
197 | { | 195 | { |
198 | error_info_t err = { func, ret }; | 196 | error_info_t err = { func, ret }; |
199 | pcmcia_report_error(handle, &err); | 197 | pcmcia_report_error(p_dev, &err); |
200 | } | 198 | } |
201 | EXPORT_SYMBOL(cs_error); | 199 | EXPORT_SYMBOL(cs_error); |
202 | 200 | ||
@@ -207,6 +205,10 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) | |||
207 | unsigned int i; | 205 | unsigned int i; |
208 | u32 hash; | 206 | u32 hash; |
209 | 207 | ||
208 | if (!p_drv->attach || !p_drv->event || !p_drv->detach) | ||
209 | printk(KERN_DEBUG "pcmcia: %s does misses a callback function", | ||
210 | p_drv->drv.name); | ||
211 | |||
210 | while (did && did->match_flags) { | 212 | while (did && did->match_flags) { |
211 | for (i=0; i<4; i++) { | 213 | for (i=0; i<4; i++) { |
212 | if (!did->prod_id[i]) | 214 | if (!did->prod_id[i]) |
@@ -376,7 +378,7 @@ static int pcmcia_device_probe(struct device * dev) | |||
376 | 378 | ||
377 | if (p_drv->attach) { | 379 | if (p_drv->attach) { |
378 | p_dev->instance = p_drv->attach(); | 380 | p_dev->instance = p_drv->attach(); |
379 | if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) { | 381 | if ((!p_dev->instance) || (p_dev->state & CLIENT_UNBOUND)) { |
380 | printk(KERN_NOTICE "ds: unable to create instance " | 382 | printk(KERN_NOTICE "ds: unable to create instance " |
381 | "of '%s'!\n", p_drv->drv.name); | 383 | "of '%s'!\n", p_drv->drv.name); |
382 | ret = -EINVAL; | 384 | ret = -EINVAL; |
@@ -516,10 +518,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
516 | sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); | 518 | sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); |
517 | 519 | ||
518 | /* compat */ | 520 | /* compat */ |
519 | p_dev->client.client_magic = CLIENT_MAGIC; | 521 | p_dev->state = CLIENT_UNBOUND; |
520 | p_dev->client.Socket = s; | ||
521 | p_dev->client.Function = function; | ||
522 | p_dev->client.state = CLIENT_UNBOUND; | ||
523 | 522 | ||
524 | /* Add to the list in pcmcia_bus_socket */ | 523 | /* Add to the list in pcmcia_bus_socket */ |
525 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 524 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
@@ -573,8 +572,6 @@ static int pcmcia_card_add(struct pcmcia_socket *s) | |||
573 | else | 572 | else |
574 | no_funcs = 1; | 573 | no_funcs = 1; |
575 | 574 | ||
576 | /* this doesn't handle multifunction devices on one pcmcia function | ||
577 | * yet. */ | ||
578 | for (i=0; i < no_funcs; i++) | 575 | for (i=0; i < no_funcs; i++) |
579 | pcmcia_device_add(s, i); | 576 | pcmcia_device_add(s, i); |
580 | 577 | ||
@@ -914,6 +911,7 @@ struct send_event_data { | |||
914 | static int send_event_callback(struct device *dev, void * _data) | 911 | static int send_event_callback(struct device *dev, void * _data) |
915 | { | 912 | { |
916 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 913 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
914 | struct pcmcia_driver *p_drv; | ||
917 | struct send_event_data *data = _data; | 915 | struct send_event_data *data = _data; |
918 | 916 | ||
919 | /* we get called for all sockets, but may only pass the event | 917 | /* we get called for all sockets, but may only pass the event |
@@ -921,11 +919,16 @@ static int send_event_callback(struct device *dev, void * _data) | |||
921 | if (p_dev->socket != data->skt) | 919 | if (p_dev->socket != data->skt) |
922 | return 0; | 920 | return 0; |
923 | 921 | ||
924 | if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE)) | 922 | p_drv = to_pcmcia_drv(p_dev->dev.driver); |
923 | if (!p_drv) | ||
925 | return 0; | 924 | return 0; |
926 | 925 | ||
927 | if (p_dev->client.EventMask & data->event) | 926 | if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE)) |
928 | return EVENT(&p_dev->client, data->event, data->priority); | 927 | return 0; |
928 | |||
929 | if (p_drv->event) | ||
930 | return p_drv->event(data->event, data->priority, | ||
931 | &p_dev->event_callback_args); | ||
929 | 932 | ||
930 | return 0; | 933 | return 0; |
931 | } | 934 | } |
@@ -987,11 +990,11 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
987 | 990 | ||
988 | 991 | ||
989 | 992 | ||
990 | int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | 993 | int pcmcia_register_client(struct pcmcia_device **handle, client_reg_t *req) |
991 | { | 994 | { |
992 | client_t *client = NULL; | ||
993 | struct pcmcia_socket *s = NULL; | 995 | struct pcmcia_socket *s = NULL; |
994 | struct pcmcia_device *p_dev = NULL; | 996 | struct pcmcia_device *p_dev = NULL; |
997 | struct pcmcia_driver *p_drv = NULL; | ||
995 | 998 | ||
996 | /* Look for unbound client with matching dev_info */ | 999 | /* Look for unbound client with matching dev_info */ |
997 | down_read(&pcmcia_socket_list_rwsem); | 1000 | down_read(&pcmcia_socket_list_rwsem); |
@@ -1006,18 +1009,16 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | |||
1006 | continue; | 1009 | continue; |
1007 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 1010 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
1008 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { | 1011 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { |
1009 | struct pcmcia_driver *p_drv; | ||
1010 | p_dev = pcmcia_get_dev(p_dev); | 1012 | p_dev = pcmcia_get_dev(p_dev); |
1011 | if (!p_dev) | 1013 | if (!p_dev) |
1012 | continue; | 1014 | continue; |
1013 | if (!(p_dev->client.state & CLIENT_UNBOUND) || | 1015 | if (!(p_dev->state & CLIENT_UNBOUND) || |
1014 | (!p_dev->dev.driver)) { | 1016 | (!p_dev->dev.driver)) { |
1015 | pcmcia_put_dev(p_dev); | 1017 | pcmcia_put_dev(p_dev); |
1016 | continue; | 1018 | continue; |
1017 | } | 1019 | } |
1018 | p_drv = to_pcmcia_drv(p_dev->dev.driver); | 1020 | p_drv = to_pcmcia_drv(p_dev->dev.driver); |
1019 | if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) { | 1021 | if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) { |
1020 | client = &p_dev->client; | ||
1021 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 1022 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
1022 | goto found; | 1023 | goto found; |
1023 | } | 1024 | } |
@@ -1028,26 +1029,20 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | |||
1028 | } | 1029 | } |
1029 | found: | 1030 | found: |
1030 | up_read(&pcmcia_socket_list_rwsem); | 1031 | up_read(&pcmcia_socket_list_rwsem); |
1031 | if (!p_dev || !client) | 1032 | if (!p_dev) |
1032 | return -ENODEV; | 1033 | return -ENODEV; |
1033 | 1034 | ||
1034 | pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */ | 1035 | pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */ |
1035 | 1036 | ||
1036 | *handle = client; | 1037 | *handle = p_dev; |
1037 | client->state &= ~CLIENT_UNBOUND; | 1038 | p_dev->state &= ~CLIENT_UNBOUND; |
1038 | client->Socket = s; | 1039 | p_dev->event_callback_args = req->event_callback_args; |
1039 | client->EventMask = req->EventMask; | 1040 | p_dev->event_callback_args.client_handle = p_dev; |
1040 | client->event_handler = req->event_handler; | ||
1041 | client->event_callback_args = req->event_callback_args; | ||
1042 | client->event_callback_args.client_handle = client; | ||
1043 | 1041 | ||
1044 | if (s->state & SOCKET_CARDBUS) | ||
1045 | client->state |= CLIENT_CARDBUS; | ||
1046 | 1042 | ||
1047 | if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) && | 1043 | if (!s->functions) { |
1048 | (client->Function != BIND_FN_ALL)) { | ||
1049 | cistpl_longlink_mfc_t mfc; | 1044 | cistpl_longlink_mfc_t mfc; |
1050 | if (pccard_read_tuple(s, client->Function, CISTPL_LONGLINK_MFC, &mfc) | 1045 | if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, &mfc) |
1051 | == CS_SUCCESS) | 1046 | == CS_SUCCESS) |
1052 | s->functions = mfc.nfn; | 1047 | s->functions = mfc.nfn; |
1053 | else | 1048 | else |
@@ -1060,13 +1055,13 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | |||
1060 | } | 1055 | } |
1061 | 1056 | ||
1062 | ds_dbg(1, "register_client(): client 0x%p, dev %s\n", | 1057 | ds_dbg(1, "register_client(): client 0x%p, dev %s\n", |
1063 | client, p_dev->dev.bus_id); | 1058 | p_dev, p_dev->dev.bus_id); |
1064 | if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE) | ||
1065 | EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW); | ||
1066 | 1059 | ||
1067 | if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) { | 1060 | if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) { |
1068 | if (client->EventMask & CS_EVENT_CARD_INSERTION) | 1061 | if (p_drv->event) |
1069 | EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); | 1062 | p_drv->event(CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW, |
1063 | &p_dev->event_callback_args); | ||
1064 | |||
1070 | } | 1065 | } |
1071 | 1066 | ||
1072 | return CS_SUCCESS; | 1067 | return CS_SUCCESS; |
@@ -1099,7 +1094,7 @@ static int unbind_request(struct pcmcia_socket *s) | |||
1099 | } | 1094 | } |
1100 | p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); | 1095 | p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); |
1101 | list_del(&p_dev->socket_device_list); | 1096 | list_del(&p_dev->socket_device_list); |
1102 | p_dev->client.state |= CLIENT_STALE; | 1097 | p_dev->state |= CLIENT_STALE; |
1103 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 1098 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
1104 | 1099 | ||
1105 | device_unregister(&p_dev->dev); | 1100 | device_unregister(&p_dev->dev); |
@@ -1108,31 +1103,25 @@ static int unbind_request(struct pcmcia_socket *s) | |||
1108 | return 0; | 1103 | return 0; |
1109 | } /* unbind_request */ | 1104 | } /* unbind_request */ |
1110 | 1105 | ||
1111 | int pcmcia_deregister_client(client_handle_t handle) | 1106 | int pcmcia_deregister_client(struct pcmcia_device *p_dev) |
1112 | { | 1107 | { |
1113 | struct pcmcia_socket *s; | 1108 | struct pcmcia_socket *s; |
1114 | int i; | 1109 | int i; |
1115 | struct pcmcia_device *p_dev = handle_to_pdev(handle); | ||
1116 | |||
1117 | if (CHECK_HANDLE(handle)) | ||
1118 | return CS_BAD_HANDLE; | ||
1119 | 1110 | ||
1120 | s = SOCKET(handle); | 1111 | s = p_dev->socket; |
1121 | ds_dbg(1, "deregister_client(%p)\n", handle); | 1112 | ds_dbg(1, "deregister_client(%p)\n", p_dev); |
1122 | 1113 | ||
1123 | if (handle->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) | 1114 | if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) |
1124 | goto warn_out; | 1115 | goto warn_out; |
1125 | for (i = 0; i < MAX_WIN; i++) | 1116 | for (i = 0; i < MAX_WIN; i++) |
1126 | if (handle->state & CLIENT_WIN_REQ(i)) | 1117 | if (p_dev->state & CLIENT_WIN_REQ(i)) |
1127 | goto warn_out; | 1118 | goto warn_out; |
1128 | 1119 | ||
1129 | if (handle->state & CLIENT_STALE) { | 1120 | if (p_dev->state & CLIENT_STALE) { |
1130 | handle->client_magic = 0; | 1121 | p_dev->state &= ~CLIENT_STALE; |
1131 | handle->state &= ~CLIENT_STALE; | ||
1132 | pcmcia_put_dev(p_dev); | 1122 | pcmcia_put_dev(p_dev); |
1133 | } else { | 1123 | } else { |
1134 | handle->state = CLIENT_UNBOUND; | 1124 | p_dev->state = CLIENT_UNBOUND; |
1135 | handle->event_handler = NULL; | ||
1136 | } | 1125 | } |
1137 | 1126 | ||
1138 | return CS_SUCCESS; | 1127 | return CS_SUCCESS; |