iwlwifi: rely on API version read from firmware
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index 7888250117dc52f48553f4daf018fa85e386facf..b3c263d2724f936164d75fa81fa85aa1596c9c47 100644 (file)
@@ -107,79 +107,6 @@ static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
 
 }
 
-/**
- * iwl_check_rxon_cmd - validate RXON structure is valid
- *
- * NOTE:  This is really only useful during development and can eventually
- * be #ifdef'd out once the driver is stable and folks aren't actively
- * making changes
- */
-static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
-{
-       int error = 0;
-       int counter = 1;
-
-       if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
-               error |= le32_to_cpu(rxon->flags &
-                               (RXON_FLG_TGJ_NARROW_BAND_MSK |
-                                RXON_FLG_RADAR_DETECT_MSK));
-               if (error)
-                       IWL_WARNING("check 24G fields %d | %d\n",
-                                   counter++, error);
-       } else {
-               error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
-                               0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
-               if (error)
-                       IWL_WARNING("check 52 fields %d | %d\n",
-                                   counter++, error);
-               error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
-               if (error)
-                       IWL_WARNING("check 52 CCK %d | %d\n",
-                                   counter++, error);
-       }
-       error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
-       if (error)
-               IWL_WARNING("check mac addr %d | %d\n", counter++, error);
-
-       /* make sure basic rates 6Mbps and 1Mbps are supported */
-       error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
-                 ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
-       if (error)
-               IWL_WARNING("check basic rate %d | %d\n", counter++, error);
-
-       error |= (le16_to_cpu(rxon->assoc_id) > 2007);
-       if (error)
-               IWL_WARNING("check assoc id %d | %d\n", counter++, error);
-
-       error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
-                       == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
-       if (error)
-               IWL_WARNING("check CCK and short slot %d | %d\n",
-                           counter++, error);
-
-       error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
-                       == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
-       if (error)
-               IWL_WARNING("check CCK & auto detect %d | %d\n",
-                           counter++, error);
-
-       error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
-                       RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
-       if (error)
-               IWL_WARNING("check TGG and auto detect %d | %d\n",
-                           counter++, error);
-
-       if (error)
-               IWL_WARNING("Tuning to channel %d\n",
-                           le16_to_cpu(rxon->channel));
-
-       if (error) {
-               IWL_ERROR("Not a valid iwl_rxon_assoc_cmd field values\n");
-               return -1;
-       }
-       return 0;
-}
-
 /**
  * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
  * @priv: staging_rxon is compared to active_rxon
@@ -252,7 +179,7 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
         * 5000, but will not damage 4965 */
        priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
 
-       ret = iwl_check_rxon_cmd(&priv->staging_rxon);
+       ret = iwl_agn_check_rxon_cmd(&priv->staging_rxon);
        if (ret) {
                IWL_ERROR("Invalid RXON configuration.  Not committing.\n");
                return -EINVAL;
@@ -1328,13 +1255,6 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
 }
 #endif
 
-static void iwl_enable_interrupts(struct iwl_priv *priv)
-{
-       IWL_DEBUG_ISR("Enabling interrupts\n");
-       set_bit(STATUS_INT_ENABLED, &priv->status);
-       iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
-}
-
 /* call this function to flush any scheduled tasklet */
 static inline void iwl_synchronize_irq(struct iwl_priv *priv)
 {
@@ -1343,21 +1263,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
        tasklet_kill(&priv->irq_tasklet);
 }
 
-static inline void iwl_disable_interrupts(struct iwl_priv *priv)
-{
-       clear_bit(STATUS_INT_ENABLED, &priv->status);
-
-       /* disable interrupts from uCode/NIC to host */
-       iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
-       /* acknowledge/clear/reset any interrupts still pending
-        * from uCode or flow handler (Rx/Tx DMA) */
-       iwl_write32(priv, CSR_INT, 0xffffffff);
-       iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
-       IWL_DEBUG_ISR("Disabled interrupts\n");
-}
-
-
 /**
  * iwl_irq_handle_error - called for HW or SW error interrupt from card
  */
@@ -1608,7 +1513,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
        if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
                /* Hardware disappeared. It might have already raised
                 * an interrupt */
-               IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
+               IWL_WARNING("HARDWARE GONE?? INTA == 0x%08x\n", inta);
                goto unplugged;
        }
 
@@ -1665,24 +1570,40 @@ static void iwl_nic_start(struct iwl_priv *priv)
 static int iwl_read_ucode(struct iwl_priv *priv)
 {
        struct iwl_ucode *ucode;
-       int ret;
+       int ret = -EINVAL, index;
        const struct firmware *ucode_raw;
-       const char *name = priv->cfg->fw_name;
+       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 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+       u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
 
        /* Ask kernel firmware_class module to get the boot firmware off disk.
         * request_firmware() is synchronous, file is in memory on return. */
-       ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
-       if (ret < 0) {
-               IWL_ERROR("%s firmware file req failed: Reason %d\n",
-                                       name, ret);
-               goto error;
+       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_ERROR("%s firmware file req failed: Reason %d\n",
+                                 buf, ret);
+                       if (ret == -ENOENT)
+                               continue;
+                       else
+                               goto error;
+               } else {
+                       if (index < api_max)
+                               IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
+                                         buf, api_max);
+                       IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
+                                      buf, ucode_raw->size);
+                       break;
+               }
        }
 
