]> Pileus Git - ~andy/linux/blobdiff - drivers/net/wireless/iwlwifi/iwl4965-base.c
iwlwifi: fix bug to show hidden APs during scan
[~andy/linux] / drivers / net / wireless / iwlwifi / iwl4965-base.c
index f273395d4a3e4a2dbbf568caa6067bc74c1b956d..0b7335181719da86a8356f8e321903fefc90cf05 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2003 - 2008 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.
 
 #include <asm/div64.h>
 
+#include "iwl-eeprom.h"
+#include "iwl-core.h"
 #include "iwl-4965.h"
 #include "iwl-helpers.h"
 
-#ifdef CONFIG_IWL4965_DEBUG
-u32 iwl4965_debug_level;
-#endif
-
 static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
                                  struct iwl4965_tx_queue *txq);
 
@@ -90,15 +88,8 @@ int iwl4965_param_amsdu_size_8K;   /* def: enable 8K amsdu size */
 #define VS
 #endif
 
-#define IWLWIFI_VERSION "1.2.26k" VD VS
-#define DRV_COPYRIGHT  "Copyright(c) 2003-2007 Intel Corporation"
-#define DRV_VERSION     IWLWIFI_VERSION
+#define DRV_VERSION     IWLWIFI_VERSION VD VS
 
-/* Change firmware file name, using "-" and incrementing number,
- *   *only* when uCode interface or architecture changes so that it
- *   is not compatible with earlier drivers.
- * This number will also appear in << 8 position of 1st dword of uCode file */
-#define IWL4965_UCODE_API "-1"
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
 MODULE_VERSION(DRV_VERSION);
@@ -204,25 +195,6 @@ int iwl4965_queue_space(const struct iwl4965_queue *q)
        return s;
 }
 
-/**
- * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl4965_queue_inc_wrap(int index, int n_bd)
-{
-       return ++index & (n_bd - 1);
-}
-
-/**
- * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end
- * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
- */
-static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
-{
-       return --index & (n_bd - 1);
-}
 
 static inline int x2_queue_used(const struct iwl4965_queue *q, int i)
 {
@@ -251,8 +223,8 @@ static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q
        q->n_window = slots_num;
        q->id = id;
 
-       /* count must be power-of-two size, otherwise iwl4965_queue_inc_wrap
-        * and iwl4965_queue_dec_wrap are broken. */
+       /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
+        * and iwl_queue_dec_wrap are broken. */
        BUG_ON(!is_power_of_2(count));
 
        /* slots_num must be power-of-two size, otherwise
@@ -352,7 +324,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
        txq->need_update = 0;
 
        /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-        * iwl4965_queue_inc_wrap and iwl4965_queue_dec_wrap are broken. */
+        * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
        BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
 
        /* Initialize queue's high/low-water marks, and head/tail indexes */
@@ -383,7 +355,7 @@ void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *t
 
        /* first, empty all BD's */
        for (; q->write_ptr != q->read_ptr;
-            q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd))
+            q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
                iwl4965_hw_txq_free_tfd(priv, txq);
 
        len = sizeof(struct iwl4965_cmd) * q->n_window;
@@ -724,7 +696,7 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c
        ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0);
 
        /* Increment and update queue's write index */
-       q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
+       q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
        iwl4965_tx_queue_update_write_ptr(priv, txq);
 
        spin_unlock_irqrestore(&priv->hcmd_lock, flags);
@@ -1589,85 +1561,6 @@ static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
        return rc;
 }
 
