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