[PATCH] libertas: remove adapter->atimwindow
[safe/jmp/linux-2.6] / drivers / net / wireless / libertas / main.c
index 4970465..d227e45 100644 (file)
@@ -4,26 +4,37 @@
   * thread etc..
   */
 
+#include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
+#include <linux/kthread.h>
 
 #include <net/iw_handler.h>
+#include <net/ieee80211.h>
 
 #include "host.h"
-#include "sbi.h"
 #include "decl.h"
 #include "dev.h"
-#include "fw.h"
 #include "wext.h"
 #include "debugfs.h"
 #include "assoc.h"
 
-#ifdef ENABLE_PM
-static struct pm_dev *wlan_pm_dev = NULL;
+#define DRIVER_RELEASE_VERSION "322.p1"
+const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
+#ifdef  DEBUG
+    "-dbg"
 #endif
+    "";
+
+
+/* Module parameters */
+unsigned int libertas_debug = 0;
+module_param(libertas_debug, int, 0644);
+EXPORT_SYMBOL_GPL(libertas_debug);
+
 
 #define WLAN_TX_PWR_DEFAULT            20      /*100mW */
 #define WLAN_TX_PWR_US_DEFAULT         20      /*100mW */
@@ -139,93 +150,151 @@ static struct region_cfp_table region_cfp_table[] = {
 };
 
 /**
- * the rates supported by the card
+ * the table to keep region code
  */
-u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] =
-    { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
-       0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
-};
+u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
+    { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
 
 /**
- * the rates supported
+ * 802.11b/g supported bitrates (in 500Kb/s units)
  */
-u8 libertas_supported_rates[G_SUPPORTED_RATES] =
-    { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
-0 };
+u8 libertas_bg_rates[MAX_RATES] =
+    { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
+0x00, 0x00 };
 
 /**
- * the rates supported for ad-hoc G mode
+ * FW rate table.  FW refers to rates by their index in this table, not by the
+ * rate value itself.  Values of 0x00 are
+ * reserved positions.
  */
-u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES] =
-    { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
-0 };
+static u8 fw_data_rates[MAX_RATES] =
+    { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
+      0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
+};
 
 /**
- * the rates supported for ad-hoc B mode
+ *  @brief use index to get the data rate
+ *
+ *  @param idx                The index of data rate
+ *  @return                    data rate or 0
  */
-u8 libertas_adhoc_rates_b[4] = { 0x82, 0x84, 0x8b, 0x96 };
+u32 libertas_fw_index_to_data_rate(u8 idx)
+{
+       if (idx >= sizeof(fw_data_rates))
+               idx = 0;
+       return fw_data_rates[idx];
+}
 
 /**
- * the global variable of a pointer to wlan_private
- * structure variable
+ *  @brief use rate to get the index
+ *
+ *  @param rate                 data rate
+ *  @return                    index or 0
  */
