Search Linux Wireless

Please pull 'for-linville' branch of libertas-2.6

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I pushed a few more patches on top of the previous bits you pulled.  I
haven't rebased that branch or anything since you pulled last so it
should be clean.

Thanks,
Dan

The following changes since commit 2d97ef17437d4a71eabf14adfc50e915a1c8120e:
  Dan Williams (1):
        libertas: bump driver version

are available in the git repository at:

  git://git.infradead.org/libertas-2.6 for-linville

Brajesh Dave (1):
      libertas: advertise 11g ad-hoc rates

Dan Williams (4):
      libertas: fix inadvertant removal of bits from commit 831441862956fffa17b9801db37e6ea1650b0f69
      libertas: reorganize and simplify init sequence
      libertas: don't stomp on interface-specific private data
      libertas: send reset command directly instead of calling libertas_reset_device

Marek Vašut (1):
      libertas: region code values specified as 8bit

Pierre Ossman (1):
      libertas: properly end commands on hardware failure

 drivers/net/wireless/libertas/cmd.c     |    2 +
 drivers/net/wireless/libertas/cmdresp.c |    6 +-
 drivers/net/wireless/libertas/decl.h    |    3 +-
 drivers/net/wireless/libertas/dev.h     |    4 -
 drivers/net/wireless/libertas/if_cs.c   |   54 +----
 drivers/net/wireless/libertas/if_usb.c  |  371 +++++++++++++----------------
 drivers/net/wireless/libertas/if_usb.h  |    4 +-
 drivers/net/wireless/libertas/join.c    |    4 +-
 drivers/net/wireless/libertas/main.c    |  408 +++++++++++++------------------
 9 files changed, 349 insertions(+), 507 deletions(-)


diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 98092b9..33dbed0 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -1009,7 +1009,9 @@ static int DownloadcommandToStation(wlan_private * priv,
 	if (ret != 0) {
 		lbs_deb_host("DNLD_CMD: hw_host_to_card failed\n");
 		spin_lock_irqsave(&adapter->driver_lock, flags);
+		adapter->cur_cmd_retcode = ret;
 		__libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
+		adapter->nr_cmd_pending--;
 		adapter->cur_cmd = NULL;
 		spin_unlock_irqrestore(&adapter->driver_lock, flags);
 		goto done;
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 4c36e63..d64ad87 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -174,7 +174,11 @@ static int wlan_ret_get_hw_spec(wlan_private * priv,
 	lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
 	       hwspec->hwifversion, hwspec->version);
 
-	adapter->regioncode = le16_to_cpu(hwspec->regioncode);
+	/* Clamp region code to 8-bit since FW spec indicates that it should
+	 * only ever be 8-bit, even though the field size is 16-bit.  Some firmware
+	 * returns non-zero high 8 bits here.
+	 */
+	adapter->regioncode = le16_to_cpu(hwspec->regioncode) & 0xFF;
 
 	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
 		/* use the region code to search for the index */
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 095edf6..87fea9d 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);
 struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band,
 						             int *cfp_no);
 wlan_private *libertas_add_card(void *card, struct device *dmdev);
-int libertas_activate_card(wlan_private *priv);
 int libertas_remove_card(wlan_private *priv);
+int libertas_start_card(wlan_private *priv);
+int libertas_stop_card(wlan_private *priv);
 int libertas_add_mesh(wlan_private *priv, struct device *dev);
 void libertas_remove_mesh(wlan_private *priv);
 int libertas_reset_device(wlan_private *priv);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index a3c94d7..1fb807a 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -143,7 +143,6 @@ struct _wlan_private {
 	   all other bits reserved 0 */
 	u8 dnld_sent;
 
-	const struct firmware *firmware;
 	struct device *hotplug_device;
 
 	/** thread to service interrupts */
@@ -156,9 +155,6 @@ struct _wlan_private {
 	struct work_struct sync_channel;
 
 	/** Hardware access */
-	int (*hw_register_dev) (wlan_private * priv);
-	int (*hw_unregister_dev) (wlan_private *);
-	int (*hw_prog_firmware) (wlan_private *);
 	int (*hw_host_to_card) (wlan_private * priv, u8 type, u8 * payload, u16 nb);
 	int (*hw_get_int_status) (wlan_private * priv, u8 *);
 	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 888f023..4dffc5c 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -608,51 +608,6 @@ done:
 /* Callback functions for libertas.ko                               */
 /********************************************************************/
 
-static int if_cs_register_dev(wlan_private *priv)
-{
-	struct if_cs_card *card = (struct if_cs_card *)priv->card;
-
-	lbs_deb_enter(LBS_DEB_CS);
-
-	card->priv = priv;
-
-	return 0;
-}
-
-
-static int if_cs_unregister_dev(wlan_private *priv)
-{
-	lbs_deb_enter(LBS_DEB_CS);
-
-	/*
-	 * Nothing special here. Because the device's power gets turned off
-	 * anyway, there's no need to send a RESET command like in if_usb.c
-	 */
-
-	return 0;
-}
-
-
-/*
- * This callback is a dummy. The reason is that the USB code needs
- * to have various things set up in order to be able to download the
- * firmware. That's not needed in our case.
- *
- * On the contrary, if libertas_add_card() has been called and we're
- * then later called via libertas_activate_card(), but without a valid
- * firmware, then it's quite tedious to tear down the half-installed
- * card. Therefore, we download the firmware before calling adding/
- * activating the card in the first place. If that doesn't work, we
- * won't call into libertas.ko at all.
- */
-
-static int if_cs_prog_firmware(wlan_private *priv)
-{
-	priv->adapter->fw_ready = 1;
-	return 0;
-}
-
-
 /* Send commands or data packets to the card */
 static int if_cs_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb)
 {
@@ -902,14 +857,14 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	}
 
 	/* Store pointers to our call-back functions */
+	card->priv = priv;
 	priv->card = card;
-	priv->hw_register_dev     = if_cs_register_dev;
-	priv->hw_unregister_dev   = if_cs_unregister_dev;
-	priv->hw_prog_firmware    = if_cs_prog_firmware;
 	priv->hw_host_to_card     = if_cs_host_to_card;
 	priv->hw_get_int_status   = if_cs_get_int_status;
 	priv->hw_read_event_cause = if_cs_read_event_cause;
 
+	priv->adapter->fw_ready = 1;
+
 	/* Now actually get the IRQ */
 	ret = request_irq(p_dev->irq.AssignedIRQ, if_cs_interrupt,
 		IRQF_SHARED, DRV_NAME, card);
@@ -919,7 +874,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	}
 
 	/* And finally bring the card up */
