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
  68static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm)
  69{
  70        int sta_id;
  71
  72        WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
  73
  74        lockdep_assert_held(&mvm->mutex);
  75
  76        /* Don't take rcu_read_lock() since we are protected by mvm->mutex */
  77        for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++)
  78                if (!rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
  79                                               lockdep_is_held(&mvm->mutex)))
  80                        return sta_id;
  81        return IWL_MVM_STATION_COUNT;
  82}
  83
  84/* send station add/update command to firmware */
  85int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
  86                           bool update)
  87{
  88        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
  89        struct iwl_mvm_add_sta_cmd add_sta_cmd;
  90        int ret;
  91        u32 status;
  92        u32 agg_size = 0, mpdu_dens = 0;
  93
  94        memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
  95
  96        add_sta_cmd.sta_id = mvm_sta->sta_id;
  97        add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
  98        if (!update) {
  99                add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
 100                memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
 101        }
 102        add_sta_cmd.add_modify = update ? 1 : 0;
 103
 104        add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
 105                                                     STA_FLG_MIMO_EN_MSK);
 106
 107        switch (sta->bandwidth) {
 108        case IEEE80211_STA_RX_BW_160:
 109                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ);
 110                /* fall through */
 111        case IEEE80211_STA_RX_BW_80:
 112                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ);
 113                /* fall through */
 114        case IEEE80211_STA_RX_BW_40:
 115                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ);
 116                /* fall through */
 117        case IEEE80211_STA_RX_BW_20:
 118                if (sta->ht_cap.ht_supported)
 119                        add_sta_cmd.station_flags |=
 120                                cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
 121                break;
 122        }
 123
 124        switch (sta->rx_nss) {
 125        case 1:
 126                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
 127                break;
 128        case 2:
 129                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO2);
 130                break;
 131        case 3 ... 8:
 132                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO3);
 133                break;
 134        }
 135
 136        switch (sta->smps_mode) {
 137        case IEEE80211_SMPS_AUTOMATIC:
 138        case IEEE80211_SMPS_NUM_MODES:
 139                WARN_ON(1);
 140                break;
 141        case IEEE80211_SMPS_STATIC:
 142                /* override NSS */
 143                add_sta_cmd.station_flags &= ~cpu_to_le32(STA_FLG_MIMO_EN_MSK);
 144                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
 145                break;
 146        case IEEE80211_SMPS_DYNAMIC:
 147                add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_RTS_MIMO_PROT);
 148                break;
 149        case IEEE80211_SMPS_OFF:
 150                /* nothing */
 151                break;
 152        }
 153
 154        if (sta->ht_cap.ht_supported) {
 155                add_sta_cmd.station_flags_msk |=
 156                        cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK |
 157                                    STA_FLG_AGG_MPDU_DENS_MSK);
 158
 159                mpdu_dens = sta->ht_cap.ampdu_density;
 160        }
 161
 162        if (sta->vht_cap.vht_supported) {
 163                agg_size = sta->vht_cap.cap &
 164                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
 165                agg_size >>=
 166                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
 167        } else if (sta->ht_cap.ht_supported) {
 168                agg_size = sta->ht_cap.ampdu_factor;
 169        }
 170
 171        add_sta_cmd.station_flags |=
 172                cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
 173        add_sta_cmd.station_flags |=
 174                cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
 175
 176        status = ADD_STA_SUCCESS;
 177        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(add_sta_cmd),
 178                                          &add_sta_cmd, &status);
 179        if (ret)
 180                return ret;
 181
 182        switch (status) {
 183        case ADD_STA_SUCCESS:
 184                IWL_DEBUG_ASSOC(mvm, "ADD_STA PASSED\n");
 185                break;
 186        default:
 187                ret = -EIO;
 188                IWL_ERR(mvm, "ADD_STA failed\n");
 189                break;
 190        }
 191
 192        return ret;
 193}
 194
 195int iwl_mvm_add_sta(struct iwl_mvm *mvm,
 196                    struct ieee80211_vif *vif,
 197                    struct ieee80211_sta *sta)
 198{
 199        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 200        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 201        int i, ret, sta_id;
 202
 203        lockdep_assert_held(&mvm->mutex);
 204
 205        if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
 206                sta_id = iwl_mvm_find_free_sta_id(mvm);
 207        else
 208                sta_id = mvm_sta->sta_id;
 209
 210        if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
 211                return -ENOSPC;
 212
 213        spin_lock_init(&mvm_sta->lock);
 214
 215        mvm_sta->sta_id = sta_id;
 216        mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
 217                                                      mvmvif->color);
 218        mvm_sta->vif = vif;
 219        mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 220
 221        /* HW restart, don't assume the memory has been zeroed */
 222        atomic_set(&mvm->pending_frames[sta_id], 0);
 223        mvm_sta->tid_disable_agg = 0;
 224        mvm_sta->tfd_queue_msk = 0;
 225        for (i = 0; i < IEEE80211_NUM_ACS; i++)
 226                if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
 227                        mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
 228
 229        if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
 230                mvm_sta->tfd_queue_msk |= BIT(vif->cab_queue);
 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
 611int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 612                       int tid, u16 ssn, bool start)
 613{
 614        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 615        struct iwl_mvm_add_sta_cmd cmd = {};
 616        int ret;
 617        u32 status;
 618
 619        lockdep_assert_held(&mvm->mutex);
 620
 621        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
 622        cmd.sta_id = mvm_sta->sta_id;
 623        cmd.add_modify = STA_MODE_MODIFY;
 624        cmd.add_immediate_ba_tid = (u8) tid;
 625        cmd.add_immediate_ba_ssn = cpu_to_le16(ssn);
 626        cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID :
 627                                  STA_MODIFY_REMOVE_BA_TID;
 628
 629        status = ADD_STA_SUCCESS;
 630        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
 631                                          &cmd, &status);
 632        if (ret)
 633                return ret;
 634
 635        switch (status) {
 636        case ADD_STA_SUCCESS:
 637                IWL_DEBUG_INFO(mvm, "RX BA Session %sed in fw\n",
 638                               start ? "start" : "stopp");
 639                break;
 640        case ADD_STA_IMMEDIATE_BA_FAILURE:
 641                IWL_WARN(mvm, "RX BA Session refused by fw\n");
 642                ret = -ENOSPC;
 643                break;
 644        default:
 645                ret = -EIO;
 646                IWL_ERR(mvm, "RX BA Session failed %sing, status 0x%x\n",
 647                        start ? "start" : "stopp", status);
 648                break;
 649        }
 650
 651        return ret;
 652}
 653
 654static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 655                              int tid, u8 queue, bool start)
 656{
 657        struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 658        struct iwl_mvm_add_sta_cmd cmd = {};
 659        int ret;
 660        u32 status;
 661
 662        lockdep_assert_held(&mvm->mutex);
 663
 664        if (start) {
 665                mvm_sta->tfd_queue_msk |= BIT(queue);
 666                mvm_sta->tid_disable_agg &= ~BIT(tid);
 667        } else {
 668                mvm_sta->tfd_queue_msk &= ~BIT(queue);
 669                mvm_sta->tid_disable_agg |= BIT(tid);
 670        }
 671
 672        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
 673        cmd.sta_id = mvm_sta->sta_id;
 674        cmd.add_modify = STA_MODE_MODIFY;
 675        cmd.modify_mask = STA_MODIFY_QUEUES | STA_MODIFY_TID_DISABLE_TX;
 676        cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
 677        cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg);
 678
 679        status = ADD_STA_SUCCESS;
 680        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
 681                                          &cmd, &status);
 682        if (ret)
 683                return ret;
 684
 685        switch (status) {
 686        case ADD_STA_SUCCESS:
 687                break;
 688        default:
 689                ret = -EIO;
 690                IWL_ERR(mvm, "TX BA Session failed %sing, status 0x%x\n",
 691                        start ? "start" : "stopp", status);
 692                break;
 693        }
 694
 695        return ret;
 696}
 697
 698static const u8 tid_to_ac[] = {
 699        IEEE80211_AC_BE,
 700        IEEE80211_AC_BK,
 701        IEEE80211_AC_BK,
 702        IEEE80211_AC_BE,
 703        IEEE80211_AC_VI,
 704        IEEE80211_AC_VI,
 705        IEEE80211_AC_VO,
 706        IEEE80211_AC_VO,
 707};
 708
 709int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 710                             struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 711{
 712        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
 713        struct iwl_mvm_tid_data *tid_data;
 714        int txq_id;
 715
 716        if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
 717                return -EINVAL;
 718
 719        if (mvmsta->tid_data[tid].state != IWL_AGG_OFF) {
 720                IWL_ERR(mvm, "Start AGG when state is not IWL_AGG_OFF %d!\n",
 721                        mvmsta->tid_data[tid].state);
 722                return -ENXIO;
 723        }
 724
 725        lockdep_assert_held(&mvm->mutex);
 726
 727        for (txq_id = IWL_MVM_FIRST_AGG_QUEUE;
 728             txq_id <= IWL_MVM_LAST_AGG_QUEUE; txq_id++)
 729                if (mvm->queue_to_mac80211[txq_id] ==
 730                    IWL_INVALID_MAC80211_QUEUE)
 731                        break;
 732
 733        if (txq_id > IWL_MVM_LAST_AGG_QUEUE) {
 734                IWL_ERR(mvm, "Failed to allocate agg queue\n");
 735                return -EIO;
 736        }
 737
 738        /* the new tx queue is still connected to the same mac80211 queue */
 739        mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_ac[tid]];
 740
 741        spin_lock_bh(&mvmsta->lock);
 742        tid_data = &mvmsta->tid_data[tid];
 743        tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 744        tid_data->txq_id = txq_id;
 745        *ssn = tid_data->ssn;
 746
 747        IWL_DEBUG_TX_QUEUES(mvm,
 748                            "Start AGG: sta %d tid %d queue %d - ssn = %d, next_recl = %d\n",
 749                            mvmsta->sta_id, tid, txq_id, tid_data->ssn,
 750                            tid_data->next_reclaimed);
 751
 752        if (tid_data->ssn == tid_data->next_reclaimed) {
 753                tid_data->state = IWL_AGG_STARTING;
 754                ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 755        } else {
 756                tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA;
 757        }
 758
 759        spin_unlock_bh(&mvmsta->lock);
 760
 761        return 0;
 762}
 763
 764int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 765                            struct ieee80211_sta *sta, u16 tid, u8 buf_size)
 766{
 767        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
 768        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
 769        int queue, fifo, ret;
 770        u16 ssn;
 771
 772        buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
 773
 774        spin_lock_bh(&mvmsta->lock);
 775        ssn = tid_data->ssn;
 776        queue = tid_data->txq_id;
 777        tid_data->state = IWL_AGG_ON;
 778        tid_data->ssn = 0xffff;
 779        spin_unlock_bh(&mvmsta->lock);
 780
 781        fifo = iwl_mvm_ac_to_tx_fifo[tid_to_ac[tid]];
 782
 783        ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true);
 784        if (ret)
 785                return -EIO;
 786
 787        iwl_trans_txq_enable(mvm->trans, queue, fifo, mvmsta->sta_id, tid,
 788                             buf_size, ssn);
 789
 790        /*
 791         * Even though in theory the peer could have different
 792         * aggregation reorder buffer sizes for different sessions,
 793         * our ucode doesn't allow for that and has a global limit
 794         * for each station. Therefore, use the minimum of all the
 795         * aggregation sessions and our default value.
 796         */
 797        mvmsta->max_agg_bufsize =
 798                min(mvmsta->max_agg_bufsize, buf_size);
 799        mvmsta->lq_sta.lq.agg_frame_cnt_limit = mvmsta->max_agg_bufsize;
 800
 801        if (mvm->cfg->ht_params->use_rts_for_aggregation) {
 802                /*
 803                 * switch to RTS/CTS if it is the prefer protection
 804                 * method for HT traffic
 805                 */
 806                mvmsta->lq_sta.lq.flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK;
 807                /*
 808                 * TODO: remove the TLC_RTS flag when we tear down the last
 809                 * AGG session (agg_tids_count in DVM)
 810                 */
 811        }
 812
 813        IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
 814                     sta->addr, tid);
 815
 816        return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, CMD_ASYNC, false);
 817}
 818
 819int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 820                            struct ieee80211_sta *sta, u16 tid)
 821{
 822        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
 823        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
 824        u16 txq_id;
 825        int err;
 826
 827
 828        /*
 829         * If mac80211 is cleaning its state, then say that we finished since
 830         * our state has been cleared anyway.
 831         */
 832        if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
 833                ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 834                return 0;
 835        }
 836
 837        spin_lock_bh(&mvmsta->lock);
 838
 839        txq_id = tid_data->txq_id;
 840
 841        IWL_DEBUG_TX_QUEUES(mvm, "Stop AGG: sta %d tid %d q %d state %d\n",
 842                            mvmsta->sta_id, tid, txq_id, tid_data->state);
 843
 844        switch (tid_data->state) {
 845        case IWL_AGG_ON:
 846                tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
 847
 848                IWL_DEBUG_TX_QUEUES(mvm,
 849                                    "ssn = %d, next_recl = %d\n",
 850                                    tid_data->ssn, tid_data->next_reclaimed);
 851
 852                /* There are still packets for this RA / TID in the HW */
 853                if (tid_data->ssn != tid_data->next_reclaimed) {
 854                        tid_data->state = IWL_EMPTYING_HW_QUEUE_DELBA;
 855                        err = 0;
 856                        break;
 857                }
 858
 859                tid_data->ssn = 0xffff;
 860                iwl_trans_txq_disable(mvm->trans, txq_id);
 861                /* fall through */
 862        case IWL_AGG_STARTING:
 863        case IWL_EMPTYING_HW_QUEUE_ADDBA:
 864                /*
 865                 * The agg session has been stopped before it was set up. This
 866                 * can happen when the AddBA timer times out for example.
 867                 */
 868
 869                /* No barriers since we are under mutex */
 870                lockdep_assert_held(&mvm->mutex);
 871                mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE;
 872
 873                ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 874                tid_data->state = IWL_AGG_OFF;
 875                err = 0;
 876                break;
 877        default:
 878                IWL_ERR(mvm,
 879                        "Stopping AGG while state not ON or starting for %d on %d (%d)\n",
 880                        mvmsta->sta_id, tid, tid_data->state);
 881                IWL_ERR(mvm,
 882                        "\ttid_data->txq_id = %d\n", tid_data->txq_id);
 883                err = -EINVAL;
 884        }
 885
 886        spin_unlock_bh(&mvmsta->lock);
 887
 888        return err;
 889}
 890
 891int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 892                            struct ieee80211_sta *sta, u16 tid)
 893{
 894        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
 895        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
 896        u16 txq_id;
 897
 898        /*
 899         * First set the agg state to OFF to avoid calling
 900         * ieee80211_stop_tx_ba_cb in iwl_mvm_check_ratid_empty.
 901         */
 902        spin_lock_bh(&mvmsta->lock);
 903        txq_id = tid_data->txq_id;
 904        IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n",
 905                            mvmsta->sta_id, tid, txq_id, tid_data->state);
 906        tid_data->state = IWL_AGG_OFF;
 907        spin_unlock_bh(&mvmsta->lock);
 908
 909        if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
 910                IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
 911
 912        iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
 913        mvm->queue_to_mac80211[tid_data->txq_id] =
 914                                IWL_INVALID_MAC80211_QUEUE;
 915
 916        return 0;
 917}
 918
 919static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
 920{
 921        int i;
 922
 923        lockdep_assert_held(&mvm->mutex);
 924
 925        i = find_first_zero_bit(mvm->fw_key_table, STA_KEY_MAX_NUM);
 926
 927        if (i == STA_KEY_MAX_NUM)
 928                return STA_KEY_IDX_INVALID;
 929
 930        __set_bit(i, mvm->fw_key_table);
 931
 932        return i;
 933}
 934
 935static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
 936                                 struct ieee80211_sta *sta)
 937{
 938        struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
 939
 940        if (sta) {
 941                struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
 942
 943                return mvm_sta->sta_id;
 944        }
 945
 946        /*
 947         * The device expects GTKs for station interfaces to be
 948         * installed as GTKs for the AP station. If we have no
 949         * station ID, then use AP's station ID.
 950         */
 951        if (vif->type == NL80211_IFTYPE_STATION &&
 952            mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT)
 953                return mvmvif->ap_sta_id;
 954
 955        return IWL_MVM_STATION_COUNT;
 956}
 957
 958static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
 959                                struct iwl_mvm_sta *mvm_sta,
 960                                struct ieee80211_key_conf *keyconf,
 961                                u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
 962                                u32 cmd_flags)
 963{
 964        __le16 key_flags;
 965        struct iwl_mvm_add_sta_cmd cmd = {};
 966        int ret, status;
 967        u16 keyidx;
 968        int i;
 969
 970        keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
 971                 STA_KEY_FLG_KEYID_MSK;
 972        key_flags = cpu_to_le16(keyidx);
 973        key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_KEY_MAP);
 974
 975        switch (keyconf->cipher) {
 976        case WLAN_CIPHER_SUITE_TKIP:
 977                key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP);
 978                cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
 979                for (i = 0; i < 5; i++)
 980                        cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
 981                memcpy(cmd.key.key, keyconf->key, keyconf->keylen);
 982                break;
 983        case WLAN_CIPHER_SUITE_CCMP:
 984                key_flags |= cpu_to_le16(STA_KEY_FLG_CCM);
 985                memcpy(cmd.key.key, keyconf->key, keyconf->keylen);
 986                break;
 987        default:
 988                WARN_ON(1);
 989                return -EINVAL;
 990        }
 991
 992        if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 993                key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
 994
 995        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
 996        cmd.key.key_offset = keyconf->hw_key_idx;
 997        cmd.key.key_flags = key_flags;
 998        cmd.add_modify = STA_MODE_MODIFY;
 999        cmd.modify_mask = STA_MODIFY_KEY;