-/******************************************************************************
- *
- * EEPROM related functions
- *
- ******************************************************************************/
-
-static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac)
-{
-       memcpy(mac, priv->eeprom.mac_address, 6);
-}
-
-static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
-{
-       iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-               CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-}
-
-/**
- * iwl4965_eeprom_init - read EEPROM contents
- *
- * Load the EEPROM contents from adapter into priv->eeprom
- *
- * NOTE:  This routine uses the non-debug IO access functions.
- */
-int iwl4965_eeprom_init(struct iwl4965_priv *priv)
-{
-       u16 *e = (u16 *)&priv->eeprom;
-       u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP);
-       u32 r;
-       int sz = sizeof(priv->eeprom);
-       int rc;
-       int i;
-       u16 addr;
-
-       /* The EEPROM structure has several padding buffers within it
-        * and when adding new EEPROM maps is subject to programmer errors
-        * which may be very difficult to identify without explicitly
-        * checking the resulting size of the eeprom map. */
-       BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
-
-       if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
-               IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
-               return -ENOENT;
-       }
-
-       /* Make sure driver (instead of uCode) is allowed to read EEPROM */
-       rc = iwl4965_eeprom_acquire_semaphore(priv);
-       if (rc < 0) {
-               IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
-               return -ENOENT;
-       }
-
-       /* eeprom is an array of 16bit values */
-       for (addr = 0; addr < sz; addr += sizeof(u16)) {
-               _iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1);
-               _iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
-
-               for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
-                                       i += IWL_EEPROM_ACCESS_DELAY) {
-                       r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG);
-                       if (r & CSR_EEPROM_REG_READ_VALID_MSK)
-                               break;
-                       udelay(IWL_EEPROM_ACCESS_DELAY);
-               }
-
-               if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
-                       IWL_ERROR("Time out reading EEPROM[%d]", addr);
-                       rc = -ETIMEDOUT;
-                       goto done;
-               }
-               e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
-       }
-       rc = 0;
-
-done:
-       iwl4965_eeprom_release_semaphore(priv);
-       return rc;
-}
-
 /******************************************************************************
  *
  * Misc. internal state and helper functions
@@ -2907,7 +2800,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
        iwl4965_tx_queue_update_wr_ptr(priv, txq, len);
 
        /* Tell device the write index *just past* this latest filled TFD */
-       q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
+       q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
        rc = iwl4965_tx_queue_update_write_ptr(priv, txq);
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -3301,9 +3194,9 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
                return 0;
        }
 
-       for (index = iwl4965_queue_inc_wrap(index, q->n_bd);
+       for (index = iwl_queue_inc_wrap(index, q->n_bd);
                q->read_ptr != index;
-               q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+               q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
                if (txq_id != IWL_CMD_QUEUE_NUM) {
                        iwl4965_txstatus_to_ieee(priv,
                                        &(txq->txb[txq->q.read_ptr]));
@@ -3548,7 +3441,7 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
 
                if (txq->q.read_ptr != (scd_ssn & 0xff)) {
                        int freed;
-                       index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
+                       index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
                        IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
                                           "%d index %d\n", scd_ssn , index);
                        freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
@@ -4918,9 +4811,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
         * atomic, make sure that inta covers all the interrupts that
         * we've discovered, even if FH interrupt came in just after
         * reading CSR_INT. */
-       if (inta_fh & CSR_FH_INT_RX_MASK)
+       if (inta_fh & CSR49_FH_INT_RX_MASK)
                inta |= CSR_INT_BIT_FH_RX;
-       if (inta_fh & CSR_FH_INT_TX_MASK)
+       if (inta_fh & CSR49_FH_INT_TX_MASK)
                inta |= CSR_INT_BIT_FH_TX;
 
        /* Now service all interrupt bits discovered above. */
@@ -5557,8 +5450,9 @@ static void iwl4965_init_hw_rates(struct iwl4965_priv *priv,
                        /*
                         * If CCK != 1M then set short preamble rate flag.
                         */
-                       rates[i].flags |= (iwl4965_rates[i].plcp == 10) ?
-                               0 : IEEE80211_RATE_SHORT_PREAMBLE;
+                       rates[i].flags |=
+                               (iwl4965_rates[i].plcp == IWL_RATE_1M_PLCP) ?
+                                       0 : IEEE80211_RATE_SHORT_PREAMBLE;
                }
        }
 }
@@ -5663,12 +5557,13 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv)
                                 geo_ch->flags);
        }
 
