iwlwifi: add missing rcu_read_lock
[safe/jmp/linux-2.6] / drivers / net / wireless / libertas / main.c
index b0799e3..d9b8ee1 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/kfifo.h>
 #include <linux/stddef.h>
 #include <linux/ieee80211.h>
+#include <linux/slab.h>
 #include <net/iw_handler.h>
 #include <net/cfg80211.h>
 
@@ -123,7 +124,7 @@ static ssize_t lbs_rtap_set(struct device *dev,
                if (priv->monitormode == monitor_mode)
                        return strlen(buf);
                if (!priv->monitormode) {
-                       if (priv->infra_open || priv->mesh_open)
+                       if (priv->infra_open || lbs_mesh_open(priv))
                                return -EBUSY;
                        if (priv->mode == IW_MODE_INFRA)
                                lbs_cmd_80211_deauthenticate(priv,
@@ -228,7 +229,7 @@ static void lbs_tx_timeout(struct net_device *dev)
 
        lbs_pr_err("tx watch dog timeout\n");
 
-       dev->trans_start = jiffies;
+       dev->trans_start = jiffies; /* prevent tx timeout */
 
        if (priv->currenttxskb)
                lbs_send_tx_feedback(priv, 0);
@@ -318,28 +319,32 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
                               struct net_device *dev, int nr_addrs)
 {
        int i = nr_addrs;
-       struct dev_mc_list *mc_list;
+       struct netdev_hw_addr *ha;
+       int cnt;
 
        if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST))
                return nr_addrs;
 
        netif_addr_lock_bh(dev);
-       for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) {
-               if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) {
+       cnt = netdev_mc_count(dev);
+       netdev_for_each_mc_addr(ha, dev) {
+               if (mac_in_list(cmd->maclist, nr_addrs, ha->addr)) {
                        lbs_deb_net("mcast address %s:%pM skipped\n", dev->name,
-                                   mc_list->dmi_addr);
+                                   ha->addr);
+                       cnt--;
                        continue;
                }
 
                if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE)
                        break;
-               memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN);
+               memcpy(&cmd->maclist[6*i], ha->addr, ETH_ALEN);
                lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name,
-                           mc_list->dmi_addr);
+                           ha->addr);
                i++;
+               cnt--;
        }
        netif_addr_unlock_bh(dev);
-       if (mc_list)
+       if (cnt)
                return -EOVERFLOW;
 
        return i;
@@ -459,7 +464,7 @@ static int lbs_thread(void *data)
                else if (!list_empty(&priv->cmdpendingq) &&
                                        !(priv->wakeup_dev_required))
                        shouldsleep = 0;        /* We have a command to send */
-               else if (__kfifo_len(priv->event_fifo))
+               else if (kfifo_len(&priv->event_fifo))
                        shouldsleep = 0;        /* We have an event to process */
                else
                        shouldsleep = 1;        /* No command */
@@ -511,10 +516,13 @@ static int lbs_thread(void *data)
 
                /* Process hardware events, e.g. card removed, link lost */
                spin_lock_irq(&priv->driver_lock);
-               while (__kfifo_len(priv->event_fifo)) {
+               while (kfifo_len(&priv->event_fifo)) {
                        u32 event;
-                       __kfifo_get(priv->event_fifo, (unsigned char *) &event,
-                               sizeof(event));
+
+                       if (kfifo_out(&priv->event_fifo,
+                               (unsigned char *) &event, sizeof(event)) !=
+                               sizeof(event))
+                                       break;
                        spin_unlock_irq(&priv->driver_lock);
                        lbs_process_event(priv, event);
                        spin_lock_irq(&priv->driver_lock);
@@ -533,31 +541,14 @@ static int lbs_thread(void *data)
                if (priv->cmd_timed_out && priv->cur_cmd) {
                        struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
 
-                       if (++priv->nr_retries > 3) {
-                               lbs_pr_info("Excessive timeouts submitting "
-                                       "command 0x%04x\n",
-                                       le16_to_cpu(cmdnode->cmdbuf->command));
-                               lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
-                               priv->nr_retries = 0;
-                               if (priv->reset_card)
-                                       priv->reset_card(priv);
-                       } else {
-                               priv->cur_cmd = NULL;
-                               priv->dnld_sent = DNLD_RES_RECEIVED;
-                               lbs_pr_info("requeueing command 0x%04x due "
-                                       "to timeout (#%d)\n",
-                                       le16_to_cpu(cmdnode->cmdbuf->command),
-                                       priv->nr_retries);
-
-                               /* Stick it back at the _top_ of the pending queue
-                                  for immediate resubmission */
-                               list_add(&cmdnode->list, &priv->cmdpendingq);
-                       }
+                       lbs_pr_info("Timeout submitting command 0x%04x\n",
+                               le16_to_cpu(cmdnode->cmdbuf->command));
+                       lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
+                       if (priv->reset_card)
+                               priv->reset_card(priv);
                }
                priv->cmd_timed_out = 0;
 
-
-
                if (!priv->fw_ready)
                        continue;
 
@@ -619,7 +610,7 @@ static int lbs_thread(void *data)
                                if (priv->connect_status == LBS_CONNECTED)
                                        netif_wake_queue(priv->dev);
                                if (priv->mesh_dev &&
-                                   priv->mesh_connect_status == LBS_CONNECTED)
+                                   lbs_mesh_connected(priv))
                                        netif_wake_queue(priv->mesh_dev);
                        }
                }