1000        cmd.sta_id = sta_id;
1001
1002        status = ADD_STA_SUCCESS;
1003        if (cmd_flags == CMD_SYNC)
1004                ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
1005                                                  &cmd, &status);
1006        else
1007                ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC,
1008                                           sizeof(cmd), &cmd);
1009
1010        switch (status) {
1011        case ADD_STA_SUCCESS:
1012                IWL_DEBUG_WEP(mvm, "MODIFY_STA: set dynamic key passed\n");
1013                break;
1014        default:
1015                ret = -EIO;
1016                IWL_ERR(mvm, "MODIFY_STA: set dynamic key failed\n");
1017                break;
1018        }
1019
1020        return ret;
1021}
1022
1023static int iwl_mvm_send_sta_igtk(struct iwl_mvm *mvm,
1024                                 struct ieee80211_key_conf *keyconf,
1025                                 u8 sta_id, bool remove_key)
1026{
1027        struct iwl_mvm_mgmt_mcast_key_cmd igtk_cmd = {};
1028
1029        /* verify the key details match the required command's expectations */
1030        if (WARN_ON((keyconf->cipher != WLAN_CIPHER_SUITE_AES_CMAC) ||
1031                    (keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE) ||
1032                    (keyconf->keyidx != 4 && keyconf->keyidx != 5)))
1033                return -EINVAL;
1034
1035        igtk_cmd.key_id = cpu_to_le32(keyconf->keyidx);
1036        igtk_cmd.sta_id = cpu_to_le32(sta_id);
1037
1038        if (remove_key) {
1039                igtk_cmd.ctrl_flags |= cpu_to_le32(STA_KEY_NOT_VALID);
1040        } else {
1041                struct ieee80211_key_seq seq;
1042                const u8 *pn;
1043
1044                memcpy(igtk_cmd.IGTK, keyconf->key, keyconf->keylen);
1045                ieee80211_aes_cmac_calculate_k1_k2(keyconf,
1046                                                   igtk_cmd.K1, igtk_cmd.K2);
1047                ieee80211_get_key_rx_seq(keyconf, 0, &seq);
1048                pn = seq.aes_cmac.pn;
1049                igtk_cmd.receive_seq_cnt = cpu_to_le64(((u64) pn[5] << 0) |
1050                                                       ((u64) pn[4] << 8) |
1051                                                       ((u64) pn[3] << 16) |
1052                                                       ((u64) pn[2] << 24) |
1053                                                       ((u64) pn[1] << 32) |
1054                                                       ((u64) pn[0] << 40));
1055        }
1056
1057        IWL_DEBUG_INFO(mvm, "%s igtk for sta %u\n",
1058                       remove_key ? "removing" : "installing",
1059                       igtk_cmd.sta_id);
1060
1061        return iwl_mvm_send_cmd_pdu(mvm, MGMT_MCAST_KEY, CMD_SYNC,
1062                                    sizeof(igtk_cmd), &igtk_cmd);
1063}
1064
1065
1066static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
1067                                       struct ieee80211_vif *vif,
1068                                       struct ieee80211_sta *sta)
1069{
1070        struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1071
1072        if (sta)
1073                return sta->addr;
1074
1075        if (vif->type == NL80211_IFTYPE_STATION &&
1076            mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
1077                u8 sta_id = mvmvif->ap_sta_id;
1078                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
1079                                                lockdep_is_held(&mvm->mutex));
1080                return sta->addr;
1081        }
1082
1083
1084        return NULL;
1085}
1086
1087int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
1088                        struct ieee80211_vif *vif,
1089                        struct ieee80211_sta *sta,
1090                        struct ieee80211_key_conf *keyconf,
1091                        bool have_key_offset)
1092{
1093        struct iwl_mvm_sta *mvm_sta;
1094        int ret;
1095        u8 *addr, sta_id;
1096        struct ieee80211_key_seq seq;
1097        u16 p1k[5];
1098
1099        lockdep_assert_held(&mvm->mutex);
1100
1101        /* Get the station id from the mvm local station table */
1102        sta_id = iwl_mvm_get_key_sta_id(vif, sta);
1103        if (sta_id == IWL_MVM_STATION_COUNT) {
1104                IWL_ERR(mvm, "Failed to find station id\n");
1105                return -EINVAL;
1106        }
1107
1108        if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
1109                ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, false);
1110                goto end;
1111        }
1112
1113        /*
1114         * It is possible that the 'sta' parameter is NULL, and thus
1115         * there is a need to retrieve  the sta from the local station table.
1116         */
1117        if (!sta) {
1118                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
1119                                                lockdep_is_held(&mvm->mutex));
1120                if (IS_ERR_OR_NULL(sta)) {
1121                        IWL_ERR(mvm, "Invalid station id\n");
1122                        return -EINVAL;
1123                }
1124        }
1125
1126        mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv;
1127        if (WARN_ON_ONCE(mvm_sta->vif != vif))
1128                return -EINVAL;
1129
1130        if (!have_key_offset) {
1131                /*
1132                 * The D3 firmware hardcodes the PTK offset to 0, so we have to
1133                 * configure it there. As a result, this workaround exists to
1134                 * let the caller set the key offset (hw_key_idx), see d3.c.
1135                 */
1136                keyconf->hw_key_idx = iwl_mvm_set_fw_key_idx(mvm);
1137                if (keyconf->hw_key_idx == STA_KEY_IDX_INVALID)
1138                        return -ENOSPC;
1139        }
1140
1141        switch (keyconf->cipher) {
1142        case WLAN_CIPHER_SUITE_TKIP:
1143                addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
1144                /* get phase 1 key from mac80211 */
1145                ieee80211_get_key_rx_seq(keyconf, 0, &seq);
1146                ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
1147                ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
1148                                           seq.tkip.iv32, p1k, CMD_SYNC);
1149                break;
1150        case WLAN_CIPHER_SUITE_CCMP:
1151                ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
1152                                           0, NULL, CMD_SYNC);
1153                break;
1154        default:
1155                IWL_ERR(mvm, "Unknown cipher %x\n", keyconf->cipher);
1156                ret = -EINVAL;
1157        }
1158
1159        if (ret)
1160                __clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
1161
1162end:
1163        IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
1164                      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
1165                      sta->addr, ret);
1166        return ret;
1167}
1168
1169int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
1170                           struct ieee80211_vif *vif,
1171                           struct ieee80211_sta *sta,
1172                           struct ieee80211_key_conf *keyconf)
1173{
1174        struct iwl_mvm_sta *mvm_sta;
1175        struct iwl_mvm_add_sta_cmd cmd = {};
1176        __le16 key_flags;
1177        int ret, status;
1178        u8 sta_id;
1179
1180        lockdep_assert_held(&mvm->mutex);
1181
1182        /* Get the station id from the mvm local station table */
1183        sta_id = iwl_mvm_get_key_sta_id(vif, sta);
1184
1185        IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
1186                      keyconf->keyidx, sta_id);
1187
1188        if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
1189                return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
1190
1191        ret = __test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
1192        if (!ret) {
1193                IWL_ERR(mvm, "offset %d not used in fw key table.\n",
1194                        keyconf->hw_key_idx);
1195                return -ENOENT;
1196        }
1197
1198        if (sta_id == IWL_MVM_STATION_COUNT) {
1199                IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
1200                return 0;
1201        }
1202
1203        /*
1204         * It is possible that the 'sta' parameter is NULL, and thus
1205         * there is a need to retrieve the sta from the local station table,
1206         * for example when a GTK is removed (where the sta_id will then be
1207         * the AP ID, and no station was passed by mac80211.)
1208         */
1209        if (!sta) {
1210                sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
1211                                                lockdep_is_held(&mvm->mutex));
1212                if (!sta) {
1213                        IWL_ERR(mvm, "Invalid station id\n");
1214                        return -EINVAL;
1215                }
1216        }
1217
1218        mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv;
1219        if (WARN_ON_ONCE(mvm_sta->vif != vif))
1220                return -EINVAL;
1221
1222        key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
1223                                 STA_KEY_FLG_KEYID_MSK);
1224        key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
1225        key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
1226
1227        if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
1228                key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
1229
1230        cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
1231        cmd.key.key_flags = key_flags;
1232        cmd.key.key_offset = keyconf->hw_key_idx;
1233        cmd.sta_id = sta_id;
1234
1235        cmd.modify_mask = STA_MODIFY_KEY;
1236        cmd.add_modify = STA_MODE_MODIFY;
1237
1238        status = ADD_STA_SUCCESS;
1239        ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd),
1240                                          &cmd, &status);
1241
1242        switch (status) {
1243        case ADD_STA_SUCCESS:
1244                IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
1245                break;
1246        default:
1247                ret = -EIO;
1248                IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
1249                break;
1250        }
1251
1252        return ret;
1253}
1254
1255void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
1256                             struct ieee80211_vif *vif,
1257                             struct ieee80211_key_conf *keyconf,
1258                             struct ieee80211_sta *sta, u32 iv32,
1259                             u16 *phase1key)
1260{
1261        struct iwl_mvm_sta *mvm_sta;
1262        u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
1263
1264        if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
1265                return;
1266
1267        rcu_read_lock();
1268
1269        if (!sta) {
1270                sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
1271                if (WARN_ON(IS_ERR_OR_NULL(sta))) {
1272                        rcu_read_unlock();
1273                        return;
1274                }
1275        }
1276
1277        mvm_sta = (void *)sta->drv_priv;
1278        iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
1279                             iv32, phase1key, CMD_ASYNC);
1280        rcu_read_unlock();
1281}
1282
1283void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
1284                                struct ieee80211_sta *sta)
1285{
1286        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
1287        struct iwl_mvm_add_sta_cmd cmd = {
1288                .add_modify = STA_MODE_MODIFY,
1289                .sta_id = mvmsta->sta_id,
1290                .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
1291                .sleep_state_flags = cpu_to_le16(STA_SLEEP_STATE_AWAKE),
1292                .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
1293        };
1294        int ret;
1295
1296        /*
1297         * Same modify mask for sleep_tx_count and sleep_state_flags but this
1298         * should be fine since if we set the STA as "awake", then
1299         * sleep_tx_count is not relevant.
1300         */
1301        ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
1302        if (ret)
1303                IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
1304}
1305
1306void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
1307                                       struct ieee80211_sta *sta,
1308                                       enum ieee80211_frame_release_type reason,
1309                                       u16 cnt)
1310{
1311        u16 sleep_state_flags =
1312                (reason == IEEE80211_FRAME_RELEASE_UAPSD) ?
1313                        STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL;
1314        struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
1315        struct iwl_mvm_add_sta_cmd cmd = {
1316                .add_modify = STA_MODE_MODIFY,
1317                .sta_id = mvmsta->sta_id,
1318                .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
1319                .sleep_tx_count = cpu_to_le16(cnt),
1320                .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
1321                /*
1322                 * Same modify mask for sleep_tx_count and sleep_state_flags so
1323                 * we must set the sleep_state_flags too.
1324                 */
1325                .sleep_state_flags = cpu_to_le16(sleep_state_flags),
1326        };
1327        int ret;
1328
1329        /* TODO: somehow the fw doesn't seem to take PS_POLL into account */
1330        ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
1331        if (ret)
1332                IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
1333}
1334