diff options
author | Jody McIntyre <scjody@modernduck.com> | 2006-01-05 22:22:50 -0500 |
---|---|---|
committer | Jody McIntyre <scjody@modernduck.com> | 2006-01-05 22:22:50 -0500 |
commit | 52cab57873c25d3c8324ee3e4d463db6e8e73fd7 (patch) | |
tree | 826cb36827afa363944e6478d19512e669446c64 /drivers/net | |
parent | 0a75c23a009ff65f651532cecc16675d05f4de37 (diff) | |
parent | 46f25dffbaba48c571d75f5f574f31978287b8d2 (diff) |
Merge with http://kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/pcmcia/3c574_cs.c | 124 | ||||
-rw-r--r-- | drivers/net/pcmcia/3c589_cs.c | 136 | ||||
-rw-r--r-- | drivers/net/pcmcia/axnet_cs.c | 128 | ||||
-rw-r--r-- | drivers/net/pcmcia/com20020_cs.c | 142 | ||||
-rw-r--r-- | drivers/net/pcmcia/fmvj18x_cs.c | 128 | ||||
-rw-r--r-- | drivers/net/pcmcia/ibmtr_cs.c | 152 | ||||
-rw-r--r-- | drivers/net/pcmcia/nmclan_cs.c | 134 | ||||
-rw-r--r-- | drivers/net/pcmcia/pcnet_cs.c | 129 | ||||
-rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 195 | ||||
-rw-r--r-- | drivers/net/pcmcia/xirc2ps_cs.c | 158 | ||||
-rw-r--r-- | drivers/net/wireless/airo_cs.c | 161 | ||||
-rw-r--r-- | drivers/net/wireless/atmel_cs.c | 156 | ||||
-rw-r--r-- | drivers/net/wireless/hostap/hostap_cs.c | 156 | ||||
-rw-r--r-- | drivers/net/wireless/netwave_cs.c | 184 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco_cs.c | 208 | ||||
-rw-r--r-- | drivers/net/wireless/ray_cs.c | 154 | ||||
-rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 175 | ||||
-rw-r--r-- | drivers/net/wireless/wavelan_cs.c | 183 | ||||
-rw-r--r-- | drivers/net/wireless/wavelan_cs.p.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/wl3501_cs.c | 133 |
20 files changed, 940 insertions, 2007 deletions
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 71fd41122c91..48774efeec71 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c | |||
@@ -227,8 +227,6 @@ static char mii_preamble_required = 0; | |||
227 | 227 | ||
228 | static void tc574_config(dev_link_t *link); | 228 | static void tc574_config(dev_link_t *link); |
229 | static void tc574_release(dev_link_t *link); | 229 | static void tc574_release(dev_link_t *link); |
230 | static int tc574_event(event_t event, int priority, | ||
231 | event_callback_args_t *args); | ||
232 | 230 | ||
233 | static void mdio_sync(kio_addr_t ioaddr, int bits); | 231 | static void mdio_sync(kio_addr_t ioaddr, int bits); |
234 | static int mdio_read(kio_addr_t ioaddr, int phy_id, int location); | 232 | static int mdio_read(kio_addr_t ioaddr, int phy_id, int location); |
@@ -250,12 +248,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | |||
250 | static struct ethtool_ops netdev_ethtool_ops; | 248 | static struct ethtool_ops netdev_ethtool_ops; |
251 | static void set_rx_mode(struct net_device *dev); | 249 | static void set_rx_mode(struct net_device *dev); |
252 | 250 | ||
253 | static dev_info_t dev_info = "3c574_cs"; | 251 | static void tc574_detach(struct pcmcia_device *p_dev); |
254 | |||
255 | static dev_link_t *tc574_attach(void); | ||
256 | static void tc574_detach(dev_link_t *); | ||
257 | |||
258 | static dev_link_t *dev_list; | ||
259 | 252 | ||
260 | /* | 253 | /* |
261 | tc574_attach() creates an "instance" of the driver, allocating | 254 | tc574_attach() creates an "instance" of the driver, allocating |
@@ -263,20 +256,18 @@ static dev_link_t *dev_list; | |||
263 | with Card Services. | 256 | with Card Services. |
264 | */ | 257 | */ |
265 | 258 | ||
266 | static dev_link_t *tc574_attach(void) | 259 | static int tc574_attach(struct pcmcia_device *p_dev) |
267 | { | 260 | { |
268 | struct el3_private *lp; | 261 | struct el3_private *lp; |
269 | client_reg_t client_reg; | ||
270 | dev_link_t *link; | 262 | dev_link_t *link; |
271 | struct net_device *dev; | 263 | struct net_device *dev; |
272 | int ret; | ||
273 | 264 | ||
274 | DEBUG(0, "3c574_attach()\n"); | 265 | DEBUG(0, "3c574_attach()\n"); |
275 | 266 | ||
276 | /* Create the PC card device object. */ | 267 | /* Create the PC card device object. */ |
277 | dev = alloc_etherdev(sizeof(struct el3_private)); | 268 | dev = alloc_etherdev(sizeof(struct el3_private)); |
278 | if (!dev) | 269 | if (!dev) |
279 | return NULL; | 270 | return -ENOMEM; |
280 | lp = netdev_priv(dev); | 271 | lp = netdev_priv(dev); |
281 | link = &lp->link; | 272 | link = &lp->link; |
282 | link->priv = dev; | 273 | link->priv = dev; |
@@ -307,20 +298,13 @@ static dev_link_t *tc574_attach(void) | |||
307 | dev->watchdog_timeo = TX_TIMEOUT; | 298 | dev->watchdog_timeo = TX_TIMEOUT; |
308 | #endif | 299 | #endif |
309 | 300 | ||
310 | /* Register with Card Services */ | 301 | link->handle = p_dev; |
311 | link->next = dev_list; | 302 | p_dev->instance = link; |
312 | dev_list = link; | ||
313 | client_reg.dev_info = &dev_info; | ||
314 | client_reg.Version = 0x0210; | ||
315 | client_reg.event_callback_args.client_data = link; | ||
316 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
317 | if (ret != 0) { | ||
318 | cs_error(link->handle, RegisterClient, ret); | ||
319 | tc574_detach(link); | ||
320 | return NULL; | ||
321 | } | ||
322 | 303 | ||
323 | return link; | 304 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
305 | tc574_config(link); | ||
306 | |||
307 | return 0; | ||
324 | } /* tc574_attach */ | 308 | } /* tc574_attach */ |
325 | 309 | ||
326 | /* | 310 | /* |
@@ -332,30 +316,19 @@ static dev_link_t *tc574_attach(void) | |||
332 | 316 | ||
333 | */ | 317 | */ |
334 | 318 | ||
335 | static void tc574_detach(dev_link_t *link) | 319 | static void tc574_detach(struct pcmcia_device *p_dev) |
336 | { | 320 | { |
321 | dev_link_t *link = dev_to_instance(p_dev); | ||
337 | struct net_device *dev = link->priv; | 322 | struct net_device *dev = link->priv; |
338 | dev_link_t **linkp; | ||
339 | 323 | ||
340 | DEBUG(0, "3c574_detach(0x%p)\n", link); | 324 | DEBUG(0, "3c574_detach(0x%p)\n", link); |
341 | 325 | ||
342 | /* Locate device structure */ | ||
343 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
344 | if (*linkp == link) break; | ||
345 | if (*linkp == NULL) | ||
346 | return; | ||
347 | |||
348 | if (link->dev) | 326 | if (link->dev) |
349 | unregister_netdev(dev); | 327 | unregister_netdev(dev); |
350 | 328 | ||
351 | if (link->state & DEV_CONFIG) | 329 | if (link->state & DEV_CONFIG) |
352 | tc574_release(link); | 330 | tc574_release(link); |
353 | 331 | ||
354 | if (link->handle) | ||
355 | pcmcia_deregister_client(link->handle); | ||
356 | |||
357 | /* Unlink device structure, free bits */ | ||
358 | *linkp = link->next; | ||
359 | free_netdev(dev); | 332 | free_netdev(dev); |
360 | } /* tc574_detach */ | 333 | } /* tc574_detach */ |
361 | 334 | ||
@@ -547,56 +520,37 @@ static void tc574_release(dev_link_t *link) | |||
547 | link->state &= ~DEV_CONFIG; | 520 | link->state &= ~DEV_CONFIG; |
548 | } | 521 | } |
549 | 522 | ||
550 | /* | 523 | static int tc574_suspend(struct pcmcia_device *p_dev) |
551 | The card status event handler. Mostly, this schedules other | ||
552 | stuff to run after an event is received. A CARD_REMOVAL event | ||
553 | also sets some flags to discourage the net drivers from trying | ||
554 | to talk to the card any more. | ||
555 | */ | ||
556 | |||
557 | static int tc574_event(event_t event, int priority, | ||
558 | event_callback_args_t *args) | ||
559 | { | 524 | { |
560 | dev_link_t *link = args->client_data; | 525 | dev_link_t *link = dev_to_instance(p_dev); |
561 | struct net_device *dev = link->priv; | 526 | struct net_device *dev = link->priv; |
562 | 527 | ||
563 | DEBUG(1, "3c574_event(0x%06x)\n", event); | 528 | link->state |= DEV_SUSPEND; |
564 | 529 | if (link->state & DEV_CONFIG) { | |
565 | switch (event) { | 530 | if (link->open) |
566 | case CS_EVENT_CARD_REMOVAL: | ||
567 | link->state &= ~DEV_PRESENT; | ||
568 | if (link->state & DEV_CONFIG) | ||
569 | netif_device_detach(dev); | 531 | netif_device_detach(dev); |
570 | break; | 532 | pcmcia_release_configuration(link->handle); |
571 | case CS_EVENT_CARD_INSERTION: | 533 | } |
572 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 534 | |
573 | tc574_config(link); | 535 | return 0; |
574 | break; | 536 | } |
575 | case CS_EVENT_PM_SUSPEND: | 537 | |
576 | link->state |= DEV_SUSPEND; | 538 | static int tc574_resume(struct pcmcia_device *p_dev) |
577 | /* Fall through... */ | 539 | { |
578 | case CS_EVENT_RESET_PHYSICAL: | 540 | dev_link_t *link = dev_to_instance(p_dev); |
579 | if (link->state & DEV_CONFIG) { | 541 | struct net_device *dev = link->priv; |
580 | if (link->open) | 542 | |
581 | netif_device_detach(dev); | 543 | link->state &= ~DEV_SUSPEND; |
582 | pcmcia_release_configuration(link->handle); | 544 | if (link->state & DEV_CONFIG) { |
583 | } | 545 | pcmcia_request_configuration(link->handle, &link->conf); |
584 | break; | 546 | if (link->open) { |
585 | case CS_EVENT_PM_RESUME: | 547 | tc574_reset(dev); |
586 | link->state &= ~DEV_SUSPEND; | 548 | netif_device_attach(dev); |
587 | /* Fall through... */ | ||
588 | case CS_EVENT_CARD_RESET: | ||
589 | if (link->state & DEV_CONFIG) { | ||
590 | pcmcia_request_configuration(link->handle, &link->conf); | ||
591 | if (link->open) { | ||
592 | tc574_reset(dev); | ||
593 | netif_device_attach(dev); | ||
594 | } | ||
595 | } | 549 | } |
596 | break; | ||
597 | } | 550 | } |
551 | |||
598 | return 0; | 552 | return 0; |
599 | } /* tc574_event */ | 553 | } |
600 | 554 | ||
601 | static void dump_status(struct net_device *dev) | 555 | static void dump_status(struct net_device *dev) |
602 | { | 556 | { |
@@ -1292,10 +1246,11 @@ static struct pcmcia_driver tc574_driver = { | |||
1292 | .drv = { | 1246 | .drv = { |
1293 | .name = "3c574_cs", | 1247 | .name = "3c574_cs", |
1294 | }, | 1248 | }, |
1295 | .attach = tc574_attach, | 1249 | .probe = tc574_attach, |
1296 | .event = tc574_event, | 1250 | .remove = tc574_detach, |
1297 | .detach = tc574_detach, | ||
1298 | .id_table = tc574_ids, | 1251 | .id_table = tc574_ids, |
1252 | .suspend = tc574_suspend, | ||
1253 | .resume = tc574_resume, | ||
1299 | }; | 1254 | }; |
1300 | 1255 | ||
1301 | static int __init init_tc574(void) | 1256 | static int __init init_tc574(void) |
@@ -1306,7 +1261,6 @@ static int __init init_tc574(void) | |||
1306 | static void __exit exit_tc574(void) | 1261 | static void __exit exit_tc574(void) |
1307 | { | 1262 | { |
1308 | pcmcia_unregister_driver(&tc574_driver); | 1263 | pcmcia_unregister_driver(&tc574_driver); |
1309 | BUG_ON(dev_list != NULL); | ||
1310 | } | 1264 | } |
1311 | 1265 | ||
1312 | module_init(init_tc574); | 1266 | module_init(init_tc574); |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index d83fdd8c1943..1c3c9c666f74 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -143,8 +143,6 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; | |||
143 | 143 | ||
144 | static void tc589_config(dev_link_t *link); | 144 | static void tc589_config(dev_link_t *link); |
145 | static void tc589_release(dev_link_t *link); | 145 | static void tc589_release(dev_link_t *link); |
146 | static int tc589_event(event_t event, int priority, | ||
147 | event_callback_args_t *args); | ||
148 | 146 | ||
149 | static u16 read_eeprom(kio_addr_t ioaddr, int index); | 147 | static u16 read_eeprom(kio_addr_t ioaddr, int index); |
150 | static void tc589_reset(struct net_device *dev); | 148 | static void tc589_reset(struct net_device *dev); |
@@ -161,12 +159,7 @@ static void el3_tx_timeout(struct net_device *dev); | |||
161 | static void set_multicast_list(struct net_device *dev); | 159 | static void set_multicast_list(struct net_device *dev); |
162 | static struct ethtool_ops netdev_ethtool_ops; | 160 | static struct ethtool_ops netdev_ethtool_ops; |
163 | 161 | ||
164 | static dev_info_t dev_info = "3c589_cs"; | 162 | static void tc589_detach(struct pcmcia_device *p_dev); |
165 | |||
166 | static dev_link_t *tc589_attach(void); | ||
167 | static void tc589_detach(dev_link_t *); | ||
168 | |||
169 | static dev_link_t *dev_list; | ||
170 | 163 | ||
171 | /*====================================================================== | 164 | /*====================================================================== |
172 | 165 | ||
@@ -176,20 +169,18 @@ static dev_link_t *dev_list; | |||
176 | 169 | ||
177 | ======================================================================*/ | 170 | ======================================================================*/ |
178 | 171 | ||
179 | static dev_link_t *tc589_attach(void) | 172 | static int tc589_attach(struct pcmcia_device *p_dev) |
180 | { | 173 | { |
181 | struct el3_private *lp; | 174 | struct el3_private *lp; |
182 | client_reg_t client_reg; | ||
183 | dev_link_t *link; | 175 | dev_link_t *link; |
184 | struct net_device *dev; | 176 | struct net_device *dev; |
185 | int ret; | ||
186 | 177 | ||
187 | DEBUG(0, "3c589_attach()\n"); | 178 | DEBUG(0, "3c589_attach()\n"); |
188 | 179 | ||
189 | /* Create new ethernet device */ | 180 | /* Create new ethernet device */ |
190 | dev = alloc_etherdev(sizeof(struct el3_private)); | 181 | dev = alloc_etherdev(sizeof(struct el3_private)); |
191 | if (!dev) | 182 | if (!dev) |
192 | return NULL; | 183 | return -ENOMEM; |
193 | lp = netdev_priv(dev); | 184 | lp = netdev_priv(dev); |
194 | link = &lp->link; | 185 | link = &lp->link; |
195 | link->priv = dev; | 186 | link->priv = dev; |
@@ -206,7 +197,7 @@ static dev_link_t *tc589_attach(void) | |||
206 | link->conf.IntType = INT_MEMORY_AND_IO; | 197 | link->conf.IntType = INT_MEMORY_AND_IO; |
207 | link->conf.ConfigIndex = 1; | 198 | link->conf.ConfigIndex = 1; |
208 | link->conf.Present = PRESENT_OPTION; | 199 | link->conf.Present = PRESENT_OPTION; |
209 | 200 | ||
210 | /* The EL3-specific entries in the device structure. */ | 201 | /* The EL3-specific entries in the device structure. */ |
211 | SET_MODULE_OWNER(dev); | 202 | SET_MODULE_OWNER(dev); |
212 | dev->hard_start_xmit = &el3_start_xmit; | 203 | dev->hard_start_xmit = &el3_start_xmit; |
@@ -221,20 +212,13 @@ static dev_link_t *tc589_attach(void) | |||
221 | #endif | 212 | #endif |
222 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 213 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
223 | 214 | ||
224 | /* Register with Card Services */ | 215 | link->handle = p_dev; |
225 | link->next = dev_list; | 216 | p_dev->instance = link; |
226 | dev_list = link; | 217 | |
227 | client_reg.dev_info = &dev_info; | 218 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
228 | client_reg.Version = 0x0210; | 219 | tc589_config(link); |
229 | client_reg.event_callback_args.client_data = link; | 220 | |
230 | ret = pcmcia_register_client(&link->handle, &client_reg); | 221 | return 0; |
231 | if (ret != 0) { | ||
232 | cs_error(link->handle, RegisterClient, ret); | ||
233 | tc589_detach(link); | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | return link; | ||
238 | } /* tc589_attach */ | 222 | } /* tc589_attach */ |
239 | 223 | ||
240 | /*====================================================================== | 224 | /*====================================================================== |
@@ -246,30 +230,19 @@ static dev_link_t *tc589_attach(void) | |||
246 | 230 | ||
247 | ======================================================================*/ | 231 | ======================================================================*/ |
248 | 232 | ||
249 | static void tc589_detach(dev_link_t *link) | 233 | static void tc589_detach(struct pcmcia_device *p_dev) |
250 | { | 234 | { |
235 | dev_link_t *link = dev_to_instance(p_dev); | ||
251 | struct net_device *dev = link->priv; | 236 | struct net_device *dev = link->priv; |
252 | dev_link_t **linkp; | 237 | |
253 | |||
254 | DEBUG(0, "3c589_detach(0x%p)\n", link); | 238 | DEBUG(0, "3c589_detach(0x%p)\n", link); |
255 | |||
256 | /* Locate device structure */ | ||
257 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
258 | if (*linkp == link) break; | ||
259 | if (*linkp == NULL) | ||
260 | return; | ||
261 | 239 | ||
262 | if (link->dev) | 240 | if (link->dev) |
263 | unregister_netdev(dev); | 241 | unregister_netdev(dev); |
264 | 242 | ||
265 | if (link->state & DEV_CONFIG) | 243 | if (link->state & DEV_CONFIG) |
266 | tc589_release(link); | 244 | tc589_release(link); |
267 | 245 | ||
268 | if (link->handle) | ||
269 | pcmcia_deregister_client(link->handle); | ||
270 | |||
271 | /* Unlink device structure, free bits */ | ||
272 | *linkp = link->next; | ||
273 | free_netdev(dev); | 246 | free_netdev(dev); |
274 | } /* tc589_detach */ | 247 | } /* tc589_detach */ |
275 | 248 | ||
@@ -421,58 +394,37 @@ static void tc589_release(dev_link_t *link) | |||
421 | link->state &= ~DEV_CONFIG; | 394 | link->state &= ~DEV_CONFIG; |
422 | } | 395 | } |
423 | 396 | ||
424 | /*====================================================================== | 397 | static int tc589_suspend(struct pcmcia_device *p_dev) |
425 | |||
426 | The card status event handler. Mostly, this schedules other | ||
427 | stuff to run after an event is received. A CARD_REMOVAL event | ||
428 | also sets some flags to discourage the net drivers from trying | ||
429 | to talk to the card any more. | ||
430 | |||
431 | ======================================================================*/ | ||
432 | |||
433 | static int tc589_event(event_t event, int priority, | ||
434 | event_callback_args_t *args) | ||
435 | { | 398 | { |
436 | dev_link_t *link = args->client_data; | 399 | dev_link_t *link = dev_to_instance(p_dev); |
437 | struct net_device *dev = link->priv; | 400 | struct net_device *dev = link->priv; |
438 | 401 | ||
439 | DEBUG(1, "3c589_event(0x%06x)\n", event); | ||
440 | |||
441 | switch (event) { | ||
442 | case CS_EVENT_CARD_REMOVAL: | ||
443 | link->state &= ~DEV_PRESENT; | ||
444 | if (link->state & DEV_CONFIG) | ||
445 | netif_device_detach(dev); | ||
446 | break; | ||
447 | case CS_EVENT_CARD_INSERTION: | ||
448 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
449 | tc589_config(link); | ||
450 | break; | ||
451 | case CS_EVENT_PM_SUSPEND: | ||
452 | link->state |= DEV_SUSPEND; | 402 | link->state |= DEV_SUSPEND; |
453 | /* Fall through... */ | ||
454 | case CS_EVENT_RESET_PHYSICAL: | ||
455 | if (link->state & DEV_CONFIG) { | 403 | if (link->state & DEV_CONFIG) { |
456 | if (link->open) | 404 | if (link->open) |
457 | netif_device_detach(dev); | 405 | netif_device_detach(dev); |
458 | pcmcia_release_configuration(link->handle); | 406 | pcmcia_release_configuration(link->handle); |
459 | } | 407 | } |
460 | break; | 408 | |
461 | case CS_EVENT_PM_RESUME: | 409 | return 0; |
410 | } | ||
411 | |||
412 | static int tc589_resume(struct pcmcia_device *p_dev) | ||
413 | { | ||
414 | dev_link_t *link = dev_to_instance(p_dev); | ||
415 | struct net_device *dev = link->priv; | ||
416 | |||
462 | link->state &= ~DEV_SUSPEND; | 417 | link->state &= ~DEV_SUSPEND; |
463 | /* Fall through... */ | ||
464 | case CS_EVENT_CARD_RESET: | ||
465 | if (link->state & DEV_CONFIG) { | 418 | if (link->state & DEV_CONFIG) { |
466 | pcmcia_request_configuration(link->handle, &link->conf); | 419 | pcmcia_request_configuration(link->handle, &link->conf); |
467 | if (link->open) { | 420 | if (link->open) { |
468 | tc589_reset(dev); | 421 | tc589_reset(dev); |
469 | netif_device_attach(dev); | 422 | netif_device_attach(dev); |
470 | } | 423 | } |
471 | } | 424 | } |
472 | break; | 425 | |
473 | } | 426 | return 0; |
474 | return 0; | 427 | } |
475 | } /* tc589_event */ | ||
476 | 428 | ||
477 | /*====================================================================*/ | 429 | /*====================================================================*/ |
478 | 430 | ||
@@ -1067,10 +1019,11 @@ static struct pcmcia_driver tc589_driver = { | |||
1067 | .drv = { | 1019 | .drv = { |
1068 | .name = "3c589_cs", | 1020 | .name = "3c589_cs", |
1069 | }, | 1021 | }, |
1070 | .attach = tc589_attach, | 1022 | .probe = tc589_attach, |
1071 | .event = tc589_event, | 1023 | .remove = tc589_detach, |
1072 | .detach = tc589_detach, | ||
1073 | .id_table = tc589_ids, | 1024 | .id_table = tc589_ids, |
1025 | .suspend = tc589_suspend, | ||
1026 | .resume = tc589_resume, | ||
1074 | }; | 1027 | }; |
1075 | 1028 | ||
1076 | static int __init init_tc589(void) | 1029 | static int __init init_tc589(void) |
@@ -1081,7 +1034,6 @@ static int __init init_tc589(void) | |||
1081 | static void __exit exit_tc589(void) | 1034 | static void __exit exit_tc589(void) |
1082 | { | 1035 | { |
1083 | pcmcia_unregister_driver(&tc589_driver); | 1036 | pcmcia_unregister_driver(&tc589_driver); |
1084 | BUG_ON(dev_list != NULL); | ||
1085 | } | 1037 | } |
1086 | 1038 | ||
1087 | module_init(init_tc589); | 1039 | module_init(init_tc589); |
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 8bb4e85689ea..01ddfc8cce3f 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -87,8 +87,6 @@ static char *version = | |||
87 | 87 | ||
88 | static void axnet_config(dev_link_t *link); | 88 | static void axnet_config(dev_link_t *link); |
89 | static void axnet_release(dev_link_t *link); | 89 | static void axnet_release(dev_link_t *link); |
90 | static int axnet_event(event_t event, int priority, | ||
91 | event_callback_args_t *args); | ||
92 | static int axnet_open(struct net_device *dev); | 90 | static int axnet_open(struct net_device *dev); |
93 | static int axnet_close(struct net_device *dev); | 91 | static int axnet_close(struct net_device *dev); |
94 | static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 92 | static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
@@ -107,11 +105,7 @@ static void block_input(struct net_device *dev, int count, | |||
107 | static void block_output(struct net_device *dev, int count, | 105 | static void block_output(struct net_device *dev, int count, |
108 | const u_char *buf, const int start_page); | 106 | const u_char *buf, const int start_page); |
109 | 107 | ||
110 | static dev_link_t *axnet_attach(void); | 108 | static void axnet_detach(struct pcmcia_device *p_dev); |
111 | static void axnet_detach(dev_link_t *); | ||
112 | |||
113 | static dev_info_t dev_info = "axnet_cs"; | ||
114 | static dev_link_t *dev_list; | ||
115 | 109 | ||
116 | static void axdev_setup(struct net_device *dev); | 110 | static void axdev_setup(struct net_device *dev); |
117 | static void AX88190_init(struct net_device *dev, int startp); | 111 | static void AX88190_init(struct net_device *dev, int startp); |
@@ -147,13 +141,11 @@ static inline axnet_dev_t *PRIV(struct net_device *dev) | |||
147 | 141 | ||
148 | ======================================================================*/ | 142 | ======================================================================*/ |
149 | 143 | ||
150 | static dev_link_t *axnet_attach(void) | 144 | static int axnet_attach(struct pcmcia_device *p_dev) |
151 | { | 145 | { |
152 | axnet_dev_t *info; | 146 | axnet_dev_t *info; |
153 | dev_link_t *link; | 147 | dev_link_t *link; |
154 | struct net_device *dev; | 148 | struct net_device *dev; |
155 | client_reg_t client_reg; | ||
156 | int ret; | ||
157 | 149 | ||
158 | DEBUG(0, "axnet_attach()\n"); | 150 | DEBUG(0, "axnet_attach()\n"); |
159 | 151 | ||
@@ -161,7 +153,7 @@ static dev_link_t *axnet_attach(void) | |||
161 | "eth%d", axdev_setup); | 153 | "eth%d", axdev_setup); |
162 | 154 | ||
163 | if (!dev) | 155 | if (!dev) |
164 | return NULL; | 156 | return -ENOMEM; |
165 | 157 | ||
166 | info = PRIV(dev); | 158 | info = PRIV(dev); |
167 | link = &info->link; | 159 | link = &info->link; |
@@ -176,20 +168,13 @@ static dev_link_t *axnet_attach(void) | |||
176 | dev->do_ioctl = &axnet_ioctl; | 168 | dev->do_ioctl = &axnet_ioctl; |
177 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 169 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
178 | 170 | ||
179 | /* Register with Card Services */ | 171 | link->handle = p_dev; |
180 | link->next = dev_list; | 172 | p_dev->instance = link; |
181 | dev_list = link; | ||
182 | client_reg.dev_info = &dev_info; | ||
183 | client_reg.Version = 0x0210; | ||
184 | client_reg.event_callback_args.client_data = link; | ||
185 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
186 | if (ret != CS_SUCCESS) { | ||
187 | cs_error(link->handle, RegisterClient, ret); | ||
188 | axnet_detach(link); | ||
189 | return NULL; | ||
190 | } | ||
191 | 173 | ||
192 | return link; | 174 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
175 | axnet_config(link); | ||
176 | |||
177 | return 0; | ||
193 | } /* axnet_attach */ | 178 | } /* axnet_attach */ |
194 | 179 | ||
195 | /*====================================================================== | 180 | /*====================================================================== |
@@ -201,30 +186,19 @@ static dev_link_t *axnet_attach(void) | |||
201 | 186 | ||
202 | ======================================================================*/ | 187 | ======================================================================*/ |
203 | 188 | ||
204 | static void axnet_detach(dev_link_t *link) | 189 | static void axnet_detach(struct pcmcia_device *p_dev) |
205 | { | 190 | { |
191 | dev_link_t *link = dev_to_instance(p_dev); | ||
206 | struct net_device *dev = link->priv; | 192 | struct net_device *dev = link->priv; |
207 | dev_link_t **linkp; | ||
208 | 193 | ||
209 | DEBUG(0, "axnet_detach(0x%p)\n", link); | 194 | DEBUG(0, "axnet_detach(0x%p)\n", link); |
210 | 195 | ||
211 | /* Locate device structure */ | ||
212 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
213 | if (*linkp == link) break; | ||
214 | if (*linkp == NULL) | ||
215 | return; | ||
216 | |||
217 | if (link->dev) | 196 | if (link->dev) |
218 | unregister_netdev(dev); | 197 | unregister_netdev(dev); |
219 | 198 | ||
220 | if (link->state & DEV_CONFIG) | 199 | if (link->state & DEV_CONFIG) |
221 | axnet_release(link); | 200 | axnet_release(link); |
222 | 201 | ||
223 | if (link->handle) | ||
224 | pcmcia_deregister_client(link->handle); | ||
225 | |||
226 | /* Unlink device structure, free bits */ | ||
227 | *linkp = link->next; | ||
228 | free_netdev(dev); | 202 | free_netdev(dev); |
229 | } /* axnet_detach */ | 203 | } /* axnet_detach */ |
230 | 204 | ||
@@ -490,59 +464,39 @@ static void axnet_release(dev_link_t *link) | |||
490 | link->state &= ~DEV_CONFIG; | 464 | link->state &= ~DEV_CONFIG; |
491 | } | 465 | } |
492 | 466 | ||
493 | /*====================================================================== | 467 | static int axnet_suspend(struct pcmcia_device *p_dev) |
494 | |||
495 | The card status event handler. Mostly, this schedules other | ||
496 | stuff to run after an event is received. A CARD_REMOVAL event | ||
497 | also sets some flags to discourage the net drivers from trying | ||
498 | to talk to the card any more. | ||
499 | |||
500 | ======================================================================*/ | ||
501 | |||
502 | static int axnet_event(event_t event, int priority, | ||
503 | event_callback_args_t *args) | ||
504 | { | 468 | { |
505 | dev_link_t *link = args->client_data; | 469 | dev_link_t *link = dev_to_instance(p_dev); |
506 | struct net_device *dev = link->priv; | 470 | struct net_device *dev = link->priv; |
507 | 471 | ||
508 | DEBUG(2, "axnet_event(0x%06x)\n", event); | ||
509 | |||
510 | switch (event) { | ||
511 | case CS_EVENT_CARD_REMOVAL: | ||
512 | link->state &= ~DEV_PRESENT; | ||
513 | if (link->state & DEV_CONFIG) | ||
514 | netif_device_detach(dev); | ||
515 | break; | ||
516 | case CS_EVENT_CARD_INSERTION: | ||
517 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
518 | axnet_config(link); | ||
519 | break; | ||
520 | case CS_EVENT_PM_SUSPEND: | ||
521 | link->state |= DEV_SUSPEND; | 472 | link->state |= DEV_SUSPEND; |
522 | /* Fall through... */ | ||
523 | case CS_EVENT_RESET_PHYSICAL: | ||
524 | if (link->state & DEV_CONFIG) { | 473 | if (link->state & DEV_CONFIG) { |
525 | if (link->open) | 474 | if (link->open) |
526 | netif_device_detach(dev); | 475 | netif_device_detach(dev); |
527 | pcmcia_release_configuration(link->handle); | 476 | pcmcia_release_configuration(link->handle); |
528 | } | 477 | } |
529 | break; | 478 | |
530 | case CS_EVENT_PM_RESUME: | 479 | return 0; |
480 | } | ||
481 | |||
482 | static int axnet_resume(struct pcmcia_device *p_dev) | ||
483 | { | ||
484 | dev_link_t *link = dev_to_instance(p_dev); | ||
485 | struct net_device *dev = link->priv; | ||
486 | |||
531 | link->state &= ~DEV_SUSPEND; | 487 | link->state &= ~DEV_SUSPEND; |
532 | /* Fall through... */ | ||
533 | case CS_EVENT_CARD_RESET: | ||
534 | if (link->state & DEV_CONFIG) { | 488 | if (link->state & DEV_CONFIG) { |
535 | pcmcia_request_configuration(link->handle, &link->conf); | 489 | pcmcia_request_configuration(link->handle, &link->conf); |
536 | if (link->open) { | 490 | if (link->open) { |
537 | axnet_reset_8390(dev); | 491 | axnet_reset_8390(dev); |
538 | AX88190_init(dev, 1); | 492 | AX88190_init(dev, 1); |
539 | netif_device_attach(dev); | 493 | netif_device_attach(dev); |
540 | } | 494 | } |
541 | } | 495 | } |
542 | break; | 496 | |
543 | } | 497 | return 0; |
544 | return 0; | 498 | } |
545 | } /* axnet_event */ | 499 | |
546 | 500 | ||
547 | /*====================================================================== | 501 | /*====================================================================== |
548 | 502 | ||
@@ -616,7 +570,7 @@ static int axnet_open(struct net_device *dev) | |||
616 | 570 | ||
617 | link->open++; | 571 | link->open++; |
618 | 572 | ||
619 | request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev); | 573 | request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, "axnet_cs", dev); |
620 | 574 | ||
621 | info->link_status = 0x00; | 575 | info->link_status = 0x00; |
622 | init_timer(&info->watchdog); | 576 | init_timer(&info->watchdog); |
@@ -877,10 +831,11 @@ static struct pcmcia_driver axnet_cs_driver = { | |||
877 | .drv = { | 831 | .drv = { |
878 | .name = "axnet_cs", | 832 | .name = "axnet_cs", |
879 | }, | 833 | }, |
880 | .attach = axnet_attach, | 834 | .probe = axnet_attach, |
881 | .event = axnet_event, | 835 | .remove = axnet_detach, |
882 | .detach = axnet_detach, | ||
883 | .id_table = axnet_ids, | 836 | .id_table = axnet_ids, |
837 | .suspend = axnet_suspend, | ||
838 | .resume = axnet_resume, | ||
884 | }; | 839 | }; |
885 | 840 | ||
886 | static int __init init_axnet_cs(void) | 841 | static int __init init_axnet_cs(void) |
@@ -891,7 +846,6 @@ static int __init init_axnet_cs(void) | |||
891 | static void __exit exit_axnet_cs(void) | 846 | static void __exit exit_axnet_cs(void) |
892 | { | 847 | { |
893 | pcmcia_unregister_driver(&axnet_cs_driver); | 848 | pcmcia_unregister_driver(&axnet_cs_driver); |
894 | BUG_ON(dev_list != NULL); | ||
895 | } | 849 | } |
896 | 850 | ||
897 | module_init(init_axnet_cs); | 851 | module_init(init_axnet_cs); |
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index b9355d9498a3..2827a48ea37c 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c | |||
@@ -120,15 +120,8 @@ MODULE_LICENSE("GPL"); | |||
120 | 120 | ||
121 | static void com20020_config(dev_link_t *link); | 121 | static void com20020_config(dev_link_t *link); |
122 | static void com20020_release(dev_link_t *link); | 122 | static void com20020_release(dev_link_t *link); |
123 | static int com20020_event(event_t event, int priority, | ||
124 | event_callback_args_t *args); | ||
125 | 123 | ||
126 | static dev_info_t dev_info = "com20020_cs"; | 124 | static void com20020_detach(struct pcmcia_device *p_dev); |
127 | |||
128 | static dev_link_t *com20020_attach(void); | ||
129 | static void com20020_detach(dev_link_t *); | ||
130 | |||
131 | static dev_link_t *dev_list; | ||
132 | 125 | ||
133 | /*====================================================================*/ | 126 | /*====================================================================*/ |
134 | 127 | ||
@@ -145,21 +138,19 @@ typedef struct com20020_dev_t { | |||
145 | 138 | ||
146 | ======================================================================*/ | 139 | ======================================================================*/ |
147 | 140 | ||
148 | static dev_link_t *com20020_attach(void) | 141 | static int com20020_attach(struct pcmcia_device *p_dev) |
149 | { | 142 | { |
150 | client_reg_t client_reg; | ||
151 | dev_link_t *link; | 143 | dev_link_t *link; |
152 | com20020_dev_t *info; | 144 | com20020_dev_t *info; |
153 | struct net_device *dev; | 145 | struct net_device *dev; |
154 | int ret; | ||
155 | struct arcnet_local *lp; | 146 | struct arcnet_local *lp; |
156 | 147 | ||
157 | DEBUG(0, "com20020_attach()\n"); | 148 | DEBUG(0, "com20020_attach()\n"); |
158 | 149 | ||
159 | /* Create new network device */ | 150 | /* Create new network device */ |
160 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); | 151 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); |
161 | if (!link) | 152 | if (!link) |
162 | return NULL; | 153 | return -ENOMEM; |
163 | 154 | ||
164 | info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); | 155 | info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); |
165 | if (!info) | 156 | if (!info) |
@@ -191,30 +182,19 @@ static dev_link_t *com20020_attach(void) | |||
191 | link->conf.IntType = INT_MEMORY_AND_IO; | 182 | link->conf.IntType = INT_MEMORY_AND_IO; |
192 | link->conf.Present = PRESENT_OPTION; | 183 | link->conf.Present = PRESENT_OPTION; |
193 | 184 | ||
194 | |||
195 | link->irq.Instance = info->dev = dev; | 185 | link->irq.Instance = info->dev = dev; |
196 | link->priv = info; | 186 | link->priv = info; |
197 | 187 | ||
198 | /* Register with Card Services */ | 188 | link->state |= DEV_PRESENT; |
199 | link->next = dev_list; | 189 | com20020_config(link); |
200 | dev_list = link; | ||
201 | client_reg.dev_info = &dev_info; | ||
202 | client_reg.Version = 0x0210; | ||
203 | client_reg.event_callback_args.client_data = link; | ||
204 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
205 | if (ret != 0) { | ||
206 | cs_error(link->handle, RegisterClient, ret); | ||
207 | com20020_detach(link); | ||
208 | return NULL; | ||
209 | } | ||
210 | 190 | ||
211 | return link; | 191 | return 0; |
212 | 192 | ||
213 | fail_alloc_dev: | 193 | fail_alloc_dev: |
214 | kfree(info); | 194 | kfree(info); |
215 | fail_alloc_info: | 195 | fail_alloc_info: |
216 | kfree(link); | 196 | kfree(link); |
217 | return NULL; | 197 | return -ENOMEM; |
218 | } /* com20020_attach */ | 198 | } /* com20020_attach */ |
219 | 199 | ||
220 | /*====================================================================== | 200 | /*====================================================================== |
@@ -226,29 +206,21 @@ fail_alloc_info: | |||
226 | 206 | ||
227 | ======================================================================*/ | 207 | ======================================================================*/ |
228 | 208 | ||
229 | static void com20020_detach(dev_link_t *link) | 209 | static void com20020_detach(struct pcmcia_device *p_dev) |
230 | { | 210 | { |
211 | dev_link_t *link = dev_to_instance(p_dev); | ||
231 | struct com20020_dev_t *info = link->priv; | 212 | struct com20020_dev_t *info = link->priv; |
232 | dev_link_t **linkp; | 213 | struct net_device *dev = info->dev; |
233 | struct net_device *dev; | 214 | |
234 | |||
235 | DEBUG(1,"detach...\n"); | 215 | DEBUG(1,"detach...\n"); |
236 | 216 | ||
237 | DEBUG(0, "com20020_detach(0x%p)\n", link); | 217 | DEBUG(0, "com20020_detach(0x%p)\n", link); |
238 | 218 | ||
239 | /* Locate device structure */ | ||
240 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
241 | if (*linkp == link) break; | ||
242 | if (*linkp == NULL) | ||
243 | return; | ||
244 | |||
245 | dev = info->dev; | ||
246 | |||
247 | if (link->dev) { | 219 | if (link->dev) { |
248 | DEBUG(1,"unregister...\n"); | 220 | DEBUG(1,"unregister...\n"); |
249 | 221 | ||
250 | unregister_netdev(dev); | 222 | unregister_netdev(dev); |
251 | 223 | ||
252 | /* | 224 | /* |
253 | * this is necessary because we register our IRQ separately | 225 | * this is necessary because we register our IRQ separately |
254 | * from card services. | 226 | * from card services. |
@@ -260,12 +232,8 @@ static void com20020_detach(dev_link_t *link) | |||
260 | if (link->state & DEV_CONFIG) | 232 | if (link->state & DEV_CONFIG) |
261 | com20020_release(link); | 233 | com20020_release(link); |
262 | 234 | ||
263 | if (link->handle) | ||
264 | pcmcia_deregister_client(link->handle); | ||
265 | |||
266 | /* Unlink device structure, free bits */ | 235 | /* Unlink device structure, free bits */ |
267 | DEBUG(1,"unlinking...\n"); | 236 | DEBUG(1,"unlinking...\n"); |
268 | *linkp = link->next; | ||
269 | if (link->priv) | 237 | if (link->priv) |
270 | { | 238 | { |
271 | dev = info->dev; | 239 | dev = info->dev; |
@@ -421,61 +389,41 @@ static void com20020_release(dev_link_t *link) | |||
421 | link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); | 389 | link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); |
422 | } | 390 | } |
423 | 391 | ||
424 | /*====================================================================== | 392 | static int com20020_suspend(struct pcmcia_device *p_dev) |
393 | { | ||
394 | dev_link_t *link = dev_to_instance(p_dev); | ||
395 | com20020_dev_t *info = link->priv; | ||
396 | struct net_device *dev = info->dev; | ||
425 | 397 | ||
426 | The card status event handler. Mostly, this schedules other | 398 | link->state |= DEV_SUSPEND; |
427 | stuff to run after an event is received. A CARD_REMOVAL event | 399 | if (link->state & DEV_CONFIG) { |
428 | also sets some flags to discourage the net drivers from trying | 400 | if (link->open) { |
429 | to talk to the card any more. | 401 | netif_device_detach(dev); |
402 | } | ||
403 | pcmcia_release_configuration(link->handle); | ||
404 | } | ||
430 | 405 | ||
431 | ======================================================================*/ | 406 | return 0; |
407 | } | ||
432 | 408 | ||
433 | static int com20020_event(event_t event, int priority, | 409 | static int com20020_resume(struct pcmcia_device *p_dev) |
434 | event_callback_args_t *args) | ||
435 | { | 410 | { |
436 | dev_link_t *link = args->client_data; | 411 | dev_link_t *link = dev_to_instance(p_dev); |
437 | com20020_dev_t *info = link->priv; | 412 | com20020_dev_t *info = link->priv; |
438 | struct net_device *dev = info->dev; | 413 | struct net_device *dev = info->dev; |
439 | 414 | ||
440 | DEBUG(1, "com20020_event(0x%06x)\n", event); | 415 | link->state &= ~DEV_SUSPEND; |
441 | |||
442 | switch (event) { | ||
443 | case CS_EVENT_CARD_REMOVAL: | ||
444 | link->state &= ~DEV_PRESENT; | ||
445 | if (link->state & DEV_CONFIG) | ||
446 | netif_device_detach(dev); | ||
447 | break; | ||
448 | case CS_EVENT_CARD_INSERTION: | ||
449 | link->state |= DEV_PRESENT; | ||
450 | com20020_config(link); | ||
451 | break; | ||
452 | case CS_EVENT_PM_SUSPEND: | ||
453 | link->state |= DEV_SUSPEND; | ||
454 | /* Fall through... */ | ||
455 | case CS_EVENT_RESET_PHYSICAL: | ||
456 | if (link->state & DEV_CONFIG) { | ||
457 | if (link->open) { | ||
458 | netif_device_detach(dev); | ||
459 | } | ||
460 | pcmcia_release_configuration(link->handle); | ||
461 | } | ||
462 | break; | ||
463 | case CS_EVENT_PM_RESUME: | ||
464 | link->state &= ~DEV_SUSPEND; | ||
465 | /* Fall through... */ | ||
466 | case CS_EVENT_CARD_RESET: | ||
467 | if (link->state & DEV_CONFIG) { | 416 | if (link->state & DEV_CONFIG) { |
468 | pcmcia_request_configuration(link->handle, &link->conf); | 417 | pcmcia_request_configuration(link->handle, &link->conf); |
469 | if (link->open) { | 418 | if (link->open) { |
470 | int ioaddr = dev->base_addr; | 419 | int ioaddr = dev->base_addr; |
471 | struct arcnet_local *lp = dev->priv; | 420 | struct arcnet_local *lp = dev->priv; |
472 | ARCRESET; | 421 | ARCRESET; |
473 | } | 422 | } |
474 | } | 423 | } |
475 | break; | 424 | |
476 | } | 425 | return 0; |
477 | return 0; | 426 | } |
478 | } /* com20020_event */ | ||
479 | 427 | ||
480 | static struct pcmcia_device_id com20020_ids[] = { | 428 | static struct pcmcia_device_id com20020_ids[] = { |
481 | PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), | 429 | PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), |
@@ -488,10 +436,11 @@ static struct pcmcia_driver com20020_cs_driver = { | |||
488 | .drv = { | 436 | .drv = { |
489 | .name = "com20020_cs", | 437 | .name = "com20020_cs", |
490 | }, | 438 | }, |
491 | .attach = com20020_attach, | 439 | .probe = com20020_attach, |
492 | .event = com20020_event, | 440 | .remove = com20020_detach, |
493 | .detach = com20020_detach, | ||
494 | .id_table = com20020_ids, | 441 | .id_table = com20020_ids, |
442 | .suspend = com20020_suspend, | ||
443 | .resume = com20020_resume, | ||
495 | }; | 444 | }; |
496 | 445 | ||
497 | static int __init init_com20020_cs(void) | 446 | static int __init init_com20020_cs(void) |
@@ -502,7 +451,6 @@ static int __init init_com20020_cs(void) | |||
502 | static void __exit exit_com20020_cs(void) | 451 | static void __exit exit_com20020_cs(void) |
503 | { | 452 | { |
504 | pcmcia_unregister_driver(&com20020_cs_driver); | 453 | pcmcia_unregister_driver(&com20020_cs_driver); |
505 | BUG_ON(dev_list != NULL); | ||
506 | } | 454 | } |
507 | 455 | ||
508 | module_init(init_com20020_cs); | 456 | module_init(init_com20020_cs); |
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 356f50909222..28fe2fb4d6c0 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c | |||
@@ -88,10 +88,7 @@ static void fmvj18x_config(dev_link_t *link); | |||
88 | static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id); | 88 | static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id); |
89 | static int fmvj18x_setup_mfc(dev_link_t *link); | 89 | static int fmvj18x_setup_mfc(dev_link_t *link); |
90 | static void fmvj18x_release(dev_link_t *link); | 90 | static void fmvj18x_release(dev_link_t *link); |
91 | static int fmvj18x_event(event_t event, int priority, | 91 | static void fmvj18x_detach(struct pcmcia_device *p_dev); |
92 | event_callback_args_t *args); | ||
93 | static dev_link_t *fmvj18x_attach(void); | ||
94 | static void fmvj18x_detach(dev_link_t *); | ||
95 | 92 | ||
96 | /* | 93 | /* |
97 | LAN controller(MBH86960A) specific routines | 94 | LAN controller(MBH86960A) specific routines |
@@ -108,9 +105,6 @@ static void set_rx_mode(struct net_device *dev); | |||
108 | static void fjn_tx_timeout(struct net_device *dev); | 105 | static void fjn_tx_timeout(struct net_device *dev); |
109 | static struct ethtool_ops netdev_ethtool_ops; | 106 | static struct ethtool_ops netdev_ethtool_ops; |
110 | 107 | ||
111 | static dev_info_t dev_info = "fmvj18x_cs"; | ||
112 | static dev_link_t *dev_list; | ||
113 | |||
114 | /* | 108 | /* |
115 | card type | 109 | card type |
116 | */ | 110 | */ |
@@ -234,20 +228,18 @@ typedef struct local_info_t { | |||
234 | #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ | 228 | #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ |
235 | #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ | 229 | #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ |
236 | 230 | ||
237 | static dev_link_t *fmvj18x_attach(void) | 231 | static int fmvj18x_attach(struct pcmcia_device *p_dev) |
238 | { | 232 | { |
239 | local_info_t *lp; | 233 | local_info_t *lp; |
240 | dev_link_t *link; | 234 | dev_link_t *link; |
241 | struct net_device *dev; | 235 | struct net_device *dev; |
242 | client_reg_t client_reg; | 236 | |
243 | int ret; | ||
244 | |||
245 | DEBUG(0, "fmvj18x_attach()\n"); | 237 | DEBUG(0, "fmvj18x_attach()\n"); |
246 | 238 | ||
247 | /* Make up a FMVJ18x specific data structure */ | 239 | /* Make up a FMVJ18x specific data structure */ |
248 | dev = alloc_etherdev(sizeof(local_info_t)); | 240 | dev = alloc_etherdev(sizeof(local_info_t)); |
249 | if (!dev) | 241 | if (!dev) |
250 | return NULL; | 242 | return -ENOMEM; |
251 | lp = netdev_priv(dev); | 243 | lp = netdev_priv(dev); |
252 | link = &lp->link; | 244 | link = &lp->link; |
253 | link->priv = dev; | 245 | link->priv = dev; |
@@ -262,7 +254,7 @@ static dev_link_t *fmvj18x_attach(void) | |||
262 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 254 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
263 | link->irq.Handler = &fjn_interrupt; | 255 | link->irq.Handler = &fjn_interrupt; |
264 | link->irq.Instance = dev; | 256 | link->irq.Instance = dev; |
265 | 257 | ||
266 | /* General socket configuration */ | 258 | /* General socket configuration */ |
267 | link->conf.Attributes = CONF_ENABLE_IRQ; | 259 | link->conf.Attributes = CONF_ENABLE_IRQ; |
268 | link->conf.Vcc = 50; | 260 | link->conf.Vcc = 50; |
@@ -281,37 +273,24 @@ static dev_link_t *fmvj18x_attach(void) | |||
281 | dev->watchdog_timeo = TX_TIMEOUT; | 273 | dev->watchdog_timeo = TX_TIMEOUT; |
282 | #endif | 274 | #endif |
283 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 275 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
284 | |||
285 | /* Register with Card Services */ | ||
286 | link->next = dev_list; | ||
287 | dev_list = link; | ||
288 | client_reg.dev_info = &dev_info; | ||
289 | client_reg.Version = 0x0210; | ||
290 | client_reg.event_callback_args.client_data = link; | ||
291 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
292 | if (ret != 0) { | ||
293 | cs_error(link->handle, RegisterClient, ret); | ||
294 | fmvj18x_detach(link); | ||
295 | return NULL; | ||
296 | } | ||
297 | 276 | ||
298 | return link; | 277 | link->handle = p_dev; |
278 | p_dev->instance = link; | ||
279 | |||
280 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
281 | fmvj18x_config(link); | ||
282 | |||
283 | return 0; | ||
299 | } /* fmvj18x_attach */ | 284 | } /* fmvj18x_attach */ |
300 | 285 | ||
301 | /*====================================================================*/ | 286 | /*====================================================================*/ |
302 | 287 | ||
303 | static void fmvj18x_detach(dev_link_t *link) | 288 | static void fmvj18x_detach(struct pcmcia_device *p_dev) |
304 | { | 289 | { |
290 | dev_link_t *link = dev_to_instance(p_dev); | ||
305 | struct net_device *dev = link->priv; | 291 | struct net_device *dev = link->priv; |
306 | dev_link_t **linkp; | 292 | |
307 | |||
308 | DEBUG(0, "fmvj18x_detach(0x%p)\n", link); | 293 | DEBUG(0, "fmvj18x_detach(0x%p)\n", link); |
309 | |||
310 | /* Locate device structure */ | ||
311 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
312 | if (*linkp == link) break; | ||
313 | if (*linkp == NULL) | ||
314 | return; | ||
315 | 294 | ||
316 | if (link->dev) | 295 | if (link->dev) |
317 | unregister_netdev(dev); | 296 | unregister_netdev(dev); |
@@ -319,12 +298,6 @@ static void fmvj18x_detach(dev_link_t *link) | |||
319 | if (link->state & DEV_CONFIG) | 298 | if (link->state & DEV_CONFIG) |
320 | fmvj18x_release(link); | 299 | fmvj18x_release(link); |
321 | 300 | ||
322 | /* Break the link with Card Services */ | ||
323 | if (link->handle) | ||
324 | pcmcia_deregister_client(link->handle); | ||
325 | |||
326 | /* Unlink device structure, free pieces */ | ||
327 | *linkp = link->next; | ||
328 | free_netdev(dev); | 301 | free_netdev(dev); |
329 | } /* fmvj18x_detach */ | 302 | } /* fmvj18x_detach */ |
330 | 303 | ||
@@ -713,51 +686,40 @@ static void fmvj18x_release(dev_link_t *link) | |||
713 | link->state &= ~DEV_CONFIG; | 686 | link->state &= ~DEV_CONFIG; |
714 | } | 687 | } |
715 | 688 | ||
716 | /*====================================================================*/ | 689 | static int fmvj18x_suspend(struct pcmcia_device *p_dev) |
717 | |||
718 | static int fmvj18x_event(event_t event, int priority, | ||
719 | event_callback_args_t *args) | ||
720 | { | 690 | { |
721 | dev_link_t *link = args->client_data; | 691 | dev_link_t *link = dev_to_instance(p_dev); |
722 | struct net_device *dev = link->priv; | 692 | struct net_device *dev = link->priv; |
723 | 693 | ||
724 | DEBUG(1, "fmvj18x_event(0x%06x)\n", event); | ||
725 | |||
726 | switch (event) { | ||
727 | case CS_EVENT_CARD_REMOVAL: | ||
728 | link->state &= ~DEV_PRESENT; | ||
729 | if (link->state & DEV_CONFIG) | ||
730 | netif_device_detach(dev); | ||
731 | break; | ||
732 | case CS_EVENT_CARD_INSERTION: | ||
733 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
734 | fmvj18x_config(link); | ||
735 | break; | ||
736 | case CS_EVENT_PM_SUSPEND: | ||
737 | link->state |= DEV_SUSPEND; | 694 | link->state |= DEV_SUSPEND; |
738 | /* Fall through... */ | ||
739 | case CS_EVENT_RESET_PHYSICAL: | ||
740 | if (link->state & DEV_CONFIG) { | 695 | if (link->state & DEV_CONFIG) { |
741 | if (link->open) | 696 | if (link->open) |
742 | netif_device_detach(dev); | 697 | netif_device_detach(dev); |
743 | pcmcia_release_configuration(link->handle); | 698 | pcmcia_release_configuration(link->handle); |
744 | } | 699 | } |
745 | break; | 700 | |
746 | case CS_EVENT_PM_RESUME: | 701 | |
702 | return 0; | ||
703 | } | ||
704 | |||
705 | static int fmvj18x_resume(struct pcmcia_device *p_dev) | ||
706 | { | ||
707 | dev_link_t *link = dev_to_instance(p_dev); | ||
708 | struct net_device *dev = link->priv; | ||
709 | |||
747 | link->state &= ~DEV_SUSPEND; | 710 | link->state &= ~DEV_SUSPEND; |
748 | /* Fall through... */ | ||
749 | case CS_EVENT_CARD_RESET: | ||
750 | if (link->state & DEV_CONFIG) { | 711 | if (link->state & DEV_CONFIG) { |
751 | pcmcia_request_configuration(link->handle, &link->conf); | 712 | pcmcia_request_configuration(link->handle, &link->conf); |
752 | if (link->open) { | 713 | if (link->open) { |
753 | fjn_reset(dev); | 714 | fjn_reset(dev); |
754 | netif_device_attach(dev); | 715 | netif_device_attach(dev); |
755 | } | 716 | } |
756 | } | 717 | } |
757 | break; | 718 | |
758 | } | 719 | return 0; |
759 | return 0; | 720 | } |
760 | } /* fmvj18x_event */ | 721 | |
722 | /*====================================================================*/ | ||
761 | 723 | ||
762 | static struct pcmcia_device_id fmvj18x_ids[] = { | 724 | static struct pcmcia_device_id fmvj18x_ids[] = { |
763 | PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004), | 725 | PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004), |
@@ -789,10 +751,11 @@ static struct pcmcia_driver fmvj18x_cs_driver = { | |||
789 | .drv = { | 751 | .drv = { |
790 | .name = "fmvj18x_cs", | 752 | .name = "fmvj18x_cs", |
791 | }, | 753 | }, |
792 | .attach = fmvj18x_attach, | 754 | .probe = fmvj18x_attach, |
793 | .event = fmvj18x_event, | 755 | .remove = fmvj18x_detach, |
794 | .detach = fmvj18x_detach, | ||
795 | .id_table = fmvj18x_ids, | 756 | .id_table = fmvj18x_ids, |
757 | .suspend = fmvj18x_suspend, | ||
758 | .resume = fmvj18x_resume, | ||
796 | }; | 759 | }; |
797 | 760 | ||
798 | static int __init init_fmvj18x_cs(void) | 761 | static int __init init_fmvj18x_cs(void) |
@@ -803,7 +766,6 @@ static int __init init_fmvj18x_cs(void) | |||
803 | static void __exit exit_fmvj18x_cs(void) | 766 | static void __exit exit_fmvj18x_cs(void) |
804 | { | 767 | { |
805 | pcmcia_unregister_driver(&fmvj18x_cs_driver); | 768 | pcmcia_unregister_driver(&fmvj18x_cs_driver); |
806 | BUG_ON(dev_list != NULL); | ||
807 | } | 769 | } |
808 | 770 | ||
809 | module_init(init_fmvj18x_cs); | 771 | module_init(init_fmvj18x_cs); |
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); |
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 980d7e5d66cb..4a232254a497 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
@@ -388,9 +388,6 @@ static char *version = | |||
388 | DRV_NAME " " DRV_VERSION " (Roger C. Pao)"; | 388 | DRV_NAME " " DRV_VERSION " (Roger C. Pao)"; |
389 | #endif | 389 | #endif |
390 | 390 | ||
391 | static dev_info_t dev_info="nmclan_cs"; | ||
392 | static dev_link_t *dev_list; | ||
393 | |||
394 | static char *if_names[]={ | 391 | static char *if_names[]={ |
395 | "Auto", "10baseT", "BNC", | 392 | "Auto", "10baseT", "BNC", |
396 | }; | 393 | }; |
@@ -422,8 +419,6 @@ Function Prototypes | |||
422 | 419 | ||
423 | static void nmclan_config(dev_link_t *link); | 420 | static void nmclan_config(dev_link_t *link); |
424 | static void nmclan_release(dev_link_t *link); | 421 | static void nmclan_release(dev_link_t *link); |
425 | static int nmclan_event(event_t event, int priority, | ||
426 | event_callback_args_t *args); | ||
427 | 422 | ||
428 | static void nmclan_reset(struct net_device *dev); | 423 | static void nmclan_reset(struct net_device *dev); |
429 | static int mace_config(struct net_device *dev, struct ifmap *map); | 424 | static int mace_config(struct net_device *dev, struct ifmap *map); |
@@ -439,8 +434,7 @@ static void set_multicast_list(struct net_device *dev); | |||
439 | static struct ethtool_ops netdev_ethtool_ops; | 434 | static struct ethtool_ops netdev_ethtool_ops; |
440 | 435 | ||
441 | 436 | ||
442 | static dev_link_t *nmclan_attach(void); | 437 | static void nmclan_detach(struct pcmcia_device *p_dev); |
443 | static void nmclan_detach(dev_link_t *); | ||
444 | 438 | ||
445 | /* ---------------------------------------------------------------------------- | 439 | /* ---------------------------------------------------------------------------- |
446 | nmclan_attach | 440 | nmclan_attach |
@@ -449,13 +443,11 @@ nmclan_attach | |||
449 | Services. | 443 | Services. |
450 | ---------------------------------------------------------------------------- */ | 444 | ---------------------------------------------------------------------------- */ |
451 | 445 | ||
452 | static dev_link_t *nmclan_attach(void) | 446 | static int nmclan_attach(struct pcmcia_device *p_dev) |
453 | { | 447 | { |
454 | mace_private *lp; | 448 | mace_private *lp; |
455 | dev_link_t *link; | 449 | dev_link_t *link; |
456 | struct net_device *dev; | 450 | struct net_device *dev; |
457 | client_reg_t client_reg; | ||
458 | int ret; | ||
459 | 451 | ||
460 | DEBUG(0, "nmclan_attach()\n"); | 452 | DEBUG(0, "nmclan_attach()\n"); |
461 | DEBUG(1, "%s\n", rcsid); | 453 | DEBUG(1, "%s\n", rcsid); |
@@ -463,7 +455,7 @@ static dev_link_t *nmclan_attach(void) | |||
463 | /* Create new ethernet device */ | 455 | /* Create new ethernet device */ |
464 | dev = alloc_etherdev(sizeof(mace_private)); | 456 | dev = alloc_etherdev(sizeof(mace_private)); |
465 | if (!dev) | 457 | if (!dev) |
466 | return NULL; | 458 | return -ENOMEM; |
467 | lp = netdev_priv(dev); | 459 | lp = netdev_priv(dev); |
468 | link = &lp->link; | 460 | link = &lp->link; |
469 | link->priv = dev; | 461 | link->priv = dev; |
@@ -497,20 +489,13 @@ static dev_link_t *nmclan_attach(void) | |||
497 | dev->watchdog_timeo = TX_TIMEOUT; | 489 | dev->watchdog_timeo = TX_TIMEOUT; |
498 | #endif | 490 | #endif |
499 | 491 | ||
500 | /* Register with Card Services */ | 492 | link->handle = p_dev; |
501 | link->next = dev_list; | 493 | p_dev->instance = link; |
502 | dev_list = link; | 494 | |
503 | client_reg.dev_info = &dev_info; | 495 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
504 | client_reg.Version = 0x0210; | 496 | nmclan_config(link); |
505 | client_reg.event_callback_args.client_data = link; | ||
506 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
507 | if (ret != 0) { | ||
508 | cs_error(link->handle, RegisterClient, ret); | ||
509 | nmclan_detach(link); | ||
510 | return NULL; | ||
511 | } | ||
512 | 497 | ||
513 | return link; | 498 | return 0; |
514 | } /* nmclan_attach */ | 499 | } /* nmclan_attach */ |
515 | 500 | ||
516 | /* ---------------------------------------------------------------------------- | 501 | /* ---------------------------------------------------------------------------- |
@@ -521,30 +506,19 @@ nmclan_detach | |||
521 | when the device is released. | 506 | when the device is released. |
522 | ---------------------------------------------------------------------------- */ | 507 | ---------------------------------------------------------------------------- */ |
523 | 508 | ||
524 | static void nmclan_detach(dev_link_t *link) | 509 | static void nmclan_detach(struct pcmcia_device *p_dev) |
525 | { | 510 | { |
511 | dev_link_t *link = dev_to_instance(p_dev); | ||
526 | struct net_device *dev = link->priv; | 512 | struct net_device *dev = link->priv; |
527 | dev_link_t **linkp; | ||
528 | 513 | ||
529 | DEBUG(0, "nmclan_detach(0x%p)\n", link); | 514 | DEBUG(0, "nmclan_detach(0x%p)\n", link); |
530 | 515 | ||
531 | /* Locate device structure */ | ||
532 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
533 | if (*linkp == link) break; | ||
534 | if (*linkp == NULL) | ||
535 | return; | ||
536 | |||
537 | if (link->dev) | 516 | if (link->dev) |
538 | unregister_netdev(dev); | 517 | unregister_netdev(dev); |
539 | 518 | ||
540 | if (link->state & DEV_CONFIG) | 519 | if (link->state & DEV_CONFIG) |
541 | nmclan_release(link); | 520 | nmclan_release(link); |
542 | 521 | ||
543 | if (link->handle) | ||
544 | pcmcia_deregister_client(link->handle); | ||
545 | |||
546 | /* Unlink device structure, free bits */ | ||
547 | *linkp = link->next; | ||
548 | free_netdev(dev); | 522 | free_netdev(dev); |
549 | } /* nmclan_detach */ | 523 | } /* nmclan_detach */ |
550 | 524 | ||
@@ -801,59 +775,39 @@ static void nmclan_release(dev_link_t *link) | |||
801 | link->state &= ~DEV_CONFIG; | 775 | link->state &= ~DEV_CONFIG; |
802 | } | 776 | } |
803 | 777 | ||
804 | /* ---------------------------------------------------------------------------- | 778 | static int nmclan_suspend(struct pcmcia_device *p_dev) |
805 | nmclan_event | ||
806 | The card status event handler. Mostly, this schedules other | ||
807 | stuff to run after an event is received. A CARD_REMOVAL event | ||
808 | also sets some flags to discourage the net drivers from trying | ||
809 | to talk to the card any more. | ||
810 | ---------------------------------------------------------------------------- */ | ||
811 | static int nmclan_event(event_t event, int priority, | ||
812 | event_callback_args_t *args) | ||
813 | { | 779 | { |
814 | dev_link_t *link = args->client_data; | 780 | dev_link_t *link = dev_to_instance(p_dev); |
815 | struct net_device *dev = link->priv; | 781 | struct net_device *dev = link->priv; |
782 | |||
783 | link->state |= DEV_SUSPEND; | ||
784 | if (link->state & DEV_CONFIG) { | ||
785 | if (link->open) | ||
786 | netif_device_detach(dev); | ||
787 | pcmcia_release_configuration(link->handle); | ||
788 | } | ||
816 | 789 | ||
817 | DEBUG(1, "nmclan_event(0x%06x)\n", event); | ||
818 | 790 | ||
819 | switch (event) { | 791 | return 0; |
820 | case CS_EVENT_CARD_REMOVAL: | 792 | } |
821 | link->state &= ~DEV_PRESENT; | 793 | |
822 | if (link->state & DEV_CONFIG) | 794 | static int nmclan_resume(struct pcmcia_device *p_dev) |
823 | netif_device_detach(dev); | 795 | { |
824 | break; | 796 | dev_link_t *link = dev_to_instance(p_dev); |
825 | case CS_EVENT_CARD_INSERTION: | 797 | struct net_device *dev = link->priv; |
826 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 798 | |
827 | nmclan_config(link); | 799 | link->state &= ~DEV_SUSPEND; |
828 | break; | 800 | if (link->state & DEV_CONFIG) { |
829 | case CS_EVENT_PM_SUSPEND: | 801 | pcmcia_request_configuration(link->handle, &link->conf); |
830 | link->state |= DEV_SUSPEND; | 802 | if (link->open) { |
831 | /* Fall through... */ | 803 | nmclan_reset(dev); |
832 | case CS_EVENT_RESET_PHYSICAL: | 804 | netif_device_attach(dev); |
833 | if (link->state & DEV_CONFIG) { | 805 | } |
834 | if (link->open) | ||
835 | netif_device_detach(dev); | ||
836 | pcmcia_release_configuration(link->handle); | ||
837 | } | ||
838 | break; | ||
839 | case CS_EVENT_PM_RESUME: | ||
840 | link->state &= ~DEV_SUSPEND; | ||
841 | /* Fall through... */ | ||
842 | case CS_EVENT_CARD_RESET: | ||
843 | if (link->state & DEV_CONFIG) { | ||
844 | pcmcia_request_configuration(link->handle, &link->conf); | ||
845 | if (link->open) { | ||
846 | nmclan_reset(dev); | ||
847 | netif_device_attach(dev); | ||
848 | } | 806 | } |
849 | } | 807 | |
850 | break; | 808 | return 0; |
851 | case CS_EVENT_RESET_REQUEST: | 809 | } |
852 | return 1; | 810 | |
853 | break; | ||
854 | } | ||
855 | return 0; | ||
856 | } /* nmclan_event */ | ||
857 | 811 | ||
858 | /* ---------------------------------------------------------------------------- | 812 | /* ---------------------------------------------------------------------------- |
859 | nmclan_reset | 813 | nmclan_reset |
@@ -1681,10 +1635,11 @@ static struct pcmcia_driver nmclan_cs_driver = { | |||
1681 | .drv = { | 1635 | .drv = { |
1682 | .name = "nmclan_cs", | 1636 | .name = "nmclan_cs", |
1683 | }, | 1637 | }, |
1684 | .attach = nmclan_attach, | 1638 | .probe = nmclan_attach, |
1685 | .event = nmclan_event, | 1639 | .remove = nmclan_detach, |
1686 | .detach = nmclan_detach, | ||
1687 | .id_table = nmclan_ids, | 1640 | .id_table = nmclan_ids, |
1641 | .suspend = nmclan_suspend, | ||
1642 | .resume = nmclan_resume, | ||
1688 | }; | 1643 | }; |
1689 | 1644 | ||
1690 | static int __init init_nmclan_cs(void) | 1645 | static int __init init_nmclan_cs(void) |
@@ -1695,7 +1650,6 @@ static int __init init_nmclan_cs(void) | |||
1695 | static void __exit exit_nmclan_cs(void) | 1650 | static void __exit exit_nmclan_cs(void) |
1696 | { | 1651 | { |
1697 | pcmcia_unregister_driver(&nmclan_cs_driver); | 1652 | pcmcia_unregister_driver(&nmclan_cs_driver); |
1698 | BUG_ON(dev_list != NULL); | ||
1699 | } | 1653 | } |
1700 | 1654 | ||
1701 | module_init(init_nmclan_cs); | 1655 | module_init(init_nmclan_cs); |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 818c185d6438..d85b758f3efa 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -105,8 +105,6 @@ module_param_array(hw_addr, int, NULL, 0); | |||
105 | static void mii_phy_probe(struct net_device *dev); | 105 | static void mii_phy_probe(struct net_device *dev); |
106 | static void pcnet_config(dev_link_t *link); | 106 | static void pcnet_config(dev_link_t *link); |
107 | static void pcnet_release(dev_link_t *link); | 107 | static void pcnet_release(dev_link_t *link); |
108 | static int pcnet_event(event_t event, int priority, | ||
109 | event_callback_args_t *args); | ||
110 | static int pcnet_open(struct net_device *dev); | 108 | static int pcnet_open(struct net_device *dev); |
111 | static int pcnet_close(struct net_device *dev); | 109 | static int pcnet_close(struct net_device *dev); |
112 | static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 110 | static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
@@ -120,11 +118,9 @@ static int setup_shmem_window(dev_link_t *link, int start_pg, | |||
120 | static int setup_dma_config(dev_link_t *link, int start_pg, | 118 | static int setup_dma_config(dev_link_t *link, int start_pg, |
121 | int stop_pg); | 119 | int stop_pg); |
122 | 120 | ||
123 | static dev_link_t *pcnet_attach(void); | 121 | static void pcnet_detach(struct pcmcia_device *p_dev); |
124 | static void pcnet_detach(dev_link_t *); | ||
125 | 122 | ||
126 | static dev_info_t dev_info = "pcnet_cs"; | 123 | static dev_info_t dev_info = "pcnet_cs"; |
127 | static dev_link_t *dev_list; | ||
128 | 124 | ||
129 | /*====================================================================*/ | 125 | /*====================================================================*/ |
130 | 126 | ||
@@ -244,19 +240,17 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev) | |||
244 | 240 | ||
245 | ======================================================================*/ | 241 | ======================================================================*/ |
246 | 242 | ||
247 | static dev_link_t *pcnet_attach(void) | 243 | static int pcnet_probe(struct pcmcia_device *p_dev) |
248 | { | 244 | { |
249 | pcnet_dev_t *info; | 245 | pcnet_dev_t *info; |
250 | dev_link_t *link; | 246 | dev_link_t *link; |
251 | struct net_device *dev; | 247 | struct net_device *dev; |
252 | client_reg_t client_reg; | ||
253 | int ret; | ||
254 | 248 | ||
255 | DEBUG(0, "pcnet_attach()\n"); | 249 | DEBUG(0, "pcnet_attach()\n"); |
256 | 250 | ||
257 | /* Create new ethernet device */ | 251 | /* Create new ethernet device */ |
258 | dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); | 252 | dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); |
259 | if (!dev) return NULL; | 253 | if (!dev) return -ENOMEM; |
260 | info = PRIV(dev); | 254 | info = PRIV(dev); |
261 | link = &info->link; | 255 | link = &info->link; |
262 | link->priv = dev; | 256 | link->priv = dev; |
@@ -271,20 +265,13 @@ static dev_link_t *pcnet_attach(void) | |||
271 | dev->stop = &pcnet_close; | 265 | dev->stop = &pcnet_close; |
272 | dev->set_config = &set_config; | 266 | dev->set_config = &set_config; |
273 | 267 | ||
274 | /* Register with Card Services */ | 268 | link->handle = p_dev; |
275 | link->next = dev_list; | 269 | p_dev->instance = link; |
276 | dev_list = link; | ||
277 | client_reg.dev_info = &dev_info; | ||
278 | client_reg.Version = 0x0210; | ||
279 | client_reg.event_callback_args.client_data = link; | ||
280 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
281 | if (ret != CS_SUCCESS) { | ||
282 | cs_error(link->handle, RegisterClient, ret); | ||
283 | pcnet_detach(link); | ||
284 | return NULL; | ||
285 | } | ||
286 | 270 | ||
287 | return link; | 271 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
272 | pcnet_config(link); | ||
273 | |||
274 | return 0; | ||
288 | } /* pcnet_attach */ | 275 | } /* pcnet_attach */ |
289 | 276 | ||
290 | /*====================================================================== | 277 | /*====================================================================== |
@@ -296,31 +283,20 @@ static dev_link_t *pcnet_attach(void) | |||
296 | 283 | ||
297 | ======================================================================*/ | 284 | ======================================================================*/ |
298 | 285 | ||
299 | static void pcnet_detach(dev_link_t *link) | 286 | static void pcnet_detach(struct pcmcia_device *p_dev) |
300 | { | 287 | { |
301 | struct net_device *dev = link->priv; | 288 | dev_link_t *link = dev_to_instance(p_dev); |
302 | dev_link_t **linkp; | 289 | struct net_device *dev = link->priv; |
303 | |||
304 | DEBUG(0, "pcnet_detach(0x%p)\n", link); | ||
305 | 290 | ||
306 | /* Locate device structure */ | 291 | DEBUG(0, "pcnet_detach(0x%p)\n", link); |
307 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
308 | if (*linkp == link) break; | ||
309 | if (*linkp == NULL) | ||
310 | return; | ||
311 | 292 | ||
312 | if (link->dev) | 293 | if (link->dev) |
313 | unregister_netdev(dev); | 294 | unregister_netdev(dev); |
314 | 295 | ||
315 | if (link->state & DEV_CONFIG) | 296 | if (link->state & DEV_CONFIG) |
316 | pcnet_release(link); | 297 | pcnet_release(link); |
317 | |||
318 | if (link->handle) | ||
319 | pcmcia_deregister_client(link->handle); | ||
320 | 298 | ||
321 | /* Unlink device structure, free bits */ | 299 | free_netdev(dev); |
322 | *linkp = link->next; | ||
323 | free_netdev(dev); | ||
324 | } /* pcnet_detach */ | 300 | } /* pcnet_detach */ |
325 | 301 | ||
326 | /*====================================================================== | 302 | /*====================================================================== |
@@ -780,50 +756,39 @@ static void pcnet_release(dev_link_t *link) | |||
780 | 756 | ||
781 | ======================================================================*/ | 757 | ======================================================================*/ |
782 | 758 | ||
783 | static int pcnet_event(event_t event, int priority, | 759 | static int pcnet_suspend(struct pcmcia_device *p_dev) |
784 | event_callback_args_t *args) | ||
785 | { | 760 | { |
786 | dev_link_t *link = args->client_data; | 761 | dev_link_t *link = dev_to_instance(p_dev); |
787 | struct net_device *dev = link->priv; | 762 | struct net_device *dev = link->priv; |
788 | 763 | ||
789 | DEBUG(2, "pcnet_event(0x%06x)\n", event); | ||
790 | |||
791 | switch (event) { | ||
792 | case CS_EVENT_CARD_REMOVAL: | ||
793 | link->state &= ~DEV_PRESENT; | ||
794 | if (link->state & DEV_CONFIG) | ||
795 | netif_device_detach(dev); | ||
796 | break; | ||
797 | case CS_EVENT_CARD_INSERTION: | ||
798 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
799 | pcnet_config(link); | ||
800 | break; | ||
801 | case CS_EVENT_PM_SUSPEND: | ||
802 | link->state |= DEV_SUSPEND; | 764 | link->state |= DEV_SUSPEND; |
803 | /* Fall through... */ | ||
804 | case CS_EVENT_RESET_PHYSICAL: | ||
805 | if (link->state & DEV_CONFIG) { | 765 | if (link->state & DEV_CONFIG) { |
806 | if (link->open) | 766 | if (link->open) |
807 | netif_device_detach(dev); | 767 | netif_device_detach(dev); |
808 | pcmcia_release_configuration(link->handle); | 768 | pcmcia_release_configuration(link->handle); |
809 | } | 769 | } |
810 | break; | 770 | |
811 | case CS_EVENT_PM_RESUME: | 771 | return 0; |
772 | } | ||
773 | |||
774 | static int pcnet_resume(struct pcmcia_device *p_dev) | ||
775 | { | ||
776 | dev_link_t *link = dev_to_instance(p_dev); | ||
777 | struct net_device *dev = link->priv; | ||
778 | |||
812 | link->state &= ~DEV_SUSPEND; | 779 | link->state &= ~DEV_SUSPEND; |
813 | /* Fall through... */ | ||
814 | case CS_EVENT_CARD_RESET: | ||
815 | if (link->state & DEV_CONFIG) { | 780 | if (link->state & DEV_CONFIG) { |
816 | pcmcia_request_configuration(link->handle, &link->conf); | 781 | pcmcia_request_configuration(link->handle, &link->conf); |
817 | if (link->open) { | 782 | if (link->open) { |
818 | pcnet_reset_8390(dev); | 783 | pcnet_reset_8390(dev); |
819 | NS8390_init(dev, 1); | 784 | NS8390_init(dev, 1); |
820 | netif_device_attach(dev); | 785 | netif_device_attach(dev); |
821 | } | 786 | } |
822 | } | 787 | } |
823 | break; | 788 | |
824 | } | 789 | return 0; |
825 | return 0; | 790 | } |
826 | } /* pcnet_event */ | 791 | |
827 | 792 | ||
828 | /*====================================================================== | 793 | /*====================================================================== |
829 | 794 | ||
@@ -1844,11 +1809,12 @@ static struct pcmcia_driver pcnet_driver = { | |||
1844 | .drv = { | 1809 | .drv = { |
1845 | .name = "pcnet_cs", | 1810 | .name = "pcnet_cs", |
1846 | }, | 1811 | }, |
1847 | .attach = pcnet_attach, | 1812 | .probe = pcnet_probe, |
1848 | .event = pcnet_event, | 1813 | .remove = pcnet_detach, |
1849 | .detach = pcnet_detach, | ||
1850 | .owner = THIS_MODULE, | 1814 | .owner = THIS_MODULE, |
1851 | .id_table = pcnet_ids, | 1815 | .id_table = pcnet_ids, |
1816 | .suspend = pcnet_suspend, | ||
1817 | .resume = pcnet_resume, | ||
1852 | }; | 1818 | }; |
1853 | 1819 | ||
1854 | static int __init init_pcnet_cs(void) | 1820 | static int __init init_pcnet_cs(void) |
@@ -1860,7 +1826,6 @@ static void __exit exit_pcnet_cs(void) | |||
1860 | { | 1826 | { |
1861 | DEBUG(0, "pcnet_cs: unloading\n"); | 1827 | DEBUG(0, "pcnet_cs: unloading\n"); |
1862 | pcmcia_unregister_driver(&pcnet_driver); | 1828 | pcmcia_unregister_driver(&pcnet_driver); |
1863 | BUG_ON(dev_list != NULL); | ||
1864 | } | 1829 | } |
1865 | 1830 | ||
1866 | module_init(init_pcnet_cs); | 1831 | module_init(init_pcnet_cs); |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index c7cca842e5ee..0122415dfeef 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -102,10 +102,6 @@ static const char *version = | |||
102 | currently have room for another Tx packet. */ | 102 | currently have room for another Tx packet. */ |
103 | #define MEMORY_WAIT_TIME 8 | 103 | #define MEMORY_WAIT_TIME 8 |
104 | 104 | ||
105 | static dev_info_t dev_info = "smc91c92_cs"; | ||
106 | |||
107 | static dev_link_t *dev_list; | ||
108 | |||
109 | struct smc_private { | 105 | struct smc_private { |
110 | dev_link_t link; | 106 | dev_link_t link; |
111 | spinlock_t lock; | 107 | spinlock_t lock; |
@@ -281,12 +277,9 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, | |||
281 | 277 | ||
282 | /*====================================================================*/ | 278 | /*====================================================================*/ |
283 | 279 | ||
284 | static dev_link_t *smc91c92_attach(void); | 280 | static void smc91c92_detach(struct pcmcia_device *p_dev); |
285 | static void smc91c92_detach(dev_link_t *); | ||
286 | static void smc91c92_config(dev_link_t *link); | 281 | static void smc91c92_config(dev_link_t *link); |
287 | static void smc91c92_release(dev_link_t *link); | 282 | static void smc91c92_release(dev_link_t *link); |
288 | static int smc91c92_event(event_t event, int priority, | ||
289 | event_callback_args_t *args); | ||
290 | 283 | ||
291 | static int smc_open(struct net_device *dev); | 284 | static int smc_open(struct net_device *dev); |
292 | static int smc_close(struct net_device *dev); | 285 | static int smc_close(struct net_device *dev); |
@@ -315,20 +308,18 @@ static struct ethtool_ops ethtool_ops; | |||
315 | 308 | ||
316 | ======================================================================*/ | 309 | ======================================================================*/ |
317 | 310 | ||
318 | static dev_link_t *smc91c92_attach(void) | 311 | static int smc91c92_attach(struct pcmcia_device *p_dev) |
319 | { | 312 | { |
320 | client_reg_t client_reg; | ||
321 | struct smc_private *smc; | 313 | struct smc_private *smc; |
322 | dev_link_t *link; | 314 | dev_link_t *link; |
323 | struct net_device *dev; | 315 | struct net_device *dev; |
324 | int ret; | ||
325 | 316 | ||
326 | DEBUG(0, "smc91c92_attach()\n"); | 317 | DEBUG(0, "smc91c92_attach()\n"); |
327 | 318 | ||
328 | /* Create new ethernet device */ | 319 | /* Create new ethernet device */ |
329 | dev = alloc_etherdev(sizeof(struct smc_private)); | 320 | dev = alloc_etherdev(sizeof(struct smc_private)); |
330 | if (!dev) | 321 | if (!dev) |
331 | return NULL; | 322 | return -ENOMEM; |
332 | smc = netdev_priv(dev); | 323 | smc = netdev_priv(dev); |
333 | link = &smc->link; | 324 | link = &smc->link; |
334 | link->priv = dev; | 325 | link->priv = dev; |
@@ -366,20 +357,13 @@ static dev_link_t *smc91c92_attach(void) | |||
366 | smc->mii_if.phy_id_mask = 0x1f; | 357 | smc->mii_if.phy_id_mask = 0x1f; |
367 | smc->mii_if.reg_num_mask = 0x1f; | 358 | smc->mii_if.reg_num_mask = 0x1f; |
368 | 359 | ||
369 | /* Register with Card Services */ | 360 | link->handle = p_dev; |
370 | link->next = dev_list; | 361 | p_dev->instance = link; |
371 | dev_list = link; | 362 | |
372 | client_reg.dev_info = &dev_info; | 363 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
373 | client_reg.Version = 0x0210; | 364 | smc91c92_config(link); |
374 | client_reg.event_callback_args.client_data = link; | ||
375 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
376 | if (ret != 0) { | ||
377 | cs_error(link->handle, RegisterClient, ret); | ||
378 | smc91c92_detach(link); | ||
379 | return NULL; | ||
380 | } | ||
381 | 365 | ||
382 | return link; | 366 | return 0; |
383 | } /* smc91c92_attach */ | 367 | } /* smc91c92_attach */ |
384 | 368 | ||
385 | /*====================================================================== | 369 | /*====================================================================== |
@@ -391,30 +375,19 @@ static dev_link_t *smc91c92_attach(void) | |||
391 | 375 | ||
392 | ======================================================================*/ | 376 | ======================================================================*/ |
393 | 377 | ||
394 | static void smc91c92_detach(dev_link_t *link) | 378 | static void smc91c92_detach(struct pcmcia_device *p_dev) |
395 | { | 379 | { |
380 | dev_link_t *link = dev_to_instance(p_dev); | ||
396 | struct net_device *dev = link->priv; | 381 | struct net_device *dev = link->priv; |
397 | dev_link_t **linkp; | ||
398 | 382 | ||
399 | DEBUG(0, "smc91c92_detach(0x%p)\n", link); | 383 | DEBUG(0, "smc91c92_detach(0x%p)\n", link); |
400 | 384 | ||
401 | /* Locate device structure */ | ||
402 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
403 | if (*linkp == link) break; | ||
404 | if (*linkp == NULL) | ||
405 | return; | ||
406 | |||
407 | if (link->dev) | 385 | if (link->dev) |
408 | unregister_netdev(dev); | 386 | unregister_netdev(dev); |
409 | 387 | ||
410 | if (link->state & DEV_CONFIG) | 388 | if (link->state & DEV_CONFIG) |
411 | smc91c92_release(link); | 389 | smc91c92_release(link); |
412 | 390 | ||
413 | if (link->handle) | ||
414 | pcmcia_deregister_client(link->handle); | ||
415 | |||
416 | /* Unlink device structure, free bits */ | ||
417 | *linkp = link->next; | ||
418 | free_netdev(dev); | 391 | free_netdev(dev); |
419 | } /* smc91c92_detach */ | 392 | } /* smc91c92_detach */ |
420 | 393 | ||
@@ -895,6 +868,62 @@ free_cfg_mem: | |||
895 | return rc; | 868 | return rc; |
896 | } | 869 | } |
897 | 870 | ||
871 | static int smc91c92_suspend(struct pcmcia_device *p_dev) | ||
872 | { | ||
873 | dev_link_t *link = dev_to_instance(p_dev); | ||
874 | struct net_device *dev = link->priv; | ||
875 | |||
876 | link->state |= DEV_SUSPEND; | ||
877 | if (link->state & DEV_CONFIG) { | ||
878 | if (link->open) | ||
879 | netif_device_detach(dev); | ||
880 | pcmcia_release_configuration(link->handle); | ||
881 | } | ||
882 | |||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | static int smc91c92_resume(struct pcmcia_device *p_dev) | ||
887 | { | ||
888 | dev_link_t *link = dev_to_instance(p_dev); | ||
889 | struct net_device *dev = link->priv; | ||
890 | struct smc_private *smc = netdev_priv(dev); | ||
891 | int i; | ||
892 | |||
893 | link->state &= ~DEV_SUSPEND; | ||
894 | if (link->state & DEV_CONFIG) { | ||
895 | if ((smc->manfid == MANFID_MEGAHERTZ) && | ||
896 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | ||
897 | mhz_3288_power(link); | ||
898 | pcmcia_request_configuration(link->handle, &link->conf); | ||
899 | if (smc->manfid == MANFID_MOTOROLA) | ||
900 | mot_config(link); | ||
901 | if ((smc->manfid == MANFID_OSITECH) && | ||
902 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
903 | /* Power up the card and enable interrupts */ | ||
904 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); | ||
905 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); | ||
906 | } | ||
907 | if (((smc->manfid == MANFID_OSITECH) && | ||
908 | (smc->cardid == PRODID_OSITECH_SEVEN)) || | ||
909 | ((smc->manfid == MANFID_PSION) && | ||
910 | (smc->cardid == PRODID_PSION_NET100))) { | ||
911 | /* Download the Seven of Diamonds firmware */ | ||
912 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
913 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
914 | udelay(50); | ||
915 | } | ||
916 | } | ||
917 | if (link->open) { | ||
918 | smc_reset(dev); | ||
919 | netif_device_attach(dev); | ||
920 | } | ||
921 | } | ||
922 | |||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | |||
898 | /*====================================================================== | 927 | /*====================================================================== |
899 | 928 | ||
900 | This verifies that the chip is some SMC91cXX variant, and returns | 929 | This verifies that the chip is some SMC91cXX variant, and returns |
@@ -935,14 +964,12 @@ static int check_sig(dev_link_t *link) | |||
935 | } | 964 | } |
936 | 965 | ||
937 | if (width) { | 966 | if (width) { |
938 | event_callback_args_t args; | ||
939 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); | 967 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); |
940 | args.client_data = link; | 968 | smc91c92_suspend(link->handle); |
941 | smc91c92_event(CS_EVENT_RESET_PHYSICAL, 0, &args); | ||
942 | pcmcia_release_io(link->handle, &link->io); | 969 | pcmcia_release_io(link->handle, &link->io); |
943 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 970 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
944 | pcmcia_request_io(link->handle, &link->io); | 971 | pcmcia_request_io(link->handle, &link->io); |
945 | smc91c92_event(CS_EVENT_CARD_RESET, 0, &args); | 972 | smc91c92_resume(link->handle); |
946 | return check_sig(link); | 973 | return check_sig(link); |
947 | } | 974 | } |
948 | return -ENODEV; | 975 | return -ENODEV; |
@@ -1172,82 +1199,6 @@ static void smc91c92_release(dev_link_t *link) | |||
1172 | 1199 | ||
1173 | /*====================================================================== | 1200 | /*====================================================================== |
1174 | 1201 | ||
1175 | The card status event handler. Mostly, this schedules other | ||
1176 | stuff to run after an event is received. A CARD_REMOVAL event | ||
1177 | also sets some flags to discourage the net drivers from trying | ||
1178 | to talk to the card any more. | ||
1179 | |||
1180 | ======================================================================*/ | ||
1181 | |||
1182 | static int smc91c92_event(event_t event, int priority, | ||
1183 | event_callback_args_t *args) | ||
1184 | { | ||
1185 | dev_link_t *link = args->client_data; | ||
1186 | struct net_device *dev = link->priv; | ||
1187 | struct smc_private *smc = netdev_priv(dev); | ||
1188 | int i; | ||
1189 | |||
1190 | DEBUG(1, "smc91c92_event(0x%06x)\n", event); | ||
1191 | |||
1192 | switch (event) { | ||
1193 | case CS_EVENT_CARD_REMOVAL: | ||
1194 | link->state &= ~DEV_PRESENT; | ||
1195 | if (link->state & DEV_CONFIG) | ||
1196 | netif_device_detach(dev); | ||
1197 | break; | ||
1198 | case CS_EVENT_CARD_INSERTION: | ||
1199 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1200 | smc91c92_config(link); | ||
1201 | break; | ||
1202 | case CS_EVENT_PM_SUSPEND: | ||
1203 | link->state |= DEV_SUSPEND; | ||
1204 | /* Fall through... */ | ||
1205 | case CS_EVENT_RESET_PHYSICAL: | ||
1206 | if (link->state & DEV_CONFIG) { | ||
1207 | if (link->open) | ||
1208 | netif_device_detach(dev); | ||
1209 | pcmcia_release_configuration(link->handle); | ||
1210 | } | ||
1211 | break; | ||
1212 | case CS_EVENT_PM_RESUME: | ||
1213 | link->state &= ~DEV_SUSPEND; | ||
1214 | /* Fall through... */ | ||
1215 | case CS_EVENT_CARD_RESET: | ||
1216 | if (link->state & DEV_CONFIG) { | ||
1217 | if ((smc->manfid == MANFID_MEGAHERTZ) && | ||
1218 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | ||
1219 | mhz_3288_power(link); | ||
1220 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1221 | if (smc->manfid == MANFID_MOTOROLA) | ||
1222 | mot_config(link); | ||
1223 | if ((smc->manfid == MANFID_OSITECH) && | ||
1224 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | ||
1225 | /* Power up the card and enable interrupts */ | ||
1226 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); | ||
1227 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); | ||
1228 | } | ||
1229 | if (((smc->manfid == MANFID_OSITECH) && | ||
1230 | (smc->cardid == PRODID_OSITECH_SEVEN)) || | ||
1231 | ((smc->manfid == MANFID_PSION) && | ||
1232 | (smc->cardid == PRODID_PSION_NET100))) { | ||
1233 | /* Download the Seven of Diamonds firmware */ | ||
1234 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
1235 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
1236 | udelay(50); | ||
1237 | } | ||
1238 | } | ||
1239 | if (link->open) { | ||
1240 | smc_reset(dev); | ||
1241 | netif_device_attach(dev); | ||
1242 | } | ||
1243 | } | ||
1244 | break; | ||
1245 | } | ||
1246 | return 0; | ||
1247 | } /* smc91c92_event */ | ||
1248 | |||
1249 | /*====================================================================== | ||
1250 | |||
1251 | MII interface support for SMC91cXX based cards | 1202 | MII interface support for SMC91cXX based cards |
1252 | ======================================================================*/ | 1203 | ======================================================================*/ |
1253 | 1204 | ||
@@ -2360,10 +2311,11 @@ static struct pcmcia_driver smc91c92_cs_driver = { | |||
2360 | .drv = { | 2311 | .drv = { |
2361 | .name = "smc91c92_cs", | 2312 | .name = "smc91c92_cs", |
2362 | }, | 2313 | }, |
2363 | .attach = smc91c92_attach, | 2314 | .probe = smc91c92_attach, |
2364 | .event = smc91c92_event, | 2315 | .remove = smc91c92_detach, |
2365 | .detach = smc91c92_detach, | ||
2366 | .id_table = smc91c92_ids, | 2316 | .id_table = smc91c92_ids, |
2317 | .suspend = smc91c92_suspend, | ||
2318 | .resume = smc91c92_resume, | ||
2367 | }; | 2319 | }; |
2368 | 2320 | ||
2369 | static int __init init_smc91c92_cs(void) | 2321 | static int __init init_smc91c92_cs(void) |
@@ -2374,7 +2326,6 @@ static int __init init_smc91c92_cs(void) | |||
2374 | static void __exit exit_smc91c92_cs(void) | 2326 | static void __exit exit_smc91c92_cs(void) |
2375 | { | 2327 | { |
2376 | pcmcia_unregister_driver(&smc91c92_cs_driver); | 2328 | pcmcia_unregister_driver(&smc91c92_cs_driver); |
2377 | BUG_ON(dev_list != NULL); | ||
2378 | } | 2329 | } |
2379 | 2330 | ||
2380 | module_init(init_smc91c92_cs); | 2331 | module_init(init_smc91c92_cs); |
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index ce143f08638a..049c34b37067 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c | |||
@@ -292,8 +292,6 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, | |||
292 | static int has_ce2_string(dev_link_t * link); | 292 | static int has_ce2_string(dev_link_t * link); |
293 | static void xirc2ps_config(dev_link_t * link); | 293 | static void xirc2ps_config(dev_link_t * link); |
294 | static void xirc2ps_release(dev_link_t * link); | 294 | static void xirc2ps_release(dev_link_t * link); |
295 | static int xirc2ps_event(event_t event, int priority, | ||
296 | event_callback_args_t * args); | ||
297 | 295 | ||
298 | /**************** | 296 | /**************** |
299 | * The attach() and detach() entry points are used to create and destroy | 297 | * The attach() and detach() entry points are used to create and destroy |
@@ -301,8 +299,7 @@ static int xirc2ps_event(event_t event, int priority, | |||
301 | * needed to manage one actual PCMCIA card. | 299 | * needed to manage one actual PCMCIA card. |
302 | */ | 300 | */ |
303 | 301 | ||
304 | static dev_link_t *xirc2ps_attach(void); | 302 | static void xirc2ps_detach(struct pcmcia_device *p_dev); |
305 | static void xirc2ps_detach(dev_link_t *); | ||
306 | 303 | ||
307 | /**************** | 304 | /**************** |
308 | * You'll also need to prototype all the functions that will actually | 305 | * You'll also need to prototype all the functions that will actually |
@@ -313,14 +310,6 @@ static void xirc2ps_detach(dev_link_t *); | |||
313 | 310 | ||
314 | static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 311 | static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
315 | 312 | ||
316 | /* | ||
317 | * The dev_info variable is the "key" that is used to match up this | ||
318 | * device driver with appropriate cards, through the card configuration | ||
319 | * database. | ||
320 | */ | ||
321 | |||
322 | static dev_info_t dev_info = "xirc2ps_cs"; | ||
323 | |||
324 | /**************** | 313 | /**************** |
325 | * A linked list of "instances" of the device. Each actual | 314 | * A linked list of "instances" of the device. Each actual |
326 | * PCMCIA card corresponds to one device instance, and is described | 315 | * PCMCIA card corresponds to one device instance, and is described |
@@ -331,15 +320,7 @@ static dev_info_t dev_info = "xirc2ps_cs"; | |||
331 | * device numbers are used to derive the corresponding array index. | 320 | * device numbers are used to derive the corresponding array index. |
332 | */ | 321 | */ |
333 | 322 | ||
334 | static dev_link_t *dev_list; | ||
335 | |||
336 | /**************** | 323 | /**************** |
337 | * A dev_link_t structure has fields for most things that are needed | ||
338 | * to keep track of a socket, but there will usually be some device | ||
339 | * specific information that also needs to be kept track of. The | ||
340 | * 'priv' pointer in a dev_link_t structure can be used to point to | ||
341 | * a device-specific private data structure, like this. | ||
342 | * | ||
343 | * A driver needs to provide a dev_node_t structure for each device | 324 | * A driver needs to provide a dev_node_t structure for each device |
344 | * on a card. In some cases, there is only one device per card (for | 325 | * on a card. In some cases, there is only one device per card (for |
345 | * example, ethernet cards, modems). In other cases, there may be | 326 | * example, ethernet cards, modems). In other cases, there may be |
@@ -571,21 +552,19 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) | |||
571 | * card insertion event. | 552 | * card insertion event. |
572 | */ | 553 | */ |
573 | 554 | ||
574 | static dev_link_t * | 555 | static int |
575 | xirc2ps_attach(void) | 556 | xirc2ps_attach(struct pcmcia_device *p_dev) |
576 | { | 557 | { |
577 | client_reg_t client_reg; | ||
578 | dev_link_t *link; | 558 | dev_link_t *link; |
579 | struct net_device *dev; | 559 | struct net_device *dev; |
580 | local_info_t *local; | 560 | local_info_t *local; |
581 | int err; | ||
582 | 561 | ||
583 | DEBUG(0, "attach()\n"); | 562 | DEBUG(0, "attach()\n"); |
584 | 563 | ||
585 | /* Allocate the device structure */ | 564 | /* Allocate the device structure */ |
586 | dev = alloc_etherdev(sizeof(local_info_t)); | 565 | dev = alloc_etherdev(sizeof(local_info_t)); |
587 | if (!dev) | 566 | if (!dev) |
588 | return NULL; | 567 | return -ENOMEM; |
589 | local = netdev_priv(dev); | 568 | local = netdev_priv(dev); |
590 | link = &local->link; | 569 | link = &local->link; |
591 | link->priv = dev; | 570 | link->priv = dev; |
@@ -614,19 +593,13 @@ xirc2ps_attach(void) | |||
614 | dev->watchdog_timeo = TX_TIMEOUT; | 593 | dev->watchdog_timeo = TX_TIMEOUT; |
615 | #endif | 594 | #endif |
616 | 595 | ||
617 | /* Register with Card Services */ | 596 | link->handle = p_dev; |
618 | link->next = dev_list; | 597 | p_dev->instance = link; |
619 | dev_list = link; | 598 | |
620 | client_reg.dev_info = &dev_info; | 599 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
621 | client_reg.Version = 0x0210; | 600 | xirc2ps_config(link); |
622 | client_reg.event_callback_args.client_data = link; | ||
623 | if ((err = pcmcia_register_client(&link->handle, &client_reg))) { | ||
624 | cs_error(link->handle, RegisterClient, err); | ||
625 | xirc2ps_detach(link); | ||
626 | return NULL; | ||
627 | } | ||
628 | 601 | ||
629 | return link; | 602 | return 0; |
630 | } /* xirc2ps_attach */ | 603 | } /* xirc2ps_attach */ |
631 | 604 | ||
632 | /**************** | 605 | /**************** |
@@ -637,40 +610,19 @@ xirc2ps_attach(void) | |||
637 | */ | 610 | */ |
638 | 611 | ||
639 | static void | 612 | static void |
640 | xirc2ps_detach(dev_link_t * link) | 613 | xirc2ps_detach(struct pcmcia_device *p_dev) |
641 | { | 614 | { |
615 | dev_link_t *link = dev_to_instance(p_dev); | ||
642 | struct net_device *dev = link->priv; | 616 | struct net_device *dev = link->priv; |
643 | dev_link_t **linkp; | ||
644 | 617 | ||
645 | DEBUG(0, "detach(0x%p)\n", link); | 618 | DEBUG(0, "detach(0x%p)\n", link); |
646 | 619 | ||
647 | /* Locate device structure */ | ||
648 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
649 | if (*linkp == link) | ||
650 | break; | ||
651 | if (!*linkp) { | ||
652 | DEBUG(0, "detach(0x%p): dev_link lost\n", link); | ||
653 | return; | ||
654 | } | ||
655 | |||
656 | if (link->dev) | 620 | if (link->dev) |
657 | unregister_netdev(dev); | 621 | unregister_netdev(dev); |
658 | 622 | ||
659 | /* | ||
660 | * If the device is currently configured and active, we won't | ||
661 | * actually delete it yet. Instead, it is marked so that when | ||
662 | * the release() function is called, that will trigger a proper | ||
663 | * detach(). | ||
664 | */ | ||
665 | if (link->state & DEV_CONFIG) | 623 | if (link->state & DEV_CONFIG) |
666 | xirc2ps_release(link); | 624 | xirc2ps_release(link); |
667 | 625 | ||
668 | /* Break the link with Card Services */ | ||
669 | if (link->handle) | ||
670 | pcmcia_deregister_client(link->handle); | ||
671 | |||
672 | /* Unlink device structure, free it */ | ||
673 | *linkp = link->next; | ||
674 | free_netdev(dev); | 626 | free_netdev(dev); |
675 | } /* xirc2ps_detach */ | 627 | } /* xirc2ps_detach */ |
676 | 628 | ||
@@ -1157,67 +1109,41 @@ xirc2ps_release(dev_link_t *link) | |||
1157 | 1109 | ||
1158 | /*====================================================================*/ | 1110 | /*====================================================================*/ |
1159 | 1111 | ||
1160 | /**************** | ||
1161 | * The card status event handler. Mostly, this schedules other | ||
1162 | * stuff to run after an event is received. A CARD_REMOVAL event | ||
1163 | * also sets some flags to discourage the net drivers from trying | ||
1164 | * to talk to the card any more. | ||
1165 | * | ||
1166 | * When a CARD_REMOVAL event is received, we immediately set a flag | ||
1167 | * to block future accesses to this device. All the functions that | ||
1168 | * actually access the device should check this flag to make sure | ||
1169 | * the card is still present. | ||
1170 | */ | ||
1171 | 1112 | ||
1172 | static int | 1113 | static int xirc2ps_suspend(struct pcmcia_device *p_dev) |
1173 | xirc2ps_event(event_t event, int priority, | ||
1174 | event_callback_args_t * args) | ||
1175 | { | 1114 | { |
1176 | dev_link_t *link = args->client_data; | 1115 | dev_link_t *link = dev_to_instance(p_dev); |
1177 | struct net_device *dev = link->priv; | 1116 | struct net_device *dev = link->priv; |
1178 | |||
1179 | DEBUG(0, "event(%d)\n", (int)event); | ||
1180 | 1117 | ||
1181 | switch (event) { | ||
1182 | case CS_EVENT_REGISTRATION_COMPLETE: | ||
1183 | DEBUG(0, "registration complete\n"); | ||
1184 | break; | ||
1185 | case CS_EVENT_CARD_REMOVAL: | ||
1186 | link->state &= ~DEV_PRESENT; | ||
1187 | if (link->state & DEV_CONFIG) | ||
1188 | netif_device_detach(dev); | ||
1189 | break; | ||
1190 | case CS_EVENT_CARD_INSERTION: | ||
1191 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1192 | xirc2ps_config(link); | ||
1193 | break; | ||
1194 | case CS_EVENT_PM_SUSPEND: | ||
1195 | link->state |= DEV_SUSPEND; | 1118 | link->state |= DEV_SUSPEND; |
1196 | /* Fall through... */ | ||
1197 | case CS_EVENT_RESET_PHYSICAL: | ||
1198 | if (link->state & DEV_CONFIG) { | 1119 | if (link->state & DEV_CONFIG) { |
1199 | if (link->open) { | 1120 | if (link->open) { |
1200 | netif_device_detach(dev); | 1121 | netif_device_detach(dev); |
1201 | do_powerdown(dev); | 1122 | do_powerdown(dev); |
1202 | } | 1123 | } |
1203 | pcmcia_release_configuration(link->handle); | 1124 | pcmcia_release_configuration(link->handle); |
1204 | } | 1125 | } |
1205 | break; | 1126 | |
1206 | case CS_EVENT_PM_RESUME: | 1127 | return 0; |
1128 | } | ||
1129 | |||
1130 | static int xirc2ps_resume(struct pcmcia_device *p_dev) | ||
1131 | { | ||
1132 | dev_link_t *link = dev_to_instance(p_dev); | ||
1133 | struct net_device *dev = link->priv; | ||
1134 | |||
1207 | link->state &= ~DEV_SUSPEND; | 1135 | link->state &= ~DEV_SUSPEND; |
1208 | /* Fall through... */ | ||
1209 | case CS_EVENT_CARD_RESET: | ||
1210 | if (link->state & DEV_CONFIG) { | 1136 | if (link->state & DEV_CONFIG) { |
1211 | pcmcia_request_configuration(link->handle, &link->conf); | 1137 | pcmcia_request_configuration(link->handle, &link->conf); |
1212 | if (link->open) { | 1138 | if (link->open) { |
1213 | do_reset(dev,1); | 1139 | do_reset(dev,1); |
1214 | netif_device_attach(dev); | 1140 | netif_device_attach(dev); |
1215 | } | 1141 | } |
1216 | } | 1142 | } |
1217 | break; | 1143 | |
1218 | } | 1144 | return 0; |
1219 | return 0; | 1145 | } |
1220 | } /* xirc2ps_event */ | 1146 | |
1221 | 1147 | ||
1222 | /*====================================================================*/ | 1148 | /*====================================================================*/ |
1223 | 1149 | ||
@@ -2009,10 +1935,11 @@ static struct pcmcia_driver xirc2ps_cs_driver = { | |||
2009 | .drv = { | 1935 | .drv = { |
2010 | .name = "xirc2ps_cs", | 1936 | .name = "xirc2ps_cs", |
2011 | }, | 1937 | }, |
2012 | .attach = xirc2ps_attach, | 1938 | .probe = xirc2ps_attach, |
2013 | .event = xirc2ps_event, | 1939 | .remove = xirc2ps_detach, |
2014 | .detach = xirc2ps_detach, | ||
2015 | .id_table = xirc2ps_ids, | 1940 | .id_table = xirc2ps_ids, |
1941 | .suspend = xirc2ps_suspend, | ||
1942 | .resume = xirc2ps_resume, | ||
2016 | }; | 1943 | }; |
2017 | 1944 | ||
2018 | static int __init | 1945 | static int __init |
@@ -2025,7 +1952,6 @@ static void __exit | |||
2025 | exit_xirc2ps_cs(void) | 1952 | exit_xirc2ps_cs(void) |
2026 | { | 1953 | { |
2027 | pcmcia_unregister_driver(&xirc2ps_cs_driver); | 1954 | pcmcia_unregister_driver(&xirc2ps_cs_driver); |
2028 | BUG_ON(dev_list != NULL); | ||
2029 | } | 1955 | } |
2030 | 1956 | ||
2031 | module_init(init_xirc2ps_cs); | 1957 | module_init(init_xirc2ps_cs); |
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 | /* |
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 17d1fd90f832..d6f4a5a3e55a 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
@@ -93,8 +93,6 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); | |||
93 | 93 | ||
94 | static void atmel_config(dev_link_t *link); | 94 | static void atmel_config(dev_link_t *link); |
95 | static void atmel_release(dev_link_t *link); | 95 | static void atmel_release(dev_link_t *link); |
96 | static int atmel_event(event_t event, int priority, | ||
97 | event_callback_args_t *args); | ||
98 | 96 | ||
99 | /* | 97 | /* |
100 | The attach() and detach() entry points are used to create and destroy | 98 | The attach() and detach() entry points are used to create and destroy |
@@ -102,8 +100,7 @@ static int atmel_event(event_t event, int priority, | |||
102 | needed to manage one actual PCMCIA card. | 100 | needed to manage one actual PCMCIA card. |
103 | */ | 101 | */ |
104 | 102 | ||
105 | static dev_link_t *atmel_attach(void); | 103 | static void atmel_detach(struct pcmcia_device *p_dev); |
106 | static void atmel_detach(dev_link_t *); | ||
107 | 104 | ||
108 | /* | 105 | /* |
109 | You'll also need to prototype all the functions that will actually | 106 | You'll also need to prototype all the functions that will actually |
@@ -113,14 +110,6 @@ static void atmel_detach(dev_link_t *); | |||
113 | */ | 110 | */ |
114 | 111 | ||
115 | /* | 112 | /* |
116 | The dev_info variable is the "key" that is used to match up this | ||
117 | device driver with appropriate cards, through the card configuration | ||
118 | database. | ||
119 | */ | ||
120 | |||
121 | static dev_info_t dev_info = "atmel_cs"; | ||
122 | |||
123 | /* | ||
124 | A linked list of "instances" of the atmelnet device. Each actual | 113 | A linked list of "instances" of the atmelnet device. Each actual |
125 | PCMCIA card corresponds to one device instance, and is described | 114 | PCMCIA card corresponds to one device instance, and is described |
126 | by one dev_link_t structure (defined in ds.h). | 115 | by one dev_link_t structure (defined in ds.h). |
@@ -130,15 +119,7 @@ static dev_info_t dev_info = "atmel_cs"; | |||
130 | device numbers are used to derive the corresponding array index. | 119 | device numbers are used to derive the corresponding array index. |
131 | */ | 120 | */ |
132 | 121 | ||
133 | static dev_link_t *dev_list = NULL; | ||
134 | |||
135 | /* | 122 | /* |
136 | A dev_link_t structure has fields for most things that are needed | ||
137 | to keep track of a socket, but there will usually be some device | ||
138 | specific information that also needs to be kept track of. The | ||
139 | 'priv' pointer in a dev_link_t structure can be used to point to | ||
140 | a device-specific private data structure, like this. | ||
141 | |||
142 | A driver needs to provide a dev_node_t structure for each device | 123 | A driver needs to provide a dev_node_t structure for each device |
143 | on a card. In some cases, there is only one device per card (for | 124 | on a card. In some cases, there is only one device per card (for |
144 | example, ethernet cards, modems). In other cases, there may be | 125 | example, ethernet cards, modems). In other cases, there may be |
@@ -171,27 +152,25 @@ typedef struct local_info_t { | |||
171 | 152 | ||
172 | ======================================================================*/ | 153 | ======================================================================*/ |
173 | 154 | ||
174 | static dev_link_t *atmel_attach(void) | 155 | static int atmel_attach(struct pcmcia_device *p_dev) |
175 | { | 156 | { |
176 | client_reg_t client_reg; | ||
177 | dev_link_t *link; | 157 | dev_link_t *link; |
178 | local_info_t *local; | 158 | local_info_t *local; |
179 | int ret; | 159 | |
180 | |||
181 | DEBUG(0, "atmel_attach()\n"); | 160 | DEBUG(0, "atmel_attach()\n"); |
182 | 161 | ||
183 | /* Initialize the dev_link_t structure */ | 162 | /* Initialize the dev_link_t structure */ |
184 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | 163 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); |
185 | if (!link) { | 164 | if (!link) { |
186 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); | 165 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); |
187 | return NULL; | 166 | return -ENOMEM; |
188 | } | 167 | } |
189 | 168 | ||
190 | /* Interrupt setup */ | 169 | /* Interrupt setup */ |
191 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 170 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
192 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 171 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
193 | link->irq.Handler = NULL; | 172 | link->irq.Handler = NULL; |
194 | 173 | ||
195 | /* | 174 | /* |
196 | General socket configuration defaults can go here. In this | 175 | General socket configuration defaults can go here. In this |
197 | client, we assume very little, and rely on the CIS for almost | 176 | client, we assume very little, and rely on the CIS for almost |
@@ -202,30 +181,23 @@ static dev_link_t *atmel_attach(void) | |||
202 | link->conf.Attributes = 0; | 181 | link->conf.Attributes = 0; |
203 | link->conf.Vcc = 50; | 182 | link->conf.Vcc = 50; |
204 | link->conf.IntType = INT_MEMORY_AND_IO; | 183 | link->conf.IntType = INT_MEMORY_AND_IO; |
205 | 184 | ||
206 | /* Allocate space for private device-specific data */ | 185 | /* Allocate space for private device-specific data */ |
207 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 186 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
208 | if (!local) { | 187 | if (!local) { |
209 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); | 188 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); |
210 | kfree (link); | 189 | kfree (link); |
211 | return NULL; | 190 | return -ENOMEM; |
212 | } | 191 | } |
213 | link->priv = local; | 192 | link->priv = local; |
214 | 193 | ||
215 | /* Register with Card Services */ | 194 | link->handle = p_dev; |
216 | link->next = dev_list; | 195 | p_dev->instance = link; |
217 | dev_list = link; | 196 | |
218 | client_reg.dev_info = &dev_info; | 197 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
219 | client_reg.Version = 0x0210; | 198 | atmel_config(link); |
220 | client_reg.event_callback_args.client_data = link; | 199 | |
221 | ret = pcmcia_register_client(&link->handle, &client_reg); | 200 | return 0; |
222 | if (ret != 0) { | ||
223 | cs_error(link->handle, RegisterClient, ret); | ||
224 | atmel_detach(link); | ||
225 | return NULL; | ||
226 | } | ||
227 | |||
228 | return link; | ||
229 | } /* atmel_attach */ | 201 | } /* atmel_attach */ |
230 | 202 | ||
231 | /*====================================================================== | 203 | /*====================================================================== |
@@ -237,27 +209,15 @@ static dev_link_t *atmel_attach(void) | |||
237 | 209 | ||
238 | ======================================================================*/ | 210 | ======================================================================*/ |
239 | 211 | ||
240 | static void atmel_detach(dev_link_t *link) | 212 | static void atmel_detach(struct pcmcia_device *p_dev) |
241 | { | 213 | { |
242 | dev_link_t **linkp; | 214 | dev_link_t *link = dev_to_instance(p_dev); |
243 | 215 | ||
244 | DEBUG(0, "atmel_detach(0x%p)\n", link); | 216 | DEBUG(0, "atmel_detach(0x%p)\n", link); |
245 | |||
246 | /* Locate device structure */ | ||
247 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
248 | if (*linkp == link) break; | ||
249 | if (*linkp == NULL) | ||
250 | return; | ||
251 | 217 | ||
252 | if (link->state & DEV_CONFIG) | 218 | if (link->state & DEV_CONFIG) |
253 | atmel_release(link); | 219 | atmel_release(link); |
254 | |||
255 | /* Break the link with Card Services */ | ||
256 | if (link->handle) | ||
257 | pcmcia_deregister_client(link->handle); | ||
258 | 220 | ||
259 | /* Unlink device structure, free pieces */ | ||
260 | *linkp = link->next; | ||
261 | kfree(link->priv); | 221 | kfree(link->priv); |
262 | kfree(link); | 222 | kfree(link); |
263 | } | 223 | } |
@@ -477,60 +437,34 @@ static void atmel_release(dev_link_t *link) | |||
477 | link->state &= ~DEV_CONFIG; | 437 | link->state &= ~DEV_CONFIG; |
478 | } | 438 | } |
479 | 439 | ||
480 | /*====================================================================== | 440 | static int atmel_suspend(struct pcmcia_device *dev) |
481 | 441 | { | |
482 | The card status event handler. Mostly, this schedules other | 442 | dev_link_t *link = dev_to_instance(dev); |
483 | stuff to run after an event is received. | 443 | local_info_t *local = link->priv; |
484 | 444 | ||
485 | When a CARD_REMOVAL event is received, we immediately set a | 445 | link->state |= DEV_SUSPEND; |
486 | private flag to block future accesses to this device. All the | 446 | if (link->state & DEV_CONFIG) { |
487 | functions that actually access the device should check this flag | 447 | netif_device_detach(local->eth_dev); |
488 | to make sure the card is still present. | 448 | pcmcia_release_configuration(link->handle); |
489 | 449 | } | |
490 | ======================================================================*/ | 450 | |
451 | return 0; | ||
452 | } | ||
491 | 453 | ||
492 | static int atmel_event(event_t event, int priority, | 454 | static int atmel_resume(struct pcmcia_device *dev) |
493 | event_callback_args_t *args) | ||
494 | { | 455 | { |
495 | dev_link_t *link = args->client_data; | 456 | dev_link_t *link = dev_to_instance(dev); |
496 | local_info_t *local = link->priv; | 457 | local_info_t *local = link->priv; |
497 | 458 | ||
498 | DEBUG(1, "atmel_event(0x%06x)\n", event); | 459 | link->state &= ~DEV_SUSPEND; |
499 | 460 | if (link->state & DEV_CONFIG) { | |
500 | switch (event) { | 461 | pcmcia_request_configuration(link->handle, &link->conf); |
501 | case CS_EVENT_CARD_REMOVAL: | 462 | atmel_open(local->eth_dev); |
502 | link->state &= ~DEV_PRESENT; | 463 | netif_device_attach(local->eth_dev); |
503 | if (link->state & DEV_CONFIG) { | ||
504 | netif_device_detach(local->eth_dev); | ||
505 | atmel_release(link); | ||
506 | } | ||
507 | break; | ||
508 | case CS_EVENT_CARD_INSERTION: | ||
509 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
510 | atmel_config(link); | ||
511 | break; | ||
512 | case CS_EVENT_PM_SUSPEND: | ||
513 | link->state |= DEV_SUSPEND; | ||
514 | /* Fall through... */ | ||
515 | case CS_EVENT_RESET_PHYSICAL: | ||
516 | if (link->state & DEV_CONFIG) { | ||
517 | netif_device_detach(local->eth_dev); | ||
518 | pcmcia_release_configuration(link->handle); | ||
519 | } | ||
520 | break; | ||
521 | case CS_EVENT_PM_RESUME: | ||
522 | link->state &= ~DEV_SUSPEND; | ||
523 | /* Fall through... */ | ||
524 | case CS_EVENT_CARD_RESET: | ||
525 | if (link->state & DEV_CONFIG) { | ||
526 | pcmcia_request_configuration(link->handle, &link->conf); | ||
527 | atmel_open(local->eth_dev); | ||
528 | netif_device_attach(local->eth_dev); | ||
529 | } | ||
530 | break; | ||
531 | } | 464 | } |
465 | |||
532 | return 0; | 466 | return 0; |
533 | } /* atmel_event */ | 467 | } |
534 | 468 | ||
535 | /*====================================================================*/ | 469 | /*====================================================================*/ |
536 | /* We use the driver_info field to store the correct firmware type for a card. */ | 470 | /* We use the driver_info field to store the correct firmware type for a card. */ |
@@ -581,10 +515,11 @@ static struct pcmcia_driver atmel_driver = { | |||
581 | .drv = { | 515 | .drv = { |
582 | .name = "atmel_cs", | 516 | .name = "atmel_cs", |
583 | }, | 517 | }, |
584 | .attach = atmel_attach, | 518 | .probe = atmel_attach, |
585 | .event = atmel_event, | 519 | .remove = atmel_detach, |
586 | .detach = atmel_detach, | ||
587 | .id_table = atmel_ids, | 520 | .id_table = atmel_ids, |
521 | .suspend = atmel_suspend, | ||
522 | .resume = atmel_resume, | ||
588 | }; | 523 | }; |
589 | 524 | ||
590 | static int atmel_cs_init(void) | 525 | static int atmel_cs_init(void) |
@@ -595,7 +530,6 @@ static int atmel_cs_init(void) | |||
595 | static void atmel_cs_cleanup(void) | 530 | static void atmel_cs_cleanup(void) |
596 | { | 531 | { |
597 | pcmcia_unregister_driver(&atmel_driver); | 532 | pcmcia_unregister_driver(&atmel_driver); |
598 | BUG_ON(dev_list != NULL); | ||
599 | } | 533 | } |
600 | 534 | ||
601 | /* | 535 | /* |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 2643976a6677..8bc0b528548f 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -25,7 +25,6 @@ | |||
25 | 25 | ||
26 | static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)"; | 26 | static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)"; |
27 | static dev_info_t dev_info = "hostap_cs"; | 27 | static dev_info_t dev_info = "hostap_cs"; |
28 | static dev_link_t *dev_list = NULL; | ||
29 | 28 | ||
30 | MODULE_AUTHOR("Jouni Malinen"); | 29 | MODULE_AUTHOR("Jouni Malinen"); |
31 | MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " | 30 | MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " |
@@ -203,10 +202,9 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) | |||
203 | 202 | ||
204 | 203 | ||
205 | 204 | ||
206 | static void prism2_detach(dev_link_t *link); | 205 | static void prism2_detach(struct pcmcia_device *p_dev); |
207 | static void prism2_release(u_long arg); | 206 | static void prism2_release(u_long arg); |
208 | static int prism2_event(event_t event, int priority, | 207 | static int prism2_config(dev_link_t *link); |
209 | event_callback_args_t *args); | ||
210 | 208 | ||
211 | 209 | ||
212 | static int prism2_pccard_card_present(local_info_t *local) | 210 | static int prism2_pccard_card_present(local_info_t *local) |
@@ -503,15 +501,13 @@ static struct prism2_helper_functions prism2_pccard_funcs = | |||
503 | 501 | ||
504 | /* allocate local data and register with CardServices | 502 | /* allocate local data and register with CardServices |
505 | * initialize dev_link structure, but do not configure the card yet */ | 503 | * initialize dev_link structure, but do not configure the card yet */ |
506 | static dev_link_t *prism2_attach(void) | 504 | static int prism2_attach(struct pcmcia_device *p_dev) |
507 | { | 505 | { |
508 | dev_link_t *link; | 506 | dev_link_t *link; |
509 | client_reg_t client_reg; | ||
510 | int ret; | ||
511 | 507 | ||
512 | link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); | 508 | link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); |
513 | if (link == NULL) | 509 | if (link == NULL) |
514 | return NULL; | 510 | return -ENOMEM; |
515 | 511 | ||
516 | memset(link, 0, sizeof(dev_link_t)); | 512 | memset(link, 0, sizeof(dev_link_t)); |
517 | 513 | ||
@@ -519,50 +515,27 @@ static dev_link_t *prism2_attach(void) | |||
519 | link->conf.Vcc = 33; | 515 | link->conf.Vcc = 33; |
520 | link->conf.IntType = INT_MEMORY_AND_IO; | 516 | link->conf.IntType = INT_MEMORY_AND_IO; |
521 | 517 | ||
522 | /* register with CardServices */ | 518 | link->handle = p_dev; |
523 | link->next = dev_list; | 519 | p_dev->instance = link; |
524 | dev_list = link; | 520 | |
525 | client_reg.dev_info = &dev_info; | 521 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
526 | client_reg.Version = 0x0210; | 522 | if (prism2_config(link)) |
527 | client_reg.event_callback_args.client_data = link; | 523 | PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); |
528 | ret = pcmcia_register_client(&link->handle, &client_reg); | 524 | |
529 | if (ret != CS_SUCCESS) { | 525 | return 0; |
530 | cs_error(link->handle, RegisterClient, ret); | ||
531 | prism2_detach(link); | ||
532 | return NULL; | ||
533 | } | ||
534 | return link; | ||
535 | } | 526 | } |
536 | 527 | ||
537 | 528 | ||
538 | static void prism2_detach(dev_link_t *link) | 529 | static void prism2_detach(struct pcmcia_device *p_dev) |
539 | { | 530 | { |
540 | dev_link_t **linkp; | 531 | dev_link_t *link = dev_to_instance(p_dev); |
541 | 532 | ||
542 | PDEBUG(DEBUG_FLOW, "prism2_detach\n"); | 533 | PDEBUG(DEBUG_FLOW, "prism2_detach\n"); |
543 | 534 | ||
544 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
545 | if (*linkp == link) | ||
546 | break; | ||
547 | if (*linkp == NULL) { | ||
548 | printk(KERN_WARNING "%s: Attempt to detach non-existing " | ||
549 | "PCMCIA client\n", dev_info); | ||
550 | return; | ||
551 | } | ||
552 | |||
553 | if (link->state & DEV_CONFIG) { | 535 | if (link->state & DEV_CONFIG) { |
554 | prism2_release((u_long)link); | 536 | prism2_release((u_long)link); |
555 | } | 537 | } |
556 | 538 | ||
557 | if (link->handle) { | ||
558 | int res = pcmcia_deregister_client(link->handle); | ||
559 | if (res) { | ||
560 | printk("CardService(DeregisterClient) => %d\n", res); | ||
561 | cs_error(link->handle, DeregisterClient, res); | ||
562 | } | ||
563 | } | ||
564 | |||
565 | *linkp = link->next; | ||
566 | /* release net devices */ | 539 | /* release net devices */ |
567 | if (link->priv) { | 540 | if (link->priv) { |
568 | struct hostap_cs_priv *hw_priv; | 541 | struct hostap_cs_priv *hw_priv; |
@@ -846,84 +819,58 @@ static void prism2_release(u_long arg) | |||
846 | PDEBUG(DEBUG_FLOW, "release - done\n"); | 819 | PDEBUG(DEBUG_FLOW, "release - done\n"); |
847 | } | 820 | } |
848 | 821 | ||
849 | 822 | static int hostap_cs_suspend(struct pcmcia_device *p_dev) | |
850 | static int prism2_event(event_t event, int priority, | ||
851 | event_callback_args_t *args) | ||
852 | { | 823 | { |
853 | dev_link_t *link = args->client_data; | 824 | dev_link_t *link = dev_to_instance(p_dev); |
854 | struct net_device *dev = (struct net_device *) link->priv; | 825 | struct net_device *dev = (struct net_device *) link->priv; |
855 | int dev_open = 0; | 826 | int dev_open = 0; |
856 | 827 | ||
828 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); | ||
829 | |||
830 | link->state |= DEV_SUSPEND; | ||
831 | |||
857 | if (link->state & DEV_CONFIG) { | 832 | if (link->state & DEV_CONFIG) { |
858 | struct hostap_interface *iface = netdev_priv(dev); | 833 | struct hostap_interface *iface = netdev_priv(dev); |
859 | if (iface && iface->local) | 834 | if (iface && iface->local) |
860 | dev_open = iface->local->num_dev_open > 0; | 835 | dev_open = iface->local->num_dev_open > 0; |
861 | } | 836 | if (dev_open) { |
862 | |||
863 | switch (event) { | ||
864 | case CS_EVENT_CARD_INSERTION: | ||
865 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_INSERTION\n", dev_info); | ||
866 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
867 | if (prism2_config(link)) { | ||
868 | PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); | ||
869 | } | ||
870 | break; | ||
871 | |||
872 | case CS_EVENT_CARD_REMOVAL: | ||
873 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_REMOVAL\n", dev_info); | ||
874 | link->state &= ~DEV_PRESENT; | ||
875 | if (link->state & DEV_CONFIG) { | ||
876 | netif_stop_queue(dev); | 837 | netif_stop_queue(dev); |
877 | netif_device_detach(dev); | 838 | netif_device_detach(dev); |
878 | prism2_release((u_long) link); | ||
879 | } | 839 | } |
880 | break; | 840 | prism2_suspend(dev); |
841 | pcmcia_release_configuration(link->handle); | ||
842 | } | ||
881 | 843 | ||
882 | case CS_EVENT_PM_SUSPEND: | 844 | return 0; |
883 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); | 845 | } |
884 | link->state |= DEV_SUSPEND; | ||
885 | /* fall through */ | ||
886 | |||
887 | case CS_EVENT_RESET_PHYSICAL: | ||
888 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info); | ||
889 | if (link->state & DEV_CONFIG) { | ||
890 | if (dev_open) { | ||
891 | netif_stop_queue(dev); | ||
892 | netif_device_detach(dev); | ||
893 | } | ||
894 | prism2_suspend(dev); | ||
895 | pcmcia_release_configuration(link->handle); | ||
896 | } | ||
897 | break; | ||
898 | 846 | ||
899 | case CS_EVENT_PM_RESUME: | 847 | static int hostap_cs_resume(struct pcmcia_device *p_dev) |
900 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); | 848 | { |
901 | link->state &= ~DEV_SUSPEND; | 849 | dev_link_t *link = dev_to_instance(p_dev); |
902 | /* fall through */ | 850 | struct net_device *dev = (struct net_device *) link->priv; |
903 | 851 | int dev_open = 0; | |
904 | case CS_EVENT_CARD_RESET: | ||
905 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_RESET\n", dev_info); | ||
906 | if (link->state & DEV_CONFIG) { | ||
907 | pcmcia_request_configuration(link->handle, | ||
908 | &link->conf); | ||
909 | prism2_hw_shutdown(dev, 1); | ||
910 | prism2_hw_config(dev, dev_open ? 0 : 1); | ||
911 | if (dev_open) { | ||
912 | netif_device_attach(dev); | ||
913 | netif_start_queue(dev); | ||
914 | } | ||
915 | } | ||
916 | break; | ||
917 | 852 | ||
918 | default: | 853 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); |
919 | PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n", | 854 | |
920 | dev_info, event); | 855 | link->state &= ~DEV_SUSPEND; |
921 | break; | 856 | if (link->state & DEV_CONFIG) { |
857 | struct hostap_interface *iface = netdev_priv(dev); | ||
858 | if (iface && iface->local) | ||
859 | dev_open = iface->local->num_dev_open > 0; | ||
860 | |||
861 | pcmcia_request_configuration(link->handle, &link->conf); | ||
862 | |||
863 | prism2_hw_shutdown(dev, 1); | ||
864 | prism2_hw_config(dev, dev_open ? 0 : 1); | ||
865 | if (dev_open) { | ||
866 | netif_device_attach(dev); | ||
867 | netif_start_queue(dev); | ||
868 | } | ||
922 | } | 869 | } |
870 | |||
923 | return 0; | 871 | return 0; |
924 | } | 872 | } |
925 | 873 | ||
926 | |||
927 | static struct pcmcia_device_id hostap_cs_ids[] = { | 874 | static struct pcmcia_device_id hostap_cs_ids[] = { |
928 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), | 875 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), |
929 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), | 876 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), |
@@ -982,11 +929,12 @@ static struct pcmcia_driver hostap_driver = { | |||
982 | .drv = { | 929 | .drv = { |
983 | .name = "hostap_cs", | 930 | .name = "hostap_cs", |
984 | }, | 931 | }, |
985 | .attach = prism2_attach, | 932 | .probe = prism2_attach, |
986 | .detach = prism2_detach, | 933 | .remove = prism2_detach, |
987 | .owner = THIS_MODULE, | 934 | .owner = THIS_MODULE, |
988 | .event = prism2_event, | ||
989 | .id_table = hostap_cs_ids, | 935 | .id_table = hostap_cs_ids, |
936 | .suspend = hostap_cs_suspend, | ||
937 | .resume = hostap_cs_resume, | ||
990 | }; | 938 | }; |
991 | 939 | ||
992 | static int __init init_prism2_pccard(void) | 940 | static int __init init_prism2_pccard(void) |
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 92793b958e32..bf6271ee387a 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c | |||
@@ -166,8 +166,6 @@ static char *version = | |||
166 | #define DEBUG(n, args...) | 166 | #define DEBUG(n, args...) |
167 | #endif | 167 | #endif |
168 | 168 | ||
169 | static dev_info_t dev_info = "netwave_cs"; | ||
170 | |||
171 | /*====================================================================*/ | 169 | /*====================================================================*/ |
172 | 170 | ||
173 | /* Parameters that can be set with 'insmod' */ | 171 | /* Parameters that can be set with 'insmod' */ |
@@ -195,12 +193,9 @@ module_param(mem_speed, int, 0); | |||
195 | 193 | ||
196 | /* PCMCIA (Card Services) related functions */ | 194 | /* PCMCIA (Card Services) related functions */ |
197 | static void netwave_release(dev_link_t *link); /* Card removal */ | 195 | static void netwave_release(dev_link_t *link); /* Card removal */ |
198 | static int netwave_event(event_t event, int priority, | ||
199 | event_callback_args_t *args); | ||
200 | static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card | 196 | static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card |
201 | insertion */ | 197 | insertion */ |
202 | static dev_link_t *netwave_attach(void); /* Create instance */ | 198 | static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */ |
203 | static void netwave_detach(dev_link_t *); /* Destroy instance */ | ||
204 | 199 | ||
205 | /* Hardware configuration */ | 200 | /* Hardware configuration */ |
206 | static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase); | 201 | static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase); |
@@ -228,17 +223,6 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev); | |||
228 | static void set_multicast_list(struct net_device *dev); | 223 | static void set_multicast_list(struct net_device *dev); |
229 | 224 | ||
230 | /* | 225 | /* |
231 | A linked list of "instances" of the skeleton device. Each actual | ||
232 | PCMCIA card corresponds to one device instance, and is described | ||
233 | by one dev_link_t structure (defined in ds.h). | ||
234 | |||
235 | You may not want to use a linked list for this -- for example, the | ||
236 | memory card driver uses an array of dev_link_t pointers, where minor | ||
237 | device numbers are used to derive the corresponding array index. | ||
238 | */ | ||
239 | static dev_link_t *dev_list; | ||
240 | |||
241 | /* | ||
242 | A dev_link_t structure has fields for most things that are needed | 226 | A dev_link_t structure has fields for most things that are needed |
243 | to keep track of a socket, but there will usually be some device | 227 | to keep track of a socket, but there will usually be some device |
244 | specific information that also needs to be kept track of. The | 228 | specific information that also needs to be kept track of. The |
@@ -394,20 +378,18 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) | |||
394 | * configure the card at this point -- we wait until we receive a | 378 | * configure the card at this point -- we wait until we receive a |
395 | * card insertion event. | 379 | * card insertion event. |
396 | */ | 380 | */ |
397 | static dev_link_t *netwave_attach(void) | 381 | static int netwave_attach(struct pcmcia_device *p_dev) |
398 | { | 382 | { |
399 | client_reg_t client_reg; | ||
400 | dev_link_t *link; | 383 | dev_link_t *link; |
401 | struct net_device *dev; | 384 | struct net_device *dev; |
402 | netwave_private *priv; | 385 | netwave_private *priv; |
403 | int ret; | 386 | |
404 | |||
405 | DEBUG(0, "netwave_attach()\n"); | 387 | DEBUG(0, "netwave_attach()\n"); |
406 | 388 | ||
407 | /* Initialize the dev_link_t structure */ | 389 | /* Initialize the dev_link_t structure */ |
408 | dev = alloc_etherdev(sizeof(netwave_private)); | 390 | dev = alloc_etherdev(sizeof(netwave_private)); |
409 | if (!dev) | 391 | if (!dev) |
410 | return NULL; | 392 | return -ENOMEM; |
411 | priv = netdev_priv(dev); | 393 | priv = netdev_priv(dev); |
412 | link = &priv->link; | 394 | link = &priv->link; |
413 | link->priv = dev; | 395 | link->priv = dev; |
@@ -449,21 +431,14 @@ static dev_link_t *netwave_attach(void) | |||
449 | dev->open = &netwave_open; | 431 | dev->open = &netwave_open; |
450 | dev->stop = &netwave_close; | 432 | dev->stop = &netwave_close; |
451 | link->irq.Instance = dev; | 433 | link->irq.Instance = dev; |
452 | |||
453 | /* Register with Card Services */ | ||
454 | link->next = dev_list; | ||
455 | dev_list = link; | ||
456 | client_reg.dev_info = &dev_info; | ||
457 | client_reg.Version = 0x0210; | ||
458 | client_reg.event_callback_args.client_data = link; | ||
459 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
460 | if (ret != 0) { | ||
461 | cs_error(link->handle, RegisterClient, ret); | ||
462 | netwave_detach(link); | ||
463 | return NULL; | ||
464 | } | ||
465 | 434 | ||
466 | return link; | 435 | link->handle = p_dev; |
436 | p_dev->instance = link; | ||
437 | |||
438 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
439 | netwave_pcmcia_config( link); | ||
440 | |||
441 | return 0; | ||
467 | } /* netwave_attach */ | 442 | } /* netwave_attach */ |
468 | 443 | ||
469 | /* | 444 | /* |
@@ -474,42 +449,20 @@ static dev_link_t *netwave_attach(void) | |||
474 | * structures are freed. Otherwise, the structures will be freed | 449 | * structures are freed. Otherwise, the structures will be freed |
475 | * when the device is released. | 450 | * when the device is released. |
476 | */ | 451 | */ |
477 | static void netwave_detach(dev_link_t *link) | 452 | static void netwave_detach(struct pcmcia_device *p_dev) |
478 | { | 453 | { |
479 | struct net_device *dev = link->priv; | 454 | dev_link_t *link = dev_to_instance(p_dev); |
480 | dev_link_t **linkp; | 455 | struct net_device *dev = link->priv; |
481 | 456 | ||
482 | DEBUG(0, "netwave_detach(0x%p)\n", link); | 457 | DEBUG(0, "netwave_detach(0x%p)\n", link); |
483 | 458 | ||
484 | /* | 459 | if (link->state & DEV_CONFIG) |
485 | If the device is currently configured and active, we won't | 460 | netwave_release(link); |
486 | actually delete it yet. Instead, it is marked so that when | 461 | |
487 | the release() function is called, that will trigger a proper | 462 | if (link->dev) |
488 | detach(). | 463 | unregister_netdev(dev); |
489 | */ | 464 | |
490 | if (link->state & DEV_CONFIG) | 465 | free_netdev(dev); |
491 | netwave_release(link); | ||
492 | |||
493 | /* Break the link with Card Services */ | ||
494 | if (link->handle) | ||
495 | pcmcia_deregister_client(link->handle); | ||
496 | |||
497 | /* Locate device structure */ | ||
498 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
499 | if (*linkp == link) break; | ||
500 | if (*linkp == NULL) | ||
501 | { | ||
502 | DEBUG(1, "netwave_cs: detach fail, '%s' not in list\n", | ||
503 | link->dev->dev_name); | ||
504 | return; | ||
505 | } | ||
506 | |||
507 | /* Unlink device structure, free pieces */ | ||
508 | *linkp = link->next; | ||
509 | if (link->dev) | ||
510 | unregister_netdev(dev); | ||
511 | free_netdev(dev); | ||
512 | |||
513 | } /* netwave_detach */ | 466 | } /* netwave_detach */ |
514 | 467 | ||
515 | /* | 468 | /* |
@@ -935,69 +888,38 @@ static void netwave_release(dev_link_t *link) | |||
935 | link->state &= ~DEV_CONFIG; | 888 | link->state &= ~DEV_CONFIG; |
936 | } | 889 | } |
937 | 890 | ||
938 | /* | 891 | static int netwave_suspend(struct pcmcia_device *p_dev) |
939 | * Function netwave_event (event, priority, args) | ||
940 | * | ||
941 | * The card status event handler. Mostly, this schedules other | ||
942 | * stuff to run after an event is received. A CARD_REMOVAL event | ||
943 | * also sets some flags to discourage the net drivers from trying | ||
944 | * to talk to the card any more. | ||
945 | * | ||
946 | * When a CARD_REMOVAL event is received, we immediately set a flag | ||
947 | * to block future accesses to this device. All the functions that | ||
948 | * actually access the device should check this flag to make sure | ||
949 | * the card is still present. | ||
950 | * | ||
951 | */ | ||
952 | static int netwave_event(event_t event, int priority, | ||
953 | event_callback_args_t *args) | ||
954 | { | 892 | { |
955 | dev_link_t *link = args->client_data; | 893 | dev_link_t *link = dev_to_instance(p_dev); |
956 | struct net_device *dev = link->priv; | 894 | struct net_device *dev = link->priv; |
957 | 895 | ||
958 | DEBUG(1, "netwave_event(0x%06x)\n", event); | ||
959 | |||
960 | switch (event) { | ||
961 | case CS_EVENT_REGISTRATION_COMPLETE: | ||
962 | DEBUG(0, "netwave_cs: registration complete\n"); | ||
963 | break; | ||
964 | |||
965 | case CS_EVENT_CARD_REMOVAL: | ||
966 | link->state &= ~DEV_PRESENT; | ||
967 | if (link->state & DEV_CONFIG) { | ||
968 | netif_device_detach(dev); | ||
969 | netwave_release(link); | ||
970 | } | ||
971 | break; | ||
972 | case CS_EVENT_CARD_INSERTION: | ||
973 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
974 | netwave_pcmcia_config( link); | ||
975 | break; | ||
976 | case CS_EVENT_PM_SUSPEND: | ||
977 | link->state |= DEV_SUSPEND; | 896 | link->state |= DEV_SUSPEND; |
978 | /* Fall through... */ | ||
979 | case CS_EVENT_RESET_PHYSICAL: | ||
980 | if (link->state & DEV_CONFIG) { | 897 | if (link->state & DEV_CONFIG) { |
981 | if (link->open) | 898 | if (link->open) |
982 | netif_device_detach(dev); | 899 | netif_device_detach(dev); |
983 | pcmcia_release_configuration(link->handle); | 900 | pcmcia_release_configuration(link->handle); |
984 | } | 901 | } |
985 | break; | 902 | |
986 | case CS_EVENT_PM_RESUME: | 903 | return 0; |
904 | } | ||
905 | |||
906 | static int netwave_resume(struct pcmcia_device *p_dev) | ||
907 | { | ||
908 | dev_link_t *link = dev_to_instance(p_dev); | ||
909 | struct net_device *dev = link->priv; | ||
910 | |||
987 | link->state &= ~DEV_SUSPEND; | 911 | link->state &= ~DEV_SUSPEND; |
988 | /* Fall through... */ | ||
989 | case CS_EVENT_CARD_RESET: | ||
990 | if (link->state & DEV_CONFIG) { | 912 | if (link->state & DEV_CONFIG) { |
991 | pcmcia_request_configuration(link->handle, &link->conf); | 913 | pcmcia_request_configuration(link->handle, &link->conf); |
992 | if (link->open) { | 914 | if (link->open) { |
993 | netwave_reset(dev); | 915 | netwave_reset(dev); |
994 | netif_device_attach(dev); | 916 | netif_device_attach(dev); |
995 | } | 917 | } |
996 | } | 918 | } |
997 | break; | 919 | |
998 | } | 920 | return 0; |
999 | return 0; | 921 | } |
1000 | } /* netwave_event */ | 922 | |
1001 | 923 | ||
1002 | /* | 924 | /* |
1003 | * Function netwave_doreset (ioBase, ramBase) | 925 | * Function netwave_doreset (ioBase, ramBase) |
@@ -1491,10 +1413,11 @@ static struct pcmcia_driver netwave_driver = { | |||
1491 | .drv = { | 1413 | .drv = { |
1492 | .name = "netwave_cs", | 1414 | .name = "netwave_cs", |
1493 | }, | 1415 | }, |
1494 | .attach = netwave_attach, | 1416 | .probe = netwave_attach, |
1495 | .event = netwave_event, | 1417 | .remove = netwave_detach, |
1496 | .detach = netwave_detach, | ||
1497 | .id_table = netwave_ids, | 1418 | .id_table = netwave_ids, |
1419 | .suspend = netwave_suspend, | ||
1420 | .resume = netwave_resume, | ||
1498 | }; | 1421 | }; |
1499 | 1422 | ||
1500 | static int __init init_netwave_cs(void) | 1423 | static int __init init_netwave_cs(void) |
@@ -1505,7 +1428,6 @@ static int __init init_netwave_cs(void) | |||
1505 | static void __exit exit_netwave_cs(void) | 1428 | static void __exit exit_netwave_cs(void) |
1506 | { | 1429 | { |
1507 | pcmcia_unregister_driver(&netwave_driver); | 1430 | pcmcia_unregister_driver(&netwave_driver); |
1508 | BUG_ON(dev_list != NULL); | ||
1509 | } | 1431 | } |
1510 | 1432 | ||
1511 | module_init(init_netwave_cs); | 1433 | module_init(init_netwave_cs); |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index dc1128a00971..b664708481cc 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -43,17 +43,6 @@ module_param(ignore_cis_vcc, int, 0); | |||
43 | MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); | 43 | MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); |
44 | 44 | ||
45 | /********************************************************************/ | 45 | /********************************************************************/ |
46 | /* Magic constants */ | ||
47 | /********************************************************************/ | ||
48 | |||
49 | /* | ||
50 | * The dev_info variable is the "key" that is used to match up this | ||
51 | * device driver with appropriate cards, through the card | ||
52 | * configuration database. | ||
53 | */ | ||
54 | static dev_info_t dev_info = DRIVER_NAME; | ||
55 | |||
56 | /********************************************************************/ | ||
57 | /* Data structures */ | 46 | /* Data structures */ |
58 | /********************************************************************/ | 47 | /********************************************************************/ |
59 | 48 | ||
@@ -69,19 +58,14 @@ struct orinoco_pccard { | |||
69 | unsigned long hard_reset_in_progress; | 58 | unsigned long hard_reset_in_progress; |
70 | }; | 59 | }; |
71 | 60 | ||
72 | /* | ||
73 | * A linked list of "instances" of the device. Each actual PCMCIA | ||
74 | * card corresponds to one device instance, and is described by one | ||
75 | * dev_link_t structure (defined in ds.h). | ||
76 | */ | ||
77 | static dev_link_t *dev_list; /* = NULL */ | ||
78 | 61 | ||
79 | /********************************************************************/ | 62 | /********************************************************************/ |
80 | /* Function prototypes */ | 63 | /* Function prototypes */ |
81 | /********************************************************************/ | 64 | /********************************************************************/ |
82 | 65 | ||
66 | static void orinoco_cs_config(dev_link_t *link); | ||
83 | static void orinoco_cs_release(dev_link_t *link); | 67 | static void orinoco_cs_release(dev_link_t *link); |
84 | static void orinoco_cs_detach(dev_link_t *link); | 68 | static void orinoco_cs_detach(struct pcmcia_device *p_dev); |
85 | 69 | ||
86 | /********************************************************************/ | 70 | /********************************************************************/ |
87 | /* Device methods */ | 71 | /* Device methods */ |
@@ -119,19 +103,17 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) | |||
119 | * The dev_link structure is initialized, but we don't actually | 103 | * The dev_link structure is initialized, but we don't actually |
120 | * configure the card at this point -- we wait until we receive a card | 104 | * configure the card at this point -- we wait until we receive a card |
121 | * insertion event. */ | 105 | * insertion event. */ |
122 | static dev_link_t * | 106 | static int |
123 | orinoco_cs_attach(void) | 107 | orinoco_cs_attach(struct pcmcia_device *p_dev) |
124 | { | 108 | { |
125 | struct net_device *dev; | 109 | struct net_device *dev; |
126 | struct orinoco_private *priv; | 110 | struct orinoco_private *priv; |
127 | struct orinoco_pccard *card; | 111 | struct orinoco_pccard *card; |
128 | dev_link_t *link; | 112 | dev_link_t *link; |
129 | client_reg_t client_reg; | ||
130 | int ret; | ||
131 | 113 | ||
132 | dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); | 114 | dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); |
133 | if (! dev) | 115 | if (! dev) |
134 | return NULL; | 116 | return -ENOMEM; |
135 | priv = netdev_priv(dev); | 117 | priv = netdev_priv(dev); |
136 | card = priv->card; | 118 | card = priv->card; |
137 | 119 | ||
@@ -154,22 +136,15 @@ orinoco_cs_attach(void) | |||
154 | link->conf.IntType = INT_MEMORY_AND_IO; | 136 | link->conf.IntType = INT_MEMORY_AND_IO; |
155 | 137 | ||
156 | /* Register with Card Services */ | 138 | /* Register with Card Services */ |
157 | /* FIXME: need a lock? */ | 139 | link->next = NULL; |
158 | link->next = dev_list; | 140 | |
159 | dev_list = link; | 141 | link->handle = p_dev; |
160 | 142 | p_dev->instance = link; | |
161 | client_reg.dev_info = &dev_info; | 143 | |
162 | client_reg.Version = 0x0210; /* FIXME: what does this mean? */ | 144 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
163 | client_reg.event_callback_args.client_data = link; | 145 | orinoco_cs_config(link); |
164 | |||
165 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
166 | if (ret != CS_SUCCESS) { | ||
167 | cs_error(link->handle, RegisterClient, ret); | ||
168 | orinoco_cs_detach(link); | ||
169 | return NULL; | ||
170 | } | ||
171 | 146 | ||
172 | return link; | 147 | return 0; |
173 | } /* orinoco_cs_attach */ | 148 | } /* orinoco_cs_attach */ |
174 | 149 | ||
175 | /* | 150 | /* |
@@ -178,27 +153,14 @@ orinoco_cs_attach(void) | |||
178 | * are freed. Otherwise, the structures will be freed when the device | 153 | * are freed. Otherwise, the structures will be freed when the device |
179 | * is released. | 154 | * is released. |
180 | */ | 155 | */ |
181 | static void orinoco_cs_detach(dev_link_t *link) | 156 | static void orinoco_cs_detach(struct pcmcia_device *p_dev) |
182 | { | 157 | { |
183 | dev_link_t **linkp; | 158 | dev_link_t *link = dev_to_instance(p_dev); |
184 | struct net_device *dev = link->priv; | 159 | struct net_device *dev = link->priv; |
185 | 160 | ||
186 | /* Locate device structure */ | ||
187 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
188 | if (*linkp == link) | ||
189 | break; | ||
190 | |||
191 | BUG_ON(*linkp == NULL); | ||
192 | |||
193 | if (link->state & DEV_CONFIG) | 161 | if (link->state & DEV_CONFIG) |
194 | orinoco_cs_release(link); | 162 | orinoco_cs_release(link); |
195 | 163 | ||
196 | /* Break the link with Card Services */ | ||
197 | if (link->handle) | ||
198 | pcmcia_deregister_client(link->handle); | ||
199 | |||
200 | /* Unlink device structure, and free it */ | ||
201 | *linkp = link->next; | ||
202 | DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); | 164 | DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); |
203 | if (link->dev) { | 165 | if (link->dev) { |
204 | DEBUG(0, PFX "About to unregister net device %p\n", | 166 | DEBUG(0, PFX "About to unregister net device %p\n", |
@@ -465,106 +427,82 @@ orinoco_cs_release(dev_link_t *link) | |||
465 | ioport_unmap(priv->hw.iobase); | 427 | ioport_unmap(priv->hw.iobase); |
466 | } /* orinoco_cs_release */ | 428 | } /* orinoco_cs_release */ |
467 | 429 | ||
468 | /* | 430 | static int orinoco_cs_suspend(struct pcmcia_device *p_dev) |
469 | * The card status event handler. Mostly, this schedules other stuff | ||
470 | * to run after an event is received. | ||
471 | */ | ||
472 | static int | ||
473 | orinoco_cs_event(event_t event, int priority, | ||
474 | event_callback_args_t * args) | ||
475 | { | 431 | { |
476 | dev_link_t *link = args->client_data; | 432 | dev_link_t *link = dev_to_instance(p_dev); |
477 | struct net_device *dev = link->priv; | 433 | struct net_device *dev = link->priv; |
478 | struct orinoco_private *priv = netdev_priv(dev); | 434 | struct orinoco_private *priv = netdev_priv(dev); |
479 | struct orinoco_pccard *card = priv->card; | 435 | struct orinoco_pccard *card = priv->card; |
480 | int err = 0; | 436 | int err = 0; |
481 | unsigned long flags; | 437 | unsigned long flags; |
482 | 438 | ||
483 | switch (event) { | 439 | link->state |= DEV_SUSPEND; |
484 | case CS_EVENT_CARD_REMOVAL: | 440 | if (link->state & DEV_CONFIG) { |
485 | link->state &= ~DEV_PRESENT; | 441 | /* This is probably racy, but I can't think of |
486 | if (link->state & DEV_CONFIG) { | 442 | a better way, short of rewriting the PCMCIA |
487 | unsigned long flags; | 443 | layer to not suck :-( */ |
488 | 444 | if (! test_bit(0, &card->hard_reset_in_progress)) { | |
489 | spin_lock_irqsave(&priv->lock, flags); | 445 | spin_lock_irqsave(&priv->lock, flags); |
446 | |||
447 | err = __orinoco_down(dev); | ||
448 | if (err) | ||
449 | printk(KERN_WARNING "%s: Error %d downing interface\n", | ||
450 | dev->name, err); | ||
451 | |||
490 | netif_device_detach(dev); | 452 | netif_device_detach(dev); |
491 | priv->hw_unavailable++; | 453 | priv->hw_unavailable++; |
454 | |||
492 | spin_unlock_irqrestore(&priv->lock, flags); | 455 | spin_unlock_irqrestore(&priv->lock, flags); |
493 | } | 456 | } |
494 | break; | ||
495 | 457 | ||
496 | case CS_EVENT_CARD_INSERTION: | 458 | pcmcia_release_configuration(link->handle); |
497 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 459 | } |
498 | orinoco_cs_config(link); | ||
499 | break; | ||
500 | 460 | ||
501 | case CS_EVENT_PM_SUSPEND: | 461 | return 0; |
502 | link->state |= DEV_SUSPEND; | 462 | } |
503 | /* Fall through... */ | 463 | |
504 | case CS_EVENT_RESET_PHYSICAL: | 464 | static int orinoco_cs_resume(struct pcmcia_device *p_dev) |
505 | /* Mark the device as stopped, to block IO until later */ | 465 | { |
506 | if (link->state & DEV_CONFIG) { | 466 | dev_link_t *link = dev_to_instance(p_dev); |
507 | /* This is probably racy, but I can't think of | 467 | struct net_device *dev = link->priv; |
508 | a better way, short of rewriting the PCMCIA | 468 | struct orinoco_private *priv = netdev_priv(dev); |
509 | layer to not suck :-( */ | 469 | struct orinoco_pccard *card = priv->card; |
510 | if (! test_bit(0, &card->hard_reset_in_progress)) { | 470 | int err = 0; |
511 | spin_lock_irqsave(&priv->lock, flags); | 471 | unsigned long flags; |
512 | 472 | ||
513 | err = __orinoco_down(dev); | 473 | link->state &= ~DEV_SUSPEND; |
514 | if (err) | 474 | if (link->state & DEV_CONFIG) { |
515 | printk(KERN_WARNING "%s: %s: Error %d downing interface\n", | 475 | /* FIXME: should we double check that this is |
516 | dev->name, | 476 | * the same card as we had before */ |
517 | event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL", | 477 | pcmcia_request_configuration(link->handle, &link->conf); |
518 | err); | 478 | |
519 | 479 | if (! test_bit(0, &card->hard_reset_in_progress)) { | |
520 | netif_device_detach(dev); | 480 | err = orinoco_reinit_firmware(dev); |
521 | priv->hw_unavailable++; | 481 | if (err) { |
522 | 482 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", | |
523 | spin_unlock_irqrestore(&priv->lock, flags); | 483 | dev->name, err); |
484 | return -EIO; | ||
524 | } | 485 | } |
525 | 486 | ||
526 | pcmcia_release_configuration(link->handle); | 487 | spin_lock_irqsave(&priv->lock, flags); |
527 | } | 488 | |
528 | break; | 489 | netif_device_attach(dev); |
490 | priv->hw_unavailable--; | ||
529 | 491 | ||
530 | case CS_EVENT_PM_RESUME: | 492 | if (priv->open && ! priv->hw_unavailable) { |
531 | link->state &= ~DEV_SUSPEND; | 493 | err = __orinoco_up(dev); |
532 | /* Fall through... */ | 494 | if (err) |
533 | case CS_EVENT_CARD_RESET: | 495 | printk(KERN_ERR "%s: Error %d restarting card\n", |
534 | if (link->state & DEV_CONFIG) { | ||
535 | /* FIXME: should we double check that this is | ||
536 | * the same card as we had before */ | ||
537 | pcmcia_request_configuration(link->handle, &link->conf); | ||
538 | |||
539 | if (! test_bit(0, &card->hard_reset_in_progress)) { | ||
540 | err = orinoco_reinit_firmware(dev); | ||
541 | if (err) { | ||
542 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", | ||
543 | dev->name, err); | 496 | dev->name, err); |
544 | break; | ||
545 | } | ||
546 | |||
547 | spin_lock_irqsave(&priv->lock, flags); | ||
548 | |||
549 | netif_device_attach(dev); | ||
550 | priv->hw_unavailable--; | ||
551 | |||
552 | if (priv->open && ! priv->hw_unavailable) { | ||
553 | err = __orinoco_up(dev); | ||
554 | if (err) | ||
555 | printk(KERN_ERR "%s: Error %d restarting card\n", | ||
556 | dev->name, err); | ||
557 | |||
558 | } | ||
559 | |||
560 | spin_unlock_irqrestore(&priv->lock, flags); | ||
561 | } | 497 | } |
498 | |||
499 | spin_unlock_irqrestore(&priv->lock, flags); | ||
562 | } | 500 | } |
563 | break; | ||
564 | } | 501 | } |
565 | 502 | ||
566 | return err; | 503 | return 0; |
567 | } /* orinoco_cs_event */ | 504 | } |
505 | |||
568 | 506 | ||
569 | /********************************************************************/ | 507 | /********************************************************************/ |
570 | /* Module initialization */ | 508 | /* Module initialization */ |
@@ -665,10 +603,11 @@ static struct pcmcia_driver orinoco_driver = { | |||
665 | .drv = { | 603 | .drv = { |
666 | .name = DRIVER_NAME, | 604 | .name = DRIVER_NAME, |
667 | }, | 605 | }, |
668 | .attach = orinoco_cs_attach, | 606 | .probe = orinoco_cs_attach, |
669 | .detach = orinoco_cs_detach, | 607 | .remove = orinoco_cs_detach, |
670 | .event = orinoco_cs_event, | ||
671 | .id_table = orinoco_cs_ids, | 608 | .id_table = orinoco_cs_ids, |
609 | .suspend = orinoco_cs_suspend, | ||
610 | .resume = orinoco_cs_resume, | ||
672 | }; | 611 | }; |
673 | 612 | ||
674 | static int __init | 613 | static int __init |
@@ -683,7 +622,6 @@ static void __exit | |||
683 | exit_orinoco_cs(void) | 622 | exit_orinoco_cs(void) |
684 | { | 623 | { |
685 | pcmcia_unregister_driver(&orinoco_driver); | 624 | pcmcia_unregister_driver(&orinoco_driver); |
686 | BUG_ON(dev_list != NULL); | ||
687 | } | 625 | } |
688 | 626 | ||
689 | module_init(init_orinoco_cs); | 627 | module_init(init_orinoco_cs); |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 70fd6fd8feb9..319180ca7e71 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -92,9 +92,7 @@ module_param(pc_debug, int, 0); | |||
92 | /** Prototypes based on PCMCIA skeleton driver *******************************/ | 92 | /** Prototypes based on PCMCIA skeleton driver *******************************/ |
93 | static void ray_config(dev_link_t *link); | 93 | static void ray_config(dev_link_t *link); |
94 | static void ray_release(dev_link_t *link); | 94 | static void ray_release(dev_link_t *link); |
95 | static int ray_event(event_t event, int priority, event_callback_args_t *args); | 95 | static void ray_detach(struct pcmcia_device *p_dev); |
96 | static dev_link_t *ray_attach(void); | ||
97 | static void ray_detach(dev_link_t *); | ||
98 | 96 | ||
99 | /***** Prototypes indicated by device structure ******************************/ | 97 | /***** Prototypes indicated by device structure ******************************/ |
100 | static int ray_dev_close(struct net_device *dev); | 98 | static int ray_dev_close(struct net_device *dev); |
@@ -192,12 +190,6 @@ static int bc; | |||
192 | static char *phy_addr = NULL; | 190 | static char *phy_addr = NULL; |
193 | 191 | ||
194 | 192 | ||
195 | /* The dev_info variable is the "key" that is used to match up this | ||
196 | device driver with appropriate cards, through the card configuration | ||
197 | database. | ||
198 | */ | ||
199 | static dev_info_t dev_info = "ray_cs"; | ||
200 | |||
201 | /* A linked list of "instances" of the ray device. Each actual | 193 | /* A linked list of "instances" of the ray device. Each actual |
202 | PCMCIA card corresponds to one device instance, and is described | 194 | PCMCIA card corresponds to one device instance, and is described |
203 | by one dev_link_t structure (defined in ds.h). | 195 | by one dev_link_t structure (defined in ds.h). |
@@ -314,12 +306,10 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world. | |||
314 | configure the card at this point -- we wait until we receive a | 306 | configure the card at this point -- we wait until we receive a |
315 | card insertion event. | 307 | card insertion event. |
316 | =============================================================================*/ | 308 | =============================================================================*/ |
317 | static dev_link_t *ray_attach(void) | 309 | static int ray_attach(struct pcmcia_device *p_dev) |
318 | { | 310 | { |
319 | client_reg_t client_reg; | ||
320 | dev_link_t *link; | 311 | dev_link_t *link; |
321 | ray_dev_t *local; | 312 | ray_dev_t *local; |
322 | int ret; | ||
323 | struct net_device *dev; | 313 | struct net_device *dev; |
324 | 314 | ||
325 | DEBUG(1, "ray_attach()\n"); | 315 | DEBUG(1, "ray_attach()\n"); |
@@ -328,7 +318,7 @@ static dev_link_t *ray_attach(void) | |||
328 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); | 318 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); |
329 | 319 | ||
330 | if (!link) | 320 | if (!link) |
331 | return NULL; | 321 | return -ENOMEM; |
332 | 322 | ||
333 | /* Allocate space for private device-specific data */ | 323 | /* Allocate space for private device-specific data */ |
334 | dev = alloc_etherdev(sizeof(ray_dev_t)); | 324 | dev = alloc_etherdev(sizeof(ray_dev_t)); |
@@ -387,30 +377,19 @@ static dev_link_t *ray_attach(void) | |||
387 | dev->stop = &ray_dev_close; | 377 | dev->stop = &ray_dev_close; |
388 | netif_stop_queue(dev); | 378 | netif_stop_queue(dev); |
389 | 379 | ||
390 | /* Register with Card Services */ | 380 | init_timer(&local->timer); |
391 | link->next = dev_list; | ||
392 | dev_list = link; | ||
393 | client_reg.dev_info = &dev_info; | ||
394 | client_reg.Version = 0x0210; | ||
395 | client_reg.event_callback_args.client_data = link; | ||
396 | 381 | ||
397 | DEBUG(2,"ray_cs ray_attach calling pcmcia_register_client(...)\n"); | 382 | link->handle = p_dev; |
383 | p_dev->instance = link; | ||
398 | 384 | ||
399 | init_timer(&local->timer); | 385 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
386 | ray_config(link); | ||
400 | 387 | ||
401 | ret = pcmcia_register_client(&link->handle, &client_reg); | 388 | return 0; |
402 | if (ret != 0) { | ||
403 | printk("ray_cs ray_attach RegisterClient unhappy - detaching\n"); | ||
404 | cs_error(link->handle, RegisterClient, ret); | ||
405 | ray_detach(link); | ||
406 | return NULL; | ||
407 | } | ||
408 | DEBUG(2,"ray_cs ray_attach ending\n"); | ||
409 | return link; | ||
410 | 389 | ||
411 | fail_alloc_dev: | 390 | fail_alloc_dev: |
412 | kfree(link); | 391 | kfree(link); |
413 | return NULL; | 392 | return -ENOMEM; |
414 | } /* ray_attach */ | 393 | } /* ray_attach */ |
415 | /*============================================================================= | 394 | /*============================================================================= |
416 | This deletes a driver "instance". The device is de-registered | 395 | This deletes a driver "instance". The device is de-registered |
@@ -418,9 +397,12 @@ fail_alloc_dev: | |||
418 | structures are freed. Otherwise, the structures will be freed | 397 | structures are freed. Otherwise, the structures will be freed |
419 | when the device is released. | 398 | when the device is released. |
420 | =============================================================================*/ | 399 | =============================================================================*/ |
421 | static void ray_detach(dev_link_t *link) | 400 | static void ray_detach(struct pcmcia_device *p_dev) |
422 | { | 401 | { |
402 | dev_link_t *link = dev_to_instance(p_dev); | ||
423 | dev_link_t **linkp; | 403 | dev_link_t **linkp; |
404 | struct net_device *dev; | ||
405 | ray_dev_t *local; | ||
424 | 406 | ||
425 | DEBUG(1, "ray_detach(0x%p)\n", link); | 407 | DEBUG(1, "ray_detach(0x%p)\n", link); |
426 | 408 | ||
@@ -430,22 +412,18 @@ static void ray_detach(dev_link_t *link) | |||
430 | if (*linkp == NULL) | 412 | if (*linkp == NULL) |
431 | return; | 413 | return; |
432 | 414 | ||
433 | /* If the device is currently configured and active, we won't | 415 | dev = link->priv; |
434 | actually delete it yet. Instead, it is marked so that when | 416 | |
435 | the release() function is called, that will trigger a proper | 417 | if (link->state & DEV_CONFIG) { |
436 | detach(). | 418 | ray_release(link); |
437 | */ | 419 | |
438 | if (link->state & DEV_CONFIG) | 420 | local = (ray_dev_t *)dev->priv; |
439 | ray_release(link); | 421 | del_timer(&local->timer); |
422 | } | ||
440 | 423 | ||
441 | /* Break the link with Card Services */ | ||
442 | if (link->handle) | ||
443 | pcmcia_deregister_client(link->handle); | ||
444 | |||
445 | /* Unlink device structure, free pieces */ | 424 | /* Unlink device structure, free pieces */ |
446 | *linkp = link->next; | 425 | *linkp = link->next; |
447 | if (link->priv) { | 426 | if (link->priv) { |
448 | struct net_device *dev = link->priv; | ||
449 | if (link->dev) unregister_netdev(dev); | 427 | if (link->dev) unregister_netdev(dev); |
450 | free_netdev(dev); | 428 | free_netdev(dev); |
451 | } | 429 | } |
@@ -891,65 +869,40 @@ static void ray_release(dev_link_t *link) | |||
891 | DEBUG(2,"ray_release ending\n"); | 869 | DEBUG(2,"ray_release ending\n"); |
892 | } | 870 | } |
893 | 871 | ||
894 | /*============================================================================= | 872 | static int ray_suspend(struct pcmcia_device *p_dev) |
895 | The card status event handler. Mostly, this schedules other | ||
896 | stuff to run after an event is received. A CARD_REMOVAL event | ||
897 | also sets some flags to discourage the net drivers from trying | ||
898 | to talk to the card any more. | ||
899 | |||
900 | When a CARD_REMOVAL event is received, we immediately set a flag | ||
901 | to block future accesses to this device. All the functions that | ||
902 | actually access the device should check this flag to make sure | ||
903 | the card is still present. | ||
904 | =============================================================================*/ | ||
905 | static int ray_event(event_t event, int priority, | ||
906 | event_callback_args_t *args) | ||
907 | { | 873 | { |
908 | dev_link_t *link = args->client_data; | 874 | dev_link_t *link = dev_to_instance(p_dev); |
909 | struct net_device *dev = link->priv; | 875 | struct net_device *dev = link->priv; |
910 | ray_dev_t *local = (ray_dev_t *)dev->priv; | 876 | |
911 | DEBUG(1, "ray_event(0x%06x)\n", event); | 877 | link->state |= DEV_SUSPEND; |
912 | |||
913 | switch (event) { | ||
914 | case CS_EVENT_CARD_REMOVAL: | ||
915 | link->state &= ~DEV_PRESENT; | ||
916 | netif_device_detach(dev); | ||
917 | if (link->state & DEV_CONFIG) { | ||
918 | ray_release(link); | ||
919 | del_timer(&local->timer); | ||
920 | } | ||
921 | break; | ||
922 | case CS_EVENT_CARD_INSERTION: | ||
923 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
924 | ray_config(link); | ||
925 | break; | ||
926 | case CS_EVENT_PM_SUSPEND: | ||
927 | link->state |= DEV_SUSPEND; | ||
928 | /* Fall through... */ | ||
929 | case CS_EVENT_RESET_PHYSICAL: | ||
930 | if (link->state & DEV_CONFIG) { | 878 | if (link->state & DEV_CONFIG) { |
931 | if (link->open) | 879 | if (link->open) |
932 | netif_device_detach(dev); | 880 | netif_device_detach(dev); |
933 | 881 | ||
934 | pcmcia_release_configuration(link->handle); | 882 | pcmcia_release_configuration(link->handle); |
935 | } | 883 | } |
936 | break; | 884 | |
937 | case CS_EVENT_PM_RESUME: | 885 | |
938 | link->state &= ~DEV_SUSPEND; | 886 | return 0; |
939 | /* Fall through... */ | 887 | } |
940 | case CS_EVENT_CARD_RESET: | 888 | |
889 | static int ray_resume(struct pcmcia_device *p_dev) | ||
890 | { | ||
891 | dev_link_t *link = dev_to_instance(p_dev); | ||
892 | struct net_device *dev = link->priv; | ||
893 | |||
894 | link->state &= ~DEV_SUSPEND; | ||
941 | if (link->state & DEV_CONFIG) { | 895 | if (link->state & DEV_CONFIG) { |
942 | pcmcia_request_configuration(link->handle, &link->conf); | 896 | pcmcia_request_configuration(link->handle, &link->conf); |
943 | if (link->open) { | 897 | if (link->open) { |
944 | ray_reset(dev); | 898 | ray_reset(dev); |
945 | netif_device_attach(dev); | 899 | netif_device_attach(dev); |
946 | } | 900 | } |
947 | } | 901 | } |
948 | break; | 902 | |
949 | } | 903 | return 0; |
950 | return 0; | 904 | } |
951 | DEBUG(2,"ray_event ending\n"); | 905 | |
952 | } /* ray_event */ | ||
953 | /*===========================================================================*/ | 906 | /*===========================================================================*/ |
954 | int ray_dev_init(struct net_device *dev) | 907 | int ray_dev_init(struct net_device *dev) |
955 | { | 908 | { |
@@ -2945,10 +2898,11 @@ static struct pcmcia_driver ray_driver = { | |||
2945 | .drv = { | 2898 | .drv = { |
2946 | .name = "ray_cs", | 2899 | .name = "ray_cs", |
2947 | }, | 2900 | }, |
2948 | .attach = ray_attach, | 2901 | .probe = ray_attach, |
2949 | .event = ray_event, | 2902 | .remove = ray_detach, |
2950 | .detach = ray_detach, | ||
2951 | .id_table = ray_ids, | 2903 | .id_table = ray_ids, |
2904 | .suspend = ray_suspend, | ||
2905 | .resume = ray_resume, | ||
2952 | }; | 2906 | }; |
2953 | 2907 | ||
2954 | static int __init init_ray_cs(void) | 2908 | static int __init init_ray_cs(void) |
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index b1bbc8e8e91f..fee4be1ce810 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -57,17 +57,6 @@ module_param(ignore_cis_vcc, int, 0); | |||
57 | MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); | 57 | MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); |
58 | 58 | ||
59 | /********************************************************************/ | 59 | /********************************************************************/ |
60 | /* Magic constants */ | ||
61 | /********************************************************************/ | ||
62 | |||
63 | /* | ||
64 | * The dev_info variable is the "key" that is used to match up this | ||
65 | * device driver with appropriate cards, through the card | ||
66 | * configuration database. | ||
67 | */ | ||
68 | static dev_info_t dev_info = DRIVER_NAME; | ||
69 | |||
70 | /********************************************************************/ | ||
71 | /* Data structures */ | 60 | /* Data structures */ |
72 | /********************************************************************/ | 61 | /********************************************************************/ |
73 | 62 | ||
@@ -78,19 +67,12 @@ struct orinoco_pccard { | |||
78 | dev_node_t node; | 67 | dev_node_t node; |
79 | }; | 68 | }; |
80 | 69 | ||
81 | /* | ||
82 | * A linked list of "instances" of the device. Each actual PCMCIA | ||
83 | * card corresponds to one device instance, and is described by one | ||
84 | * dev_link_t structure (defined in ds.h). | ||
85 | */ | ||
86 | static dev_link_t *dev_list; /* = NULL */ | ||
87 | |||
88 | /********************************************************************/ | 70 | /********************************************************************/ |
89 | /* Function prototypes */ | 71 | /* Function prototypes */ |
90 | /********************************************************************/ | 72 | /********************************************************************/ |
91 | 73 | ||
74 | static void spectrum_cs_config(dev_link_t *link); | ||
92 | static void spectrum_cs_release(dev_link_t *link); | 75 | static void spectrum_cs_release(dev_link_t *link); |
93 | static void spectrum_cs_detach(dev_link_t *link); | ||
94 | 76 | ||
95 | /********************************************************************/ | 77 | /********************************************************************/ |
96 | /* Firmware downloader */ | 78 | /* Firmware downloader */ |
@@ -601,19 +583,17 @@ spectrum_cs_hard_reset(struct orinoco_private *priv) | |||
601 | * The dev_link structure is initialized, but we don't actually | 583 | * The dev_link structure is initialized, but we don't actually |
602 | * configure the card at this point -- we wait until we receive a card | 584 | * configure the card at this point -- we wait until we receive a card |
603 | * insertion event. */ | 585 | * insertion event. */ |
604 | static dev_link_t * | 586 | static int |
605 | spectrum_cs_attach(void) | 587 | spectrum_cs_attach(struct pcmcia_device *p_dev) |
606 | { | 588 | { |
607 | struct net_device *dev; | 589 | struct net_device *dev; |
608 | struct orinoco_private *priv; | 590 | struct orinoco_private *priv; |
609 | struct orinoco_pccard *card; | 591 | struct orinoco_pccard *card; |
610 | dev_link_t *link; | 592 | dev_link_t *link; |
611 | client_reg_t client_reg; | ||
612 | int ret; | ||
613 | 593 | ||
614 | dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); | 594 | dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); |
615 | if (! dev) | 595 | if (! dev) |
616 | return NULL; | 596 | return -ENOMEM; |
617 | priv = netdev_priv(dev); | 597 | priv = netdev_priv(dev); |
618 | card = priv->card; | 598 | card = priv->card; |
619 | 599 | ||
@@ -635,23 +615,13 @@ spectrum_cs_attach(void) | |||
635 | link->conf.Attributes = 0; | 615 | link->conf.Attributes = 0; |
636 | link->conf.IntType = INT_MEMORY_AND_IO; | 616 | link->conf.IntType = INT_MEMORY_AND_IO; |
637 | 617 | ||
638 | /* Register with Card Services */ | 618 | link->handle = p_dev; |
639 | /* FIXME: need a lock? */ | 619 | p_dev->instance = link; |
640 | link->next = dev_list; | ||
641 | dev_list = link; | ||
642 | 620 | ||
643 | client_reg.dev_info = &dev_info; | 621 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
644 | client_reg.Version = 0x0210; /* FIXME: what does this mean? */ | 622 | spectrum_cs_config(link); |
645 | client_reg.event_callback_args.client_data = link; | ||
646 | 623 | ||
647 | ret = pcmcia_register_client(&link->handle, &client_reg); | 624 | return 0; |
648 | if (ret != CS_SUCCESS) { | ||
649 | cs_error(link->handle, RegisterClient, ret); | ||
650 | spectrum_cs_detach(link); | ||
651 | return NULL; | ||
652 | } | ||
653 | |||
654 | return link; | ||
655 | } /* spectrum_cs_attach */ | 625 | } /* spectrum_cs_attach */ |
656 | 626 | ||
657 | /* | 627 | /* |
@@ -660,27 +630,14 @@ spectrum_cs_attach(void) | |||
660 | * are freed. Otherwise, the structures will be freed when the device | 630 | * are freed. Otherwise, the structures will be freed when the device |
661 | * is released. | 631 | * is released. |
662 | */ | 632 | */ |
663 | static void spectrum_cs_detach(dev_link_t *link) | 633 | static void spectrum_cs_detach(struct pcmcia_device *p_dev) |
664 | { | 634 | { |
665 | dev_link_t **linkp; | 635 | dev_link_t *link = dev_to_instance(p_dev); |
666 | struct net_device *dev = link->priv; | 636 | struct net_device *dev = link->priv; |
667 | 637 | ||
668 | /* Locate device structure */ | ||
669 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
670 | if (*linkp == link) | ||
671 | break; | ||
672 | |||
673 | BUG_ON(*linkp == NULL); | ||
674 | |||
675 | if (link->state & DEV_CONFIG) | 638 | if (link->state & DEV_CONFIG) |
676 | spectrum_cs_release(link); | 639 | spectrum_cs_release(link); |
677 | 640 | ||
678 | /* Break the link with Card Services */ | ||
679 | if (link->handle) | ||
680 | pcmcia_deregister_client(link->handle); | ||
681 | |||
682 | /* Unlink device structure, and free it */ | ||
683 | *linkp = link->next; | ||
684 | DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); | 641 | DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); |
685 | if (link->dev) { | 642 | if (link->dev) { |
686 | DEBUG(0, PFX "About to unregister net device %p\n", | 643 | DEBUG(0, PFX "About to unregister net device %p\n", |
@@ -948,82 +905,56 @@ spectrum_cs_release(dev_link_t *link) | |||
948 | ioport_unmap(priv->hw.iobase); | 905 | ioport_unmap(priv->hw.iobase); |
949 | } /* spectrum_cs_release */ | 906 | } /* spectrum_cs_release */ |
950 | 907 | ||
951 | /* | 908 | |
952 | * The card status event handler. Mostly, this schedules other stuff | ||
953 | * to run after an event is received. | ||
954 | */ | ||
955 | static int | 909 | static int |
956 | spectrum_cs_event(event_t event, int priority, | 910 | spectrum_cs_suspend(struct pcmcia_device *p_dev) |
957 | event_callback_args_t * args) | ||
958 | { | 911 | { |
959 | dev_link_t *link = args->client_data; | 912 | dev_link_t *link = dev_to_instance(p_dev); |
960 | struct net_device *dev = link->priv; | 913 | struct net_device *dev = link->priv; |
961 | struct orinoco_private *priv = netdev_priv(dev); | 914 | struct orinoco_private *priv = netdev_priv(dev); |
962 | int err = 0; | ||
963 | unsigned long flags; | 915 | unsigned long flags; |
916 | int err = 0; | ||
964 | 917 | ||
965 | switch (event) { | 918 | link->state |= DEV_SUSPEND; |
966 | case CS_EVENT_CARD_REMOVAL: | 919 | /* Mark the device as stopped, to block IO until later */ |
967 | link->state &= ~DEV_PRESENT; | 920 | if (link->state & DEV_CONFIG) { |
968 | if (link->state & DEV_CONFIG) { | 921 | spin_lock_irqsave(&priv->lock, flags); |
969 | unsigned long flags; | ||
970 | 922 | ||
971 | spin_lock_irqsave(&priv->lock, flags); | 923 | err = __orinoco_down(dev); |
972 | netif_device_detach(dev); | 924 | if (err) |
973 | priv->hw_unavailable++; | 925 | printk(KERN_WARNING "%s: Error %d downing interface\n", |
974 | spin_unlock_irqrestore(&priv->lock, flags); | 926 | dev->name, err); |
975 | } | ||
976 | break; | ||
977 | 927 | ||
978 | case CS_EVENT_CARD_INSERTION: | 928 | netif_device_detach(dev); |
979 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 929 | priv->hw_unavailable++; |
980 | spectrum_cs_config(link); | ||
981 | break; | ||
982 | 930 | ||
983 | case CS_EVENT_PM_SUSPEND: | 931 | spin_unlock_irqrestore(&priv->lock, flags); |
984 | link->state |= DEV_SUSPEND; | ||
985 | /* Fall through... */ | ||
986 | case CS_EVENT_RESET_PHYSICAL: | ||
987 | /* Mark the device as stopped, to block IO until later */ | ||
988 | if (link->state & DEV_CONFIG) { | ||
989 | /* This is probably racy, but I can't think of | ||
990 | a better way, short of rewriting the PCMCIA | ||
991 | layer to not suck :-( */ | ||
992 | spin_lock_irqsave(&priv->lock, flags); | ||
993 | |||
994 | err = __orinoco_down(dev); | ||
995 | if (err) | ||
996 | printk(KERN_WARNING "%s: %s: Error %d downing interface\n", | ||
997 | dev->name, | ||
998 | event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL", | ||
999 | err); | ||
1000 | |||
1001 | netif_device_detach(dev); | ||
1002 | priv->hw_unavailable++; | ||
1003 | |||
1004 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1005 | |||
1006 | pcmcia_release_configuration(link->handle); | ||
1007 | } | ||
1008 | break; | ||
1009 | 932 | ||
1010 | case CS_EVENT_PM_RESUME: | 933 | pcmcia_release_configuration(link->handle); |
1011 | link->state &= ~DEV_SUSPEND; | 934 | } |
1012 | /* Fall through... */ | 935 | |
1013 | case CS_EVENT_CARD_RESET: | 936 | return 0; |
1014 | if (link->state & DEV_CONFIG) { | 937 | } |
1015 | /* FIXME: should we double check that this is | 938 | |
1016 | * the same card as we had before */ | 939 | static int |
1017 | pcmcia_request_configuration(link->handle, &link->conf); | 940 | spectrum_cs_resume(struct pcmcia_device *p_dev) |
1018 | netif_device_attach(dev); | 941 | { |
1019 | priv->hw_unavailable--; | 942 | dev_link_t *link = dev_to_instance(p_dev); |
1020 | schedule_work(&priv->reset_work); | 943 | struct net_device *dev = link->priv; |
1021 | } | 944 | struct orinoco_private *priv = netdev_priv(dev); |
1022 | break; | 945 | |
946 | link->state &= ~DEV_SUSPEND; | ||
947 | if (link->state & DEV_CONFIG) { | ||
948 | /* FIXME: should we double check that this is | ||
949 | * the same card as we had before */ | ||
950 | pcmcia_request_configuration(link->handle, &link->conf); | ||
951 | netif_device_attach(dev); | ||
952 | priv->hw_unavailable--; | ||
953 | schedule_work(&priv->reset_work); | ||
1023 | } | 954 | } |
955 | return 0; | ||
956 | } | ||
1024 | 957 | ||
1025 | return err; | ||
1026 | } /* spectrum_cs_event */ | ||
1027 | 958 | ||
1028 | /********************************************************************/ | 959 | /********************************************************************/ |
1029 | /* Module initialization */ | 960 | /* Module initialization */ |
@@ -1048,9 +979,10 @@ static struct pcmcia_driver orinoco_driver = { | |||
1048 | .drv = { | 979 | .drv = { |
1049 | .name = DRIVER_NAME, | 980 | .name = DRIVER_NAME, |
1050 | }, | 981 | }, |
1051 | .attach = spectrum_cs_attach, | 982 | .probe = spectrum_cs_attach, |
1052 | .detach = spectrum_cs_detach, | 983 | .remove = spectrum_cs_detach, |
1053 | .event = spectrum_cs_event, | 984 | .suspend = spectrum_cs_suspend, |
985 | .resume = spectrum_cs_resume, | ||
1054 | .id_table = spectrum_cs_ids, | 986 | .id_table = spectrum_cs_ids, |
1055 | }; | 987 | }; |
1056 | 988 | ||
@@ -1066,7 +998,6 @@ static void __exit | |||
1066 | exit_spectrum_cs(void) | 998 | exit_spectrum_cs(void) |
1067 | { | 999 | { |
1068 | pcmcia_unregister_driver(&orinoco_driver); | 1000 | pcmcia_unregister_driver(&orinoco_driver); |
1069 | BUG_ON(dev_list != NULL); | ||
1070 | } | 1001 | } |
1071 | 1002 | ||
1072 | module_init(init_spectrum_cs); | 1003 | module_init(init_spectrum_cs); |
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index c822cad3333f..7e2039f52c49 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
@@ -4594,14 +4594,12 @@ wavelan_close(struct net_device * dev) | |||
4594 | * configure the card at this point -- we wait until we receive a | 4594 | * configure the card at this point -- we wait until we receive a |
4595 | * card insertion event. | 4595 | * card insertion event. |
4596 | */ | 4596 | */ |
4597 | static dev_link_t * | 4597 | static int |
4598 | wavelan_attach(void) | 4598 | wavelan_attach(struct pcmcia_device *p_dev) |
4599 | { | 4599 | { |
4600 | client_reg_t client_reg; /* Register with cardmgr */ | ||
4601 | dev_link_t * link; /* Info for cardmgr */ | 4600 | dev_link_t * link; /* Info for cardmgr */ |
4602 | struct net_device * dev; /* Interface generic data */ | 4601 | struct net_device * dev; /* Interface generic data */ |
4603 | net_local * lp; /* Interface specific data */ | 4602 | net_local * lp; /* Interface specific data */ |
4604 | int ret; | ||
4605 | 4603 | ||
4606 | #ifdef DEBUG_CALLBACK_TRACE | 4604 | #ifdef DEBUG_CALLBACK_TRACE |
4607 | printk(KERN_DEBUG "-> wavelan_attach()\n"); | 4605 | printk(KERN_DEBUG "-> wavelan_attach()\n"); |
@@ -4609,7 +4607,7 @@ wavelan_attach(void) | |||
4609 | 4607 | ||
4610 | /* Initialize the dev_link_t structure */ | 4608 | /* Initialize the dev_link_t structure */ |
4611 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | 4609 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); |
4612 | if (!link) return NULL; | 4610 | if (!link) return -ENOMEM; |
4613 | 4611 | ||
4614 | /* The io structure describes IO port mapping */ | 4612 | /* The io structure describes IO port mapping */ |
4615 | link->io.NumPorts1 = 8; | 4613 | link->io.NumPorts1 = 8; |
@@ -4627,14 +4625,13 @@ wavelan_attach(void) | |||
4627 | link->conf.IntType = INT_MEMORY_AND_IO; | 4625 | link->conf.IntType = INT_MEMORY_AND_IO; |
4628 | 4626 | ||
4629 | /* Chain drivers */ | 4627 | /* Chain drivers */ |
4630 | link->next = dev_list; | 4628 | link->next = NULL; |
4631 | dev_list = link; | ||
4632 | 4629 | ||
4633 | /* Allocate the generic data structure */ | 4630 | /* Allocate the generic data structure */ |
4634 | dev = alloc_etherdev(sizeof(net_local)); | 4631 | dev = alloc_etherdev(sizeof(net_local)); |
4635 | if (!dev) { | 4632 | if (!dev) { |
4636 | kfree(link); | 4633 | kfree(link); |
4637 | return NULL; | 4634 | return -ENOMEM; |
4638 | } | 4635 | } |
4639 | link->priv = link->irq.Instance = dev; | 4636 | link->priv = link->irq.Instance = dev; |
4640 | 4637 | ||
@@ -4679,28 +4676,21 @@ wavelan_attach(void) | |||
4679 | /* Other specific data */ | 4676 | /* Other specific data */ |
4680 | dev->mtu = WAVELAN_MTU; | 4677 | dev->mtu = WAVELAN_MTU; |
4681 | 4678 | ||
4682 | /* Register with Card Services */ | 4679 | link->handle = p_dev; |
4683 | client_reg.dev_info = &dev_info; | 4680 | p_dev->instance = link; |
4684 | client_reg.Version = 0x0210; | ||
4685 | client_reg.event_callback_args.client_data = link; | ||
4686 | 4681 | ||
4687 | #ifdef DEBUG_CONFIG_INFO | 4682 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
4688 | printk(KERN_DEBUG "wavelan_attach(): almost done, calling pcmcia_register_client\n"); | 4683 | if(wv_pcmcia_config(link) && |
4689 | #endif | 4684 | wv_hw_config(dev)) |
4690 | 4685 | wv_init_info(dev); | |
4691 | ret = pcmcia_register_client(&link->handle, &client_reg); | 4686 | else |
4692 | if(ret != 0) | 4687 | dev->irq = 0; |
4693 | { | ||
4694 | cs_error(link->handle, RegisterClient, ret); | ||
4695 | wavelan_detach(link); | ||
4696 | return NULL; | ||
4697 | } | ||
4698 | 4688 | ||
4699 | #ifdef DEBUG_CALLBACK_TRACE | 4689 | #ifdef DEBUG_CALLBACK_TRACE |
4700 | printk(KERN_DEBUG "<- wavelan_attach()\n"); | 4690 | printk(KERN_DEBUG "<- wavelan_attach()\n"); |
4701 | #endif | 4691 | #endif |
4702 | 4692 | ||
4703 | return link; | 4693 | return 0; |
4704 | } | 4694 | } |
4705 | 4695 | ||
4706 | /*------------------------------------------------------------------*/ | 4696 | /*------------------------------------------------------------------*/ |
@@ -4711,8 +4701,10 @@ wavelan_attach(void) | |||
4711 | * is released. | 4701 | * is released. |
4712 | */ | 4702 | */ |
4713 | static void | 4703 | static void |
4714 | wavelan_detach(dev_link_t * link) | 4704 | wavelan_detach(struct pcmcia_device *p_dev) |
4715 | { | 4705 | { |
4706 | dev_link_t *link = dev_to_instance(p_dev); | ||
4707 | |||
4716 | #ifdef DEBUG_CALLBACK_TRACE | 4708 | #ifdef DEBUG_CALLBACK_TRACE |
4717 | printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); | 4709 | printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); |
4718 | #endif | 4710 | #endif |
@@ -4729,31 +4721,6 @@ wavelan_detach(dev_link_t * link) | |||
4729 | wv_pcmcia_release(link); | 4721 | wv_pcmcia_release(link); |
4730 | } | 4722 | } |
4731 | 4723 | ||
4732 | /* Break the link with Card Services */ | ||
4733 | if(link->handle) | ||
4734 | pcmcia_deregister_client(link->handle); | ||
4735 | |||
4736 | /* Remove the interface data from the linked list */ | ||
4737 | if(dev_list == link) | ||
4738 | dev_list = link->next; | ||
4739 | else | ||
4740 | { | ||
4741 | dev_link_t * prev = dev_list; | ||
4742 | |||
4743 | while((prev != (dev_link_t *) NULL) && (prev->next != link)) | ||
4744 | prev = prev->next; | ||
4745 | |||
4746 | if(prev == (dev_link_t *) NULL) | ||
4747 | { | ||
4748 | #ifdef DEBUG_CONFIG_ERRORS | ||
4749 | printk(KERN_WARNING "wavelan_detach : Attempting to remove a nonexistent device.\n"); | ||
4750 | #endif | ||
4751 | return; | ||
4752 | } | ||
4753 | |||
4754 | prev->next = link->next; | ||
4755 | } | ||
4756 | |||
4757 | /* Free pieces */ | 4724 | /* Free pieces */ |
4758 | if(link->priv) | 4725 | if(link->priv) |
4759 | { | 4726 | { |
@@ -4775,65 +4742,11 @@ wavelan_detach(dev_link_t * link) | |||
4775 | #endif | 4742 | #endif |
4776 | } | 4743 | } |
4777 | 4744 | ||
4778 | /*------------------------------------------------------------------*/ | 4745 | static int wavelan_suspend(struct pcmcia_device *p_dev) |
4779 | /* | ||
4780 | * The card status event handler. Mostly, this schedules other stuff | ||
4781 | * to run after an event is received. A CARD_REMOVAL event also sets | ||
4782 | * some flags to discourage the net drivers from trying to talk to the | ||
4783 | * card any more. | ||
4784 | */ | ||
4785 | static int | ||
4786 | wavelan_event(event_t event, /* The event received */ | ||
4787 | int priority, | ||
4788 | event_callback_args_t * args) | ||
4789 | { | 4746 | { |
4790 | dev_link_t * link = (dev_link_t *) args->client_data; | 4747 | dev_link_t *link = dev_to_instance(p_dev); |
4791 | struct net_device * dev = (struct net_device *) link->priv; | 4748 | struct net_device * dev = (struct net_device *) link->priv; |
4792 | |||
4793 | #ifdef DEBUG_CALLBACK_TRACE | ||
4794 | printk(KERN_DEBUG "->wavelan_event(): %s\n", | ||
4795 | ((event == CS_EVENT_REGISTRATION_COMPLETE)?"registration complete" : | ||
4796 | ((event == CS_EVENT_CARD_REMOVAL) ? "card removal" : | ||
4797 | ((event == CS_EVENT_CARD_INSERTION) ? "card insertion" : | ||
4798 | ((event == CS_EVENT_PM_SUSPEND) ? "pm suspend" : | ||
4799 | ((event == CS_EVENT_RESET_PHYSICAL) ? "physical reset" : | ||
4800 | ((event == CS_EVENT_PM_RESUME) ? "pm resume" : | ||
4801 | ((event == CS_EVENT_CARD_RESET) ? "card reset" : | ||
4802 | "unknown")))))))); | ||
4803 | #endif | ||
4804 | |||
4805 | switch(event) | ||
4806 | { | ||
4807 | case CS_EVENT_REGISTRATION_COMPLETE: | ||
4808 | #ifdef DEBUG_CONFIG_INFO | ||
4809 | printk(KERN_DEBUG "wavelan_cs: registration complete\n"); | ||
4810 | #endif | ||
4811 | break; | ||
4812 | 4749 | ||
4813 | case CS_EVENT_CARD_REMOVAL: | ||
4814 | /* Oups ! The card is no more there */ | ||
4815 | link->state &= ~DEV_PRESENT; | ||
4816 | if(link->state & DEV_CONFIG) | ||
4817 | { | ||
4818 | /* Accept no more transmissions */ | ||
4819 | netif_device_detach(dev); | ||
4820 | |||
4821 | /* Release the card */ | ||
4822 | wv_pcmcia_release(link); | ||
4823 | } | ||
4824 | break; | ||
4825 | |||
4826 | case CS_EVENT_CARD_INSERTION: | ||
4827 | /* Reset and configure the card */ | ||
4828 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
4829 | if(wv_pcmcia_config(link) && | ||
4830 | wv_hw_config(dev)) | ||
4831 | wv_init_info(dev); | ||
4832 | else | ||
4833 | dev->irq = 0; | ||
4834 | break; | ||
4835 | |||
4836 | case CS_EVENT_PM_SUSPEND: | ||
4837 | /* NB: wavelan_close will be called, but too late, so we are | 4750 | /* NB: wavelan_close will be called, but too late, so we are |
4838 | * obliged to close nicely the wavelan here. David, could you | 4751 | * obliged to close nicely the wavelan here. David, could you |
4839 | * close the device before suspending them ? And, by the way, | 4752 | * close the device before suspending them ? And, by the way, |
@@ -4848,38 +4761,37 @@ wavelan_event(event_t event, /* The event received */ | |||
4848 | 4761 | ||
4849 | /* The card is now suspended */ | 4762 | /* The card is now suspended */ |
4850 | link->state |= DEV_SUSPEND; | 4763 | link->state |= DEV_SUSPEND; |
4851 | /* Fall through... */ | 4764 | |
4852 | case CS_EVENT_RESET_PHYSICAL: | ||
4853 | if(link->state & DEV_CONFIG) | 4765 | if(link->state & DEV_CONFIG) |
4854 | { | 4766 | { |
4855 | if(link->open) | 4767 | if(link->open) |
4856 | netif_device_detach(dev); | 4768 | netif_device_detach(dev); |
4857 | pcmcia_release_configuration(link->handle); | 4769 | pcmcia_release_configuration(link->handle); |
4858 | } | 4770 | } |
4859 | break; | 4771 | |
4772 | return 0; | ||
4773 | } | ||
4774 | |||
4775 | static int wavelan_resume(struct pcmcia_device *p_dev) | ||
4776 | { | ||
4777 | dev_link_t *link = dev_to_instance(p_dev); | ||
4778 | struct net_device * dev = (struct net_device *) link->priv; | ||
4860 | 4779 | ||
4861 | case CS_EVENT_PM_RESUME: | ||
4862 | link->state &= ~DEV_SUSPEND; | 4780 | link->state &= ~DEV_SUSPEND; |
4863 | /* Fall through... */ | ||
4864 | case CS_EVENT_CARD_RESET: | ||
4865 | if(link->state & DEV_CONFIG) | 4781 | if(link->state & DEV_CONFIG) |
4866 | { | 4782 | { |
4867 | pcmcia_request_configuration(link->handle, &link->conf); | 4783 | pcmcia_request_configuration(link->handle, &link->conf); |
4868 | if(link->open) /* If RESET -> True, If RESUME -> False ? */ | 4784 | if(link->open) /* If RESET -> True, If RESUME -> False ? */ |
4869 | { | 4785 | { |
4870 | wv_hw_reset(dev); | 4786 | wv_hw_reset(dev); |
4871 | netif_device_attach(dev); | 4787 | netif_device_attach(dev); |
4872 | } | 4788 | } |
4873 | } | 4789 | } |
4874 | break; | ||
4875 | } | ||
4876 | 4790 | ||
4877 | #ifdef DEBUG_CALLBACK_TRACE | 4791 | return 0; |
4878 | printk(KERN_DEBUG "<-wavelan_event()\n"); | ||
4879 | #endif | ||
4880 | return 0; | ||
4881 | } | 4792 | } |
4882 | 4793 | ||
4794 | |||
4883 | static struct pcmcia_device_id wavelan_ids[] = { | 4795 | static struct pcmcia_device_id wavelan_ids[] = { |
4884 | PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), | 4796 | PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), |
4885 | PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), | 4797 | PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), |
@@ -4894,10 +4806,11 @@ static struct pcmcia_driver wavelan_driver = { | |||
4894 | .drv = { | 4806 | .drv = { |
4895 | .name = "wavelan_cs", | 4807 | .name = "wavelan_cs", |
4896 | }, | 4808 | }, |
4897 | .attach = wavelan_attach, | 4809 | .probe = wavelan_attach, |
4898 | .event = wavelan_event, | 4810 | .remove = wavelan_detach, |
4899 | .detach = wavelan_detach, | ||
4900 | .id_table = wavelan_ids, | 4811 | .id_table = wavelan_ids, |
4812 | .suspend = wavelan_suspend, | ||
4813 | .resume = wavelan_resume, | ||
4901 | }; | 4814 | }; |
4902 | 4815 | ||
4903 | static int __init | 4816 | static int __init |
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index 724a715089c9..f2d597568151 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h | |||
@@ -754,20 +754,11 @@ static void | |||
754 | static int | 754 | static int |
755 | wavelan_open(struct net_device *), /* Open the device */ | 755 | wavelan_open(struct net_device *), /* Open the device */ |
756 | wavelan_close(struct net_device *); /* Close the device */ | 756 | wavelan_close(struct net_device *); /* Close the device */ |
757 | static dev_link_t * | ||
758 | wavelan_attach(void); /* Create a new device */ | ||
759 | static void | 757 | static void |
760 | wavelan_detach(dev_link_t *); /* Destroy a removed device */ | 758 | wavelan_detach(struct pcmcia_device *p_dev); /* Destroy a removed device */ |
761 | static int | ||
762 | wavelan_event(event_t, /* Manage pcmcia events */ | ||
763 | int, | ||
764 | event_callback_args_t *); | ||
765 | 759 | ||
766 | /**************************** VARIABLES ****************************/ | 760 | /**************************** VARIABLES ****************************/ |
767 | 761 | ||
768 | static dev_info_t dev_info = "wavelan_cs"; | ||
769 | static dev_link_t *dev_list = NULL; /* Linked list of devices */ | ||
770 | |||
771 | /* | 762 | /* |
772 | * Parameters that can be set with 'insmod' | 763 | * Parameters that can be set with 'insmod' |
773 | * The exact syntax is 'insmod wavelan_cs.o <var>=<value>' | 764 | * The exact syntax is 'insmod wavelan_cs.o <var>=<value>' |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 978fdc606781..48e10b0c7e74 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -105,7 +105,6 @@ module_param(pc_debug, int, 0); | |||
105 | */ | 105 | */ |
106 | static void wl3501_config(dev_link_t *link); | 106 | static void wl3501_config(dev_link_t *link); |
107 | static void wl3501_release(dev_link_t *link); | 107 | static void wl3501_release(dev_link_t *link); |
108 | static int wl3501_event(event_t event, int pri, event_callback_args_t *args); | ||
109 | 108 | ||
110 | /* | 109 | /* |
111 | * The dev_info variable is the "key" that is used to match up this | 110 | * The dev_info variable is the "key" that is used to match up this |
@@ -1498,9 +1497,11 @@ static struct ethtool_ops ops = { | |||
1498 | * Services. If it has been released, all local data structures are freed. | 1497 | * Services. If it has been released, all local data structures are freed. |
1499 | * Otherwise, the structures will be freed when the device is released. | 1498 | * Otherwise, the structures will be freed when the device is released. |
1500 | */ | 1499 | */ |
1501 | static void wl3501_detach(dev_link_t *link) | 1500 | static void wl3501_detach(struct pcmcia_device *p_dev) |
1502 | { | 1501 | { |
1502 | dev_link_t *link = dev_to_instance(p_dev); | ||
1503 | dev_link_t **linkp; | 1503 | dev_link_t **linkp; |
1504 | struct net_device *dev = link->priv; | ||
1504 | 1505 | ||
1505 | /* Locate device structure */ | 1506 | /* Locate device structure */ |
1506 | for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next) | 1507 | for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next) |
@@ -1514,16 +1515,12 @@ static void wl3501_detach(dev_link_t *link) | |||
1514 | * function is called, that will trigger a proper detach(). */ | 1515 | * function is called, that will trigger a proper detach(). */ |
1515 | 1516 | ||
1516 | if (link->state & DEV_CONFIG) { | 1517 | if (link->state & DEV_CONFIG) { |
1517 | #ifdef PCMCIA_DEBUG | 1518 | while (link->open > 0) |
1518 | printk(KERN_DEBUG "wl3501_cs: detach postponed, '%s' " | 1519 | wl3501_close(dev); |
1519 | "still locked\n", link->dev->dev_name); | ||
1520 | #endif | ||
1521 | goto out; | ||
1522 | } | ||
1523 | 1520 | ||
1524 | /* Break the link with Card Services */ | 1521 | netif_device_detach(dev); |
1525 | if (link->handle) | 1522 | wl3501_release(link); |
1526 | pcmcia_deregister_client(link->handle); | 1523 | } |
1527 | 1524 | ||
1528 | /* Unlink device structure, free pieces */ | 1525 | /* Unlink device structure, free pieces */ |
1529 | *linkp = link->next; | 1526 | *linkp = link->next; |
@@ -1956,18 +1953,16 @@ static const struct iw_handler_def wl3501_handler_def = { | |||
1956 | * The dev_link structure is initialized, but we don't actually configure the | 1953 | * The dev_link structure is initialized, but we don't actually configure the |
1957 | * card at this point -- we wait until we receive a card insertion event. | 1954 | * card at this point -- we wait until we receive a card insertion event. |
1958 | */ | 1955 | */ |
1959 | static dev_link_t *wl3501_attach(void) | 1956 | static int wl3501_attach(struct pcmcia_device *p_dev) |
1960 | { | 1957 | { |
1961 | client_reg_t client_reg; | ||
1962 | dev_link_t *link; | 1958 | dev_link_t *link; |
1963 | struct net_device *dev; | 1959 | struct net_device *dev; |
1964 | struct wl3501_card *this; | 1960 | struct wl3501_card *this; |
1965 | int ret; | ||
1966 | 1961 | ||
1967 | /* Initialize the dev_link_t structure */ | 1962 | /* Initialize the dev_link_t structure */ |
1968 | link = kzalloc(sizeof(*link), GFP_KERNEL); | 1963 | link = kzalloc(sizeof(*link), GFP_KERNEL); |
1969 | if (!link) | 1964 | if (!link) |
1970 | goto out; | 1965 | return -ENOMEM; |
1971 | 1966 | ||
1972 | /* The io structure describes IO port mapping */ | 1967 | /* The io structure describes IO port mapping */ |
1973 | link->io.NumPorts1 = 16; | 1968 | link->io.NumPorts1 = 16; |
@@ -2003,24 +1998,17 @@ static dev_link_t *wl3501_attach(void) | |||
2003 | netif_stop_queue(dev); | 1998 | netif_stop_queue(dev); |
2004 | link->priv = link->irq.Instance = dev; | 1999 | link->priv = link->irq.Instance = dev; |
2005 | 2000 | ||
2006 | /* Register with Card Services */ | 2001 | link->handle = p_dev; |
2007 | link->next = wl3501_dev_list; | 2002 | p_dev->instance = link; |
2008 | wl3501_dev_list = link; | 2003 | |
2009 | client_reg.dev_info = &wl3501_dev_info; | 2004 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
2010 | client_reg.Version = 0x0210; | 2005 | wl3501_config(link); |
2011 | client_reg.event_callback_args.client_data = link; | 2006 | |
2012 | ret = pcmcia_register_client(&link->handle, &client_reg); | 2007 | return 0; |
2013 | if (ret) { | ||
2014 | cs_error(link->handle, RegisterClient, ret); | ||
2015 | wl3501_detach(link); | ||
2016 | link = NULL; | ||
2017 | } | ||
2018 | out: | ||
2019 | return link; | ||
2020 | out_link: | 2008 | out_link: |
2021 | kfree(link); | 2009 | kfree(link); |
2022 | link = NULL; | 2010 | link = NULL; |
2023 | goto out; | 2011 | return -ENOMEM; |
2024 | } | 2012 | } |
2025 | 2013 | ||
2026 | #define CS_CHECK(fn, ret) \ | 2014 | #define CS_CHECK(fn, ret) \ |
@@ -2173,67 +2161,41 @@ static void wl3501_release(dev_link_t *link) | |||
2173 | link->state &= ~DEV_CONFIG; | 2161 | link->state &= ~DEV_CONFIG; |
2174 | } | 2162 | } |
2175 | 2163 | ||
2176 | /** | 2164 | static int wl3501_suspend(struct pcmcia_device *p_dev) |
2177 | * wl3501_event - The card status event handler | ||
2178 | * @event - event | ||
2179 | * @pri - priority | ||
2180 | * @args - arguments for this event | ||
2181 | * | ||
2182 | * The card status event handler. Mostly, this schedules other stuff to run | ||
2183 | * after an event is received. A CARD_REMOVAL event also sets some flags to | ||
2184 | * discourage the net drivers from trying to talk to the card any more. | ||
2185 | * | ||
2186 | * When a CARD_REMOVAL event is received, we immediately set a flag to block | ||
2187 | * future accesses to this device. All the functions that actually access the | ||
2188 | * device should check this flag to make sure the card is still present. | ||
2189 | */ | ||
2190 | static int wl3501_event(event_t event, int pri, event_callback_args_t *args) | ||
2191 | { | 2165 | { |
2192 | dev_link_t *link = args->client_data; | 2166 | dev_link_t *link = dev_to_instance(p_dev); |
2193 | struct net_device *dev = link->priv; | 2167 | struct net_device *dev = link->priv; |
2194 | 2168 | ||
2195 | switch (event) { | 2169 | link->state |= DEV_SUSPEND; |
2196 | case CS_EVENT_CARD_REMOVAL: | 2170 | |
2197 | link->state &= ~DEV_PRESENT; | 2171 | wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND); |
2198 | if (link->state & DEV_CONFIG) { | 2172 | if (link->state & DEV_CONFIG) { |
2199 | while (link->open > 0) | 2173 | if (link->open) |
2200 | wl3501_close(dev); | ||
2201 | netif_device_detach(dev); | 2174 | netif_device_detach(dev); |
2202 | wl3501_release(link); | 2175 | pcmcia_release_configuration(link->handle); |
2203 | } | 2176 | } |
2204 | break; | 2177 | |
2205 | case CS_EVENT_CARD_INSERTION: | 2178 | return 0; |
2206 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 2179 | } |
2207 | wl3501_config(link); | 2180 | |
2208 | break; | 2181 | static int wl3501_resume(struct pcmcia_device *p_dev) |
2209 | case CS_EVENT_PM_SUSPEND: | 2182 | { |
2210 | link->state |= DEV_SUSPEND; | 2183 | dev_link_t *link = dev_to_instance(p_dev); |
2211 | wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND); | 2184 | struct net_device *dev = link->priv; |
2212 | /* Fall through... */ | 2185 | |
2213 | case CS_EVENT_RESET_PHYSICAL: | 2186 | wl3501_pwr_mgmt(dev->priv, WL3501_RESUME); |
2214 | if (link->state & DEV_CONFIG) { | 2187 | if (link->state & DEV_CONFIG) { |
2215 | if (link->open) | 2188 | pcmcia_request_configuration(link->handle, &link->conf); |
2216 | netif_device_detach(dev); | 2189 | if (link->open) { |
2217 | pcmcia_release_configuration(link->handle); | 2190 | wl3501_reset(dev); |
2218 | } | 2191 | netif_device_attach(dev); |
2219 | break; | ||
2220 | case CS_EVENT_PM_RESUME: | ||
2221 | link->state &= ~DEV_SUSPEND; | ||
2222 | wl3501_pwr_mgmt(dev->priv, WL3501_RESUME); | ||
2223 | /* Fall through... */ | ||
2224 | case CS_EVENT_CARD_RESET: | ||
2225 | if (link->state & DEV_CONFIG) { | ||
2226 | pcmcia_request_configuration(link->handle, &link->conf); | ||
2227 | if (link->open) { | ||
2228 | wl3501_reset(dev); | ||
2229 | netif_device_attach(dev); | ||
2230 | } | ||
2231 | } | 2192 | } |
2232 | break; | ||
2233 | } | 2193 | } |
2194 | |||
2234 | return 0; | 2195 | return 0; |
2235 | } | 2196 | } |
2236 | 2197 | ||
2198 | |||
2237 | static struct pcmcia_device_id wl3501_ids[] = { | 2199 | static struct pcmcia_device_id wl3501_ids[] = { |
2238 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001), | 2200 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001), |
2239 | PCMCIA_DEVICE_NULL | 2201 | PCMCIA_DEVICE_NULL |
@@ -2245,10 +2207,11 @@ static struct pcmcia_driver wl3501_driver = { | |||
2245 | .drv = { | 2207 | .drv = { |
2246 | .name = "wl3501_cs", | 2208 | .name = "wl3501_cs", |
2247 | }, | 2209 | }, |
2248 | .attach = wl3501_attach, | 2210 | .probe = wl3501_attach, |
2249 | .event = wl3501_event, | 2211 | .remove = wl3501_detach, |
2250 | .detach = wl3501_detach, | ||
2251 | .id_table = wl3501_ids, | 2212 | .id_table = wl3501_ids, |
2213 | .suspend = wl3501_suspend, | ||
2214 | .resume = wl3501_resume, | ||
2252 | }; | 2215 | }; |
2253 | 2216 | ||
2254 | static int __init wl3501_init_module(void) | 2217 | static int __init wl3501_init_module(void) |