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/sf.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) 2013-2014, 2018-2019 Intel Corporation
    4  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
    5  */
    6 #include "mvm.h"
    7 
    8 /* For counting bound interfaces */
    9 struct iwl_mvm_active_iface_iterator_data {
   10         struct ieee80211_vif *ignore_vif;
   11         u8 sta_vif_ap_sta_id;
   12         enum iwl_sf_state sta_vif_state;
   13         u32 num_active_macs;
   14 };
   15 
   16 /*
   17  * Count bound interfaces which are not p2p, besides data->ignore_vif.
   18  * data->station_vif will point to one bound vif of type station, if exists.
   19  */
   20 static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac,
   21                                          struct ieee80211_vif *vif)
   22 {
   23         struct iwl_mvm_active_iface_iterator_data *data = _data;
   24         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
   25 
   26         if (vif == data->ignore_vif || !mvmvif->phy_ctxt ||
   27             vif->type == NL80211_IFTYPE_P2P_DEVICE)
   28                 return;
   29 
   30         data->num_active_macs++;
   31 
   32         if (vif->type == NL80211_IFTYPE_STATION) {
   33                 data->sta_vif_ap_sta_id = mvmvif->ap_sta_id;
   34                 if (vif->bss_conf.assoc)
   35                         data->sta_vif_state = SF_FULL_ON;
   36                 else
   37                         data->sta_vif_state = SF_INIT_OFF;
   38         }
   39 }
   40 
   41 /*
   42  * Aging and idle timeouts for the different possible scenarios
   43  * in default configuration
   44  */
   45 static const
   46 __le32 sf_full_timeout_def[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = {
   47         {
   48                 cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER_DEF),
   49                 cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
   50         },
   51         {
   52                 cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER_DEF),
   53                 cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER_DEF)
   54         },
   55         {
   56                 cpu_to_le32(SF_MCAST_AGING_TIMER_DEF),
   57                 cpu_to_le32(SF_MCAST_IDLE_TIMER_DEF)
   58         },
   59         {
   60                 cpu_to_le32(SF_BA_AGING_TIMER_DEF),
   61                 cpu_to_le32(SF_BA_IDLE_TIMER_DEF)
   62         },
   63         {
   64                 cpu_to_le32(SF_TX_RE_AGING_TIMER_DEF),
   65                 cpu_to_le32(SF_TX_RE_IDLE_TIMER_DEF)
   66         },
   67 };
   68 
   69 /*
   70  * Aging and idle timeouts for the different possible scenarios
   71  * in single BSS MAC configuration.
   72  */
   73 static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = {
   74         {
   75                 cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER),
   76                 cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER)
   77         },
   78         {
   79                 cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER),
   80                 cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER)
   81         },
   82         {
   83                 cpu_to_le32(SF_MCAST_AGING_TIMER),
   84                 cpu_to_le32(SF_MCAST_IDLE_TIMER)
   85         },
   86         {
   87                 cpu_to_le32(SF_BA_AGING_TIMER),
   88                 cpu_to_le32(SF_BA_IDLE_TIMER)
   89         },
   90         {
   91                 cpu_to_le32(SF_TX_RE_AGING_TIMER),
   92                 cpu_to_le32(SF_TX_RE_IDLE_TIMER)
   93         },
   94 };
   95 
   96 static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
   97                                     struct iwl_sf_cfg_cmd *sf_cmd,
   98                                     struct ieee80211_sta *sta)
   99 {
  100         int i, j, watermark;
  101 
  102         sf_cmd->watermark[SF_LONG_DELAY_ON] = cpu_to_le32(SF_W_MARK_SCAN);
  103 
  104         /*
  105          * If we are in association flow - check antenna configuration
  106          * capabilities of the AP station, and choose the watermark accordingly.
  107          */
  108         if (sta) {
  109                 if (sta->deflink.ht_cap.ht_supported ||
  110                     sta->deflink.vht_cap.vht_supported ||
  111                     sta->deflink.he_cap.has_he) {
  112                         switch (sta->deflink.rx_nss) {
  113                         case 1:
  114                                 watermark = SF_W_MARK_SISO;
  115                                 break;
  116                         case 2:
  117                                 watermark = SF_W_MARK_MIMO2;
  118                                 break;
  119                         default:
  120                                 watermark = SF_W_MARK_MIMO3;
  121                                 break;
  122                         }
  123                 } else {
  124                         watermark = SF_W_MARK_LEGACY;
  125                 }
  126         /* default watermark value for unassociated mode. */
  127         } else {
  128                 watermark = SF_W_MARK_MIMO2;
  129         }
  130         sf_cmd->watermark[SF_FULL_ON] = cpu_to_le32(watermark);
  131 
  132         for (i = 0; i < SF_NUM_SCENARIO; i++) {
  133                 for (j = 0; j < SF_NUM_TIMEOUT_TYPES; j++) {
  134                         sf_cmd->long_delay_timeouts[i][j] =
  135                                         cpu_to_le32(SF_LONG_DELAY_AGING_TIMER);
  136                 }
  137         }
  138 
  139         if (sta) {
  140                 BUILD_BUG_ON(sizeof(sf_full_timeout) !=
  141                              sizeof(__le32) * SF_NUM_SCENARIO *
  142                              SF_NUM_TIMEOUT_TYPES);
  143 
  144                 memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
  145                        sizeof(sf_full_timeout));
  146         } else {
  147                 BUILD_BUG_ON(sizeof(sf_full_timeout_def) !=
  148                              sizeof(__le32) * SF_NUM_SCENARIO *
  149                              SF_NUM_TIMEOUT_TYPES);
  150 
  151                 memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
  152                        sizeof(sf_full_timeout_def));
  153         }
  154 
  155 }
  156 
  157 static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id,
  158                              enum iwl_sf_state new_state)
  159 {
  160         struct iwl_sf_cfg_cmd sf_cmd = {
  161                 .state = cpu_to_le32(new_state),
  162         };
  163         struct ieee80211_sta *sta;
  164         int ret = 0;
  165 
  166         if (mvm->cfg->disable_dummy_notification)
  167                 sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF);
  168 
  169         /*
  170          * If an associated AP sta changed its antenna configuration, the state
  171          * will remain FULL_ON but SF parameters need to be reconsidered.
  172          */
  173         if (new_state != SF_FULL_ON && mvm->sf_state == new_state)
  174                 return 0;
  175 
  176         switch (new_state) {
  177         case SF_UNINIT:
  178                 iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL);
  179                 break;
  180         case SF_FULL_ON:
  181                 if (sta_id == IWL_MVM_INVALID_STA) {
  182                         IWL_ERR(mvm,
  183                                 "No station: Cannot switch SF to FULL_ON\n");
  184                         return -EINVAL;
  185                 }
  186                 rcu_read_lock();
  187                 sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
  188                 if (IS_ERR_OR_NULL(sta)) {
  189                         IWL_ERR(mvm, "Invalid station id\n");
  190                         rcu_read_unlock();
  191                         return -EINVAL;
  192                 }
  193                 iwl_mvm_fill_sf_command(mvm, &sf_cmd, sta);
  194                 rcu_read_unlock();
  195                 break;
  196         case SF_INIT_OFF:
  197                 iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL);
  198                 break;
  199         default:
  200                 WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n",
  201                           new_state);
  202                 return -EINVAL;
  203         }
  204 
  205         ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_SF_CFG_CMD, CMD_ASYNC,
  206                                    sizeof(sf_cmd), &sf_cmd);
  207         if (!ret)
  208                 mvm->sf_state = new_state;
  209 
  210         return ret;
  211 }
  212 
  213 /*
  214  * Update Smart fifo:
  215  * Count bound interfaces that are not to be removed, ignoring p2p devices,
  216  * and set new state accordingly.
  217  */
  218 int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
  219                       bool remove_vif)
  220 {
  221         enum iwl_sf_state new_state;
  222         u8 sta_id = IWL_MVM_INVALID_STA;
  223         struct iwl_mvm_vif *mvmvif = NULL;
  224         struct iwl_mvm_active_iface_iterator_data data = {
  225                 .ignore_vif = changed_vif,
  226                 .sta_vif_state = SF_UNINIT,
  227                 .sta_vif_ap_sta_id = IWL_MVM_INVALID_STA,
  228         };
  229 
  230         /*
  231          * Ignore the call if we are in HW Restart flow, or if the handled
  232          * vif is a p2p device.
  233          */
  234         if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
  235             (changed_vif && changed_vif->type == NL80211_IFTYPE_P2P_DEVICE))
  236                 return 0;
  237 
  238         ieee80211_iterate_active_interfaces_atomic(mvm->hw,
  239                                                    IEEE80211_IFACE_ITER_NORMAL,
  240                                                    iwl_mvm_bound_iface_iterator,
  241                                                    &data);
  242 
  243         /* If changed_vif exists and is not to be removed, add to the count */
  244         if (changed_vif && !remove_vif)
  245                 data.num_active_macs++;
  246 
  247         switch (data.num_active_macs) {
  248         case 0:
  249                 /* If there are no active macs - change state to SF_INIT_OFF */
  250                 new_state = SF_INIT_OFF;
  251                 break;
  252         case 1:
  253                 if (remove_vif) {
  254                         /* The one active mac left is of type station
  255                          * and we filled the relevant data during iteration
  256                          */
  257                         new_state = data.sta_vif_state;
  258                         sta_id = data.sta_vif_ap_sta_id;
  259                 } else {
  260                         if (WARN_ON(!changed_vif))
  261                                 return -EINVAL;
  262                         if (changed_vif->type != NL80211_IFTYPE_STATION) {
  263                                 new_state = SF_UNINIT;
  264                         } else if (changed_vif->bss_conf.assoc &&
  265                                    changed_vif->bss_conf.dtim_period) {
  266                                 mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
  267                                 sta_id = mvmvif->ap_sta_id;
  268                                 new_state = SF_FULL_ON;
  269                         } else {
  270                                 new_state = SF_INIT_OFF;
  271                         }
  272                 }
  273                 break;
  274         default:
  275                 /* If there are multiple active macs - change to SF_UNINIT */
  276                 new_state = SF_UNINIT;
  277         }
  278         return iwl_mvm_sf_config(mvm, sta_id, new_state);
  279 }

Cache object: 48d23d36fd7f816e1ed632fe08906ccc


[ 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.