Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[sfrench/cifs-2.6.git] / drivers / net / wireless / libertas / main.c
index dcbf102a057e79895fdf4e662fcc5bc412ab5a92..4a59306a3f05feb9d7f31f4273bc3a549ff9cf3f 100644 (file)
@@ -4,6 +4,7 @@
   * thread etc..
   */
 
+#include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.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.p0"
+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 */
@@ -138,14 +148,6 @@ static struct region_cfp_table region_cfp_table[] = {
 /*Add new region here */
 };
 
-/**
- * the rates supported by the card
- */
-u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] =
-    { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
-       0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
-};
-
 /**
  * the rates supported
  */
@@ -165,67 +167,58 @@ u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES] =
  */
 u8 libertas_adhoc_rates_b[4] = { 0x82, 0x84, 0x8b, 0x96 };
 
-/**
- * the global variable of a pointer to wlan_private
- * structure variable
- */
-static wlan_private *wlanpriv = NULL;
-
-#define MAX_DEVS 5
-static struct net_device *libertas_devs[MAX_DEVS];
-static int libertas_found = 0;
-
 /**
  * the table to keep region code
  */
 u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
     { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
 
-static u8 *default_fw_name = "usb8388.bin";
-
 /**
  * Attributes exported through sysfs
  */
 
 /**
- * @brief Get function for sysfs attribute libertas_mpp
+ * @brief Get function for sysfs attribute anycast_mask
  */
-static ssize_t libertas_mpp_get(struct device * dev,
-               struct device_attribute *attr, 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_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 device * dev,
-               struct device_attribute *attr, 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_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 DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get,
-               libertas_mpp_set );
+static DEVICE_ATTR(anycast_mask, 0644, libertas_anycast_get, libertas_anycast_set);
 
 /**
  *  @brief Check if the device can be open and wait if necessary.
@@ -238,7 +231,8 @@ static 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 +242,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;
        }
 
@@ -267,17 +260,19 @@ static int wlan_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);
+               netif_carrier_on(priv->dev);
+               netif_carrier_on(priv->mesh_dev);
+       } else {
+               netif_carrier_off(priv->dev);
+               netif_carrier_off(priv->mesh_dev);
+       }
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_NET);
        return 0;
 }
 /**
@@ -290,12 +285,12 @@ static int 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 wlan_dev_open(priv->dev) ;
        return 0;
 }
 
@@ -312,9 +307,9 @@ static int wlan_open(struct net_device *dev)
        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 wlan_dev_open(priv->dev) ;
        return 0;
 }
 
@@ -322,12 +317,12 @@ static int wlan_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;
 }
 
@@ -344,7 +339,7 @@ static int mesh_close(struct net_device *dev)
        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 wlan_dev_close(dev);
        else
                return 0;
 }
@@ -355,147 +350,38 @@ 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 wlan_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 wlan_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)
 {
        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);
+       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;
 }
 
@@ -506,33 +392,43 @@ done:
 static int 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 = wlan_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
  *
  */
-static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) {
-       ENTER();
+static int wlan_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 = wlan_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)
 {
        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) {
@@ -543,10 +439,12 @@ static void wlan_tx_timeout(struct net_device *dev)
                        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);
+       } else if (priv->adapter->connect_status == libertas_connected) {
+               netif_wake_queue(priv->dev);
+               netif_wake_queue(priv->mesh_dev);
+       }
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_TX);
 }
 
 /**
@@ -569,7 +467,10 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr)
        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);
 
@@ -584,17 +485,18 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr)
                                    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);
        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;
 }
 
@@ -619,12 +521,12 @@ static void wlan_set_multicast_list(struct net_device *dev)
        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;
                adapter->currentpacketfilter &=
@@ -637,7 +539,7 @@ static void wlan_set_multicast_list(struct net_device *dev)
 
                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;
                        adapter->currentpacketfilter &=
@@ -647,8 +549,8 @@ static void wlan_set_multicast_list(struct net_device *dev)
                            ~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;
                        } else {
@@ -660,12 +562,12 @@ static void wlan_set_multicast_list(struct net_device *dev)
                                adapter->nr_of_multicastmacaddr =
                                    wlan_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,7 +575,7 @@ 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,
@@ -686,13 +588,13 @@ 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
@@ -705,26 +607,26 @@ static int wlan_service_main_thread(void *data)
        wait_queue_t wait;
        u8 ireg = 0;
 
-       ENTER();
+       lbs_deb_enter(LBS_DEB_THREAD);
 
        wlan_activate_thread(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);
                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 +636,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);
                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 +663,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,14 +674,14 @@ 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");
+                       lbs_deb_thread("main-thread: cmd response ready\n");
 
                        adapter->hisregcpy &= ~his_cmdupldrdy;
                        spin_unlock_irq(&adapter->driver_lock);
@@ -789,13 +691,13 @@ static int wlan_service_main_thread(void *data)
 
                /* Any Card Event */
                if (adapter->hisregcpy & his_cardevent) {
-                       lbs_pr_debug(1, "main-thread: Card Event Activity.\n");
+                       lbs_deb_thread("main-thread: Card Event Activity\n");
 
                        adapter->hisregcpy &= ~his_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 +708,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,
+                                       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 +742,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
@@ -857,7 +759,7 @@ static int wlan_service_main_thread(void *data)
        wake_up_all(&adapter->cmd_pending);
        wlan_deactivate_thread(thread);
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_THREAD);
        return 0;
 }
 