-static wlan_private *wlanpriv = NULL;
-
-#define MAX_DEVS 5
-static struct net_device *libertas_devs[MAX_DEVS];
-static int libertas_found = 0;
+u8 libertas_data_rate_to_fw_index(u32 rate)
+{
+       u8 i;
 
-/**
- * the table to keep region code
- */
-u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
-    { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
+       if (!rate)
+               return 0;
 
-static u8 *default_fw_name = "usb8388.bin";
+       for (i = 0; i < sizeof(fw_data_rates); i++) {
+               if (rate == fw_data_rates[i])
+                       return i;
+       }
+       return 0;
+}
 
 /**
  * Attributes exported through sysfs
  */
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
 
 /**
- * @brief Get function for sysfs attribute libertas_mpp
+ * @brief Get function for sysfs attribute anycast_mask
  */
-static ssize_t libertas_mpp_get(struct class_device * dev, char * buf) {
+static ssize_t libertas_anycast_get(struct device * dev,
+               struct device_attribute *attr, char * buf)
+{
        struct cmd_ds_mesh_access mesh_access;
 
        memset(&mesh_access, 0, sizeof(mesh_access));
        libertas_prepare_and_send_command(to_net_dev(dev)->priv,
-                       cmd_mesh_access,
-                       cmd_act_mesh_get_mpp,
-                       cmd_option_waitforrsp, 0, (void *)&mesh_access);
+                       CMD_MESH_ACCESS,
+                       CMD_ACT_MESH_GET_ANYCAST,
+                       CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
 
-       return snprintf(buf, 3, "%d\n", mesh_access.data[0]);
+       return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
 }
 
 /**
- * @brief Set function for sysfs attribute libertas_mpp
+ * @brief Set function for sysfs attribute anycast_mask
  */
-static ssize_t libertas_mpp_set(struct class_device * dev, const char * buf,
-               size_t count) {
+static ssize_t libertas_anycast_set(struct device * dev,
+               struct device_attribute *attr, const char * buf, size_t count)
+{
        struct cmd_ds_mesh_access mesh_access;
-
+       uint32_t datum;
 
        memset(&mesh_access, 0, sizeof(mesh_access));
-       sscanf(buf, "%d", &(mesh_access.data[0]));
+       sscanf(buf, "%x", &datum);
+       mesh_access.data[0] = cpu_to_le32(datum);
+
        libertas_prepare_and_send_command((to_net_dev(dev))->priv,
-                       cmd_mesh_access,
-                       cmd_act_mesh_set_mpp,
-                       cmd_option_waitforrsp, 0, (void *)&mesh_access);
+                       CMD_MESH_ACCESS,
+                       CMD_ACT_MESH_SET_ANYCAST,
+                       CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
        return strlen(buf);
 }
 
 /**
- * libertas_mpp attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/libertas-mpp)
+ * anycast_mask attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/anycast_mask)
  */
-static CLASS_DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get,
-               libertas_mpp_set );
+static DEVICE_ATTR(anycast_mask, 0644, libertas_anycast_get, libertas_anycast_set);
+
+static ssize_t libertas_autostart_enabled_get(struct device * dev,
+               struct device_attribute *attr, char * buf)
+{
+       struct cmd_ds_mesh_access mesh_access;
+
+       memset(&mesh_access, 0, sizeof(mesh_access));
+       libertas_prepare_and_send_command(to_net_dev(dev)->priv,
+                       CMD_MESH_ACCESS,
+                       CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
+                       CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
+
+       return sprintf(buf, "%d\n", le32_to_cpu(mesh_access.data[0]));
+}
+
+static ssize_t libertas_autostart_enabled_set(struct device * dev,
+               struct device_attribute *attr, const char * buf, size_t count)
+{
+       struct cmd_ds_mesh_access mesh_access;
+       uint32_t datum;
+
+       memset(&mesh_access, 0, sizeof(mesh_access));
+       sscanf(buf, "%d", &datum);
+       mesh_access.data[0] = cpu_to_le32(datum);
+
+       libertas_prepare_and_send_command((to_net_dev(dev))->priv,
+                       CMD_MESH_ACCESS,
+                       CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
+                       CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
+       return strlen(buf);
+}
+
+static DEVICE_ATTR(autostart_enabled, 0644,
+               libertas_autostart_enabled_get, libertas_autostart_enabled_set);
+
+static struct attribute *libertas_mesh_sysfs_entries[] = {
+       &dev_attr_anycast_mask.attr,
+       &dev_attr_autostart_enabled.attr,
+       NULL,
+};
+
+static struct attribute_group libertas_mesh_attr_group = {
+       .attrs = libertas_mesh_sysfs_entries,
+};
 
 /**
  *  @brief Check if the device can be open and wait if necessary.
@@ -238,7 +307,8 @@ static CLASS_DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get,
  * function to work around the issue.
  *
  */
-static int pre_open_check(struct net_device *dev) {
+static int pre_open_check(struct net_device *dev)
+{
        wlan_private *priv = (wlan_private *) dev->priv;
        wlan_adapter *adapter = priv->adapter;
        int i = 0;
@@ -248,8 +318,7 @@ static int pre_open_check(struct net_device *dev) {
                msleep_interruptible(100);
        }
        if (!adapter->fw_ready) {
-               lbs_pr_info("FW not ready, pre_open_check() return failure\n");
-               LEAVE();
+               lbs_pr_err("firmware not ready\n");
                return -1;
        }
 
@@ -262,22 +331,26 @@ static int pre_open_check(struct net_device *dev) {
  *  @param dev     A pointer to net_device structure
  *  @return       0
  */
-static int wlan_dev_open(struct net_device *dev)
+static int libertas_dev_open(struct net_device *dev)
 {
        wlan_private *priv = (wlan_private *) dev->priv;
        wlan_adapter *adapter = priv->adapter;
 
-       ENTER();
-
+       lbs_deb_enter(LBS_DEB_NET);
 
        priv->open = 1;
 
-       if (adapter->connect_status == libertas_connected) {
-               netif_carrier_on(priv->wlan_dev.netdev);
-       } else
-               netif_carrier_off(priv->wlan_dev.netdev);
+       if (adapter->connect_status == LIBERTAS_CONNECTED) {
+               netif_carrier_on(priv->dev);
+               if (priv->mesh_dev)
+                       netif_carrier_on(priv->mesh_dev);
+       } else {
+               netif_carrier_off(priv->dev);
+               if (priv->mesh_dev)
+                       netif_carrier_off(priv->mesh_dev);
+       }
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_NET);
        return 0;
 }
 /**
@@ -286,16 +359,16 @@ static int wlan_dev_open(struct net_device *dev)
  *  @param dev     A pointer to net_device structure
  *  @return       0
  */
-static int mesh_open(struct net_device *dev)
+static int libertas_mesh_open(struct net_device *dev)
 {
        wlan_private *priv = (wlan_private *) dev->priv ;
 
-       if(pre_open_check(dev) == -1)
+       if (pre_open_check(dev) == -1)
                return -1;
        priv->mesh_open = 1 ;
-       netif_start_queue(priv->mesh_dev);
+       netif_wake_queue(priv->mesh_dev);
        if (priv->infra_open == 0)
-               return wlan_dev_open(priv->wlan_dev.netdev) ;
+               return libertas_dev_open(priv->dev) ;
        return 0;
 }
 
@@ -305,29 +378,29 @@ static int mesh_open(struct net_device *dev)
  *  @param dev     A pointer to net_device structure
  *  @return       0
  */
-static int wlan_open(struct net_device *dev)
+static int libertas_open(struct net_device *dev)
 {
        wlan_private *priv = (wlan_private *) dev->priv ;
 
        if(pre_open_check(dev) == -1)
                return -1;
        priv->infra_open = 1 ;
-       netif_wake_queue(priv->wlan_dev.netdev);
+       netif_wake_queue(priv->dev);
        if (priv->open == 0)
-               return wlan_dev_open(priv->wlan_dev.netdev) ;
+               return libertas_dev_open(priv->dev) ;
        return 0;
 }
 
-static int wlan_dev_close(struct net_device *dev)
+static int libertas_dev_close(struct net_device *dev)
 {
        wlan_private *priv = dev->priv;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_NET);
 
-       netif_carrier_off(priv->wlan_dev.netdev);
+       netif_carrier_off(priv->dev);
        priv->open = 0;
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_NET);
        return 0;
 }
 
@@ -337,14 +410,14 @@ static int wlan_dev_close(struct net_device *dev)
  *  @param dev     A pointer to net_device structure
  *  @return       0
  */
-static int mesh_close(struct net_device *dev)
+static int libertas_mesh_close(struct net_device *dev)
 {
        wlan_private *priv = (wlan_private *) (dev->priv);
 
        priv->mesh_open = 0;
        netif_stop_queue(priv->mesh_dev);
        if (priv->infra_open == 0)
-               return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ;
+               return libertas_dev_close(dev);
        else
                return 0;
 }
@@ -355,184 +428,87 @@ static int mesh_close(struct net_device *dev)
  *  @param dev     A pointer to net_device structure
  *  @return       0
  */
-static int wlan_close(struct net_device *dev) {
+static int libertas_close(struct net_device *dev)
+{
        wlan_private *priv = (wlan_private *) dev->priv;
 
-       netif_stop_queue(priv->wlan_dev.netdev);
+       netif_stop_queue(dev);
        priv->infra_open = 0;
        if (priv->mesh_open == 0)
-               return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ;
+               return libertas_dev_close(dev);
        else
                return 0;
 }
 
 
-#ifdef ENABLE_PM
-
-/**
- *  @brief This function is a callback function. it is called by
- *  kernel to enter or exit power saving mode.
- *
- *  @param pmdev   A pointer to pm_dev
- *  @param pmreq   pm_request_t
- *  @param pmdata  A pointer to pmdata
- *  @return       0 or -1
- */
-static int wlan_pm_callback(struct pm_dev *pmdev, pm_request_t pmreq,
-                           void *pmdata)
-{
-       wlan_private *priv = wlanpriv;
-       wlan_adapter *adapter = priv->adapter;
-       struct net_device *dev = priv->wlan_dev.netdev;
-
-       lbs_pr_debug(1, "WPRM_PM_CALLBACK: pmreq = %d.\n", pmreq);
-
-       switch (pmreq) {
-       case PM_SUSPEND:
-               lbs_pr_debug(1, "WPRM_PM_CALLBACK: enter PM_SUSPEND.\n");
-
-               /* in associated mode */
-               if (adapter->connect_status == libertas_connected) {
-                       if ((adapter->psstate != PS_STATE_SLEEP)
-                           ) {
-                               lbs_pr_debug(1,
-                                      "wlan_pm_callback: can't enter sleep mode\n");
-                               return -1;
-                       } else {
-
-                               /*
-                                * Detach the network interface
-                                * if the network is running
-                                */
-                               if (netif_running(dev)) {
-                                       netif_device_detach(dev);
-                                       lbs_pr_debug(1,
-                                              "netif_device_detach().\n");
-                               }
-                               libertas_sbi_suspend(priv);
-                       }
-                       break;
-               }
-
-               /* in non associated mode */
-
-               /*
-                * Detach the network interface
-                * if the network is running
-                */
-               if (netif_running(dev))
-                       netif_device_detach(dev);
-
-               /*
-                * Storing and restoring of the regs be taken care
-                * at the driver rest will be done at wlan driver
-                * this makes driver independent of the card
-                */
-
-               libertas_sbi_suspend(priv);
-
-               break;
-
-       case PM_RESUME:
-               /* in associated mode */
-               if (adapter->connect_status == libertas_connected) {
-                       {
-                               /*
-                                * Bring the inteface up first
-                                * This case should not happen still ...
-                                */
-                               libertas_sbi_resume(priv);
-
-                               /*
-                                * Attach the network interface
-                                * if the network is running
-                                */
-                               if (netif_running(dev)) {
-                                       netif_device_attach(dev);
-                                       lbs_pr_debug(1,
-                                              "after netif_device_attach().\n");
-                               }
-                               lbs_pr_debug(1,
-                                      "After netif attach, in associated mode.\n");
-                       }
-                       break;
-               }
-
-               /* in non associated mode */
-
-               /*
-                * Bring the inteface up first
-                * This case should not happen still ...
-                */
-
-               libertas_sbi_resume(priv);
-
-               if (netif_running(dev))
-                       netif_device_attach(dev);
-
-               lbs_pr_debug(1, "after netif attach, in NON associated mode.\n");
-               break;
-       }
-
-       return 0;
-}
-#endif                         /* ENABLE_PM */
-
-static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int libertas_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        int ret = 0;
        wlan_private *priv = dev->priv;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_NET);
 
-       if (priv->wlan_dev.dnld_sent || priv->adapter->TxLockFlag) {
+       if (priv->dnld_sent || priv->adapter->TxLockFlag) {
                priv->stats.tx_dropped++;
                goto done;
        }
 
-       netif_stop_queue(priv->wlan_dev.netdev);
+       netif_stop_queue(priv->dev);
+       if (priv->mesh_dev)
+               netif_stop_queue(priv->mesh_dev);
 
        if (libertas_process_tx(priv, skb) == 0)
                dev->trans_start = jiffies;
 done:
-       LEAVE();
+       lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
        return ret;
 }
 
 /**
- * @brief Mark mesh packets and handover them to wlan_hard_start_xmit
+ * @brief Mark mesh packets and handover them to libertas_hard_start_xmit
  *
  */
-static int mesh_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int libertas_mesh_pre_start_xmit(struct sk_buff *skb,
+               struct net_device *dev)
 {
        wlan_private *priv = dev->priv;
-       ENTER();
+       int ret;
+
+       lbs_deb_enter(LBS_DEB_MESH);
+
        SET_MESH_FRAME(skb);
-       LEAVE();
 
-       return wlan_hard_start_xmit(skb, priv->wlan_dev.netdev);
+       ret = libertas_hard_start_xmit(skb, priv->dev);
+       lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+       return ret;
 }
 
 /**
- * @brief Mark non-mesh packets and handover them to wlan_hard_start_xmit
+ * @brief Mark non-mesh packets and handover them to libertas_hard_start_xmit
  *
  */
-static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) {
-       ENTER();
+static int libertas_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       int ret;
+
+       lbs_deb_enter(LBS_DEB_NET);
+
        UNSET_MESH_FRAME(skb);
-       LEAVE();
-       return wlan_hard_start_xmit(skb, dev);
+
+       ret = libertas_hard_start_xmit(skb, dev);
+       lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+       return ret;
 }
 
-static void wlan_tx_timeout(struct net_device *dev)
+static void libertas_tx_timeout(struct net_device *dev)
 {
        wlan_private *priv = (wlan_private *) dev->priv;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_TX);
 
-       lbs_pr_err("tx watch dog timeout!\n");
+       lbs_pr_err("tx watch dog timeout\n");
 
-       priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+       priv->dnld_sent = DNLD_RES_RECEIVED;
        dev->trans_start = jiffies;
 
        if (priv->adapter->currenttxskb) {
@@ -542,11 +518,14 @@ static void wlan_tx_timeout(struct net_device *dev)
                        priv->adapter->eventcause = 0x01000000;
                        libertas_send_tx_feedback(priv);
                } else
-                       wake_up_interruptible(&priv->mainthread.waitq);
-       } else if (priv->adapter->connect_status == libertas_connected)
-               netif_wake_queue(priv->wlan_dev.netdev);
+                       wake_up_interruptible(&priv->waitq);
+       } else if (priv->adapter->connect_status == LIBERTAS_CONNECTED) {
+               netif_wake_queue(priv->dev);
+               if (priv->mesh_dev)
+                       netif_wake_queue(priv->mesh_dev);
+       }
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_TX);
 }
 
 /**
@@ -555,50 +534,54 @@ static void wlan_tx_timeout(struct net_device *dev)
  *  @param dev     A pointer to wlan_private structure
  *  @return       A pointer to net_device_stats structure
  */
