diff options
Diffstat (limited to 'drivers/net/pcmcia/ibmtr_cs.c')
-rw-r--r-- | drivers/net/pcmcia/ibmtr_cs.c | 152 |
1 files changed, 47 insertions, 105 deletions
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index b6c140eb9799..b9c7e39576f5 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c | |||
@@ -108,15 +108,7 @@ MODULE_LICENSE("GPL"); | |||
108 | static void ibmtr_config(dev_link_t *link); | 108 | static void ibmtr_config(dev_link_t *link); |
109 | static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); | 109 | static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); |
110 | static void ibmtr_release(dev_link_t *link); | 110 | static void ibmtr_release(dev_link_t *link); |
111 | static int ibmtr_event(event_t event, int priority, | 111 | static void ibmtr_detach(struct pcmcia_device *p_dev); |
112 | event_callback_args_t *args); | ||
113 | |||
114 | static dev_info_t dev_info = "ibmtr_cs"; | ||
115 | |||
116 | static dev_link_t *ibmtr_attach(void); | ||
117 | static void ibmtr_detach(dev_link_t *); | ||
118 | |||
119 | static dev_link_t *dev_list; | ||
120 | 112 | ||
121 | /*====================================================================*/ | 113 | /*====================================================================*/ |
122 | 114 | ||
@@ -146,25 +138,23 @@ static struct ethtool_ops netdev_ethtool_ops = { | |||
146 | 138 | ||
147 | ======================================================================*/ | 139 | ======================================================================*/ |
148 | 140 | ||
149 | static dev_link_t *ibmtr_attach(void) | 141 | static int ibmtr_attach(struct pcmcia_device *p_dev) |
150 | { | 142 | { |
151 | ibmtr_dev_t *info; | 143 | ibmtr_dev_t *info; |
152 | dev_link_t *link; | 144 | dev_link_t *link; |
153 | struct net_device *dev; | 145 | struct net_device *dev; |
154 | client_reg_t client_reg; | ||
155 | int ret; | ||
156 | 146 | ||
157 | DEBUG(0, "ibmtr_attach()\n"); | 147 | DEBUG(0, "ibmtr_attach()\n"); |
158 | 148 | ||
159 | /* Create new token-ring device */ | 149 | /* Create new token-ring device */ |
160 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 150 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
161 | if (!info) return NULL; | 151 | if (!info) return -ENOMEM; |
162 | memset(info,0,sizeof(*info)); | 152 | memset(info,0,sizeof(*info)); |
163 | dev = alloc_trdev(sizeof(struct tok_info)); | 153 | dev = alloc_trdev(sizeof(struct tok_info)); |
164 | if (!dev) { | 154 | if (!dev) { |
165 | kfree(info); | 155 | kfree(info); |
166 | return NULL; | 156 | return -ENOMEM; |
167 | } | 157 | } |
168 | 158 | ||
169 | link = &info->link; | 159 | link = &info->link; |
170 | link->priv = info; | 160 | link->priv = info; |
@@ -185,25 +175,13 @@ static dev_link_t *ibmtr_attach(void) | |||
185 | 175 | ||
186 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 176 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
187 | 177 | ||
188 | /* Register with Card Services */ | 178 | link->handle = p_dev; |
189 | link->next = dev_list; | 179 | p_dev->instance = link; |
190 | dev_list = link; | ||
191 | client_reg.dev_info = &dev_info; | ||
192 | client_reg.Version = 0x0210; | ||
193 | client_reg.event_callback_args.client_data = link; | ||
194 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
195 | if (ret != 0) { | ||
196 | cs_error(link->handle, RegisterClient, ret); | ||
197 | goto out_detach; | ||
198 | } | ||
199 | 180 | ||
200 | out: | 181 | link->state |= DEV_PRESENT; |
201 | return link; | 182 | ibmtr_config(link); |
202 | 183 | ||
203 | out_detach: | 184 | return 0; |
204 | ibmtr_detach(link); | ||
205 | link = NULL; | ||
206 | goto out; | ||
207 | } /* ibmtr_attach */ | 185 | } /* ibmtr_attach */ |
208 | 186 | ||
209 | /*====================================================================== | 187 | /*====================================================================== |
@@ -215,22 +193,14 @@ out_detach: | |||
215 | 193 | ||
216 | ======================================================================*/ | 194 | ======================================================================*/ |
217 | 195 | ||
218 | static void ibmtr_detach(dev_link_t *link) | 196 | static void ibmtr_detach(struct pcmcia_device *p_dev) |
219 | { | 197 | { |
198 | dev_link_t *link = dev_to_instance(p_dev); | ||
220 | struct ibmtr_dev_t *info = link->priv; | 199 | struct ibmtr_dev_t *info = link->priv; |
221 | dev_link_t **linkp; | 200 | struct net_device *dev = info->dev; |
222 | struct net_device *dev; | ||
223 | 201 | ||
224 | DEBUG(0, "ibmtr_detach(0x%p)\n", link); | 202 | DEBUG(0, "ibmtr_detach(0x%p)\n", link); |
225 | 203 | ||
226 | /* Locate device structure */ | ||
227 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
228 | if (*linkp == link) break; | ||
229 | if (*linkp == NULL) | ||
230 | return; | ||
231 | |||
232 | dev = info->dev; | ||
233 | |||
234 | if (link->dev) | 204 | if (link->dev) |
235 | unregister_netdev(dev); | 205 | unregister_netdev(dev); |
236 | 206 | ||
@@ -241,13 +211,8 @@ static void ibmtr_detach(dev_link_t *link) | |||
241 | if (link->state & DEV_CONFIG) | 211 | if (link->state & DEV_CONFIG) |
242 | ibmtr_release(link); | 212 | ibmtr_release(link); |
243 | 213 | ||
244 | if (link->handle) | ||
245 | pcmcia_deregister_client(link->handle); | ||
246 | |||
247 | /* Unlink device structure, free bits */ | ||
248 | *linkp = link->next; | ||
249 | free_netdev(dev); | 214 | free_netdev(dev); |
250 | kfree(info); | 215 | kfree(info); |
251 | } /* ibmtr_detach */ | 216 | } /* ibmtr_detach */ |
252 | 217 | ||
253 | /*====================================================================== | 218 | /*====================================================================== |
@@ -401,63 +366,40 @@ static void ibmtr_release(dev_link_t *link) | |||
401 | link->state &= ~DEV_CONFIG; | 366 | link->state &= ~DEV_CONFIG; |
402 | } | 367 | } |
403 | 368 | ||
404 | /*====================================================================== | 369 | static int ibmtr_suspend(struct pcmcia_device *p_dev) |
370 | { | ||
371 | dev_link_t *link = dev_to_instance(p_dev); | ||
372 | ibmtr_dev_t *info = link->priv; | ||
373 | struct net_device *dev = info->dev; | ||
405 | 374 | ||
406 | The card status event handler. Mostly, this schedules other | 375 | link->state |= DEV_SUSPEND; |
407 | stuff to run after an event is received. A CARD_REMOVAL event | 376 | if (link->state & DEV_CONFIG) { |
408 | also sets some flags to discourage the net drivers from trying | 377 | if (link->open) |
409 | to talk to the card any more. | 378 | netif_device_detach(dev); |
379 | pcmcia_release_configuration(link->handle); | ||
380 | } | ||
410 | 381 | ||
411 | ======================================================================*/ | 382 | return 0; |
383 | } | ||
412 | 384 | ||
413 | static int ibmtr_event(event_t event, int priority, | 385 | static int ibmtr_resume(struct pcmcia_device *p_dev) |
414 | event_callback_args_t *args) | ||
415 | { | 386 | { |
416 | dev_link_t *link = args->client_data; | 387 | dev_link_t *link = dev_to_instance(p_dev); |
417 | ibmtr_dev_t *info = link->priv; | 388 | ibmtr_dev_t *info = link->priv; |
418 | struct net_device *dev = info->dev; | 389 | struct net_device *dev = info->dev; |
419 | 390 | ||
420 | DEBUG(1, "ibmtr_event(0x%06x)\n", event); | 391 | link->state &= ~DEV_SUSPEND; |
421 | |||
422 | switch (event) { | ||
423 | case CS_EVENT_CARD_REMOVAL: | ||
424 | link->state &= ~DEV_PRESENT; | ||
425 | if (link->state & DEV_CONFIG) { | ||
426 | /* set flag to bypass normal interrupt code */ | ||
427 | struct tok_info *priv = netdev_priv(dev); | ||
428 | priv->sram_phys |= 1; | ||
429 | netif_device_detach(dev); | ||
430 | } | ||
431 | break; | ||
432 | case CS_EVENT_CARD_INSERTION: | ||
433 | link->state |= DEV_PRESENT; | ||
434 | ibmtr_config(link); | ||
435 | break; | ||
436 | case CS_EVENT_PM_SUSPEND: | ||
437 | link->state |= DEV_SUSPEND; | ||
438 | /* Fall through... */ | ||
439 | case CS_EVENT_RESET_PHYSICAL: | ||
440 | if (link->state & DEV_CONFIG) { | 392 | if (link->state & DEV_CONFIG) { |
441 | if (link->open) | 393 | pcmcia_request_configuration(link->handle, &link->conf); |
442 | netif_device_detach(dev); | 394 | if (link->open) { |
443 | pcmcia_release_configuration(link->handle); | 395 | ibmtr_probe(dev); /* really? */ |
396 | netif_device_attach(dev); | ||
397 | } | ||
444 | } | 398 | } |
445 | break; | 399 | |
446 | case CS_EVENT_PM_RESUME: | 400 | return 0; |
447 | link->state &= ~DEV_SUSPEND; | 401 | } |
448 | /* Fall through... */ | 402 | |
449 | case CS_EVENT_CARD_RESET: | ||
450 | if (link->state & DEV_CONFIG) { | ||
451 | pcmcia_request_configuration(link->handle, &link->conf); | ||
452 | if (link->open) { | ||
453 | ibmtr_probe(dev); /* really? */ | ||
454 | netif_device_attach(dev); | ||
455 | } | ||
456 | } | ||
457 | break; | ||
458 | } | ||
459 | return 0; | ||
460 | } /* ibmtr_event */ | ||
461 | 403 | ||
462 | /*====================================================================*/ | 404 | /*====================================================================*/ |
463 | 405 | ||
@@ -514,10 +456,11 @@ static struct pcmcia_driver ibmtr_cs_driver = { | |||
514 | .drv = { | 456 | .drv = { |
515 | .name = "ibmtr_cs", | 457 | .name = "ibmtr_cs", |
516 | }, | 458 | }, |
517 | .attach = ibmtr_attach, | 459 | .probe = ibmtr_attach, |
518 | .event = ibmtr_event, | 460 | .remove = ibmtr_detach, |
519 | .detach = ibmtr_detach, | ||
520 | .id_table = ibmtr_ids, | 461 | .id_table = ibmtr_ids, |
462 | .suspend = ibmtr_suspend, | ||
463 | .resume = ibmtr_resume, | ||
521 | }; | 464 | }; |
522 | 465 | ||
523 | static int __init init_ibmtr_cs(void) | 466 | static int __init init_ibmtr_cs(void) |
@@ -528,7 +471,6 @@ static int __init init_ibmtr_cs(void) | |||
528 | static void __exit exit_ibmtr_cs(void) | 471 | static void __exit exit_ibmtr_cs(void) |
529 | { | 472 | { |
530 | pcmcia_unregister_driver(&ibmtr_cs_driver); | 473 | pcmcia_unregister_driver(&ibmtr_cs_driver); |
531 | BUG_ON(dev_list != NULL); | ||
532 | } | 474 | } |
533 | 475 | ||
534 | module_init(init_ibmtr_cs); | 476 | module_init(init_ibmtr_cs); |