diff options
Diffstat (limited to 'drivers/net/wireless/airo_cs.c')
-rw-r--r-- | drivers/net/wireless/airo_cs.c | 161 |
1 files changed, 46 insertions, 115 deletions
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index e328547599dc..a496460ce224 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
@@ -82,8 +82,6 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); | |||
82 | 82 | ||
83 | static void airo_config(dev_link_t *link); | 83 | static void airo_config(dev_link_t *link); |
84 | static void airo_release(dev_link_t *link); | 84 | static void airo_release(dev_link_t *link); |
85 | static int airo_event(event_t event, int priority, | ||
86 | event_callback_args_t *args); | ||
87 | 85 | ||
88 | /* | 86 | /* |
89 | The attach() and detach() entry points are used to create and destroy | 87 | The attach() and detach() entry points are used to create and destroy |
@@ -91,8 +89,7 @@ static int airo_event(event_t event, int priority, | |||
91 | needed to manage one actual PCMCIA card. | 89 | needed to manage one actual PCMCIA card. |
92 | */ | 90 | */ |
93 | 91 | ||
94 | static dev_link_t *airo_attach(void); | 92 | static void airo_detach(struct pcmcia_device *p_dev); |
95 | static void airo_detach(dev_link_t *); | ||
96 | 93 | ||
97 | /* | 94 | /* |
98 | You'll also need to prototype all the functions that will actually | 95 | You'll also need to prototype all the functions that will actually |
@@ -102,14 +99,6 @@ static void airo_detach(dev_link_t *); | |||
102 | */ | 99 | */ |
103 | 100 | ||
104 | /* | 101 | /* |
105 | The dev_info variable is the "key" that is used to match up this | ||
106 | device driver with appropriate cards, through the card configuration | ||
107 | database. | ||
108 | */ | ||
109 | |||
110 | static dev_info_t dev_info = "airo_cs"; | ||
111 | |||
112 | /* | ||
113 | A linked list of "instances" of the aironet device. Each actual | 102 | A linked list of "instances" of the aironet device. Each actual |
114 | PCMCIA card corresponds to one device instance, and is described | 103 | PCMCIA card corresponds to one device instance, and is described |
115 | by one dev_link_t structure (defined in ds.h). | 104 | by one dev_link_t structure (defined in ds.h). |
@@ -119,15 +108,7 @@ static dev_info_t dev_info = "airo_cs"; | |||
119 | device numbers are used to derive the corresponding array index. | 108 | device numbers are used to derive the corresponding array index. |
120 | */ | 109 | */ |
121 | 110 | ||
122 | static dev_link_t *dev_list = NULL; | ||
123 | |||
124 | /* | 111 | /* |
125 | A dev_link_t structure has fields for most things that are needed | ||
126 | to keep track of a socket, but there will usually be some device | ||
127 | specific information that also needs to be kept track of. The | ||
128 | 'priv' pointer in a dev_link_t structure can be used to point to | ||
129 | a device-specific private data structure, like this. | ||
130 | |||
131 | A driver needs to provide a dev_node_t structure for each device | 112 | A driver needs to provide a dev_node_t structure for each device |
132 | on a card. In some cases, there is only one device per card (for | 113 | on a card. In some cases, there is only one device per card (for |
133 | example, ethernet cards, modems). In other cases, there may be | 114 | example, ethernet cards, modems). In other cases, there may be |
@@ -160,20 +141,18 @@ typedef struct local_info_t { | |||
160 | 141 | ||
161 | ======================================================================*/ | 142 | ======================================================================*/ |
162 | 143 | ||
163 | static dev_link_t *airo_attach(void) | 144 | static int airo_attach(struct pcmcia_device *p_dev) |
164 | { | 145 | { |
165 | client_reg_t client_reg; | ||
166 | dev_link_t *link; | 146 | dev_link_t *link; |
167 | local_info_t *local; | 147 | local_info_t *local; |
168 | int ret; | 148 | |
169 | |||
170 | DEBUG(0, "airo_attach()\n"); | 149 | DEBUG(0, "airo_attach()\n"); |
171 | 150 | ||
172 | /* Initialize the dev_link_t structure */ | 151 | /* Initialize the dev_link_t structure */ |
173 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | 152 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); |
174 | if (!link) { | 153 | if (!link) { |
175 | printk(KERN_ERR "airo_cs: no memory for new device\n"); | 154 | printk(KERN_ERR "airo_cs: no memory for new device\n"); |
176 | return NULL; | 155 | return -ENOMEM; |
177 | } | 156 | } |
178 | 157 | ||
179 | /* Interrupt setup */ | 158 | /* Interrupt setup */ |
@@ -197,24 +176,17 @@ static dev_link_t *airo_attach(void) | |||
197 | if (!local) { | 176 | if (!local) { |
198 | printk(KERN_ERR "airo_cs: no memory for new device\n"); | 177 | printk(KERN_ERR "airo_cs: no memory for new device\n"); |
199 | kfree (link); | 178 | kfree (link); |
200 | return NULL; | 179 | return -ENOMEM; |
201 | } | 180 | } |
202 | link->priv = local; | 181 | link->priv = local; |
203 | 182 | ||
204 | /* Register with Card Services */ | 183 | link->handle = p_dev; |
205 | link->next = dev_list; | 184 | p_dev->instance = link; |
206 | dev_list = link; | 185 | |
207 | client_reg.dev_info = &dev_info; | 186 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
208 | client_reg.Version = 0x0210; | 187 | airo_config(link); |
209 | client_reg.event_callback_args.client_data = link; | 188 | |
210 | ret = pcmcia_register_client(&link->handle, &client_reg); | 189 | return 0; |
211 | if (ret != 0) { | ||
212 | cs_error(link->handle, RegisterClient, ret); | ||
213 | airo_detach(link); | ||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | return link; | ||
218 | } /* airo_attach */ | 190 | } /* airo_attach */ |
219 | 191 | ||
220 | /*====================================================================== | 192 | /*====================================================================== |
@@ -226,37 +198,22 @@ static dev_link_t *airo_attach(void) | |||
226 | 198 | ||
227 | ======================================================================*/ | 199 | ======================================================================*/ |
228 | 200 | ||
229 | static void airo_detach(dev_link_t *link) | 201 | static void airo_detach(struct pcmcia_device *p_dev) |
230 | { | 202 | { |
231 | dev_link_t **linkp; | 203 | dev_link_t *link = dev_to_instance(p_dev); |
232 | 204 | ||
233 | DEBUG(0, "airo_detach(0x%p)\n", link); | 205 | DEBUG(0, "airo_detach(0x%p)\n", link); |
234 | 206 | ||
235 | /* Locate device structure */ | ||
236 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
237 | if (*linkp == link) break; | ||
238 | if (*linkp == NULL) | ||
239 | return; | ||
240 | |||
241 | if (link->state & DEV_CONFIG) | 207 | if (link->state & DEV_CONFIG) |
242 | airo_release(link); | 208 | airo_release(link); |
243 | 209 | ||
244 | if ( ((local_info_t*)link->priv)->eth_dev ) { | 210 | if ( ((local_info_t*)link->priv)->eth_dev ) { |
245 | stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); | 211 | stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); |
246 | } | 212 | } |
247 | ((local_info_t*)link->priv)->eth_dev = NULL; | 213 | ((local_info_t*)link->priv)->eth_dev = NULL; |
248 | 214 | ||
249 | /* Break the link with Card Services */ | ||
250 | if (link->handle) | ||
251 | pcmcia_deregister_client(link->handle); | ||
252 | |||
253 | |||
254 | |||
255 | /* Unlink device structure, free pieces */ | ||
256 | *linkp = link->next; | ||
257 | kfree(link->priv); | 215 | kfree(link->priv); |
258 | kfree(link); | 216 | kfree(link); |
259 | |||
260 | } /* airo_detach */ | 217 | } /* airo_detach */ |
261 | 218 | ||
262 | /*====================================================================== | 219 | /*====================================================================== |
@@ -492,60 +449,34 @@ static void airo_release(dev_link_t *link) | |||
492 | link->state &= ~DEV_CONFIG; | 449 | link->state &= ~DEV_CONFIG; |
493 | } | 450 | } |
494 | 451 | ||
495 | /*====================================================================== | 452 | static int airo_suspend(struct pcmcia_device *p_dev) |
496 | 453 | { | |
497 | The card status event handler. Mostly, this schedules other | 454 | dev_link_t *link = dev_to_instance(p_dev); |
498 | stuff to run after an event is received. | 455 | local_info_t *local = link->priv; |
499 | 456 | ||
500 | When a CARD_REMOVAL event is received, we immediately set a | 457 | link->state |= DEV_SUSPEND; |
501 | private flag to block future accesses to this device. All the | 458 | if (link->state & DEV_CONFIG) { |
502 | functions that actually access the device should check this flag | 459 | netif_device_detach(local->eth_dev); |
503 | to make sure the card is still present. | 460 | pcmcia_release_configuration(link->handle); |
504 | 461 | } | |
505 | ======================================================================*/ | 462 | |
463 | return 0; | ||
464 | } | ||
506 | 465 | ||
507 | static int airo_event(event_t event, int priority, | 466 | static int airo_resume(struct pcmcia_device *p_dev) |
508 | event_callback_args_t *args) | ||
509 | { | 467 | { |
510 | dev_link_t *link = args->client_data; | 468 | dev_link_t *link = dev_to_instance(p_dev); |
511 | local_info_t *local = link->priv; | 469 | local_info_t *local = link->priv; |
512 | 470 | ||
513 | DEBUG(1, "airo_event(0x%06x)\n", event); | 471 | link->state &= ~DEV_SUSPEND; |
514 | 472 | if (link->state & DEV_CONFIG) { | |
515 | switch (event) { | 473 | pcmcia_request_configuration(link->handle, &link->conf); |
516 | case CS_EVENT_CARD_REMOVAL: | 474 | reset_airo_card(local->eth_dev); |
517 | link->state &= ~DEV_PRESENT; | 475 | netif_device_attach(local->eth_dev); |
518 | if (link->state & DEV_CONFIG) { | ||
519 | netif_device_detach(local->eth_dev); | ||
520 | airo_release(link); | ||
521 | } | ||
522 | break; | ||
523 | case CS_EVENT_CARD_INSERTION: | ||
524 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
525 | airo_config(link); | ||
526 | break; | ||
527 | case CS_EVENT_PM_SUSPEND: | ||
528 | link->state |= DEV_SUSPEND; | ||
529 | /* Fall through... */ | ||
530 | case CS_EVENT_RESET_PHYSICAL: | ||
531 | if (link->state & DEV_CONFIG) { | ||
532 | netif_device_detach(local->eth_dev); | ||
533 | pcmcia_release_configuration(link->handle); | ||
534 | } | ||
535 | break; | ||
536 | case CS_EVENT_PM_RESUME: | ||
537 | link->state &= ~DEV_SUSPEND; | ||
538 | /* Fall through... */ | ||
539 | case CS_EVENT_CARD_RESET: | ||
540 | if (link->state & DEV_CONFIG) { | ||
541 | pcmcia_request_configuration(link->handle, &link->conf); | ||
542 | reset_airo_card(local->eth_dev); | ||
543 | netif_device_attach(local->eth_dev); | ||
544 | } | ||
545 | break; | ||
546 | } | 476 | } |
477 | |||
547 | return 0; | 478 | return 0; |
548 | } /* airo_event */ | 479 | } |
549 | 480 | ||
550 | static struct pcmcia_device_id airo_ids[] = { | 481 | static struct pcmcia_device_id airo_ids[] = { |
551 | PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a), | 482 | PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a), |
@@ -561,10 +492,11 @@ static struct pcmcia_driver airo_driver = { | |||
561 | .drv = { | 492 | .drv = { |
562 | .name = "airo_cs", | 493 | .name = "airo_cs", |
563 | }, | 494 | }, |
564 | .attach = airo_attach, | 495 | .probe = airo_attach, |
565 | .event = airo_event, | 496 | .remove = airo_detach, |
566 | .detach = airo_detach, | ||
567 | .id_table = airo_ids, | 497 | .id_table = airo_ids, |
498 | .suspend = airo_suspend, | ||
499 | .resume = airo_resume, | ||
568 | }; | 500 | }; |
569 | 501 | ||
570 | static int airo_cs_init(void) | 502 | static int airo_cs_init(void) |
@@ -575,7 +507,6 @@ static int airo_cs_init(void) | |||
575 | static void airo_cs_cleanup(void) | 507 | static void airo_cs_cleanup(void) |
576 | { | 508 | { |
577 | pcmcia_unregister_driver(&airo_driver); | 509 | pcmcia_unregister_driver(&airo_driver); |
578 | BUG_ON(dev_list != NULL); | ||
579 | } | 510 | } |
580 | 511 | ||
581 | /* | 512 | /* |