Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[safe/jmp/linux-2.6] / drivers / net / wireless / iwlwifi / iwl-agn.c
index 771b03c..bdff565 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
 #define VD
 #endif
 
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
-#define VS "s"
-#else
-#define VS
-#endif
-
-#define DRV_VERSION     IWLWIFI_VERSION VD VS
+#define DRV_VERSION     IWLWIFI_VERSION VD
 
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -203,7 +198,8 @@ int iwl_commit_rxon(struct iwl_priv *priv)
        priv->start_calib = 0;
 
        /* Add the broadcast address so we can send broadcast frames */
-       iwl_add_bcast_station(priv);
+       priv->cfg->ops->lib->add_bcast_station(priv);
+
 
        /* If we have set the ASSOC_MSK and we are in BSS mode then
         * add the IWL_AP_ID to the station rate table */
@@ -704,7 +700,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
        spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
 
-void iwl_continuous_event_trace(struct iwl_priv *priv)
+static void iwl_continuous_event_trace(struct iwl_priv *priv)
 {
        u32 capacity;   /* event log capacity in # entries */
        u32 base;       /* SRAM byte address of event log header */
@@ -888,6 +884,8 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
        priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
        priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
        priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
+       priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
+                       iwl_rx_spectrum_measure_notif;
        priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
        priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
            iwl_rx_pm_debug_statistics_notif;
@@ -901,7 +899,6 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
        priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics;
        priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
 
-       iwl_setup_spectrum_handlers(priv);
        iwl_setup_rx_scan_handlers(priv);
 
        /* status change handler */
@@ -1262,7 +1259,15 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
        /* Ack/clear/reset pending uCode interrupts.
         * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
         */
-       iwl_write32(priv, CSR_INT, priv->inta);
+       /* There is a hardware bug in the interrupt mask function that some
+        * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if
+        * they are disabled in the CSR_INT_MASK register. Furthermore the
+        * ICT interrupt handling mechanism has another bug that might cause
+        * these unmasked interrupts fail to be detected. We workaround the
+        * hardware bugs here by ACKing all the possible interrupts so that
+        * interrupt coalescing can still be achieved.
+        */
+       iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask);
 
        inta = priv->inta;
 
@@ -1467,59 +1472,66 @@ static void iwl_nic_start(struct iwl_priv *priv)
 }
 
 
+static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
+static int iwl_mac_setup_register(struct iwl_priv *priv);
+
+static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
+{
+       const char *name_pre = priv->cfg->fw_name_pre;
+
+       if (first)
+               priv->fw_index = priv->cfg->ucode_api_max;
+       else
+               priv->fw_index--;
+
+       if (priv->fw_index < priv->cfg->ucode_api_min) {
+               IWL_ERR(priv, "no suitable firmware found!\n");
+               return -ENOENT;
+       }
+
+       sprintf(priv->firmware_name, "%s%d%s",
+               name_pre, priv->fw_index, ".ucode");
+
+       IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n",
+                      priv->firmware_name);
+
+       return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
+                                      &priv->pci_dev->dev, GFP_KERNEL, priv,
+                                      iwl_ucode_callback);
+}
+
 /**
- * iwl_read_ucode - Read uCode images from disk file.
+ * iwl_ucode_callback - callback when firmware was loaded
  *
- * Copy into buffers for card to fetch via bus-mastering
+ * If loaded successfully, copies the firmware into buffers
+ * for the card to fetch (via DMA).
  */
