aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/sl811_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/sl811_cs.c')
-rw-r--r--drivers/usb/host/sl811_cs.c110
1 files changed, 32 insertions, 78 deletions
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 5056b7459994..466384d7c79f 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -66,13 +66,13 @@ module_param(pc_debug, int, 0644);
66 66
67static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; 67static const char driver_name[DEV_NAME_LEN] = "sl811_cs";
68 68
69static dev_link_t *dev_list = NULL;
70
71typedef struct local_info_t { 69typedef struct local_info_t {
72 dev_link_t link; 70 dev_link_t link;
73 dev_node_t node; 71 dev_node_t node;
74} local_info_t; 72} local_info_t;
75 73
74static void sl811_cs_release(dev_link_t * link);
75
76/*====================================================================*/ 76/*====================================================================*/
77 77
78static void release_platform_dev(struct device * dev) 78static void release_platform_dev(struct device * dev)
@@ -138,26 +138,16 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
138 138
139/*====================================================================*/ 139/*====================================================================*/
140 140
141static void sl811_cs_detach(dev_link_t *link) 141static void sl811_cs_detach(struct pcmcia_device *p_dev)
142{ 142{
143 dev_link_t **linkp; 143 dev_link_t *link = dev_to_instance(p_dev);
144 144
145 DBG(0, "sl811_cs_detach(0x%p)\n", link); 145 DBG(0, "sl811_cs_detach(0x%p)\n", link);
146 146
147 /* Locate device structure */ 147 link->state &= ~DEV_PRESENT;
148 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { 148 if (link->state & DEV_CONFIG)
149 if (*linkp == link) 149 sl811_cs_release(link);
150 break;
151 }
152 if (*linkp == NULL)
153 return;
154
155 /* Break the link with Card Services */
156 if (link->handle)
157 pcmcia_deregister_client(link->handle);
158 150
159 /* Unlink device structure, and free it */
160 *linkp = link->next;
161 /* This points to the parent local_info_t struct */ 151 /* This points to the parent local_info_t struct */
162 kfree(link->priv); 152 kfree(link->priv);
163} 153}
@@ -167,13 +157,6 @@ static void sl811_cs_release(dev_link_t * link)
167 157
168 DBG(0, "sl811_cs_release(0x%p)\n", link); 158 DBG(0, "sl811_cs_release(0x%p)\n", link);
169 159
170 if (link->open) {
171 DBG(1, "sl811_cs: release postponed, '%s' still open\n",
172 link->dev->dev_name);
173 link->state |= DEV_STALE_CONFIG;
174 return;
175 }
176
177 /* Unlink the device chain */ 160 /* Unlink the device chain */
178 link->dev = NULL; 161 link->dev = NULL;
179 162
@@ -184,9 +167,6 @@ static void sl811_cs_release(dev_link_t * link)
184 if (link->irq.AssignedIRQ) 167 if (link->irq.AssignedIRQ)
185 pcmcia_release_irq(link->handle, &link->irq); 168 pcmcia_release_irq(link->handle, &link->irq);
186 link->state &= ~DEV_CONFIG; 169 link->state &= ~DEV_CONFIG;
187
188 if (link->state & DEV_STALE_LINK)
189 sl811_cs_detach(link);
190} 170}
191 171
192static void sl811_cs_config(dev_link_t *link) 172static void sl811_cs_config(dev_link_t *link)
@@ -323,55 +303,36 @@ cs_failed:
323 } 303 }
324} 304}
325 305
326static int 306static int sl811_suspend(struct pcmcia_device *dev)
327sl811_cs_event(event_t event, int priority, event_callback_args_t *args)
328{ 307{
329 dev_link_t *link = args->client_data; 308 dev_link_t *link = dev_to_instance(dev);
330 309
331 DBG(1, "sl811_cs_event(0x%06x)\n", event); 310 link->state |= DEV_SUSPEND;
311 if (link->state & DEV_CONFIG)
312 pcmcia_release_configuration(link->handle);
332 313
333 switch (event) { 314 return 0;
334 case CS_EVENT_CARD_REMOVAL: 315}
335 link->state &= ~DEV_PRESENT;
336 if (link->state & DEV_CONFIG)
337 sl811_cs_release(link);
338 break;
339 316
340 case CS_EVENT_CARD_INSERTION: 317static int sl811_resume(struct pcmcia_device *dev)
341 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 318{
342 sl811_cs_config(link); 319 dev_link_t *link = dev_to_instance(dev);
343 break;
344 320
345 case CS_EVENT_PM_SUSPEND: 321 link->state &= ~DEV_SUSPEND;
346 link->state |= DEV_SUSPEND; 322 if (link->state & DEV_CONFIG)
347 /* Fall through... */ 323 pcmcia_request_configuration(link->handle, &link->conf);
348 case CS_EVENT_RESET_PHYSICAL:
349 if (link->state & DEV_CONFIG)
350 pcmcia_release_configuration(link->handle);
351 break;
352 324
353 case CS_EVENT_PM_RESUME:
354 link->state &= ~DEV_SUSPEND;
355 /* Fall through... */
356 case CS_EVENT_CARD_RESET:
357 if (link->state & DEV_CONFIG)
358 pcmcia_request_configuration(link->handle, &link->conf);
359 DBG(0, "reset sl811-hcd here?\n");
360 break;
361 }
362 return 0; 325 return 0;
363} 326}
364 327
365static dev_link_t *sl811_cs_attach(void) 328static int sl811_cs_attach(struct pcmcia_device *p_dev)
366{ 329{
367 local_info_t *local; 330 local_info_t *local;
368 dev_link_t *link; 331 dev_link_t *link;
369 client_reg_t client_reg;
370 int ret;
371 332
372 local = kmalloc(sizeof(local_info_t), GFP_KERNEL); 333 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
373 if (!local) 334 if (!local)
374 return NULL; 335 return -ENOMEM;
375 memset(local, 0, sizeof(local_info_t)); 336 memset(local, 0, sizeof(local_info_t));
376 link = &local->link; 337 link = &local->link;
377 link->priv = local; 338 link->priv = local;
@@ -385,21 +346,13 @@ static dev_link_t *sl811_cs_attach(void)
385 link->conf.Vcc = 33; 346 link->conf.Vcc = 33;
386 link->conf.IntType = INT_MEMORY_AND_IO; 347 link->conf.IntType = INT_MEMORY_AND_IO;
387 348
388 /* Register with Card Services */ 349 link->handle = p_dev;
389 link->next = dev_list; 350 p_dev->instance = link;
390 dev_list = link;
391 client_reg.dev_info = (dev_info_t *) &driver_name;
392 client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
393 client_reg.Version = 0x0210;
394 client_reg.event_callback_args.client_data = link;
395 ret = pcmcia_register_client(&link->handle, &client_reg);
396 if (ret != CS_SUCCESS) {
397 cs_error(link->handle, RegisterClient, ret);
398 sl811_cs_detach(link);
399 return NULL;
400 }
401 351
402 return link; 352 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
353 sl811_cs_config(link);
354
355 return 0;
403} 356}
404 357
405static struct pcmcia_device_id sl811_ids[] = { 358static struct pcmcia_device_id sl811_ids[] = {
@@ -413,10 +366,11 @@ static struct pcmcia_driver sl811_cs_driver = {
413 .drv = { 366 .drv = {
414 .name = (char *)driver_name, 367 .name = (char *)driver_name,
415 }, 368 },
416 .attach = sl811_cs_attach, 369 .probe = sl811_cs_attach,
417 .event = sl811_cs_event, 370 .remove = sl811_cs_detach,
418 .detach = sl811_cs_detach,
419 .id_table = sl811_ids, 371 .id_table = sl811_ids,
372 .suspend = sl811_suspend,
373 .resume = sl811_resume,
420}; 374};
421 375
422/*====================================================================*/ 376/*====================================================================*/