Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / wireless / iwlwifi / iwl-core.c
index c4ff381..6b18aab 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/etherdevice.h>
+#include <linux/sched.h>
 #include <net/mac80211.h>
 
 #include "iwl-eeprom.h"
@@ -46,6 +47,37 @@ MODULE_VERSION(IWLWIFI_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
 MODULE_LICENSE("GPL");
 
+static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
+       {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
+        0, COEX_UNASSOC_IDLE_FLAGS},
+       {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP,
+        0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
+       {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP,
+        0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
+       {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP,
+        0, COEX_CALIBRATION_FLAGS},
+       {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP,
+        0, COEX_PERIODIC_CALIBRATION_FLAGS},
+       {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP,
+        0, COEX_CONNECTION_ESTAB_FLAGS},
+       {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP,
+        0, COEX_ASSOCIATED_IDLE_FLAGS},
+       {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP,
+        0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
+       {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP,
+        0, COEX_ASSOC_AUTO_SCAN_FLAGS},
+       {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP,
+        0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
+       {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS},
+       {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS},
+       {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP,
+        0, COEX_STAND_ALONE_DEBUG_FLAGS},
+       {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP,
+        0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
+       {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS},
+       {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS}
+};
+
 #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np)    \
        [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,      \
                                    IWL_RATE_SISO_##s##M_PLCP, \
@@ -1285,19 +1317,24 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
        struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
        struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
 
-       if (!le32_to_cpu(csa->status)) {
-               rxon->channel = csa->channel;
-               priv->staging_rxon.channel = csa->channel;
-               IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
-                     le16_to_cpu(csa->channel));
-       } else
-               IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
-                     le16_to_cpu(csa->channel));
+       if (priv->switch_rxon.switch_in_progress) {
+               if (!le32_to_cpu(csa->status) &&
+                   (csa->channel == priv->switch_rxon.channel)) {
+                       rxon->channel = csa->channel;
+                       priv->staging_rxon.channel = csa->channel;
+                       IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+                             le16_to_cpu(csa->channel));
+               } else
+                       IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+                             le16_to_cpu(csa->channel));
+
+               priv->switch_rxon.switch_in_progress = false;
+       }
 }
 EXPORT_SYMBOL(iwl_rx_csa);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
+void iwl_print_rx_config_cmd(struct iwl_priv *priv)
 {
        struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
 
@@ -1315,6 +1352,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
        IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
        IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
 }
+EXPORT_SYMBOL(iwl_print_rx_config_cmd);
 #endif
 /**
  * iwl_irq_handle_error - called for HW or SW error interrupt from card
@@ -2269,7 +2307,7 @@ static void iwl_ht_conf(struct iwl_priv *priv,
        switch (priv->iw_mode) {
        case NL80211_IFTYPE_STATION:
                rcu_read_lock();
-               sta = ieee80211_find_sta(priv->hw, priv->bssid);
+               sta = ieee80211_find_sta(priv->vif, priv->bssid);
                if (sta) {
                        struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
                        int maxstreams;
@@ -2279,12 +2317,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
                                        >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
                        maxstreams += 1;
 
-                       ht_conf->sm_ps =
-                               (u8)((ht_cap->cap & IEEE80211_HT_CAP_SM_PS)
-                               >> 2);
-                       IWL_DEBUG_MAC80211(priv, "sm_ps: 0x%x\n",
-                               ht_conf->sm_ps);
-
                        if ((ht_cap->mcs.rx_mask[1] == 0) &&
                            (ht_cap->mcs.rx_mask[2] == 0))
                                ht_conf->single_chain_sufficient = true;
@@ -2658,14 +2690,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
                        goto set_ch_out;
                }
 
-               if (iwl_is_associated(priv) &&
-                   (le16_to_cpu(priv->active_rxon.channel) != ch) &&
-                   priv->cfg->ops->lib->set_channel_switch) {
-                       ret = priv->cfg->ops->lib->set_channel_switch(priv,
-                               ch);
-                       goto out;
-               }
-
                spin_lock_irqsave(&priv->lock, flags);
 
                /* Configure HT40 channels */
@@ -2700,6 +2724,22 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 
                iwl_set_flags_for_band(priv, conf->channel->band);
                spin_unlock_irqrestore(&priv->lock, flags);
+               if (iwl_is_associated(priv) &&
+                   (le16_to_cpu(priv->active_rxon.channel) != ch) &&
+                   priv->cfg->ops->lib->set_channel_switch) {
+                       iwl_set_rate(priv);
+                       /*
+                        * at this point, staging_rxon has the
+                        * configuration for channel switch
+                        */
+                       ret = priv->cfg->ops->lib->set_channel_switch(priv,
+                               ch);
+                       if (!ret) {
+                               iwl_print_rx_config_cmd(priv);
+                               goto out;
+                       }
+                       priv->switch_rxon.switch_in_progress = false;
+               }
  set_ch_out:
                /* The list of supported rates and rate mask can be different
                 * for each band; since the band may have changed, reset
@@ -2865,6 +2905,34 @@ void iwl_free_txq_mem(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_free_txq_mem);
 
+int iwl_send_wimax_coex(struct iwl_priv *priv)
+{
+       struct iwl_wimax_coex_cmd uninitialized_var(coex_cmd);
+
+       if (priv->cfg->support_wimax_coexist) {
+               /* UnMask wake up src at associated sleep */
+               coex_cmd.flags |= COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
+
+               /* UnMask wake up src at unassociated sleep */
+               coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK;
+               memcpy(coex_cmd.sta_prio, cu_priorities,
+                       sizeof(struct iwl_wimax_coex_event_entry) *
+                        COEX_NUM_OF_EVENTS);
+
+               /* enabling the coexistence feature */
+               coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK;
+
+               /* enabling the priorities tables */
+               coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK;
+       } else {
+               /* coexistence is disabled */
+               memset(&coex_cmd, 0, sizeof(coex_cmd));
+       }
+       return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
+                               sizeof(coex_cmd), &coex_cmd);
+}
+EXPORT_SYMBOL(iwl_send_wimax_coex);
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 
 #define IWL_TRAFFIC_DUMP_SIZE  (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)