-	if (libertas_activate_card(priv) != 0) {
+	if (libertas_start_card(priv) != 0) {
 		lbs_pr_err("could not activate card\n");
 		goto out3;
 	}
@@ -951,6 +906,7 @@ static void if_cs_detach(struct pcmcia_device *p_dev)
 
 	lbs_deb_enter(LBS_DEB_CS);
 
+	libertas_stop_card(card->priv);
 	libertas_remove_card(card->priv);
 	if_cs_release(p_dev);
 	kfree(card);
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 364eae3..8a3c70e 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);
 
 static void if_usb_receive(struct urb *urb);
 static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_register_dev(wlan_private * priv);
-static int if_usb_unregister_dev(wlan_private *);
-static int if_usb_prog_firmware(wlan_private *);
+static int if_usb_prog_firmware(struct usb_card_rec *cardp);
 static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
 static int if_usb_get_int_status(wlan_private * priv, u8 *);
 static int if_usb_read_event_cause(wlan_private *);
-static int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb);
+static int usb_tx_block(struct usb_card_rec *cardp, u8 *payload, u16 nb);
 static void if_usb_free(struct usb_card_rec *cardp);
+static int if_usb_submit_rx_urb(struct usb_card_rec *cardp);
+static int if_usb_reset_device(struct usb_card_rec *cardp);
 
 /**
  *  @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);
  */
 static void if_usb_write_bulk_callback(struct urb *urb)
 {
-	wlan_private *priv = (wlan_private *) (urb->context);
-	wlan_adapter *adapter = priv->adapter;
-	struct net_device *dev = priv->dev;
+	struct usb_card_rec *cardp = (struct usb_card_rec *) urb->context;
 
 	/* handle the transmission complete validations */
 
-	if (urb->status != 0) {
-		/* print the failure status number for debug */
-		lbs_pr_info("URB in failure status: %d\n", urb->status);
-	} else {
+	if (urb->status == 0) {
+		wlan_private *priv = cardp->priv;
+
 		/*
 		lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n");
 		lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n",
 		       urb->actual_length);
 		*/
-		priv->dnld_sent = DNLD_RES_RECEIVED;
-		/* Wake main thread if commands are pending */
-		if (!adapter->cur_cmd)
-			wake_up_interruptible(&priv->waitq);
-		if ((adapter->connect_status == LIBERTAS_CONNECTED)) {
-			netif_wake_queue(dev);
-			netif_wake_queue(priv->mesh_dev);
+
+		/* Used for both firmware TX and regular TX.  priv isn't
+		 * valid at firmware load time.
+		 */
+		if (priv) {
+			wlan_adapter *adapter = priv->adapter;
+			struct net_device *dev = priv->dev;
+
+			priv->dnld_sent = DNLD_RES_RECEIVED;
+
+			/* Wake main thread if commands are pending */
+			if (!adapter->cur_cmd)
+				wake_up_interruptible(&priv->waitq);
+
+			if ((adapter->connect_status == LIBERTAS_CONNECTED)) {
+				netif_wake_queue(dev);
+				netif_wake_queue(priv->mesh_dev);
+			}
 		}
+	} else {
+		/* print the failure status number for debug */
+		lbs_pr_info("URB in failure status: %d\n", urb->status);
 	}
 
 	return;
@@ -205,24 +216,35 @@ static int if_usb_probe(struct usb_interface *intf,
 		}
 	}
 
+	/* Upload firmware */
+	cardp->rinfo.cardp = cardp;
+	if (if_usb_prog_firmware(cardp)) {
+		lbs_deb_usbd(&udev->dev, "FW upload failed");
+		goto err_prog_firmware;
+	}
+
 	if (!(priv = libertas_add_card(cardp, &udev->dev)))
-		goto dealloc;
+		goto err_prog_firmware;
 
-	udev->dev.driver_data = priv;
+	cardp->priv = priv;
 
 	if (libertas_add_mesh(priv, &udev->dev))
 		goto err_add_mesh;
 
-	priv->hw_register_dev = if_usb_register_dev;
-	priv->hw_unregister_dev = if_usb_unregister_dev;
-	priv->hw_prog_firmware = if_usb_prog_firmware;
+	cardp->eth_dev = priv->dev;
+
 	priv->hw_host_to_card = if_usb_host_to_card;
 	priv->hw_get_int_status = if_usb_get_int_status;
 	priv->hw_read_event_cause = if_usb_read_event_cause;
 	priv->boot2_version = udev->descriptor.bcdDevice;
 
-	if (libertas_activate_card(priv))
-		goto err_activate_card;
+	/* Delay 200 ms to waiting for the FW ready */
+	if_usb_submit_rx_urb(cardp);
+	msleep_interruptible(200);
+	priv->adapter->fw_ready = 1;
+
+	if (libertas_start_card(priv))
+		goto err_start_card;
 
 	list_add_tail(&cardp->list, &usb_devices);
 
@@ -231,11 +253,12 @@ static int if_usb_probe(struct usb_interface *intf,
 
 	return 0;
 
-err_activate_card:
+err_start_card:
 	libertas_remove_mesh(priv);
 err_add_mesh:
-	free_netdev(priv->dev);
-	kfree(priv->adapter);
+	libertas_remove_card(priv);
+err_prog_firmware:
+	if_usb_reset_device(cardp);
 dealloc:
 	if_usb_free(cardp);
 
@@ -252,21 +275,22 @@ static void if_usb_disconnect(struct usb_interface *intf)
 {
 	struct usb_card_rec *cardp = usb_get_intfdata(intf);
 	wlan_private *priv = (wlan_private *) cardp->priv;
-	wlan_adapter *adapter = NULL;
 
-	adapter = priv->adapter;
+	lbs_deb_enter(LBS_DEB_MAIN);
 
-	/*
-	 * Update Surprise removed to TRUE
-	 */
-	adapter->surpriseremoved = 1;
+	/* Update Surprise removed to TRUE */
+	cardp->surprise_removed = 1;
 
 	list_del(&cardp->list);
 
-	/* card is removed and we can call wlan_remove_card */
-	lbs_deb_usbd(&cardp->udev->dev, "call remove card\n");
-	libertas_remove_mesh(priv);
-	libertas_remove_card(priv);
+	if (priv) {
+		wlan_adapter *adapter = priv->adapter;
+
+		adapter->surpriseremoved = 1;
+		libertas_stop_card(priv);
+		libertas_remove_mesh(priv);
+		libertas_remove_card(priv);
+	}
 
 	/* Unlink and free urb */
 	if_usb_free(cardp);
@@ -274,7 +298,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
 	usb_set_intfdata(intf, NULL);
 	usb_put_dev(interface_to_usbdev(intf));
 
-	return;
+	lbs_deb_leave(LBS_DEB_MAIN);
 }
 
 /**
@@ -282,12 +306,11 @@ static void if_usb_disconnect(struct usb_interface *intf)
  *  @param priv		pointer to wlan_private
  *  @return 	   	0
  */
-static int if_prog_firmware(wlan_private * priv)
+static int if_prog_firmware(struct usb_card_rec *cardp)
 {
-	struct usb_card_rec *cardp = priv->card;
 	struct FWData *fwdata;
 	struct fwheader *fwheader;
-	u8 *firmware = priv->firmware->data;
+	u8 *firmware = cardp->fw->data;
 
 	fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);
 
@@ -335,7 +358,7 @@ static int if_prog_firmware(wlan_private * priv)
 			    cardp->totalbytes);
 		*/
 		memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
-		usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
+		usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
 
 	} else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
 		/*
@@ -345,7 +368,7 @@ static int if_prog_firmware(wlan_private * priv)
 			    "Donwloading FW JUMP BLOCK\n");
 		*/
 		memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
-		usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
+		usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
 		cardp->fwfinalblk = 1;
 	}
 