-static struct net_device_stats *wlan_get_stats(struct net_device *dev)
+static struct net_device_stats *libertas_get_stats(struct net_device *dev)
 {
        wlan_private *priv = (wlan_private *) dev->priv;
 
        return &priv->stats;
 }
 
-static int wlan_set_mac_address(struct net_device *dev, void *addr)
+static int libertas_set_mac_address(struct net_device *dev, void *addr)
 {
        int ret = 0;
        wlan_private *priv = (wlan_private *) dev->priv;
        wlan_adapter *adapter = priv->adapter;
        struct sockaddr *phwaddr = addr;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_NET);
+
+       /* In case it was called from the mesh device */
+       dev = priv->dev ;
 
        memset(adapter->current_addr, 0, ETH_ALEN);
 
        /* dev->dev_addr is 8 bytes */
-       lbs_dbg_hex("dev->dev_addr:", dev->dev_addr, ETH_ALEN);
+       lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN);
 
-       lbs_dbg_hex("addr:", phwaddr->sa_data, ETH_ALEN);
+       lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN);
        memcpy(adapter->current_addr, phwaddr->sa_data, ETH_ALEN);
 
-       ret = libertas_prepare_and_send_command(priv, cmd_802_11_mac_address,
-                                   cmd_act_set,
-                                   cmd_option_waitforrsp, 0, NULL);
+       ret = libertas_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS,
+                                   CMD_ACT_SET,
+                                   CMD_OPTION_WAITFORRSP, 0, NULL);
 
        if (ret) {
-               lbs_pr_debug(1, "set mac address failed.\n");
+               lbs_deb_net("set MAC address failed\n");
                ret = -1;
                goto done;
        }
 
