diff options
Diffstat (limited to 'drivers/telephony/ixj_pcmcia.c')
-rw-r--r-- | drivers/telephony/ixj_pcmcia.c | 112 |
1 files changed, 40 insertions, 72 deletions
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 57c0c6e3fbed..d3a7b0c3d38b 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c | |||
@@ -34,24 +34,19 @@ typedef struct ixj_info_t { | |||
34 | struct ixj *port; | 34 | struct ixj *port; |
35 | } ixj_info_t; | 35 | } ixj_info_t; |
36 | 36 | ||
37 | static dev_link_t *ixj_attach(void); | 37 | static void ixj_detach(struct pcmcia_device *p_dev); |
38 | static void ixj_detach(dev_link_t *); | ||
39 | static void ixj_config(dev_link_t * link); | 38 | static void ixj_config(dev_link_t * link); |
40 | static void ixj_cs_release(dev_link_t * link); | 39 | static void ixj_cs_release(dev_link_t * link); |
41 | static int ixj_event(event_t event, int priority, event_callback_args_t * args); | ||
42 | static dev_info_t dev_info = "ixj_cs"; | ||
43 | static dev_link_t *dev_list = NULL; | ||
44 | 40 | ||
45 | static dev_link_t *ixj_attach(void) | 41 | static int ixj_attach(struct pcmcia_device *p_dev) |
46 | { | 42 | { |
47 | client_reg_t client_reg; | ||
48 | dev_link_t *link; | 43 | dev_link_t *link; |
49 | int ret; | 44 | |
50 | DEBUG(0, "ixj_attach()\n"); | 45 | DEBUG(0, "ixj_attach()\n"); |
51 | /* Create new ixj device */ | 46 | /* Create new ixj device */ |
52 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); | 47 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); |
53 | if (!link) | 48 | if (!link) |
54 | return NULL; | 49 | return -ENOMEM; |
55 | memset(link, 0, sizeof(struct dev_link_t)); | 50 | memset(link, 0, sizeof(struct dev_link_t)); |
56 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 51 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
57 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | 52 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; |
@@ -61,44 +56,29 @@ static dev_link_t *ixj_attach(void) | |||
61 | link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); | 56 | link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); |
62 | if (!link->priv) { | 57 | if (!link->priv) { |
63 | kfree(link); | 58 | kfree(link); |
64 | return NULL; | 59 | return -ENOMEM; |
65 | } | 60 | } |
66 | memset(link->priv, 0, sizeof(struct ixj_info_t)); | 61 | memset(link->priv, 0, sizeof(struct ixj_info_t)); |
67 | /* Register with Card Services */ | 62 | |
68 | link->next = dev_list; | 63 | link->handle = p_dev; |
69 | dev_list = link; | 64 | p_dev->instance = link; |
70 | client_reg.dev_info = &dev_info; | 65 | |
71 | client_reg.Version = 0x0210; | 66 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
72 | client_reg.event_callback_args.client_data = link; | 67 | ixj_config(link); |
73 | ret = pcmcia_register_client(&link->handle, &client_reg); | 68 | |
74 | if (ret != CS_SUCCESS) { | 69 | return 0; |
75 | cs_error(link->handle, RegisterClient, ret); | ||
76 | ixj_detach(link); | ||
77 | return NULL; | ||
78 | } | ||
79 | return link; | ||
80 | } | 70 | } |
81 | 71 | ||
82 | static void ixj_detach(dev_link_t * link) | 72 | static void ixj_detach(struct pcmcia_device *p_dev) |
83 | { | 73 | { |
84 | dev_link_t **linkp; | 74 | dev_link_t *link = dev_to_instance(p_dev); |
85 | int ret; | 75 | |
86 | DEBUG(0, "ixj_detach(0x%p)\n", link); | 76 | DEBUG(0, "ixj_detach(0x%p)\n", link); |
87 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | 77 | |
88 | if (*linkp == link) | ||
89 | break; | ||
90 | if (*linkp == NULL) | ||
91 | return; | ||
92 | link->state &= ~DEV_RELEASE_PENDING; | 78 | link->state &= ~DEV_RELEASE_PENDING; |
93 | if (link->state & DEV_CONFIG) | 79 | if (link->state & DEV_CONFIG) |
94 | ixj_cs_release(link); | 80 | ixj_cs_release(link); |
95 | if (link->handle) { | 81 | |
96 | ret = pcmcia_deregister_client(link->handle); | ||
97 | if (ret != CS_SUCCESS) | ||
98 | cs_error(link->handle, DeregisterClient, ret); | ||
99 | } | ||
100 | /* Unlink device structure, free bits */ | ||
101 | *linkp = link->next; | ||
102 | kfree(link->priv); | 82 | kfree(link->priv); |
103 | kfree(link); | 83 | kfree(link); |
104 | } | 84 | } |
@@ -255,37 +235,25 @@ static void ixj_cs_release(dev_link_t *link) | |||
255 | link->state &= ~DEV_CONFIG; | 235 | link->state &= ~DEV_CONFIG; |
256 | } | 236 | } |
257 | 237 | ||
258 | static int ixj_event(event_t event, int priority, event_callback_args_t * args) | 238 | static int ixj_suspend(struct pcmcia_device *dev) |
259 | { | 239 | { |
260 | dev_link_t *link = args->client_data; | 240 | dev_link_t *link = dev_to_instance(dev); |
261 | DEBUG(1, "ixj_event(0x%06x)\n", event); | 241 | |
262 | switch (event) { | 242 | link->state |= DEV_SUSPEND; |
263 | case CS_EVENT_CARD_REMOVAL: | 243 | if (link->state & DEV_CONFIG) |
264 | link->state &= ~DEV_PRESENT; | 244 | pcmcia_release_configuration(link->handle); |
265 | if (link->state & DEV_CONFIG) { | 245 | |
266 | link->state |= DEV_RELEASE_PENDING; | 246 | return 0; |
267 | ixj_cs_release(link); | 247 | } |
268 | } | 248 | |
269 | break; | 249 | static int ixj_resume(struct pcmcia_device *dev) |
270 | case CS_EVENT_CARD_INSERTION: | 250 | { |
271 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 251 | dev_link_t *link = dev_to_instance(dev); |
272 | ixj_config(link); | 252 | |
273 | break; | 253 | link->state &= ~DEV_SUSPEND; |
274 | case CS_EVENT_PM_SUSPEND: | 254 | if (DEV_OK(link)) |
275 | link->state |= DEV_SUSPEND; | 255 | pcmcia_request_configuration(link->handle, &link->conf); |
276 | /* Fall through... */ | 256 | |
277 | case CS_EVENT_RESET_PHYSICAL: | ||
278 | if (link->state & DEV_CONFIG) | ||
279 | pcmcia_release_configuration(link->handle); | ||
280 | break; | ||
281 | case CS_EVENT_PM_RESUME: | ||
282 | link->state &= ~DEV_SUSPEND; | ||
283 | /* Fall through... */ | ||
284 | case CS_EVENT_CARD_RESET: | ||
285 | if (DEV_OK(link)) | ||
286 | pcmcia_request_configuration(link->handle, &link->conf); | ||
287 | break; | ||
288 | } | ||
289 | return 0; | 257 | return 0; |
290 | } | 258 | } |
291 | 259 | ||
@@ -300,10 +268,11 @@ static struct pcmcia_driver ixj_driver = { | |||
300 | .drv = { | 268 | .drv = { |
301 | .name = "ixj_cs", | 269 | .name = "ixj_cs", |
302 | }, | 270 | }, |
303 | .attach = ixj_attach, | 271 | .probe = ixj_attach, |
304 | .event = ixj_event, | 272 | .remove = ixj_detach, |
305 | .detach = ixj_detach, | ||
306 | .id_table = ixj_ids, | 273 | .id_table = ixj_ids, |
274 | .suspend = ixj_suspend, | ||
275 | .resume = ixj_resume, | ||
307 | }; | 276 | }; |
308 | 277 | ||
309 | static int __init ixj_pcmcia_init(void) | 278 | static int __init ixj_pcmcia_init(void) |
@@ -314,7 +283,6 @@ static int __init ixj_pcmcia_init(void) | |||
314 | static void ixj_pcmcia_exit(void) | 283 | static void ixj_pcmcia_exit(void) |
315 | { | 284 | { |
316 | pcmcia_unregister_driver(&ixj_driver); | 285 | pcmcia_unregister_driver(&ixj_driver); |
317 | BUG_ON(dev_list != NULL); | ||
318 | } | 286 | } |
319 | 287 | ||
320 | module_init(ixj_pcmcia_init); | 288 | module_init(ixj_pcmcia_init); |