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/rtw88/tx.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) 2018-2019  Realtek Corporation
    3  */
    4 
    5 #include "main.h"
    6 #include "tx.h"
    7 #include "fw.h"
    8 #include "ps.h"
    9 #include "debug.h"
   10 
   11 static
   12 void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
   13                   struct sk_buff *skb)
   14 {
   15         struct ieee80211_hdr *hdr;
   16         struct rtw_vif *rtwvif;
   17 
   18         hdr = (struct ieee80211_hdr *)skb->data;
   19 
   20         if (!ieee80211_is_data(hdr->frame_control))
   21                 return;
   22 
   23         if (!is_broadcast_ether_addr(hdr->addr1) &&
   24             !is_multicast_ether_addr(hdr->addr1)) {
   25                 rtwdev->stats.tx_unicast += skb->len;
   26                 rtwdev->stats.tx_cnt++;
   27                 if (vif) {
   28                         rtwvif = (struct rtw_vif *)vif->drv_priv;
   29                         rtwvif->stats.tx_unicast += skb->len;
   30                         rtwvif->stats.tx_cnt++;
   31                 }
   32         }
   33 }
   34 
   35 void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
   36 {
   37         __le32 *txdesc = (__le32 *)skb->data;
   38 
   39         SET_TX_DESC_TXPKTSIZE(txdesc,  pkt_info->tx_pkt_size);
   40         SET_TX_DESC_OFFSET(txdesc, pkt_info->offset);
   41         SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset);
   42         SET_TX_DESC_QSEL(txdesc, pkt_info->qsel);
   43         SET_TX_DESC_BMC(txdesc, pkt_info->bmc);
   44         SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id);
   45         SET_TX_DESC_DATARATE(txdesc, pkt_info->rate);
   46         SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback);
   47         SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate);
   48         SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type);
   49         SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw);
   50         SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq);
   51         SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor);
   52         SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density);
   53         SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc);
   54         SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc);
   55         SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en);
   56         SET_TX_DESC_LS(txdesc, pkt_info->ls);
   57         SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi);
   58         SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report);
   59         SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn);
   60         SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts);
   61         if (pkt_info->rts) {
   62                 SET_TX_DESC_RTSRATE(txdesc, DESC_RATE24M);
   63                 SET_TX_DESC_DATA_RTS_SHORT(txdesc, 1);
   64         }
   65         SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq);
   66         SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq);
   67         SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel);
   68         SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr);
   69         SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null);
   70         if (pkt_info->tim_offset) {
   71                 SET_TX_DESC_TIM_EN(txdesc, 1);
   72                 SET_TX_DESC_TIM_OFFSET(txdesc, pkt_info->tim_offset);
   73         }
   74 }
   75 EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
   76 
   77 static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta)
   78 {
   79         u8 exp = sta->deflink.ht_cap.ampdu_factor;
   80 
   81         /* the least ampdu factor is 8K, and the value in the tx desc is the
   82          * max aggregation num, which represents val * 2 packets can be
   83          * aggregated in an AMPDU, so here we should use 8/2=4 as the base
   84          */
   85         return (BIT(2) << exp) - 1;
   86 }
   87 
   88 static u8 get_tx_ampdu_density(struct ieee80211_sta *sta)
   89 {
   90         return sta->deflink.ht_cap.ampdu_density;
   91 }
   92 
   93 static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev,
   94                                  struct ieee80211_sta *sta)
   95 {
   96         u8 rate;
   97 
   98         if (rtwdev->hal.rf_type == RF_2T2R && sta->deflink.ht_cap.mcs.rx_mask[1] != 0)
   99                 rate = DESC_RATEMCS15;
  100         else
  101                 rate = DESC_RATEMCS7;
  102 
  103         return rate;
  104 }
  105 
  106 static u8 get_highest_vht_tx_rate(struct rtw_dev *rtwdev,
  107                                   struct ieee80211_sta *sta)
  108 {
  109         struct rtw_efuse *efuse = &rtwdev->efuse;
  110         u8 rate;
  111         u16 tx_mcs_map;
  112 
  113         tx_mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.tx_mcs_map);
  114         if (efuse->hw_cap.nss == 1) {
  115                 switch (tx_mcs_map & 0x3) {
  116                 case IEEE80211_VHT_MCS_SUPPORT_0_7:
  117                         rate = DESC_RATEVHT1SS_MCS7;
  118                         break;
  119                 case IEEE80211_VHT_MCS_SUPPORT_0_8:
  120                         rate = DESC_RATEVHT1SS_MCS8;
  121                         break;
  122                 default:
  123                 case IEEE80211_VHT_MCS_SUPPORT_0_9:
  124                         rate = DESC_RATEVHT1SS_MCS9;
  125                         break;
  126                 }
  127         } else if (efuse->hw_cap.nss >= 2) {
  128                 switch ((tx_mcs_map & 0xc) >> 2) {
  129                 case IEEE80211_VHT_MCS_SUPPORT_0_7:
  130                         rate = DESC_RATEVHT2SS_MCS7;
  131                         break;
  132                 case IEEE80211_VHT_MCS_SUPPORT_0_8:
  133                         rate = DESC_RATEVHT2SS_MCS8;
  134                         break;
  135                 default:
  136                 case IEEE80211_VHT_MCS_SUPPORT_0_9:
  137                         rate = DESC_RATEVHT2SS_MCS9;
  138                         break;
  139                 }
  140         } else {
  141                 rate = DESC_RATEVHT1SS_MCS9;
  142         }
  143 
  144         return rate;
  145 }
  146 
  147 static void rtw_tx_report_enable(struct rtw_dev *rtwdev,
  148                                  struct rtw_tx_pkt_info *pkt_info)
  149 {
  150         struct rtw_tx_report *tx_report = &rtwdev->tx_report;
  151 
  152         /* [11:8], reserved, fills with zero
  153          * [7:2],  tx report sequence number
  154          * [1:0],  firmware use, fills with zero
  155          */
  156         pkt_info->sn = (atomic_inc_return(&tx_report->sn) << 2) & 0xfc;
  157         pkt_info->report = true;
  158 }
  159 
  160 void rtw_tx_report_purge_timer(struct timer_list *t)
  161 {
  162         struct rtw_dev *rtwdev = from_timer(rtwdev, t, tx_report.purge_timer);
  163         struct rtw_tx_report *tx_report = &rtwdev->tx_report;
  164         unsigned long flags;
  165 
  166 #if defined(__linux__)
  167         if (skb_queue_len(&tx_report->queue) == 0)
  168                 return;
  169 
  170         rtw_warn(rtwdev, "failed to get tx report from firmware\n");
  171 
  172         spin_lock_irqsave(&tx_report->q_lock, flags);
  173         skb_queue_purge(&tx_report->queue);
  174         spin_unlock_irqrestore(&tx_report->q_lock, flags);
  175 #elif defined(__FreeBSD__)
  176         uint32_t qlen;
  177 
  178         spin_lock_irqsave(&tx_report->q_lock, flags);
  179         qlen = skb_queue_len(&tx_report->queue);
  180         if (qlen > 0)
  181                 skb_queue_purge(&tx_report->queue);
  182         spin_unlock_irqrestore(&tx_report->q_lock, flags);
  183 
  184         /*
  185          * XXX while there could be a new enqueue in the queue
  186          * simply not yet processed given the timer is updated without
  187          * locks after enqueue in rtw_tx_report_enqueue(), the numbers
  188          * seen can be in the 100s.  We revert to rtw_dbg from
  189          * Linux git 584dce175f0461d5d9d63952a1e7955678c91086 .
  190          */
  191         rtw_dbg(rtwdev, RTW_DBG_TX, "failed to get tx report from firmware: "
  192             "txreport qlen %u\n", qlen);
  193 #endif
  194 }
  195 
  196 void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)
  197 {
  198         struct rtw_tx_report *tx_report = &rtwdev->tx_report;
  199         unsigned long flags;
  200         u8 *drv_data;
  201 
  202         /* pass sn to tx report handler through driver data */
  203         drv_data = (u8 *)IEEE80211_SKB_CB(skb)->status.status_driver_data;
  204         *drv_data = sn;
  205 
  206         spin_lock_irqsave(&tx_report->q_lock, flags);
  207         __skb_queue_tail(&tx_report->queue, skb);
  208         spin_unlock_irqrestore(&tx_report->q_lock, flags);
  209 
  210         mod_timer(&tx_report->purge_timer, jiffies + RTW_TX_PROBE_TIMEOUT);
  211 }
  212 EXPORT_SYMBOL(rtw_tx_report_enqueue);
  213 
  214 static void rtw_tx_report_tx_status(struct rtw_dev *rtwdev,
  215                                     struct sk_buff *skb, bool acked)
  216 {
  217         struct ieee80211_tx_info *info;
  218 
  219         info = IEEE80211_SKB_CB(skb);
  220         ieee80211_tx_info_clear_status(info);
  221         if (acked)
  222                 info->flags |= IEEE80211_TX_STAT_ACK;
  223         else
  224                 info->flags &= ~IEEE80211_TX_STAT_ACK;
  225 
  226         ieee80211_tx_status_irqsafe(rtwdev->hw, skb);
  227 }
  228 
  229 void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src)
  230 {
  231         struct rtw_tx_report *tx_report = &rtwdev->tx_report;
  232         struct rtw_c2h_cmd *c2h;
  233         struct sk_buff *cur, *tmp;
  234         unsigned long flags;
  235         u8 sn, st;
  236         u8 *n;
  237 
  238         c2h = get_c2h_from_skb(skb);
  239 
  240         if (src == C2H_CCX_TX_RPT) {
  241                 sn = GET_CCX_REPORT_SEQNUM_V0(c2h->payload);
  242                 st = GET_CCX_REPORT_STATUS_V0(c2h->payload);
  243         } else {
  244                 sn = GET_CCX_REPORT_SEQNUM_V1(c2h->payload);
  245                 st = GET_CCX_REPORT_STATUS_V1(c2h->payload);
  246         }
  247 
  248         spin_lock_irqsave(&tx_report->q_lock, flags);
  249         skb_queue_walk_safe(&tx_report->queue, cur, tmp) {
  250                 n = (u8 *)IEEE80211_SKB_CB(cur)->status.status_driver_data;
  251                 if (*n == sn) {
  252                         __skb_unlink(cur, &tx_report->queue);
  253                         rtw_tx_report_tx_status(rtwdev, cur, st == 0);
  254                         break;
  255                 }
  256         }
  257         spin_unlock_irqrestore(&tx_report->q_lock, flags);
  258 }
  259 
  260 static u8 rtw_get_mgmt_rate(struct rtw_dev *rtwdev, struct sk_buff *skb,
  261                             u8 lowest_rate, bool ignore_rate)
  262 {
  263         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
  264         struct ieee80211_vif *vif = tx_info->control.vif;
  265         bool force_lowest = test_bit(RTW_FLAG_FORCE_LOWEST_RATE, rtwdev->flags);
  266 
  267         if (!vif || !vif->bss_conf.basic_rates || ignore_rate || force_lowest)
  268                 return lowest_rate;
  269 
  270         return __ffs(vif->bss_conf.basic_rates) + lowest_rate;
  271 }
  272 
  273 static void rtw_tx_pkt_info_update_rate(struct rtw_dev *rtwdev,
  274                                         struct rtw_tx_pkt_info *pkt_info,
  275                                         struct sk_buff *skb,
  276                                         bool ignore_rate)
  277 {
  278         if (rtwdev->hal.current_band_type == RTW_BAND_2G) {
  279                 pkt_info->rate_id = RTW_RATEID_B_20M;
  280                 pkt_info->rate = rtw_get_mgmt_rate(rtwdev, skb, DESC_RATE1M,
  281                                                    ignore_rate);
  282         } else {
  283                 pkt_info->rate_id = RTW_RATEID_G;
  284                 pkt_info->rate = rtw_get_mgmt_rate(rtwdev, skb, DESC_RATE6M,
  285                                                    ignore_rate);
  286         }
  287 
  288         pkt_info->use_rate = true;
  289         pkt_info->dis_rate_fallback = true;
  290 }
  291 
  292 static void rtw_tx_pkt_info_update_sec(struct rtw_dev *rtwdev,
  293                                        struct rtw_tx_pkt_info *pkt_info,
  294                                        struct sk_buff *skb)
  295 {
  296         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  297         u8 sec_type = 0;
  298 
  299         if (info && info->control.hw_key) {
  300                 struct ieee80211_key_conf *key = info->control.hw_key;
  301 
  302                 switch (key->cipher) {
  303                 case WLAN_CIPHER_SUITE_WEP40:
  304                 case WLAN_CIPHER_SUITE_WEP104:
  305                 case WLAN_CIPHER_SUITE_TKIP:
  306                         sec_type = 0x01;
  307                         break;
  308                 case WLAN_CIPHER_SUITE_CCMP:
  309                         sec_type = 0x03;
  310                         break;
  311                 default:
  312                         break;
  313                 }
  314         }
  315 
  316         pkt_info->sec_type = sec_type;
  317 }
  318 
  319 static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev,
  320                                         struct rtw_tx_pkt_info *pkt_info,
  321                                         struct ieee80211_sta *sta,
  322                                         struct sk_buff *skb)
  323 {
  324         rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb, false);
  325         pkt_info->dis_qselseq = true;
  326         pkt_info->en_hwseq = true;
  327         pkt_info->hw_ssn_sel = 0;
  328         /* TODO: need to change hw port and hw ssn sel for multiple vifs */
  329 }
  330 
  331 static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
  332                                         struct rtw_tx_pkt_info *pkt_info,
  333                                         struct ieee80211_sta *sta,
  334                                         struct sk_buff *skb)
  335 {
  336         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
  337         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  338         struct ieee80211_hw *hw = rtwdev->hw;
  339         struct rtw_dm_info *dm_info = &rtwdev->dm_info;
  340         struct rtw_sta_info *si;
  341         u8 fix_rate;
  342         u16 seq;
  343         u8 ampdu_factor = 0;
  344         u8 ampdu_density = 0;
  345         bool ampdu_en = false;
  346         u8 rate = DESC_RATE6M;
  347         u8 rate_id = 6;
  348         u8 bw = RTW_CHANNEL_WIDTH_20;
  349         bool stbc = false;
  350         bool ldpc = false;
  351 
  352         seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
  353 
  354         /* for broadcast/multicast, use default values */
  355         if (!sta)
  356                 goto out;
  357 
  358         if (info->flags & IEEE80211_TX_CTL_AMPDU) {
  359                 ampdu_en = true;
  360                 ampdu_factor = get_tx_ampdu_factor(sta);
  361                 ampdu_density = get_tx_ampdu_density(sta);
  362         }
  363 
  364         if (info->control.use_rts || skb->len > hw->wiphy->rts_threshold)
  365                 pkt_info->rts = true;
  366 
  367         if (sta->deflink.vht_cap.vht_supported)
  368                 rate = get_highest_vht_tx_rate(rtwdev, sta);
  369         else if (sta->deflink.ht_cap.ht_supported)
  370                 rate = get_highest_ht_tx_rate(rtwdev, sta);
  371         else if (sta->deflink.supp_rates[0] <= 0xf)
  372                 rate = DESC_RATE11M;
  373         else
  374                 rate = DESC_RATE54M;
  375 
  376         si = (struct rtw_sta_info *)sta->drv_priv;
  377 
  378         bw = si->bw_mode;
  379         rate_id = si->rate_id;
  380         stbc = rtwdev->hal.txrx_1ss ? false : si->stbc_en;
  381         ldpc = si->ldpc_en;
  382 
  383 out:
  384         pkt_info->seq = seq;
  385         pkt_info->ampdu_factor = ampdu_factor;
  386         pkt_info->ampdu_density = ampdu_density;
  387         pkt_info->ampdu_en = ampdu_en;
  388         pkt_info->rate = rate;
  389         pkt_info->rate_id = rate_id;
  390         pkt_info->bw = bw;
  391         pkt_info->stbc = stbc;
  392         pkt_info->ldpc = ldpc;
  393 
  394         fix_rate = dm_info->fix_rate;
  395         if (fix_rate < DESC_RATE_MAX) {
  396                 pkt_info->rate = fix_rate;
  397                 pkt_info->dis_rate_fallback = true;
  398                 pkt_info->use_rate = true;
  399         }
  400 }
  401 
  402 void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
  403                             struct rtw_tx_pkt_info *pkt_info,
  404                             struct ieee80211_sta *sta,
  405                             struct sk_buff *skb)
  406 {
  407         struct rtw_chip_info *chip = rtwdev->chip;
  408         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  409         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
  410         struct rtw_sta_info *si;
  411         struct ieee80211_vif *vif = NULL;
  412         __le16 fc = hdr->frame_control;
  413         bool bmc;
  414 
  415         if (sta) {
  416                 si = (struct rtw_sta_info *)sta->drv_priv;
  417                 vif = si->vif;
  418         }
  419 
  420         if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc))
  421                 rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, sta, skb);
  422         else if (ieee80211_is_data(fc))
  423                 rtw_tx_data_pkt_info_update(rtwdev, pkt_info, sta, skb);
  424 
  425         bmc = is_broadcast_ether_addr(hdr->addr1) ||
  426               is_multicast_ether_addr(hdr->addr1);
  427 
  428         if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
  429                 rtw_tx_report_enable(rtwdev, pkt_info);
  430 
  431         pkt_info->bmc = bmc;
  432         rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
  433         pkt_info->tx_pkt_size = skb->len;
  434         pkt_info->offset = chip->tx_pkt_desc_sz;
  435         pkt_info->qsel = skb->priority;
  436         pkt_info->ls = true;
  437 
  438         /* maybe merge with tx status ? */
  439         rtw_tx_stats(rtwdev, vif, skb);
  440 }
  441 
  442 void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
  443                                       struct rtw_tx_pkt_info *pkt_info,
  444                                       struct sk_buff *skb,
  445                                       enum rtw_rsvd_packet_type type)
  446 {
  447         struct rtw_chip_info *chip = rtwdev->chip;
  448         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
  449         bool bmc;
  450 
  451         /* A beacon or dummy reserved page packet indicates that it is the first
  452          * reserved page, and the qsel of it will be set in each hci.
  453          */
  454         if (type != RSVD_BEACON && type != RSVD_DUMMY)
  455                 pkt_info->qsel = TX_DESC_QSEL_MGMT;
  456 
  457         rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb, true);
  458 
  459         bmc = is_broadcast_ether_addr(hdr->addr1) ||
  460               is_multicast_ether_addr(hdr->addr1);
  461         pkt_info->bmc = bmc;
  462         pkt_info->tx_pkt_size = skb->len;
  463         pkt_info->offset = chip->tx_pkt_desc_sz;
  464         pkt_info->ls = true;
  465         if (type == RSVD_PS_POLL) {
  466                 pkt_info->nav_use_hdr = true;
  467         } else {
  468                 pkt_info->dis_qselseq = true;
  469                 pkt_info->en_hwseq = true;
  470                 pkt_info->hw_ssn_sel = 0;
  471         }
  472         if (type == RSVD_QOS_NULL)
  473                 pkt_info->bt_null = true;
  474 
  475         if (type == RSVD_BEACON) {
  476                 struct rtw_rsvd_page *rsvd_pkt;
  477                 int hdr_len;
  478 
  479                 rsvd_pkt = list_first_entry_or_null(&rtwdev->rsvd_page_list,
  480                                                     struct rtw_rsvd_page,
  481                                                     build_list);
  482                 if (rsvd_pkt && rsvd_pkt->tim_offset != 0) {
  483                         hdr_len = sizeof(struct ieee80211_hdr_3addr);
  484                         pkt_info->tim_offset = rsvd_pkt->tim_offset - hdr_len;
  485                 }
  486         }
  487 
  488         rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
  489 
  490         /* TODO: need to change hw port and hw ssn sel for multiple vifs */
  491 }
  492 
  493 struct sk_buff *
  494 rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
  495                                 struct rtw_tx_pkt_info *pkt_info,
  496                                 u8 *buf, u32 size)
  497 {
  498         struct rtw_chip_info *chip = rtwdev->chip;
  499         struct sk_buff *skb;
  500         u32 tx_pkt_desc_sz;
  501         u32 length;
  502 
  503         tx_pkt_desc_sz = chip->tx_pkt_desc_sz;
  504         length = size + tx_pkt_desc_sz;
  505         skb = dev_alloc_skb(length);
  506         if (!skb) {
  507                 rtw_err(rtwdev, "failed to alloc write data rsvd page skb\n");
  508                 return NULL;
  509         }
  510 
  511         skb_reserve(skb, tx_pkt_desc_sz);
  512         skb_put_data(skb, buf, size);
  513         rtw_tx_rsvd_page_pkt_info_update(rtwdev, pkt_info, skb, RSVD_BEACON);
  514 
  515         return skb;
  516 }
  517 EXPORT_SYMBOL(rtw_tx_write_data_rsvd_page_get);
  518 
  519 struct sk_buff *
  520 rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
  521                           struct rtw_tx_pkt_info *pkt_info,
  522                           u8 *buf, u32 size)
  523 {
  524         struct rtw_chip_info *chip = rtwdev->chip;
  525         struct sk_buff *skb;
  526         u32 tx_pkt_desc_sz;
  527         u32 length;
  528 
  529         tx_pkt_desc_sz = chip->tx_pkt_desc_sz;
  530         length = size + tx_pkt_desc_sz;
  531         skb = dev_alloc_skb(length);
  532         if (!skb) {
  533                 rtw_err(rtwdev, "failed to alloc write data h2c skb\n");
  534                 return NULL;
  535         }
  536 
  537         skb_reserve(skb, tx_pkt_desc_sz);
  538         skb_put_data(skb, buf, size);
  539         pkt_info->tx_pkt_size = size;
  540 
  541         return skb;
  542 }
  543 EXPORT_SYMBOL(rtw_tx_write_data_h2c_get);
  544 
  545 void rtw_tx(struct rtw_dev *rtwdev,
  546             struct ieee80211_tx_control *control,
  547             struct sk_buff *skb)
  548 {
  549         struct rtw_tx_pkt_info pkt_info = {0};
  550         int ret;
  551 
  552         rtw_tx_pkt_info_update(rtwdev, &pkt_info, control->sta, skb);
  553         ret = rtw_hci_tx_write(rtwdev, &pkt_info, skb);
  554         if (ret) {
  555 #if defined(__linux__)
  556                 rtw_err(rtwdev, "failed to write TX skb to HCI\n");
  557 #elif defined(__FreeBSD__)
  558                 rtw_err(rtwdev, "%s: failed to write TX skb to HCI: %d\n", __func__, ret);
  559 #endif
  560                 goto out;
  561         }
  562 
  563         rtw_hci_tx_kick_off(rtwdev);
  564 
  565         return;
  566 
  567 out:
  568         ieee80211_free_txskb(rtwdev->hw, skb);
  569 }
  570 
  571 static void rtw_txq_check_agg(struct rtw_dev *rtwdev,
  572                               struct rtw_txq *rtwtxq,
  573                               struct sk_buff *skb)
  574 {
  575         struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
  576         struct ieee80211_tx_info *info;
  577         struct rtw_sta_info *si;
  578 
  579         if (test_bit(RTW_TXQ_AMPDU, &rtwtxq->flags)) {
  580                 info = IEEE80211_SKB_CB(skb);
  581                 info->flags |= IEEE80211_TX_CTL_AMPDU;
  582                 return;
  583         }
  584 
  585         if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
  586                 return;
  587 
  588         if (test_bit(RTW_TXQ_BLOCK_BA, &rtwtxq->flags))
  589                 return;
  590 
  591         if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
  592                 return;
  593 
  594         if (!txq->sta)
  595                 return;
  596 
  597         si = (struct rtw_sta_info *)txq->sta->drv_priv;
  598         set_bit(txq->tid, si->tid_ba);
  599 
  600         ieee80211_queue_work(rtwdev->hw, &rtwdev->ba_work);
  601 }
  602 
  603 static int rtw_txq_push_skb(struct rtw_dev *rtwdev,
  604                             struct rtw_txq *rtwtxq,
  605                             struct sk_buff *skb)
  606 {
  607         struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
  608         struct rtw_tx_pkt_info pkt_info = {0};
  609         int ret;
  610 
  611         rtw_txq_check_agg(rtwdev, rtwtxq, skb);
  612 
  613         rtw_tx_pkt_info_update(rtwdev, &pkt_info, txq->sta, skb);
  614         ret = rtw_hci_tx_write(rtwdev, &pkt_info, skb);
  615         if (ret) {
  616 #if defined(__linux__)
  617                 rtw_err(rtwdev, "failed to write TX skb to HCI\n");
  618 #elif defined(__FreeBSD__)
  619                 rtw_err(rtwdev, "%s: failed to write TX skb to HCI: %d\n", __func__, ret);
  620 #endif
  621                 return ret;
  622         }
  623         rtwtxq->last_push = jiffies;
  624 
  625         return 0;
  626 }
  627 
  628 static struct sk_buff *rtw_txq_dequeue(struct rtw_dev *rtwdev,
  629                                        struct rtw_txq *rtwtxq)
  630 {
  631         struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
  632         struct sk_buff *skb;
  633 
  634         skb = ieee80211_tx_dequeue(rtwdev->hw, txq);
  635         if (!skb)
  636                 return NULL;
  637 
  638         return skb;
  639 }
  640 
  641 static void rtw_txq_push(struct rtw_dev *rtwdev,
  642                          struct rtw_txq *rtwtxq,
  643                          unsigned long frames)
  644 {
  645         struct sk_buff *skb;
  646         int ret;
  647         int i;
  648 
  649         rcu_read_lock();
  650 
  651         for (i = 0; i < frames; i++) {
  652                 skb = rtw_txq_dequeue(rtwdev, rtwtxq);
  653                 if (!skb)
  654                         break;
  655 
  656                 ret = rtw_txq_push_skb(rtwdev, rtwtxq, skb);
  657                 if (ret) {
  658 #if defined(__FreeBSD__)
  659                         dev_kfree_skb_any(skb);
  660                         rtw_err(rtwdev, "failed to push skb, ret %d\n", ret);
  661 #else
  662                         rtw_err(rtwdev, "failed to pusk skb, ret %d\n", ret);
  663 #endif
  664                         break;
  665                 }
  666         }
  667 
  668         rcu_read_unlock();
  669 }
  670 
  671 void rtw_tx_work(struct work_struct *w)
  672 {
  673         struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work);
  674         struct rtw_txq *rtwtxq, *tmp;
  675 
  676         spin_lock_bh(&rtwdev->txq_lock);
  677 
  678         list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->txqs, list) {
  679                 struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
  680                 unsigned long frame_cnt;
  681                 unsigned long byte_cnt;
  682 
  683                 ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt);
  684                 rtw_txq_push(rtwdev, rtwtxq, frame_cnt);
  685 
  686                 list_del_init(&rtwtxq->list);
  687         }
  688 
  689         rtw_hci_tx_kick_off(rtwdev);
  690 
  691         spin_unlock_bh(&rtwdev->txq_lock);
  692 }
  693 
  694 void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
  695 {
  696         struct rtw_txq *rtwtxq;
  697 
  698         if (!txq)
  699                 return;
  700 
  701         rtwtxq = (struct rtw_txq *)txq->drv_priv;
  702         INIT_LIST_HEAD(&rtwtxq->list);
  703 }
  704 
  705 void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
  706 {
  707         struct rtw_txq *rtwtxq;
  708 
  709         if (!txq)
  710                 return;
  711 
  712         rtwtxq = (struct rtw_txq *)txq->drv_priv;
  713         spin_lock_bh(&rtwdev->txq_lock);
  714         if (!list_empty(&rtwtxq->list))
  715                 list_del_init(&rtwtxq->list);
  716         spin_unlock_bh(&rtwdev->txq_lock);
  717 }

Cache object: 6aa93c54250b160bbee5a550d5046e4e


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