@@ -360,10 +383,10 @@ static int if_prog_firmware(wlan_private * priv)
 	return 0;
 }
 
-static int if_usb_reset_device(wlan_private *priv)
+static int if_usb_reset_device(struct usb_card_rec *cardp)
 {
 	int ret;
-	struct usb_card_rec *cardp = priv->card;
+	wlan_private * priv = cardp->priv;
 
 	lbs_deb_enter(LBS_DEB_USB);
 
@@ -371,7 +394,7 @@ static int if_usb_reset_device(wlan_private *priv)
 	 * command to the firmware.
 	 */
 	ret = usb_reset_device(cardp->udev);
-	if (!ret) {
+	if (!ret && priv) {
 		msleep(10);
 		ret = libertas_reset_device(priv);
 		msleep(10);
@@ -389,14 +412,12 @@ static int if_usb_reset_device(wlan_private *priv)
  *  @param nb		data length
  *  @return 	   	0 or -1
  */
-static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
+static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb)
 {
-	/* pointer to card structure */
-	struct usb_card_rec *cardp = priv->card;
 	int ret = -1;
 
 	/* check if device is removed */
-	if (priv->adapter->surpriseremoved) {
+	if (cardp->surprise_removed) {
 		lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
 		goto tx_ret;
 	}
@@ -404,7 +425,7 @@ static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
 	usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
 			  usb_sndbulkpipe(cardp->udev,
 					  cardp->bulk_out_endpointAddr),
-			  payload, nb, if_usb_write_bulk_callback, priv);
+			  payload, nb, if_usb_write_bulk_callback, cardp);
 
 	cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
 
@@ -421,11 +442,9 @@ tx_ret:
 	return ret;
 }
 
-static int __if_usb_submit_rx_urb(wlan_private * priv,
-				  void (*callbackfn)
-				  (struct urb *urb))
+static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp,
+				  void (*callbackfn)(struct urb *urb))
 {
-	struct usb_card_rec *cardp = priv->card;
 	struct sk_buff *skb;
 	struct read_cb_info *rinfo = &cardp->rinfo;
 	int ret = -1;
@@ -461,22 +480,21 @@ rx_ret:
 	return ret;
 }
 
-static inline int if_usb_submit_rx_urb_fwload(wlan_private * priv)
+static int if_usb_submit_rx_urb_fwload(struct usb_card_rec *cardp)
 {
-	return __if_usb_submit_rx_urb(priv, &if_usb_receive_fwload);
+	return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
 }
 
-static inline int if_usb_submit_rx_urb(wlan_private * priv)
+static int if_usb_submit_rx_urb(struct usb_card_rec *cardp)
 {
-	return __if_usb_submit_rx_urb(priv, &if_usb_receive);
+	return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
 }
 
 static void if_usb_receive_fwload(struct urb *urb)
 {
 	struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
-	wlan_private *priv = rinfo->priv;
 	struct sk_buff *skb = rinfo->skb;
-	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)rinfo->cardp;
 	struct fwsyncheader *syncfwheader;
 	struct bootcmdrespStr bootcmdresp;
 
@@ -492,7 +510,7 @@ static void if_usb_receive_fwload(struct urb *urb)
 			sizeof(bootcmdresp));
 		if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
 			kfree_skb(skb);
-			if_usb_submit_rx_urb_fwload(priv);
+			if_usb_submit_rx_urb_fwload(cardp);
 			cardp->bootcmdresp = 1;
 			lbs_deb_usbd(&cardp->udev->dev,
 				    "Received valid boot command response\n");
@@ -516,7 +534,7 @@ static void if_usb_receive_fwload(struct urb *urb)
 				    "Received valid boot command response\n");
 		}
 		kfree_skb(skb);
-		if_usb_submit_rx_urb_fwload(priv);
+		if_usb_submit_rx_urb_fwload(cardp);
 		return;
 	}
 
