aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/ds.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-11-14 15:25:51 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2006-01-05 18:03:24 -0500
commitf8cfa618dccbdc6dab5297f75779566a388a98fd (patch)
treeb91e0952038dafc6e03bf8b1d8948b1fdefec031 /drivers/pcmcia/ds.c
parentb463581154f3f3eecda27cae60df813fefcd84d3 (diff)
[PATCH] pcmcia: unify attach, EVENT_CARD_INSERTION handlers into one probe callback
Unify the EVENT_CARD_INSERTION and "attach" callbacks to one unified probe() callback. As all in-kernel drivers are changed to this new callback, there will be no temporary backwards-compatibility. Inside a probe() function, each driver _must_ set struct pcmcia_device *p_dev->instance and instance->handle correctly. With these patches, the basic driver interface for 16-bit PCMCIA drivers now has the classic four callbacks known also from other buses: int (*probe) (struct pcmcia_device *dev); void (*remove) (struct pcmcia_device *dev); int (*suspend) (struct pcmcia_device *dev); int (*resume) (struct pcmcia_device *dev); Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia/ds.c')
-rw-r--r--drivers/pcmcia/ds.c177
1 files changed, 27 insertions, 150 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 8eff55b6c9e9..0fc61dd1d4d0 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -203,7 +203,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
203 unsigned int i; 203 unsigned int i;
204 u32 hash; 204 u32 hash;
205 205
206 if (!p_drv->attach || !p_drv->event || !p_drv->remove) 206 if (!p_drv->probe || !p_drv->remove)
207 printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback " 207 printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
208 "function\n", p_drv->drv.name); 208 "function\n", p_drv->drv.name);
209 209
@@ -361,6 +361,7 @@ static int pcmcia_device_probe(struct device * dev)
361{ 361{
362 struct pcmcia_device *p_dev; 362 struct pcmcia_device *p_dev;
363 struct pcmcia_driver *p_drv; 363 struct pcmcia_driver *p_drv;
364 struct pcmcia_socket *s;
364 int ret = 0; 365 int ret = 0;
365 366
366 dev = get_device(dev); 367 dev = get_device(dev);
@@ -369,25 +370,39 @@ static int pcmcia_device_probe(struct device * dev)
369 370
370 p_dev = to_pcmcia_dev(dev); 371 p_dev = to_pcmcia_dev(dev);
371 p_drv = to_pcmcia_drv(dev->driver); 372 p_drv = to_pcmcia_drv(dev->driver);
373 s = p_dev->socket;
372 374
373 if (!try_module_get(p_drv->owner)) { 375 if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) {
374 ret = -EINVAL; 376 ret = -EINVAL;
375 goto put_dev; 377 goto put_dev;
376 } 378 }
377 379
378 if (p_drv->attach) { 380 p_dev->state &= ~CLIENT_UNBOUND;
379 p_dev->instance = p_drv->attach(); 381
380 if ((!p_dev->instance) || (p_dev->state & CLIENT_UNBOUND)) { 382 /* set up the device configuration, if it hasn't been done before */
381 printk(KERN_NOTICE "ds: unable to create instance " 383 if (!s->functions) {
382 "of '%s'!\n", p_drv->drv.name); 384 cistpl_longlink_mfc_t mfc;
383 ret = -EINVAL; 385 if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC,
386 &mfc) == CS_SUCCESS)
387 s->functions = mfc.nfn;
388 else
389 s->functions = 1;
390 s->config = kmalloc(sizeof(config_t) * s->functions,
391 GFP_KERNEL);
392 if (!s->config) {
393 ret = -ENOMEM;
394 goto put_module;
384 } 395 }
396 memset(s->config, 0, sizeof(config_t) * s->functions);
385 } 397 }
386 398
399 ret = p_drv->probe(p_dev);
400
401 put_module:
387 if (ret) 402 if (ret)
388 module_put(p_drv->owner); 403 module_put(p_drv->owner);
389 put_dev: 404 put_dev:
390 if ((ret) || !(p_drv->attach)) 405 if (ret)
391 put_device(dev); 406 put_device(dev);
392 return (ret); 407 return (ret);
393} 408}
@@ -418,11 +433,8 @@ static int pcmcia_device_remove(struct device * dev)
418 printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n", 433 printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
419 p_drv->drv.name); 434 p_drv->drv.name);
420 435
421 /* undo pcmcia_register_client */
422 p_dev->state = CLIENT_UNBOUND;
423 pcmcia_put_dev(p_dev);
424
425 /* references from pcmcia_probe_device */ 436 /* references from pcmcia_probe_device */
437 p_dev->state = CLIENT_UNBOUND;
426 pcmcia_put_dev(p_dev); 438 pcmcia_put_dev(p_dev);
427 module_put(p_drv->owner); 439 module_put(p_drv->owner);
428 440
@@ -1042,49 +1054,6 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
1042 1054
1043======================================================================*/ 1055======================================================================*/
1044 1056
1045struct send_event_data {
1046 struct pcmcia_socket *skt;
1047 event_t event;
1048 int priority;
1049};
1050
1051static int send_event_callback(struct device *dev, void * _data)
1052{
1053 struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
1054 struct pcmcia_driver *p_drv;
1055 struct send_event_data *data = _data;
1056
1057 /* we get called for all sockets, but may only pass the event
1058 * for drivers _on the affected socket_ */
1059 if (p_dev->socket != data->skt)
1060 return 0;
1061
1062 p_drv = to_pcmcia_drv(p_dev->dev.driver);
1063 if (!p_drv)
1064 return 0;
1065
1066 if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE))
1067 return 0;
1068
1069 if (p_drv->event)
1070 return p_drv->event(data->event, data->priority,
1071 &p_dev->event_callback_args);
1072
1073 return 0;
1074}
1075
1076static int send_event(struct pcmcia_socket *s, event_t event, int priority)
1077{
1078 struct send_event_data private;
1079
1080 private.skt = s;
1081 private.event = event;
1082 private.priority = priority;
1083
1084 return bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback);
1085} /* send_event */
1086
1087
1088/* Normally, the event is passed to individual drivers after 1057/* Normally, the event is passed to individual drivers after
1089 * informing userspace. Only for CS_EVENT_CARD_REMOVAL this 1058 * informing userspace. Only for CS_EVENT_CARD_REMOVAL this
1090 * is inversed to maintain historic compatibility. 1059 * is inversed to maintain historic compatibility.
@@ -1093,20 +1062,17 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)
1093static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) 1062static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
1094{ 1063{
1095 struct pcmcia_socket *s = pcmcia_get_socket(skt); 1064 struct pcmcia_socket *s = pcmcia_get_socket(skt);
1096 int ret = 0;
1097 1065
1098 ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n", 1066 ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
1099 event, priority, skt); 1067 event, priority, skt);
1100
1101 switch (event) {
1102 1068
1069 switch (event) {
1103 case CS_EVENT_CARD_REMOVAL: 1070 case CS_EVENT_CARD_REMOVAL:
1104 s->pcmcia_state.present = 0; 1071 s->pcmcia_state.present = 0;
1105 send_event(skt, event, priority);
1106 pcmcia_card_remove(skt); 1072 pcmcia_card_remove(skt);
1107 handle_event(skt, event); 1073 handle_event(skt, event);
1108 break; 1074 break;
1109 1075
1110 case CS_EVENT_CARD_INSERTION: 1076 case CS_EVENT_CARD_INSERTION:
1111 s->pcmcia_state.present = 1; 1077 s->pcmcia_state.present = 1;
1112 pcmcia_card_add(skt); 1078 pcmcia_card_add(skt);
@@ -1114,19 +1080,14 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
1114 break; 1080 break;
1115 1081
1116 case CS_EVENT_EJECTION_REQUEST: 1082 case CS_EVENT_EJECTION_REQUEST:
1117 ret = send_event(skt, event, priority);
1118 break; 1083 break;
1119 1084
1120 case CS_EVENT_PM_SUSPEND: 1085 case CS_EVENT_PM_SUSPEND:
1121 case CS_EVENT_PM_RESUME: 1086 case CS_EVENT_PM_RESUME:
1122 case CS_EVENT_RESET_PHYSICAL: 1087 case CS_EVENT_RESET_PHYSICAL:
1123 case CS_EVENT_CARD_RESET: 1088 case CS_EVENT_CARD_RESET:
1124 handle_event(skt, event);
1125 break;
1126
1127 default: 1089 default:
1128 handle_event(skt, event); 1090 handle_event(skt, event);
1129 send_event(skt, event, priority);
1130 break; 1091 break;
1131 } 1092 }
1132 1093
@@ -1136,90 +1097,6 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
1136} /* ds_event */ 1097} /* ds_event */
1137 1098
1138 1099
1139
1140int pcmcia_register_client(struct pcmcia_device **handle, client_reg_t *req)
1141{
1142 struct pcmcia_socket *s = NULL;
1143 struct pcmcia_device *p_dev = NULL;
1144 struct pcmcia_driver *p_drv = NULL;
1145
1146 /* Look for unbound client with matching dev_info */
1147 down_read(&pcmcia_socket_list_rwsem);
1148 list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
1149 unsigned long flags;
1150
1151 if (s->state & SOCKET_CARDBUS)
1152 continue;
1153
1154 s = pcmcia_get_socket(s);
1155 if (!s)
1156 continue;
1157 spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
1158 list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
1159 p_dev = pcmcia_get_dev(p_dev);
1160 if (!p_dev)
1161 continue;
1162 if (!(p_dev->state & CLIENT_UNBOUND) ||
1163 (!p_dev->dev.driver)) {
1164 pcmcia_put_dev(p_dev);
1165 continue;
1166 }
1167 p_drv = to_pcmcia_drv(p_dev->dev.driver);
1168 if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) {
1169 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
1170 goto found;
1171 }
1172 pcmcia_put_dev(p_dev);
1173 }
1174 spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
1175 pcmcia_put_socket(s);
1176 }
1177 found:
1178 up_read(&pcmcia_socket_list_rwsem);
1179 if (!p_dev)
1180 return -ENODEV;
1181
1182 pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */
1183
1184 *handle = p_dev;
1185 p_dev->state &= ~CLIENT_UNBOUND;
1186 p_dev->event_callback_args = req->event_callback_args;
1187 p_dev->event_callback_args.client_handle = p_dev;
1188
1189
1190 if (!s->functions) {
1191 cistpl_longlink_mfc_t mfc;
1192 if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, &mfc)
1193 == CS_SUCCESS)
1194 s->functions = mfc.nfn;
1195 else
1196 s->functions = 1;
1197 s->config = kmalloc(sizeof(config_t) * s->functions,
1198 GFP_KERNEL);
1199 if (!s->config)
1200 goto out_no_resource;
1201 memset(s->config, 0, sizeof(config_t) * s->functions);
1202 }
1203
1204 ds_dbg(1, "register_client(): client 0x%p, dev %s\n",
1205 p_dev, p_dev->dev.bus_id);
1206
1207 if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
1208 if (p_drv->event)
1209 p_drv->event(CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW,
1210 &p_dev->event_callback_args);
1211
1212 }
1213
1214 return CS_SUCCESS;
1215
1216 out_no_resource:
1217 pcmcia_put_dev(p_dev);
1218 return CS_OUT_OF_RESOURCE;
1219} /* register_client */
1220EXPORT_SYMBOL(pcmcia_register_client);
1221
1222
1223static struct pcmcia_callback pcmcia_bus_callback = { 1100static struct pcmcia_callback pcmcia_bus_callback = {
1224 .owner = THIS_MODULE, 1101 .owner = THIS_MODULE,
1225 .event = ds_event, 1102 .event = ds_event,