1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
6 ******************************************************************************/
11 uint rtw_remainder_len(struct pkt_file *pfile)
13 return (pfile->buf_len - ((SIZE_PTR)(pfile->cur_addr) - (SIZE_PTR)(pfile->buf_start)));
16 void _rtw_open_pktfile(struct sk_buff *pktptr, struct pkt_file *pfile)
19 pfile->cur_addr = pfile->buf_start = pktptr->data;
20 pfile->pkt_len = pfile->buf_len = pktptr->len;
22 pfile->cur_buffer = pfile->buf_start;
25 uint _rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
29 len = rtw_remainder_len(pfile);
30 len = (rlen > len) ? len : rlen;
33 skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len, rmem, len);
35 pfile->cur_addr += len;
36 pfile->pkt_len -= len;
40 signed int rtw_endofpktfile(struct pkt_file *pfile)
42 if (pfile->pkt_len == 0)
47 int rtw_os_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitbuf, u32 alloc_sz, u8 flag)
50 pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
51 if (!pxmitbuf->pallocated_buf)
54 pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
60 void rtw_os_xmit_resource_free(struct adapter *padapter, struct xmit_buf *pxmitbuf, u32 free_sz, u8 flag)
63 kfree(pxmitbuf->pallocated_buf);
66 #define WMM_XMIT_THRESHOLD (NR_XMITFRAME * 2 / 5)
68 void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt)
71 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
73 queue = skb_get_queue_mapping(pkt);
74 if (padapter->registrypriv.wifi_spec) {
75 if (__netif_subqueue_stopped(padapter->pnetdev, queue) &&
76 (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
77 netif_wake_subqueue(padapter->pnetdev, queue);
79 if (__netif_subqueue_stopped(padapter->pnetdev, queue))
80 netif_wake_subqueue(padapter->pnetdev, queue);
83 dev_kfree_skb_any(pkt);
86 void rtw_os_xmit_complete(struct adapter *padapter, struct xmit_frame *pxframe)
89 rtw_os_pkt_complete(padapter, pxframe->pkt);
94 void rtw_os_xmit_schedule(struct adapter *padapter)
96 struct adapter *pri_adapter = padapter;
101 if (!list_empty(&padapter->xmitpriv.pending_xmitbuf_queue.queue))
102 complete(&pri_adapter->xmitpriv.xmit_comp);
105 static void rtw_check_xmit_resource(struct adapter *padapter, struct sk_buff *pkt)
107 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
110 queue = skb_get_queue_mapping(pkt);
111 if (padapter->registrypriv.wifi_spec) {
112 /* No free space for Tx, tx_worker is too slow */
113 if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD)
114 netif_stop_subqueue(padapter->pnetdev, queue);
116 if (pxmitpriv->free_xmitframe_cnt <= 4) {
117 if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
118 netif_stop_subqueue(padapter->pnetdev, queue);
123 static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
125 struct sta_priv *pstapriv = &padapter->stapriv;
126 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
127 struct list_head *phead, *plist;
128 struct sk_buff *newskb;
129 struct sta_info *psta = NULL;
130 u8 chk_alive_num = 0;
131 char chk_alive_list[NUM_STA];
132 u8 bc_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
133 u8 null_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
138 spin_lock_bh(&pstapriv->asoc_list_lock);
139 phead = &pstapriv->asoc_list;
140 /* free sta asoc_queue */
141 list_for_each(plist, phead) {
144 psta = list_entry(plist, struct sta_info, asoc_list);
146 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
147 if (stainfo_offset_valid(stainfo_offset)) {
148 chk_alive_list[chk_alive_num++] = stainfo_offset;
151 spin_unlock_bh(&pstapriv->asoc_list_lock);
153 for (i = 0; i < chk_alive_num; i++) {
154 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
155 if (!(psta->state & _FW_LINKED))
158 /* avoid come from STA1 and send back STA1 */
159 if (!memcmp(psta->hwaddr, &skb->data[6], 6) ||
160 !memcmp(psta->hwaddr, null_addr, 6) ||
161 !memcmp(psta->hwaddr, bc_addr, 6))
164 newskb = rtw_skb_copy(skb);
167 memcpy(newskb->data, psta->hwaddr, 6);
168 res = rtw_xmit(padapter, &newskb);
170 pxmitpriv->tx_drop++;
171 dev_kfree_skb_any(newskb);
174 pxmitpriv->tx_drop++;
175 /* dev_kfree_skb_any(skb); */
176 return false; /* Caller shall tx this multicast frame via normal way. */
180 dev_kfree_skb_any(skb);
184 int _rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
186 struct adapter *padapter = rtw_netdev_priv(pnetdev);
187 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
188 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
191 if (rtw_if_up(padapter) == false)
194 rtw_check_xmit_resource(padapter, pkt);
196 if (!rtw_mc2u_disable
197 && check_fwstate(pmlmepriv, WIFI_AP_STATE) == true
198 && (IP_MCAST_MAC(pkt->data)
199 || ICMPV6_MCAST_MAC(pkt->data)
201 && padapter->registrypriv.wifi_spec == 0) {
202 if (pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME / 4)) {
203 res = rtw_mlcst2unicst(padapter, pkt);
209 res = rtw_xmit(padapter, &pkt);
216 pxmitpriv->tx_drop++;
217 dev_kfree_skb_any(pkt);
223 int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
228 ret = _rtw_xmit_entry(pkt, pnetdev);