-       IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
-                      name, ucode_raw->size);
+       if (ret < 0)
+               goto error;
 
        /* Make sure that we got at least our header! */
        if (ucode_raw->size < sizeof(*ucode)) {
@@ -1694,14 +1615,40 @@ static int iwl_read_ucode(struct iwl_priv *priv)
        /* Data from ucode file:  header followed by uCode images */
        ucode = (void *)ucode_raw->data;
 
-       ver = le32_to_cpu(ucode->ver);
+       priv->ucode_ver = le32_to_cpu(ucode->ver);
+       api_ver = IWL_UCODE_API(priv->ucode_ver);
        inst_size = le32_to_cpu(ucode->inst_size);
        data_size = le32_to_cpu(ucode->data_size);
        init_size = le32_to_cpu(ucode->init_size);
        init_data_size = le32_to_cpu(ucode->init_data_size);
        boot_size = le32_to_cpu(ucode->boot_size);
 
-       IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
+       /* api_ver should match the api version forming part of the
+        * firmware filename ... but we don't check for that and only rely
+        * on the API version read from firware header from here on forward */
+
+       if (api_ver < api_min || api_ver > api_max) {
+               IWL_ERROR("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;
+       }
+       if (api_ver != api_max)
+               IWL_ERROR("Firmware has old API version. Expected v%u, "
+                         "got v%u. New firmware can be obtained "
+                         "from http://www.intellinuxwireless.org.\n",
+                         api_max, api_ver);
+
+       printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n",
+                      IWL_UCODE_MAJOR(priv->ucode_ver),
+                      IWL_UCODE_MINOR(priv->ucode_ver),
+                      IWL_UCODE_API(priv->ucode_ver),
+                      IWL_UCODE_SERIAL(priv->ucode_ver));
+
+       IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
+                      priv->ucode_ver);
        IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n",
                       inst_size);
        IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n",
@@ -3675,68 +3622,6 @@ static ssize_t show_power_level(struct device *d,
 static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
                   store_power_level);
 
-static ssize_t show_channels(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       struct ieee80211_channel *channels = NULL;
-       const struct ieee80211_supported_band *supp_band = NULL;
-       int len = 0, i;
-       int count = 0;
-
-       if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
-               return -EAGAIN;
-
-       supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
-       channels = supp_band->channels;
-       count = supp_band->n_channels;
-
-       len += sprintf(&buf[len],
-                       "Displaying %d channels in 2.4GHz band "
-                       "(802.11bg):\n", count);
-
-       for (i = 0; i < count; i++)
-               len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-                               ieee80211_frequency_to_channel(
-                               channels[i].center_freq),
-                               channels[i].max_power,
-                               channels[i].flags & IEEE80211_CHAN_RADAR ?
-                               " (IEEE 802.11h required)" : "",
-                               (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS)
-                               || (channels[i].flags &
-                               IEEE80211_CHAN_RADAR)) ? "" :
-                               ", IBSS",
-                               channels[i].flags &
-                               IEEE80211_CHAN_PASSIVE_SCAN ?
-                               "passive only" : "active/passive");
-
-       supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
-       channels = supp_band->channels;
-       count = supp_band->n_channels;
-
-       len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
-                       "(802.11a):\n", count);
-
-       for (i = 0; i < count; i++)
-               len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-                               ieee80211_frequency_to_channel(
-                               channels[i].center_freq),
-                               channels[i].max_power,
-                               channels[i].flags & IEEE80211_CHAN_RADAR ?
-                               " (IEEE 802.11h required)" : "",
-                               ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
-                               || (channels[i].flags &
-                               IEEE80211_CHAN_RADAR)) ? "" :
-                               ", IBSS",
-                               channels[i].flags &
-                               IEEE80211_CHAN_PASSIVE_SCAN ?
-                               "passive only" : "active/passive");
-
-       return len;
-}
-
-static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
 
 static ssize_t show_statistics(struct device *d,
                               struct device_attribute *attr, char *buf)
@@ -3836,7 +3721,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
 }
 
 static struct attribute *iwl_sysfs_entries[] = {
-       &dev_attr_channels.attr,
        &dev_attr_flags.attr,
        &dev_attr_filter_flags.attr,
        &dev_attr_power_level.attr,
@@ -4210,7 +4094,11 @@ static struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)},
        {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)},
        {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)},
+/* 5150 Wifi/WiMax */
+       {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
+       {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
 #endif /* CONFIG_IWL5000 */
+
        {0}
 };
 MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
This page took 0.027748 seconds and 5 git commands to generate.