@@ -552,9 +570,9 @@ static void if_usb_receive_fwload(struct urb *urb)
 		goto exit;
 	}
 
-	if_prog_firmware(priv);
+	if_prog_firmware(cardp);
 
-	if_usb_submit_rx_urb_fwload(priv);
+	if_usb_submit_rx_urb_fwload(cardp);
 exit:
 	kfree(syncfwheader);
 
@@ -633,9 +651,9 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
 static void if_usb_receive(struct urb *urb)
 {
 	struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
-	wlan_private *priv = rinfo->priv;
 	struct sk_buff *skb = rinfo->skb;
-	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
+	struct usb_card_rec *cardp = (struct usb_card_rec *) rinfo->cardp;
+	wlan_private * priv = cardp->priv;
 
 	int recvlength = urb->actual_length;
 	u8 *recvbuff = NULL;
@@ -696,7 +714,7 @@ static void if_usb_receive(struct urb *urb)
 	}
 
 setup_for_next:
-	if_usb_submit_rx_urb(priv);
+	if_usb_submit_rx_urb(cardp);
 rx_exit:
 	lbs_deb_leave(LBS_DEB_USB);
 }
@@ -731,7 +749,7 @@ static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 n
 
 	memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb);
 
-	return usb_tx_block(priv, cardp->bulk_out_buffer,
+	return usb_tx_block(cardp, cardp->bulk_out_buffer,
 	                    nb + MESSAGE_HEADER_LEN);
 }
 
@@ -751,46 +769,10 @@ static int if_usb_get_int_status(wlan_private * priv, u8 * ireg)
 static int if_usb_read_event_cause(wlan_private * priv)
 {
 	struct usb_card_rec *cardp = priv->card;
+
 	priv->adapter->eventcause = cardp->usb_event_cause;
 	/* Re-submit rx urb here to avoid event lost issue */
-	if_usb_submit_rx_urb(priv);
-	return 0;
-}
-
-static int if_usb_unregister_dev(wlan_private * priv)
-{
-	int ret = 0;
-
-	/* Need to send a Reset command to device before USB resources freed
-	 * and wlan_remove_card() called, then device can handle FW download
-	 * again.
-	 */
-	if (priv)
-		libertas_reset_device(priv);
-
-	return ret;
-}
-
-
-/**
- *  @brief  This function register usb device and initialize parameter
- *  @param		priv pointer to wlan_private
- *  @return		0 or -1
- */
-static int if_usb_register_dev(wlan_private * priv)
-{
-	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
-
-	lbs_deb_enter(LBS_DEB_USB);
-
-	cardp->priv = priv;
-	cardp->eth_dev = priv->dev;
-	priv->hotplug_device = &(cardp->udev->dev);
-
-	lbs_deb_usbd(&cardp->udev->dev, "udev pointer is at %p\n",
-		    cardp->udev);
-
-	lbs_deb_leave(LBS_DEB_USB);
+	if_usb_submit_rx_urb(cardp);
 	return 0;
 }
 
@@ -800,10 +782,9 @@ static int if_usb_register_dev(wlan_private * priv)
  *                  2:Boot from FW in EEPROM
  *  @return 	   	0
  */
-static int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
+static int if_usb_issue_boot_command(struct usb_card_rec *cardp, int ivalue)
 {
-	struct usb_card_rec	*cardp = priv->card;
-	struct bootcmdstr	sbootcmd;
+	struct bootcmdstr sbootcmd;
 	int i;
 
 	/* Prepare command */
@@ -814,28 +795,83 @@ static int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
 	memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr));
 
 	/* Issue command */
