linux/drivers/net/wireless/iwlwifi/mvm/sta.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * This file is provided under a dual BSD/GPLv2 license.  When using or
   4 * redistributing this file, you may do so under either license.
   5 *
   6 * GPL LICENSE SUMMARY
   7 *
   8 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of version 2 of the GNU General Public License as
  12 * published by the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful, but
  15 * WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  22 * USA
  23 *
  24 * The full GNU General Public License is included in this distribution
  25 * in the file called COPYING.
  26 *
  27 * Contact Information:
  28 *  Intel Linux Wireless <ilw@linux.intel.com>
  29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  30 *
  31 * BSD LICENSE
  32 *
  33 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
  34 * All rights reserved.
  35 *
  36 * Redistribution and use in source and binary forms, with or without
  37 * modification, are permitted provided that the following conditions
  38 * are met:
  39 *
  40 *  * Redistributions of source code must retain the above copyright
  41 *    notice, this list of conditions and the following disclaimer.
  42 *  * Redistributions in binary form must reproduce the above copyright
  43 *    notice, this list of conditions and the following disclaimer in
  44 *    the documentation and/or other materials provided with the
  45 *    distribution.
  46 *  * Neither the name Intel Corporation nor the names of its
  47 *    contributors may be used to endorse or promote products derived
  48 *    from this software without specific prior written permission.
  49 *
  50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61 *
  62 *****************************************************************************/
  63#include <net/mac80211.h>
  64
  65#include "mvm.h"
  66#include "sta.h"
  67#include "rs.h"
  68
  69static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm)
  70{
  71        int sta_id;
  72
  73        WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
  74
  75        lockdep_assert_held(&mvm->mutex);
  76
  77        /* Don't take rcu_read_lock() since we are protected by mvm->mutex */
  78        for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++)
  79                if (!rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
  80                                               lockdep_is_held(&mvm->mutex)))
  81                        return sta_id;
  82        return IWL_MVM_STATION_COUNT;
  83}
  84
  85/* send station add/update command to firmware */
  86int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
  87                           bool update)
  88{
  89        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
  90        struct iwl_mvm_add_sta_cmd add_sta_cmd;
  91        int ret;
  92        u32 status;
  93        u32 agg_size = 0, mpdu_dens = 0;
  94
  95        memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
  96
  97        add_sta_cmd.sta_id = mvm_sta->sta_id;
  98        add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
  99        if (!update) {
 100                add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
 101                memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
 102        }
 103        add_sta_cmd.add_modify = update ? 1 : 0;
 104
 105        add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
 106                                                     STA_FLG_MIMO_EN_MSK);
 107
 108        switch (sta->bandwidth) {
 109        case IEEE80211_STA_RX_BW_160:
 110                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ);
 111                /* fall through */
 112        case IEEE80211_STA_RX_BW_80:
 113                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ);
 114                /* fall through */
 115        case IEEE80211_STA_RX_BW_40:
 116                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ);
 117                /* fall through */
 118        case IEEE80211_STA_RX_BW_20:
 119                if (sta->ht_cap.ht_supported)
 120                        add_sta_cmd.station_flags |=
 121                                cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
 122                break;
 123        }
 124
 125        switch (sta->rx_nss) {
 126        case 1:
 127                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
 128                break;
 129        case 2:
 130                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO2);
 131                break;
 132        case 3 ... 8:
 133                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO3);
 134                break;
 135        }
 136
 137        switch (sta->smps_mode) {
 138        case IEEE80211_SMPS_AUTOMATIC:
 139        case IEEE80211_SMPS_NUM_MODES:
 140                WARN_ON(1);
 141                break;
 142        case IEEE80211_SMPS_STATIC:
 143                /* override NSS */
 144                add_sta_cmd.station_flags &= ~cpu_to_le32(STA_FLG_MIMO_EN_MSK);
 145                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
 146                break;
 147        case IEEE80211_SMPS_DYNAMIC:
 148                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_RTS_MIMO_PROT);
 149                break;
 150        case IEEE80211_SMPS_OFF:
 151                /* nothing */
 152                break;
 153        }
 154
 155        if (sta->ht_cap.ht_supported) {
 156                add_sta_cmd.station_flags_msk |=
 157                        cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK |
 158                                    STA_FLG_AGG_MPDU_DENS_MSK);
 159
 160                mpdu_dens = sta->ht_cap.ampdu_density;
 161        }
 162
 163        if (sta->vht_cap.vht_supported) {
 164                agg_size = sta->vht_cap.cap &
 165                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
 166                agg_size >>=
 167                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
 168        } else if (sta->ht_cap.ht_supported) {
 169                agg_size = sta->ht_cap.ampdu_factor;
 170        }
 171
 172        add_sta_cmd.station_flags |=
 173                cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
 174        add_sta_cmd.station_flags |=
 175                cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
 176
 177        status = ADD_STA_SUCCESS;
 178        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(add_sta_cmd),
 179                                          &add_sta_cmd, &status);
 180        if (ret)
 181                return ret;
 182
 183        switch (status) {
 184        case ADD_STA_SUCCESS:
 185                IWL_DEBUG_ASSOC(mvm, "ADD_STA PASSED\n");
 186                break;
 187        default:
 188                ret = -EIO;
 189                IWL_ERR(mvm, "ADD_STA failed\n");
 190                break;
 191        }
 192
 193        return ret;
 194}
 195
 196int iwl_mvm_add_sta(struct iwl_mvm *mvm,
 197                    struct ieee80211_vif *vif,
 198                    struct ieee80211_sta *sta)
 199{
 200        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 201        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 202        int i, ret, sta_id;
 203
 204        lockdep_assert_held(&mvm->mutex);
 205
 206        if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
 207                sta_id = iwl_mvm_find_free_sta_id(mvm);
 208        else
 209                sta_id = mvm_sta->sta_id;
 210
 211        if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
 212                return -ENOSPC;
 213
 214        spin_lock_init(&mvm_sta->lock);
 215
 216        mvm_sta->sta_id = sta_id;
 217        mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
 218                                                      mvmvif->color);
 219        mvm_sta->vif = vif;
 220        mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 221        mvm_sta->tx_protection = 0;
 222        mvm_sta->tt_tx_protection = false;
 223
 224        /* HW restart, don't assume the memory has been zeroed */
 225        atomic_set(&mvm->pending_frames[sta_id], 0);
 226        mvm_sta->tid_disable_agg = 0;
 227        mvm_sta->tfd_queue_msk = 0;
 228        for (i = 0; i < IEEE80211_NUM_ACS; i++)
 229                if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
 230                        mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
 231
 232        /* for HW restart - need to reset the seq_number etc... */
 233        memset(mvm_sta->tid_data, 0, sizeof(mvm_sta->tid_data));
 234
 235        ret = iwl_mvm_sta_send_to_fw(mvm, sta, false);
 236        if (ret)
 237                return ret;
 238
 239        /* The first station added is the AP, the others are TDLS STAs */
 240        if (vif->type == NL80211_IFTYPE_STATION &&
 241            mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
 242                mvmvif->ap_sta_id = sta_id;
 243
 244        rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
 245
 246        return 0;
 247}
 248
 249int iwl_mvm_update_sta(struct iwl_mvm *mvm,
 250                       struct ieee80211_vif *vif,
 251                       struct ieee80211_sta *sta)
 252{
 253        return iwl_mvm_sta_send_to_fw(mvm, sta, true);
 254}
 255
 256int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
 257                      bool drain)
 258{
 259        struct iwl_mvm_add_sta_cmd cmd = {};
 260        int ret;
 261        u32 status;
 262
 263        lockdep_assert_held(&mvm->mutex);
 264
 265        cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color);
 266        cmd.sta_id = mvmsta->sta_id;
 267        cmd.add_modify = STA_MODE_MODIFY;
 268        cmd.station_flags = drain ? cpu_to_le32(STA_FLG_DRAIN_FLOW) : 0;
 269        cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW);
 270
 271        status = ADD_STA_SUCCESS;
 272        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
 273                                          &cmd, &status);
 274        if (ret)
 275                return ret;
 276
 277        switch (status) {
 278        case ADD_STA_SUCCESS:
 279                IWL_DEBUG_INFO(mvm, "Frames for staid %d will drained in fw\n",
 280                               mvmsta->sta_id);
 281                break;
 282        default:
 283                ret = -EIO;
 284                IWL_ERR(mvm, "Couldn't drain frames for staid %d\n",
 285                        mvmsta->sta_id);
 286                break;
 287        }
 288
 289        return ret;
 290}
 291
 292/*
 293 * Remove a station from the FW table. Before sending the command to remove
 294 * the station validate that the station is indeed known to the driver (sanity
 295 * only).
 296 */
 297static int iwl_mvm_rm_sta_common(struct iwl_mvm *mvm, u8 sta_id)
 298{
 299        struct ieee80211_sta *sta;
 300        struct iwl_mvm_rm_sta_cmd rm_sta_cmd = {
 301                .sta_id = sta_id,
 302        };
 303        int ret;
 304
 305        sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
 306                                        lockdep_is_held(&mvm->mutex));
 307
 308        /* Note: internal stations are marked as error values */
 309        if (!sta) {
 310                IWL_ERR(mvm, "Invalid station id\n");
 311                return -EINVAL;
 312        }
 313
 314        ret = iwl_mvm_send_cmd_pdu(mvm, REMOVE_STA, CMD_SYNC,
 315                                   sizeof(rm_sta_cmd), &rm_sta_cmd);
 316        if (ret) {
 317                IWL_ERR(mvm, "Failed to remove station. Id=%d\n", sta_id);
 318                return ret;
 319        }
 320
 321        return 0;
 322}
 323
 324void iwl_mvm_sta_drained_wk(struct work_struct *wk)
 325{
 326        struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, sta_drained_wk);
 327        u8 sta_id;
 328
 329        /*
 330         * The mutex is needed because of the SYNC cmd, but not only: if the
 331         * work would run concurrently with iwl_mvm_rm_sta, it would run before
 332         * iwl_mvm_rm_sta sets the station as busy, and exit. Then
 333         * iwl_mvm_rm_sta would set the station as busy, and nobody will clean
 334         * that later.
 335         */
 336        mutex_lock(&mvm->mutex);
 337
 338        for_each_set_bit(sta_id, mvm->sta_drained, IWL_MVM_STATION_COUNT) {
 339                int ret;
 340                struct ieee80211_sta *sta =
 341                        rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
 342                                                  lockdep_is_held(&mvm->mutex));
 343
 344                /* This station is in use */
 345                if (!IS_ERR(sta))
 346                        continue;
 347
 348                if (PTR_ERR(sta) == -EINVAL) {
 349                        IWL_ERR(mvm, "Drained sta %d, but it is internal?\n",
 350                                sta_id);
 351                        continue;
 352                }
 353
 354                if (!sta) {
 355                        IWL_ERR(mvm, "Drained sta %d, but it was NULL?\n",
 356                                sta_id);
 357                        continue;
 358                }
 359
 360                WARN_ON(PTR_ERR(sta) != -EBUSY);
 361                /* This station was removed and we waited until it got drained,
 362                 * we can now proceed and remove it.
 363                 */
 364                ret = iwl_mvm_rm_sta_common(mvm, sta_id);
 365                if (ret) {
 366                        IWL_ERR(mvm,
 367                                "Couldn't remove sta %d after it was drained\n",
 368                                sta_id);
 369                        continue;
 370                }
 371                rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], NULL);
 372                clear_bit(sta_id, mvm->sta_drained);
 373        }
 374
 375        mutex_unlock(&mvm->mutex);
 376}
 377
 378int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 379                   struct ieee80211_vif *vif,
 380                   struct ieee80211_sta *sta)
 381{
 382        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 383        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 384        int ret;
 385
 386        lockdep_assert_held(&mvm->mutex);
 387
 388        if (vif->type == NL80211_IFTYPE_STATION &&
 389            mvmvif->ap_sta_id == mvm_sta->sta_id) {
 390                /* flush its queues here since we are freeing mvm_sta */
 391                ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
 392
 393                /*
 394                 * Put a non-NULL since the fw station isn't removed.
 395                 * It will be removed after the MAC will be set as
 396                 * unassoc.
 397                 */
 398                rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
 399                                   ERR_PTR(-EINVAL));
 400
 401                /* if we are associated - we can't remove the AP STA now */
 402                if (vif->bss_conf.assoc)
 403                        return ret;
 404
 405                /* unassoc - go ahead - remove the AP STA now */
 406                mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
 407        }
 408
 409        /*
 410         * Make sure that the tx response code sees the station as -EBUSY and
 411         * calls the drain worker.
 412         */
 413        spin_lock_bh(&mvm_sta->lock);
 414        /*
 415         * There are frames pending on the AC queues for this station.
 416         * We need to wait until all the frames are drained...
 417         */
 418        if (atomic_read(&mvm->pending_frames[mvm_sta->sta_id])) {
 419                rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
 420                                   ERR_PTR(-EBUSY));
 421                spin_unlock_bh(&mvm_sta->lock);
 422                ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
 423        } else {
 424                spin_unlock_bh(&mvm_sta->lock);
 425                ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
 426                rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
 427        }
 428
 429        return ret;
 430}
 431
 432int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,
 433                      struct ieee80211_vif *vif,
 434                      u8 sta_id)
 435{
 436        int ret = iwl_mvm_rm_sta_common(mvm, sta_id);
 437
 438        lockdep_assert_held(&mvm->mutex);
 439
 440        rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], NULL);
 441        return ret;
 442}
 443
 444int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
 445                             u32 qmask)
 446{
 447        if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
 448                sta->sta_id = iwl_mvm_find_free_sta_id(mvm);
 449                if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_STATION_COUNT))
 450                        return -ENOSPC;
 451        }
 452
 453        sta->tfd_queue_msk = qmask;
 454
 455        /* put a non-NULL value so iterating over the stations won't stop */
 456        rcu_assign_pointer(mvm->fw_id_to_mac_id[sta->sta_id], ERR_PTR(-EINVAL));
 457        return 0;
 458}
 459
 460void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)
 461{
 462        rcu_assign_pointer(mvm->fw_id_to_mac_id[sta->sta_id], NULL);
 463        memset(sta, 0, sizeof(struct iwl_mvm_int_sta));
 464        sta->sta_id = IWL_MVM_STATION_COUNT;
 465}
 466
 467static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
 468                                      struct iwl_mvm_int_sta *sta,
 469                                      const u8 *addr,
 470                                      u16 mac_id, u16 color)
 471{
 472        struct iwl_mvm_add_sta_cmd cmd;
 473        int ret;
 474        u32 status;
 475
 476        lockdep_assert_held(&mvm->mutex);
 477
 478        memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd));
 479        cmd.sta_id = sta->sta_id;
 480        cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
 481                                                             color));
 482
 483        cmd.tfd_queue_msk = cpu_to_le32(sta->tfd_queue_msk);
 484
 485        if (addr)
 486                memcpy(cmd.addr, addr, ETH_ALEN);
 487
 488        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
 489                                          &cmd, &status);
 490        if (ret)
 491                return ret;
 492
 493        switch (status) {
 494        case ADD_STA_SUCCESS:
 495                IWL_DEBUG_INFO(mvm, "Internal station added.\n");
 496                return 0;
 497        default:
 498                ret = -EIO;
 499                IWL_ERR(mvm, "Add internal station failed, status=0x%x\n",
 500                        status);
 501                break;
 502        }
 503        return ret;
 504}
 505
 506int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
 507{
 508        int ret;
 509
 510        lockdep_assert_held(&mvm->mutex);
 511
 512        /* Add the aux station, but without any queues */
 513        ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0);
 514        if (ret)
 515                return ret;
 516
 517        ret = iwl_mvm_add_int_sta_common(mvm, &mvm->aux_sta, NULL,
 518                                         MAC_INDEX_AUX, 0);
 519
 520        if (ret)
 521                iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
 522        return ret;
 523}
 524
 525/*
 526 * Send the add station command for the vif's broadcast station.
 527 * Assumes that the station was already allocated.
 528 *
 529 * @mvm: the mvm component
 530 * @vif: the interface to which the broadcast station is added
 531 * @bsta: the broadcast station to add.
 532 */
 533int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 534                           struct iwl_mvm_int_sta *bsta)
 535{
 536        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 537        static const u8 baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 538
 539        lockdep_assert_held(&mvm->mutex);
 540
 541        if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT))
 542                return -ENOSPC;
 543
 544        return iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
 545                                          mvmvif->id, mvmvif->color);
 546}
 547
 548/* Send the FW a request to remove the station from it's internal data
 549 * structures, but DO NOT remove the entry from the local data structures. */
 550int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm,
 551                              struct iwl_mvm_int_sta *bsta)
 552{
 553        int ret;
 554
 555        lockdep_assert_held(&mvm->mutex);
 556
 557        ret = iwl_mvm_rm_sta_common(mvm, bsta->sta_id);
 558        if (ret)
 559                IWL_WARN(mvm, "Failed sending remove station\n");
 560        return ret;
 561}
 562
 563/* Allocate a new station entry for the broadcast station to the given vif,
 564 * and send it to the FW.
 565 * Note that each P2P mac should have its own broadcast station.
 566 *
 567 * @mvm: the mvm component
 568 * @vif: the interface to which the broadcast station is added
 569 * @bsta: the broadcast station to add. */
 570int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 571                          struct iwl_mvm_int_sta *bsta)
 572{
 573        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 574        static const u8 baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 575        u32 qmask;
 576        int ret;
 577
 578        lockdep_assert_held(&mvm->mutex);
 579
 580        qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
 581        ret = iwl_mvm_allocate_int_sta(mvm, bsta, qmask);
 582        if (ret)
 583                return ret;
 584
 585        ret = iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
 586                                         mvmvif->id, mvmvif->color);
 587
 588        if (ret)
 589                iwl_mvm_dealloc_int_sta(mvm, bsta);
 590        return ret;
 591}
 592
 593/*
 594 * Send the FW a request to remove the station from it's internal data
 595 * structures, and in addition remove it from the local data structure.
 596 */
 597int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta)
 598{
 599        int ret;
 600
 601        lockdep_assert_held(&mvm->mutex);
 602
 603        ret = iwl_mvm_rm_sta_common(mvm, bsta->sta_id);
 604        if (ret)
 605                return ret;
 606
 607        iwl_mvm_dealloc_int_sta(mvm, bsta);
 608        return ret;
 609}
 610
 611#define IWL_MAX_RX_BA_SESSIONS 16
 612
 613int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 614                       int tid, u16 ssn, bool start)
 615{
 616        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 617        struct iwl_mvm_add_sta_cmd cmd = {};
 618        int ret;
 619        u32 status;
 620
 621        lockdep_assert_held(&mvm->mutex);
 622
 623        if (start && mvm->rx_ba_sessions >= IWL_MAX_RX_BA_SESSIONS) {
 624                IWL_WARN(mvm, "Not enough RX BA SESSIONS\n");
 625                return -ENOSPC;
 626        }
 627
 628        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
 629        cmd.sta_id = mvm_sta->sta_id;
 630        cmd.add_modify = STA_MODE_MODIFY;
 631        if (start) {
 632                cmd.add_immediate_ba_tid = (u8) tid;
 633                cmd.add_immediate_ba_ssn = cpu_to_le16(ssn);
 634        } else {
 635                cmd.remove_immediate_ba_tid = (u8) tid;
 636        }
 637        cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID :
 638                                  STA_MODIFY_REMOVE_BA_TID;
 639
 640        status = ADD_STA_SUCCESS;
 641        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
 642                                          &cmd, &status);
 643        if (ret)
 644                return ret;
 645
 646        switch (status) {
 647        case ADD_STA_SUCCESS:
 648                IWL_DEBUG_INFO(mvm, "RX BA Session %sed in fw\n",
 649                               start ? "start" : "stopp");
 650                break;
 651        case ADD_STA_IMMEDIATE_BA_FAILURE:
 652                IWL_WARN(mvm, "RX BA Session refused by fw\n");
 653                ret = -ENOSPC;
 654                break;
 655        default:
 656                ret = -EIO;
 657                IWL_ERR(mvm, "RX BA Session failed %sing, status 0x%x\n",
 658                        start ? "start" : "stopp", status);
 659                break;
 660        }
 661
 662        if (!ret) {
 663                if (start)
 664                        mvm->rx_ba_sessions++;
 665                else if (mvm->rx_ba_sessions > 0)
 666                        /* check that restart flow didn't zero the counter */
 667                        mvm->rx_ba_sessions--;
 668        }
 669
 670        return ret;
 671}
 672
 673static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 674                              int tid, u8 queue, bool start)
 675{
 676        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 677        struct iwl_mvm_add_sta_cmd cmd = {};
 678        int ret;
 679        u32 status;
 680
 681        lockdep_assert_held(&mvm->mutex);
 682
 683        if (start) {
 684                mvm_sta->tfd_queue_msk |= BIT(queue);
 685                mvm_sta->tid_disable_agg &= ~BIT(tid);
 686        } else {
 687                mvm_sta->tfd_queue_msk &= ~BIT(queue);
 688                mvm_sta->tid_disable_agg |= BIT(tid);
 689        }
 690
 691        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
 692        cmd.sta_id = mvm_sta->sta_id;
 693        cmd.add_modify = STA_MODE_MODIFY;
 694        cmd.modify_mask = STA_MODIFY_QUEUES | STA_MODIFY_TID_DISABLE_TX;
 695        cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
 696        cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg);
 697
 698        status = ADD_STA_SUCCESS;
 699        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
 700                                          &cmd, &status);
 701        if (ret)
 702                return ret;
 703
 704        switch (status) {
 705        case ADD_STA_SUCCESS:
 706                break;
 707        default:
 708                ret = -EIO;
 709                IWL_ERR(mvm, "TX BA Session failed %sing, status 0x%x\n",
 710                        start ? "start" : "stopp", status);
 711                break;
 712        }
 713
 714        return ret;
 715}
 716
 717static const u8 tid_to_ac[] = {
 718        IEEE80211_AC_BE,
 719        IEEE80211_AC_BK,
 720        IEEE80211_AC_BK,
 721        IEEE80211_AC_BE,
 722        IEEE80211_AC_VI,
 723        IEEE80211_AC_VI,
 724        IEEE80211_AC_VO,
 725        IEEE80211_AC_VO,
 726};
 727
 728int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 729                             struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 730{
 731        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
 732        struct iwl_mvm_tid_data *tid_data;
 733        int txq_id;
 734
 735        if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
 736                return -EINVAL;
 737
 738        if (mvmsta->tid_data[tid].state != IWL_AGG_OFF) {
 739                IWL_ERR(mvm, "Start AGG when state is not IWL_AGG_OFF %d!\n",
 740                        mvmsta->tid_data[tid].state);
 741                return -ENXIO;
 742        }
 743
 744        lockdep_assert_held(&mvm->mutex);
 745
 746        for (txq_id = IWL_MVM_FIRST_AGG_QUEUE;
 747             txq_id <= IWL_MVM_LAST_AGG_QUEUE; txq_id++)
 748                if (mvm->queue_to_mac80211[txq_id] ==
 749                    IWL_INVALID_MAC80211_QUEUE)
 750                        break;
 751
 752        if (txq_id > IWL_MVM_LAST_AGG_QUEUE) {
 753                IWL_ERR(mvm, "Failed to allocate agg queue\n");
 754                return -EIO;
 755        }
 756
 757        /* the new tx queue is still connected to the same mac80211 queue */
 758        mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_ac[tid]];
 759
 760        spin_lock_bh(&mvmsta->lock);
 761        tid_data = &mvmsta->tid_data[tid];
 762        tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 763        tid_data->txq_id = txq_id;
 764        *ssn = tid_data->ssn;
 765
 766        IWL_DEBUG_TX_QUEUES(mvm,
 767                            "Start AGG: sta %d tid %d queue %d - ssn = %d, next_recl = %d\n",
 768                            mvmsta->sta_id, tid, txq_id, tid_data->ssn,
 769                            tid_data->next_reclaimed);
 770
 771        if (tid_data->ssn == tid_data->next_reclaimed) {
 772                tid_data->state = IWL_AGG_STARTING;
 773                ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 774        } else {
 775                tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA;
 776        }
 777
 778        spin_unlock_bh(&mvmsta->lock);
 779
 780        return 0;
 781}
 782
 783int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 784                            struct ieee80211_sta *sta, u16 tid, u8 buf_size)
 785{
 786        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
 787        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
 788        int queue, fifo, ret;
 789        u16 ssn;
 790
 791        buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
 792
 793        spin_lock_bh(&mvmsta->lock);
 794        ssn = tid_data->ssn;
 795        queue = tid_data->txq_id;
 796        tid_data->state = IWL_AGG_ON;
 797        tid_data->ssn = 0xffff;
 798        spin_unlock_bh(&mvmsta->lock);
 799
 800        fifo = iwl_mvm_ac_to_tx_fifo[tid_to_ac[tid]];
 801
 802        ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true);
 803        if (ret)
 804                return -EIO;
 805
 806        iwl_trans_txq_enable(mvm->trans, queue, fifo, mvmsta->sta_id, tid,
 807                             buf_size, ssn);
 808
 809        /*
 810         * Even though in theory the peer could have different
 811         * aggregation reorder buffer sizes for different sessions,
 812         * our ucode doesn't allow for that and has a global limit
 813         * for each station. Therefore, use the minimum of all the
 814         * aggregation sessions and our default value.
 815         */
 816        mvmsta->max_agg_bufsize =
 817                min(mvmsta->max_agg_bufsize, buf_size);
 818        mvmsta->lq_sta.lq.agg_frame_cnt_limit = mvmsta->max_agg_bufsize;
 819
 820        IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
 821                     sta->addr, tid);
 822
 823        if (mvm->cfg->ht_params->use_rts_for_aggregation) {
 824                /*
 825                 * switch to RTS/CTS if it is the prefer protection
 826                 * method for HT traffic
 827                 * this function also sends the LQ command
 828                 */
 829                return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq,
 830                                             mvmsta, true);
 831                /*
 832                 * TODO: remove the TLC_RTS flag when we tear down the last
 833                 * AGG session (agg_tids_count in DVM)
 834                 */
 835        }
 836
 837        return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, CMD_ASYNC, false);
 838}
 839
 840int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 841                            struct ieee80211_sta *sta, u16 tid)
 842{
 843        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
 844        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
 845        u16 txq_id;
 846        int err;
 847
 848
 849        /*
 850         * If mac80211 is cleaning its state, then say that we finished since
 851         * our state has been cleared anyway.
 852         */
 853        if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
 854                ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 855                return 0;
 856        }
 857
 858        spin_lock_bh(&mvmsta->lock);
 859
 860        txq_id = tid_data->txq_id;
 861
 862        IWL_DEBUG_TX_QUEUES(mvm, "Stop AGG: sta %d tid %d q %d state %d\n",
 863                            mvmsta->sta_id, tid, txq_id, tid_data->state);
 864
 865        switch (tid_data->state) {
 866        case IWL_AGG_ON:
 867                tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 868
 869                IWL_DEBUG_TX_QUEUES(mvm,
 870                                    "ssn = %d, next_recl = %d\n",
 871                                    tid_data->ssn, tid_data->next_reclaimed);
 872
 873                /* There are still packets for this RA / TID in the HW */
 874                if (tid_data->ssn != tid_data->next_reclaimed) {
 875                        tid_data->state = IWL_EMPTYING_HW_QUEUE_DELBA;
 876                        err = 0;
 877                        break;
 878                }
 879
 880                tid_data->ssn = 0xffff;
 881                iwl_trans_txq_disable(mvm->trans, txq_id);
 882                /* fall through */
 883        case IWL_AGG_STARTING:
 884        case IWL_EMPTYING_HW_QUEUE_ADDBA:
 885                /*
 886                 * The agg session has been stopped before it was set up. This
 887                 * can happen when the AddBA timer times out for example.
 888                 */
 889
 890                /* No barriers since we are under mutex */
 891                lockdep_assert_held(&mvm->mutex);
 892                mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE;
 893
 894                ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 895                tid_data->state = IWL_AGG_OFF;
 896                err = 0;
 897                break;
 898        default:
 899                IWL_ERR(mvm,
 900                        "Stopping AGG while state not ON or starting for %d on %d (%d)\n",
 901                        mvmsta->sta_id, tid, tid_data->state);
 902                IWL_ERR(mvm,
 903                        "\ttid_data->txq_id = %d\n", tid_data->txq_id);
 904                err = -EINVAL;
 905        }
 906
 907        spin_unlock_bh(&mvmsta->lock);
 908
 909        return err;
 910}
 911
 912int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 913                            struct ieee80211_sta *sta, u16 tid)
 914{
 915        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
 916        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
 917        u16 txq_id;
 918        enum iwl_mvm_agg_state old_state;
 919
 920        /*
 921         * First set the agg state to OFF to avoid calling
 922         * ieee80211_stop_tx_ba_cb in iwl_mvm_check_ratid_empty.
 923         */
 924        spin_lock_bh(&mvmsta->lock);
 925        txq_id = tid_data->txq_id;
 926        IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n",
 927                            mvmsta->sta_id, tid, txq_id, tid_data->state);
 928        old_state = tid_data->state;
 929        tid_data->state = IWL_AGG_OFF;
 930        spin_unlock_bh(&mvmsta->lock);
 931
 932        if (old_state >= IWL_AGG_ON) {
 933                if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
 934                        IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
 935
 936                iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
 937        }
 938
 939        mvm->queue_to_mac80211[tid_data->txq_id] =
 940                                IWL_INVALID_MAC80211_QUEUE;
 941
 942        return 0;
 943}
 944
 945static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
 946{
 947        int i;
 948
 949        lockdep_assert_held(&mvm->mutex);
 950
 951        i = find_first_zero_bit(mvm->fw_key_table, STA_KEY_MAX_NUM);
 952
 953        if (i == STA_KEY_MAX_NUM)
 954                return STA_KEY_IDX_INVALID;
 955
 956        __set_bit(i, mvm->fw_key_table);
 957
 958        return i;
 959}
 960
 961static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
 962                                 struct ieee80211_sta *sta)
 963{
 964        struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
 965
 966        if (sta) {
 967                struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 968
 969                return mvm_sta->sta_id;
 970        }
 971
 972        /*
 973         * The device expects GTKs for station interfaces to be
 974         * installed as GTKs for the AP station. If we have no
 975         * station ID, then use AP's station ID.
 976         */
 977        if (vif->type == NL80211_IFTYPE_STATION &&
 978            mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT)
 979                return mvmvif->ap_sta_id;
 980
 981        return IWL_MVM_STATION_COUNT;
 982}
 983
 984static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
 985                                struct iwl_mvm_sta *mvm_sta,
 986                                struct ieee80211_key_conf *keyconf,
 987                                u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
 988                                u32 cmd_flags)
 989{
 990        __le16 key_flags;
 991        struct iwl_mvm_add_sta_cmd cmd = {};
 992        int ret, status;
 993        u16 keyidx;
 994        int i;
 995
 996        keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
 997                 STA_KEY_FLG_KEYID_MSK;
 998        key_flags = cpu_to_le16(keyidx);
 999        key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_KEY_MAP);
