iwlwifi: rely on API version read from firmware
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl-agn.c
index 8fa4f7a2dc1a43319f473908660e10c2d274164f..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;
@@ -466,9 +393,9 @@ static u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
 
        /* Set rate mask*/
        if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
-               rate_mask = priv->active_rate_basic & 0xF;
+               rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
        else
-               rate_mask = priv->active_rate_basic & 0xFF0;
+               rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
 
        /* Find lowest valid rate */
        for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
@@ -1228,9 +1155,11 @@ void iwl_rx_handle(struct iwl_priv *priv)
 
                rxq->queue[i] = NULL;
 
-               pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->aligned_dma_addr,
-                                           priv->hw_params.rx_buf_size,
-                                           PCI_DMA_FROMDEVICE);
+               dma_sync_single_range_for_cpu(
+                               &priv->pci_dev->dev, rxb->real_dma_addr,
+                               rxb->aligned_dma_addr - rxb->real_dma_addr,
+                               priv->hw_params.rx_buf_size,
+                               PCI_DMA_FROMDEVICE);
                pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
                /* Reclaim a command buffer only if this packet is a response
@@ -1326,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)
 {
@@ -1341,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
  */
@@ -1492,7 +1399,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
                        hw_rf_kill = 1;
 
                IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
-                               hw_rf_kill ? "disable radio":"enable radio");
+                               hw_rf_kill ? "disable radio" : "enable radio");
 
                /* driver only loads ucode once setting the interface up.
                 * the driver as well won't allow loading if RFKILL is set
@@ -1606,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;
        }
 
@@ -1663,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)) {
@@ -1692,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",
@@ -2224,27 +2173,6 @@ static void iwl_bg_rf_kill(struct work_struct *work)
        iwl_rfkill_set_hw_state(priv);
 }
 
-static void iwl_bg_set_monitor(struct work_struct *work)
-{
-       struct iwl_priv *priv = container_of(work,
-                               struct iwl_priv, set_monitor);
-       int ret;
-
-       IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
-
-       mutex_lock(&priv->mutex);
-
-       ret = iwl_set_mode(priv, NL80211_IFTYPE_MONITOR);
-       if (ret) {
-               if (ret == -EAGAIN)
-                       IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
-               else
-                       IWL_ERROR("iwl_set_mode() failed ret = %d\n", ret);
-       }
-
-       mutex_unlock(&priv->mutex);
-}
-
 static void iwl_bg_run_time_calib_work(struct work_struct *work)
 {
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
@@ -2890,16 +2818,43 @@ static void iwl_configure_filter(struct ieee80211_hw *hw,
                                 int mc_count, struct dev_addr_list *mc_list)
 {
        struct iwl_priv *priv = hw->priv;
+       __le32 *filter_flags = &priv->staging_rxon.filter_flags;
+
+       IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
+                       changed_flags, *total_flags);
 
-       if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
-               IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
-                                  NL80211_IFTYPE_MONITOR,
-                                  changed_flags, *total_flags);
-               /* queue work 'cuz mac80211 is holding a lock which
-                * prevents us from issuing (synchronous) f/w cmds */
-               queue_work(priv->workqueue, &priv->set_monitor);
+       if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
+               if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
+                       *filter_flags |= RXON_FILTER_PROMISC_MSK;
+               else
+                       *filter_flags &= ~RXON_FILTER_PROMISC_MSK;
+       }
+       if (changed_flags & FIF_ALLMULTI) {
+               if (*total_flags & FIF_ALLMULTI)
+                       *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
+               else
+                       *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
+       }
+       if (changed_flags & FIF_CONTROL) {
+               if (*total_flags & FIF_CONTROL)
+                       *filter_flags |= RXON_FILTER_CTL2HOST_MSK;
+               else
+                       *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
+       }
+       if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+               if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+                       *filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
+               else
+                       *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
        }
-       *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
+
+       /* We avoid iwl_commit_rxon here to commit the new filter flags
+        * since mac80211 will call ieee80211_hw_config immediately.
+        * (mc_list is not supported at this time). Otherwise, we need to
+        * queue a background iwl_commit_rxon work.
+        */
+
+       *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
                        FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
 
@@ -3058,49 +3013,11 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
                        struct ieee80211_key_conf *keyconf, const u8 *addr,
                        u32 iv32, u16 *phase1key)
 {
-       struct iwl_priv *priv = hw->priv;
-       u8 sta_id = IWL_INVALID_STATION;
-       unsigned long flags;
-       __le16 key_flags = 0;
-       int i;
 
+       struct iwl_priv *priv = hw->priv;
        IWL_DEBUG_MAC80211("enter\n");
 
-       sta_id = iwl_find_station(priv, addr);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
-                                  addr);
-               return;
-       }
-
-       if (iwl_scan_cancel(priv)) {
-               /* cancel scan failed, just live w/ bad key and rely
-                  briefly on SW decryption */
-               return;
-       }
-
-       key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
-       key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-       key_flags &= ~STA_KEY_FLG_INVALID;
-
-       if (sta_id == priv->hw_params.bcast_sta_id)
-               key_flags |= STA_KEY_MULTICAST_MSK;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       priv->stations[sta_id].sta.key.key_flags = key_flags;
-       priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
-
-       for (i = 0; i < 5; i++)
-               priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
-                       cpu_to_le16(phase1key[i]);
-
-       priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-       priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-       iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
+       iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key);
 
        IWL_DEBUG_MAC80211("leave\n");
 }
@@ -3239,10 +3156,10 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
        switch (action) {
        case IEEE80211_AMPDU_RX_START:
                IWL_DEBUG_HT("start Rx\n");
-               return iwl_rx_agg_start(priv, sta->addr, tid, *ssn);
+               return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn);
        case IEEE80211_AMPDU_RX_STOP:
                IWL_DEBUG_HT("stop Rx\n");
-               return iwl_rx_agg_stop(priv, sta->addr, tid);
+               return iwl_sta_rx_agg_stop(priv, sta->addr, tid);
        case IEEE80211_AMPDU_TX_START:
                IWL_DEBUG_HT("start Tx\n");
                return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
@@ -3256,6 +3173,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
        }
        return 0;
 }
+
 static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
                                struct ieee80211_tx_queue_stats *stats)
 {
@@ -3694,7 +3612,8 @@ static ssize_t show_power_level(struct device *d,
                break;
        }
 
-       p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO)?"fixed":"auto");
+       p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
+                       "fixed" : "auto");
        p += sprintf(p, "\tINDEX:%d", level);
        p += sprintf(p, "\n");
        return p - buf + 1;
@@ -3703,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)
@@ -3832,7 +3689,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
        INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
        INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
        INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
-       INIT_WORK(&priv->set_monitor, iwl_bg_set_monitor);
        INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
        INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
        INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
@@ -3865,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,
@@ -4239,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.02988 seconds and 5 git commands to generate.