-	usb_tx_block(priv, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
+	usb_tx_block(cardp, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
 
 	return 0;
 }
 
 
-static int if_usb_do_prog_firmware(wlan_private * priv)
+/**
+ *  @brief This function checks the validity of Boot2/FW image.
+ *
+ *  @param data              pointer to image
+ *         len               image length
+ *  @return     0 or -1
+ */
+static int check_fwfile_format(u8 *data, u32 totlen)
+{
+	u32 bincmd, exit;
+	u32 blksize, offset, len;
+	int ret;
+
+	ret = 1;
+	exit = len = 0;
+
+	do {
+		struct fwheader *fwh = (void *)data;
+
+		bincmd = le32_to_cpu(fwh->dnldcmd);
+		blksize = le32_to_cpu(fwh->datalength);
+		switch (bincmd) {
+		case FW_HAS_DATA_TO_RECV:
+			offset = sizeof(struct fwheader) + blksize;
+			data += offset;
+			len += offset;
+			if (len >= totlen)
+				exit = 1;
+			break;
+		case FW_HAS_LAST_BLOCK:
+			exit = 1;
+			ret = 0;
+			break;
+		default:
+			exit = 1;
+			break;
+		}
+	} while (!exit);
+
+	if (ret)
+		lbs_pr_err("firmware file format check FAIL\n");
+	else
+		lbs_deb_fw("firmware file format check PASS\n");
+
+	return ret;
+}
+
+
+static int if_usb_prog_firmware(struct usb_card_rec *cardp)
 {
-	struct usb_card_rec *cardp = priv->card;
 	int i = 0;
 	static int reset_count = 10;
 	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_USB);
 
-	cardp->rinfo.priv = priv;
+	if ((ret = request_firmware(&cardp->fw, libertas_fw_name,
+				    &cardp->udev->dev)) < 0) {
+		lbs_pr_err("request_firmware() failed with %#x\n", ret);
+		lbs_pr_err("firmware %s not found\n", libertas_fw_name);
+		goto done;
+	}
+
+	if (check_fwfile_format(cardp->fw->data, cardp->fw->size))
+		goto release_fw;
 
 restart:
-	if (if_usb_submit_rx_urb_fwload(priv) < 0) {
+	if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
 		lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
 		ret = -1;
-		goto done;
+		goto release_fw;
 	}
 
 	cardp->bootcmdresp = 0;
@@ -843,7 +879,7 @@ restart:
 		int j = 0;
 		i++;
 		/* Issue Boot command = 1, Boot from Download-FW */
-		if_usb_issue_boot_command(priv, BOOT_CMD_FW_BY_USB);
+		if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
 		/* wait for command response */
 		do {
 			j++;
@@ -853,14 +889,13 @@ restart:
 
 	if (cardp->bootcmdresp == 0) {
 		if (--reset_count >= 0) {
-			if_usb_reset_device(priv);
+			if_usb_reset_device(cardp);
 			goto restart;
 		}
 		return -1;
 	}
 
 	i = 0;
-	priv->adapter->fw_ready = 0;
 
 	cardp->totalbytes = 0;
 	cardp->fwlastblksent = 0;
@@ -870,113 +905,37 @@ restart:
 	cardp->totalbytes = 0;
 	cardp->fwfinalblk = 0;
 
-	if_prog_firmware(priv);
+	if_prog_firmware(cardp);
 
 	do {
 		lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n");
 		i++;
 		msleep_interruptible(100);
-		if (priv->adapter->surpriseremoved || i >= 20)
+		if (cardp->surprise_removed || i >= 20)
 			break;
 	} while (!cardp->fwdnldover);
 
 	if (!cardp->fwdnldover) {
 		lbs_pr_info("failed to load fw, resetting device!\n");
 		if (--reset_count >= 0) {
-			if_usb_reset_device(priv);
+			if_usb_reset_device(cardp);
 			goto restart;
 		}
 
 		lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
 		ret = -1;
-		goto done;
+		goto release_fw;
 	}
 
-	if_usb_submit_rx_urb(priv);
-
-	/* Delay 200 ms to waiting for the FW ready */
-	msleep_interruptible(200);
-
-	priv->adapter->fw_ready = 1;
+release_fw:
+	release_firmware(cardp->fw);
+	cardp->fw = NULL;
 
 done:
 	lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
 	return ret;
 }
 
-/**
- *  @brief This function checks the validity of Boot2/FW image.
- *
- *  @param data              pointer to image
- *         len               image length
- *  @return     0 or -1
- */
-static int check_fwfile_format(u8 *data, u32 totlen)
-{
-	u32 bincmd, exit;
-	u32 blksize, offset, len;
-	int ret;
-
-	ret = 1;
-	exit = len = 0;
-
-	do {
-		struct fwheader *fwh = (void *)data;
-
-		bincmd = le32_to_cpu(fwh->dnldcmd);
-		blksize = le32_to_cpu(fwh->datalength);
-		switch (bincmd) {
-		case FW_HAS_DATA_TO_RECV:
-			offset = sizeof(struct fwheader) + blksize;
-			data += offset;
-			len += offset;
-			if (len >= totlen)
-				exit = 1;
-			break;
-		case FW_HAS_LAST_BLOCK:
-			exit = 1;
-			ret = 0;
-			break;
-		default:
-			exit = 1;
-			break;
-		}
-	} while (!exit);
-
-	if (ret)
-		lbs_pr_err("firmware file format check FAIL\n");
-	else
-		lbs_deb_fw("firmware file format check PASS\n");
-
-	return ret;
-}
-
-
-static int if_usb_prog_firmware(wlan_private *priv)
-{
-	int ret = -1;
-
-	lbs_deb_enter(LBS_DEB_FW);
-
-	if ((ret = request_firmware(&priv->firmware, libertas_fw_name,
-				    priv->hotplug_device)) < 0) {
-		lbs_pr_err("request_firmware() failed with %#x\n", ret);
-		lbs_pr_err("firmware %s not found\n", libertas_fw_name);
-		goto done;
-	}
-
-	if (check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
-		release_firmware(priv->firmware);
-		goto done;
-	}
-
-	ret = if_usb_do_prog_firmware(priv);
-
-	release_firmware(priv->firmware);
-done:
-	return ret;
-}
-
 
 #ifdef CONFIG_PM
 static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
@@ -1085,8 +1044,10 @@ static void if_usb_exit_module(void)
 
 	lbs_deb_enter(LBS_DEB_MAIN);
 
-	list_for_each_entry_safe(cardp, cardp_temp, &usb_devices, list)
-		libertas_reset_device((wlan_private *) cardp->priv);
+	list_for_each_entry_safe(cardp, cardp_temp, &usb_devices, list) {
+		libertas_prepare_and_send_command(cardp->priv, CMD_802_11_RESET,
+		                                  CMD_ACT_HALT, 0, 0, NULL);
+	}
 
 	/* API unregisters the driver from USB subsystem */
 	usb_deregister(&if_usb_driver);
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index 8b3b4f1..e07a10e 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -38,7 +38,7 @@ struct bootcmdrespStr
 
 /* read callback private data */
 struct read_cb_info {
-        wlan_private *priv;
+        struct usb_card_rec *cardp;
         struct sk_buff *skb;
 };
 
@@ -58,6 +58,7 @@ struct usb_card_rec {
 	int bulk_out_size;
 	u8 bulk_out_endpointAddr;
 
+	const struct firmware *fw;
 	u8 CRC_OK;
 	u32 fwseqnum;
 	u32 lastseqnum;
@@ -65,6 +66,7 @@ struct usb_card_rec {
 	u32 fwlastblksent;
 	u8 fwdnldover;
 	u8 fwfinalblk;
+	u8 surprise_removed;
 
 	u32 usb_event_cause;
 	u8 usb_int_cause;
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
index ce49d3f..72f8120 100644
--- a/drivers/net/wireless/libertas/join.c
+++ b/drivers/net/wireless/libertas/join.c
@@ -550,8 +550,8 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
 	adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
 
 	memset(adhs->rates, 0, sizeof(adhs->rates));
-	ratesize = min(sizeof(adhs->rates), sizeof(adhoc_rates_b));
-	memcpy(adhs->rates, adhoc_rates_b, ratesize);
+	ratesize = min(sizeof(adhs->rates), sizeof(libertas_bg_rates));
+	memcpy(adhs->rates, libertas_bg_rates, ratesize);
 
 	/* Copy the ad-hoc creating rates into Current BSS state structure */
 	memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates));
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index f0213ec..3feddcc 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -256,7 +256,7 @@ void libertas_remove_rtap(wlan_private *priv);
 static ssize_t libertas_rtap_get(struct device * dev,
 		struct device_attribute *attr, char * buf)
 {
-	wlan_private *priv = (wlan_private *) dev->driver_data;
+	wlan_private *priv = (wlan_private *) (to_net_dev(dev))->priv;
 	wlan_adapter *adapter = priv->adapter;
 	return snprintf(buf, 5, "0x%X\n", adapter->monitormode);
 }
@@ -268,7 +268,7 @@ static ssize_t libertas_rtap_set(struct device * dev,
 		struct device_attribute *attr, const char * buf, size_t count)
 {
 	int monitor_mode;
-	wlan_private *priv = (wlan_private *) dev->driver_data;
+	wlan_private *priv = (wlan_private *) (to_net_dev(dev))->priv;
 	wlan_adapter *adapter = priv->adapter;
 
 	sscanf(buf, "%x", &monitor_mode);
@@ -768,6 +768,7 @@ static int libertas_thread(void *data)
 
 	init_waitqueue_entry(&wait, current);
 
+	set_freezable();
 	for (;;) {
 		lbs_deb_thread( "main-thread 111: intcounter=%d "
 		       "currenttxskb=%p dnld_sent=%d\n",
@@ -790,7 +791,6 @@ static int libertas_thread(void *data)
 		} else
 			spin_unlock_irq(&adapter->driver_lock);
 
-
 		lbs_deb_thread(
 		       "main-thread 222 (waking up): intcounter=%d currenttxskb=%p "
 		       "dnld_sent=%d\n", adapter->intcounter,
@@ -925,7 +925,7 @@ static int libertas_thread(void *data)
  *  @param priv    A pointer to wlan_private structure
  *  @return 	   0 or -1
  */
-static int wlan_setup_station_hw(wlan_private * priv)
+static int wlan_setup_firmware(wlan_private * priv)
 {
 	int ret = -1;
 	wlan_adapter *adapter = priv->adapter;
@@ -933,14 +933,6 @@ static int wlan_setup_station_hw(wlan_private * priv)
 
 	lbs_deb_enter(LBS_DEB_FW);
 
-	ret = priv->hw_prog_firmware(priv);
-
-	if (ret) {
-		lbs_deb_fw("bootloader in invalid state\n");
-		ret = -1;
-		goto done;
-	}
-
 	/*
 	 * Read MAC address from HW
 	 */
@@ -991,8 +983,6 @@ done:
 	return ret;
 }
 
-static void command_timer_fn(unsigned long data);
-
 /**
  *  This function handles the timeout of command sending.
  *  It will re-send the same command again.
@@ -1034,155 +1024,99 @@ static void command_timer_fn(unsigned long data)
 	return;
 }
 
-static void libertas_free_adapter(wlan_private * priv)
+static int libertas_init_adapter(wlan_private * priv)
 {
 	wlan_adapter *adapter = priv->adapter;
-
-	if (!adapter) {
-		lbs_deb_fw("why double free adapter?\n");
-		return;
-	}
-
-	lbs_deb_fw("free command buffer\n");
-	libertas_free_cmd_buffer(priv);
-
-	lbs_deb_fw("free command_timer\n");
-	del_timer(&adapter->command_timer);
-
-	lbs_deb_fw("free scan results table\n");
-	kfree(adapter->networks);
-	adapter->networks = NULL;
-
-	/* Free the adapter object itself */
-	lbs_deb_fw("free adapter\n");
-	kfree(adapter);
-	priv->adapter = NULL;
-}
-
-static int wlan_allocate_adapter(wlan_private * priv)
-{
 	size_t bufsize;
-	wlan_adapter *adapter = priv->adapter;
+	int i, ret = 0;
 
 	/* Allocate buffer to store the BSSID list */
 	bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
 	adapter->networks = kzalloc(bufsize, GFP_KERNEL);
 	if (!adapter->networks) {
 		lbs_pr_err("Out of memory allocating beacons\n");
-		libertas_free_adapter(priv);
-		return -ENOMEM;
+		ret = -1;
+		goto out;
 	}
 
-	/* Allocate the command buffers */
-	libertas_allocate_cmd_buffer(priv);
+	/* Initialize scan result lists */
+	INIT_LIST_HEAD(&adapter->network_free_list);
+	INIT_LIST_HEAD(&adapter->network_list);
+	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
+		list_add_tail(&adapter->networks[i].list,
+			      &adapter->network_free_list);
+	}
 
-	memset(&adapter->libertas_ps_confirm_sleep, 0, sizeof(struct PS_CMD_ConfirmSleep));
 	adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum);
 	adapter->libertas_ps_confirm_sleep.command =
 	    cpu_to_le16(CMD_802_11_PS_MODE);
 	adapter->libertas_ps_confirm_sleep.size =
 	    cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
-	adapter->libertas_ps_confirm_sleep.result = 0;
 	adapter->libertas_ps_confirm_sleep.action =
 	    cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
 
-	return 0;
-}
-
-static void wlan_init_adapter(wlan_private * priv)
-{
-	wlan_adapter *adapter = priv->adapter;
-	int i;
-
-	adapter->connect_status = LIBERTAS_DISCONNECTED;
 	memset(adapter->current_addr, 0xff, ETH_ALEN);
 
-	/* 802.11 specific */
-	adapter->secinfo.wep_enabled = 0;
-	for (i = 0; i < sizeof(adapter->wep_keys) / sizeof(adapter->wep_keys[0]);
-	     i++)
-		memset(&adapter->wep_keys[i], 0, sizeof(struct enc_key));
-	adapter->wep_tx_keyidx = 0;
+	adapter->connect_status = LIBERTAS_DISCONNECTED;
 	adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
 	adapter->mode = IW_MODE_INFRA;
-
-	adapter->pending_assoc_req = NULL;
-	adapter->in_progress_assoc_req = NULL;
-
-	/* Initialize scan result lists */
-	INIT_LIST_HEAD(&adapter->network_free_list);
-	INIT_LIST_HEAD(&adapter->network_list);
-	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
-		list_add_tail(&adapter->networks[i].list,
-			      &adapter->network_free_list);
-	}
-
-	mutex_init(&adapter->lock);
-
-	memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
 	adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
-
-	/* PnP and power profile */
-	adapter->surpriseremoved = 0;
-
-	adapter->currentpacketfilter =
-	    CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
-
+	adapter->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
 	adapter->radioon = RADIO_ON;
-
 	adapter->auto_rate = 1;
-	adapter->cur_rate = 0;
-
-	// set default capabilities
 	adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
-
 	adapter->psmode = WLAN802_11POWERMODECAM;
-
 	adapter->psstate = PS_STATE_FULL_POWER;
-	adapter->needtowakeup = 0;
 
-	adapter->intcounter = 0;
-
-	adapter->currenttxskb = NULL;
+	mutex_init(&adapter->lock);
 
 	memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*));
 	adapter->tx_queue_idx = 0;
 	spin_lock_init(&adapter->txqueue_lock);
 