-static int iwl_read_ucode(struct iwl_priv *priv)
+static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 {
+       struct iwl_priv *priv = context;
        struct iwl_ucode_header *ucode;
-       int ret = -EINVAL, index;
-       const struct firmware *ucode_raw;
-       const char *name_pre = priv->cfg->fw_name_pre;
        const unsigned int api_max = priv->cfg->ucode_api_max;
        const unsigned int api_min = priv->cfg->ucode_api_min;
-       char buf[25];
        u8 *src;
        size_t len;
        u32 api_ver, build;
        u32 inst_size, data_size, init_size, init_data_size, boot_size;
+       int err;
        u16 eeprom_ver;
 
-       /* Ask kernel firmware_class module to get the boot firmware off disk.
-        * request_firmware() is synchronous, file is in memory on return. */
-       for (index = api_max; index >= api_min; index--) {
-               sprintf(buf, "%s%d%s", name_pre, index, ".ucode");
-               ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
-               if (ret < 0) {
-                       IWL_ERR(priv, "%s firmware file req failed: %d\n",
-                                 buf, ret);
-                       if (ret == -ENOENT)
-                               continue;
-                       else
-                               goto error;
-               } else {
-                       if (index < api_max)
-                               IWL_ERR(priv, "Loaded firmware %s, "
-                                       "which is deprecated. "
-                                       "Please use API v%u instead.\n",
-                                         buf, api_max);
-
-                       IWL_DEBUG_INFO(priv, "Got firmware '%s' file (%zd bytes) from disk\n",
-                                      buf, ucode_raw->size);
-                       break;
-               }
+       if (!ucode_raw) {
+               IWL_ERR(priv, "request for firmware file '%s' failed.\n",
+                       priv->firmware_name);
+               goto try_again;
        }
 
-       if (ret < 0)
-               goto error;
+       IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
+                      priv->firmware_name, ucode_raw->size);
 
        /* Make sure that we got at least the v1 header! */
        if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
                IWL_ERR(priv, "File size way too small!\n");
-               ret = -EINVAL;
-               goto err_release;
+               goto try_again;
        }
 
        /* Data from ucode file:  header followed by uCode images */
@@ -1544,10 +1556,9 @@ static int iwl_read_ucode(struct iwl_priv *priv)
                IWL_ERR(priv, "Driver unable to support your firmware API. "
                          "Driver supports v%u, firmware is v%u.\n",
                          api_max, api_ver);
-               priv->ucode_ver = 0;
-               ret = -EINVAL;
-               goto err_release;
+               goto try_again;
        }
+
        if (api_ver != api_max)
                IWL_ERR(priv, "Firmware has old API version. Expected v%u, "
                          "got v%u. New firmware can be obtained "
@@ -1589,6 +1600,12 @@ static int iwl_read_ucode(struct iwl_priv *priv)
        IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n",
                       boot_size);
 
+       /*
+        * For any of the failures below (before allocating pci memory)
+        * we will try to load a version with a smaller API -- maybe the
+        * user just got a corrupted version of the latest API.
+        */
+
        /* Verify size of file vs. image size info in file's header */
        if (ucode_raw->size !=
                priv->cfg->ops->ucode->get_header_size(api_ver) +
@@ -1598,41 +1615,35 @@ static int iwl_read_ucode(struct iwl_priv *priv)
                IWL_DEBUG_INFO(priv,
                        "uCode file size %d does not match expected size\n",
                        (int)ucode_raw->size);
-               ret = -EINVAL;
-               goto err_release;
+               goto try_again;
        }
 
        /* Verify that uCode images will fit in card's SRAM */
        if (inst_size > priv->hw_params.max_inst_size) {
                IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
                               inst_size);
-               ret = -EINVAL;
-               goto err_release;
+               goto try_again;
        }
 
        if (data_size > priv->hw_params.max_data_size) {
                IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
                                data_size);
-               ret = -EINVAL;
-               goto err_release;
+               goto try_again;
        }
        if (init_size > priv->hw_params.max_inst_size) {
                IWL_INFO(priv, "uCode init instr len %d too large to fit in\n",
                        init_size);
-               ret = -EINVAL;
-               goto err_release;
+               goto try_again;
        }
        if (init_data_size > priv->hw_params.max_data_size) {
                IWL_INFO(priv, "uCode init data len %d too large to fit in\n",
                      init_data_size);
-               ret = -EINVAL;
-               goto err_release;
+               goto try_again;
        }
        if (boot_size > priv->hw_params.max_bsm_size) {
                IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n",
                        boot_size);
-               ret = -EINVAL;
-               goto err_release;
+               goto try_again;
        }
 
        /* Allocate ucode buffers for card's bus-master loading ... */
@@ -1716,20 +1727,36 @@ static int iwl_read_ucode(struct iwl_priv *priv)
        IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len);
        memcpy(priv->ucode_boot.v_addr, src, len);
 
+       /**************************************************
+        * This is still part of probe() in a sense...
+        *
+        * 9. Setup and register with mac80211 and debugfs
+        **************************************************/
+       err = iwl_mac_setup_register(priv);
+       if (err)
+               goto out_unbind;
+
+       err = iwl_dbgfs_register(priv, DRV_NAME);
+       if (err)
+               IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
+
        /* We have our copies now, allow OS release its copies */
        release_firmware(ucode_raw);
