root/drivers/net/wireless/intel/iwlwifi/mvm/binding.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iwl_mvm_binding_cmd
  2. iwl_mvm_iface_iterator
  3. iwl_mvm_binding_update
  4. iwl_mvm_binding_add_vif
  5. iwl_mvm_binding_remove_vif

   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 - 2014 Intel Corporation. All rights reserved.
   9  * Copyright(c) 2016 Intel Deutschland GmbH
  10  *
  11  * This program is free software; you can redistribute it and/or modify
  12  * it under the terms of version 2 of the GNU General Public License as
  13  * published by the Free Software Foundation.
  14  *
  15  * This program is distributed in the hope that it will be useful, but
  16  * WITHOUT ANY WARRANTY; without even the implied warranty of
  17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18  * General Public License for more details.
  19  *
  20  * The full GNU General Public License is included in this distribution
  21  * in the file called COPYING.
  22  *
  23  * Contact Information:
  24  *  Intel Linux Wireless <linuxwifi@intel.com>
  25  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  26  *
  27  * BSD LICENSE
  28  *
  29  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  30  * Copyright(c) 2016 Intel Deutschland GmbH
  31  * All rights reserved.
  32  *
  33  * Redistribution and use in source and binary forms, with or without
  34  * modification, are permitted provided that the following conditions
  35  * are met:
  36  *
  37  *  * Redistributions of source code must retain the above copyright
  38  *    notice, this list of conditions and the following disclaimer.
  39  *  * Redistributions in binary form must reproduce the above copyright
  40  *    notice, this list of conditions and the following disclaimer in
  41  *    the documentation and/or other materials provided with the
  42  *    distribution.
  43  *  * Neither the name Intel Corporation nor the names of its
  44  *    contributors may be used to endorse or promote products derived
  45  *    from this software without specific prior written permission.
  46  *
  47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  48  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  49  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  50  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  51  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  52  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  53  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  54  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  55  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  56  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  57  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  58  *
  59  *****************************************************************************/
  60 
  61 #include <net/mac80211.h>
  62 #include "fw-api.h"
  63 #include "mvm.h"
  64 
  65 struct iwl_mvm_iface_iterator_data {
  66         struct ieee80211_vif *ignore_vif;
  67         int idx;
  68 
  69         struct iwl_mvm_phy_ctxt *phyctxt;
  70 
  71         u16 ids[MAX_MACS_IN_BINDING];
  72         u16 colors[MAX_MACS_IN_BINDING];
  73 };
  74 
  75 static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
  76                                struct iwl_mvm_iface_iterator_data *data)
  77 {
  78         struct iwl_binding_cmd cmd;
  79         struct iwl_mvm_phy_ctxt *phyctxt = data->phyctxt;
  80         int i, ret;
  81         u32 status;
  82         int size;
  83 
  84         memset(&cmd, 0, sizeof(cmd));
  85 
  86         if (fw_has_capa(&mvm->fw->ucode_capa,
  87                         IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
  88                 size = sizeof(cmd);
  89                 if (phyctxt->channel->band == NL80211_BAND_2GHZ ||
  90                     !iwl_mvm_is_cdb_supported(mvm))
  91                         cmd.lmac_id = cpu_to_le32(IWL_LMAC_24G_INDEX);
  92                 else
  93                         cmd.lmac_id = cpu_to_le32(IWL_LMAC_5G_INDEX);
  94         } else {
  95                 size = IWL_BINDING_CMD_SIZE_V1;
  96         }
  97 
  98         cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
  99                                                            phyctxt->color));
 100         cmd.action = cpu_to_le32(action);
 101         cmd.phy = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
 102                                                   phyctxt->color));
 103 
 104         for (i = 0; i < MAX_MACS_IN_BINDING; i++)
 105                 cmd.macs[i] = cpu_to_le32(FW_CTXT_INVALID);
 106         for (i = 0; i < data->idx; i++)
 107                 cmd.macs[i] = cpu_to_le32(FW_CMD_ID_AND_COLOR(data->ids[i],
 108                                                               data->colors[i]));
 109 
 110         status = 0;
 111         ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
 112                                           size, &cmd, &status);
 113         if (ret) {
 114                 IWL_ERR(mvm, "Failed to send binding (action:%d): %d\n",
 115                         action, ret);
 116                 return ret;
 117         }
 118 
 119         if (status) {
 120                 IWL_ERR(mvm, "Binding command failed: %u\n", status);
 121                 ret = -EIO;
 122         }
 123 
 124         return ret;
 125 }
 126 
 127 static void iwl_mvm_iface_iterator(void *_data, u8 *mac,
 128                                    struct ieee80211_vif *vif)
 129 {
 130         struct iwl_mvm_iface_iterator_data *data = _data;
 131         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 132 
 133         if (vif == data->ignore_vif)
 134                 return;
 135 
 136         if (mvmvif->phy_ctxt != data->phyctxt)
 137                 return;
 138 
 139         if (WARN_ON_ONCE(data->idx >= MAX_MACS_IN_BINDING))
 140                 return;
 141 
 142         data->ids[data->idx] = mvmvif->id;
 143         data->colors[data->idx] = mvmvif->color;
 144         data->idx++;
 145 }
 146 
 147 static int iwl_mvm_binding_update(struct iwl_mvm *mvm,
 148                                   struct ieee80211_vif *vif,
 149                                   struct iwl_mvm_phy_ctxt *phyctxt,
 150                                   bool add)
 151 {
 152         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 153         struct iwl_mvm_iface_iterator_data data = {
 154                 .ignore_vif = vif,
 155                 .phyctxt = phyctxt,
 156         };
 157         u32 action = FW_CTXT_ACTION_MODIFY;
 158 
 159         lockdep_assert_held(&mvm->mutex);
 160 
 161         ieee80211_iterate_active_interfaces_atomic(mvm->hw,
 162                                                    IEEE80211_IFACE_ITER_NORMAL,
 163                                                    iwl_mvm_iface_iterator,
 164                                                    &data);
 165 
 166         /*
 167          * If there are no other interfaces yet we
 168          * need to create a new binding.
 169          */
 170         if (data.idx == 0) {
 171                 if (add)
 172                         action = FW_CTXT_ACTION_ADD;
 173                 else
 174                         action = FW_CTXT_ACTION_REMOVE;
 175         }
 176 
 177         if (add) {
 178                 if (WARN_ON_ONCE(data.idx >= MAX_MACS_IN_BINDING))
 179                         return -EINVAL;
 180 
 181                 data.ids[data.idx] = mvmvif->id;
 182                 data.colors[data.idx] = mvmvif->color;
 183                 data.idx++;
 184         }
 185 
 186         return iwl_mvm_binding_cmd(mvm, action, &data);
 187 }
 188 
 189 int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 190 {
 191         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 192 
 193         if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
 194                 return -EINVAL;
 195 
 196         /*
 197          * Update SF - Disable if needed. if this fails, SF might still be on
 198          * while many macs are bound, which is forbidden - so fail the binding.
 199          */
 200         if (iwl_mvm_sf_update(mvm, vif, false))
 201                 return -EINVAL;
 202 
 203         return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
 204 }
 205 
 206 int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 207 {
 208         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 209         int ret;
 210 
 211         if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
 212                 return -EINVAL;
 213 
 214         ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
 215 
 216         if (!ret)
 217                 if (iwl_mvm_sf_update(mvm, vif, true))
 218                         IWL_ERR(mvm, "Failed to update SF state\n");
 219 
 220         return ret;
 221 }

/* [<][>][^][v][top][bottom][index][help] */