-	return;
-}
+	setup_timer(&adapter->command_timer, command_timer_fn,
+	            (unsigned long)priv);
 
-static int libertas_init_fw(wlan_private * priv)
-{
-	int ret = -1;
-	wlan_adapter *adapter = priv->adapter;
+	INIT_LIST_HEAD(&adapter->cmdfreeq);
+	INIT_LIST_HEAD(&adapter->cmdpendingq);
 
-	lbs_deb_enter(LBS_DEB_FW);
+	spin_lock_init(&adapter->driver_lock);
+	init_waitqueue_head(&adapter->cmd_pending);
+	adapter->nr_cmd_pending = 0;
 
-	/* Allocate adapter structure */
-	if ((ret = wlan_allocate_adapter(priv)) != 0)
-		goto done;
+	/* Allocate the command buffers */
+	if (libertas_allocate_cmd_buffer(priv)) {
+		lbs_pr_err("Out of memory allocating command buffers\n");
+		ret = -1;
+	}
 
-	/* init adapter structure */
-	wlan_init_adapter(priv);
+out:
+	return ret;
+}
 
-	/* init timer etc. */
-	setup_timer(&adapter->command_timer, command_timer_fn,
-			(unsigned long)priv);
+static void libertas_free_adapter(wlan_private * priv)
+{
+	wlan_adapter *adapter = priv->adapter;
 
-	/* download fimrware etc. */
-	if ((ret = wlan_setup_station_hw(priv)) != 0) {
-		del_timer_sync(&adapter->command_timer);
-		goto done;
+	if (!adapter) {
+		lbs_deb_fw("why double free adapter?\n");
+		return;
 	}
 
-	/* init 802.11d */
-	libertas_init_11d(priv);
+	lbs_deb_fw("free command buffer\n");
+	libertas_free_cmd_buffer(priv);
 
-	ret = 0;
-done:
-	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
-	return ret;
+	lbs_deb_fw("free command_timer\n");
+	del_timer(&adapter->command_timer);
+
+	lbs_deb_fw("free scan results table\n");
+	kfree(adapter->networks);
+	adapter->networks = NULL;
+
+	/* Free the adapter object itself */
+	lbs_deb_fw("free adapter\n");
+	kfree(adapter);
+	priv->adapter = NULL;
 }
 
 /**
@@ -1202,7 +1136,7 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
 	/* Allocate an Ethernet device and register it */
 	if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
 		lbs_pr_err("init ethX device failed\n");
-		return NULL;
+		goto done;
 	}
 	priv = dev->priv;
 
