The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/iwlwifi/mvm/binding.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
    2 /*
    3  * Copyright (C) 2012-2014, 2020 Intel Corporation
    4  * Copyright (C) 2016 Intel Deutschland GmbH
    5  */
    6 #include <net/mac80211.h>
    7 #include "fw-api.h"
    8 #include "mvm.h"
    9 
   10 struct iwl_mvm_iface_iterator_data {
   11         struct ieee80211_vif *ignore_vif;
   12         int idx;
   13 
   14         struct iwl_mvm_phy_ctxt *phyctxt;
   15 
   16         u16 ids[MAX_MACS_IN_BINDING];
   17         u16 colors[MAX_MACS_IN_BINDING];
   18 };
   19 
   20 static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
   21                                struct iwl_mvm_iface_iterator_data *data)
   22 {
   23         struct iwl_binding_cmd cmd;
   24         struct iwl_mvm_phy_ctxt *phyctxt = data->phyctxt;
   25         int i, ret;
   26         u32 status;
   27         int size;
   28 
   29         memset(&cmd, 0, sizeof(cmd));
   30 
   31         if (fw_has_capa(&mvm->fw->ucode_capa,
   32                         IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
   33                 size = sizeof(cmd);
   34                 cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
   35                                                               phyctxt->channel->band));
   36         } else {
   37                 size = IWL_BINDING_CMD_SIZE_V1;
   38         }
   39 
   40         cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
   41                                                            phyctxt->color));
   42         cmd.action = cpu_to_le32(action);
   43         cmd.phy = cpu_to_le32(FW_CMD_ID_AND_COLOR(phyctxt->id,
   44                                                   phyctxt->color));
   45 
   46         for (i = 0; i < MAX_MACS_IN_BINDING; i++)
   47                 cmd.macs[i] = cpu_to_le32(FW_CTXT_INVALID);
   48         for (i = 0; i < data->idx; i++)
   49                 cmd.macs[i] = cpu_to_le32(FW_CMD_ID_AND_COLOR(data->ids[i],
   50                                                               data->colors[i]));
   51 
   52         status = 0;
   53         ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
   54                                           size, &cmd, &status);
   55         if (ret) {
   56                 IWL_ERR(mvm, "Failed to send binding (action:%d): %d\n",
   57                         action, ret);
   58                 return ret;
   59         }
   60 
   61         if (status) {
   62                 IWL_ERR(mvm, "Binding command failed: %u\n", status);
   63                 ret = -EIO;
   64         }
   65 
   66         return ret;
   67 }
   68 
   69 static void iwl_mvm_iface_iterator(void *_data, u8 *mac,
   70                                    struct ieee80211_vif *vif)
   71 {
   72         struct iwl_mvm_iface_iterator_data *data = _data;
   73         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
   74 
   75         if (vif == data->ignore_vif)
   76                 return;
   77 
   78         if (mvmvif->phy_ctxt != data->phyctxt)
   79                 return;
   80 
   81         if (WARN_ON_ONCE(data->idx >= MAX_MACS_IN_BINDING))
   82                 return;
   83 
   84         data->ids[data->idx] = mvmvif->id;
   85         data->colors[data->idx] = mvmvif->color;
   86         data->idx++;
   87 }
   88 
   89 static int iwl_mvm_binding_update(struct iwl_mvm *mvm,
   90                                   struct ieee80211_vif *vif,
   91                                   struct iwl_mvm_phy_ctxt *phyctxt,
   92                                   bool add)
   93 {
   94         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
   95         struct iwl_mvm_iface_iterator_data data = {
   96                 .ignore_vif = vif,
   97                 .phyctxt = phyctxt,
   98         };
   99         u32 action = FW_CTXT_ACTION_MODIFY;
  100 
  101         lockdep_assert_held(&mvm->mutex);
  102 
  103         ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  104                                                    IEEE80211_IFACE_ITER_NORMAL,
  105                                                    iwl_mvm_iface_iterator,
  106                                                    &data);
  107 
  108         /*
  109          * If there are no other interfaces yet we
  110          * need to create a new binding.
  111          */
  112         if (data.idx == 0) {
  113                 if (add)
  114                         action = FW_CTXT_ACTION_ADD;
  115                 else
  116                         action = FW_CTXT_ACTION_REMOVE;
  117         }
  118 
  119         if (add) {
  120                 if (WARN_ON_ONCE(data.idx >= MAX_MACS_IN_BINDING))
  121                         return -EINVAL;
  122 
  123                 data.ids[data.idx] = mvmvif->id;
  124                 data.colors[data.idx] = mvmvif->color;
  125                 data.idx++;
  126         }
  127 
  128         return iwl_mvm_binding_cmd(mvm, action, &data);
  129 }
  130 
  131 int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
  132 {
  133         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  134 
  135         if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
  136                 return -EINVAL;
  137 
  138         /*
  139          * Update SF - Disable if needed. if this fails, SF might still be on
  140          * while many macs are bound, which is forbidden - so fail the binding.
  141          */
  142         if (iwl_mvm_sf_update(mvm, vif, false))
  143                 return -EINVAL;
  144 
  145         return iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, true);
  146 }
  147 
  148 int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
  149 {
  150         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  151         int ret;
  152 
  153         if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
  154                 return -EINVAL;
  155 
  156         ret = iwl_mvm_binding_update(mvm, vif, mvmvif->phy_ctxt, false);
  157 
  158         if (!ret)
  159                 if (iwl_mvm_sf_update(mvm, vif, true))
  160                         IWL_ERR(mvm, "Failed to update SF state\n");
  161 
  162         return ret;
  163 }

Cache object: fa67e17dbae548677cfda826549dd382


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.