-       lbs_dbg_hex("adapter->macaddr:", adapter->current_addr, ETH_ALEN);
+       lbs_deb_hex(LBS_DEB_NET, "adapter->macaddr", adapter->current_addr, ETH_ALEN);
        memcpy(dev->dev_addr, adapter->current_addr, ETH_ALEN);
-       memcpy(((wlan_private *) dev->priv)->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
+       if (priv->mesh_dev)
+               memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
 
 done:
-       LEAVE();
+       lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
        return ret;
 }
 
-static int wlan_copy_multicast_address(wlan_adapter * adapter,
+static int libertas_copy_multicast_address(wlan_adapter * adapter,
                                     struct net_device *dev)
 {
        int i = 0;
@@ -613,59 +596,59 @@ static int wlan_copy_multicast_address(wlan_adapter * adapter,
 
 }
 
-static void wlan_set_multicast_list(struct net_device *dev)
+static void libertas_set_multicast_list(struct net_device *dev)
 {
        wlan_private *priv = dev->priv;
        wlan_adapter *adapter = priv->adapter;
        int oldpacketfilter;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_NET);
 
        oldpacketfilter = adapter->currentpacketfilter;
 
        if (dev->flags & IFF_PROMISC) {
-               lbs_pr_debug(1, "enable Promiscuous mode\n");
+               lbs_deb_net("enable promiscuous mode\n");
                adapter->currentpacketfilter |=
-                   cmd_act_mac_promiscuous_enable;
+                   CMD_ACT_MAC_PROMISCUOUS_ENABLE;
                adapter->currentpacketfilter &=
-                   ~(cmd_act_mac_all_multicast_enable |
-                     cmd_act_mac_multicast_enable);
+                   ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE |
+                     CMD_ACT_MAC_MULTICAST_ENABLE);
        } else {
                /* Multicast */
                adapter->currentpacketfilter &=
-                   ~cmd_act_mac_promiscuous_enable;
+                   ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
 
                if (dev->flags & IFF_ALLMULTI || dev->mc_count >
                    MRVDRV_MAX_MULTICAST_LIST_SIZE) {
-                       lbs_pr_debug(1, "Enabling All Multicast!\n");
+                       lbs_deb_net( "enabling all multicast\n");
                        adapter->currentpacketfilter |=
-                           cmd_act_mac_all_multicast_enable;
+                           CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
                        adapter->currentpacketfilter &=
-                           ~cmd_act_mac_multicast_enable;
+                           ~CMD_ACT_MAC_MULTICAST_ENABLE;
                } else {
                        adapter->currentpacketfilter &=
-                           ~cmd_act_mac_all_multicast_enable;
+                           ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
 
                        if (!dev->mc_count) {
-                               lbs_pr_debug(1, "No multicast addresses - "
-                                      "disabling multicast!\n");
+                               lbs_deb_net("no multicast addresses, "
+                                      "disabling multicast\n");
                                adapter->currentpacketfilter &=
-                                   ~cmd_act_mac_multicast_enable;
+                                   ~CMD_ACT_MAC_MULTICAST_ENABLE;
                        } else {
                                int i;
 
                                adapter->currentpacketfilter |=
-                                   cmd_act_mac_multicast_enable;
+                                   CMD_ACT_MAC_MULTICAST_ENABLE;
 
                                adapter->nr_of_multicastmacaddr =
-                                   wlan_copy_multicast_address(adapter, dev);
+                                   libertas_copy_multicast_address(adapter, dev);
 
-                               lbs_pr_debug(1, "Multicast addresses: %d\n",
+                               lbs_deb_net("multicast addresses: %d\n",
                                       dev->mc_count);
 
                                for (i = 0; i < dev->mc_count; i++) {
-                                       lbs_pr_debug(1, "Multicast address %d:"
-                                              "%x %x %x %x %x %x\n", i,
+                                       lbs_deb_net("Multicast address %d:"
+                                              MAC_FMT "\n", i,
                                               adapter->multicastlist[i][0],
                                               adapter->multicastlist[i][1],
                                               adapter->multicastlist[i][2],
@@ -673,10 +656,10 @@ static void wlan_set_multicast_list(struct net_device *dev)
                                               adapter->multicastlist[i][4],
                                               adapter->multicastlist[i][5]);
                                }
-                               /* set multicast addresses to firmware */
+                               /* send multicast addresses to firmware */
                                libertas_prepare_and_send_command(priv,
-                                                     cmd_mac_multicast_adr,
-                                                     cmd_act_set, 0, 0,
+                                                     CMD_MAC_MULTICAST_ADR,
+                                                     CMD_ACT_SET, 0, 0,
                                                      NULL);
                        }
                }
@@ -686,45 +669,43 @@ static void wlan_set_multicast_list(struct net_device *dev)
                libertas_set_mac_packet_filter(priv);
        }
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_NET);
 }
 
 /**
- *  @brief This function hanldes the major job in WLAN driver.
- *  it handles the event generated by firmware, rx data received
- *  from firmware and tx data sent from kernel.
+ *  @brief This function handles the major jobs in the WLAN driver.
+ *  It handles all events generated by firmware, RX data received
+ *  from firmware and TX data sent from kernel.
  *
  *  @param data    A pointer to wlan_thread structure
  *  @return       0
  */
-static int wlan_service_main_thread(void *data)
+static int libertas_thread(void *data)
 {
-       struct wlan_thread *thread = data;
-       wlan_private *priv = thread->priv;
+       struct net_device *dev = data;
+       wlan_private *priv = dev->priv;
        wlan_adapter *adapter = priv->adapter;
        wait_queue_t wait;
        u8 ireg = 0;
 
-       ENTER();
-
-       wlan_activate_thread(thread);
+       lbs_deb_enter(LBS_DEB_THREAD);
 
        init_waitqueue_entry(&wait, current);
 
        for (;;) {
-               lbs_pr_debug(1, "main-thread 111: intcounter=%d "
+               lbs_deb_thread( "main-thread 111: intcounter=%d "
                       "currenttxskb=%p dnld_sent=%d\n",
                       adapter->intcounter,
-                      adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+                      adapter->currenttxskb, priv->dnld_sent);
 
-               add_wait_queue(&thread->waitq, &wait);
+               add_wait_queue(&priv->waitq, &wait);
                set_current_state(TASK_INTERRUPTIBLE);
                spin_lock_irq(&adapter->driver_lock);
                if ((adapter->psstate == PS_STATE_SLEEP) ||
                    (!adapter->intcounter
-                    && (priv->wlan_dev.dnld_sent || adapter->cur_cmd ||
+                    && (priv->dnld_sent || adapter->cur_cmd ||
                         list_empty(&adapter->cmdpendingq)))) {
-                       lbs_pr_debug(1,
+                       lbs_deb_thread(
                               "main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
                               adapter->connect_status, adapter->intcounter,
                               adapter->psmode, adapter->psstate);
@@ -734,23 +715,23 @@ static int wlan_service_main_thread(void *data)
                        spin_unlock_irq(&adapter->driver_lock);
 
 
-               lbs_pr_debug(1,
+               lbs_deb_thread(
                       "main-thread 222 (waking up): intcounter=%d currenttxskb=%p "
                       "dnld_sent=%d\n", adapter->intcounter,
-                      adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+                      adapter->currenttxskb, priv->dnld_sent);
 
                set_current_state(TASK_RUNNING);
-               remove_wait_queue(&thread->waitq, &wait);
+               remove_wait_queue(&priv->waitq, &wait);
                try_to_freeze();
 
-               lbs_pr_debug(1, "main-thread 333: intcounter=%d currenttxskb=%p "
+               lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p "
                       "dnld_sent=%d\n",
                       adapter->intcounter,
-                      adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+                      adapter->currenttxskb, priv->dnld_sent);
 
                if (kthread_should_stop()
                    || adapter->surpriseremoved) {
-                       lbs_pr_debug(1,
+                       lbs_deb_thread(
                               "main-thread: break from main thread: surpriseremoved=0x%x\n",
                               adapter->surpriseremoved);
                        break;
@@ -761,10 +742,10 @@ static int wlan_service_main_thread(void *data)
                if (adapter->intcounter) {
                        u8 int_status;
                        adapter->intcounter = 0;
-                       int_status = libertas_sbi_get_int_status(priv, &ireg);
+                       int_status = priv->hw_get_int_status(priv, &ireg);
 
                        if (int_status) {
-                               lbs_pr_debug(1,
+                               lbs_deb_thread(
                                       "main-thread: reading HOST_INT_STATUS_REG failed\n");
                                spin_unlock_irq(&adapter->driver_lock);
                                continue;
@@ -772,30 +753,30 @@ static int wlan_service_main_thread(void *data)
                        adapter->hisregcpy |= ireg;
                }
 
-               lbs_pr_debug(1, "main-thread 444: intcounter=%d currenttxskb=%p "
+               lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p "
                       "dnld_sent=%d\n",
                       adapter->intcounter,
-                      adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+                      adapter->currenttxskb, priv->dnld_sent);
 
                /* command response? */
-               if (adapter->hisregcpy & his_cmdupldrdy) {
-                       lbs_pr_debug(1, "main-thread: cmd response ready.\n");
+               if (adapter->hisregcpy & MRVDRV_CMD_UPLD_RDY) {
+                       lbs_deb_thread("main-thread: cmd response ready\n");
 
-                       adapter->hisregcpy &= ~his_cmdupldrdy;
+                       adapter->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
                        spin_unlock_irq(&adapter->driver_lock);
                        libertas_process_rx_command(priv);
                        spin_lock_irq(&adapter->driver_lock);
                }
 
                /* Any Card Event */
-               if (adapter->hisregcpy & his_cardevent) {
-                       lbs_pr_debug(1, "main-thread: Card Event Activity.\n");
+               if (adapter->hisregcpy & MRVDRV_CARDEVENT) {
+                       lbs_deb_thread("main-thread: Card Event Activity\n");
 
-                       adapter->hisregcpy &= ~his_cardevent;
+                       adapter->hisregcpy &= ~MRVDRV_CARDEVENT;
 
-                       if (libertas_sbi_read_event_cause(priv)) {
+                       if (priv->hw_read_event_cause(priv)) {
                                lbs_pr_alert(
-                                      "main-thread: libertas_sbi_read_event_cause failed.\n");
+                                      "main-thread: hw_read_event_cause failed\n");
                                spin_unlock_irq(&adapter->driver_lock);
                                continue;
                        }
@@ -806,15 +787,15 @@ static int wlan_service_main_thread(void *data)
 
                /* Check if we need to confirm Sleep Request received previously */
                if (adapter->psstate == PS_STATE_PRE_SLEEP) {
-                       if (!priv->wlan_dev.dnld_sent && !adapter->cur_cmd) {
+                       if (!priv->dnld_sent && !adapter->cur_cmd) {
                                if (adapter->connect_status ==
-                                   libertas_connected) {
-                                       lbs_pr_debug(1,
+                                   LIBERTAS_CONNECTED) {
+                                       lbs_deb_thread(
                                               "main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p "
                                               "dnld_sent=%d cur_cmd=%p, confirm now\n",
                                               adapter->intcounter,
                                               adapter->currenttxskb,
-                                              priv->wlan_dev.dnld_sent,
+                                              priv->dnld_sent,
                                               adapter->cur_cmd);
 
                                        libertas_ps_confirm_sleep(priv,
@@ -840,7 +821,7 @@ static int wlan_service_main_thread(void *data)
                        continue;
 
                /* Execute the next command */
-               if (!priv->wlan_dev.dnld_sent && !priv->adapter->cur_cmd)
+               if (!priv->dnld_sent && !priv->adapter->cur_cmd)
                        libertas_execute_next_command(priv);
 
                /* Wake-up command waiters which can't sleep in
@@ -855,93 +836,322 @@ static int wlan_service_main_thread(void *data)
        del_timer(&adapter->command_timer);
        adapter->nr_cmd_pending = 0;
        wake_up_all(&adapter->cmd_pending);
-       wlan_deactivate_thread(thread);
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_THREAD);
        return 0;
 }
 
 /**
+ *  @brief This function downloads firmware image, gets
+ *  HW spec from firmware and set basic parameters to
+ *  firmware.
+ *
+ *  @param priv    A pointer to wlan_private structure
+ *  @return       0 or -1
+ */
+static int wlan_setup_station_hw(wlan_private * priv)
+{
+       int ret = -1;
+       wlan_adapter *adapter = priv->adapter;
+
+       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
+        */
+       memset(adapter->current_addr, 0xff, ETH_ALEN);
+
+       ret = libertas_prepare_and_send_command(priv, CMD_GET_HW_SPEC,
+                                   0, CMD_OPTION_WAITFORRSP, 0, NULL);
+
+       if (ret) {
+               ret = -1;
+               goto done;
+       }
+
+       libertas_set_mac_packet_filter(priv);
+
+       /* Get the supported Data rates */
+       ret = libertas_prepare_and_send_command(priv, CMD_802_11_DATA_RATE,
+                                   CMD_ACT_GET_TX_RATE,
+                                   CMD_OPTION_WAITFORRSP, 0, NULL);
+
+       if (ret) {
+               ret = -1;
+               goto done;
+       }
+
+       ret = 0;
+done:
+       lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+       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.
+ */
+static void command_timer_fn(unsigned long data)
+{
+       wlan_private *priv = (wlan_private *)data;
+       wlan_adapter *adapter = priv->adapter;
+       struct cmd_ctrl_node *ptempnode;
+       struct cmd_ds_command *cmd;
+       unsigned long flags;
+
+       ptempnode = adapter->cur_cmd;
+       if (ptempnode == NULL) {
+               lbs_deb_fw("ptempnode empty\n");
+               return;
+       }
+
+       cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr;
+       if (!cmd) {
+               lbs_deb_fw("cmd is NULL\n");
+               return;
+       }
+
+       lbs_deb_fw("command_timer_fn fired, cmd %x\n", cmd->command);
+
+       if (!adapter->fw_ready)
+               return;
+
+       spin_lock_irqsave(&adapter->driver_lock, flags);
+       adapter->cur_cmd = NULL;
+       spin_unlock_irqrestore(&adapter->driver_lock, flags);
+
+       lbs_deb_fw("re-sending same command because of timeout\n");
+       libertas_queue_cmd(adapter, ptempnode, 0);
+
+       wake_up_interruptible(&priv->waitq);
+
+       return;
+}
+
+static void libertas_free_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;
+
+       /* 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;
+       }
+
+       /* Allocate the command buffers */
+       libertas_allocate_cmd_buffer(priv);
+
+       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);
+
+       /* scan type */
+       adapter->scantype = CMD_SCAN_TYPE_ACTIVE;
+
+       /* scan mode */
+       adapter->scanmode = CMD_BSS_TYPE_ANY;
+
+       /* 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->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->radioon = RADIO_ON;
+
+       adapter->auto_rate = 1;
+       adapter->cur_rate = 0;
+       adapter->adhoc_grate_enabled = 0;
+
+       adapter->beaconperiod = MRVDRV_BEACON_INTERVAL;
+
+       // set default capabilities
+       adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
+
+       adapter->psmode = WLAN802_11POWERMODECAM;
+
+       adapter->listeninterval = MRVDRV_DEFAULT_LISTEN_INTERVAL;
+
+       adapter->psstate = PS_STATE_FULL_POWER;
+       adapter->needtowakeup = 0;
+
+       adapter->intcounter = 0;
+
+       adapter->currenttxskb = NULL;
+
+       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;
+}
+
+static int libertas_init_fw(wlan_private * priv)
+{
+       int ret = -1;
+       wlan_adapter *adapter = priv->adapter;
+
+       lbs_deb_enter(LBS_DEB_FW);
+
+       /* Allocate adapter structure */
+       if ((ret = wlan_allocate_adapter(priv)) != 0)
+               goto done;
+
+       /* init adapter structure */
+       wlan_init_adapter(priv);
+
+       /* init timer etc. */
+       setup_timer(&adapter->command_timer, command_timer_fn,
+                       (unsigned long)priv);
+
+       /* download fimrware etc. */
+       if ((ret = wlan_setup_station_hw(priv)) != 0) {
+               del_timer_sync(&adapter->command_timer);
+               goto done;
+       }
+
+       /* init 802.11d */
+       libertas_init_11d(priv);
+
+       ret = 0;
+done:
+       lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+       return ret;
+}
+
+/**
  * @brief This function adds the card. it will probe the
  * card, allocate the wlan_priv and initialize the device.
  *
  *  @param card    A pointer to card
  *  @return       A pointer to wlan_private structure
  */
-wlan_private *wlan_add_card(void *card)
+wlan_private *libertas_add_card(void *card, struct device *dmdev)
 {
        struct net_device *dev = NULL;
-       struct net_device *mesh_dev = NULL;
        wlan_private *priv = NULL;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_NET);
 
        /* Allocate an Ethernet device and register it */
        if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
-               lbs_pr_alert( "Init ethernet device failed!\n");
+               lbs_pr_err("init ethX device failed\n");
                return NULL;
        }
-
        priv = dev->priv;
 
        /* allocate buffer for wlan_adapter */
-       if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
-               lbs_pr_alert( "Allocate buffer for wlan_adapter failed!\n");
-               goto err_kmalloc;
+       if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
+               lbs_pr_err("allocate buffer for wlan_adapter failed\n");
+               goto err_kzalloc;
        }
 
-       /* Allocate a virtual mesh device */
-       if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
-               lbs_pr_debug(1, "Init ethernet device failed!\n");
-               return NULL;
-       }
-
-       /* Both intervaces share the priv structure */
-       mesh_dev->priv = priv;
-
-       /* init wlan_adapter */
-       memset(priv->adapter, 0, sizeof(wlan_adapter));
-
-       priv->wlan_dev.netdev = dev;
-       priv->wlan_dev.card = card;
+       priv->dev = dev;
+       priv->card = card;
        priv->mesh_open = 0;
        priv->infra_open = 0;
-       priv->mesh_dev = mesh_dev;
-       wlanpriv = priv;
 
        SET_MODULE_OWNER(dev);
-       SET_MODULE_OWNER(mesh_dev);
 
        /* Setup the OS Interface to our functions */
-       dev->open = wlan_open;
-       dev->hard_start_xmit = wlan_pre_start_xmit;
-       dev->stop = wlan_close;
-       dev->do_ioctl = libertas_do_ioctl;
-       dev->set_mac_address = wlan_set_mac_address;
-       mesh_dev->open = mesh_open;
-       mesh_dev->hard_start_xmit = mesh_pre_start_xmit;
-       mesh_dev->stop = mesh_close;
-       mesh_dev->do_ioctl = libertas_do_ioctl;
-       memcpy(mesh_dev->dev_addr, wlanpriv->wlan_dev.netdev->dev_addr,
-                       sizeof(wlanpriv->wlan_dev.netdev->dev_addr));
-
-#define        WLAN_WATCHDOG_TIMEOUT   (5 * HZ)
-
-       dev->tx_timeout = wlan_tx_timeout;
-       dev->get_stats = wlan_get_stats;
-       dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT;
+       dev->open = libertas_open;
+       dev->hard_start_xmit = libertas_pre_start_xmit;
+       dev->stop = libertas_close;
+       dev->set_mac_address = libertas_set_mac_address;
+       dev->tx_timeout = libertas_tx_timeout;
+       dev->get_stats = libertas_get_stats;
+       dev->watchdog_timeo = 5 * HZ;
        dev->ethtool_ops = &libertas_ethtool_ops;
-       mesh_dev->get_stats = wlan_get_stats;
-       mesh_dev->ethtool_ops = &libertas_ethtool_ops;
-
 #ifdef WIRELESS_EXT
        dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
-       mesh_dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
 #endif
 #define NETIF_F_DYNALLOC 16
        dev->features |= NETIF_F_DYNALLOC;
        dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
-       dev->set_multicast_list = wlan_set_multicast_list;
+       dev->set_multicast_list = libertas_set_multicast_list;
+
+       SET_NETDEV_DEV(dev, dmdev);
 
        INIT_LIST_HEAD(&priv->adapter->cmdfreeq);
        INIT_LIST_HEAD(&priv->adapter->cmdpendingq);
@@ -949,85 +1159,153 @@ wlan_private *wlan_add_card(void *card)
        spin_lock_init(&priv->adapter->driver_lock);
        init_waitqueue_head(&priv->adapter->cmd_pending);
        priv->adapter->nr_cmd_pending = 0;
+       goto done;
 
-       lbs_pr_debug(1, "Starting kthread...\n");
-       priv->mainthread.priv = priv;
-       wlan_create_thread(wlan_service_main_thread,
-                          &priv->mainthread, "wlan_main_service");
+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)
+{
+       struct net_device *dev = priv->dev;
+       int ret = -1;
+
+       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;
+       }
 
        priv->assoc_thread =
                create_singlethread_workqueue("libertas_assoc");
-       INIT_DELAYED_WORK(&priv->assoc_work, wlan_association_worker);
+       INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
+       INIT_WORK(&priv->sync_channel, libertas_sync_channel);
 
        /*
         * Register the device. Fillup the private data structure with
         * relevant information from the card and request for the required
         * IRQ.
         */
-       if (libertas_sbi_register_dev(priv) < 0) {
-               lbs_pr_info("failed to register wlan device!\n");
+       if (priv->hw_register_dev(priv) < 0) {
+               lbs_pr_err("failed to register WLAN device\n");
                goto err_registerdev;
        }
 
        /* init FW and HW */
        if (libertas_init_fw(priv)) {
-               lbs_pr_debug(1, "Firmware Init failed\n");
+               lbs_pr_err("firmware init failed\n");
                goto err_registerdev;
        }
 
        if (register_netdev(dev)) {
-               lbs_pr_err("Cannot register network device!\n");
+               lbs_pr_err("cannot register ethX device\n");
                goto err_init_fw;
        }
 
-       /* Register virtual mesh interface */
-       if (register_netdev(mesh_dev)) {
-               lbs_pr_info("Cannot register mesh virtual interface!\n");
-               goto err_init_fw;
-       }
-
-       lbs_pr_info("%s: Marvell Wlan 802.11 adapter ", dev->name);
+       lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
 
        libertas_debugfs_init_one(priv, dev);
 
-       if (libertas_found == MAX_DEVS)
-               goto err_init_fw;
-       libertas_devs[libertas_found] = dev;
-       libertas_found++;
-#ifdef ENABLE_PM
-       if (!(wlan_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, wlan_pm_callback)))
-               lbs_pr_alert( "failed to register PM callback\n");
-#endif
-       if (class_device_create_file(&(mesh_dev->class_dev), &class_device_attr_libertas_mpp))
-               goto err_create_file;
+       ret = 0;
+       goto done;
 
-       LEAVE();
-       return priv;
-
-err_create_file:
-       class_device_remove_file(&(mesh_dev->class_dev), &class_device_attr_libertas_mpp);
 err_init_fw:
-       libertas_sbi_unregister_dev(priv);
+       priv->hw_unregister_dev(priv);
 err_registerdev:
        destroy_workqueue(priv->assoc_thread);
        /* Stop the thread servicing the interrupts */
-       wake_up_interruptible(&priv->mainthread.waitq);
-       wlan_terminate_thread(&priv->mainthread);
-       kfree(priv->adapter);
-err_kmalloc:
-       free_netdev(dev);
+       wake_up_interruptible(&priv->waitq);
+       kthread_stop(priv->main_thread);
+done:
+       lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(libertas_activate_card);
+
+
+/**
+ * @brief This function adds mshX interface
+ *
+ *  @param priv    A pointer to the wlan_private structure
+ *  @return       0 if successful, -X otherwise
+ */
+int libertas_add_mesh(wlan_private *priv, struct device *dev)
+{
+       struct net_device *mesh_dev = NULL;
+       int ret = 0;
+
+       lbs_deb_enter(LBS_DEB_MESH);
+
+       /* Allocate a virtual mesh device */
+       if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
+               lbs_deb_mesh("init mshX device failed\n");
+               ret = -ENOMEM;
+               goto done;
+       }
+       mesh_dev->priv = priv;
+       priv->mesh_dev = mesh_dev;
+
+       SET_MODULE_OWNER(mesh_dev);
+
+       mesh_dev->open = libertas_mesh_open;
+       mesh_dev->hard_start_xmit = libertas_mesh_pre_start_xmit;
+       mesh_dev->stop = libertas_mesh_close;
+       mesh_dev->get_stats = libertas_get_stats;
+       mesh_dev->set_mac_address = libertas_set_mac_address;
+       mesh_dev->ethtool_ops = &libertas_ethtool_ops;
+       memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
+                       sizeof(priv->dev->dev_addr));
+
+       SET_NETDEV_DEV(priv->mesh_dev, dev);
+
+#ifdef WIRELESS_EXT
+       mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
+#endif
+#define NETIF_F_DYNALLOC 16
+
+       /* Register virtual mesh interface */
+       ret = register_netdev(mesh_dev);
+       if (ret) {
+               lbs_pr_err("cannot register mshX virtual interface\n");
+               goto err_free;
+       }
+
+       ret = sysfs_create_group(&(mesh_dev->dev.kobj), &libertas_mesh_attr_group);
+       if (ret)
+               goto err_unregister;
+
+       /* Everything successful */
+       ret = 0;
+       goto done;
+
+err_unregister:
+       unregister_netdev(mesh_dev);
+
+err_free:
        free_netdev(mesh_dev);
-       wlanpriv = NULL;
 
-       LEAVE();
-       return NULL;
+done:
+       lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+       return ret;
 }
+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;
@@ -1037,87 +1315,89 @@ static void wake_pending_cmdnodes(wlan_private *priv)
 }
 
 
-int wlan_remove_card(void *card)
+int libertas_remove_card(wlan_private *priv)
 {
-       wlan_private *priv = libertas_sbi_get_priv(card);
        wlan_adapter *adapter;
        struct net_device *dev;
-       struct net_device *mesh_dev;
        union iwreq_data wrqu;
-       int i;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_NET);
 
-       if (!priv) {
-               LEAVE();
-               return 0;
-       }
+       if (!priv)
+               goto out;
 
        adapter = priv->adapter;
 
-       if (!adapter) {
-               LEAVE();
-               return 0;
-       }
+       if (!adapter)
+               goto out;
 
-       dev = priv->wlan_dev.netdev;
-       mesh_dev = priv->mesh_dev;
+       dev = priv->dev;
 
-       netif_stop_queue(mesh_dev);
-       netif_stop_queue(priv->wlan_dev.netdev);
-       netif_carrier_off(priv->wlan_dev.netdev);
+       netif_stop_queue(priv->dev);
+       netif_carrier_off(priv->dev);
 
        wake_pending_cmdnodes(priv);
 
-       class_device_remove_file(&(mesh_dev->class_dev), &class_device_attr_libertas_mpp);
-       unregister_netdev(mesh_dev);
        unregister_netdev(dev);
 
        cancel_delayed_work(&priv->assoc_work);
        destroy_workqueue(priv->assoc_thread);
 
-       if (adapter->psmode == wlan802_11powermodemax_psp) {
-               adapter->psmode = wlan802_11powermodecam;
-               libertas_ps_wakeup(priv, cmd_option_waitforrsp);
+       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->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
-
-#ifdef ENABLE_PM
-       pm_unregister(wlan_pm_dev);
-#endif
+       wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
 
        adapter->surpriseremoved = 1;
 
        /* Stop the thread servicing the interrupts */
-       wlan_terminate_thread(&priv->mainthread);
+       kthread_stop(priv->main_thread);
 
        libertas_debugfs_remove_one(priv);
 
-       lbs_pr_debug(1, "Free adapter\n");
+       lbs_deb_net("free adapter\n");
        libertas_free_adapter(priv);
 
-       for (i = 0; i<libertas_found; i++) {
-               if (libertas_devs[i]==priv->wlan_dev.netdev) {
-                       libertas_devs[i] = libertas_devs[--libertas_found];
-                       libertas_devs[libertas_found] = NULL ;
-                       break ;
-               }
-       }
+       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);
+
 
-       lbs_pr_debug(1, "Unregister finish\n");
+void libertas_remove_mesh(wlan_private *priv)
+{
+       struct net_device *mesh_dev;
+
+       lbs_deb_enter(LBS_DEB_NET);
+
+       if (!priv)
+               goto out;
+
+       mesh_dev = priv->mesh_dev;
+
+       netif_stop_queue(mesh_dev);
+       netif_carrier_off(priv->mesh_dev);
+
+       sysfs_remove_group(&(mesh_dev->dev.kobj), &libertas_mesh_attr_group);
+       unregister_netdev(mesh_dev);
 
-       priv->wlan_dev.netdev = NULL;
        priv->mesh_dev = NULL ;
        free_netdev(mesh_dev);
-       free_netdev(dev);
-       wlanpriv = NULL;
 
-       LEAVE();
-       return 0;
+out:
+       lbs_deb_leave(LBS_DEB_NET);
 }
+EXPORT_SYMBOL_GPL(libertas_remove_mesh);
 
 /**
  *  @brief This function finds the CFP in
@@ -1132,33 +1412,34 @@ struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *c
 {
        int i, end;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_MAIN);
 
        end = sizeof(region_cfp_table)/sizeof(struct region_cfp_table);
 
        for (i = 0; i < end ; i++) {
-               lbs_pr_debug(1, "region_cfp_table[i].region=%d\n",
+               lbs_deb_main("region_cfp_table[i].region=%d\n",
                        region_cfp_table[i].region);
                if (region_cfp_table[i].region == region) {
                        *cfp_no = region_cfp_table[i].cfp_no_BG;
-                       LEAVE();
+                       lbs_deb_leave(LBS_DEB_MAIN);
                        return region_cfp_table[i].cfp_BG;
                }
        }
 
-       LEAVE();
+       lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
        return NULL;
 }
 
 int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band)
 {
        wlan_adapter *adapter = priv->adapter;
+       int ret = 0;
        int i = 0;
 
        struct chan_freq_power *cfp;
        int cfp_no;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_MAIN);
 
        memset(adapter->region_channel, 0, sizeof(adapter->region_channel));
 
@@ -1168,17 +1449,19 @@ int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band)
                        adapter->region_channel[i].nrcfp = cfp_no;
                        adapter->region_channel[i].CFP = cfp;
                } else {
-                       lbs_pr_debug(1, "wrong region code %#x in band B-G\n",
+                       lbs_deb_main("wrong region code %#x in band B/G\n",
                               region);
-                       return -1;
+                       ret = -1;
+                       goto out;
                }
                adapter->region_channel[i].valid = 1;
                adapter->region_channel[i].region = region;
                adapter->region_channel[i].band = band;
                i++;
        }
-       LEAVE();
-       return 0;
+out:
+       lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+       return ret;
 }
 
 /**
@@ -1193,9 +1476,9 @@ void libertas_interrupt(struct net_device *dev)
 {
        wlan_private *priv = dev->priv;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_THREAD);
 
-       lbs_pr_debug(1, "libertas_interrupt: intcounter=%d\n",
+       lbs_deb_thread("libertas_interrupt: intcounter=%d\n",
               priv->adapter->intcounter);
 
        priv->adapter->intcounter++;
@@ -1203,56 +1486,50 @@ void libertas_interrupt(struct net_device *dev)
        if (priv->adapter->psstate == PS_STATE_SLEEP) {
                priv->adapter->psstate = PS_STATE_AWAKE;
                netif_wake_queue(dev);
+               if (priv->mesh_dev)
+                       netif_wake_queue(priv->mesh_dev);
        }
 
-       wake_up_interruptible(&priv->mainthread.waitq);
+       wake_up_interruptible(&priv->waitq);
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_THREAD);
 }
+EXPORT_SYMBOL_GPL(libertas_interrupt);
 
-static int wlan_init_module(void)
+int libertas_reset_device(wlan_private *priv)
 {
-       int ret = 0;
+       int ret;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_MAIN);
+       ret = libertas_prepare_and_send_command(priv, CMD_802_11_RESET,
+                                   CMD_ACT_HALT, 0, 0, NULL);
+       msleep_interruptible(10);
 
-       if (libertas_fw_name == NULL) {
-               libertas_fw_name = default_fw_name;
-       }
-
-       libertas_debugfs_init();
-
-       if (libertas_sbi_register()) {
-               ret = -1;
-               libertas_debugfs_remove();
-               goto done;
-       }
-
-done:
-       LEAVE();
+       lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
        return ret;
 }
+EXPORT_SYMBOL_GPL(libertas_reset_device);
 
-static void wlan_cleanup_module(void)
+static int libertas_init_module(void)
 {
-       int i;
-
-       ENTER();
+       lbs_deb_enter(LBS_DEB_MAIN);
+       libertas_debugfs_init();
+       lbs_deb_leave(LBS_DEB_MAIN);
+       return 0;
+}
 
-       for (i = 0; i<libertas_found; i++) {
-               wlan_private *priv = libertas_devs[i]->priv;
-               reset_device(priv);
-       }
+static void libertas_exit_module(void)
+{
+       lbs_deb_enter(LBS_DEB_MAIN);
 
-       libertas_sbi_unregister();
        libertas_debugfs_remove();
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_MAIN);
 }
 
-module_init(wlan_init_module);
-module_exit(wlan_cleanup_module);
+module_init(libertas_init_module);
+module_exit(libertas_exit_module);
 
-MODULE_DESCRIPTION("M-WLAN Driver");
+MODULE_DESCRIPTION("Libertas WLAN Driver Library");
 MODULE_AUTHOR("Marvell International Ltd.");
 MODULE_LICENSE("GPL");