@@ -1212,10 +1146,16 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
 		goto err_kzalloc;
 	}
 
+	if (libertas_init_adapter(priv)) {
+		lbs_pr_err("failed to initialize adapter structure.\n");
+		goto err_init_adapter;
+	}
+
 	priv->dev = dev;
 	priv->card = card;
 	priv->mesh_open = 0;
 	priv->infra_open = 0;
+	priv->hotplug_device = dmdev;
 
 	SET_MODULE_OWNER(dev);
 
@@ -1238,87 +1178,144 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
 
 	SET_NETDEV_DEV(dev, dmdev);
 
-	INIT_LIST_HEAD(&priv->adapter->cmdfreeq);
-	INIT_LIST_HEAD(&priv->adapter->cmdpendingq);
-
-	spin_lock_init(&priv->adapter->driver_lock);
-	init_waitqueue_head(&priv->adapter->cmd_pending);
-	priv->adapter->nr_cmd_pending = 0;
 	priv->rtap_net_dev = NULL;
 	if (device_create_file(dmdev, &dev_attr_libertas_rtap))
-		goto err_kzalloc;
+		goto err_init_adapter;
+
+	lbs_deb_thread("Starting main thread...\n");
+	init_waitqueue_head(&priv->waitq);
+	priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main");
+	if (IS_ERR(priv->main_thread)) {
+		lbs_deb_thread("Error creating main thread.\n");
+		goto err_kthread_run;
+	}
+
+	priv->work_thread = create_singlethread_workqueue("libertas_worker");
+	INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
+	INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker);
+	INIT_WORK(&priv->sync_channel, libertas_sync_channel);
+
 	goto done;
 
+err_kthread_run:
+	device_remove_file(dmdev, &dev_attr_libertas_rtap);
+
+err_init_adapter:
+	libertas_free_adapter(priv);
+
 err_kzalloc:
 	free_netdev(dev);
 	priv = NULL;
+
 done:
 	lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv);
 	return priv;
 }
 EXPORT_SYMBOL_GPL(libertas_add_card);
 
-int libertas_activate_card(wlan_private *priv)
+
+int libertas_remove_card(wlan_private *priv)
 {
+	wlan_adapter *adapter = priv->adapter;
 	struct net_device *dev = priv->dev;
-	int ret = -1;
+	union iwreq_data wrqu;
 
 	lbs_deb_enter(LBS_DEB_MAIN);
 
-	lbs_deb_thread("Starting main thread...\n");
-	init_waitqueue_head(&priv->waitq);
-	priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main");
-	if (IS_ERR(priv->main_thread)) {
-		lbs_deb_thread("Error creating main thread.\n");
-		goto done;
-	}
+	libertas_remove_rtap(priv);
 
-	priv->work_thread = create_singlethread_workqueue("libertas_worker");
-	INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
-	INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker);
+	dev = priv->dev;
+	device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap);
 
