staging: r8188eu: correct set/defined but unused warnings from debug cleanup
[linux-block.git] / drivers / staging / rtl8188eu / os_dep / xmit_linux.c
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 xmit_buf *pxmitbuf, u32 alloc_sz)
18 {
19         int i;
20
21         pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL);
22         if (!pxmitbuf->pallocated_buf)
23                 return _FAIL;
24
25         pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ);
26
27         for (i = 0; i < 8; i++) {
28                 pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
29                 if (!pxmitbuf->pxmit_urb[i])
30                         return _FAIL;
31         }
32         return _SUCCESS;
33 }
34
35 void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf)
36 {
37         int i;
38
39         for (i = 0; i < 8; i++)
40                 usb_free_urb(pxmitbuf->pxmit_urb[i]);
41
42         kfree(pxmitbuf->pallocated_buf);
43 }
44
45 #define WMM_XMIT_THRESHOLD      (NR_XMITFRAME * 2 / 5)
46
47 void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt)
48 {
49         u16 queue;
50         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
51
52         queue = skb_get_queue_mapping(pkt);
53         if (padapter->registrypriv.wifi_spec) {
54                 if (__netif_subqueue_stopped(padapter->pnetdev, queue) &&
55                     (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
56                         netif_wake_subqueue(padapter->pnetdev, queue);
57         } else {
58                 if (__netif_subqueue_stopped(padapter->pnetdev, queue))
59                         netif_wake_subqueue(padapter->pnetdev, queue);
60         }
61
62         dev_kfree_skb_any(pkt);
63 }
64
65 void rtw_os_xmit_complete(struct adapter *padapter, struct xmit_frame *pxframe)
66 {
67         if (pxframe->pkt)
68                 rtw_os_pkt_complete(padapter, pxframe->pkt);
69         pxframe->pkt = NULL;
70 }
71
72 void rtw_os_xmit_schedule(struct adapter *padapter)
73 {
74         struct xmit_priv *pxmitpriv;
75
76         if (!padapter)
77                 return;
78
79         pxmitpriv = &padapter->xmitpriv;
80
81         spin_lock_bh(&pxmitpriv->lock);
82
83         if (rtw_txframes_pending(padapter))
84                 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
85
86         spin_unlock_bh(&pxmitpriv->lock);
87 }
88
89 static void rtw_check_xmit_resource(struct adapter *padapter,
90                                     struct sk_buff *pkt)
91 {
92         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
93         u16 queue;
94
95         queue = skb_get_queue_mapping(pkt);
96         if (padapter->registrypriv.wifi_spec) {
97                 /* No free space for Tx, tx_worker is too slow */
98                 if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD)
99                         netif_stop_subqueue(padapter->pnetdev, queue);
100         } else {
101                 if (pxmitpriv->free_xmitframe_cnt <= 4) {
102                         if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
103                                 netif_stop_subqueue(padapter->pnetdev, queue);
104                 }
105         }
106 }
107
108 static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
109 {
110         struct sta_priv *pstapriv = &padapter->stapriv;
111         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
112         struct list_head *phead, *plist;
113         struct sk_buff *newskb;
114         struct sta_info *psta = NULL;
115         s32 res;
116
117         spin_lock_bh(&pstapriv->asoc_list_lock);
118         phead = &pstapriv->asoc_list;
119         /* free sta asoc_queue */
120         list_for_each(plist, phead) {
121                 psta = list_entry(plist, struct sta_info, asoc_list);
122
123                 /* avoid come from STA1 and send back STA1 */
124                 if (!memcmp(psta->hwaddr, &skb->data[6], 6))
125                         continue;
126
127                 newskb = skb_copy(skb, GFP_ATOMIC);
128
129                 if (newskb) {
130                         memcpy(newskb->data, psta->hwaddr, 6);
131                         res = rtw_xmit(padapter, &newskb);
132                         if (res < 0) {
133                                 pxmitpriv->tx_drop++;
134                                 dev_kfree_skb_any(newskb);
135                         } else {
136                                 pxmitpriv->tx_pkts++;
137                         }
138                 } else {
139                         pxmitpriv->tx_drop++;
140
141                         spin_unlock_bh(&pstapriv->asoc_list_lock);
142
143                         /* Caller shall tx this multicast frame
144                          * via normal way.
145                          */
146                         return false;
147                 }
148         }
149
150         spin_unlock_bh(&pstapriv->asoc_list_lock);
151         dev_kfree_skb_any(skb);
152         return true;
153 }
154
155 int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
156 {
157         struct adapter *padapter = netdev_priv(pnetdev);
158         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
159         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
160         s32 res = 0;
161
162         if (!rtw_if_up(padapter))
163                 goto drop_packet;
164
165         rtw_check_xmit_resource(padapter, pkt);
166
167         if (!rtw_mc2u_disable && check_fwstate(pmlmepriv, WIFI_AP_STATE) &&
168             (IP_MCAST_MAC(pkt->data) || ICMPV6_MCAST_MAC(pkt->data)) &&
169             (padapter->registrypriv.wifi_spec == 0)) {
170                 if (pxmitpriv->free_xmitframe_cnt > NR_XMITFRAME / 4) {
171                         res = rtw_mlcst2unicst(padapter, pkt);
172                         if (res)
173                                 goto exit;
174                 }
175         }
176
177         res = rtw_xmit(padapter, &pkt);
178         if (res < 0)
179                 goto drop_packet;
180
181         pxmitpriv->tx_pkts++;
182         goto exit;
183
184 drop_packet:
185         pxmitpriv->tx_drop++;
186         dev_kfree_skb_any(pkt);
187 exit:
188         return NETDEV_TX_OK;
189 }