1 /******************************************************************************
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_XMIT_C_
31 #include "osdep_service.h"
32 #include "drv_types.h"
33 #include "rtl871x_byteorder.h"
35 #include "osdep_intf.h"
39 static const u8 P802_1H_OUI
[P80211_OUI_LEN
] = {0x00, 0x00, 0xf8};
40 static const u8 RFC1042_OUI
[P80211_OUI_LEN
] = {0x00, 0x00, 0x00};
41 static void init_hwxmits(struct hw_xmit
*phwxmit
, sint entry
);
42 static void alloc_hwxmits(struct _adapter
*padapter
);
43 static void free_hwxmits(struct _adapter
*padapter
);
45 static void _init_txservq(struct tx_servq
*ptxservq
)
47 _init_listhead(&ptxservq
->tx_pending
);
48 _init_queue(&ptxservq
->sta_pending
);
52 void _r8712_init_sta_xmit_priv(struct sta_xmit_priv
*psta_xmitpriv
)
54 memset((unsigned char *)psta_xmitpriv
, 0,
55 sizeof(struct sta_xmit_priv
));
56 spin_lock_init(&psta_xmitpriv
->lock
);
57 _init_txservq(&psta_xmitpriv
->be_q
);
58 _init_txservq(&psta_xmitpriv
->bk_q
);
59 _init_txservq(&psta_xmitpriv
->vi_q
);
60 _init_txservq(&psta_xmitpriv
->vo_q
);
61 _init_listhead(&psta_xmitpriv
->legacy_dz
);
62 _init_listhead(&psta_xmitpriv
->apsd
);
65 sint
_r8712_init_xmit_priv(struct xmit_priv
*pxmitpriv
,
66 struct _adapter
*padapter
)
69 struct xmit_buf
*pxmitbuf
;
70 struct xmit_frame
*pxframe
;
72 memset((unsigned char *)pxmitpriv
, 0, sizeof(struct xmit_priv
));
73 spin_lock_init(&pxmitpriv
->lock
);
74 sema_init(&pxmitpriv
->xmit_sema
, 0);
75 sema_init(&pxmitpriv
->terminate_xmitthread_sema
, 0);
77 Please insert all the queue initializaiton using _init_queue below
79 pxmitpriv
->adapter
= padapter
;
80 _init_queue(&pxmitpriv
->be_pending
);
81 _init_queue(&pxmitpriv
->bk_pending
);
82 _init_queue(&pxmitpriv
->vi_pending
);
83 _init_queue(&pxmitpriv
->vo_pending
);
84 _init_queue(&pxmitpriv
->bm_pending
);
85 _init_queue(&pxmitpriv
->legacy_dz_queue
);
86 _init_queue(&pxmitpriv
->apsd_queue
);
87 _init_queue(&pxmitpriv
->free_xmit_queue
);
89 Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
90 and initialize free_xmit_frame below.
91 Please also apply free_txobj to link_up all the xmit_frames...
93 pxmitpriv
->pallocated_frame_buf
= _malloc(NR_XMITFRAME
*
94 sizeof(struct xmit_frame
) + 4);
95 if (pxmitpriv
->pallocated_frame_buf
== NULL
) {
96 pxmitpriv
->pxmit_frame_buf
= NULL
;
99 pxmitpriv
->pxmit_frame_buf
= pxmitpriv
->pallocated_frame_buf
+ 4 -
100 ((addr_t
) (pxmitpriv
->pallocated_frame_buf
) & 3);
101 pxframe
= (struct xmit_frame
*) pxmitpriv
->pxmit_frame_buf
;
102 for (i
= 0; i
< NR_XMITFRAME
; i
++) {
103 _init_listhead(&(pxframe
->list
));
104 pxframe
->padapter
= padapter
;
105 pxframe
->frame_tag
= DATA_FRAMETAG
;
107 pxframe
->buf_addr
= NULL
;
108 pxframe
->pxmitbuf
= NULL
;
109 list_insert_tail(&(pxframe
->list
),
110 &(pxmitpriv
->free_xmit_queue
.queue
));
113 pxmitpriv
->free_xmitframe_cnt
= NR_XMITFRAME
;
117 _r8712_init_hw_txqueue(&pxmitpriv
->be_txqueue
, BE_QUEUE_INX
);
118 _r8712_init_hw_txqueue(&pxmitpriv
->bk_txqueue
, BK_QUEUE_INX
);
119 _r8712_init_hw_txqueue(&pxmitpriv
->vi_txqueue
, VI_QUEUE_INX
);
120 _r8712_init_hw_txqueue(&pxmitpriv
->vo_txqueue
, VO_QUEUE_INX
);
121 _r8712_init_hw_txqueue(&pxmitpriv
->bmc_txqueue
, BMC_QUEUE_INX
);
122 pxmitpriv
->frag_len
= MAX_FRAG_THRESHOLD
;
123 pxmitpriv
->txirp_cnt
= 1;
124 sema_init(&(pxmitpriv
->tx_retevt
), 0);
125 /*per AC pending irp*/
126 pxmitpriv
->beq_cnt
= 0;
127 pxmitpriv
->bkq_cnt
= 0;
128 pxmitpriv
->viq_cnt
= 0;
129 pxmitpriv
->voq_cnt
= 0;
131 _init_queue(&pxmitpriv
->free_xmitbuf_queue
);
132 _init_queue(&pxmitpriv
->pending_xmitbuf_queue
);
133 pxmitpriv
->pallocated_xmitbuf
= _malloc(NR_XMITBUFF
*
134 sizeof(struct xmit_buf
) + 4);
135 if (pxmitpriv
->pallocated_xmitbuf
== NULL
)
137 pxmitpriv
->pxmitbuf
= pxmitpriv
->pallocated_xmitbuf
+ 4 -
138 ((addr_t
)(pxmitpriv
->pallocated_xmitbuf
) & 3);
139 pxmitbuf
= (struct xmit_buf
*)pxmitpriv
->pxmitbuf
;
140 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
141 _init_listhead(&pxmitbuf
->list
);
142 pxmitbuf
->pallocated_buf
= _malloc(MAX_XMITBUF_SZ
+
144 if (pxmitbuf
->pallocated_buf
== NULL
)
146 pxmitbuf
->pbuf
= pxmitbuf
->pallocated_buf
+ XMITBUF_ALIGN_SZ
-
147 ((addr_t
) (pxmitbuf
->pallocated_buf
) &
148 (XMITBUF_ALIGN_SZ
- 1));
149 r8712_xmit_resource_alloc(padapter
, pxmitbuf
);
150 list_insert_tail(&pxmitbuf
->list
,
151 &(pxmitpriv
->free_xmitbuf_queue
.queue
));
154 pxmitpriv
->free_xmitbuf_cnt
= NR_XMITBUFF
;
155 _init_workitem(&padapter
->wkFilterRxFF0
, r8712_SetFilter
, padapter
);
156 alloc_hwxmits(padapter
);
157 init_hwxmits(pxmitpriv
->hwxmits
, pxmitpriv
->hwxmit_entry
);
158 tasklet_init(&pxmitpriv
->xmit_tasklet
,
159 (void(*)(unsigned long))r8712_xmit_bh
,
160 (unsigned long)padapter
);
164 void _free_xmit_priv(struct xmit_priv
*pxmitpriv
)
167 struct _adapter
*padapter
= pxmitpriv
->adapter
;
168 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)
169 pxmitpriv
->pxmit_frame_buf
;
170 struct xmit_buf
*pxmitbuf
= (struct xmit_buf
*)pxmitpriv
->pxmitbuf
;
172 if (pxmitpriv
->pxmit_frame_buf
== NULL
)
174 for (i
= 0; i
< NR_XMITFRAME
; i
++) {
175 r8712_xmit_complete(padapter
, pxmitframe
);
178 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
179 r8712_xmit_resource_free(padapter
, pxmitbuf
);
180 kfree(pxmitbuf
->pallocated_buf
);
183 kfree(pxmitpriv
->pallocated_frame_buf
);
184 kfree(pxmitpriv
->pallocated_xmitbuf
);
185 free_hwxmits(padapter
);
188 sint
r8712_update_attrib(struct _adapter
*padapter
, _pkt
*pkt
,
189 struct pkt_attrib
*pattrib
)
192 struct pkt_file pktfile
;
193 struct sta_info
*psta
= NULL
;
194 struct ethhdr etherhdr
;
196 struct tx_cmd txdesc
;
199 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
200 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
201 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
202 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
204 _r8712_open_pktfile(pkt
, &pktfile
);
206 i
= _r8712_pktfile_read(&pktfile
, (unsigned char *)ðerhdr
, ETH_HLEN
);
208 pattrib
->ether_type
= ntohs(etherhdr
.h_proto
);
212 /*If driver xmit ARP packet, driver can set ps mode to initial
213 * setting. It stands for getting DHCP or fix IP.*/
214 if (pattrib
->ether_type
== 0x0806) {
215 if (padapter
->pwrctrlpriv
.pwr_mode
!=
216 padapter
->registrypriv
.power_mgnt
) {
217 _cancel_timer(&(pmlmepriv
->dhcp_timer
), &bool);
218 r8712_set_ps_mode(padapter
, padapter
->registrypriv
.
219 power_mgnt
, padapter
->registrypriv
.smart_ps
);
223 memcpy(pattrib
->dst
, ðerhdr
.h_dest
, ETH_ALEN
);
224 memcpy(pattrib
->src
, ðerhdr
.h_source
, ETH_ALEN
);
226 if ((check_fwstate(pmlmepriv
, WIFI_ADHOC_STATE
) == true) ||
227 (check_fwstate(pmlmepriv
, WIFI_ADHOC_MASTER_STATE
) == true)) {
228 memcpy(pattrib
->ra
, pattrib
->dst
, ETH_ALEN
);
229 memcpy(pattrib
->ta
, pattrib
->src
, ETH_ALEN
);
230 } else if (check_fwstate(pmlmepriv
, WIFI_STATION_STATE
)) {
231 memcpy(pattrib
->ra
, get_bssid(pmlmepriv
), ETH_ALEN
);
232 memcpy(pattrib
->ta
, pattrib
->src
, ETH_ALEN
);
233 } else if (check_fwstate(pmlmepriv
, WIFI_AP_STATE
)) {
234 memcpy(pattrib
->ra
, pattrib
->dst
, ETH_ALEN
);
235 memcpy(pattrib
->ta
, get_bssid(pmlmepriv
), ETH_ALEN
);
236 } else if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true) {
237 /*firstly, filter packet not belongs to mp*/
238 if (pattrib
->ether_type
!= 0x8712)
240 /* for mp storing the txcmd per packet,
241 * according to the info of txcmd to update pattrib */
242 /*get MP_TXDESC_SIZE bytes txcmd per packet*/
243 i
= _r8712_pktfile_read(&pktfile
, (u8
*)&txdesc
, TXDESC_SIZE
);
244 memcpy(pattrib
->ra
, pattrib
->dst
, ETH_ALEN
);
245 memcpy(pattrib
->ta
, pattrib
->src
, ETH_ALEN
);
248 /* r8712_xmitframe_coalesce() overwrite this!*/
249 pattrib
->pktlen
= pktfile
.pkt_len
;
250 if (ETH_P_IP
== pattrib
->ether_type
) {
251 /* The following is for DHCP and ARP packet, we use cck1M to
252 * tx these packets and let LPS awake some time
253 * to prevent DHCP protocol fail */
255 _r8712_pktfile_read(&pktfile
, &tmp
[0], 24);
256 pattrib
->dhcp_pkt
= 0;
257 if (pktfile
.pkt_len
> 282) {/*MINIMUM_DHCP_PACKET_SIZE)*/
258 if (ETH_P_IP
== pattrib
->ether_type
) {/* IP header*/
259 if (((tmp
[21] == 68) && (tmp
[23] == 67)) ||
260 ((tmp
[21] == 67) && (tmp
[23] == 68))) {
261 /* 68 : UDP BOOTP client
262 * 67 : UDP BOOTP server
263 * Use low rate to send DHCP packet.*/
264 pattrib
->dhcp_pkt
= 1;
269 bmcast
= IS_MCAST(pattrib
->ra
);
272 psta
= r8712_get_bcmc_stainfo(padapter
);
275 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true) {
276 psta
= r8712_get_stainfo(pstapriv
,
277 get_bssid(pmlmepriv
));
280 psta
= r8712_get_stainfo(pstapriv
, pattrib
->ra
);
281 if (psta
== NULL
) /* drop the pkt */
283 if (check_fwstate(pmlmepriv
, WIFI_STATION_STATE
))
286 pattrib
->mac_id
= psta
->mac_id
;
291 pattrib
->psta
= psta
;
293 /* if we cannot get psta => drrp the pkt */
297 pattrib
->ack_policy
= 0;
298 /* get ether_hdr_len */
299 pattrib
->pkt_hdrlen
= ETH_HLEN
;
301 if (pqospriv
->qos_option
)
302 r8712_set_qos(&pktfile
, pattrib
);
304 pattrib
->hdrlen
= WLAN_HDR_A3_LEN
;
305 pattrib
->subtype
= WIFI_DATA_TYPE
;
306 pattrib
->priority
= 0;
308 if (psta
->ieee8021x_blocked
== true) {
309 pattrib
->encrypt
= 0;
310 if ((pattrib
->ether_type
!= 0x888e) &&
311 (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == false))
314 GET_ENCRY_ALGO(psecuritypriv
, psta
, pattrib
->encrypt
, bmcast
);
315 switch (pattrib
->encrypt
) {
319 pattrib
->icv_len
= 4;
323 pattrib
->icv_len
= 4;
324 if (padapter
->securitypriv
.busetkipkey
== _FAIL
)
329 pattrib
->icv_len
= 8;
333 pattrib
->icv_len
= 0;
337 if (pattrib
->encrypt
&&
338 ((padapter
->securitypriv
.sw_encrypt
== true) ||
339 (psecuritypriv
->hw_decrypted
== false)))
340 pattrib
->bswenc
= true;
342 pattrib
->bswenc
= false;
343 /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite
344 * some settings above.*/
345 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true)
346 pattrib
->priority
= (txdesc
.txdw1
>> QSEL_SHT
) & 0x1f;
350 static sint
xmitframe_addmic(struct _adapter
*padapter
,
351 struct xmit_frame
*pxmitframe
)
353 u32 curfragnum
, length
, datalen
;
354 u8
*pframe
, *payload
, mic
[8];
355 struct mic_data micdata
;
356 struct sta_info
*stainfo
;
357 struct qos_priv
*pqospriv
= &(padapter
->mlmepriv
.qospriv
);
358 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
359 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
360 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
361 u8 priority
[4] = {0x0, 0x0, 0x0, 0x0};
362 sint bmcst
= IS_MCAST(pattrib
->ra
);
365 stainfo
= pattrib
->psta
;
367 stainfo
= r8712_get_stainfo(&padapter
->stapriv
,
369 if (pattrib
->encrypt
== _TKIP_
) {
371 if (stainfo
!= NULL
) {
372 u8 null_key
[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
373 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
375 datalen
= pattrib
->pktlen
- pattrib
->hdrlen
;
376 pframe
= pxmitframe
->buf_addr
+ TXDESC_OFFSET
;
378 if (!memcmp(psecuritypriv
->XGrptxmickey
379 [psecuritypriv
->XGrpKeyid
].skey
,
382 /*start to calculate the mic code*/
383 r8712_secmicsetkey(&micdata
,
385 XGrptxmickey
[psecuritypriv
->
388 if (!memcmp(&stainfo
->tkiptxmickey
.skey
[0],
391 /* start to calculate the mic code */
392 r8712_secmicsetkey(&micdata
,
393 &stainfo
->tkiptxmickey
.skey
[0]);
395 if (pframe
[1] & 1) { /* ToDS==1 */
396 r8712_secmicappend(&micdata
,
397 &pframe
[16], 6); /*DA*/
398 if (pframe
[1]&2) /* From Ds==1 */
399 r8712_secmicappend(&micdata
,
402 r8712_secmicappend(&micdata
,
404 } else { /* ToDS==0 */
405 r8712_secmicappend(&micdata
,
406 &pframe
[4], 6); /* DA */
407 if (pframe
[1]&2) /* From Ds==1 */
408 r8712_secmicappend(&micdata
,
411 r8712_secmicappend(&micdata
,
414 if (pqospriv
->qos_option
== 1)
415 priority
[0] = (u8
)pxmitframe
->
417 r8712_secmicappend(&micdata
, &priority
[0], 4);
419 for (curfragnum
= 0; curfragnum
< pattrib
->nr_frags
;
421 payload
= (u8
*)RND4((addr_t
)(payload
));
422 payload
= payload
+pattrib
->
423 hdrlen
+pattrib
->iv_len
;
424 if ((curfragnum
+ 1) == pattrib
->nr_frags
) {
425 length
= pattrib
->last_txcmdsz
-
428 ((psecuritypriv
->sw_encrypt
)
429 ? pattrib
->icv_len
: 0);
430 r8712_secmicappend(&micdata
, payload
,
432 payload
= payload
+length
;
434 length
= pxmitpriv
->frag_len
-
435 pattrib
->hdrlen
-pattrib
->iv_len
-
436 ((psecuritypriv
->sw_encrypt
) ?
437 pattrib
->icv_len
: 0);
438 r8712_secmicappend(&micdata
, payload
,
440 payload
= payload
+ length
+
444 r8712_secgetmic(&micdata
, &(mic
[0]));
445 /* add mic code and add the mic code length in
447 memcpy(payload
, &(mic
[0]), 8);
448 pattrib
->last_txcmdsz
+= 8;
449 payload
= payload
-pattrib
->last_txcmdsz
+ 8;
455 static sint
xmitframe_swencrypt(struct _adapter
*padapter
,
456 struct xmit_frame
*pxmitframe
)
458 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
460 if (pattrib
->bswenc
) {
461 switch (pattrib
->encrypt
) {
464 r8712_wep_encrypt(padapter
, (u8
*)pxmitframe
);
467 r8712_tkip_encrypt(padapter
, (u8
*)pxmitframe
);
470 r8712_aes_encrypt(padapter
, (u8
*)pxmitframe
);
479 static sint
make_wlanhdr(struct _adapter
*padapter
, u8
*hdr
,
480 struct pkt_attrib
*pattrib
)
484 struct ieee80211_hdr
*pwlanhdr
= (struct ieee80211_hdr
*)hdr
;
485 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
486 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
487 u16
*fctrl
= &pwlanhdr
->frame_ctl
;
488 memset(hdr
, 0, WLANHDR_OFFSET
);
489 SetFrameSubType(fctrl
, pattrib
->subtype
);
490 if (pattrib
->subtype
& WIFI_DATA_TYPE
) {
491 if ((check_fwstate(pmlmepriv
, WIFI_STATION_STATE
) == true)) {
492 /* to_ds = 1, fr_ds = 0; */
494 memcpy(pwlanhdr
->addr1
, get_bssid(pmlmepriv
),
496 memcpy(pwlanhdr
->addr2
, pattrib
->src
, ETH_ALEN
);
497 memcpy(pwlanhdr
->addr3
, pattrib
->dst
, ETH_ALEN
);
498 } else if ((check_fwstate(pmlmepriv
, WIFI_AP_STATE
) == true)) {
499 /* to_ds = 0, fr_ds = 1; */
501 memcpy(pwlanhdr
->addr1
, pattrib
->dst
, ETH_ALEN
);
502 memcpy(pwlanhdr
->addr2
, get_bssid(pmlmepriv
),
504 memcpy(pwlanhdr
->addr3
, pattrib
->src
, ETH_ALEN
);
505 } else if ((check_fwstate(pmlmepriv
, WIFI_ADHOC_STATE
) == true)
506 || (check_fwstate(pmlmepriv
, WIFI_ADHOC_MASTER_STATE
)
508 memcpy(pwlanhdr
->addr1
, pattrib
->dst
, ETH_ALEN
);
509 memcpy(pwlanhdr
->addr2
, pattrib
->src
, ETH_ALEN
);
510 memcpy(pwlanhdr
->addr3
, get_bssid(pmlmepriv
),
512 } else if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true) {
513 memcpy(pwlanhdr
->addr1
, pattrib
->dst
, ETH_ALEN
);
514 memcpy(pwlanhdr
->addr2
, pattrib
->src
, ETH_ALEN
);
515 memcpy(pwlanhdr
->addr3
, get_bssid(pmlmepriv
),
520 if (pattrib
->encrypt
)
522 if (pqospriv
->qos_option
) {
523 qc
= (unsigned short *)(hdr
+ pattrib
->hdrlen
- 2);
524 if (pattrib
->priority
)
525 SetPriority(qc
, pattrib
->priority
);
526 SetAckpolicy(qc
, pattrib
->ack_policy
);
528 /* TODO: fill HT Control Field */
529 /* Update Seq Num will be handled by f/w */
531 struct sta_info
*psta
;
533 sint bmcst
= IS_MCAST(pattrib
->ra
);
535 psta
= pattrib
->psta
;
538 psta
= r8712_get_bcmc_stainfo(padapter
);
541 r8712_get_stainfo(&padapter
->stapriv
,
545 psta
->sta_xmitpriv
.txseq_tid
546 [pattrib
->priority
]++;
547 psta
->sta_xmitpriv
.txseq_tid
[pattrib
->priority
]
549 pattrib
->seqnum
= psta
->sta_xmitpriv
.
550 txseq_tid
[pattrib
->priority
];
551 SetSeqNum(hdr
, pattrib
->seqnum
);
558 static sint
r8712_put_snap(u8
*data
, u16 h_proto
)
560 struct ieee80211_snap_hdr
*snap
;
563 snap
= (struct ieee80211_snap_hdr
*)data
;
567 if (h_proto
== 0x8137 || h_proto
== 0x80f3)
571 snap
->oui
[0] = oui
[0];
572 snap
->oui
[1] = oui
[1];
573 snap
->oui
[2] = oui
[2];
574 *(u16
*)(data
+ SNAP_SIZE
) = htons(h_proto
);
575 return SNAP_SIZE
+ sizeof(u16
);
579 * This sub-routine will perform all the following:
580 * 1. remove 802.3 header.
581 * 2. create wlan_header, based on the info in pxmitframe
582 * 3. append sta's iv/ext-iv
584 * 5. move frag chunk from pframe to pxmitframe->mem
585 * 6. apply sw-encrypt, if necessary.
587 sint
r8712_xmitframe_coalesce(struct _adapter
*padapter
, _pkt
*pkt
,
588 struct xmit_frame
*pxmitframe
)
590 struct pkt_file pktfile
;
592 sint frg_len
, mpdu_len
, llc_sz
;
596 u8
*pframe
, *mem_start
, *ptxdesc
;
597 struct sta_info
*psta
;
598 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
599 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
600 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
601 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
603 sint bmcst
= IS_MCAST(pattrib
->ra
);
605 if (pattrib
->psta
== NULL
)
607 psta
= pattrib
->psta
;
608 if (pxmitframe
->buf_addr
== NULL
)
610 pbuf_start
= pxmitframe
->buf_addr
;
611 ptxdesc
= pbuf_start
;
612 mem_start
= pbuf_start
+ TXDESC_OFFSET
;
613 if (make_wlanhdr(padapter
, mem_start
, pattrib
) == _FAIL
)
615 _r8712_open_pktfile(pkt
, &pktfile
);
616 _r8712_pktfile_read(&pktfile
, NULL
, (uint
) pattrib
->pkt_hdrlen
);
617 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true) {
618 /* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
619 if (pattrib
->ether_type
== 0x8712) {
620 /* take care - update_txdesc overwrite this */
621 _r8712_pktfile_read(&pktfile
, ptxdesc
, TXDESC_SIZE
);
624 pattrib
->pktlen
= pktfile
.pkt_len
;
626 frg_len
= pxmitpriv
->frag_len
- 4;
632 pframe
+= pattrib
->hdrlen
;
633 mpdu_len
-= pattrib
->hdrlen
;
634 /* adding icv, if necessary...*/
635 if (pattrib
->iv_len
) {
637 switch (pattrib
->encrypt
) {
640 WEP_IV(pattrib
->iv
, psta
->txpn
,
651 TKIP_IV(pattrib
->iv
, psta
->txpn
,
656 AES_IV(pattrib
->iv
, psta
->txpn
,
660 AES_IV(pattrib
->iv
, psta
->txpn
,
665 memcpy(pframe
, pattrib
->iv
, pattrib
->iv_len
);
666 pframe
+= pattrib
->iv_len
;
667 mpdu_len
-= pattrib
->iv_len
;
670 llc_sz
= r8712_put_snap(pframe
, pattrib
->ether_type
);
674 if ((pattrib
->icv_len
> 0) && (pattrib
->bswenc
))
675 mpdu_len
-= pattrib
->icv_len
;
677 mem_sz
= _r8712_pktfile_read(&pktfile
, pframe
,
680 mem_sz
= _r8712_pktfile_read(&pktfile
, pframe
,
683 if ((pattrib
->icv_len
> 0) && (pattrib
->bswenc
)) {
684 memcpy(pframe
, pattrib
->icv
, pattrib
->icv_len
);
685 pframe
+= pattrib
->icv_len
;
688 if (bmcst
|| (r8712_endofpktfile(&pktfile
) == true)) {
689 pattrib
->nr_frags
= frg_inx
;
690 pattrib
->last_txcmdsz
= pattrib
->hdrlen
+
692 ((pattrib
->nr_frags
== 1) ?
695 pattrib
->icv_len
: 0) + mem_sz
;
696 ClearMFrag(mem_start
);
699 addr
= (addr_t
)(pframe
);
700 mem_start
= (unsigned char *)RND4(addr
) + TXDESC_OFFSET
;
701 memcpy(mem_start
, pbuf_start
+ TXDESC_OFFSET
, pattrib
->hdrlen
);
704 if (xmitframe_addmic(padapter
, pxmitframe
) == _FAIL
)
706 xmitframe_swencrypt(padapter
, pxmitframe
);
710 void r8712_update_protection(struct _adapter
*padapter
, u8
*ie
, uint ie_len
)
715 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
716 struct registry_priv
*pregistrypriv
= &padapter
->registrypriv
;
718 switch (pxmitpriv
->vcs_setting
) {
720 pxmitpriv
->vcs
= NONE_VCS
;
726 perp
= r8712_get_ie(ie
, _ERPINFO_IE_
, &erp_len
, ie_len
);
728 pxmitpriv
->vcs
= NONE_VCS
;
730 protection
= (*(perp
+ 2)) & BIT(1);
732 if (pregistrypriv
->vcs_type
== RTS_CTS
)
733 pxmitpriv
->vcs
= RTS_CTS
;
735 pxmitpriv
->vcs
= CTS_TO_SELF
;
737 pxmitpriv
->vcs
= NONE_VCS
;
743 struct xmit_buf
*r8712_alloc_xmitbuf(struct xmit_priv
*pxmitpriv
)
746 struct xmit_buf
*pxmitbuf
= NULL
;
747 struct list_head
*plist
, *phead
;
748 struct __queue
*pfree_xmitbuf_queue
= &pxmitpriv
->free_xmitbuf_queue
;
750 spin_lock_irqsave(&pfree_xmitbuf_queue
->lock
, irqL
);
751 if (_queue_empty(pfree_xmitbuf_queue
) == true)
754 phead
= get_list_head(pfree_xmitbuf_queue
);
755 plist
= get_next(phead
);
756 pxmitbuf
= LIST_CONTAINOR(plist
, struct xmit_buf
, list
);
757 list_delete(&(pxmitbuf
->list
));
759 if (pxmitbuf
!= NULL
)
760 pxmitpriv
->free_xmitbuf_cnt
--;
761 spin_unlock_irqrestore(&pfree_xmitbuf_queue
->lock
, irqL
);
765 int r8712_free_xmitbuf(struct xmit_priv
*pxmitpriv
, struct xmit_buf
*pxmitbuf
)
768 struct __queue
*pfree_xmitbuf_queue
= &pxmitpriv
->free_xmitbuf_queue
;
770 if (pxmitbuf
== NULL
)
772 spin_lock_irqsave(&pfree_xmitbuf_queue
->lock
, irqL
);
773 list_delete(&pxmitbuf
->list
);
774 list_insert_tail(&(pxmitbuf
->list
), get_list_head(pfree_xmitbuf_queue
));
775 pxmitpriv
->free_xmitbuf_cnt
++;
776 spin_unlock_irqrestore(&pfree_xmitbuf_queue
->lock
, irqL
);
783 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
785 If we turn on USE_RXTHREAD, then, no need for critical section.
786 Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
788 Must be very very cautious...
792 struct xmit_frame
*r8712_alloc_xmitframe(struct xmit_priv
*pxmitpriv
)
795 Please remember to use all the osdep_service api,
796 and lock/unlock or _enter/_exit critical to protect
800 struct xmit_frame
*pxframe
= NULL
;
801 struct list_head
*plist
, *phead
;
802 struct __queue
*pfree_xmit_queue
= &pxmitpriv
->free_xmit_queue
;
804 spin_lock_irqsave(&pfree_xmit_queue
->lock
, irqL
);
805 if (_queue_empty(pfree_xmit_queue
) == true)
808 phead
= get_list_head(pfree_xmit_queue
);
809 plist
= get_next(phead
);
810 pxframe
= LIST_CONTAINOR(plist
, struct xmit_frame
, list
);
811 list_delete(&(pxframe
->list
));
813 if (pxframe
!= NULL
) {
814 pxmitpriv
->free_xmitframe_cnt
--;
815 pxframe
->buf_addr
= NULL
;
816 pxframe
->pxmitbuf
= NULL
;
817 pxframe
->attrib
.psta
= NULL
;
820 spin_unlock_irqrestore(&pfree_xmit_queue
->lock
, irqL
);
824 void r8712_free_xmitframe(struct xmit_priv
*pxmitpriv
,
825 struct xmit_frame
*pxmitframe
)
828 struct __queue
*pfree_xmit_queue
= &pxmitpriv
->free_xmit_queue
;
829 struct _adapter
*padapter
= pxmitpriv
->adapter
;
830 struct sk_buff
*pndis_pkt
= NULL
;
832 if (pxmitframe
== NULL
)
834 spin_lock_irqsave(&pfree_xmit_queue
->lock
, irqL
);
835 list_delete(&pxmitframe
->list
);
836 if (pxmitframe
->pkt
) {
837 pndis_pkt
= pxmitframe
->pkt
;
838 pxmitframe
->pkt
= NULL
;
840 list_insert_tail(&pxmitframe
->list
, get_list_head(pfree_xmit_queue
));
841 pxmitpriv
->free_xmitframe_cnt
++;
842 spin_unlock_irqrestore(&pfree_xmit_queue
->lock
, irqL
);
843 if (netif_queue_stopped(padapter
->pnetdev
))
844 netif_wake_queue(padapter
->pnetdev
);
847 void r8712_free_xmitframe_ex(struct xmit_priv
*pxmitpriv
,
848 struct xmit_frame
*pxmitframe
)
850 if (pxmitframe
== NULL
)
852 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
)
853 r8712_free_xmitframe(pxmitpriv
, pxmitframe
);
856 void r8712_free_xmitframe_queue(struct xmit_priv
*pxmitpriv
,
857 struct __queue
*pframequeue
)
860 struct list_head
*plist
, *phead
;
861 struct xmit_frame
*pxmitframe
;
863 spin_lock_irqsave(&(pframequeue
->lock
), irqL
);
864 phead
= get_list_head(pframequeue
);
865 plist
= get_next(phead
);
866 while (end_of_queue_search(phead
, plist
) == false) {
867 pxmitframe
= LIST_CONTAINOR(plist
, struct xmit_frame
, list
);
868 plist
= get_next(plist
);
869 r8712_free_xmitframe(pxmitpriv
, pxmitframe
);
871 spin_unlock_irqrestore(&(pframequeue
->lock
), irqL
);
874 static inline struct tx_servq
*get_sta_pending(struct _adapter
*padapter
,
875 struct __queue
**ppstapending
,
876 struct sta_info
*psta
, sint up
)
879 struct tx_servq
*ptxservq
;
880 struct hw_xmit
*phwxmits
= padapter
->xmitpriv
.hwxmits
;
885 ptxservq
= &(psta
->sta_xmitpriv
.bk_q
);
886 *ppstapending
= &padapter
->xmitpriv
.bk_pending
;
887 (phwxmits
+3)->accnt
++;
891 ptxservq
= &(psta
->sta_xmitpriv
.vi_q
);
892 *ppstapending
= &padapter
->xmitpriv
.vi_pending
;
893 (phwxmits
+1)->accnt
++;
897 ptxservq
= &(psta
->sta_xmitpriv
.vo_q
);
898 *ppstapending
= &padapter
->xmitpriv
.vo_pending
;
899 (phwxmits
+0)->accnt
++;
904 ptxservq
= &(psta
->sta_xmitpriv
.be_q
);
905 *ppstapending
= &padapter
->xmitpriv
.be_pending
;
906 (phwxmits
+ 2)->accnt
++;
913 * Will enqueue pxmitframe to the proper queue, and indicate it
914 * to xx_pending list.....
916 sint
r8712_xmit_classifier(struct _adapter
*padapter
,
917 struct xmit_frame
*pxmitframe
)
920 struct __queue
*pstapending
;
921 struct sta_info
*psta
;
922 struct tx_servq
*ptxservq
;
923 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
924 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
925 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
926 sint bmcst
= IS_MCAST(pattrib
->ra
);
929 psta
= pattrib
->psta
;
932 psta
= r8712_get_bcmc_stainfo(padapter
);
934 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true)
935 psta
= r8712_get_stainfo(pstapriv
,
936 get_bssid(pmlmepriv
));
938 psta
= r8712_get_stainfo(pstapriv
, pattrib
->ra
);
943 ptxservq
= get_sta_pending(padapter
, &pstapending
,
944 psta
, pattrib
->priority
);
945 spin_lock_irqsave(&pstapending
->lock
, irqL0
);
946 if (is_list_empty(&ptxservq
->tx_pending
))
947 list_insert_tail(&ptxservq
->tx_pending
,
948 get_list_head(pstapending
));
949 list_insert_tail(&pxmitframe
->list
,
950 get_list_head(&ptxservq
->sta_pending
));
952 spin_unlock_irqrestore(&pstapending
->lock
, irqL0
);
956 static void alloc_hwxmits(struct _adapter
*padapter
)
958 struct hw_xmit
*hwxmits
;
959 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
961 pxmitpriv
->hwxmit_entry
= HWXMIT_ENTRY
;
962 pxmitpriv
->hwxmits
= (struct hw_xmit
*)_malloc(sizeof(struct hw_xmit
) *
963 pxmitpriv
->hwxmit_entry
);
964 if (pxmitpriv
->hwxmits
== NULL
)
966 hwxmits
= pxmitpriv
->hwxmits
;
967 if (pxmitpriv
->hwxmit_entry
== 5) {
968 pxmitpriv
->bmc_txqueue
.head
= 0;
969 hwxmits
[0] .phwtxqueue
= &pxmitpriv
->bmc_txqueue
;
970 hwxmits
[0] .sta_queue
= &pxmitpriv
->bm_pending
;
971 pxmitpriv
->vo_txqueue
.head
= 0;
972 hwxmits
[1] .phwtxqueue
= &pxmitpriv
->vo_txqueue
;
973 hwxmits
[1] .sta_queue
= &pxmitpriv
->vo_pending
;
974 pxmitpriv
->vi_txqueue
.head
= 0;
975 hwxmits
[2] .phwtxqueue
= &pxmitpriv
->vi_txqueue
;
976 hwxmits
[2] .sta_queue
= &pxmitpriv
->vi_pending
;
977 pxmitpriv
->bk_txqueue
.head
= 0;
978 hwxmits
[3] .phwtxqueue
= &pxmitpriv
->bk_txqueue
;
979 hwxmits
[3] .sta_queue
= &pxmitpriv
->bk_pending
;
980 pxmitpriv
->be_txqueue
.head
= 0;
981 hwxmits
[4] .phwtxqueue
= &pxmitpriv
->be_txqueue
;
982 hwxmits
[4] .sta_queue
= &pxmitpriv
->be_pending
;
983 } else if (pxmitpriv
->hwxmit_entry
== 4) {
984 pxmitpriv
->vo_txqueue
.head
= 0;
985 hwxmits
[0] .phwtxqueue
= &pxmitpriv
->vo_txqueue
;
986 hwxmits
[0] .sta_queue
= &pxmitpriv
->vo_pending
;
987 pxmitpriv
->vi_txqueue
.head
= 0;
988 hwxmits
[1] .phwtxqueue
= &pxmitpriv
->vi_txqueue
;
989 hwxmits
[1] .sta_queue
= &pxmitpriv
->vi_pending
;
990 pxmitpriv
->be_txqueue
.head
= 0;
991 hwxmits
[2] .phwtxqueue
= &pxmitpriv
->be_txqueue
;
992 hwxmits
[2] .sta_queue
= &pxmitpriv
->be_pending
;
993 pxmitpriv
->bk_txqueue
.head
= 0;
994 hwxmits
[3] .phwtxqueue
= &pxmitpriv
->bk_txqueue
;
995 hwxmits
[3] .sta_queue
= &pxmitpriv
->bk_pending
;
999 static void free_hwxmits(struct _adapter
*padapter
)
1001 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
1003 kfree(pxmitpriv
->hwxmits
);
1006 static void init_hwxmits(struct hw_xmit
*phwxmit
, sint entry
)
1010 for (i
= 0; i
< entry
; i
++, phwxmit
++) {
1011 spin_lock_init(&phwxmit
->xmit_lock
);
1012 _init_listhead(&phwxmit
->pending
);
1013 phwxmit
->txcmdcnt
= 0;
1018 void xmitframe_xmitbuf_attach(struct xmit_frame
*pxmitframe
,
1019 struct xmit_buf
*pxmitbuf
)
1021 /* pxmitbuf attach to pxmitframe */
1022 pxmitframe
->pxmitbuf
= pxmitbuf
;
1023 /* urb and irp connection */
1024 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
1025 /* buffer addr assoc */
1026 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
;
1027 /* pxmitframe attach to pxmitbuf */
1028 pxmitbuf
->priv_data
= pxmitframe
;
1032 * tx_action == 0 == no frames to transmit
1033 * tx_action > 0 ==> we have frames to transmit
1034 * tx_action < 0 ==> we have frames to transmit, but TXFF is not even enough
1035 * to transmit 1 frame.
1038 int r8712_pre_xmit(struct _adapter
*padapter
, struct xmit_frame
*pxmitframe
)
1042 struct xmit_buf
*pxmitbuf
= NULL
;
1043 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
1044 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
1046 r8712_do_queue_select(padapter
, pattrib
);
1047 spin_lock_irqsave(&pxmitpriv
->lock
, irqL
);
1048 if (r8712_txframes_sta_ac_pending(padapter
, pattrib
) > 0) {
1050 r8712_xmit_enqueue(padapter
, pxmitframe
);
1051 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
1054 pxmitbuf
= r8712_alloc_xmitbuf(pxmitpriv
);
1055 if (pxmitbuf
== NULL
) { /*enqueue packet*/
1057 r8712_xmit_enqueue(padapter
, pxmitframe
);
1058 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
1059 } else { /*dump packet directly*/
1060 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
1062 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
1063 r8712_xmit_direct(padapter
, pxmitframe
);