diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/libertas/decl.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_cs.c | 54 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.c | 365 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 405 |
6 files changed, 334 insertions, 501 deletions
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 095edf6a4c29..87fea9d5b90a 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -72,8 +72,9 @@ void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str); | |||
72 | struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, | 72 | struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, |
73 | int *cfp_no); | 73 | int *cfp_no); |
74 | wlan_private *libertas_add_card(void *card, struct device *dmdev); | 74 | wlan_private *libertas_add_card(void *card, struct device *dmdev); |
75 | int libertas_activate_card(wlan_private *priv); | ||
76 | int libertas_remove_card(wlan_private *priv); | 75 | int libertas_remove_card(wlan_private *priv); |
76 | int libertas_start_card(wlan_private *priv); | ||
77 | int libertas_stop_card(wlan_private *priv); | ||
77 | int libertas_add_mesh(wlan_private *priv, struct device *dev); | 78 | int libertas_add_mesh(wlan_private *priv, struct device *dev); |
78 | void libertas_remove_mesh(wlan_private *priv); | 79 | void libertas_remove_mesh(wlan_private *priv); |
79 | int libertas_reset_device(wlan_private *priv); | 80 | int libertas_reset_device(wlan_private *priv); |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index a3c94d7388ab..1fb807aa91b9 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -143,7 +143,6 @@ struct _wlan_private { | |||
143 | all other bits reserved 0 */ | 143 | all other bits reserved 0 */ |
144 | u8 dnld_sent; | 144 | u8 dnld_sent; |
145 | 145 | ||
146 | const struct firmware *firmware; | ||
147 | struct device *hotplug_device; | 146 | struct device *hotplug_device; |
148 | 147 | ||
149 | /** thread to service interrupts */ | 148 | /** thread to service interrupts */ |
@@ -156,9 +155,6 @@ struct _wlan_private { | |||
156 | struct work_struct sync_channel; | 155 | struct work_struct sync_channel; |
157 | 156 | ||
158 | /** Hardware access */ | 157 | /** Hardware access */ |
159 | int (*hw_register_dev) (wlan_private * priv); | ||
160 | int (*hw_unregister_dev) (wlan_private *); | ||
161 | int (*hw_prog_firmware) (wlan_private *); | ||
162 | int (*hw_host_to_card) (wlan_private * priv, u8 type, u8 * payload, u16 nb); | 158 | int (*hw_host_to_card) (wlan_private * priv, u8 type, u8 * payload, u16 nb); |
163 | int (*hw_get_int_status) (wlan_private * priv, u8 *); | 159 | int (*hw_get_int_status) (wlan_private * priv, u8 *); |
164 | int (*hw_read_event_cause) (wlan_private *); | 160 | int (*hw_read_event_cause) (wlan_private *); |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 888f023a74e1..4dffc5cc0d1a 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -608,51 +608,6 @@ done: | |||
608 | /* Callback functions for libertas.ko */ | 608 | /* Callback functions for libertas.ko */ |
609 | /********************************************************************/ | 609 | /********************************************************************/ |
610 | 610 | ||
611 | static int if_cs_register_dev(wlan_private *priv) | ||
612 | { | ||
613 | struct if_cs_card *card = (struct if_cs_card *)priv->card; | ||
614 | |||
615 | lbs_deb_enter(LBS_DEB_CS); | ||
616 | |||
617 | card->priv = priv; | ||
618 | |||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | |||
623 | static int if_cs_unregister_dev(wlan_private *priv) | ||
624 | { | ||
625 | lbs_deb_enter(LBS_DEB_CS); | ||
626 | |||
627 | /* | ||
628 | * Nothing special here. Because the device's power gets turned off | ||
629 | * anyway, there's no need to send a RESET command like in if_usb.c | ||
630 | */ | ||
631 | |||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | |||
636 | /* | ||
637 | * This callback is a dummy. The reason is that the USB code needs | ||
638 | * to have various things set up in order to be able to download the | ||
639 | * firmware. That's not needed in our case. | ||
640 | * | ||
641 | * On the contrary, if libertas_add_card() has been called and we're | ||
642 | * then later called via libertas_activate_card(), but without a valid | ||
643 | * firmware, then it's quite tedious to tear down the half-installed | ||
644 | * card. Therefore, we download the firmware before calling adding/ | ||
645 | * activating the card in the first place. If that doesn't work, we | ||
646 | * won't call into libertas.ko at all. | ||
647 | */ | ||
648 | |||
649 | static int if_cs_prog_firmware(wlan_private *priv) | ||
650 | { | ||
651 | priv->adapter->fw_ready = 1; | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | |||
656 | /* Send commands or data packets to the card */ | 611 | /* Send commands or data packets to the card */ |
657 | static int if_cs_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb) | 612 | static int if_cs_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb) |
658 | { | 613 | { |
@@ -902,14 +857,14 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
902 | } | 857 | } |
903 | 858 | ||
904 | /* Store pointers to our call-back functions */ | 859 | /* Store pointers to our call-back functions */ |
860 | card->priv = priv; | ||
905 | priv->card = card; | 861 | priv->card = card; |
906 | priv->hw_register_dev = if_cs_register_dev; | ||
907 | priv->hw_unregister_dev = if_cs_unregister_dev; | ||
908 | priv->hw_prog_firmware = if_cs_prog_firmware; | ||
909 | priv->hw_host_to_card = if_cs_host_to_card; | 862 | priv->hw_host_to_card = if_cs_host_to_card; |
910 | priv->hw_get_int_status = if_cs_get_int_status; | 863 | priv->hw_get_int_status = if_cs_get_int_status; |
911 | priv->hw_read_event_cause = if_cs_read_event_cause; | 864 | priv->hw_read_event_cause = if_cs_read_event_cause; |
912 | 865 | ||
866 | priv->adapter->fw_ready = 1; | ||
867 | |||
913 | /* Now actually get the IRQ */ | 868 | /* Now actually get the IRQ */ |
914 | ret = request_irq(p_dev->irq.AssignedIRQ, if_cs_interrupt, | 869 | ret = request_irq(p_dev->irq.AssignedIRQ, if_cs_interrupt, |
915 | IRQF_SHARED, DRV_NAME, card); | 870 | IRQF_SHARED, DRV_NAME, card); |
@@ -919,7 +874,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
919 | } | 874 | } |
920 | 875 | ||
921 | /* And finally bring the card up */ | 876 | /* And finally bring the card up */ |
922 | if (libertas_activate_card(priv) != 0) { | 877 | if (libertas_start_card(priv) != 0) { |
923 | lbs_pr_err("could not activate card\n"); | 878 | lbs_pr_err("could not activate card\n"); |
924 | goto out3; | 879 | goto out3; |
925 | } | 880 | } |
@@ -951,6 +906,7 @@ static void if_cs_detach(struct pcmcia_device *p_dev) | |||
951 | 906 | ||
952 | lbs_deb_enter(LBS_DEB_CS); | 907 | lbs_deb_enter(LBS_DEB_CS); |
953 | 908 | ||
909 | libertas_stop_card(card->priv); | ||
954 | libertas_remove_card(card->priv); | 910 | libertas_remove_card(card->priv); |
955 | if_cs_release(p_dev); | 911 | if_cs_release(p_dev); |
956 | kfree(card); | 912 | kfree(card); |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 364eae374b93..105a00a7025d 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -45,14 +45,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table); | |||
45 | 45 | ||
46 | static void if_usb_receive(struct urb *urb); | 46 | static void if_usb_receive(struct urb *urb); |
47 | static void if_usb_receive_fwload(struct urb *urb); | 47 | static void if_usb_receive_fwload(struct urb *urb); |
48 | static int if_usb_register_dev(wlan_private * priv); | 48 | static int if_usb_prog_firmware(struct usb_card_rec *cardp); |
49 | static int if_usb_unregister_dev(wlan_private *); | ||
50 | static int if_usb_prog_firmware(wlan_private *); | ||
51 | static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb); | 49 | static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb); |
52 | static int if_usb_get_int_status(wlan_private * priv, u8 *); | 50 | static int if_usb_get_int_status(wlan_private * priv, u8 *); |
53 | static int if_usb_read_event_cause(wlan_private *); | 51 | static int if_usb_read_event_cause(wlan_private *); |
54 | static int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb); | 52 | static int usb_tx_block(struct usb_card_rec *cardp, u8 *payload, u16 nb); |
55 | static void if_usb_free(struct usb_card_rec *cardp); | 53 | static void if_usb_free(struct usb_card_rec *cardp); |
54 | static int if_usb_submit_rx_urb(struct usb_card_rec *cardp); | ||
55 | static int if_usb_reset_device(struct usb_card_rec *cardp); | ||
56 | 56 | ||
57 | /** | 57 | /** |
58 | * @brief call back function to handle the status of the URB | 58 | * @brief call back function to handle the status of the URB |
@@ -61,29 +61,40 @@ static void if_usb_free(struct usb_card_rec *cardp); | |||
61 | */ | 61 | */ |
62 | static void if_usb_write_bulk_callback(struct urb *urb) | 62 | static void if_usb_write_bulk_callback(struct urb *urb) |
63 | { | 63 | { |
64 | wlan_private *priv = (wlan_private *) (urb->context); | 64 | struct usb_card_rec *cardp = (struct usb_card_rec *) urb->context; |
65 | wlan_adapter *adapter = priv->adapter; | ||
66 | struct net_device *dev = priv->dev; | ||
67 | 65 | ||
68 | /* handle the transmission complete validations */ | 66 | /* handle the transmission complete validations */ |
69 | 67 | ||
70 | if (urb->status != 0) { | 68 | if (urb->status == 0) { |
71 | /* print the failure status number for debug */ | 69 | wlan_private *priv = cardp->priv; |
72 | lbs_pr_info("URB in failure status: %d\n", urb->status); | 70 | |
73 | } else { | ||
74 | /* | 71 | /* |
75 | lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n"); | 72 | lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n"); |
76 | lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n", | 73 | lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n", |
77 | urb->actual_length); | 74 | urb->actual_length); |
78 | */ | 75 | */ |
79 | priv->dnld_sent = DNLD_RES_RECEIVED; | 76 | |
80 | /* Wake main thread if commands are pending */ | 77 | /* Used for both firmware TX and regular TX. priv isn't |
81 | if (!adapter->cur_cmd) | 78 | * valid at firmware load time. |
82 | wake_up_interruptible(&priv->waitq); | 79 | */ |
83 | if ((adapter->connect_status == LIBERTAS_CONNECTED)) { | 80 | if (priv) { |
84 | netif_wake_queue(dev); | 81 | wlan_adapter *adapter = priv->adapter; |
85 | netif_wake_queue(priv->mesh_dev); | 82 | struct net_device *dev = priv->dev; |
83 | |||
84 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
85 | |||
86 | /* Wake main thread if commands are pending */ | ||
87 | if (!adapter->cur_cmd) | ||
88 | wake_up_interruptible(&priv->waitq); | ||
89 | |||
90 | if ((adapter->connect_status == LIBERTAS_CONNECTED)) { | ||
91 | netif_wake_queue(dev); | ||
92 | netif_wake_queue(priv->mesh_dev); | ||
93 | } | ||
86 | } | 94 | } |
95 | } else { | ||
96 | /* print the failure status number for debug */ | ||
97 | lbs_pr_info("URB in failure status: %d\n", urb->status); | ||
87 | } | 98 | } |
88 | 99 | ||
89 | return; | 100 | return; |
@@ -205,24 +216,35 @@ static int if_usb_probe(struct usb_interface *intf, | |||
205 | } | 216 | } |
206 | } | 217 | } |
207 | 218 | ||
219 | /* Upload firmware */ | ||
220 | cardp->rinfo.cardp = cardp; | ||
221 | if (if_usb_prog_firmware(cardp)) { | ||
222 | lbs_deb_usbd(&udev->dev, "FW upload failed"); | ||
223 | goto err_prog_firmware; | ||
224 | } | ||
225 | |||
208 | if (!(priv = libertas_add_card(cardp, &udev->dev))) | 226 | if (!(priv = libertas_add_card(cardp, &udev->dev))) |
209 | goto dealloc; | 227 | goto err_prog_firmware; |
210 | 228 | ||
211 | udev->dev.driver_data = priv; | 229 | cardp->priv = priv; |
212 | 230 | ||
213 | if (libertas_add_mesh(priv, &udev->dev)) | 231 | if (libertas_add_mesh(priv, &udev->dev)) |
214 | goto err_add_mesh; | 232 | goto err_add_mesh; |
215 | 233 | ||
216 | priv->hw_register_dev = if_usb_register_dev; | 234 | cardp->eth_dev = priv->dev; |
217 | priv->hw_unregister_dev = if_usb_unregister_dev; | 235 | |
218 | priv->hw_prog_firmware = if_usb_prog_firmware; | ||
219 | priv->hw_host_to_card = if_usb_host_to_card; | 236 | priv->hw_host_to_card = if_usb_host_to_card; |
220 | priv->hw_get_int_status = if_usb_get_int_status; | 237 | priv->hw_get_int_status = if_usb_get_int_status; |
221 | priv->hw_read_event_cause = if_usb_read_event_cause; | 238 | priv->hw_read_event_cause = if_usb_read_event_cause; |
222 | priv->boot2_version = udev->descriptor.bcdDevice; | 239 | priv->boot2_version = udev->descriptor.bcdDevice; |
223 | 240 | ||
224 | if (libertas_activate_card(priv)) | 241 | /* Delay 200 ms to waiting for the FW ready */ |
225 | goto err_activate_card; | 242 | if_usb_submit_rx_urb(cardp); |
243 | msleep_interruptible(200); | ||
244 | priv->adapter->fw_ready = 1; | ||
245 | |||
246 | if (libertas_start_card(priv)) | ||
247 | goto err_start_card; | ||
226 | 248 | ||
227 | list_add_tail(&cardp->list, &usb_devices); | 249 | list_add_tail(&cardp->list, &usb_devices); |
228 | 250 | ||
@@ -231,11 +253,12 @@ static int if_usb_probe(struct usb_interface *intf, | |||
231 | 253 | ||
232 | return 0; | 254 | return 0; |
233 | 255 | ||
234 | err_activate_card: | 256 | err_start_card: |
235 | libertas_remove_mesh(priv); | 257 | libertas_remove_mesh(priv); |
236 | err_add_mesh: | 258 | err_add_mesh: |
237 | free_netdev(priv->dev); | 259 | libertas_remove_card(priv); |
238 | kfree(priv->adapter); | 260 | err_prog_firmware: |
261 | if_usb_reset_device(cardp); | ||
239 | dealloc: | 262 | dealloc: |
240 | if_usb_free(cardp); | 263 | if_usb_free(cardp); |
241 | 264 | ||
@@ -252,21 +275,22 @@ static void if_usb_disconnect(struct usb_interface *intf) | |||
252 | { | 275 | { |
253 | struct usb_card_rec *cardp = usb_get_intfdata(intf); | 276 | struct usb_card_rec *cardp = usb_get_intfdata(intf); |
254 | wlan_private *priv = (wlan_private *) cardp->priv; | 277 | wlan_private *priv = (wlan_private *) cardp->priv; |
255 | wlan_adapter *adapter = NULL; | ||
256 | 278 | ||
257 | adapter = priv->adapter; | 279 | lbs_deb_enter(LBS_DEB_MAIN); |
258 | 280 | ||
259 | /* | 281 | /* Update Surprise removed to TRUE */ |
260 | * Update Surprise removed to TRUE | 282 | cardp->surprise_removed = 1; |
261 | */ | ||
262 | adapter->surpriseremoved = 1; | ||
263 | 283 | ||
264 | list_del(&cardp->list); | 284 | list_del(&cardp->list); |
265 | 285 | ||
266 | /* card is removed and we can call wlan_remove_card */ | 286 | if (priv) { |
267 | lbs_deb_usbd(&cardp->udev->dev, "call remove card\n"); | 287 | wlan_adapter *adapter = priv->adapter; |
268 | libertas_remove_mesh(priv); | 288 | |
269 | libertas_remove_card(priv); | 289 | adapter->surpriseremoved = 1; |
290 | libertas_stop_card(priv); | ||
291 | libertas_remove_mesh(priv); | ||
292 | libertas_remove_card(priv); | ||
293 | } | ||
270 | 294 | ||
271 | /* Unlink and free urb */ | 295 | /* Unlink and free urb */ |
272 | if_usb_free(cardp); | 296 | if_usb_free(cardp); |
@@ -274,7 +298,7 @@ static void if_usb_disconnect(struct usb_interface *intf) | |||
274 | usb_set_intfdata(intf, NULL); | 298 | usb_set_intfdata(intf, NULL); |
275 | usb_put_dev(interface_to_usbdev(intf)); | 299 | usb_put_dev(interface_to_usbdev(intf)); |
276 | 300 | ||
277 | return; | 301 | lbs_deb_leave(LBS_DEB_MAIN); |
278 | } | 302 | } |
279 | 303 | ||
280 | /** | 304 | /** |
@@ -282,12 +306,11 @@ static void if_usb_disconnect(struct usb_interface *intf) | |||
282 | * @param priv pointer to wlan_private | 306 | * @param priv pointer to wlan_private |
283 | * @return 0 | 307 | * @return 0 |
284 | */ | 308 | */ |
285 | static int if_prog_firmware(wlan_private * priv) | 309 | static int if_prog_firmware(struct usb_card_rec *cardp) |
286 | { | 310 | { |
287 | struct usb_card_rec *cardp = priv->card; | ||
288 | struct FWData *fwdata; | 311 | struct FWData *fwdata; |
289 | struct fwheader *fwheader; | 312 | struct fwheader *fwheader; |
290 | u8 *firmware = priv->firmware->data; | 313 | u8 *firmware = cardp->fw->data; |
291 | 314 | ||
292 | fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC); | 315 | fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC); |
293 | 316 | ||
@@ -335,7 +358,7 @@ static int if_prog_firmware(wlan_private * priv) | |||
335 | cardp->totalbytes); | 358 | cardp->totalbytes); |
336 | */ | 359 | */ |
337 | memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE); | 360 | memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE); |
338 | usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); | 361 | usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); |
339 | 362 | ||
340 | } else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { | 363 | } else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { |
341 | /* | 364 | /* |
@@ -345,7 +368,7 @@ static int if_prog_firmware(wlan_private * priv) | |||
345 | "Donwloading FW JUMP BLOCK\n"); | 368 | "Donwloading FW JUMP BLOCK\n"); |
346 | */ | 369 | */ |
347 | memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE); | 370 | memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE); |
348 | usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); | 371 | usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); |
349 | cardp->fwfinalblk = 1; | 372 | cardp->fwfinalblk = 1; |
350 | } | 373 | } |
351 | 374 | ||
@@ -360,10 +383,10 @@ static int if_prog_firmware(wlan_private * priv) | |||
360 | return 0; | 383 | return 0; |
361 | } | 384 | } |
362 | 385 | ||
363 | static int if_usb_reset_device(wlan_private *priv) | 386 | static int if_usb_reset_device(struct usb_card_rec *cardp) |
364 | { | 387 | { |
365 | int ret; | 388 | int ret; |
366 | struct usb_card_rec *cardp = priv->card; | 389 | wlan_private * priv = cardp->priv; |
367 | 390 | ||
368 | lbs_deb_enter(LBS_DEB_USB); | 391 | lbs_deb_enter(LBS_DEB_USB); |
369 | 392 | ||
@@ -371,7 +394,7 @@ static int if_usb_reset_device(wlan_private *priv) | |||
371 | * command to the firmware. | 394 | * command to the firmware. |
372 | */ | 395 | */ |
373 | ret = usb_reset_device(cardp->udev); | 396 | ret = usb_reset_device(cardp->udev); |
374 | if (!ret) { | 397 | if (!ret && priv) { |
375 | msleep(10); | 398 | msleep(10); |
376 | ret = libertas_reset_device(priv); | 399 | ret = libertas_reset_device(priv); |
377 | msleep(10); | 400 | msleep(10); |
@@ -389,14 +412,12 @@ static int if_usb_reset_device(wlan_private *priv) | |||
389 | * @param nb data length | 412 | * @param nb data length |
390 | * @return 0 or -1 | 413 | * @return 0 or -1 |
391 | */ | 414 | */ |
392 | static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb) | 415 | static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb) |
393 | { | 416 | { |
394 | /* pointer to card structure */ | ||
395 | struct usb_card_rec *cardp = priv->card; | ||
396 | int ret = -1; | 417 | int ret = -1; |
397 | 418 | ||
398 | /* check if device is removed */ | 419 | /* check if device is removed */ |
399 | if (priv->adapter->surpriseremoved) { | 420 | if (cardp->surprise_removed) { |
400 | lbs_deb_usbd(&cardp->udev->dev, "Device removed\n"); | 421 | lbs_deb_usbd(&cardp->udev->dev, "Device removed\n"); |
401 | goto tx_ret; | 422 | goto tx_ret; |
402 | } | 423 | } |
@@ -404,7 +425,7 @@ static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb) | |||
404 | usb_fill_bulk_urb(cardp->tx_urb, cardp->udev, | 425 | usb_fill_bulk_urb(cardp->tx_urb, cardp->udev, |
405 | usb_sndbulkpipe(cardp->udev, | 426 | usb_sndbulkpipe(cardp->udev, |
406 | cardp->bulk_out_endpointAddr), | 427 | cardp->bulk_out_endpointAddr), |
407 | payload, nb, if_usb_write_bulk_callback, priv); | 428 | payload, nb, if_usb_write_bulk_callback, cardp); |
408 | 429 | ||
409 | cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET; | 430 | cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET; |
410 | 431 | ||
@@ -421,11 +442,9 @@ tx_ret: | |||
421 | return ret; | 442 | return ret; |
422 | } | 443 | } |
423 | 444 | ||
424 | static int __if_usb_submit_rx_urb(wlan_private * priv, | 445 | static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp, |
425 | void (*callbackfn) | 446 | void (*callbackfn)(struct urb *urb)) |
426 | (struct urb *urb)) | ||
427 | { | 447 | { |
428 | struct usb_card_rec *cardp = priv->card; | ||
429 | struct sk_buff *skb; | 448 | struct sk_buff *skb; |
430 | struct read_cb_info *rinfo = &cardp->rinfo; | 449 | struct read_cb_info *rinfo = &cardp->rinfo; |
431 | int ret = -1; | 450 | int ret = -1; |
@@ -461,22 +480,21 @@ rx_ret: | |||
461 | return ret; | 480 | return ret; |
462 | } | 481 | } |
463 | 482 | ||
464 | static inline int if_usb_submit_rx_urb_fwload(wlan_private * priv) | 483 | static int if_usb_submit_rx_urb_fwload(struct usb_card_rec *cardp) |
465 | { | 484 | { |
466 | return __if_usb_submit_rx_urb(priv, &if_usb_receive_fwload); | 485 | return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload); |
467 | } | 486 | } |
468 | 487 | ||
469 | static inline int if_usb_submit_rx_urb(wlan_private * priv) | 488 | static int if_usb_submit_rx_urb(struct usb_card_rec *cardp) |
470 | { | 489 | { |
471 | return __if_usb_submit_rx_urb(priv, &if_usb_receive); | 490 | return __if_usb_submit_rx_urb(cardp, &if_usb_receive); |
472 | } | 491 | } |
473 | 492 | ||
474 | static void if_usb_receive_fwload(struct urb *urb) | 493 | static void if_usb_receive_fwload(struct urb *urb) |
475 | { | 494 | { |
476 | struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; | 495 | struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; |
477 | wlan_private *priv = rinfo->priv; | ||
478 | struct sk_buff *skb = rinfo->skb; | 496 | struct sk_buff *skb = rinfo->skb; |
479 | struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; | 497 | struct usb_card_rec *cardp = (struct usb_card_rec *)rinfo->cardp; |
480 | struct fwsyncheader *syncfwheader; | 498 | struct fwsyncheader *syncfwheader; |
481 | struct bootcmdrespStr bootcmdresp; | 499 | struct bootcmdrespStr bootcmdresp; |
482 | 500 | ||
@@ -492,7 +510,7 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
492 | sizeof(bootcmdresp)); | 510 | sizeof(bootcmdresp)); |
493 | if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) { | 511 | if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) { |
494 | kfree_skb(skb); | 512 | kfree_skb(skb); |
495 | if_usb_submit_rx_urb_fwload(priv); | 513 | if_usb_submit_rx_urb_fwload(cardp); |
496 | cardp->bootcmdresp = 1; | 514 | cardp->bootcmdresp = 1; |
497 | lbs_deb_usbd(&cardp->udev->dev, | 515 | lbs_deb_usbd(&cardp->udev->dev, |
498 | "Received valid boot command response\n"); | 516 | "Received valid boot command response\n"); |
@@ -516,7 +534,7 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
516 | "Received valid boot command response\n"); | 534 | "Received valid boot command response\n"); |
517 | } | 535 | } |
518 | kfree_skb(skb); | 536 | kfree_skb(skb); |
519 | if_usb_submit_rx_urb_fwload(priv); | 537 | if_usb_submit_rx_urb_fwload(cardp); |
520 | return; | 538 | return; |
521 | } | 539 | } |
522 | 540 | ||
@@ -552,9 +570,9 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
552 | goto exit; | 570 | goto exit; |
553 | } | 571 | } |
554 | 572 | ||
555 | if_prog_firmware(priv); | 573 | if_prog_firmware(cardp); |
556 | 574 | ||
557 | if_usb_submit_rx_urb_fwload(priv); | 575 | if_usb_submit_rx_urb_fwload(cardp); |
558 | exit: | 576 | exit: |
559 | kfree(syncfwheader); | 577 | kfree(syncfwheader); |
560 | 578 | ||
@@ -633,9 +651,9 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff, | |||
633 | static void if_usb_receive(struct urb *urb) | 651 | static void if_usb_receive(struct urb *urb) |
634 | { | 652 | { |
635 | struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; | 653 | struct read_cb_info *rinfo = (struct read_cb_info *)urb->context; |
636 | wlan_private *priv = rinfo->priv; | ||
637 | struct sk_buff *skb = rinfo->skb; | 654 | struct sk_buff *skb = rinfo->skb; |
638 | struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; | 655 | struct usb_card_rec *cardp = (struct usb_card_rec *) rinfo->cardp; |
656 | wlan_private * priv = cardp->priv; | ||
639 | 657 | ||
640 | int recvlength = urb->actual_length; | 658 | int recvlength = urb->actual_length; |
641 | u8 *recvbuff = NULL; | 659 | u8 *recvbuff = NULL; |
@@ -696,7 +714,7 @@ static void if_usb_receive(struct urb *urb) | |||
696 | } | 714 | } |
697 | 715 | ||
698 | setup_for_next: | 716 | setup_for_next: |
699 | if_usb_submit_rx_urb(priv); | 717 | if_usb_submit_rx_urb(cardp); |
700 | rx_exit: | 718 | rx_exit: |
701 | lbs_deb_leave(LBS_DEB_USB); | 719 | lbs_deb_leave(LBS_DEB_USB); |
702 | } | 720 | } |
@@ -731,7 +749,7 @@ static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 n | |||
731 | 749 | ||
732 | memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb); | 750 | memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb); |
733 | 751 | ||
734 | return usb_tx_block(priv, cardp->bulk_out_buffer, | 752 | return usb_tx_block(cardp, cardp->bulk_out_buffer, |
735 | nb + MESSAGE_HEADER_LEN); | 753 | nb + MESSAGE_HEADER_LEN); |
736 | } | 754 | } |
737 | 755 | ||
@@ -751,46 +769,10 @@ static int if_usb_get_int_status(wlan_private * priv, u8 * ireg) | |||
751 | static int if_usb_read_event_cause(wlan_private * priv) | 769 | static int if_usb_read_event_cause(wlan_private * priv) |
752 | { | 770 | { |
753 | struct usb_card_rec *cardp = priv->card; | 771 | struct usb_card_rec *cardp = priv->card; |
772 | |||
754 | priv->adapter->eventcause = cardp->usb_event_cause; | 773 | priv->adapter->eventcause = cardp->usb_event_cause; |
755 | /* Re-submit rx urb here to avoid event lost issue */ | 774 | /* Re-submit rx urb here to avoid event lost issue */ |
756 | if_usb_submit_rx_urb(priv); | 775 | if_usb_submit_rx_urb(cardp); |
757 | return 0; | ||
758 | } | ||
759 | |||
760 | static int if_usb_unregister_dev(wlan_private * priv) | ||
761 | { | ||
762 | int ret = 0; | ||
763 | |||
764 | /* Need to send a Reset command to device before USB resources freed | ||
765 | * and wlan_remove_card() called, then device can handle FW download | ||
766 | * again. | ||
767 | */ | ||
768 | if (priv) | ||
769 | libertas_reset_device(priv); | ||
770 | |||
771 | return ret; | ||
772 | } | ||
773 | |||
774 | |||
775 | /** | ||
776 | * @brief This function register usb device and initialize parameter | ||
777 | * @param priv pointer to wlan_private | ||
778 | * @return 0 or -1 | ||
779 | */ | ||
780 | static int if_usb_register_dev(wlan_private * priv) | ||
781 | { | ||
782 | struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card; | ||
783 | |||
784 | lbs_deb_enter(LBS_DEB_USB); | ||
785 | |||
786 | cardp->priv = priv; | ||
787 | cardp->eth_dev = priv->dev; | ||
788 | priv->hotplug_device = &(cardp->udev->dev); | ||
789 | |||
790 | lbs_deb_usbd(&cardp->udev->dev, "udev pointer is at %p\n", | ||
791 | cardp->udev); | ||
792 | |||
793 | lbs_deb_leave(LBS_DEB_USB); | ||
794 | return 0; | 776 | return 0; |
795 | } | 777 | } |
796 | 778 | ||
@@ -800,10 +782,9 @@ static int if_usb_register_dev(wlan_private * priv) | |||
800 | * 2:Boot from FW in EEPROM | 782 | * 2:Boot from FW in EEPROM |
801 | * @return 0 | 783 | * @return 0 |
802 | */ | 784 | */ |
803 | static int if_usb_issue_boot_command(wlan_private *priv, int ivalue) | 785 | static int if_usb_issue_boot_command(struct usb_card_rec *cardp, int ivalue) |
804 | { | 786 | { |
805 | struct usb_card_rec *cardp = priv->card; | 787 | struct bootcmdstr sbootcmd; |
806 | struct bootcmdstr sbootcmd; | ||
807 | int i; | 788 | int i; |
808 | 789 | ||
809 | /* Prepare command */ | 790 | /* Prepare command */ |
@@ -814,28 +795,83 @@ static int if_usb_issue_boot_command(wlan_private *priv, int ivalue) | |||
814 | memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr)); | 795 | memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr)); |
815 | 796 | ||
816 | /* Issue command */ | 797 | /* Issue command */ |
817 | usb_tx_block(priv, cardp->bulk_out_buffer, sizeof(struct bootcmdstr)); | 798 | usb_tx_block(cardp, cardp->bulk_out_buffer, sizeof(struct bootcmdstr)); |
818 | 799 | ||
819 | return 0; | 800 | return 0; |
820 | } | 801 | } |
821 | 802 | ||
822 | 803 | ||
823 | static int if_usb_do_prog_firmware(wlan_private * priv) | 804 | /** |
805 | * @brief This function checks the validity of Boot2/FW image. | ||
806 | * | ||
807 | * @param data pointer to image | ||
808 | * len image length | ||
809 | * @return 0 or -1 | ||
810 | */ | ||
811 | static int check_fwfile_format(u8 *data, u32 totlen) | ||
812 | { | ||
813 | u32 bincmd, exit; | ||
814 | u32 blksize, offset, len; | ||
815 | int ret; | ||
816 | |||
817 | ret = 1; | ||
818 | exit = len = 0; | ||
819 | |||
820 | do { | ||
821 | struct fwheader *fwh = (void *)data; | ||
822 | |||
823 | bincmd = le32_to_cpu(fwh->dnldcmd); | ||
824 | blksize = le32_to_cpu(fwh->datalength); | ||
825 | switch (bincmd) { | ||
826 | case FW_HAS_DATA_TO_RECV: | ||
827 | offset = sizeof(struct fwheader) + blksize; | ||
828 | data += offset; | ||
829 | len += offset; | ||
830 | if (len >= totlen) | ||
831 | exit = 1; | ||
832 | break; | ||
833 | case FW_HAS_LAST_BLOCK: | ||
834 | exit = 1; | ||
835 | ret = 0; | ||
836 | break; | ||
837 | default: | ||
838 | exit = 1; | ||
839 | break; | ||
840 | } | ||
841 | } while (!exit); | ||
842 | |||
843 | if (ret) | ||
844 | lbs_pr_err("firmware file format check FAIL\n"); | ||
845 | else | ||
846 | lbs_deb_fw("firmware file format check PASS\n"); | ||
847 | |||
848 | return ret; | ||
849 | } | ||
850 | |||
851 | |||
852 | static int if_usb_prog_firmware(struct usb_card_rec *cardp) | ||
824 | { | 853 | { |
825 | struct usb_card_rec *cardp = priv->card; | ||
826 | int i = 0; | 854 | int i = 0; |
827 | static int reset_count = 10; | 855 | static int reset_count = 10; |
828 | int ret = 0; | 856 | int ret = 0; |
829 | 857 | ||
830 | lbs_deb_enter(LBS_DEB_USB); | 858 | lbs_deb_enter(LBS_DEB_USB); |
831 | 859 | ||
832 | cardp->rinfo.priv = priv; | 860 | if ((ret = request_firmware(&cardp->fw, libertas_fw_name, |
861 | &cardp->udev->dev)) < 0) { | ||
862 | lbs_pr_err("request_firmware() failed with %#x\n", ret); | ||
863 | lbs_pr_err("firmware %s not found\n", libertas_fw_name); | ||
864 | goto done; | ||
865 | } | ||
866 | |||
867 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) | ||
868 | goto release_fw; | ||
833 | 869 | ||
834 | restart: | 870 | restart: |
835 | if (if_usb_submit_rx_urb_fwload(priv) < 0) { | 871 | if (if_usb_submit_rx_urb_fwload(cardp) < 0) { |
836 | lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); | 872 | lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); |
837 | ret = -1; | 873 | ret = -1; |
838 | goto done; | 874 | goto release_fw; |
839 | } | 875 | } |
840 | 876 | ||
841 | cardp->bootcmdresp = 0; | 877 | cardp->bootcmdresp = 0; |
@@ -843,7 +879,7 @@ restart: | |||
843 | int j = 0; | 879 | int j = 0; |
844 | i++; | 880 | i++; |
845 | /* Issue Boot command = 1, Boot from Download-FW */ | 881 | /* Issue Boot command = 1, Boot from Download-FW */ |
846 | if_usb_issue_boot_command(priv, BOOT_CMD_FW_BY_USB); | 882 | if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB); |
847 | /* wait for command response */ | 883 | /* wait for command response */ |
848 | do { | 884 | do { |
849 | j++; | 885 | j++; |
@@ -853,14 +889,13 @@ restart: | |||
853 | 889 | ||
854 | if (cardp->bootcmdresp == 0) { | 890 | if (cardp->bootcmdresp == 0) { |
855 | if (--reset_count >= 0) { | 891 | if (--reset_count >= 0) { |
856 | if_usb_reset_device(priv); | 892 | if_usb_reset_device(cardp); |
857 | goto restart; | 893 | goto restart; |
858 | } | 894 | } |
859 | return -1; | 895 | return -1; |
860 | } | 896 | } |
861 | 897 | ||
862 | i = 0; | 898 | i = 0; |
863 | priv->adapter->fw_ready = 0; | ||
864 | 899 | ||
865 | cardp->totalbytes = 0; | 900 | cardp->totalbytes = 0; |
866 | cardp->fwlastblksent = 0; | 901 | cardp->fwlastblksent = 0; |
@@ -870,113 +905,37 @@ restart: | |||
870 | cardp->totalbytes = 0; | 905 | cardp->totalbytes = 0; |
871 | cardp->fwfinalblk = 0; | 906 | cardp->fwfinalblk = 0; |
872 | 907 | ||
873 | if_prog_firmware(priv); | 908 | if_prog_firmware(cardp); |
874 | 909 | ||
875 | do { | 910 | do { |
876 | lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n"); | 911 | lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n"); |
877 | i++; | 912 | i++; |
878 | msleep_interruptible(100); | 913 | msleep_interruptible(100); |
879 | if (priv->adapter->surpriseremoved || i >= 20) | 914 | if (cardp->surprise_removed || i >= 20) |
880 | break; | 915 | break; |
881 | } while (!cardp->fwdnldover); | 916 | } while (!cardp->fwdnldover); |
882 | 917 | ||
883 | if (!cardp->fwdnldover) { | 918 | if (!cardp->fwdnldover) { |
884 | lbs_pr_info("failed to load fw, resetting device!\n"); | 919 | lbs_pr_info("failed to load fw, resetting device!\n"); |
885 | if (--reset_count >= 0) { | 920 | if (--reset_count >= 0) { |
886 | if_usb_reset_device(priv); | 921 | if_usb_reset_device(cardp); |
887 | goto restart; | 922 | goto restart; |
888 | } | 923 | } |
889 | 924 | ||
890 | lbs_pr_info("FW download failure, time = %d ms\n", i * 100); | 925 | lbs_pr_info("FW download failure, time = %d ms\n", i * 100); |
891 | ret = -1; | 926 | ret = -1; |
892 | goto done; | 927 | goto release_fw; |
893 | } | 928 | } |
894 | 929 | ||
895 | if_usb_submit_rx_urb(priv); | 930 | release_fw: |
896 | 931 | release_firmware(cardp->fw); | |
897 | /* Delay 200 ms to waiting for the FW ready */ | 932 | cardp->fw = NULL; |
898 | msleep_interruptible(200); | ||
899 | |||
900 | priv->adapter->fw_ready = 1; | ||
901 | 933 | ||
902 | done: | 934 | done: |
903 | lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); | 935 | lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); |
904 | return ret; | 936 | return ret; |
905 | } | 937 | } |
906 | 938 | ||
907 | /** | ||
908 | * @brief This function checks the validity of Boot2/FW image. | ||
909 | * | ||
910 | * @param data pointer to image | ||
911 | * len image length | ||
912 | * @return 0 or -1 | ||
913 | */ | ||
914 | static int check_fwfile_format(u8 *data, u32 totlen) | ||
915 | { | ||
916 | u32 bincmd, exit; | ||
917 | u32 blksize, offset, len; | ||
918 | int ret; | ||
919 | |||
920 | ret = 1; | ||
921 | exit = len = 0; | ||
922 | |||
923 | do { | ||
924 | struct fwheader *fwh = (void *)data; | ||
925 | |||
926 | bincmd = le32_to_cpu(fwh->dnldcmd); | ||
927 | blksize = le32_to_cpu(fwh->datalength); | ||
928 | switch (bincmd) { | ||
929 | case FW_HAS_DATA_TO_RECV: | ||
930 | offset = sizeof(struct fwheader) + blksize; | ||
931 | data += offset; | ||
932 | len += offset; | ||
933 | if (len >= totlen) | ||
934 | exit = 1; | ||
935 | break; | ||
936 | case FW_HAS_LAST_BLOCK: | ||
937 | exit = 1; | ||
938 | ret = 0; | ||
939 | break; | ||
940 | default: | ||
941 | exit = 1; | ||
942 | break; | ||
943 | } | ||
944 | } while (!exit); | ||
945 | |||
946 | if (ret) | ||
947 | lbs_pr_err("firmware file format check FAIL\n"); | ||
948 | else | ||
949 | lbs_deb_fw("firmware file format check PASS\n"); | ||
950 | |||
951 | return ret; | ||
952 | } | ||
953 | |||
954 | |||
955 | static int if_usb_prog_firmware(wlan_private *priv) | ||
956 | { | ||
957 | int ret = -1; | ||
958 | |||
959 | lbs_deb_enter(LBS_DEB_FW); | ||
960 | |||
961 | if ((ret = request_firmware(&priv->firmware, libertas_fw_name, | ||
962 | priv->hotplug_device)) < 0) { | ||
963 | lbs_pr_err("request_firmware() failed with %#x\n", ret); | ||
964 | lbs_pr_err("firmware %s not found\n", libertas_fw_name); | ||
965 | goto done; | ||
966 | } | ||
967 | |||
968 | if (check_fwfile_format(priv->firmware->data, priv->firmware->size)) { | ||
969 | release_firmware(priv->firmware); | ||
970 | goto done; | ||
971 | } | ||
972 | |||
973 | ret = if_usb_do_prog_firmware(priv); | ||
974 | |||
975 | release_firmware(priv->firmware); | ||
976 | done: | ||
977 | return ret; | ||
978 | } | ||
979 | |||
980 | 939 | ||
981 | #ifdef CONFIG_PM | 940 | #ifdef CONFIG_PM |
982 | static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) | 941 | static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) |
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index 8b3b4f1e47f6..e07a10ed28b5 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h | |||
@@ -38,7 +38,7 @@ struct bootcmdrespStr | |||
38 | 38 | ||
39 | /* read callback private data */ | 39 | /* read callback private data */ |
40 | struct read_cb_info { | 40 | struct read_cb_info { |
41 | wlan_private *priv; | 41 | struct usb_card_rec *cardp; |
42 | struct sk_buff *skb; | 42 | struct sk_buff *skb; |
43 | }; | 43 | }; |
44 | 44 | ||
@@ -58,6 +58,7 @@ struct usb_card_rec { | |||
58 | int bulk_out_size; | 58 | int bulk_out_size; |
59 | u8 bulk_out_endpointAddr; | 59 | u8 bulk_out_endpointAddr; |
60 | 60 | ||
61 | const struct firmware *fw; | ||
61 | u8 CRC_OK; | 62 | u8 CRC_OK; |
62 | u32 fwseqnum; | 63 | u32 fwseqnum; |
63 | u32 lastseqnum; | 64 | u32 lastseqnum; |
@@ -65,6 +66,7 @@ struct usb_card_rec { | |||
65 | u32 fwlastblksent; | 66 | u32 fwlastblksent; |
66 | u8 fwdnldover; | 67 | u8 fwdnldover; |
67 | u8 fwfinalblk; | 68 | u8 fwfinalblk; |
69 | u8 surprise_removed; | ||
68 | 70 | ||
69 | u32 usb_event_cause; | 71 | u32 usb_event_cause; |
70 | u8 usb_int_cause; | 72 | u8 usb_int_cause; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index ce1c18ee6280..6304bd97d399 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -791,7 +791,6 @@ static int libertas_thread(void *data) | |||
791 | } else | 791 | } else |
792 | spin_unlock_irq(&adapter->driver_lock); | 792 | spin_unlock_irq(&adapter->driver_lock); |
793 | 793 | ||
794 | |||
795 | lbs_deb_thread( | 794 | lbs_deb_thread( |
796 | "main-thread 222 (waking up): intcounter=%d currenttxskb=%p " | 795 | "main-thread 222 (waking up): intcounter=%d currenttxskb=%p " |
797 | "dnld_sent=%d\n", adapter->intcounter, | 796 | "dnld_sent=%d\n", adapter->intcounter, |
@@ -926,7 +925,7 @@ static int libertas_thread(void *data) | |||
926 | * @param priv A pointer to wlan_private structure | 925 | * @param priv A pointer to wlan_private structure |
927 | * @return 0 or -1 | 926 | * @return 0 or -1 |
928 | */ | 927 | */ |
929 | static int wlan_setup_station_hw(wlan_private * priv) | 928 | static int wlan_setup_firmware(wlan_private * priv) |
930 | { | 929 | { |
931 | int ret = -1; | 930 | int ret = -1; |
932 | wlan_adapter *adapter = priv->adapter; | 931 | wlan_adapter *adapter = priv->adapter; |
@@ -934,14 +933,6 @@ static int wlan_setup_station_hw(wlan_private * priv) | |||
934 | 933 | ||
935 | lbs_deb_enter(LBS_DEB_FW); | 934 | lbs_deb_enter(LBS_DEB_FW); |
936 | 935 | ||
937 | ret = priv->hw_prog_firmware(priv); | ||
938 | |||
939 | if (ret) { | ||
940 | lbs_deb_fw("bootloader in invalid state\n"); | ||
941 | ret = -1; | ||
942 | goto done; | ||
943 | } | ||
944 | |||
945 | /* | 936 | /* |
946 | * Read MAC address from HW | 937 | * Read MAC address from HW |
947 | */ | 938 | */ |
@@ -992,8 +983,6 @@ done: | |||
992 | return ret; | 983 | return ret; |
993 | } | 984 | } |
994 | 985 | ||
995 | static void command_timer_fn(unsigned long data); | ||
996 | |||
997 | /** | 986 | /** |
998 | * This function handles the timeout of command sending. | 987 | * This function handles the timeout of command sending. |
999 | * It will re-send the same command again. | 988 | * It will re-send the same command again. |
@@ -1035,155 +1024,99 @@ static void command_timer_fn(unsigned long data) | |||
1035 | return; | 1024 | return; |
1036 | } | 1025 | } |
1037 | 1026 | ||
1038 | static void libertas_free_adapter(wlan_private * priv) | 1027 | static int libertas_init_adapter(wlan_private * priv) |
1039 | { | 1028 | { |
1040 | wlan_adapter *adapter = priv->adapter; | 1029 | wlan_adapter *adapter = priv->adapter; |
1041 | |||
1042 | if (!adapter) { | ||
1043 | lbs_deb_fw("why double free adapter?\n"); | ||
1044 | return; | ||
1045 | } | ||
1046 | |||
1047 | lbs_deb_fw("free command buffer\n"); | ||
1048 | libertas_free_cmd_buffer(priv); | ||
1049 | |||
1050 | lbs_deb_fw("free command_timer\n"); | ||
1051 | del_timer(&adapter->command_timer); | ||
1052 | |||
1053 | lbs_deb_fw("free scan results table\n"); | ||
1054 | kfree(adapter->networks); | ||
1055 | adapter->networks = NULL; | ||
1056 | |||
1057 | /* Free the adapter object itself */ | ||
1058 | lbs_deb_fw("free adapter\n"); | ||
1059 | kfree(adapter); | ||
1060 | priv->adapter = NULL; | ||
1061 | } | ||
1062 | |||
1063 | static int wlan_allocate_adapter(wlan_private * priv) | ||
1064 | { | ||
1065 | size_t bufsize; | 1030 | size_t bufsize; |
1066 | wlan_adapter *adapter = priv->adapter; | 1031 | int i, ret = 0; |
1067 | 1032 | ||
1068 | /* Allocate buffer to store the BSSID list */ | 1033 | /* Allocate buffer to store the BSSID list */ |
1069 | bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); | 1034 | bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); |
1070 | adapter->networks = kzalloc(bufsize, GFP_KERNEL); | 1035 | adapter->networks = kzalloc(bufsize, GFP_KERNEL); |
1071 | if (!adapter->networks) { | 1036 | if (!adapter->networks) { |
1072 | lbs_pr_err("Out of memory allocating beacons\n"); | 1037 | lbs_pr_err("Out of memory allocating beacons\n"); |
1073 | libertas_free_adapter(priv); | 1038 | ret = -1; |
1074 | return -ENOMEM; | 1039 | goto out; |
1075 | } | 1040 | } |
1076 | 1041 | ||
1077 | /* Allocate the command buffers */ | 1042 | /* Initialize scan result lists */ |
1078 | libertas_allocate_cmd_buffer(priv); | 1043 | INIT_LIST_HEAD(&adapter->network_free_list); |
1044 | INIT_LIST_HEAD(&adapter->network_list); | ||
1045 | for (i = 0; i < MAX_NETWORK_COUNT; i++) { | ||
1046 | list_add_tail(&adapter->networks[i].list, | ||
1047 | &adapter->network_free_list); | ||
1048 | } | ||
1079 | 1049 | ||
1080 | memset(&adapter->libertas_ps_confirm_sleep, 0, sizeof(struct PS_CMD_ConfirmSleep)); | ||
1081 | adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum); | 1050 | adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum); |
1082 | adapter->libertas_ps_confirm_sleep.command = | 1051 | adapter->libertas_ps_confirm_sleep.command = |
1083 | cpu_to_le16(CMD_802_11_PS_MODE); | 1052 | cpu_to_le16(CMD_802_11_PS_MODE); |
1084 | adapter->libertas_ps_confirm_sleep.size = | 1053 | adapter->libertas_ps_confirm_sleep.size = |
1085 | cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep)); | 1054 | cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep)); |
1086 | adapter->libertas_ps_confirm_sleep.result = 0; | ||
1087 | adapter->libertas_ps_confirm_sleep.action = | 1055 | adapter->libertas_ps_confirm_sleep.action = |
1088 | cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); | 1056 | cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); |
1089 | 1057 | ||
1090 | return 0; | ||
1091 | } | ||
1092 | |||
1093 | static void wlan_init_adapter(wlan_private * priv) | ||
1094 | { | ||
1095 | wlan_adapter *adapter = priv->adapter; | ||
1096 | int i; | ||
1097 | |||
1098 | adapter->connect_status = LIBERTAS_DISCONNECTED; | ||
1099 | memset(adapter->current_addr, 0xff, ETH_ALEN); | 1058 | memset(adapter->current_addr, 0xff, ETH_ALEN); |
1100 | 1059 | ||
1101 | /* 802.11 specific */ | 1060 | adapter->connect_status = LIBERTAS_DISCONNECTED; |
1102 | adapter->secinfo.wep_enabled = 0; | ||
1103 | for (i = 0; i < sizeof(adapter->wep_keys) / sizeof(adapter->wep_keys[0]); | ||
1104 | i++) | ||
1105 | memset(&adapter->wep_keys[i], 0, sizeof(struct enc_key)); | ||
1106 | adapter->wep_tx_keyidx = 0; | ||
1107 | adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 1061 | adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
1108 | adapter->mode = IW_MODE_INFRA; | 1062 | adapter->mode = IW_MODE_INFRA; |
1109 | |||
1110 | adapter->pending_assoc_req = NULL; | ||
1111 | adapter->in_progress_assoc_req = NULL; | ||
1112 | |||
1113 | /* Initialize scan result lists */ | ||
1114 | INIT_LIST_HEAD(&adapter->network_free_list); | ||
1115 | INIT_LIST_HEAD(&adapter->network_list); | ||
1116 | for (i = 0; i < MAX_NETWORK_COUNT; i++) { | ||
1117 | list_add_tail(&adapter->networks[i].list, | ||
1118 | &adapter->network_free_list); | ||
1119 | } | ||
1120 | |||
1121 | mutex_init(&adapter->lock); | ||
1122 | |||
1123 | memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams)); | ||
1124 | adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; | 1063 | adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; |
1125 | 1064 | adapter->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | |
1126 | /* PnP and power profile */ | ||
1127 | adapter->surpriseremoved = 0; | ||
1128 | |||
1129 | adapter->currentpacketfilter = | ||
1130 | CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | ||
1131 | |||
1132 | adapter->radioon = RADIO_ON; | 1065 | adapter->radioon = RADIO_ON; |
1133 | |||
1134 | adapter->auto_rate = 1; | 1066 | adapter->auto_rate = 1; |
1135 | adapter->cur_rate = 0; | ||
1136 | |||
1137 | // set default capabilities | ||
1138 | adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | 1067 | adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; |
1139 | |||
1140 | adapter->psmode = WLAN802_11POWERMODECAM; | 1068 | adapter->psmode = WLAN802_11POWERMODECAM; |
1141 | |||
1142 | adapter->psstate = PS_STATE_FULL_POWER; | 1069 | adapter->psstate = PS_STATE_FULL_POWER; |
1143 | adapter->needtowakeup = 0; | ||
1144 | 1070 | ||
1145 | adapter->intcounter = 0; | 1071 | mutex_init(&adapter->lock); |
1146 | |||
1147 | adapter->currenttxskb = NULL; | ||
1148 | 1072 | ||
1149 | memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*)); | 1073 | memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*)); |
1150 | adapter->tx_queue_idx = 0; | 1074 | adapter->tx_queue_idx = 0; |
1151 | spin_lock_init(&adapter->txqueue_lock); | 1075 | spin_lock_init(&adapter->txqueue_lock); |
1152 | 1076 | ||
1153 | return; | 1077 | setup_timer(&adapter->command_timer, command_timer_fn, |
1154 | } | 1078 | (unsigned long)priv); |
1155 | 1079 | ||
1156 | static int libertas_init_fw(wlan_private * priv) | 1080 | INIT_LIST_HEAD(&adapter->cmdfreeq); |
1157 | { | 1081 | INIT_LIST_HEAD(&adapter->cmdpendingq); |
1158 | int ret = -1; | ||
1159 | wlan_adapter *adapter = priv->adapter; | ||
1160 | 1082 | ||
1161 | lbs_deb_enter(LBS_DEB_FW); | 1083 | spin_lock_init(&adapter->driver_lock); |
1084 | init_waitqueue_head(&adapter->cmd_pending); | ||
1085 | adapter->nr_cmd_pending = 0; | ||
1162 | 1086 | ||
1163 | /* Allocate adapter structure */ | 1087 | /* Allocate the command buffers */ |
1164 | if ((ret = wlan_allocate_adapter(priv)) != 0) | 1088 | if (libertas_allocate_cmd_buffer(priv)) { |
1165 | goto done; | 1089 | lbs_pr_err("Out of memory allocating command buffers\n"); |
1090 | ret = -1; | ||
1091 | } | ||
1166 | 1092 | ||
1167 | /* init adapter structure */ | 1093 | out: |
1168 | wlan_init_adapter(priv); | 1094 | return ret; |
1095 | } | ||
1169 | 1096 | ||
1170 | /* init timer etc. */ | 1097 | static void libertas_free_adapter(wlan_private * priv) |
1171 | setup_timer(&adapter->command_timer, command_timer_fn, | 1098 | { |
1172 | (unsigned long)priv); | 1099 | wlan_adapter *adapter = priv->adapter; |
1173 | 1100 | ||
1174 | /* download fimrware etc. */ | 1101 | if (!adapter) { |
1175 | if ((ret = wlan_setup_station_hw(priv)) != 0) { | 1102 | lbs_deb_fw("why double free adapter?\n"); |
1176 | del_timer_sync(&adapter->command_timer); | 1103 | return; |
1177 | goto done; | ||
1178 | } | 1104 | } |
1179 | 1105 | ||
1180 | /* init 802.11d */ | 1106 | lbs_deb_fw("free command buffer\n"); |
1181 | libertas_init_11d(priv); | 1107 | libertas_free_cmd_buffer(priv); |
1182 | 1108 | ||
1183 | ret = 0; | 1109 | lbs_deb_fw("free command_timer\n"); |
1184 | done: | 1110 | del_timer(&adapter->command_timer); |
1185 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | 1111 | |
1186 | return ret; | 1112 | lbs_deb_fw("free scan results table\n"); |
1113 | kfree(adapter->networks); | ||
1114 | adapter->networks = NULL; | ||
1115 | |||
1116 | /* Free the adapter object itself */ | ||
1117 | lbs_deb_fw("free adapter\n"); | ||
1118 | kfree(adapter); | ||
1119 | priv->adapter = NULL; | ||
1187 | } | 1120 | } |
1188 | 1121 | ||
1189 | /** | 1122 | /** |
@@ -1203,9 +1136,9 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev) | |||
1203 | /* Allocate an Ethernet device and register it */ | 1136 | /* Allocate an Ethernet device and register it */ |
1204 | if (!(dev = alloc_etherdev(sizeof(wlan_private)))) { | 1137 | if (!(dev = alloc_etherdev(sizeof(wlan_private)))) { |
1205 | lbs_pr_err("init ethX device failed\n"); | 1138 | lbs_pr_err("init ethX device failed\n"); |
1206 | return NULL; | 1139 | goto done; |
1207 | } | 1140 | } |
1208 | priv = dev->priv; | 1141 | dmdev->driver_data = priv = dev->priv; |
1209 | 1142 | ||
1210 | /* allocate buffer for wlan_adapter */ | 1143 | /* allocate buffer for wlan_adapter */ |
1211 | if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) { | 1144 | if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) { |
@@ -1213,10 +1146,16 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev) | |||
1213 | goto err_kzalloc; | 1146 | goto err_kzalloc; |
1214 | } | 1147 | } |
1215 | 1148 | ||
1149 | if (libertas_init_adapter(priv)) { | ||
1150 | lbs_pr_err("failed to initialize adapter structure.\n"); | ||
1151 | goto err_init_adapter; | ||
1152 | } | ||
1153 | |||
1216 | priv->dev = dev; | 1154 | priv->dev = dev; |
1217 | priv->card = card; | 1155 | priv->card = card; |
1218 | priv->mesh_open = 0; | 1156 | priv->mesh_open = 0; |
1219 | priv->infra_open = 0; | 1157 | priv->infra_open = 0; |
1158 | priv->hotplug_device = dmdev; | ||
1220 | 1159 | ||
1221 | SET_MODULE_OWNER(dev); | 1160 | SET_MODULE_OWNER(dev); |
1222 | 1161 | ||
@@ -1239,87 +1178,144 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev) | |||
1239 | 1178 | ||
1240 | SET_NETDEV_DEV(dev, dmdev); | 1179 | SET_NETDEV_DEV(dev, dmdev); |
1241 | 1180 | ||
1242 | INIT_LIST_HEAD(&priv->adapter->cmdfreeq); | ||
1243 | INIT_LIST_HEAD(&priv->adapter->cmdpendingq); | ||
1244 | |||
1245 | spin_lock_init(&priv->adapter->driver_lock); | ||
1246 | init_waitqueue_head(&priv->adapter->cmd_pending); | ||
1247 | priv->adapter->nr_cmd_pending = 0; | ||
1248 | priv->rtap_net_dev = NULL; | 1181 | priv->rtap_net_dev = NULL; |
1249 | if (device_create_file(dmdev, &dev_attr_libertas_rtap)) | 1182 | if (device_create_file(dmdev, &dev_attr_libertas_rtap)) |
1250 | goto err_kzalloc; | 1183 | goto err_init_adapter; |
1184 | |||
1185 | lbs_deb_thread("Starting main thread...\n"); | ||
1186 | init_waitqueue_head(&priv->waitq); | ||
1187 | priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main"); | ||
1188 | if (IS_ERR(priv->main_thread)) { | ||
1189 | lbs_deb_thread("Error creating main thread.\n"); | ||
1190 | goto err_kthread_run; | ||
1191 | } | ||
1192 | |||
1193 | priv->work_thread = create_singlethread_workqueue("libertas_worker"); | ||
1194 | INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker); | ||
1195 | INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker); | ||
1196 | INIT_WORK(&priv->sync_channel, libertas_sync_channel); | ||
1197 | |||
1251 | goto done; | 1198 | goto done; |
1252 | 1199 | ||
1200 | err_kthread_run: | ||
1201 | device_remove_file(dmdev, &dev_attr_libertas_rtap); | ||
1202 | |||
1203 | err_init_adapter: | ||
1204 | libertas_free_adapter(priv); | ||
1205 | |||
1253 | err_kzalloc: | 1206 | err_kzalloc: |
1254 | free_netdev(dev); | 1207 | free_netdev(dev); |
1255 | priv = NULL; | 1208 | priv = NULL; |
1209 | |||
1256 | done: | 1210 | done: |
1257 | lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv); | 1211 | lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv); |
1258 | return priv; | 1212 | return priv; |
1259 | } | 1213 | } |
1260 | EXPORT_SYMBOL_GPL(libertas_add_card); | 1214 | EXPORT_SYMBOL_GPL(libertas_add_card); |
1261 | 1215 | ||
1262 | int libertas_activate_card(wlan_private *priv) | 1216 | |
1217 | int libertas_remove_card(wlan_private *priv) | ||
1263 | { | 1218 | { |
1219 | wlan_adapter *adapter = priv->adapter; | ||
1264 | struct net_device *dev = priv->dev; | 1220 | struct net_device *dev = priv->dev; |
1265 | int ret = -1; | 1221 | union iwreq_data wrqu; |
1266 | 1222 | ||
1267 | lbs_deb_enter(LBS_DEB_MAIN); | 1223 | lbs_deb_enter(LBS_DEB_MAIN); |
1268 | 1224 | ||
1269 | lbs_deb_thread("Starting main thread...\n"); | 1225 | libertas_remove_rtap(priv); |
1270 | init_waitqueue_head(&priv->waitq); | ||
1271 | priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main"); | ||
1272 | if (IS_ERR(priv->main_thread)) { | ||
1273 | lbs_deb_thread("Error creating main thread.\n"); | ||
1274 | goto done; | ||
1275 | } | ||
1276 | 1226 | ||
1277 | priv->work_thread = create_singlethread_workqueue("libertas_worker"); | 1227 | dev = priv->dev; |
1278 | INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker); | 1228 | device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap); |
1279 | INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker); | ||
1280 | 1229 | ||
1281 | INIT_WORK(&priv->sync_channel, libertas_sync_channel); | 1230 | cancel_delayed_work(&priv->scan_work); |
1231 | cancel_delayed_work(&priv->assoc_work); | ||
1232 | destroy_workqueue(priv->work_thread); | ||
1282 | 1233 | ||
1283 | /* | 1234 | if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) { |
1284 | * Register the device. Fillup the private data structure with | 1235 | adapter->psmode = WLAN802_11POWERMODECAM; |
1285 | * relevant information from the card and request for the required | 1236 | libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); |
1286 | * IRQ. | ||
1287 | */ | ||
1288 | if (priv->hw_register_dev(priv) < 0) { | ||
1289 | lbs_pr_err("failed to register WLAN device\n"); | ||
1290 | goto err_registerdev; | ||
1291 | } | 1237 | } |
1292 | 1238 | ||
1293 | /* init FW and HW */ | 1239 | memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); |
1294 | if (libertas_init_fw(priv)) { | 1240 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
1295 | lbs_pr_err("firmware init failed\n"); | 1241 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); |
1296 | goto err_registerdev; | 1242 | |
1297 | } | 1243 | /* Stop the thread servicing the interrupts */ |
1244 | adapter->surpriseremoved = 1; | ||
1245 | kthread_stop(priv->main_thread); | ||
1246 | |||
1247 | libertas_free_adapter(priv); | ||
1248 | |||
1249 | priv->dev = NULL; | ||
1250 | free_netdev(dev); | ||
1251 | |||
1252 | lbs_deb_leave(LBS_DEB_MAIN); | ||
1253 | return 0; | ||
1254 | } | ||
1255 | EXPORT_SYMBOL_GPL(libertas_remove_card); | ||
1256 | |||
1257 | |||
1258 | int libertas_start_card(wlan_private *priv) | ||
1259 | { | ||
1260 | struct net_device *dev = priv->dev; | ||
1261 | int ret = -1; | ||
1262 | |||
1263 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1264 | |||
1265 | /* poke the firmware */ | ||
1266 | ret = wlan_setup_firmware(priv); | ||
1267 | if (ret) | ||
1268 | goto done; | ||
1269 | |||
1270 | /* init 802.11d */ | ||
1271 | libertas_init_11d(priv); | ||
1298 | 1272 | ||
1299 | if (register_netdev(dev)) { | 1273 | if (register_netdev(dev)) { |
1300 | lbs_pr_err("cannot register ethX device\n"); | 1274 | lbs_pr_err("cannot register ethX device\n"); |
1301 | goto err_init_fw; | 1275 | goto done; |
1302 | } | 1276 | } |
1303 | 1277 | ||
1304 | lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); | ||
1305 | |||
1306 | libertas_debugfs_init_one(priv, dev); | 1278 | libertas_debugfs_init_one(priv, dev); |
1307 | 1279 | ||
1280 | lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); | ||
1281 | |||
1308 | ret = 0; | 1282 | ret = 0; |
1309 | goto done; | ||
1310 | 1283 | ||
1311 | err_init_fw: | ||
1312 | priv->hw_unregister_dev(priv); | ||
1313 | err_registerdev: | ||
1314 | destroy_workqueue(priv->work_thread); | ||
1315 | /* Stop the thread servicing the interrupts */ | ||
1316 | wake_up_interruptible(&priv->waitq); | ||
1317 | kthread_stop(priv->main_thread); | ||
1318 | done: | 1284 | done: |
1319 | lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); | 1285 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); |
1320 | return ret; | 1286 | return ret; |
1321 | } | 1287 | } |
1322 | EXPORT_SYMBOL_GPL(libertas_activate_card); | 1288 | EXPORT_SYMBOL_GPL(libertas_start_card); |
1289 | |||
1290 | |||
1291 | int libertas_stop_card(wlan_private *priv) | ||
1292 | { | ||
1293 | struct net_device *dev = priv->dev; | ||
1294 | int ret = -1; | ||
1295 | struct cmd_ctrl_node *cmdnode; | ||
1296 | unsigned long flags; | ||
1297 | |||
1298 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1299 | |||
1300 | netif_stop_queue(priv->dev); | ||
1301 | netif_carrier_off(priv->dev); | ||
1302 | |||
1303 | libertas_debugfs_remove_one(priv); | ||
1304 | |||
1305 | /* Flush pending command nodes */ | ||
1306 | spin_lock_irqsave(&priv->adapter->driver_lock, flags); | ||
1307 | list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) { | ||
1308 | cmdnode->cmdwaitqwoken = 1; | ||
1309 | wake_up_interruptible(&cmdnode->cmdwait_q); | ||
1310 | } | ||
1311 | spin_unlock_irqrestore(&priv->adapter->driver_lock, flags); | ||
1312 | |||
1313 | unregister_netdev(dev); | ||
1314 | |||
1315 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
1316 | return ret; | ||
1317 | } | ||
1318 | EXPORT_SYMBOL_GPL(libertas_stop_card); | ||
1323 | 1319 | ||
1324 | 1320 | ||
1325 | /** | 1321 | /** |
@@ -1389,89 +1385,12 @@ done: | |||
1389 | } | 1385 | } |
1390 | EXPORT_SYMBOL_GPL(libertas_add_mesh); | 1386 | EXPORT_SYMBOL_GPL(libertas_add_mesh); |
1391 | 1387 | ||
1392 | static void wake_pending_cmdnodes(wlan_private *priv) | ||
1393 | { | ||
1394 | struct cmd_ctrl_node *cmdnode; | ||
1395 | unsigned long flags; | ||
1396 | |||
1397 | lbs_deb_enter(LBS_DEB_HOST); | ||
1398 | |||
1399 | spin_lock_irqsave(&priv->adapter->driver_lock, flags); | ||
1400 | list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) { | ||
1401 | cmdnode->cmdwaitqwoken = 1; | ||
1402 | wake_up_interruptible(&cmdnode->cmdwait_q); | ||
1403 | } | ||
1404 | spin_unlock_irqrestore(&priv->adapter->driver_lock, flags); | ||
1405 | } | ||
1406 | |||
1407 | |||
1408 | int libertas_remove_card(wlan_private *priv) | ||
1409 | { | ||
1410 | wlan_adapter *adapter; | ||
1411 | struct net_device *dev; | ||
1412 | union iwreq_data wrqu; | ||
1413 | |||
1414 | lbs_deb_enter(LBS_DEB_NET); | ||
1415 | |||
1416 | libertas_remove_rtap(priv); | ||
1417 | if (!priv) | ||
1418 | goto out; | ||
1419 | |||
1420 | adapter = priv->adapter; | ||
1421 | |||
1422 | if (!adapter) | ||
1423 | goto out; | ||
1424 | |||
1425 | dev = priv->dev; | ||
1426 | device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap); | ||
1427 | |||
1428 | netif_stop_queue(priv->dev); | ||
1429 | netif_carrier_off(priv->dev); | ||
1430 | |||
1431 | wake_pending_cmdnodes(priv); | ||
1432 | |||
1433 | unregister_netdev(dev); | ||
1434 | |||
1435 | cancel_delayed_work(&priv->scan_work); | ||
1436 | cancel_delayed_work(&priv->assoc_work); | ||
1437 | destroy_workqueue(priv->work_thread); | ||
1438 | |||
1439 | if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) { | ||
1440 | adapter->psmode = WLAN802_11POWERMODECAM; | ||
1441 | libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); | ||
1442 | } | ||
1443 | |||
1444 | memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); | ||
1445 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1446 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
1447 | |||
1448 | adapter->surpriseremoved = 1; | ||
1449 | |||
1450 | /* Stop the thread servicing the interrupts */ | ||
1451 | kthread_stop(priv->main_thread); | ||
1452 | |||
1453 | libertas_debugfs_remove_one(priv); | ||
1454 | |||
1455 | lbs_deb_net("free adapter\n"); | ||
1456 | libertas_free_adapter(priv); | ||
1457 | |||
1458 | lbs_deb_net("unregister finish\n"); | ||
1459 | |||
1460 | priv->dev = NULL; | ||
1461 | free_netdev(dev); | ||
1462 | |||
1463 | out: | ||
1464 | lbs_deb_leave(LBS_DEB_NET); | ||
1465 | return 0; | ||
1466 | } | ||
1467 | EXPORT_SYMBOL_GPL(libertas_remove_card); | ||
1468 | |||
1469 | 1388 | ||
1470 | void libertas_remove_mesh(wlan_private *priv) | 1389 | void libertas_remove_mesh(wlan_private *priv) |
1471 | { | 1390 | { |
1472 | struct net_device *mesh_dev; | 1391 | struct net_device *mesh_dev; |
1473 | 1392 | ||
1474 | lbs_deb_enter(LBS_DEB_NET); | 1393 | lbs_deb_enter(LBS_DEB_MAIN); |
1475 | 1394 | ||
1476 | if (!priv) | 1395 | if (!priv) |
1477 | goto out; | 1396 | goto out; |
@@ -1488,7 +1407,7 @@ void libertas_remove_mesh(wlan_private *priv) | |||
1488 | free_netdev(mesh_dev); | 1407 | free_netdev(mesh_dev); |
1489 | 1408 | ||
1490 | out: | 1409 | out: |
1491 | lbs_deb_leave(LBS_DEB_NET); | 1410 | lbs_deb_leave(LBS_DEB_MAIN); |
1492 | } | 1411 | } |
1493 | EXPORT_SYMBOL_GPL(libertas_remove_mesh); | 1412 | EXPORT_SYMBOL_GPL(libertas_remove_mesh); |
1494 | 1413 | ||