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

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

DEFINITIONS

This source file includes following definitions.
  1. rtw_os_xmit_resource_alloc
  2. rtw_os_xmit_resource_free
  3. rtw_os_pkt_complete
  4. rtw_os_xmit_complete
  5. rtw_os_xmit_schedule
  6. rtw_check_xmit_resource
  7. rtw_mlcst2unicst
  8. 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 <osdep_service.h>
  10 #include <drv_types.h>
  11 
  12 #include <wifi.h>
  13 #include <mlme_osdep.h>
  14 #include <xmit_osdep.h>
  15 #include <osdep_intf.h>
  16 
  17 int rtw_os_xmit_resource_alloc(struct adapter *padapter,
  18                                struct xmit_buf *pxmitbuf, u32 alloc_sz)
  19 {
  20         int i;
  21 
  22         pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL);
  23         if (!pxmitbuf->pallocated_buf)
  24                 return _FAIL;
  25 
  26         pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ);
  27         pxmitbuf->dma_transfer_addr = 0;
  28 
  29         for (i = 0; i < 8; i++) {
  30                 pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
  31                 if (!pxmitbuf->pxmit_urb[i]) {
  32                         DBG_88E("pxmitbuf->pxmit_urb[i]==NULL");
  33                         return _FAIL;
  34                 }
  35         }
  36         return _SUCCESS;
  37 }
  38 
  39 void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf)
  40 {
  41         int i;
  42 
  43         for (i = 0; i < 8; i++)
  44                 usb_free_urb(pxmitbuf->pxmit_urb[i]);
  45 
  46         kfree(pxmitbuf->pallocated_buf);
  47 }
  48 
  49 #define WMM_XMIT_THRESHOLD      (NR_XMITFRAME * 2 / 5)
  50 
  51 void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt)
  52 {
  53         u16 queue;
  54         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  55 
  56         queue = skb_get_queue_mapping(pkt);
  57         if (padapter->registrypriv.wifi_spec) {
  58                 if (__netif_subqueue_stopped(padapter->pnetdev, queue) &&
  59                     (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
  60                         netif_wake_subqueue(padapter->pnetdev, queue);
  61         } else {
  62                 if (__netif_subqueue_stopped(padapter->pnetdev, queue))
  63                         netif_wake_subqueue(padapter->pnetdev, queue);
  64         }
  65 
  66         dev_kfree_skb_any(pkt);
  67 }
  68 
  69 void rtw_os_xmit_complete(struct adapter *padapter, struct xmit_frame *pxframe)
  70 {
  71         if (pxframe->pkt)
  72                 rtw_os_pkt_complete(padapter, pxframe->pkt);
  73         pxframe->pkt = NULL;
  74 }
  75 
  76 void rtw_os_xmit_schedule(struct adapter *padapter)
  77 {
  78         struct xmit_priv *pxmitpriv;
  79 
  80         if (!padapter)
  81                 return;
  82 
  83         pxmitpriv = &padapter->xmitpriv;
  84 
  85         spin_lock_bh(&pxmitpriv->lock);
  86 
  87         if (rtw_txframes_pending(padapter))
  88                 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
  89 
  90         spin_unlock_bh(&pxmitpriv->lock);
  91 }
  92 
  93 static void rtw_check_xmit_resource(struct adapter *padapter,
  94                                     struct sk_buff *pkt)
  95 {
  96         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  97         u16 queue;
  98 
  99         queue = skb_get_queue_mapping(pkt);
 100         if (padapter->registrypriv.wifi_spec) {
 101                 /* No free space for Tx, tx_worker is too slow */
 102                 if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD)
 103                         netif_stop_subqueue(padapter->pnetdev, queue);
 104         } else {
 105                 if (pxmitpriv->free_xmitframe_cnt <= 4) {
 106                         if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
 107                                 netif_stop_subqueue(padapter->pnetdev, queue);
 108                 }
 109         }
 110 }
 111 
 112 static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
 113 {
 114         struct sta_priv *pstapriv = &padapter->stapriv;
 115         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 116         struct list_head *phead, *plist;
 117         struct sk_buff *newskb;
 118         struct sta_info *psta = NULL;
 119         s32 res;
 120 
 121         spin_lock_bh(&pstapriv->asoc_list_lock);
 122         phead = &pstapriv->asoc_list;
 123         plist = phead->next;
 124 
 125         /* free sta asoc_queue */
 126         while (phead != plist) {
 127                 psta = container_of(plist, struct sta_info, asoc_list);
 128 
 129                 plist = plist->next;
 130 
 131                 /* avoid come from STA1 and send back STA1 */
 132                 if (!memcmp(psta->hwaddr, &skb->data[6], 6))
 133                         continue;
 134 
 135                 newskb = skb_copy(skb, GFP_ATOMIC);
 136 
 137                 if (newskb) {
 138                         memcpy(newskb->data, psta->hwaddr, 6);
 139                         res = rtw_xmit(padapter, &newskb);
 140                         if (res < 0) {
 141                                 DBG_88E("%s()-%d: rtw_xmit() return error!\n",
 142                                         __func__, __LINE__);
 143                                 pxmitpriv->tx_drop++;
 144                                 dev_kfree_skb_any(newskb);
 145                         } else {
 146                                 pxmitpriv->tx_pkts++;
 147                         }
 148                 } else {
 149                         DBG_88E("%s-%d: skb_copy() failed!\n",
 150                                 __func__, __LINE__);
 151                         pxmitpriv->tx_drop++;
 152 
 153                         spin_unlock_bh(&pstapriv->asoc_list_lock);
 154 
 155                         /* Caller shall tx this multicast frame
 156                          * via normal way.
 157                          */
 158                         return false;
 159                 }
 160         }
 161 
 162         spin_unlock_bh(&pstapriv->asoc_list_lock);
 163         dev_kfree_skb_any(skb);
 164         return true;
 165 }
 166 
 167 int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
 168 {
 169         struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
 170         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 171         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 172         s32 res = 0;
 173 
 174         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
 175 
 176         if (!rtw_if_up(padapter)) {
 177                 RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
 178                          ("%s: rtw_if_up fail\n", __func__));
 179                 goto drop_packet;
 180         }
 181 
 182         rtw_check_xmit_resource(padapter, pkt);
 183 
 184         if (!rtw_mc2u_disable && check_fwstate(pmlmepriv, WIFI_AP_STATE) &&
 185             (IP_MCAST_MAC(pkt->data) || ICMPV6_MCAST_MAC(pkt->data)) &&
 186             (padapter->registrypriv.wifi_spec == 0)) {
 187                 if (pxmitpriv->free_xmitframe_cnt > NR_XMITFRAME / 4) {
 188                         res = rtw_mlcst2unicst(padapter, pkt);
 189                         if (res)
 190                                 goto exit;
 191                 }
 192         }
 193 
 194         res = rtw_xmit(padapter, &pkt);
 195         if (res < 0)
 196                 goto drop_packet;
 197 
 198         pxmitpriv->tx_pkts++;
 199         RT_TRACE(_module_xmit_osdep_c_, _drv_info_,
 200                  ("%s: tx_pkts=%d\n", __func__, (u32)pxmitpriv->tx_pkts));
 201         goto exit;
 202 
 203 drop_packet:
 204         pxmitpriv->tx_drop++;
 205         dev_kfree_skb_any(pkt);
 206         RT_TRACE(_module_xmit_osdep_c_, _drv_notice_,
 207                  ("%s: drop, tx_drop=%d\n", __func__, (u32)pxmitpriv->tx_drop));
 208 
 209 exit:
 210         return 0;
 211 }

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