@@ -868,166 +770,203 @@ static int wlan_service_main_thread(void *data)
  *  @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;
-       }
-
-       /* 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;
+       if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
+               lbs_pr_err("allocate buffer for wlan_adapter failed\n");
+               goto err_kzalloc;
        }
 
-       /* 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->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;
 
+       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;
+       goto done;
+
+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);
 
-       lbs_pr_debug(1, "Starting kthread...\n");
+int libertas_activate_card(wlan_private *priv, char *fw_name)
+{
+       struct net_device *dev = priv->dev;
+       int ret = -1;
+
+       lbs_deb_enter(LBS_DEB_MAIN);
+
+       lbs_deb_thread("Starting kthread...\n");
        priv->mainthread.priv = priv;
        wlan_create_thread(wlan_service_main_thread,
                           &priv->mainthread, "wlan_main_service");
 
        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");
+       if (fw_name && libertas_init_fw(priv, fw_name)) {
+               lbs_pr_err("firmware init failed\n");
                goto err_registerdev;
        }
 
        if (register_netdev(dev)) {
-               lbs_pr_err("Cannot register network device!\n");
-               goto err_init_fw;
-       }
-
-       /* Register virtual mesh interface */
-       if (register_netdev(mesh_dev)) {
-               lbs_pr_info("Cannot register mesh virtual interface!\n");
+               lbs_pr_err("cannot register ethX device\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 (device_create_file(&(mesh_dev->dev), &dev_attr_libertas_mpp))
-               goto err_create_file;
+       ret = 0;
+       goto done;
 
-       LEAVE();
-       return priv;
-
-err_create_file:
-       device_remove_file(&(mesh_dev->dev), &dev_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);
+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 = mesh_open;
+       mesh_dev->hard_start_xmit = mesh_pre_start_xmit;
+       mesh_dev->stop = mesh_close;
+       mesh_dev->get_stats = wlan_get_stats;
+       mesh_dev->set_mac_address = wlan_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 = device_create_file(&(mesh_dev->dev), &dev_attr_anycast_mask);
+       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_CMD);
+
        spin_lock_irqsave(&priv->adapter->driver_lock, flags);
        list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {
                cmdnode->cmdwaitqwoken = 1;
@@ -1037,40 +976,29 @@ 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);
 
-       device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp);
-       unregister_netdev(mesh_dev);
        unregister_netdev(dev);
 
        cancel_delayed_work(&priv->assoc_work);
@@ -1083,11 +1011,7 @@ int wlan_remove_card(void *card)
 
        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;
 
@@ -1096,28 +1020,45 @@ int wlan_remove_card(void *card)
 
        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);
+
+
+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);
 
-       lbs_pr_debug(1, "Unregister finish\n");
+       device_remove_file(&(mesh_dev->dev), &dev_attr_anycast_mask);
+       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 +1073,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 +1110,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 +1137,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 +1147,35 @@ void libertas_interrupt(struct net_device *dev)
        if (priv->adapter->psstate == PS_STATE_SLEEP) {
                priv->adapter->psstate = PS_STATE_AWAKE;
                netif_wake_queue(dev);
+               netif_wake_queue(priv->mesh_dev);
        }
 
        wake_up_interruptible(&priv->mainthread.waitq);
 
-       LEAVE();
+       lbs_deb_leave(LBS_DEB_THREAD);
 }
+EXPORT_SYMBOL_GPL(libertas_interrupt);
 
-static int wlan_init_module(void)
+static int libertas_init_module(void)
 {
-       int ret = 0;
-
-       ENTER();
-
-       if (libertas_fw_name == NULL) {
-               libertas_fw_name = default_fw_name;
-       }
-
+       lbs_deb_enter(LBS_DEB_MAIN);
        libertas_debugfs_init();
-
-       if (libertas_sbi_register()) {
-               ret = -1;
-               libertas_debugfs_remove();
-               goto done;
-       }
-
-done:
-       LEAVE();
-       return ret;
+       lbs_deb_leave(LBS_DEB_MAIN);
+       return 0;
 }
 
-static void wlan_cleanup_module(void)
+static void libertas_exit_module(void)
 {
-       int i;
-
-       ENTER();
-
-       for (i = 0; i<libertas_found; i++) {
-               wlan_private *priv = libertas_devs[i]->priv;
-               reset_device(priv);
-       }
+       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");