aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAbhijeet Kolekar <abhijeet.kolekar@intel.com>2009-04-08 14:26:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:54:41 -0400
commit5bbe233b9bafabc08a5404d54b9fa086e8390fc7 (patch)
treef0a4a015d2429d9b2aac4c198543e483494d9214 /drivers/net
parentde2b3e864aa908e613dd9912def88af7877d85f3 (diff)
iwl3945: use iwl_bss_info_changed
3945 can use iwl_bss_info_changed. A new lib op is created for post_assoicate to distinguish between 3945 and iwlwifi's post_associate operations. Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c50
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c138
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c136
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c116
8 files changed, 204 insertions, 247 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 2399328e8de7..519e8922d9f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -1964,6 +1964,50 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
1964 return 0; 1964 return 0;
1965} 1965}
1966 1966
1967static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
1968{
1969 int rc = 0;
1970 struct iwl_rx_packet *res = NULL;
1971 struct iwl3945_rxon_assoc_cmd rxon_assoc;
1972 struct iwl_host_cmd cmd = {
1973 .id = REPLY_RXON_ASSOC,
1974 .len = sizeof(rxon_assoc),
1975 .meta.flags = CMD_WANT_SKB,
1976 .data = &rxon_assoc,
1977 };
1978 const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
1979 const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
1980
1981 if ((rxon1->flags == rxon2->flags) &&
1982 (rxon1->filter_flags == rxon2->filter_flags) &&
1983 (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
1984 (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
1985 IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n");
1986 return 0;
1987 }
1988
1989 rxon_assoc.flags = priv->staging_rxon.flags;
1990 rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
1991 rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
1992 rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
1993 rxon_assoc.reserved = 0;
1994
1995 rc = iwl_send_cmd_sync(priv, &cmd);
1996 if (rc)
1997 return rc;
1998
1999 res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
2000 if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
2001 IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
2002 rc = -EIO;
2003 }
2004
2005 priv->alloc_rxb_skb--;
2006 dev_kfree_skb_any(cmd.meta.u.skb);
2007
2008 return rc;
2009}
2010
1967/* will add 3945 channel switch cmd handling later */ 2011/* will add 3945 channel switch cmd handling later */
1968int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) 2012int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1969{ 2013{
@@ -2729,6 +2773,10 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
2729 return 0; 2773 return 0;
2730} 2774}
2731 2775
2776static struct iwl_hcmd_ops iwl3945_hcmd = {
2777 .rxon_assoc = iwl3945_send_rxon_assoc,
2778};
2779
2732static struct iwl_lib_ops iwl3945_lib = { 2780static struct iwl_lib_ops iwl3945_lib = {
2733 .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, 2781 .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
2734 .txq_free_tfd = iwl3945_hw_txq_free_tfd, 2782 .txq_free_tfd = iwl3945_hw_txq_free_tfd,
@@ -2758,6 +2806,7 @@ static struct iwl_lib_ops iwl3945_lib = {
2758 }, 2806 },
2759 .send_tx_power = iwl3945_send_tx_power, 2807 .send_tx_power = iwl3945_send_tx_power,
2760 .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, 2808 .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
2809 .post_associate = iwl3945_post_associate,
2761}; 2810};
2762 2811
2763static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { 2812static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
@@ -2767,6 +2816,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
2767 2816
2768static struct iwl_ops iwl3945_ops = { 2817static struct iwl_ops iwl3945_ops = {
2769 .lib = &iwl3945_lib, 2818 .lib = &iwl3945_lib,
2819 .hcmd = &iwl3945_hcmd,
2770 .utils = &iwl3945_hcmd_utils, 2820 .utils = &iwl3945_hcmd_utils,
2771}; 2821};
2772 2822
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 29bc0d2656bc..13b191f155ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -276,7 +276,7 @@ extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
276 struct iwl_rx_mem_buffer *rxb); 276 struct iwl_rx_mem_buffer *rxb);
277extern void iwl3945_disable_events(struct iwl_priv *priv); 277extern void iwl3945_disable_events(struct iwl_priv *priv);
278extern int iwl4965_get_temperature(const struct iwl_priv *priv); 278extern int iwl4965_get_temperature(const struct iwl_priv *priv);
279 279extern void iwl3945_post_associate(struct iwl_priv *priv);
280/** 280/**
281 * iwl3945_hw_find_station - Find station id for a given BSSID 281 * iwl3945_hw_find_station - Find station id for a given BSSID
282 * @bssid: MAC address of station ID to find 282 * @bssid: MAC address of station ID to find
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 847a6220c5e6..37544afbebe6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2324,6 +2324,7 @@ static struct iwl_lib_ops iwl4965_lib = {
2324 .send_tx_power = iwl4965_send_tx_power, 2324 .send_tx_power = iwl4965_send_tx_power,
2325 .update_chain_flags = iwl_update_chain_flags, 2325 .update_chain_flags = iwl_update_chain_flags,
2326 .temperature = iwl4965_temperature_calib, 2326 .temperature = iwl4965_temperature_calib,
2327 .post_associate = iwl_post_associate,
2327}; 2328};
2328 2329
2329static struct iwl_ops iwl4965_ops = { 2330static struct iwl_ops iwl4965_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index e5ca2511a81a..837dbad80e5e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1527,6 +1527,7 @@ struct iwl_lib_ops iwl5000_lib = {
1527 .calib_version = iwl5000_eeprom_calib_version, 1527 .calib_version = iwl5000_eeprom_calib_version,
1528 .query_addr = iwl5000_eeprom_query_addr, 1528 .query_addr = iwl5000_eeprom_query_addr,
1529 }, 1529 },
1530 .post_associate = iwl_post_associate,
1530}; 1531};
1531 1532
1532struct iwl_ops iwl5000_ops = { 1533struct iwl_ops iwl5000_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 1f5ee55778f1..d14146fa751f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -531,76 +531,6 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv,
531 * 531 *
532 ******************************************************************************/ 532 ******************************************************************************/
533 533
534static void iwl_ht_conf(struct iwl_priv *priv,
535 struct ieee80211_bss_conf *bss_conf)
536{
537 struct ieee80211_sta_ht_cap *ht_conf;
538 struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
539 struct ieee80211_sta *sta;
540
541 IWL_DEBUG_MAC80211(priv, "enter: \n");
542
543 if (!iwl_conf->is_ht)
544 return;
545
546
547 /*
548 * It is totally wrong to base global information on something
549 * that is valid only when associated, alas, this driver works
550 * that way and I don't know how to fix it.
551 */
552
553 rcu_read_lock();
554 sta = ieee80211_find_sta(priv->hw, priv->bssid);
555 if (!sta) {
556 rcu_read_unlock();
557 return;
558 }
559 ht_conf = &sta->ht_cap;
560
561 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
562 iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
563 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
564 iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
565
566 iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
567 iwl_conf->max_amsdu_size =
568 !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
569
570 iwl_conf->supported_chan_width =
571 !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
572
573 /*
574 * XXX: The HT configuration needs to be moved into iwl_mac_config()
575 * to be done there correctly.
576 */
577
578 iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
579 if (conf_is_ht40_minus(&priv->hw->conf))
580 iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
581 else if (conf_is_ht40_plus(&priv->hw->conf))
582 iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
583
584 /* If no above or below channel supplied disable FAT channel */
585 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
586 iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
587 iwl_conf->supported_chan_width = 0;
588
589 iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
590
591 memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
592
593 iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
594 iwl_conf->ht_protection =
595 bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
596 iwl_conf->non_GF_STA_present =
597 !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
598
599 rcu_read_unlock();
600
601 IWL_DEBUG_MAC80211(priv, "leave\n");
602}
603
604#define MAX_UCODE_BEACON_INTERVAL 4096 534#define MAX_UCODE_BEACON_INTERVAL 4096
605 535
606static u16 iwl_adjust_beacon_interval(u16 beacon_val) 536static u16 iwl_adjust_beacon_interval(u16 beacon_val)
@@ -1911,7 +1841,7 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
1911 1841
1912#define IWL_DELAY_NEXT_SCAN (HZ*2) 1842#define IWL_DELAY_NEXT_SCAN (HZ*2)
1913 1843
1914static void iwl_post_associate(struct iwl_priv *priv) 1844void iwl_post_associate(struct iwl_priv *priv)
1915{ 1845{
1916 struct ieee80211_conf *conf = NULL; 1846 struct ieee80211_conf *conf = NULL;
1917 int ret = 0; 1847 int ret = 0;
@@ -2482,70 +2412,6 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
2482 2412
2483} 2413}
2484 2414
2485#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
2486static void iwl_bss_info_changed(struct ieee80211_hw *hw,
2487 struct ieee80211_vif *vif,
2488 struct ieee80211_bss_conf *bss_conf,
2489 u32 changes)
2490{
2491 struct iwl_priv *priv = hw->priv;
2492
2493 IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
2494
2495 if (changes & BSS_CHANGED_ERP_PREAMBLE) {
2496 IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
2497 bss_conf->use_short_preamble);
2498 if (bss_conf->use_short_preamble)
2499 priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
2500 else
2501 priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
2502 }
2503
2504 if (changes & BSS_CHANGED_ERP_CTS_PROT) {
2505 IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
2506 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
2507 priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
2508 else
2509 priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
2510 }
2511
2512 if (changes & BSS_CHANGED_HT) {
2513 iwl_ht_conf(priv, bss_conf);
2514 iwl_set_rxon_chain(priv);
2515 }
2516
2517 if (changes & BSS_CHANGED_ASSOC) {
2518 IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
2519 /* This should never happen as this function should
2520 * never be called from interrupt context. */
2521 if (WARN_ON_ONCE(in_interrupt()))
2522 return;
2523 if (bss_conf->assoc) {
2524 priv->assoc_id = bss_conf->aid;
2525 priv->beacon_int = bss_conf->beacon_int;
2526 priv->power_data.dtim_period = bss_conf->dtim_period;
2527 priv->timestamp = bss_conf->timestamp;
2528 priv->assoc_capability = bss_conf->assoc_capability;
2529
2530 /* we have just associated, don't start scan too early
2531 * leave time for EAPOL exchange to complete
2532 */
2533 priv->next_scan_jiffies = jiffies +
2534 IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
2535 mutex_lock(&priv->mutex);
2536 iwl_post_associate(priv);
2537 mutex_unlock(&priv->mutex);
2538 } else {
2539 priv->assoc_id = 0;
2540 IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc);
2541 }
2542 } else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
2543 IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes);
2544 iwl_send_rxon_assoc(priv);
2545 }
2546
2547}
2548
2549static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, 2415static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
2550 struct ieee80211_key_conf *keyconf, const u8 *addr, 2416 struct ieee80211_key_conf *keyconf, const u8 *addr,
2551 u32 iv32, u16 *phase1key) 2417 u32 iv32, u16 *phase1key)
@@ -2825,7 +2691,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
2825 2691
2826 iwl_reset_qos(priv); 2692 iwl_reset_qos(priv);
2827 2693
2828 iwl_post_associate(priv); 2694 priv->cfg->ops->lib->post_associate(priv);
2829 2695
2830 2696
2831 return 0; 2697 return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 84ac1cec6f5b..15691829e023 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2157,6 +2157,142 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
2157 return 0; 2157 return 0;
2158} 2158}
2159EXPORT_SYMBOL(iwl_mac_conf_tx); 2159EXPORT_SYMBOL(iwl_mac_conf_tx);
2160
2161static void iwl_ht_conf(struct iwl_priv *priv,
2162 struct ieee80211_bss_conf *bss_conf)
2163{
2164 struct ieee80211_sta_ht_cap *ht_conf;
2165 struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
2166 struct ieee80211_sta *sta;
2167
2168 IWL_DEBUG_MAC80211(priv, "enter: \n");
2169
2170 if (!iwl_conf->is_ht)
2171 return;
2172
2173
2174 /*
2175 * It is totally wrong to base global information on something
2176 * that is valid only when associated, alas, this driver works
2177 * that way and I don't know how to fix it.
2178 */
2179
2180 rcu_read_lock();
2181 sta = ieee80211_find_sta(priv->hw, priv->bssid);
2182 if (!sta) {
2183 rcu_read_unlock();
2184 return;
2185 }
2186 ht_conf = &sta->ht_cap;
2187
2188 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
2189 iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
2190 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
2191 iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
2192
2193 iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
2194 iwl_conf->max_amsdu_size =
2195 !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
2196
2197 iwl_conf->supported_chan_width =
2198 !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
2199
2200 /*
2201 * XXX: The HT configuration needs to be moved into iwl_mac_config()
2202 * to be done there correctly.
2203 */
2204
2205 iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
2206 if (conf_is_ht40_minus(&priv->hw->conf))
2207 iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
2208 else if (conf_is_ht40_plus(&priv->hw->conf))
2209 iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
2210
2211 /* If no above or below channel supplied disable FAT channel */
2212 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
2213 iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
2214 iwl_conf->supported_chan_width = 0;
2215
2216 iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
2217
2218 memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
2219
2220 iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
2221 iwl_conf->ht_protection =
2222 bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
2223 iwl_conf->non_GF_STA_present =
2224 !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
2225
2226 rcu_read_unlock();
2227
2228 IWL_DEBUG_MAC80211(priv, "leave\n");
2229}
2230
2231#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
2232void iwl_bss_info_changed(struct ieee80211_hw *hw,
2233 struct ieee80211_vif *vif,
2234 struct ieee80211_bss_conf *bss_conf,
2235 u32 changes)
2236{
2237 struct iwl_priv *priv = hw->priv;
2238
2239 IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
2240
2241 if (changes & BSS_CHANGED_ERP_PREAMBLE) {
2242 IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
2243 bss_conf->use_short_preamble);
2244 if (bss_conf->use_short_preamble)
2245 priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
2246 else
2247 priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
2248 }
2249
2250 if (changes & BSS_CHANGED_ERP_CTS_PROT) {
2251 IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
2252 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
2253 priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
2254 else
2255 priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
2256 }
2257
2258 if (changes & BSS_CHANGED_HT) {
2259 iwl_ht_conf(priv, bss_conf);
2260 iwl_set_rxon_chain(priv);
2261 }
2262
2263 if (changes & BSS_CHANGED_ASSOC) {
2264 IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
2265 /* This should never happen as this function should
2266 * never be called from interrupt context. */
2267 if (WARN_ON_ONCE(in_interrupt()))
2268 return;
2269 if (bss_conf->assoc) {
2270 priv->assoc_id = bss_conf->aid;
2271 priv->beacon_int = bss_conf->beacon_int;
2272 priv->power_data.dtim_period = bss_conf->dtim_period;
2273 priv->timestamp = bss_conf->timestamp;
2274 priv->assoc_capability = bss_conf->assoc_capability;
2275
2276 /* we have just associated, don't start scan too early
2277 * leave time for EAPOL exchange to complete
2278 */
2279 priv->next_scan_jiffies = jiffies +
2280 IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
2281 mutex_lock(&priv->mutex);
2282 priv->cfg->ops->lib->post_associate(priv);
2283 mutex_unlock(&priv->mutex);
2284 } else {
2285 priv->assoc_id = 0;
2286 IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc);
2287 }
2288 } else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
2289 IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes);
2290 iwl_send_rxon_assoc(priv);
2291 }
2292
2293}
2294EXPORT_SYMBOL(iwl_bss_info_changed);
2295
2160#ifdef CONFIG_PM 2296#ifdef CONFIG_PM
2161 2297
2162int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) 2298int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index d56edcd97aa0..4ad8465ae5fb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -149,6 +149,8 @@ struct iwl_lib_ops {
149 int (*send_tx_power) (struct iwl_priv *priv); 149 int (*send_tx_power) (struct iwl_priv *priv);
150 void (*update_chain_flags)(struct iwl_priv *priv); 150 void (*update_chain_flags)(struct iwl_priv *priv);
151 void (*temperature) (struct iwl_priv *priv); 151 void (*temperature) (struct iwl_priv *priv);
152 void (*post_associate) (struct iwl_priv *priv);
153
152 /* eeprom operations (as defined in iwl-eeprom.h) */ 154 /* eeprom operations (as defined in iwl-eeprom.h) */
153 struct iwl_eeprom_ops eeprom_ops; 155 struct iwl_eeprom_ops eeprom_ops;
154}; 156};
@@ -251,6 +253,11 @@ int iwl_setup_mac(struct iwl_priv *priv);
251int iwl_set_hw_params(struct iwl_priv *priv); 253int iwl_set_hw_params(struct iwl_priv *priv);
252int iwl_init_drv(struct iwl_priv *priv); 254int iwl_init_drv(struct iwl_priv *priv);
253void iwl_uninit_drv(struct iwl_priv *priv); 255void iwl_uninit_drv(struct iwl_priv *priv);
256void iwl_post_associate(struct iwl_priv *priv);
257void iwl_bss_info_changed(struct ieee80211_hw *hw,
258 struct ieee80211_vif *vif,
259 struct ieee80211_bss_conf *bss_conf,
260 u32 changes);
254 261
255/***************************************************** 262/*****************************************************
256 * RX handlers. 263 * RX handlers.
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index ed31030c7643..6f44abc2dce0 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -233,50 +233,6 @@ u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flag
233 233
234} 234}
235 235
236static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
237{
238 int rc = 0;
239 struct iwl_rx_packet *res = NULL;
240 struct iwl3945_rxon_assoc_cmd rxon_assoc;
241 struct iwl_host_cmd cmd = {
242 .id = REPLY_RXON_ASSOC,
243 .len = sizeof(rxon_assoc),
244 .meta.flags = CMD_WANT_SKB,
245 .data = &rxon_assoc,
246 };
247 const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
248 const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
249
250 if ((rxon1->flags == rxon2->flags) &&
251 (rxon1->filter_flags == rxon2->filter_flags) &&
252 (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
253 (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
254 IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n");
255 return 0;
256 }
257
258 rxon_assoc.flags = priv->staging_rxon.flags;
259 rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
260 rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
261 rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
262 rxon_assoc.reserved = 0;
263
264 rc = iwl_send_cmd_sync(priv, &cmd);
265 if (rc)
266 return rc;
267
268 res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
269 if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
270 IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
271 rc = -EIO;
272 }
273
274 priv->alloc_rxb_skb--;
275 dev_kfree_skb_any(cmd.meta.u.skb);
276
277 return rc;
278}
279
280/** 236/**
281 * iwl3945_get_antenna_flags - Get antenna flags for RXON command 237 * iwl3945_get_antenna_flags - Get antenna flags for RXON command
282 * @priv: eeprom and antenna fields are used to determine antenna flags 238 * @priv: eeprom and antenna fields are used to determine antenna flags
@@ -352,7 +308,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
352 * iwl3945_rxon_assoc_cmd which is used to reconfigure filter 308 * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
353 * and other flags for the current radio configuration. */ 309 * and other flags for the current radio configuration. */
354 if (!iwl_full_rxon_required(priv)) { 310 if (!iwl_full_rxon_required(priv)) {
355 rc = iwl3945_send_rxon_assoc(priv); 311 rc = iwl_send_rxon_assoc(priv);
356 if (rc) { 312 if (rc) {
357 IWL_ERR(priv, "Error setting RXON_ASSOC " 313 IWL_ERR(priv, "Error setting RXON_ASSOC "
358 "configuration (%d).\n", rc); 314 "configuration (%d).\n", rc);
@@ -3450,9 +3406,11 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
3450 mutex_unlock(&priv->mutex); 3406 mutex_unlock(&priv->mutex);
3451} 3407}
3452 3408
3409static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
3410
3453#define IWL_DELAY_NEXT_SCAN (HZ*2) 3411#define IWL_DELAY_NEXT_SCAN (HZ*2)
3454 3412
3455static void iwl3945_post_associate(struct iwl_priv *priv) 3413void iwl3945_post_associate(struct iwl_priv *priv)
3456{ 3414{
3457 int rc = 0; 3415 int rc = 0;
3458 struct ieee80211_conf *conf = NULL; 3416 struct ieee80211_conf *conf = NULL;
@@ -3542,8 +3500,6 @@ static void iwl3945_post_associate(struct iwl_priv *priv)
3542 priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; 3500 priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
3543} 3501}
3544 3502
3545static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
3546
3547/***************************************************************************** 3503/*****************************************************************************
3548 * 3504 *
3549 * mac80211 entry point functions 3505 * mac80211 entry point functions
@@ -3982,66 +3938,6 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
3982 IWL_DEBUG_MAC80211(priv, "leave\n"); 3938 IWL_DEBUG_MAC80211(priv, "leave\n");
3983} 3939}
3984 3940
3985#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
3986
3987static void iwl3945_bss_info_changed(struct ieee80211_hw *hw,
3988 struct ieee80211_vif *vif,
3989 struct ieee80211_bss_conf *bss_conf,
3990 u32 changes)
3991{
3992 struct iwl_priv *priv = hw->priv;
3993
3994 IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
3995
3996 if (changes & BSS_CHANGED_ERP_PREAMBLE) {
3997 IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
3998 bss_conf->use_short_preamble);
3999 if (bss_conf->use_short_preamble)
4000 priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
4001 else
4002 priv->staging_rxon.flags &=
4003 ~RXON_FLG_SHORT_PREAMBLE_MSK;
4004 }
4005
4006 if (changes & BSS_CHANGED_ERP_CTS_PROT) {
4007 IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n",
4008 bss_conf->use_cts_prot);
4009 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
4010 priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
4011 else
4012 priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
4013 }
4014
4015 if (changes & BSS_CHANGED_ASSOC) {
4016 IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
4017 /* This should never happen as this function should
4018 * never be called from interrupt context. */
4019 if (WARN_ON_ONCE(in_interrupt()))
4020 return;
4021 if (bss_conf->assoc) {
4022 priv->assoc_id = bss_conf->aid;
4023 priv->beacon_int = bss_conf->beacon_int;
4024 priv->timestamp = bss_conf->timestamp;
4025 priv->assoc_capability = bss_conf->assoc_capability;
4026 priv->power_data.dtim_period = bss_conf->dtim_period;
4027 priv->next_scan_jiffies = jiffies +
4028 IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
4029 mutex_lock(&priv->mutex);
4030 iwl3945_post_associate(priv);
4031 mutex_unlock(&priv->mutex);
4032 } else {
4033 priv->assoc_id = 0;
4034 IWL_DEBUG_MAC80211(priv,
4035 "DISASSOC %d\n", bss_conf->assoc);
4036 }
4037 } else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
4038 IWL_DEBUG_MAC80211(priv,
4039 "Associated Changes %d\n", changes);
4040 iwl3945_send_rxon_assoc(priv);
4041 }
4042
4043}
4044
4045static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 3941static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
4046 struct ieee80211_vif *vif, 3942 struct ieee80211_vif *vif,
4047 struct ieee80211_sta *sta, 3943 struct ieee80211_sta *sta,
@@ -4227,7 +4123,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
4227 4123
4228 iwl_reset_qos(priv); 4124 iwl_reset_qos(priv);
4229 4125
4230 iwl3945_post_associate(priv); 4126 priv->cfg->ops->lib->post_associate(priv);
4231 4127
4232 4128
4233 return 0; 4129 return 0;
@@ -4765,7 +4661,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
4765 .get_tx_stats = iwl3945_mac_get_tx_stats, 4661 .get_tx_stats = iwl3945_mac_get_tx_stats,
4766 .conf_tx = iwl_mac_conf_tx, 4662 .conf_tx = iwl_mac_conf_tx,
4767 .reset_tsf = iwl3945_mac_reset_tsf, 4663 .reset_tsf = iwl3945_mac_reset_tsf,
4768 .bss_info_changed = iwl3945_bss_info_changed, 4664 .bss_info_changed = iwl_bss_info_changed,
4769 .hw_scan = iwl_mac_hw_scan 4665 .hw_scan = iwl_mac_hw_scan
4770}; 4666};
4771 4667