-	INIT_WORK(&priv->sync_channel, libertas_sync_channel);
+	cancel_delayed_work(&priv->scan_work);
+	cancel_delayed_work(&priv->assoc_work);
+	destroy_workqueue(priv->work_thread);
 
-	/*
-	 * Register the device. Fillup the private data structure with
-	 * relevant information from the card and request for the required
-	 * IRQ.
-	 */
-	if (priv->hw_register_dev(priv) < 0) {
-		lbs_pr_err("failed to register WLAN device\n");
-		goto err_registerdev;
+	if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) {
+		adapter->psmode = WLAN802_11POWERMODECAM;
+		libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
 	}
 
-	/* init FW and HW */
-	if (libertas_init_fw(priv)) {
-		lbs_pr_err("firmware init failed\n");
-		goto err_registerdev;
-	}
+	memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+
+	/* Stop the thread servicing the interrupts */
+	adapter->surpriseremoved = 1;
+	kthread_stop(priv->main_thread);
+
+	libertas_free_adapter(priv);
+
+	priv->dev = NULL;
+	free_netdev(dev);
+
+	lbs_deb_leave(LBS_DEB_MAIN);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(libertas_remove_card);
+
+
+int libertas_start_card(wlan_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = -1;
+
+	lbs_deb_enter(LBS_DEB_MAIN);
+
+	/* poke the firmware */
+	ret = wlan_setup_firmware(priv);
+	if (ret)
+		goto done;
+
+	/* init 802.11d */
+	libertas_init_11d(priv);
 
 	if (register_netdev(dev)) {
 		lbs_pr_err("cannot register ethX device\n");
-		goto err_init_fw;
+		goto done;
 	}
 
-	lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
-
 	libertas_debugfs_init_one(priv, dev);
 
+	lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
+
 	ret = 0;
-	goto done;
 
-err_init_fw:
-	priv->hw_unregister_dev(priv);
-err_registerdev:
-	destroy_workqueue(priv->work_thread);
-	/* Stop the thread servicing the interrupts */
-	wake_up_interruptible(&priv->waitq);
-	kthread_stop(priv->main_thread);
 done:
-	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(libertas_activate_card);
+EXPORT_SYMBOL_GPL(libertas_start_card);
+
+
+int libertas_stop_card(wlan_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = -1;
+	struct cmd_ctrl_node *cmdnode;
+	unsigned long flags;
+
+	lbs_deb_enter(LBS_DEB_MAIN);
+
+	netif_stop_queue(priv->dev);
+	netif_carrier_off(priv->dev);
+
+	libertas_debugfs_remove_one(priv);
+
+	/* Flush pending command nodes */
+	spin_lock_irqsave(&priv->adapter->driver_lock, flags);
+	list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {
+		cmdnode->cmdwaitqwoken = 1;
+		wake_up_interruptible(&cmdnode->cmdwait_q);
+	}
+	spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
+
+	unregister_netdev(dev);
+
+	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(libertas_stop_card);
 
 
 /**
@@ -1388,89 +1385,12 @@ done:
 }
 EXPORT_SYMBOL_GPL(libertas_add_mesh);
 
-static void wake_pending_cmdnodes(wlan_private *priv)
-{
-	struct cmd_ctrl_node *cmdnode;
-	unsigned long flags;
-
-	lbs_deb_enter(LBS_DEB_HOST);
-
-	spin_lock_irqsave(&priv->adapter->driver_lock, flags);
-	list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {
-		cmdnode->cmdwaitqwoken = 1;
-		wake_up_interruptible(&cmdnode->cmdwait_q);
-	}
-	spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
-}
-
-
-int libertas_remove_card(wlan_private *priv)
-{
-	wlan_adapter *adapter;
-	struct net_device *dev;
-	union iwreq_data wrqu;
-
-	lbs_deb_enter(LBS_DEB_NET);
-
-	libertas_remove_rtap(priv);
-	if (!priv)
-		goto out;
-
-	adapter = priv->adapter;
-
-	if (!adapter)
-		goto out;
-
-	dev = priv->dev;
-	device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap);
-
-	netif_stop_queue(priv->dev);
-	netif_carrier_off(priv->dev);
-
-	wake_pending_cmdnodes(priv);
-
-	unregister_netdev(dev);
-
-	cancel_delayed_work(&priv->scan_work);
-	cancel_delayed_work(&priv->assoc_work);
-	destroy_workqueue(priv->work_thread);
-
-	if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) {
-		adapter->psmode = WLAN802_11POWERMODECAM;
-		libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
-	}
-
-	memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
-	adapter->surpriseremoved = 1;
-
-	/* Stop the thread servicing the interrupts */
-	kthread_stop(priv->main_thread);
-
-	libertas_debugfs_remove_one(priv);
-
-	lbs_deb_net("free adapter\n");
-	libertas_free_adapter(priv);
-
-	lbs_deb_net("unregister finish\n");
-
-	priv->dev = NULL;
-	free_netdev(dev);
-
-out:
-	lbs_deb_leave(LBS_DEB_NET);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(libertas_remove_card);
-
 
 void libertas_remove_mesh(wlan_private *priv)
 {
 	struct net_device *mesh_dev;
 
-	lbs_deb_enter(LBS_DEB_NET);
+	lbs_deb_enter(LBS_DEB_MAIN);
 
 	if (!priv)
 		goto out;
@@ -1487,7 +1407,7 @@ void libertas_remove_mesh(wlan_private *priv)
 	free_netdev(mesh_dev);
 
 out:
-	lbs_deb_leave(LBS_DEB_NET);
+	lbs_deb_leave(LBS_DEB_MAIN);
 }
 EXPORT_SYMBOL_GPL(libertas_remove_mesh);
 

-
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux