LCOV - code coverage report
Current view: top level - drivers/net/wireless/realtek/rtw88 - tx.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 25 199 12.6 %
Date: 2022-03-28 16:04:14 Functions: 1 13 7.7 %
Branches: 10 81 12.3 %

           Branch data     Line data    Source code
       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                 :            : 
      10                 :            : static
      11                 :            : void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
      12                 :            :                   struct sk_buff *skb)
      13                 :            : {
      14                 :            :         struct ieee80211_hdr *hdr;
      15                 :            :         struct rtw_vif *rtwvif;
      16                 :            : 
      17                 :            :         hdr = (struct ieee80211_hdr *)skb->data;
      18                 :            : 
      19                 :            :         if (!ieee80211_is_data(hdr->frame_control))
      20                 :            :                 return;
      21                 :            : 
      22                 :            :         if (!is_broadcast_ether_addr(hdr->addr1) &&
      23                 :            :             !is_multicast_ether_addr(hdr->addr1)) {
      24                 :            :                 rtwdev->stats.tx_unicast += skb->len;
      25                 :            :                 rtwdev->stats.tx_cnt++;
      26                 :            :                 if (vif) {
      27                 :            :                         rtwvif = (struct rtw_vif *)vif->drv_priv;
      28                 :            :                         rtwvif->stats.tx_unicast += skb->len;
      29                 :            :                         rtwvif->stats.tx_cnt++;
      30                 :            :                 }
      31                 :            :         }
      32                 :            : }
      33                 :            : 
      34                 :        380 : void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
      35                 :            : {
      36                 :        380 :         __le32 *txdesc = (__le32 *)skb->data;
      37                 :            : 
      38         [ -  + ]:        380 :         SET_TX_DESC_TXPKTSIZE(txdesc,  pkt_info->tx_pkt_size);
      39                 :        380 :         SET_TX_DESC_OFFSET(txdesc, pkt_info->offset);
      40         [ -  + ]:        380 :         SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset);
      41         [ -  + ]:        380 :         SET_TX_DESC_QSEL(txdesc, pkt_info->qsel);
      42                 :        380 :         SET_TX_DESC_BMC(txdesc, pkt_info->bmc);
      43         [ -  + ]:        380 :         SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id);
      44         [ -  + ]:        380 :         SET_TX_DESC_DATARATE(txdesc, pkt_info->rate);
      45                 :        380 :         SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback);
      46                 :        380 :         SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate);
      47         [ -  + ]:        380 :         SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type);
      48         [ -  + ]:        380 :         SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw);
      49         [ -  + ]:        380 :         SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq);
      50         [ -  + ]:        380 :         SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor);
      51         [ -  + ]:        380 :         SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density);
      52                 :        380 :         SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc);
      53                 :        380 :         SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc);
      54                 :        380 :         SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en);
      55                 :        380 :         SET_TX_DESC_LS(txdesc, pkt_info->ls);
      56                 :        380 :         SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi);
      57                 :        380 :         SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report);
      58                 :        380 :         SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn);
      59                 :        380 :         SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts);
      60                 :        380 : }
      61                 :            : EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
      62                 :            : 
      63                 :            : static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta)
      64                 :            : {
      65                 :            :         u8 exp = sta->ht_cap.ampdu_factor;
      66                 :            : 
      67                 :            :         /* the least ampdu factor is 8K, and the value in the tx desc is the
      68                 :            :          * max aggregation num, which represents val * 2 packets can be
      69                 :            :          * aggregated in an AMPDU, so here we should use 8/2=4 as the base
      70                 :            :          */
      71                 :            :         return (BIT(2) << exp) - 1;
      72                 :            : }
      73                 :            : 
      74                 :            : static u8 get_tx_ampdu_density(struct ieee80211_sta *sta)
      75                 :            : {
      76                 :            :         return sta->ht_cap.ampdu_density;
      77                 :            : }
      78                 :            : 
      79                 :            : static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev,
      80                 :            :                                  struct ieee80211_sta *sta)
      81                 :            : {
      82                 :            :         u8 rate;
      83                 :            : 
      84                 :            :         if (rtwdev->hal.rf_type == RF_2T2R && sta->ht_cap.mcs.rx_mask[1] != 0)
      85                 :            :                 rate = DESC_RATEMCS15;
      86                 :            :         else
      87                 :            :                 rate = DESC_RATEMCS7;
      88                 :            : 
      89                 :            :         return rate;
      90                 :            : }
      91                 :            : 
      92                 :            : static u8 get_highest_vht_tx_rate(struct rtw_dev *rtwdev,
      93                 :            :                                   struct ieee80211_sta *sta)
      94                 :            : {
      95                 :            :         struct rtw_efuse *efuse = &rtwdev->efuse;
      96                 :            :         u8 rate;
      97                 :            :         u16 tx_mcs_map;
      98                 :            : 
      99                 :            :         tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map);
     100                 :            :         if (efuse->hw_cap.nss == 1) {
     101                 :            :                 switch (tx_mcs_map & 0x3) {
     102                 :            :                 case IEEE80211_VHT_MCS_SUPPORT_0_7:
     103                 :            :                         rate = DESC_RATEVHT1SS_MCS7;
     104                 :            :                         break;
     105                 :            :                 case IEEE80211_VHT_MCS_SUPPORT_0_8:
     106                 :            :                         rate = DESC_RATEVHT1SS_MCS8;
     107                 :            :                         break;
     108                 :            :                 default:
     109                 :            :                 case IEEE80211_VHT_MCS_SUPPORT_0_9:
     110                 :            :                         rate = DESC_RATEVHT1SS_MCS9;
     111                 :            :                         break;
     112                 :            :                 }
     113                 :            :         } else if (efuse->hw_cap.nss >= 2) {
     114                 :            :                 switch ((tx_mcs_map & 0xc) >> 2) {
     115                 :            :                 case IEEE80211_VHT_MCS_SUPPORT_0_7:
     116                 :            :                         rate = DESC_RATEVHT2SS_MCS7;
     117                 :            :                         break;
     118                 :            :                 case IEEE80211_VHT_MCS_SUPPORT_0_8:
     119                 :            :                         rate = DESC_RATEVHT2SS_MCS8;
     120                 :            :                         break;
     121                 :            :                 default:
     122                 :            :                 case IEEE80211_VHT_MCS_SUPPORT_0_9:
     123                 :            :                         rate = DESC_RATEVHT2SS_MCS9;
     124                 :            :                         break;
     125                 :            :                 }
     126                 :            :         } else {
     127                 :            :                 rate = DESC_RATEVHT1SS_MCS9;
     128                 :            :         }
     129                 :            : 
     130                 :            :         return rate;
     131                 :            : }
     132                 :            : 
     133                 :          0 : static void rtw_tx_report_enable(struct rtw_dev *rtwdev,
     134                 :            :                                  struct rtw_tx_pkt_info *pkt_info)
     135                 :            : {
     136                 :          0 :         struct rtw_tx_report *tx_report = &rtwdev->tx_report;
     137                 :            : 
     138                 :            :         /* [11:8], reserved, fills with zero
     139                 :            :          * [7:2],  tx report sequence number
     140                 :            :          * [1:0],  firmware use, fills with zero
     141                 :            :          */
     142                 :          0 :         pkt_info->sn = (atomic_inc_return(&tx_report->sn) << 2) & 0xfc;
     143                 :          0 :         pkt_info->report = true;
     144                 :          0 : }
     145                 :            : 
     146                 :          0 : void rtw_tx_report_purge_timer(struct timer_list *t)
     147                 :            : {
     148                 :          0 :         struct rtw_dev *rtwdev = from_timer(rtwdev, t, tx_report.purge_timer);
     149                 :          0 :         struct rtw_tx_report *tx_report = &rtwdev->tx_report;
     150                 :          0 :         unsigned long flags;
     151                 :            : 
     152         [ #  # ]:          0 :         if (skb_queue_len(&tx_report->queue) == 0)
     153                 :            :                 return;
     154                 :            : 
     155                 :          0 :         WARN(1, "purge skb(s) not reported by firmware\n");
     156                 :            : 
     157                 :          0 :         spin_lock_irqsave(&tx_report->q_lock, flags);
     158                 :          0 :         skb_queue_purge(&tx_report->queue);
     159                 :          0 :         spin_unlock_irqrestore(&tx_report->q_lock, flags);
     160                 :            : }
     161                 :            : 
     162                 :          0 : void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)
     163                 :            : {
     164                 :          0 :         struct rtw_tx_report *tx_report = &rtwdev->tx_report;
     165                 :          0 :         unsigned long flags;
     166                 :          0 :         u8 *drv_data;
     167                 :            : 
     168                 :            :         /* pass sn to tx report handler through driver data */
     169                 :          0 :         drv_data = (u8 *)IEEE80211_SKB_CB(skb)->status.status_driver_data;
     170                 :          0 :         *drv_data = sn;
     171                 :            : 
     172                 :          0 :         spin_lock_irqsave(&tx_report->q_lock, flags);
     173                 :          0 :         __skb_queue_tail(&tx_report->queue, skb);
     174                 :          0 :         spin_unlock_irqrestore(&tx_report->q_lock, flags);
     175                 :            : 
     176                 :          0 :         mod_timer(&tx_report->purge_timer, jiffies + RTW_TX_PROBE_TIMEOUT);
     177                 :          0 : }
     178                 :            : EXPORT_SYMBOL(rtw_tx_report_enqueue);
     179                 :            : 
     180                 :          0 : static void rtw_tx_report_tx_status(struct rtw_dev *rtwdev,
     181                 :            :                                     struct sk_buff *skb, bool acked)
     182                 :            : {
     183                 :          0 :         struct ieee80211_tx_info *info;
     184                 :            : 
     185                 :          0 :         info = IEEE80211_SKB_CB(skb);
     186                 :          0 :         ieee80211_tx_info_clear_status(info);
     187         [ #  # ]:          0 :         if (acked)
     188                 :          0 :                 info->flags |= IEEE80211_TX_STAT_ACK;
     189                 :            :         else
     190                 :          0 :                 info->flags &= ~IEEE80211_TX_STAT_ACK;
     191                 :            : 
     192                 :          0 :         ieee80211_tx_status_irqsafe(rtwdev->hw, skb);
     193                 :          0 : }
     194                 :            : 
     195                 :          0 : void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
     196                 :            : {
     197                 :          0 :         struct rtw_tx_report *tx_report = &rtwdev->tx_report;
     198                 :          0 :         struct rtw_c2h_cmd *c2h;
     199                 :          0 :         struct sk_buff *cur, *tmp;
     200                 :          0 :         unsigned long flags;
     201                 :          0 :         u8 sn, st;
     202                 :          0 :         u8 *n;
     203                 :            : 
     204                 :          0 :         c2h = get_c2h_from_skb(skb);
     205                 :            : 
     206                 :          0 :         sn = GET_CCX_REPORT_SEQNUM(c2h->payload);
     207                 :          0 :         st = GET_CCX_REPORT_STATUS(c2h->payload);
     208                 :            : 
     209                 :          0 :         spin_lock_irqsave(&tx_report->q_lock, flags);
     210         [ #  # ]:          0 :         skb_queue_walk_safe(&tx_report->queue, cur, tmp) {
     211         [ #  # ]:          0 :                 n = (u8 *)IEEE80211_SKB_CB(cur)->status.status_driver_data;
     212         [ #  # ]:          0 :                 if (*n == sn) {
     213                 :          0 :                         __skb_unlink(cur, &tx_report->queue);
     214                 :          0 :                         rtw_tx_report_tx_status(rtwdev, cur, st == 0);
     215                 :          0 :                         break;
     216                 :            :                 }
     217                 :            :         }
     218                 :          0 :         spin_unlock_irqrestore(&tx_report->q_lock, flags);
     219                 :          0 : }
     220                 :            : 
     221                 :          0 : static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev,
     222                 :            :                                         struct rtw_tx_pkt_info *pkt_info,
     223                 :            :                                         struct ieee80211_tx_control *control,
     224                 :            :                                         struct sk_buff *skb)
     225                 :            : {
     226                 :          0 :         pkt_info->use_rate = true;
     227                 :          0 :         pkt_info->rate_id = 6;
     228                 :          0 :         pkt_info->dis_rate_fallback = true;
     229                 :          0 : }
     230                 :            : 
     231                 :            : static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
     232                 :            :                                         struct rtw_tx_pkt_info *pkt_info,
     233                 :            :                                         struct ieee80211_tx_control *control,
     234                 :            :                                         struct sk_buff *skb)
     235                 :            : {
     236                 :            :         struct ieee80211_sta *sta = control->sta;
     237                 :            :         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
     238                 :            :         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
     239                 :            :         struct rtw_sta_info *si;
     240                 :            :         u16 seq;
     241                 :            :         u8 ampdu_factor = 0;
     242                 :            :         u8 ampdu_density = 0;
     243                 :            :         bool ampdu_en = false;
     244                 :            :         u8 rate = DESC_RATE6M;
     245                 :            :         u8 rate_id = 6;
     246                 :            :         u8 bw = RTW_CHANNEL_WIDTH_20;
     247                 :            :         bool stbc = false;
     248                 :            :         bool ldpc = false;
     249                 :            : 
     250                 :            :         seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
     251                 :            : 
     252                 :            :         /* for broadcast/multicast, use default values */
     253                 :            :         if (!sta)
     254                 :            :                 goto out;
     255                 :            : 
     256                 :            :         if (info->flags & IEEE80211_TX_CTL_AMPDU) {
     257                 :            :                 ampdu_en = true;
     258                 :            :                 ampdu_factor = get_tx_ampdu_factor(sta);
     259                 :            :                 ampdu_density = get_tx_ampdu_density(sta);
     260                 :            :         }
     261                 :            : 
     262                 :            :         if (info->control.use_rts)
     263                 :            :                 pkt_info->rts = true;
     264                 :            : 
     265                 :            :         if (sta->vht_cap.vht_supported)
     266                 :            :                 rate = get_highest_vht_tx_rate(rtwdev, sta);
     267                 :            :         else if (sta->ht_cap.ht_supported)
     268                 :            :                 rate = get_highest_ht_tx_rate(rtwdev, sta);
     269                 :            :         else if (sta->supp_rates[0] <= 0xf)
     270                 :            :                 rate = DESC_RATE11M;
     271                 :            :         else
     272                 :            :                 rate = DESC_RATE54M;
     273                 :            : 
     274                 :            :         si = (struct rtw_sta_info *)sta->drv_priv;
     275                 :            : 
     276                 :            :         bw = si->bw_mode;
     277                 :            :         rate_id = si->rate_id;
     278                 :            :         stbc = si->stbc_en;
     279                 :            :         ldpc = si->ldpc_en;
     280                 :            : 
     281                 :            : out:
     282                 :            :         pkt_info->seq = seq;
     283                 :            :         pkt_info->ampdu_factor = ampdu_factor;
     284                 :            :         pkt_info->ampdu_density = ampdu_density;
     285                 :            :         pkt_info->ampdu_en = ampdu_en;
     286                 :            :         pkt_info->rate = rate;
     287                 :            :         pkt_info->rate_id = rate_id;
     288                 :            :         pkt_info->bw = bw;
     289                 :            :         pkt_info->stbc = stbc;
     290                 :            :         pkt_info->ldpc = ldpc;
     291                 :            : }
     292                 :            : 
     293                 :          0 : void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
     294                 :            :                             struct rtw_tx_pkt_info *pkt_info,
     295                 :            :                             struct ieee80211_tx_control *control,
     296                 :            :                             struct sk_buff *skb)
     297                 :            : {
     298                 :          0 :         struct rtw_chip_info *chip = rtwdev->chip;
     299         [ #  # ]:          0 :         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
     300                 :          0 :         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
     301                 :          0 :         struct rtw_sta_info *si;
     302                 :          0 :         struct ieee80211_vif *vif = NULL;
     303                 :          0 :         __le16 fc = hdr->frame_control;
     304                 :          0 :         u8 sec_type = 0;
     305                 :          0 :         bool bmc;
     306                 :            : 
     307         [ #  # ]:          0 :         if (control->sta) {
     308                 :          0 :                 si = (struct rtw_sta_info *)control->sta->drv_priv;
     309                 :          0 :                 vif = si->vif;
     310                 :            :         }
     311                 :            : 
     312   [ #  #  #  # ]:          0 :         if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc))
     313                 :          0 :                 rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, control, skb);
     314         [ #  # ]:          0 :         else if (ieee80211_is_data(fc))
     315                 :          0 :                 rtw_tx_data_pkt_info_update(rtwdev, pkt_info, control, skb);
     316                 :            : 
     317         [ #  # ]:          0 :         if (info->control.hw_key) {
     318                 :          0 :                 struct ieee80211_key_conf *key = info->control.hw_key;
     319                 :            : 
     320      [ #  #  # ]:          0 :                 switch (key->cipher) {
     321                 :          0 :                 case WLAN_CIPHER_SUITE_WEP40:
     322                 :            :                 case WLAN_CIPHER_SUITE_WEP104:
     323                 :            :                 case WLAN_CIPHER_SUITE_TKIP:
     324                 :          0 :                         sec_type = 0x01;
     325                 :          0 :                         break;
     326                 :          0 :                 case WLAN_CIPHER_SUITE_CCMP:
     327                 :          0 :                         sec_type = 0x03;
     328                 :          0 :                         break;
     329                 :            :                 default:
     330                 :            :                         break;
     331                 :            :                 }
     332                 :          0 :         }
     333                 :            : 
     334   [ #  #  #  # ]:          0 :         bmc = is_broadcast_ether_addr(hdr->addr1) ||
     335                 :            :               is_multicast_ether_addr(hdr->addr1);
     336                 :            : 
     337         [ #  # ]:          0 :         if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
     338                 :          0 :                 rtw_tx_report_enable(rtwdev, pkt_info);
     339                 :            : 
     340                 :          0 :         pkt_info->bmc = bmc;
     341                 :          0 :         pkt_info->sec_type = sec_type;
     342                 :          0 :         pkt_info->tx_pkt_size = skb->len;
     343                 :          0 :         pkt_info->offset = chip->tx_pkt_desc_sz;
     344                 :          0 :         pkt_info->qsel = skb->priority;
     345                 :          0 :         pkt_info->ls = true;
     346                 :            : 
     347                 :            :         /* maybe merge with tx status ? */
     348                 :          0 :         rtw_tx_stats(rtwdev, vif, skb);
     349                 :          0 : }
     350                 :            : 
     351                 :          0 : void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
     352                 :            :                                    struct rtw_tx_pkt_info *pkt_info,
     353                 :            :                                    struct sk_buff *skb)
     354                 :            : {
     355                 :          0 :         struct rtw_chip_info *chip = rtwdev->chip;
     356                 :          0 :         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
     357                 :          0 :         bool bmc;
     358                 :            : 
     359   [ #  #  #  # ]:          0 :         bmc = is_broadcast_ether_addr(hdr->addr1) ||
     360                 :            :               is_multicast_ether_addr(hdr->addr1);
     361                 :          0 :         pkt_info->use_rate = true;
     362                 :          0 :         pkt_info->rate_id = 6;
     363                 :          0 :         pkt_info->dis_rate_fallback = true;
     364                 :          0 :         pkt_info->bmc = bmc;
     365                 :          0 :         pkt_info->tx_pkt_size = skb->len;
     366                 :          0 :         pkt_info->offset = chip->tx_pkt_desc_sz;
     367                 :          0 :         pkt_info->qsel = TX_DESC_QSEL_MGMT;
     368                 :          0 :         pkt_info->ls = true;
     369                 :          0 : }
     370                 :            : 
     371                 :          0 : void rtw_tx(struct rtw_dev *rtwdev,
     372                 :            :             struct ieee80211_tx_control *control,
     373                 :            :             struct sk_buff *skb)
     374                 :            : {
     375                 :          0 :         struct rtw_tx_pkt_info pkt_info = {0};
     376                 :            : 
     377                 :          0 :         rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb);
     378         [ #  # ]:          0 :         if (rtw_hci_tx(rtwdev, &pkt_info, skb))
     379                 :          0 :                 goto out;
     380                 :            : 
     381                 :          0 :         return;
     382                 :            : 
     383                 :            : out:
     384                 :          0 :         ieee80211_free_txskb(rtwdev->hw, skb);
     385                 :            : }
     386                 :            : 
     387                 :          0 : static void rtw_txq_check_agg(struct rtw_dev *rtwdev,
     388                 :            :                               struct rtw_txq *rtwtxq,
     389                 :            :                               struct sk_buff *skb)
     390                 :            : {
     391                 :          0 :         struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
     392                 :          0 :         struct ieee80211_tx_info *info;
     393                 :          0 :         struct rtw_sta_info *si;
     394                 :            : 
     395         [ #  # ]:          0 :         if (test_bit(RTW_TXQ_AMPDU, &rtwtxq->flags)) {
     396                 :          0 :                 info = IEEE80211_SKB_CB(skb);
     397                 :          0 :                 info->flags |= IEEE80211_TX_CTL_AMPDU;
     398                 :          0 :                 return;
     399                 :            :         }
     400                 :            : 
     401         [ #  # ]:          0 :         if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
     402                 :            :                 return;
     403                 :            : 
     404         [ #  # ]:          0 :         if (test_bit(RTW_TXQ_BLOCK_BA, &rtwtxq->flags))
     405                 :            :                 return;
     406                 :            : 
     407         [ #  # ]:          0 :         if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
     408                 :            :                 return;
     409                 :            : 
     410         [ #  # ]:          0 :         if (!txq->sta)
     411                 :            :                 return;
     412                 :            : 
     413                 :          0 :         si = (struct rtw_sta_info *)txq->sta->drv_priv;
     414                 :          0 :         set_bit(txq->tid, si->tid_ba);
     415                 :            : 
     416                 :          0 :         ieee80211_queue_work(rtwdev->hw, &rtwdev->ba_work);
     417                 :            : }
     418                 :            : 
     419                 :          0 : static bool rtw_txq_dequeue(struct rtw_dev *rtwdev,
     420                 :            :                             struct rtw_txq *rtwtxq)
     421                 :            : {
     422                 :          0 :         struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
     423                 :          0 :         struct ieee80211_tx_control control;
     424                 :          0 :         struct sk_buff *skb;
     425                 :            : 
     426                 :          0 :         skb = ieee80211_tx_dequeue(rtwdev->hw, txq);
     427         [ #  # ]:          0 :         if (!skb)
     428                 :            :                 return false;
     429                 :            : 
     430                 :          0 :         rtw_txq_check_agg(rtwdev, rtwtxq, skb);
     431                 :            : 
     432                 :          0 :         control.sta = txq->sta;
     433                 :          0 :         rtw_tx(rtwdev, &control, skb);
     434                 :          0 :         rtwtxq->last_push = jiffies;
     435                 :            : 
     436                 :          0 :         return true;
     437                 :            : }
     438                 :            : 
     439                 :          0 : static void rtw_txq_push(struct rtw_dev *rtwdev,
     440                 :            :                          struct rtw_txq *rtwtxq,
     441                 :            :                          unsigned long frames)
     442                 :            : {
     443                 :          0 :         int i;
     444                 :            : 
     445                 :          0 :         rcu_read_lock();
     446                 :            : 
     447         [ #  # ]:          0 :         for (i = 0; i < frames; i++)
     448         [ #  # ]:          0 :                 if (!rtw_txq_dequeue(rtwdev, rtwtxq))
     449                 :            :                         break;
     450                 :            : 
     451                 :          0 :         rcu_read_unlock();
     452                 :            : }
     453                 :            : 
     454                 :          0 : void rtw_tx_tasklet(unsigned long data)
     455                 :            : {
     456                 :          0 :         struct rtw_dev *rtwdev = (void *)data;
     457                 :          0 :         struct rtw_txq *rtwtxq, *tmp;
     458                 :            : 
     459                 :          0 :         spin_lock_bh(&rtwdev->txq_lock);
     460                 :            : 
     461         [ #  # ]:          0 :         list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->txqs, list) {
     462                 :          0 :                 struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
     463                 :          0 :                 unsigned long frame_cnt;
     464                 :          0 :                 unsigned long byte_cnt;
     465                 :            : 
     466                 :          0 :                 ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt);
     467                 :          0 :                 rtw_txq_push(rtwdev, rtwtxq, frame_cnt);
     468                 :            : 
     469                 :          0 :                 list_del_init(&rtwtxq->list);
     470                 :            :         }
     471                 :            : 
     472                 :          0 :         spin_unlock_bh(&rtwdev->txq_lock);
     473                 :          0 : }
     474                 :            : 
     475                 :          0 : void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
     476                 :            : {
     477                 :          0 :         struct rtw_txq *rtwtxq;
     478                 :            : 
     479         [ #  # ]:          0 :         if (!txq)
     480                 :            :                 return;
     481                 :            : 
     482                 :          0 :         rtwtxq = (struct rtw_txq *)txq->drv_priv;
     483                 :          0 :         INIT_LIST_HEAD(&rtwtxq->list);
     484                 :            : }
     485                 :            : 
     486                 :          0 : void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
     487                 :            : {
     488                 :          0 :         struct rtw_txq *rtwtxq;
     489                 :            : 
     490         [ #  # ]:          0 :         if (!txq)
     491                 :            :                 return;
     492                 :            : 
     493                 :          0 :         rtwtxq = (struct rtw_txq *)txq->drv_priv;
     494                 :          0 :         spin_lock_bh(&rtwdev->txq_lock);
     495         [ #  # ]:          0 :         if (!list_empty(&rtwtxq->list))
     496                 :          0 :                 list_del_init(&rtwtxq->list);
     497                 :          0 :         spin_unlock_bh(&rtwdev->txq_lock);
     498                 :            : }

Generated by: LCOV version 1.14