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