@@ -729,7 +720,7 @@ done:
  *  This function handles the timeout of command sending.
  *  It will re-send the same command again.
  */
-static void command_timer_fn(unsigned long data)
+static void lbs_cmd_timeout_handler(unsigned long data)
 {
        struct lbs_private *priv = (struct lbs_private *)data;
        unsigned long flags;
@@ -833,24 +824,23 @@ static int lbs_init_adapter(struct lbs_private *priv)
        memset(priv->current_addr, 0xff, ETH_ALEN);
 
        priv->connect_status = LBS_DISCONNECTED;
-       priv->mesh_connect_status = LBS_DISCONNECTED;
        priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
        priv->mode = IW_MODE_INFRA;
        priv->channel = DEFAULT_AD_HOC_CHANNEL;
        priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
        priv->radio_on = 1;
        priv->enablehwauto = 1;
-       priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
        priv->psmode = LBS802_11POWERMODECAM;
        priv->psstate = PS_STATE_FULL_POWER;
        priv->is_deep_sleep = 0;
        priv->is_auto_deep_sleep_enabled = 0;
        priv->wakeup_dev_required = 0;
        init_waitqueue_head(&priv->ds_awake_q);
+       priv->authtype_auto = 1;
 
        mutex_init(&priv->lock);
 
-       setup_timer(&priv->command_timer, command_timer_fn,
+       setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
                (unsigned long)priv);
        setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
                        (unsigned long)priv);
@@ -871,10 +861,9 @@ static int lbs_init_adapter(struct lbs_private *priv)
        priv->resp_len[0] = priv->resp_len[1] = 0;
 
        /* Create the event FIFO */
-       priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL);
-       if (IS_ERR(priv->event_fifo)) {
+       ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL);
+       if (ret) {
                lbs_pr_err("Out of memory allocating event FIFO buffer\n");
-               ret = -ENOMEM;
                goto out;
        }
 
@@ -889,8 +878,7 @@ static void lbs_free_adapter(struct lbs_private *priv)
        lbs_deb_enter(LBS_DEB_MAIN);
 
        lbs_free_cmd_buffer(priv);
-       if (priv->event_fifo)
-               kfifo_free(priv->event_fifo);
+       kfifo_free(&priv->event_fifo);
        del_timer(&priv->command_timer);
        del_timer(&priv->auto_deepsleep_timer);
        kfree(priv->networks);
@@ -986,10 +974,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
        INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
        INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
 
-       priv->mesh_open = 0;
-       sprintf(priv->mesh_ssid, "mesh");
-       priv->mesh_ssid_len = 4;
-
        priv->wol_criteria = 0xffffffff;
        priv->wol_gpio = 0xff;
 
@@ -1062,6 +1046,17 @@ void lbs_remove_card(struct lbs_private *priv)
 EXPORT_SYMBOL_GPL(lbs_remove_card);
 
 
+static int lbs_rtap_supported(struct lbs_private *priv)
+{
+       if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
+               return 1;
+
+       /* newer firmware use a capability mask */
+       return ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) &&
+               (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK));
+}
+
+
 int lbs_start_card(struct lbs_private *priv)
 {
        struct net_device *dev = priv->dev;
@@ -1081,12 +1076,14 @@ int lbs_start_card(struct lbs_private *priv)
 
        lbs_update_channel(priv);
 
+       lbs_init_mesh(priv);
+
        /*
         * While rtap isn't related to mesh, only mesh-enabled
         * firmware implements the rtap functionality via
         * CMD_802_11_MONITOR_MODE.
         */
-       if (lbs_init_mesh(priv)) {
+       if (lbs_rtap_supported(priv)) {
                if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
                        lbs_pr_err("cannot register lbs_rtap attribute\n");
        }
@@ -1120,7 +1117,9 @@ void lbs_stop_card(struct lbs_private *priv)
        netif_carrier_off(dev);
 
        lbs_debugfs_remove_one(priv);
-       if (lbs_deinit_mesh(priv))
+       lbs_deinit_mesh(priv);
+
+       if (lbs_rtap_supported(priv))
                device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
 
        /* Delete the timeout of the currently processing command */
@@ -1164,7 +1163,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
        if (priv->psstate == PS_STATE_SLEEP)
                priv->psstate = PS_STATE_AWAKE;
 
-       __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32));
+       kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32));
 
        wake_up_interruptible(&priv->waitq);