-       if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) {
+       if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
+            priv->cfg->sku & IWL_SKU_A) {
                printk(KERN_INFO DRV_NAME
                       ": Incorrectly detected BG card as ABG.  Please send "
                       "your PCI ID 0x%04X:0x%04X to maintainer.\n",
                       priv->pci_dev->device, priv->pci_dev->subsystem_device);
-               priv->is_abg = 0;
+               priv->cfg->sku &= ~IWL_SKU_A;
        }
 
        printk(KERN_INFO DRV_NAME
@@ -6017,7 +5912,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv)
        struct iwl4965_ucode *ucode;
        int ret;
        const struct firmware *ucode_raw;
-       const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode";
+       const char *name = priv->cfg->fw_name;
        u8 *src;
        size_t len;
        u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
@@ -6849,18 +6744,23 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
        if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
                scan->filter_flags = RXON_FILTER_PROMISC_MSK;
 
-       if (direct_mask)
+       if (direct_mask) {
                IWL_DEBUG_SCAN
                    ("Initiating direct scan for %s.\n",
                     iwl4965_escape_essid(priv->essid, priv->essid_len));
-       else
+               scan->channel_count =
+                       iwl4965_get_channels_for_scan(
+                               priv, band, 1, /* active */
+                               direct_mask,
+                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+       } else {
                IWL_DEBUG_SCAN("Initiating indirect scan.\n");
-
-       scan->channel_count =
-               iwl4965_get_channels_for_scan(
-                       priv, band, 1, /* active */
-                       direct_mask,
-                       (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+               scan->channel_count =
+                       iwl4965_get_channels_for_scan(
+                               priv, band, 0, /* passive */
+                               direct_mask,
+                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+       }
 
        cmd.len += le16_to_cpu(scan->tx_cmd.len) +
            scan->channel_count * sizeof(struct iwl4965_scan_channel);
@@ -7427,6 +7327,12 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
        if (conf == NULL)
                return -EIO;
 
+       if (priv->vif != vif) {
+               IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
+               mutex_unlock(&priv->mutex);
+               return 0;
+       }
+
        if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
            (!conf->beacon || !conf->ssid_len)) {
                IWL_DEBUG_MAC80211
@@ -7449,17 +7355,6 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
        if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
            !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
  */
-       if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
-               IWL_DEBUG_MAC80211("leave - scanning\n");
-               mutex_unlock(&priv->mutex);
-               return 0;
-       }
-
-       if (priv->vif != vif) {
-               IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
-               mutex_unlock(&priv->mutex);
-               return 0;
-       }
 
        if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
                if (!conf->bssid) {
@@ -8613,6 +8508,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        int err = 0;
        struct iwl4965_priv *priv;
        struct ieee80211_hw *hw;
+       struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
        int i;
        DECLARE_MAC_BUF(mac);
 
@@ -8646,6 +8542,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
        priv = hw->priv;
        priv->hw = hw;
+       priv->cfg = cfg;
 
        priv->pci_dev = pdev;
        priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna;
@@ -8748,8 +8645,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        /* Choose which receivers/antennas to use */
        iwl4965_set_rxon_chain(priv);
 
+
        printk(KERN_INFO DRV_NAME
-              ": Detected Intel Wireless WiFi Link 4965AGN\n");
+               ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
 
        /* Device-specific setup */
        if (iwl4965_hw_set_hw_setting(priv)) {
@@ -8795,13 +8693,13 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
                goto out_remove_sysfs;
         }
        /* Read the EEPROM */
-       err = iwl4965_eeprom_init(priv);
+       err = iwl_eeprom_init(priv);
        if (err) {
                IWL_ERROR("Unable to init EEPROM\n");
                goto out_remove_sysfs;
        }
        /* MAC Address location in EEPROM same for 3945/4965 */
-       get_eeprom_mac(priv, priv->mac_addr);
+       iwl_eeprom_get_mac(priv, priv->mac_addr);
        IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
        SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);