-       return 0;
+       return;
+
+ try_again:
+       /* try next, if any */
+       if (iwl_request_firmware(priv, false))
+               goto out_unbind;
+       release_firmware(ucode_raw);
+       return;
 
  err_pci_alloc:
        IWL_ERR(priv, "failed to allocate pci memory\n");
-       ret = -ENOMEM;
        iwl_dealloc_ucode_pci(priv);
-
- err_release:
+ out_unbind:
+       device_release_driver(&priv->pci_dev->dev);
        release_firmware(ucode_raw);
-
- error:
-       return ret;
 }
 
 static const char *desc_lookup_text[] = {
@@ -1761,7 +1788,7 @@ static const char *desc_lookup_text[] = {
        "DEBUG_1",
        "DEBUG_2",
        "DEBUG_3",
-       "UNKNOWN"
+       "ADVANCED SYSASSERT"
 };
 
 static const char *desc_lookup(int i)
@@ -1965,7 +1992,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
                IWL_ERR(priv,
                        "Invalid event log pointer 0x%08X for %s uCode\n",
                        base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
-               return pos;
+               return -EINVAL;
        }
 
        /* event log header */
@@ -2013,7 +2040,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
                        bufsz = size * 48;
                *buf = kmalloc(bufsz, GFP_KERNEL);
                if (!*buf)
-                       return pos;
+                       return -ENOMEM;
        }
        if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
                /*
@@ -2443,18 +2470,6 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
        return;
 }
 
-static void iwl_bg_up(struct work_struct *data)
-{
-       struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       mutex_lock(&priv->mutex);
-       __iwl_up(priv);
-       mutex_unlock(&priv->mutex);
-}
-
 static void iwl_bg_restart(struct work_struct *data)
 {
        struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
@@ -2471,7 +2486,13 @@ static void iwl_bg_restart(struct work_struct *data)
                ieee80211_restart_hw(priv->hw);
        } else {
                iwl_down(priv);
-               queue_work(priv->workqueue, &priv->up);
+
+               if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+                       return;
+
+               mutex_lock(&priv->mutex);
+               __iwl_up(priv);
+               mutex_unlock(&priv->mutex);
        }
 }
 
@@ -2607,7 +2628,7 @@ void iwl_post_associate(struct iwl_priv *priv)
  * Not a mac80211 entry point function, but it fits in with all the
  * other mac80211 functions grouped here.
  */
-static int iwl_setup_mac(struct iwl_priv *priv)
+static int iwl_mac_setup_register(struct iwl_priv *priv)
 {
        int ret;
        struct ieee80211_hw *hw = priv->hw;
@@ -2632,7 +2653,7 @@ static int iwl_setup_mac(struct iwl_priv *priv)
                BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC);
 
-       hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY |
+       hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
                            WIPHY_FLAG_DISABLE_BEACON_HINTS;
 
        /*
@@ -2677,21 +2698,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
 
        /* we should be verifying the device is ready to be opened */
        mutex_lock(&priv->mutex);
-
-       /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
-        * ucode filename and max sizes are card-specific. */
-
-       if (!priv->ucode_code.len) {
-               ret = iwl_read_ucode(priv);
-               if (ret) {
-                       IWL_ERR(priv, "Could not read microcode: %d\n", ret);
-                       mutex_unlock(&priv->mutex);
-                       return ret;
-               }
-       }
-
        ret = __iwl_up(priv);
-
        mutex_unlock(&priv->mutex);
 
        if (ret)
@@ -2839,14 +2846,18 @@ void iwl_config_ap(struct iwl_priv *priv)
 }
 
 static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
-                       struct ieee80211_key_conf *keyconf, const u8 *addr,
-                       u32 iv32, u16 *phase1key)
+                                   struct ieee80211_vif *vif,
+                                   struct ieee80211_key_conf *keyconf,
+                                   struct ieee80211_sta *sta,
+                                   u32 iv32, u16 *phase1key)
 {
 
        struct iwl_priv *priv = hw->priv;
        IWL_DEBUG_MAC80211(priv, "enter\n");
 
-       iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key);
+       iwl_update_tkip_key(priv, keyconf,
+                           sta ? sta->addr : iwl_bcast_addr,
+                           iv32, phase1key);
 
        IWL_DEBUG_MAC80211(priv, "leave\n");
 }