1000
1001        switch (keyconf->cipher) {
1002        case WLAN_CIPHER_SUITE_TKIP:
1003                key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP);
1004                cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
1005                for (i = 0; i < 5; i++)
1006                        cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
1007                memcpy(cmd.key.key, keyconf->key, keyconf->keylen);
1008                break;
1009        case WLAN_CIPHER_SUITE_CCMP:
1010                key_flags |= cpu_to_le16(STA_KEY_FLG_CCM);
1011                memcpy(cmd.key.key, keyconf->key, keyconf->keylen);
1012                break;
1013        default:
1014                WARN_ON(1);
1015                return -EINVAL;
1016        }
1017
1018        if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
1019                key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
1020
1021        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
1022        cmd.key.key_offset = keyconf->hw_key_idx;
1023        cmd.key.key_flags = key_flags;
1024        cmd.add_modify = STA_MODE_MODIFY;
1025        cmd.modify_mask = STA_MODIFY_KEY;
1026        cmd.sta_id = sta_id;
1027
1028        status = ADD_STA_SUCCESS;
1029        if (cmd_flags == CMD_SYNC)
1030                ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
1031                                                  &cmd, &status);
1032        else
1033                ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC,
1034                                           sizeof(cmd), &cmd);
1035
1036        switch (status) {
1037        case ADD_STA_SUCCESS:
1038                IWL_DEBUG_WEP(mvm, "MODIFY_STA: set dynamic key passed\n");
1039                break;
1040        default:
1041                ret = -EIO;
1042                IWL_ERR(mvm, "MODIFY_STA: set dynamic key failed\n");
1043                break;
1044        }
1045
1046        return ret;
1047}
1048
1049static int iwl_mvm_send_sta_igtk(struct iwl_mvm *mvm,
1050                                 struct ieee80211_key_conf *keyconf,
1051                                 u8 sta_id, bool remove_key)
1052{
1053        struct iwl_mvm_mgmt_mcast_key_cmd igtk_cmd = {};
1054
1055        /* verify the key details match the required command's expectations */
1056        if (WARN_ON((keyconf->cipher != WLAN_CIPHER_SUITE_AES_CMAC) ||
1057                    (keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE) ||
1058                    (keyconf->keyidx != 4 && keyconf->keyidx != 5)))
1059                return -EINVAL;
1060
1061        igtk_cmd.key_id = cpu_to_le32(keyconf->keyidx);
1062        igtk_cmd.sta_id = cpu_to_le32(sta_id);
1063
1064        if (remove_key) {
1065                igtk_cmd.ctrl_flags |= cpu_to_le32(STA_KEY_NOT_VALID);
1066        } else {
1067                struct ieee80211_key_seq seq;
1068                const u8 *pn;
1069
1070                memcpy(igtk_cmd.IGTK, keyconf->key, keyconf->keylen);
1071                ieee80211_aes_cmac_calculate_k1_k2(keyconf,
1072                                                   igtk_cmd.K1, igtk_cmd.K2);
1073                ieee80211_get_key_rx_seq(keyconf, 0, &seq);
1074                pn = seq.aes_cmac.pn;
1075                igtk_cmd.receive_seq_cnt = cpu_to_le64(((u64) pn[5] << 0) |
1076                                                       ((u64) pn[4] << 8) |
1077                                                       ((u64) pn[3] << 16) |
1078                                                       ((u64) pn[2] << 24) |
1079                                                       ((u64) pn[1] << 32) |
1080                                                       ((u64) pn[0] << 40));
1081        }
1082
1083        IWL_DEBUG_INFO(mvm, "%s igtk for sta %u\n",
1084                       remove_key ? "removing" : "installing",
1085                       igtk_cmd.sta_id);
1086
1087        return iwl_mvm_send_cmd_pdu(mvm, MGMT_MCAST_KEY, CMD_SYNC,
1088                                    sizeof(igtk_cmd), &igtk_cmd);
1089}
1090
1091
1092static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
1093                                       struct ieee80211_vif *vif,
1094                                       struct ieee80211_sta *sta)
1095{
1096        struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1097
1098        if (sta)
1099                return sta->addr;
1100
1101        if (vif->type == NL80211_IFTYPE_STATION &&
1102            mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
1103                u8 sta_id = mvmvif->ap_sta_id;
1104                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
1105                                                lockdep_is_held(&mvm->mutex));
1106                return sta->addr;
1107        }
1108
1109
1110        return NULL;
1111}
1112
1113int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
1114                        struct ieee80211_vif *vif,
1115                        struct ieee80211_sta *sta,
1116                        struct ieee80211_key_conf *keyconf,
1117                        bool have_key_offset)
1118{
1119        struct iwl_mvm_sta *mvm_sta;
1120        int ret;
1121        u8 *addr, sta_id;
1122        struct ieee80211_key_seq seq;
1123        u16 p1k[5];
1124
1125        lockdep_assert_held(&mvm->mutex);
1126
1127        /* Get the station id from the mvm local station table */
1128        sta_id = iwl_mvm_get_key_sta_id(vif, sta);
1129        if (sta_id == IWL_MVM_STATION_COUNT) {
1130                IWL_ERR(mvm, "Failed to find station id\n");
1131                return -EINVAL;
1132        }
1133
1134        if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
1135                ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, false);
1136                goto end;
1137        }
1138
1139        /*
1140         * It is possible that the 'sta' parameter is NULL, and thus
1141         * there is a need to retrieve  the sta from the local station table.
1142         */
1143        if (!sta) {
1144                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
1145                                                lockdep_is_held(&mvm->mutex));
1146                if (IS_ERR_OR_NULL(sta)) {
1147                        IWL_ERR(mvm, "Invalid station id\n");
1148                        return -EINVAL;
1149                }
1150        }
1151
1152        mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv;
1153        if (WARN_ON_ONCE(mvm_sta->vif != vif))
1154                return -EINVAL;
1155
1156        if (!have_key_offset) {
1157                /*
1158                 * The D3 firmware hardcodes the PTK offset to 0, so we have to
1159                 * configure it there. As a result, this workaround exists to
1160                 * let the caller set the key offset (hw_key_idx), see d3.c.
1161                 */
1162                keyconf->hw_key_idx = iwl_mvm_set_fw_key_idx(mvm);
1163                if (keyconf->hw_key_idx == STA_KEY_IDX_INVALID)
1164                        return -ENOSPC;
1165        }
1166
1167        switch (keyconf->cipher) {
1168        case WLAN_CIPHER_SUITE_TKIP:
1169                addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
1170                /* get phase 1 key from mac80211 */
1171                ieee80211_get_key_rx_seq(keyconf, 0, &seq);
1172                ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
1173                ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
1174                                           seq.tkip.iv32, p1k, CMD_SYNC);
1175                break;
1176        case WLAN_CIPHER_SUITE_CCMP:
1177                ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
1178                                           0, NULL, CMD_SYNC);
1179                break;
1180        default:
1181                IWL_ERR(mvm, "Unknown cipher %x\n", keyconf->cipher);
1182                ret = -EINVAL;
1183        }
1184
1185        if (ret)
1186                __clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
1187
1188end:
1189        IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
1190                      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
1191                      sta->addr, ret);
1192        return ret;
1193}
1194
1195int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
1196                           struct ieee80211_vif *vif,
1197                           struct ieee80211_sta *sta,
1198                           struct ieee80211_key_conf *keyconf)
1199{
1200        struct iwl_mvm_sta *mvm_sta;
1201        struct iwl_mvm_add_sta_cmd cmd = {};
1202        __le16 key_flags;
1203        int ret, status;
1204        u8 sta_id;
1205
1206        lockdep_assert_held(&mvm->mutex);
1207
1208        /* Get the station id from the mvm local station table */
1209        sta_id = iwl_mvm_get_key_sta_id(vif, sta);
1210
1211        IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
1212                      keyconf->keyidx, sta_id);
1213
1214        if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
1215                return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
1216
1217        ret = __test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
1218        if (!ret) {
1219                IWL_ERR(mvm, "offset %d not used in fw key table.\n",
1220                        keyconf->hw_key_idx);
1221                return -ENOENT;
1222        }
1223
1224        if (sta_id == IWL_MVM_STATION_COUNT) {
1225                IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
1226                return 0;
1227        }
1228
1229        /*
1230         * It is possible that the 'sta' parameter is NULL, and thus
1231         * there is a need to retrieve the sta from the local station table,
1232         * for example when a GTK is removed (where the sta_id will then be
1233         * the AP ID, and no station was passed by mac80211.)
1234         */
1235        if (!sta) {
1236                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
1237                                                lockdep_is_held(&mvm->mutex));
1238                if (!sta) {
1239                        IWL_ERR(mvm, "Invalid station id\n");
1240                        return -EINVAL;
1241                }
1242        }
1243
1244        mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv;
1245        if (WARN_ON_ONCE(mvm_sta->vif != vif))
1246                return -EINVAL;
1247
1248        key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
1249                                 STA_KEY_FLG_KEYID_MSK);
1250        key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
1251        key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
1252
1253        if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
1254                key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
1255
1256        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
1257        cmd.key.key_flags = key_flags;
1258        cmd.key.key_offset = keyconf->hw_key_idx;
1259        cmd.sta_id = sta_id;
1260
1261        cmd.modify_mask = STA_MODIFY_KEY;
1262        cmd.add_modify = STA_MODE_MODIFY;
1263
1264        status = ADD_STA_SUCCESS;
1265        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
1266                                          &cmd, &status);
1267
1268        switch (status) {
1269        case ADD_STA_SUCCESS:
1270                IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
1271                break;
1272        default:
1273                ret = -EIO;
1274                IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
1275                break;
1276        }
1277
1278        return ret;
1279}
1280
1281void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
1282                             struct ieee80211_vif *vif,
1283                             struct ieee80211_key_conf *keyconf,
1284                             struct ieee80211_sta *sta, u32 iv32,
1285                             u16 *phase1key)
1286{
1287        struct iwl_mvm_sta *mvm_sta;
1288        u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
1289
1290        if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
1291                return;
1292
1293        rcu_read_lock();
1294
1295        if (!sta) {
1296                sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
1297                if (WARN_ON(IS_ERR_OR_NULL(sta))) {
1298                        rcu_read_unlock();
1299                        return;
1300                }
1301        }
1302
1303        mvm_sta = (void *)sta->drv_priv;
1304        iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
1305                             iv32, phase1key, CMD_ASYNC);
1306        rcu_read_unlock();
1307}
1308
1309void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
1310                                struct ieee80211_sta *sta)
1311{
1312        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
1313        struct iwl_mvm_add_sta_cmd cmd = {
1314                .add_modify = STA_MODE_MODIFY,
1315                .sta_id = mvmsta->sta_id,
1316                .station_flags_msk = cpu_to_le32(STA_FLG_PS),
1317                .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
1318        };
1319        int ret;
1320
1321        ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
1322        if (ret)
1323                IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
1324}
1325
1326void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
1327                                       struct ieee80211_sta *sta,
1328                                       enum ieee80211_frame_release_type reason,
1329                                       u16 cnt)
1330{
1331        u16 sleep_state_flags =
1332                (reason == IEEE80211_FRAME_RELEASE_UAPSD) ?
1333                        STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL;
1334        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
1335        struct iwl_mvm_add_sta_cmd cmd = {
1336                .add_modify = STA_MODE_MODIFY,
1337                .sta_id = mvmsta->sta_id,
1338                .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
1339                .sleep_tx_count = cpu_to_le16(cnt),
1340                .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
1341                /*
1342                 * Same modify mask for sleep_tx_count and sleep_state_flags so
1343                 * we must set the sleep_state_flags too.
1344                 */
1345                .sleep_state_flags = cpu_to_le16(sleep_state_flags),
1346        };
1347        int ret;
1348
1349        /* TODO: somehow the fw doesn't seem to take PS_POLL into account */
1350        ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
1351        if (ret)
1352                IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
1353}
1354