root/drivers/staging/rtl8723bs/os_dep/xmit_linux.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtw_remainder_len
  2. _rtw_open_pktfile
  3. _rtw_pktfile_read
  4. rtw_endofpktfile
  5. rtw_os_xmit_resource_alloc
  6. rtw_os_xmit_resource_free
  7. rtw_os_pkt_complete
  8. rtw_os_xmit_complete
  9. rtw_os_xmit_schedule
  10. rtw_check_xmit_resource
  11. rtw_mlcst2unicst
  12. _rtw_xmit_entry
  13. rtw_xmit_entry

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5  *
   6  ******************************************************************************/
   7 #define _XMIT_OSDEP_C_
   8 
   9 #include <drv_types.h>
  10 #include <rtw_debug.h>
  11 
  12 
  13 uint rtw_remainder_len(struct pkt_file *pfile)
  14 {
  15         return (pfile->buf_len - ((SIZE_PTR)(pfile->cur_addr) - (SIZE_PTR)(pfile->buf_start)));
  16 }
  17 
  18 void _rtw_open_pktfile (_pkt *pktptr, struct pkt_file *pfile)
  19 {
  20         pfile->pkt = pktptr;
  21         pfile->cur_addr = pfile->buf_start = pktptr->data;
  22         pfile->pkt_len = pfile->buf_len = pktptr->len;
  23 
  24         pfile->cur_buffer = pfile->buf_start ;
  25 }
  26 
  27 uint _rtw_pktfile_read (struct pkt_file *pfile, u8 *rmem, uint rlen)
  28 {
  29         uint    len = 0;
  30 
  31         len =  rtw_remainder_len(pfile);
  32         len = (rlen > len) ? len : rlen;
  33 
  34         if (rmem)
  35                 skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len, rmem, len);
  36 
  37         pfile->cur_addr += len;
  38         pfile->pkt_len -= len;
  39         return len;
  40 }
  41 
  42 sint rtw_endofpktfile(struct pkt_file *pfile)
  43 {
  44         if (pfile->pkt_len == 0)
  45                 return true;
  46         return false;
  47 }
  48 
  49 int rtw_os_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitbuf, u32 alloc_sz, u8 flag)
  50 {
  51         if (alloc_sz > 0) {
  52                 pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
  53                 if (!pxmitbuf->pallocated_buf)
  54                         return _FAIL;
  55 
  56                 pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
  57         }
  58 
  59         return _SUCCESS;
  60 }
  61 
  62 void rtw_os_xmit_resource_free(struct adapter *padapter, struct xmit_buf *pxmitbuf, u32 free_sz, u8 flag)
  63 {
  64         if (free_sz > 0)
  65                 kfree(pxmitbuf->pallocated_buf);
  66 }
  67 
  68 #define WMM_XMIT_THRESHOLD      (NR_XMITFRAME * 2 / 5)
  69 
  70 void rtw_os_pkt_complete(struct adapter *padapter, _pkt *pkt)
  71 {
  72         u16 queue;
  73         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  74 
  75         queue = skb_get_queue_mapping(pkt);
  76         if (padapter->registrypriv.wifi_spec) {
  77                 if (__netif_subqueue_stopped(padapter->pnetdev, queue) &&
  78                     (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
  79                         netif_wake_subqueue(padapter->pnetdev, queue);
  80         } else {
  81                 if (__netif_subqueue_stopped(padapter->pnetdev, queue))
  82                         netif_wake_subqueue(padapter->pnetdev, queue);
  83         }
  84 
  85         dev_kfree_skb_any(pkt);
  86 }
  87 
  88 void rtw_os_xmit_complete(struct adapter *padapter, struct xmit_frame *pxframe)
  89 {
  90         if (pxframe->pkt)
  91                 rtw_os_pkt_complete(padapter, pxframe->pkt);
  92 
  93         pxframe->pkt = NULL;
  94 }
  95 
  96 void rtw_os_xmit_schedule(struct adapter *padapter)
  97 {
  98         struct adapter *pri_adapter = padapter;
  99 
 100         if (!padapter)
 101                 return;
 102 
 103         if (!list_empty(&padapter->xmitpriv.pending_xmitbuf_queue.queue))
 104                 complete(&pri_adapter->xmitpriv.xmit_comp);
 105 }
 106 
 107 static void rtw_check_xmit_resource(struct adapter *padapter, _pkt *pkt)
 108 {
 109         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 110         u16 queue;
 111 
 112         queue = skb_get_queue_mapping(pkt);
 113         if (padapter->registrypriv.wifi_spec) {
 114                 /* No free space for Tx, tx_worker is too slow */
 115                 if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD) {
 116                         /* DBG_871X("%s(): stop netif_subqueue[%d]\n", __func__, queue); */
 117                         netif_stop_subqueue(padapter->pnetdev, queue);
 118                 }
 119         } else {
 120                 if (pxmitpriv->free_xmitframe_cnt <= 4) {
 121                         if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
 122                                 netif_stop_subqueue(padapter->pnetdev, queue);
 123                 }
 124         }
 125 }
 126 
 127 static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
 128 {
 129         struct  sta_priv *pstapriv = &padapter->stapriv;
 130         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 131         struct list_head        *phead, *plist;
 132         struct sk_buff *newskb;
 133         struct sta_info *psta = NULL;
 134         u8 chk_alive_num = 0;
 135         char chk_alive_list[NUM_STA];
 136         u8 bc_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 137         u8 null_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 138 
 139         int i;
 140         s32     res;
 141 
 142         DBG_COUNTER(padapter->tx_logs.os_tx_m2u);
 143 
 144         spin_lock_bh(&pstapriv->asoc_list_lock);
 145         phead = &pstapriv->asoc_list;
 146         plist = get_next(phead);
 147 
 148         /* free sta asoc_queue */
 149         while (phead != plist) {
 150                 int stainfo_offset;
 151                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
 152                 plist = get_next(plist);
 153 
 154                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
 155                 if (stainfo_offset_valid(stainfo_offset)) {
 156                         chk_alive_list[chk_alive_num++] = stainfo_offset;
 157                 }
 158         }
 159         spin_unlock_bh(&pstapriv->asoc_list_lock);
 160 
 161         for (i = 0; i < chk_alive_num; i++) {
 162                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
 163                 if (!(psta->state & _FW_LINKED)) {
 164                         DBG_COUNTER(padapter->tx_logs.os_tx_m2u_ignore_fw_linked);
 165                         continue;
 166                 }
 167 
 168                 /* avoid come from STA1 and send back STA1 */
 169                 if (!memcmp(psta->hwaddr, &skb->data[6], 6) ||
 170                     !memcmp(psta->hwaddr, null_addr, 6) ||
 171                     !memcmp(psta->hwaddr, bc_addr, 6)) {
 172                         DBG_COUNTER(padapter->tx_logs.os_tx_m2u_ignore_self);
 173                         continue;
 174                 }
 175 
 176                 DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry);
 177 
 178                 newskb = rtw_skb_copy(skb);
 179 
 180                 if (newskb) {
 181                         memcpy(newskb->data, psta->hwaddr, 6);
 182                         res = rtw_xmit(padapter, &newskb);
 183                         if (res < 0) {
 184                                 DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry_err_xmit);
 185                                 DBG_871X("%s()-%d: rtw_xmit() return error!\n", __func__, __LINE__);
 186                                 pxmitpriv->tx_drop++;
 187                                 dev_kfree_skb_any(newskb);
 188                         }
 189                 } else {
 190                         DBG_COUNTER(padapter->tx_logs.os_tx_m2u_entry_err_skb);
 191                         DBG_871X("%s-%d: rtw_skb_copy() failed!\n", __func__, __LINE__);
 192                         pxmitpriv->tx_drop++;
 193                         /* dev_kfree_skb_any(skb); */
 194                         return false;   /*  Caller shall tx this multicast frame via normal way. */
 195                 }
 196         }
 197 
 198         dev_kfree_skb_any(skb);
 199         return true;
 200 }
 201 
 202 int _rtw_xmit_entry(_pkt *pkt, _nic_hdl pnetdev)
 203 {
 204         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
 205         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 206         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 207         s32 res = 0;
 208 
 209         DBG_COUNTER(padapter->tx_logs.os_tx);
 210         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
 211 
 212         if (rtw_if_up(padapter) == false) {
 213                 DBG_COUNTER(padapter->tx_logs.os_tx_err_up);
 214                 RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit_entry: rtw_if_up fail\n"));
 215                 #ifdef DBG_TX_DROP_FRAME
 216                 DBG_871X("DBG_TX_DROP_FRAME %s if_up fail\n", __func__);
 217                 #endif
 218                 goto drop_packet;
 219         }
 220 
 221         rtw_check_xmit_resource(padapter, pkt);
 222 
 223         if (!rtw_mc2u_disable
 224                 && check_fwstate(pmlmepriv, WIFI_AP_STATE) == true
 225                 && (IP_MCAST_MAC(pkt->data)
 226                         || ICMPV6_MCAST_MAC(pkt->data)
 227                         #ifdef CONFIG_TX_BCAST2UNI
 228                         || is_broadcast_mac_addr(pkt->data)
 229                         #endif
 230                         )
 231                 && padapter->registrypriv.wifi_spec == 0) {
 232                 if (pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME / 4)) {
 233                         res = rtw_mlcst2unicst(padapter, pkt);
 234                         if (res)
 235                                 goto exit;
 236                 } else {
 237                         /* DBG_871X("Stop M2U(%d, %d)! ", pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmitbuf_cnt); */
 238                         /* DBG_871X("!m2u); */
 239                         DBG_COUNTER(padapter->tx_logs.os_tx_m2u_stop);
 240                 }
 241         }
 242 
 243         res = rtw_xmit(padapter, &pkt);
 244         if (res < 0) {
 245                 #ifdef DBG_TX_DROP_FRAME
 246                 DBG_871X("DBG_TX_DROP_FRAME %s rtw_xmit fail\n", __func__);
 247                 #endif
 248                 goto drop_packet;
 249         }
 250 
 251         RT_TRACE(_module_xmit_osdep_c_, _drv_info_, ("rtw_xmit_entry: tx_pkts =%d\n", (u32)pxmitpriv->tx_pkts));
 252         goto exit;
 253 
 254 drop_packet:
 255         pxmitpriv->tx_drop++;
 256         dev_kfree_skb_any(pkt);
 257         RT_TRACE(_module_xmit_osdep_c_, _drv_notice_, ("rtw_xmit_entry: drop, tx_drop =%d\n", (u32)pxmitpriv->tx_drop));
 258 
 259 exit:
 260         return 0;
 261 }
 262 
 263 int rtw_xmit_entry(_pkt *pkt, _nic_hdl pnetdev)
 264 {
 265         int ret = 0;
 266 
 267         if (pkt) {
 268                 rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, pkt->truesize);
 269                 ret = _rtw_xmit_entry(pkt, pnetdev);
 270         }
 271 
 272         return ret;
 273 }

/* [<][>][^][v][top][bottom][index][help] */