@@ -2955,6 +2966,9 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
                        return 0;
                else
                        return ret;
+       case IEEE80211_AMPDU_TX_OPERATIONAL:
+               /* do nothing */
+               return -EOPNOTSUPP;
        default:
                IWL_DEBUG_HT(priv, "unknown\n");
                return -EINVAL;
@@ -3004,6 +3018,8 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
                break;
        case STA_NOTIFY_AWAKE:
                WARN_ON(!sta_priv->client);
+               if (!sta_priv->asleep)
+                       break;
                sta_priv->asleep = false;
                sta_id = iwl_find_station(priv, sta->addr);
                if (sta_id != IWL_INVALID_STATION)
@@ -3280,7 +3296,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 
        init_waitqueue_head(&priv->wait_command_queue);
 
-       INIT_WORK(&priv->up, iwl_bg_up);
        INIT_WORK(&priv->restart, iwl_bg_restart);
        INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
        INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
@@ -3316,6 +3331,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
 
        cancel_delayed_work_sync(&priv->init_alive_start);
        cancel_delayed_work(&priv->scan_check);
+       cancel_work_sync(&priv->start_internal_scan);
        cancel_delayed_work(&priv->alive_start);
        cancel_work_sync(&priv->beacon_update);
        del_timer_sync(&priv->statistics_periodic);
@@ -3355,6 +3371,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
        INIT_LIST_HEAD(&priv->free_frames);
 
        mutex_init(&priv->mutex);
+       mutex_init(&priv->sync_cmd_mutex);
 
        /* Clear the driver's (not device's) station table */
        iwl_clear_stations_table(priv);
@@ -3365,6 +3382,13 @@ static int iwl_init_drv(struct iwl_priv *priv)
 
        priv->iw_mode = NL80211_IFTYPE_STATION;
        priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
+       priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
+
+       /* initialize force reset */
+       priv->force_reset[IWL_RF_RESET].reset_duration =
+               IWL_DELAY_NEXT_FORCE_RF_RESET;
+       priv->force_reset[IWL_FW_RESET].reset_duration =
+               IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
        /* Choose which receivers/antennas to use */
        if (priv->cfg->ops->hcmd->set_rxon_chain)
@@ -3441,7 +3465,6 @@ static struct ieee80211_ops iwl_hw_ops = {
        .set_key = iwl_mac_set_key,
        .update_tkip_key = iwl_mac_update_tkip_key,
        .get_stats = iwl_mac_get_stats,
-       .get_tx_stats = iwl_mac_get_tx_stats,
        .conf_tx = iwl_mac_conf_tx,
        .reset_tsf = iwl_mac_reset_tsf,
        .bss_info_changed = iwl_bss_info_changed,
@@ -3542,6 +3565,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         */
        spin_lock_init(&priv->reg_lock);
        spin_lock_init(&priv->lock);
+
+       /*
+        * stop and reset the on-board processor just in case it is in a
+        * strange state ... like being left stranded by a primary kernel
+        * and this is now the kdump kernel trying to start up
+        */
+       iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
        iwl_hw_detect(priv);
        IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
                priv->cfg->name, priv->hw_rev);
@@ -3616,9 +3647,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        iwl_setup_deferred_work(priv);
        iwl_setup_rx_handlers(priv);
 
-       /**********************************
-        * 8. Setup and register mac80211
-        **********************************/
+       /*********************************************
+        * 8. Enable interrupts and read RFKILL state
+        *********************************************/
 
        /* enable interrupts if needed: hw bug w/a */
        pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
@@ -3629,14 +3660,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        iwl_enable_interrupts(priv);
 
-       err = iwl_setup_mac(priv);
-       if (err)
-               goto out_remove_sysfs;
-
-       err = iwl_dbgfs_register(priv, DRV_NAME);
-       if (err)
-               IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
-
        /* If platform's RF_KILL switch is NOT set to KILL */
        if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -3648,6 +3671,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        iwl_power_initialize(priv);
        iwl_tt_initialize(priv);
+
+       err = iwl_request_firmware(priv, true);
+       if (err)
+               goto out_remove_sysfs;
+
        return 0;
 
  out_remove_sysfs:
@@ -3766,7 +3794,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
  *****************************************************************************/
 
 /* Hardware specific file defines the PCI IDs table for that hardware module */
-static struct pci_device_id iwl_hw_card_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 #ifdef CONFIG_IWL4965
        {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
        {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},