linux/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17 *
  18 * The full GNU General Public License is included in this distribution in the
  19 * file called LICENSE.
  20 *
  21 * Contact Information:
  22 * Intel Linux Wireless <ilw@linux.intel.com>
  23 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  24 *
  25 *****************************************************************************/
  26
  27#include "iwl-dev.h"
  28#include "iwl-agn.h"
  29#include "iwl-sta.h"
  30#include "iwl-core.h"
  31#include "iwl-agn-calib.h"
  32
  33static int iwlagn_disable_bss(struct iwl_priv *priv,
  34                              struct iwl_rxon_context *ctx,
  35                              struct iwl_rxon_cmd *send)
  36{
  37        __le32 old_filter = send->filter_flags;
  38        int ret;
  39
  40        send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
  41        ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
  42
  43        send->filter_flags = old_filter;
  44
  45        if (ret)
  46                IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret);
  47
  48        return ret;
  49}
  50
  51static int iwlagn_disable_pan(struct iwl_priv *priv,
  52                              struct iwl_rxon_context *ctx,
  53                              struct iwl_rxon_cmd *send)
  54{
  55        __le32 old_filter = send->filter_flags;
  56        u8 old_dev_type = send->dev_type;
  57        int ret;
  58
  59        send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
  60        send->dev_type = RXON_DEV_TYPE_P2P;
  61        ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
  62
  63        send->filter_flags = old_filter;
  64        send->dev_type = old_dev_type;
  65
  66        if (ret)
  67                IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
  68
  69        /* FIXME: WAIT FOR PAN DISABLE */
  70        msleep(300);
  71
  72        return ret;
  73}
  74
  75static void iwlagn_update_qos(struct iwl_priv *priv,
  76                              struct iwl_rxon_context *ctx)
  77{
  78        int ret;
  79
  80        if (!ctx->is_active)
  81                return;
  82
  83        ctx->qos_data.def_qos_parm.qos_flags = 0;
  84
  85        if (ctx->qos_data.qos_active)
  86                ctx->qos_data.def_qos_parm.qos_flags |=
  87                        QOS_PARAM_FLG_UPDATE_EDCA_MSK;
  88
  89        if (ctx->ht.enabled)
  90                ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
  91
  92        IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
  93                      ctx->qos_data.qos_active,
  94                      ctx->qos_data.def_qos_parm.qos_flags);
  95
  96        ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
  97                               sizeof(struct iwl_qosparam_cmd),
  98                               &ctx->qos_data.def_qos_parm);
  99        if (ret)
 100                IWL_ERR(priv, "Failed to update QoS\n");
 101}
 102
 103static int iwlagn_update_beacon(struct iwl_priv *priv,
 104                                struct ieee80211_vif *vif)
 105{
 106        lockdep_assert_held(&priv->mutex);
 107
 108        dev_kfree_skb(priv->beacon_skb);
 109        priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
 110        if (!priv->beacon_skb)
 111                return -ENOMEM;
 112        return iwlagn_send_beacon_cmd(priv);
 113}
 114
 115/**
 116 * iwlagn_commit_rxon - commit staging_rxon to hardware
 117 *
 118 * The RXON command in staging_rxon is committed to the hardware and
 119 * the active_rxon structure is updated with the new data.  This
 120 * function correctly transitions out of the RXON_ASSOC_MSK state if
 121 * a HW tune is required based on the RXON structure changes.
 122 */
 123int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 124{
 125        /* cast away the const for active_rxon in this function */
 126        struct iwl_rxon_cmd *active = (void *)&ctx->active;
 127        bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
 128        bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
 129        int ret;
 130
 131        lockdep_assert_held(&priv->mutex);
 132
 133        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 134                return -EINVAL;
 135
 136        if (!iwl_is_alive(priv))
 137                return -EBUSY;
 138
 139        /* This function hardcodes a bunch of dual-mode assumptions */
 140        BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
 141
 142        if (!ctx->is_active)
 143                return 0;
 144
 145        /* always get timestamp with Rx frame */
 146        ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
 147
 148        if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
 149            !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
 150                ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 151        else
 152                ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 153
 154        ret = iwl_check_rxon_cmd(priv, ctx);
 155        if (ret) {
 156                IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
 157                return -EINVAL;
 158        }
 159
 160        /*
 161         * receive commit_rxon request
 162         * abort any previous channel switch if still in process
 163         */
 164        if (priv->switch_rxon.switch_in_progress &&
 165            (priv->switch_rxon.channel != ctx->staging.channel)) {
 166                IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
 167                      le16_to_cpu(priv->switch_rxon.channel));
 168                iwl_chswitch_done(priv, false);
 169        }
 170
 171        /*
 172         * If we don't need to send a full RXON, we can use
 173         * iwl_rxon_assoc_cmd which is used to reconfigure filter
 174         * and other flags for the current radio configuration.
 175         */
 176        if (!iwl_full_rxon_required(priv, ctx)) {
 177                ret = iwl_send_rxon_assoc(priv, ctx);
 178                if (ret) {
 179                        IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
 180                        return ret;
 181                }
 182
 183                memcpy(active, &ctx->staging, sizeof(*active));
 184                iwl_print_rx_config_cmd(priv, ctx);
 185                return 0;
 186        }
 187
 188        if (priv->cfg->ops->hcmd->set_pan_params) {
 189                ret = priv->cfg->ops->hcmd->set_pan_params(priv);
 190                if (ret)
 191                        return ret;
 192        }
 193
 194        iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
 195
 196        IWL_DEBUG_INFO(priv,
 197                       "Going to commit RXON\n"
 198                       "  * with%s RXON_FILTER_ASSOC_MSK\n"
 199                       "  * channel = %d\n"
 200                       "  * bssid = %pM\n",
 201                       (new_assoc ? "" : "out"),
 202                       le16_to_cpu(ctx->staging.channel),
 203                       ctx->staging.bssid_addr);
 204
 205        /*
 206         * Always clear associated first, but with the correct config.
 207         * This is required as for example station addition for the
 208         * AP station must be done after the BSSID is set to correctly
 209         * set up filters in the device.
 210         */
 211        if ((old_assoc && new_assoc) || !new_assoc) {
 212                if (ctx->ctxid == IWL_RXON_CTX_BSS)
 213                        ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
 214                else
 215                        ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
 216                if (ret)
 217                        return ret;
 218
 219                memcpy(active, &ctx->staging, sizeof(*active));
 220
 221                /*
 222                 * Un-assoc RXON clears the station table and WEP
 223                 * keys, so we have to restore those afterwards.
 224                 */
 225                iwl_clear_ucode_stations(priv, ctx);
 226                iwl_restore_stations(priv, ctx);
 227                ret = iwl_restore_default_wep_keys(priv, ctx);
 228                if (ret) {
 229                        IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
 230                        return ret;
 231                }
 232        }
 233
 234        /* RXON timing must be before associated RXON */
 235        ret = iwl_send_rxon_timing(priv, ctx);
 236        if (ret) {
 237                IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
 238                return ret;
 239        }
 240
 241        if (new_assoc) {
 242                /* QoS info may be cleared by previous un-assoc RXON */
 243                iwlagn_update_qos(priv, ctx);
 244
 245                /*
 246                 * We'll run into this code path when beaconing is
 247                 * enabled, but then we also need to send the beacon
 248                 * to the device.
 249                 */
 250                if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) {
 251                        ret = iwlagn_update_beacon(priv, ctx->vif);
 252                        if (ret) {
 253                                IWL_ERR(priv,
 254                                        "Error sending required beacon (%d)!\n",
 255                                        ret);
 256                                return ret;
 257                        }
 258                }
 259
 260                priv->start_calib = 0;
 261                /*
 262                 * Apply the new configuration.
 263                 *
 264                 * Associated RXON doesn't clear the station table in uCode,
 265                 * so we don't need to restore stations etc. after this.
 266                 */
 267                ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
 268                              sizeof(struct iwl_rxon_cmd), &ctx->staging);
 269                if (ret) {
 270                        IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
 271                        return ret;
 272                }
 273                memcpy(active, &ctx->staging, sizeof(*active));
 274
 275                iwl_reprogram_ap_sta(priv, ctx);
 276
 277                /* IBSS beacon needs to be sent after setting assoc */
 278                if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
 279                        if (iwlagn_update_beacon(priv, ctx->vif))
 280                                IWL_ERR(priv, "Error sending IBSS beacon\n");
 281        }
 282
 283        iwl_print_rx_config_cmd(priv, ctx);
 284
 285        iwl_init_sensitivity(priv);
 286
 287        /*
 288         * If we issue a new RXON command which required a tune then we must
 289         * send a new TXPOWER command or we won't be able to Tx any frames.
 290         *
 291         * FIXME: which RXON requires a tune? Can we optimise this out in
 292         *        some cases?
 293         */
 294        ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
 295        if (ret) {
 296                IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
 297                return ret;
 298        }
 299
 300        return 0;
 301}
 302
 303int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
 304{
 305        struct iwl_priv *priv = hw->priv;
 306        struct iwl_rxon_context *ctx;
 307        struct ieee80211_conf *conf = &hw->conf;
 308        struct ieee80211_channel *channel = conf->channel;
 309        const struct iwl_channel_info *ch_info;
 310        int ret = 0;
 311        bool ht_changed[NUM_IWL_RXON_CTX] = {};
 312
 313        IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
 314
 315        mutex_lock(&priv->mutex);
 316
 317        if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
 318                IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
 319                goto out;
 320        }
 321
 322        if (!iwl_is_ready(priv)) {
 323                IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
 324                goto out;
 325        }
 326
 327        if (changed & (IEEE80211_CONF_CHANGE_SMPS |
 328                       IEEE80211_CONF_CHANGE_CHANNEL)) {
 329                /* mac80211 uses static for non-HT which is what we want */
 330                priv->current_ht_config.smps = conf->smps_mode;
 331
 332                /*
 333                 * Recalculate chain counts.
 334                 *
 335                 * If monitor mode is enabled then mac80211 will
 336                 * set up the SM PS mode to OFF if an HT channel is
 337                 * configured.
 338                 */
 339                if (priv->cfg->ops->hcmd->set_rxon_chain)
 340                        for_each_context(priv, ctx)
 341                                priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 342        }
 343
 344        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 345                unsigned long flags;
 346
 347                ch_info = iwl_get_channel_info(priv, channel->band,
 348                                               channel->hw_value);
 349                if (!is_channel_valid(ch_info)) {
 350                        IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
 351                        ret = -EINVAL;
 352                        goto out;
 353                }
 354
 355                spin_lock_irqsave(&priv->lock, flags);
 356
 357                for_each_context(priv, ctx) {
 358                        /* Configure HT40 channels */
 359                        if (ctx->ht.enabled != conf_is_ht(conf)) {
 360                                ctx->ht.enabled = conf_is_ht(conf);
 361                                ht_changed[ctx->ctxid] = true;
 362                        }
 363
 364                        if (ctx->ht.enabled) {
 365                                if (conf_is_ht40_minus(conf)) {
 366                                        ctx->ht.extension_chan_offset =
 367                                                IEEE80211_HT_PARAM_CHA_SEC_BELOW;
 368                                        ctx->ht.is_40mhz = true;
 369                                } else if (conf_is_ht40_plus(conf)) {
 370                                        ctx->ht.extension_chan_offset =
 371                                                IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
 372                                        ctx->ht.is_40mhz = true;
 373                                } else {
 374                                        ctx->ht.extension_chan_offset =
 375                                                IEEE80211_HT_PARAM_CHA_SEC_NONE;
 376                                        ctx->ht.is_40mhz = false;
 377                                }
 378                        } else
 379                                ctx->ht.is_40mhz = false;
 380
 381                        /*
 382                         * Default to no protection. Protection mode will
 383                         * later be set from BSS config in iwl_ht_conf
 384                         */
 385                        ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
 386
 387                        /* if we are switching from ht to 2.4 clear flags
 388                         * from any ht related info since 2.4 does not
 389                         * support ht */
 390                        if (le16_to_cpu(ctx->staging.channel) !=
 391                            channel->hw_value)
 392                                ctx->staging.flags = 0;
 393
 394                        iwl_set_rxon_channel(priv, channel, ctx);
 395                        iwl_set_rxon_ht(priv, &priv->current_ht_config);
 396
 397                        iwl_set_flags_for_band(priv, ctx, channel->band,
 398                                               ctx->vif);
 399                }
 400
 401                spin_unlock_irqrestore(&priv->lock, flags);
 402
 403                iwl_update_bcast_stations(priv);
 404
 405                /*
 406                 * The list of supported rates and rate mask can be different
 407                 * for each band; since the band may have changed, reset
 408                 * the rate mask to what mac80211 lists.
 409                 */
 410                iwl_set_rate(priv);
 411        }
 412
 413        if (changed & (IEEE80211_CONF_CHANGE_PS |
 414                        IEEE80211_CONF_CHANGE_IDLE)) {
 415                ret = iwl_power_update_mode(priv, false);
 416                if (ret)
 417                        IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
 418        }
 419
 420        if (changed & IEEE80211_CONF_CHANGE_POWER) {
 421                IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
 422                        priv->tx_power_user_lmt, conf->power_level);
 423
 424                iwl_set_tx_power(priv, conf->power_level, false);
 425        }
 426
 427        for_each_context(priv, ctx) {
 428                if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
 429                        continue;
 430                iwlagn_commit_rxon(priv, ctx);
 431                if (ht_changed[ctx->ctxid])
 432                        iwlagn_update_qos(priv, ctx);
 433        }
 434 out:
 435        mutex_unlock(&priv->mutex);
 436        return ret;
 437}
 438
 439static void iwlagn_check_needed_chains(struct iwl_priv *priv,
 440                                       struct iwl_rxon_context *ctx,
 441                                       struct ieee80211_bss_conf *bss_conf)
 442{
 443        struct ieee80211_vif *vif = ctx->vif;
 444        struct iwl_rxon_context *tmp;
 445        struct ieee80211_sta *sta;
 446        struct iwl_ht_config *ht_conf = &priv->current_ht_config;
 447        bool need_multiple;
 448
 449        lockdep_assert_held(&priv->mutex);
 450
 451        switch (vif->type) {
 452        case NL80211_IFTYPE_STATION:
 453                rcu_read_lock();
 454                sta = ieee80211_find_sta(vif, bss_conf->bssid);
 455                if (sta) {
 456                        struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
 457                        int maxstreams;
 458
 459                        maxstreams = (ht_cap->mcs.tx_params &
 460                                      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
 461                                        >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
 462                        maxstreams += 1;
 463
 464                        need_multiple = true;
 465
 466                        if ((ht_cap->mcs.rx_mask[1] == 0) &&
 467                            (ht_cap->mcs.rx_mask[2] == 0))
 468                                need_multiple = false;
 469                        if (maxstreams <= 1)
 470                                need_multiple = false;
 471                } else {
 472                        /*
 473                         * If at all, this can only happen through a race
 474                         * when the AP disconnects us while we're still
 475                         * setting up the connection, in that case mac80211
 476                         * will soon tell us about that.
 477                         */
 478                        need_multiple = false;
 479                }
 480                rcu_read_unlock();
 481                break;
 482        case NL80211_IFTYPE_ADHOC:
 483                /* currently */
 484                need_multiple = false;
 485                break;
 486        default:
 487                /* only AP really */
 488                need_multiple = true;
 489                break;
 490        }
 491
 492        ctx->ht_need_multiple_chains = need_multiple;
 493
 494        if (!need_multiple) {
 495                /* check all contexts */
 496                for_each_context(priv, tmp) {
 497                        if (!tmp->vif)
 498                                continue;
 499                        if (tmp->ht_need_multiple_chains) {
 500                                need_multiple = true;
 501                                break;
 502                        }
 503                }
 504        }
 505
 506        ht_conf->single_chain_sufficient = !need_multiple;
 507}
 508
 509void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 510                             struct ieee80211_vif *vif,
 511                             struct ieee80211_bss_conf *bss_conf,
 512                             u32 changes)
 513{
 514        struct iwl_priv *priv = hw->priv;
 515        struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 516        int ret;
 517        bool force = false;
 518
 519        mutex_lock(&priv->mutex);
 520
 521        if (unlikely(!iwl_is_ready(priv))) {
 522                IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
 523                mutex_unlock(&priv->mutex);
 524                return;
 525        }
 526
 527        if (unlikely(!ctx->vif)) {
 528                IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
 529                mutex_unlock(&priv->mutex);
 530                return;
 531        }
 532
 533        if (changes & BSS_CHANGED_BEACON_INT)
 534                force = true;
 535
 536        if (changes & BSS_CHANGED_QOS) {
 537                ctx->qos_data.qos_active = bss_conf->qos;
 538                iwlagn_update_qos(priv, ctx);
 539        }
 540
 541        ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
 542        if (vif->bss_conf.use_short_preamble)
 543                ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 544        else
 545                ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 546
 547        if (changes & BSS_CHANGED_ASSOC) {
 548                if (bss_conf->assoc) {
 549                        iwl_led_associate(priv);
 550                        priv->timestamp = bss_conf->timestamp;
 551                        ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 552                } else {
 553                        ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 554                        iwl_led_disassociate(priv);
 555                }
 556        }
 557
 558        if (ctx->ht.enabled) {
 559                ctx->ht.protection = bss_conf->ht_operation_mode &
 560                                        IEEE80211_HT_OP_MODE_PROTECTION;
 561                ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode &
 562                                        IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
 563                iwlagn_check_needed_chains(priv, ctx, bss_conf);
 564                iwl_set_rxon_ht(priv, &priv->current_ht_config);
 565        }
 566
 567        if (priv->cfg->ops->hcmd->set_rxon_chain)
 568                priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 569
 570        if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
 571                ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
 572        else
 573                ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
 574
 575        if (bss_conf->use_cts_prot)
 576                ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
 577        else
 578                ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
 579
 580        memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
 581
 582        if (vif->type == NL80211_IFTYPE_AP ||
 583            vif->type == NL80211_IFTYPE_ADHOC) {
 584                if (vif->bss_conf.enable_beacon) {
 585                        ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 586                        priv->beacon_ctx = ctx;
 587                } else {
 588                        ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 589                        priv->beacon_ctx = NULL;
 590                }
 591        }
 592
 593        if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
 594                iwlagn_commit_rxon(priv, ctx);
 595
 596        if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) {
 597                /*
 598                 * The chain noise calibration will enable PM upon
 599                 * completion. If calibration has already been run
 600                 * then we need to enable power management here.
 601                 */
 602                if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
 603                        iwl_power_update_mode(priv, false);
 604
 605                /* Enable RX differential gain and sensitivity calibrations */
 606                iwl_chain_noise_reset(priv);
 607                priv->start_calib = 1;
 608        }
 609
 610        if (changes & BSS_CHANGED_IBSS) {
 611                ret = iwlagn_manage_ibss_station(priv, vif,
 612                                                 bss_conf->ibss_joined);
 613                if (ret)
 614                        IWL_ERR(priv, "failed to %s IBSS station %pM\n",
 615                                bss_conf->ibss_joined ? "add" : "remove",
 616                                bss_conf->bssid);
 617        }
 618
 619        if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_ADHOC &&
 620            priv->beacon_ctx) {
 621                if (iwlagn_update_beacon(priv, vif))
 622                        IWL_ERR(priv, "Error sending IBSS beacon\n");
 623        }
 624
 625        mutex_unlock(&priv->mutex);
 626}
 627
 628void iwlagn_post_scan(struct iwl_priv *priv)
 629{
 630        struct iwl_rxon_context *ctx;
 631
 632        /*
 633         * Since setting the RXON may have been deferred while
 634         * performing the scan, fire one off if needed
 635         */
 636        for_each_context(priv, ctx)
 637                if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
 638                        iwlagn_commit_rxon(priv, ctx);
 639
 640        if (priv->cfg->ops->hcmd->set_pan_params)
 641                priv->cfg->ops->hcmd->set_pan_params(priv);
 642}
 643