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/rtw89/mac80211.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 /* Copyright(c) 2019-2020  Realtek Corporation
    3  */
    4 
    5 #include "cam.h"
    6 #include "chan.h"
    7 #include "coex.h"
    8 #include "debug.h"
    9 #include "fw.h"
   10 #include "mac.h"
   11 #include "phy.h"
   12 #include "ps.h"
   13 #include "reg.h"
   14 #include "sar.h"
   15 #include "ser.h"
   16 
   17 static void rtw89_ops_tx(struct ieee80211_hw *hw,
   18                          struct ieee80211_tx_control *control,
   19                          struct sk_buff *skb)
   20 {
   21         struct rtw89_dev *rtwdev = hw->priv;
   22         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
   23         struct ieee80211_vif *vif = info->control.vif;
   24         struct ieee80211_sta *sta = control->sta;
   25         int ret, qsel;
   26 
   27         ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel);
   28         if (ret) {
   29                 rtw89_err(rtwdev, "failed to transmit skb: %d\n", ret);
   30                 ieee80211_free_txskb(hw, skb);
   31                 return;
   32         }
   33         rtw89_core_tx_kick_off(rtwdev, qsel);
   34 }
   35 
   36 static void rtw89_ops_wake_tx_queue(struct ieee80211_hw *hw,
   37                                     struct ieee80211_txq *txq)
   38 {
   39         struct rtw89_dev *rtwdev = hw->priv;
   40 
   41         ieee80211_schedule_txq(hw, txq);
   42         queue_work(rtwdev->txq_wq, &rtwdev->txq_work);
   43 }
   44 
   45 static int rtw89_ops_start(struct ieee80211_hw *hw)
   46 {
   47         struct rtw89_dev *rtwdev = hw->priv;
   48         int ret;
   49 
   50         mutex_lock(&rtwdev->mutex);
   51         ret = rtw89_core_start(rtwdev);
   52         mutex_unlock(&rtwdev->mutex);
   53 
   54         return ret;
   55 }
   56 
   57 static void rtw89_ops_stop(struct ieee80211_hw *hw)
   58 {
   59         struct rtw89_dev *rtwdev = hw->priv;
   60 
   61         mutex_lock(&rtwdev->mutex);
   62         rtw89_core_stop(rtwdev);
   63         mutex_unlock(&rtwdev->mutex);
   64 }
   65 
   66 static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed)
   67 {
   68         struct rtw89_dev *rtwdev = hw->priv;
   69 
   70         /* let previous ips work finish to ensure we don't leave ips twice */
   71         cancel_work_sync(&rtwdev->ips_work);
   72 
   73         mutex_lock(&rtwdev->mutex);
   74         rtw89_leave_ps_mode(rtwdev);
   75 
   76         if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
   77             !(hw->conf.flags & IEEE80211_CONF_IDLE))
   78                 rtw89_leave_ips(rtwdev);
   79 
   80         if (changed & IEEE80211_CONF_CHANGE_PS) {
   81                 if (hw->conf.flags & IEEE80211_CONF_PS) {
   82                         rtwdev->lps_enabled = true;
   83                 } else {
   84                         rtw89_leave_lps(rtwdev);
   85                         rtwdev->lps_enabled = false;
   86                 }
   87         }
   88 
   89         if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
   90                 rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0,
   91                                             &hw->conf.chandef);
   92                 rtw89_set_channel(rtwdev);
   93         }
   94 
   95         if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
   96             (hw->conf.flags & IEEE80211_CONF_IDLE))
   97                 rtw89_enter_ips(rtwdev);
   98 
   99         mutex_unlock(&rtwdev->mutex);
  100 
  101         return 0;
  102 }
  103 
  104 static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
  105                                    struct ieee80211_vif *vif)
  106 {
  107         struct rtw89_dev *rtwdev = hw->priv;
  108         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  109         int ret = 0;
  110 
  111         mutex_lock(&rtwdev->mutex);
  112         rtwvif->rtwdev = rtwdev;
  113         list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
  114         INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work);
  115         rtw89_leave_ps_mode(rtwdev);
  116 
  117         rtw89_traffic_stats_init(rtwdev, &rtwvif->stats);
  118         rtw89_vif_type_mapping(vif, false);
  119         rtwvif->port = rtw89_core_acquire_bit_map(rtwdev->hw_port,
  120                                                   RTW89_PORT_NUM);
  121         if (rtwvif->port == RTW89_PORT_NUM) {
  122                 ret = -ENOSPC;
  123                 goto out;
  124         }
  125 
  126         rtwvif->bcn_hit_cond = 0;
  127         rtwvif->mac_idx = RTW89_MAC_0;
  128         rtwvif->phy_idx = RTW89_PHY_0;
  129         rtwvif->hit_rule = 0;
  130         ether_addr_copy(rtwvif->mac_addr, vif->addr);
  131 
  132         ret = rtw89_mac_add_vif(rtwdev, rtwvif);
  133         if (ret) {
  134                 rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
  135                 goto out;
  136         }
  137 
  138         rtw89_core_txq_init(rtwdev, vif->txq);
  139 
  140         rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_START);
  141 out:
  142         mutex_unlock(&rtwdev->mutex);
  143 
  144         return ret;
  145 }
  146 
  147 static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
  148                                        struct ieee80211_vif *vif)
  149 {
  150         struct rtw89_dev *rtwdev = hw->priv;
  151         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  152 
  153         cancel_work_sync(&rtwvif->update_beacon_work);
  154 
  155         mutex_lock(&rtwdev->mutex);
  156         rtw89_leave_ps_mode(rtwdev);
  157         rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_STOP);
  158         rtw89_mac_remove_vif(rtwdev, rtwvif);
  159         rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
  160         list_del_init(&rtwvif->list);
  161         mutex_unlock(&rtwdev->mutex);
  162 }
  163 
  164 static void rtw89_ops_configure_filter(struct ieee80211_hw *hw,
  165                                        unsigned int changed_flags,
  166                                        unsigned int *new_flags,
  167                                        u64 multicast)
  168 {
  169         struct rtw89_dev *rtwdev = hw->priv;
  170 
  171         mutex_lock(&rtwdev->mutex);
  172         rtw89_leave_ps_mode(rtwdev);
  173 
  174         *new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
  175                       FIF_BCN_PRBRESP_PROMISC | FIF_PROBE_REQ;
  176 
  177         if (changed_flags & FIF_ALLMULTI) {
  178                 if (*new_flags & FIF_ALLMULTI)
  179                         rtwdev->hal.rx_fltr &= ~B_AX_A_MC;
  180                 else
  181                         rtwdev->hal.rx_fltr |= B_AX_A_MC;
  182         }
  183         if (changed_flags & FIF_FCSFAIL) {
  184                 if (*new_flags & FIF_FCSFAIL)
  185                         rtwdev->hal.rx_fltr |= B_AX_A_CRC32_ERR;
  186                 else
  187                         rtwdev->hal.rx_fltr &= ~B_AX_A_CRC32_ERR;
  188         }
  189         if (changed_flags & FIF_OTHER_BSS) {
  190                 if (*new_flags & FIF_OTHER_BSS)
  191                         rtwdev->hal.rx_fltr &= ~B_AX_A_A1_MATCH;
  192                 else
  193                         rtwdev->hal.rx_fltr |= B_AX_A_A1_MATCH;
  194         }
  195         if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
  196                 if (*new_flags & FIF_BCN_PRBRESP_PROMISC) {
  197                         rtwdev->hal.rx_fltr &= ~B_AX_A_BCN_CHK_EN;
  198                         rtwdev->hal.rx_fltr &= ~B_AX_A_BC;
  199                         rtwdev->hal.rx_fltr &= ~B_AX_A_A1_MATCH;
  200                 } else {
  201                         rtwdev->hal.rx_fltr |= B_AX_A_BCN_CHK_EN;
  202                         rtwdev->hal.rx_fltr |= B_AX_A_BC;
  203                         rtwdev->hal.rx_fltr |= B_AX_A_A1_MATCH;
  204                 }
  205         }
  206         if (changed_flags & FIF_PROBE_REQ) {
  207                 if (*new_flags & FIF_PROBE_REQ) {
  208                         rtwdev->hal.rx_fltr &= ~B_AX_A_BC_CAM_MATCH;
  209                         rtwdev->hal.rx_fltr &= ~B_AX_A_UC_CAM_MATCH;
  210                 } else {
  211                         rtwdev->hal.rx_fltr |= B_AX_A_BC_CAM_MATCH;
  212                         rtwdev->hal.rx_fltr |= B_AX_A_UC_CAM_MATCH;
  213                 }
  214         }
  215 
  216         rtw89_write32_mask(rtwdev,
  217                            rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
  218                            B_AX_RX_FLTR_CFG_MASK,
  219                            rtwdev->hal.rx_fltr);
  220         if (!rtwdev->dbcc_en)
  221                 goto out;
  222         rtw89_write32_mask(rtwdev,
  223                            rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_1),
  224                            B_AX_RX_FLTR_CFG_MASK,
  225                            rtwdev->hal.rx_fltr);
  226 
  227 out:
  228         mutex_unlock(&rtwdev->mutex);
  229 }
  230 
  231 static const u8 ac_to_fw_idx[IEEE80211_NUM_ACS] = {
  232         [IEEE80211_AC_VO] = 3,
  233         [IEEE80211_AC_VI] = 2,
  234         [IEEE80211_AC_BE] = 0,
  235         [IEEE80211_AC_BK] = 1,
  236 };
  237 
  238 static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev,
  239                               struct rtw89_vif *rtwvif, u8 aifsn)
  240 {
  241         struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
  242         const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
  243         u8 slot_time;
  244         u8 sifs;
  245 
  246         slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
  247         sifs = chan->band_type == RTW89_BAND_5G ? 16 : 10;
  248 
  249         return aifsn * slot_time + sifs;
  250 }
  251 
  252 static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev,
  253                                    struct rtw89_vif *rtwvif, u16 ac)
  254 {
  255         struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
  256         u32 val;
  257         u8 ecw_max, ecw_min;
  258         u8 aifs;
  259 
  260         /* 2^ecw - 1 = cw; ecw = log2(cw + 1) */
  261         ecw_max = ilog2(params->cw_max + 1);
  262         ecw_min = ilog2(params->cw_min + 1);
  263         aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif, params->aifs);
  264         val = FIELD_PREP(FW_EDCA_PARAM_TXOPLMT_MSK, params->txop) |
  265               FIELD_PREP(FW_EDCA_PARAM_CWMAX_MSK, ecw_max) |
  266               FIELD_PREP(FW_EDCA_PARAM_CWMIN_MSK, ecw_min) |
  267               FIELD_PREP(FW_EDCA_PARAM_AIFS_MSK, aifs);
  268         rtw89_fw_h2c_set_edca(rtwdev, rtwvif, ac_to_fw_idx[ac], val);
  269 }
  270 
  271 static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS] = {
  272         [IEEE80211_AC_VO] = R_AX_MUEDCA_VO_PARAM_0,
  273         [IEEE80211_AC_VI] = R_AX_MUEDCA_VI_PARAM_0,
  274         [IEEE80211_AC_BE] = R_AX_MUEDCA_BE_PARAM_0,
  275         [IEEE80211_AC_BK] = R_AX_MUEDCA_BK_PARAM_0,
  276 };
  277 
  278 static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev,
  279                                       struct rtw89_vif *rtwvif, u16 ac)
  280 {
  281         struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
  282         struct ieee80211_he_mu_edca_param_ac_rec *mu_edca;
  283         u8 aifs, aifsn;
  284         u16 timer_32us;
  285         u32 reg;
  286         u32 val;
  287 
  288         if (!params->mu_edca)
  289                 return;
  290 
  291         mu_edca = &params->mu_edca_param_rec;
  292         aifsn = FIELD_GET(GENMASK(3, 0), mu_edca->aifsn);
  293         aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif, aifsn) : 0;
  294         timer_32us = mu_edca->mu_edca_timer << 8;
  295 
  296         val = FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_TIMER_MASK, timer_32us) |
  297               FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_CW_MASK, mu_edca->ecw_min_max) |
  298               FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_AIFS_MASK, aifs);
  299         reg = rtw89_mac_reg_by_idx(ac_to_mu_edca_param[ac], rtwvif->mac_idx);
  300         rtw89_write32(rtwdev, reg, val);
  301 
  302         rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif, true);
  303 }
  304 
  305 static void __rtw89_conf_tx(struct rtw89_dev *rtwdev,
  306                             struct rtw89_vif *rtwvif, u16 ac)
  307 {
  308         ____rtw89_conf_tx_edca(rtwdev, rtwvif, ac);
  309         ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif, ac);
  310 }
  311 
  312 static void rtw89_conf_tx(struct rtw89_dev *rtwdev,
  313                           struct rtw89_vif *rtwvif)
  314 {
  315         u16 ac;
  316 
  317         for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
  318                 __rtw89_conf_tx(rtwdev, rtwvif, ac);
  319 }
  320 
  321 static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev,
  322                                          struct ieee80211_vif *vif,
  323                                          struct ieee80211_bss_conf *conf)
  324 {
  325         struct ieee80211_sta *sta;
  326 
  327         if (vif->type != NL80211_IFTYPE_STATION)
  328                 return;
  329 
  330         sta = ieee80211_find_sta(vif, conf->bssid);
  331         if (!sta) {
  332                 rtw89_err(rtwdev, "can't find sta to set sta_assoc state\n");
  333                 return;
  334         }
  335 
  336         rtw89_vif_type_mapping(vif, true);
  337 
  338         rtw89_core_sta_assoc(rtwdev, vif, sta);
  339 }
  340 
  341 static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
  342                                        struct ieee80211_vif *vif,
  343                                        struct ieee80211_bss_conf *conf,
  344                                        u64 changed)
  345 {
  346         struct rtw89_dev *rtwdev = hw->priv;
  347         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  348 
  349         mutex_lock(&rtwdev->mutex);
  350         rtw89_leave_ps_mode(rtwdev);
  351 
  352         if (changed & BSS_CHANGED_ASSOC) {
  353                 if (vif->cfg.assoc) {
  354                         rtw89_station_mode_sta_assoc(rtwdev, vif, conf);
  355                         rtw89_phy_set_bss_color(rtwdev, vif);
  356                         rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif);
  357                         rtw89_mac_port_update(rtwdev, rtwvif);
  358                         rtw89_store_op_chan(rtwdev, true);
  359                 } else {
  360                         /* Abort ongoing scan if cancel_scan isn't issued
  361                          * when disconnected by peer
  362                          */
  363                         if (rtwdev->scanning)
  364                                 rtw89_hw_scan_abort(rtwdev, vif);
  365                 }
  366         }
  367 
  368         if (changed & BSS_CHANGED_BSSID) {
  369                 ether_addr_copy(rtwvif->bssid, conf->bssid);
  370                 rtw89_cam_bssid_changed(rtwdev, rtwvif);
  371                 rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
  372         }
  373 
  374         if (changed & BSS_CHANGED_BEACON)
  375                 rtw89_fw_h2c_update_beacon(rtwdev, rtwvif);
  376 
  377         if (changed & BSS_CHANGED_ERP_SLOT)
  378                 rtw89_conf_tx(rtwdev, rtwvif);
  379 
  380         if (changed & BSS_CHANGED_HE_BSS_COLOR)
  381                 rtw89_phy_set_bss_color(rtwdev, vif);
  382 
  383         if (changed & BSS_CHANGED_MU_GROUPS)
  384                 rtw89_mac_bf_set_gid_table(rtwdev, vif, conf);
  385 
  386         mutex_unlock(&rtwdev->mutex);
  387 }
  388 
  389 static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
  390                               struct ieee80211_vif *vif,
  391                               struct ieee80211_bss_conf *link_conf)
  392 {
  393         struct rtw89_dev *rtwdev = hw->priv;
  394         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  395 
  396         mutex_lock(&rtwdev->mutex);
  397         ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid);
  398         rtw89_cam_bssid_changed(rtwdev, rtwvif);
  399         rtw89_mac_port_update(rtwdev, rtwvif);
  400         rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
  401         rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_TYPE_CHANGE);
  402         rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
  403         rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
  404         rtw89_chip_rfk_channel(rtwdev);
  405         mutex_unlock(&rtwdev->mutex);
  406 
  407         return 0;
  408 }
  409 
  410 static
  411 void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  412                        struct ieee80211_bss_conf *link_conf)
  413 {
  414         struct rtw89_dev *rtwdev = hw->priv;
  415         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  416 
  417         mutex_lock(&rtwdev->mutex);
  418         rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
  419         rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
  420         mutex_unlock(&rtwdev->mutex);
  421 }
  422 
  423 static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
  424                              bool set)
  425 {
  426         struct rtw89_dev *rtwdev = hw->priv;
  427         struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
  428         struct rtw89_vif *rtwvif = rtwsta->rtwvif;
  429 
  430         ieee80211_queue_work(rtwdev->hw, &rtwvif->update_beacon_work);
  431 
  432         return 0;
  433 }
  434 
  435 static int rtw89_ops_conf_tx(struct ieee80211_hw *hw,
  436                              struct ieee80211_vif *vif,
  437                              unsigned int link_id, u16 ac,
  438                              const struct ieee80211_tx_queue_params *params)
  439 {
  440         struct rtw89_dev *rtwdev = hw->priv;
  441         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  442 
  443         mutex_lock(&rtwdev->mutex);
  444         rtw89_leave_ps_mode(rtwdev);
  445         rtwvif->tx_params[ac] = *params;
  446         __rtw89_conf_tx(rtwdev, rtwvif, ac);
  447         mutex_unlock(&rtwdev->mutex);
  448 
  449         return 0;
  450 }
  451 
  452 static int __rtw89_ops_sta_state(struct ieee80211_hw *hw,
  453                                  struct ieee80211_vif *vif,
  454                                  struct ieee80211_sta *sta,
  455                                  enum ieee80211_sta_state old_state,
  456                                  enum ieee80211_sta_state new_state)
  457 {
  458         struct rtw89_dev *rtwdev = hw->priv;
  459 
  460         if (old_state == IEEE80211_STA_NOTEXIST &&
  461             new_state == IEEE80211_STA_NONE)
  462                 return rtw89_core_sta_add(rtwdev, vif, sta);
  463 
  464         if (old_state == IEEE80211_STA_AUTH &&
  465             new_state == IEEE80211_STA_ASSOC) {
  466                 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
  467                         return 0; /* defer to bss_info_changed to have vif info */
  468                 return rtw89_core_sta_assoc(rtwdev, vif, sta);
  469         }
  470 
  471         if (old_state == IEEE80211_STA_ASSOC &&
  472             new_state == IEEE80211_STA_AUTH)
  473                 return rtw89_core_sta_disassoc(rtwdev, vif, sta);
  474 
  475         if (old_state == IEEE80211_STA_AUTH &&
  476             new_state == IEEE80211_STA_NONE)
  477                 return rtw89_core_sta_disconnect(rtwdev, vif, sta);
  478 
  479         if (old_state == IEEE80211_STA_NONE &&
  480             new_state == IEEE80211_STA_NOTEXIST)
  481                 return rtw89_core_sta_remove(rtwdev, vif, sta);
  482 
  483         return 0;
  484 }
  485 
  486 static int rtw89_ops_sta_state(struct ieee80211_hw *hw,
  487                                struct ieee80211_vif *vif,
  488                                struct ieee80211_sta *sta,
  489                                enum ieee80211_sta_state old_state,
  490                                enum ieee80211_sta_state new_state)
  491 {
  492         struct rtw89_dev *rtwdev = hw->priv;
  493         int ret;
  494 
  495         mutex_lock(&rtwdev->mutex);
  496         rtw89_leave_ps_mode(rtwdev);
  497         ret = __rtw89_ops_sta_state(hw, vif, sta, old_state, new_state);
  498         mutex_unlock(&rtwdev->mutex);
  499 
  500         return ret;
  501 }
  502 
  503 static int rtw89_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
  504                              struct ieee80211_vif *vif,
  505                              struct ieee80211_sta *sta,
  506                              struct ieee80211_key_conf *key)
  507 {
  508         struct rtw89_dev *rtwdev = hw->priv;
  509         int ret = 0;
  510 
  511         mutex_lock(&rtwdev->mutex);
  512         rtw89_leave_ps_mode(rtwdev);
  513 
  514         switch (cmd) {
  515         case SET_KEY:
  516                 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL_END);
  517                 ret = rtw89_cam_sec_key_add(rtwdev, vif, sta, key);
  518                 if (ret && ret != -EOPNOTSUPP) {
  519                         rtw89_err(rtwdev, "failed to add key to sec cam\n");
  520                         goto out;
  521                 }
  522                 break;
  523         case DISABLE_KEY:
  524                 rtw89_hci_flush_queues(rtwdev, BIT(rtwdev->hw->queues) - 1,
  525                                        false);
  526                 rtw89_mac_flush_txq(rtwdev, BIT(rtwdev->hw->queues) - 1, false);
  527                 ret = rtw89_cam_sec_key_del(rtwdev, vif, sta, key, true);
  528                 if (ret) {
  529                         rtw89_err(rtwdev, "failed to remove key from sec cam\n");
  530                         goto out;
  531                 }
  532                 break;
  533         }
  534 
  535 out:
  536         mutex_unlock(&rtwdev->mutex);
  537 
  538         return ret;
  539 }
  540 
  541 static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw,
  542                                   struct ieee80211_vif *vif,
  543                                   struct ieee80211_ampdu_params *params)
  544 {
  545         struct rtw89_dev *rtwdev = hw->priv;
  546         struct ieee80211_sta *sta = params->sta;
  547         struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
  548         u16 tid = params->tid;
  549         struct ieee80211_txq *txq = sta->txq[tid];
  550         struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv;
  551 
  552         switch (params->action) {
  553         case IEEE80211_AMPDU_TX_START:
  554                 return IEEE80211_AMPDU_TX_START_IMMEDIATE;
  555         case IEEE80211_AMPDU_TX_STOP_CONT:
  556         case IEEE80211_AMPDU_TX_STOP_FLUSH:
  557         case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
  558                 mutex_lock(&rtwdev->mutex);
  559                 clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags);
  560                 mutex_unlock(&rtwdev->mutex);
  561                 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
  562                 break;
  563         case IEEE80211_AMPDU_TX_OPERATIONAL:
  564                 mutex_lock(&rtwdev->mutex);
  565                 set_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags);
  566                 rtwsta->ampdu_params[tid].agg_num = params->buf_size;
  567                 rtwsta->ampdu_params[tid].amsdu = params->amsdu;
  568                 rtw89_leave_ps_mode(rtwdev);
  569                 mutex_unlock(&rtwdev->mutex);
  570                 break;
  571         case IEEE80211_AMPDU_RX_START:
  572                 mutex_lock(&rtwdev->mutex);
  573                 rtw89_fw_h2c_ba_cam(rtwdev, rtwsta, true, params);
  574                 mutex_unlock(&rtwdev->mutex);
  575                 break;
  576         case IEEE80211_AMPDU_RX_STOP:
  577                 mutex_lock(&rtwdev->mutex);
  578                 rtw89_fw_h2c_ba_cam(rtwdev, rtwsta, false, params);
  579                 mutex_unlock(&rtwdev->mutex);
  580                 break;
  581         default:
  582                 WARN_ON(1);
  583                 return -ENOTSUPP;
  584         }
  585 
  586         return 0;
  587 }
  588 
  589 static int rtw89_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
  590 {
  591         struct rtw89_dev *rtwdev = hw->priv;
  592 
  593         mutex_lock(&rtwdev->mutex);
  594         rtw89_leave_ps_mode(rtwdev);
  595         if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
  596                 rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0);
  597         mutex_unlock(&rtwdev->mutex);
  598 
  599         return 0;
  600 }
  601 
  602 static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw,
  603                                      struct ieee80211_vif *vif,
  604                                      struct ieee80211_sta *sta,
  605                                      struct station_info *sinfo)
  606 {
  607         struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
  608 
  609         sinfo->txrate = rtwsta->ra_report.txrate;
  610         sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
  611 }
  612 
  613 static void rtw89_ops_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  614                             u32 queues, bool drop)
  615 {
  616         struct rtw89_dev *rtwdev = hw->priv;
  617 
  618         mutex_lock(&rtwdev->mutex);
  619         rtw89_leave_lps(rtwdev);
  620         rtw89_hci_flush_queues(rtwdev, queues, drop);
  621         rtw89_mac_flush_txq(rtwdev, queues, drop);
  622         mutex_unlock(&rtwdev->mutex);
  623 }
  624 
  625 struct rtw89_iter_bitrate_mask_data {
  626         struct rtw89_dev *rtwdev;
  627         struct ieee80211_vif *vif;
  628         const struct cfg80211_bitrate_mask *mask;
  629 };
  630 
  631 static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
  632 {
  633         struct rtw89_iter_bitrate_mask_data *br_data = data;
  634         struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
  635         struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif);
  636 
  637         if (vif != br_data->vif)
  638                 return;
  639 
  640         rtwsta->use_cfg_mask = true;
  641         rtwsta->mask = *br_data->mask;
  642         rtw89_phy_ra_updata_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
  643 }
  644 
  645 static void rtw89_ra_mask_info_update(struct rtw89_dev *rtwdev,
  646                                       struct ieee80211_vif *vif,
  647                                       const struct cfg80211_bitrate_mask *mask)
  648 {
  649         struct rtw89_iter_bitrate_mask_data br_data = { .rtwdev = rtwdev,
  650                                                         .vif = vif,
  651                                                         .mask = mask};
  652 
  653         ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_ra_mask_info_update_iter,
  654                                           &br_data);
  655 }
  656 
  657 static int rtw89_ops_set_bitrate_mask(struct ieee80211_hw *hw,
  658                                       struct ieee80211_vif *vif,
  659                                       const struct cfg80211_bitrate_mask *mask)
  660 {
  661         struct rtw89_dev *rtwdev = hw->priv;
  662 
  663         mutex_lock(&rtwdev->mutex);
  664         rtw89_phy_rate_pattern_vif(rtwdev, vif, mask);
  665         rtw89_ra_mask_info_update(rtwdev, vif, mask);
  666         mutex_unlock(&rtwdev->mutex);
  667 
  668         return 0;
  669 }
  670 
  671 static
  672 int rtw89_ops_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
  673 {
  674         struct rtw89_dev *rtwdev = hw->priv;
  675         struct rtw89_hal *hal = &rtwdev->hal;
  676 
  677         if (rx_ant != hw->wiphy->available_antennas_rx)
  678                 return -EINVAL;
  679 
  680         mutex_lock(&rtwdev->mutex);
  681         hal->antenna_tx = tx_ant;
  682         hal->antenna_rx = rx_ant;
  683         mutex_unlock(&rtwdev->mutex);
  684 
  685         return 0;
  686 }
  687 
  688 static
  689 int rtw89_ops_get_antenna(struct ieee80211_hw *hw,  u32 *tx_ant, u32 *rx_ant)
  690 {
  691         struct rtw89_dev *rtwdev = hw->priv;
  692         struct rtw89_hal *hal = &rtwdev->hal;
  693 
  694         *tx_ant = hal->antenna_tx;
  695         *rx_ant = hal->antenna_rx;
  696 
  697         return 0;
  698 }
  699 
  700 static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw,
  701                                     struct ieee80211_vif *vif,
  702                                     const u8 *mac_addr)
  703 {
  704         struct rtw89_dev *rtwdev = hw->priv;
  705         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  706 
  707         mutex_lock(&rtwdev->mutex);
  708         rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, false);
  709         mutex_unlock(&rtwdev->mutex);
  710 }
  711 
  712 static void rtw89_ops_sw_scan_complete(struct ieee80211_hw *hw,
  713                                        struct ieee80211_vif *vif)
  714 {
  715         struct rtw89_dev *rtwdev = hw->priv;
  716 
  717         mutex_lock(&rtwdev->mutex);
  718         rtw89_core_scan_complete(rtwdev, vif, false);
  719         mutex_unlock(&rtwdev->mutex);
  720 }
  721 
  722 static void rtw89_ops_reconfig_complete(struct ieee80211_hw *hw,
  723                                         enum ieee80211_reconfig_type reconfig_type)
  724 {
  725         struct rtw89_dev *rtwdev = hw->priv;
  726 
  727         if (reconfig_type == IEEE80211_RECONFIG_TYPE_RESTART)
  728                 rtw89_ser_recfg_done(rtwdev);
  729 }
  730 
  731 static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  732                              struct ieee80211_scan_request *req)
  733 {
  734         struct rtw89_dev *rtwdev = hw->priv;
  735         int ret = 0;
  736 
  737         if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
  738                 return 1;
  739 
  740         if (rtwdev->scanning)
  741                 return -EBUSY;
  742 
  743         mutex_lock(&rtwdev->mutex);
  744         rtw89_hw_scan_start(rtwdev, vif, req);
  745         ret = rtw89_hw_scan_offload(rtwdev, vif, true);
  746         if (ret) {
  747                 rtw89_hw_scan_abort(rtwdev, vif);
  748                 rtw89_err(rtwdev, "HW scan failed with status: %d\n", ret);
  749         }
  750         mutex_unlock(&rtwdev->mutex);
  751 
  752         return ret;
  753 }
  754 
  755 static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw,
  756                                      struct ieee80211_vif *vif)
  757 {
  758         struct rtw89_dev *rtwdev = hw->priv;
  759 
  760         if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
  761                 return;
  762 
  763         if (!rtwdev->scanning)
  764                 return;
  765 
  766         mutex_lock(&rtwdev->mutex);
  767         rtw89_hw_scan_abort(rtwdev, vif);
  768         mutex_unlock(&rtwdev->mutex);
  769 }
  770 
  771 static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw,
  772                                     struct ieee80211_vif *vif,
  773                                     struct ieee80211_sta *sta, u32 changed)
  774 {
  775         struct rtw89_dev *rtwdev = hw->priv;
  776 
  777         rtw89_phy_ra_updata_sta(rtwdev, sta, changed);
  778 }
  779 
  780 static int rtw89_ops_add_chanctx(struct ieee80211_hw *hw,
  781                                  struct ieee80211_chanctx_conf *ctx)
  782 {
  783         struct rtw89_dev *rtwdev = hw->priv;
  784         int ret;
  785 
  786         mutex_lock(&rtwdev->mutex);
  787         ret = rtw89_chanctx_ops_add(rtwdev, ctx);
  788         mutex_unlock(&rtwdev->mutex);
  789 
  790         return ret;
  791 }
  792 
  793 static void rtw89_ops_remove_chanctx(struct ieee80211_hw *hw,
  794                                      struct ieee80211_chanctx_conf *ctx)
  795 {
  796         struct rtw89_dev *rtwdev = hw->priv;
  797 
  798         mutex_lock(&rtwdev->mutex);
  799         rtw89_chanctx_ops_remove(rtwdev, ctx);
  800         mutex_unlock(&rtwdev->mutex);
  801 }
  802 
  803 static void rtw89_ops_change_chanctx(struct ieee80211_hw *hw,
  804                                      struct ieee80211_chanctx_conf *ctx,
  805                                      u32 changed)
  806 {
  807         struct rtw89_dev *rtwdev = hw->priv;
  808 
  809         mutex_lock(&rtwdev->mutex);
  810         rtw89_chanctx_ops_change(rtwdev, ctx, changed);
  811         mutex_unlock(&rtwdev->mutex);
  812 }
  813 
  814 static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw,
  815                                         struct ieee80211_vif *vif,
  816                                         struct ieee80211_bss_conf *link_conf,
  817                                         struct ieee80211_chanctx_conf *ctx)
  818 {
  819         struct rtw89_dev *rtwdev = hw->priv;
  820         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  821         int ret;
  822 
  823         mutex_lock(&rtwdev->mutex);
  824         ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif, ctx);
  825         mutex_unlock(&rtwdev->mutex);
  826 
  827         return ret;
  828 }
  829 
  830 static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw,
  831                                            struct ieee80211_vif *vif,
  832                                            struct ieee80211_bss_conf *link_conf,
  833                                            struct ieee80211_chanctx_conf *ctx)
  834 {
  835         struct rtw89_dev *rtwdev = hw->priv;
  836         struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
  837 
  838         mutex_lock(&rtwdev->mutex);
  839         rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif, ctx);
  840         mutex_unlock(&rtwdev->mutex);
  841 }
  842 
  843 const struct ieee80211_ops rtw89_ops = {
  844         .tx                     = rtw89_ops_tx,
  845         .wake_tx_queue          = rtw89_ops_wake_tx_queue,
  846         .start                  = rtw89_ops_start,
  847         .stop                   = rtw89_ops_stop,
  848         .config                 = rtw89_ops_config,
  849         .add_interface          = rtw89_ops_add_interface,
  850         .remove_interface       = rtw89_ops_remove_interface,
  851         .configure_filter       = rtw89_ops_configure_filter,
  852         .bss_info_changed       = rtw89_ops_bss_info_changed,
  853         .start_ap               = rtw89_ops_start_ap,
  854         .stop_ap                = rtw89_ops_stop_ap,
  855         .set_tim                = rtw89_ops_set_tim,
  856         .conf_tx                = rtw89_ops_conf_tx,
  857         .sta_state              = rtw89_ops_sta_state,
  858         .set_key                = rtw89_ops_set_key,
  859         .ampdu_action           = rtw89_ops_ampdu_action,
  860         .set_rts_threshold      = rtw89_ops_set_rts_threshold,
  861         .sta_statistics         = rtw89_ops_sta_statistics,
  862         .flush                  = rtw89_ops_flush,
  863         .set_bitrate_mask       = rtw89_ops_set_bitrate_mask,
  864         .set_antenna            = rtw89_ops_set_antenna,
  865         .get_antenna            = rtw89_ops_get_antenna,
  866         .sw_scan_start          = rtw89_ops_sw_scan_start,
  867         .sw_scan_complete       = rtw89_ops_sw_scan_complete,
  868         .reconfig_complete      = rtw89_ops_reconfig_complete,
  869         .hw_scan                = rtw89_ops_hw_scan,
  870         .cancel_hw_scan         = rtw89_ops_cancel_hw_scan,
  871         .add_chanctx            = rtw89_ops_add_chanctx,
  872         .remove_chanctx         = rtw89_ops_remove_chanctx,
  873         .change_chanctx         = rtw89_ops_change_chanctx,
  874         .assign_vif_chanctx     = rtw89_ops_assign_vif_chanctx,
  875         .unassign_vif_chanctx   = rtw89_ops_unassign_vif_chanctx,
  876         .set_sar_specs          = rtw89_ops_set_sar_specs,
  877         .sta_rc_update          = rtw89_ops_sta_rc_update,
  878 };
  879 EXPORT_SYMBOL(rtw89_ops);

Cache object: 83ff885d224d7ff66a3dbd644fede22e


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