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"
34 #include "osdep_intf.h"
38 static const u8 P802_1H_OUI
[P80211_OUI_LEN
] = {0x00, 0x00, 0xf8};
39 static const u8 RFC1042_OUI
[P80211_OUI_LEN
] = {0x00, 0x00, 0x00};
40 static void init_hwxmits(struct hw_xmit
*phwxmit
, sint entry
);
41 static void alloc_hwxmits(struct _adapter
*padapter
);
42 static void free_hwxmits(struct _adapter
*padapter
);
44 static void _init_txservq(struct tx_servq
*ptxservq
)
46 INIT_LIST_HEAD(&ptxservq
->tx_pending
);
47 _init_queue(&ptxservq
->sta_pending
);
51 void _r8712_init_sta_xmit_priv(struct sta_xmit_priv
*psta_xmitpriv
)
53 memset((unsigned char *)psta_xmitpriv
, 0,
54 sizeof(struct sta_xmit_priv
));
55 spin_lock_init(&psta_xmitpriv
->lock
);
56 _init_txservq(&psta_xmitpriv
->be_q
);
57 _init_txservq(&psta_xmitpriv
->bk_q
);
58 _init_txservq(&psta_xmitpriv
->vi_q
);
59 _init_txservq(&psta_xmitpriv
->vo_q
);
60 INIT_LIST_HEAD(&psta_xmitpriv
->legacy_dz
);
61 INIT_LIST_HEAD(&psta_xmitpriv
->apsd
);
64 sint
_r8712_init_xmit_priv(struct xmit_priv
*pxmitpriv
,
65 struct _adapter
*padapter
)
68 struct xmit_buf
*pxmitbuf
;
69 struct xmit_frame
*pxframe
;
71 memset((unsigned char *)pxmitpriv
, 0, sizeof(struct xmit_priv
));
72 spin_lock_init(&pxmitpriv
->lock
);
74 Please insert all the queue initialization using _init_queue below
76 pxmitpriv
->adapter
= padapter
;
77 _init_queue(&pxmitpriv
->be_pending
);
78 _init_queue(&pxmitpriv
->bk_pending
);
79 _init_queue(&pxmitpriv
->vi_pending
);
80 _init_queue(&pxmitpriv
->vo_pending
);
81 _init_queue(&pxmitpriv
->bm_pending
);
82 _init_queue(&pxmitpriv
->legacy_dz_queue
);
83 _init_queue(&pxmitpriv
->apsd_queue
);
84 _init_queue(&pxmitpriv
->free_xmit_queue
);
86 Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
87 and initialize free_xmit_frame below.
88 Please also apply free_txobj to link_up all the xmit_frames...
90 pxmitpriv
->pallocated_frame_buf
= kmalloc(NR_XMITFRAME
* sizeof(struct xmit_frame
) + 4,
92 if (!pxmitpriv
->pallocated_frame_buf
) {
93 pxmitpriv
->pxmit_frame_buf
= NULL
;
96 pxmitpriv
->pxmit_frame_buf
= pxmitpriv
->pallocated_frame_buf
+ 4 -
97 ((addr_t
) (pxmitpriv
->pallocated_frame_buf
) & 3);
98 pxframe
= (struct xmit_frame
*) pxmitpriv
->pxmit_frame_buf
;
99 for (i
= 0; i
< NR_XMITFRAME
; i
++) {
100 INIT_LIST_HEAD(&(pxframe
->list
));
101 pxframe
->padapter
= padapter
;
102 pxframe
->frame_tag
= DATA_FRAMETAG
;
104 pxframe
->buf_addr
= NULL
;
105 pxframe
->pxmitbuf
= NULL
;
106 list_add_tail(&(pxframe
->list
),
107 &(pxmitpriv
->free_xmit_queue
.queue
));
110 pxmitpriv
->free_xmitframe_cnt
= NR_XMITFRAME
;
114 _r8712_init_hw_txqueue(&pxmitpriv
->be_txqueue
, BE_QUEUE_INX
);
115 _r8712_init_hw_txqueue(&pxmitpriv
->bk_txqueue
, BK_QUEUE_INX
);
116 _r8712_init_hw_txqueue(&pxmitpriv
->vi_txqueue
, VI_QUEUE_INX
);
117 _r8712_init_hw_txqueue(&pxmitpriv
->vo_txqueue
, VO_QUEUE_INX
);
118 _r8712_init_hw_txqueue(&pxmitpriv
->bmc_txqueue
, BMC_QUEUE_INX
);
119 pxmitpriv
->frag_len
= MAX_FRAG_THRESHOLD
;
120 pxmitpriv
->txirp_cnt
= 1;
121 /*per AC pending irp*/
122 pxmitpriv
->beq_cnt
= 0;
123 pxmitpriv
->bkq_cnt
= 0;
124 pxmitpriv
->viq_cnt
= 0;
125 pxmitpriv
->voq_cnt
= 0;
127 _init_queue(&pxmitpriv
->free_xmitbuf_queue
);
128 _init_queue(&pxmitpriv
->pending_xmitbuf_queue
);
129 pxmitpriv
->pallocated_xmitbuf
= kmalloc(NR_XMITBUFF
* sizeof(struct xmit_buf
) + 4,
131 if (!pxmitpriv
->pallocated_xmitbuf
)
133 pxmitpriv
->pxmitbuf
= pxmitpriv
->pallocated_xmitbuf
+ 4 -
134 ((addr_t
)(pxmitpriv
->pallocated_xmitbuf
) & 3);
135 pxmitbuf
= (struct xmit_buf
*)pxmitpriv
->pxmitbuf
;
136 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
137 INIT_LIST_HEAD(&pxmitbuf
->list
);
138 pxmitbuf
->pallocated_buf
= kmalloc(MAX_XMITBUF_SZ
+ XMITBUF_ALIGN_SZ
,
140 if (!pxmitbuf
->pallocated_buf
)
142 pxmitbuf
->pbuf
= pxmitbuf
->pallocated_buf
+ XMITBUF_ALIGN_SZ
-
143 ((addr_t
) (pxmitbuf
->pallocated_buf
) &
144 (XMITBUF_ALIGN_SZ
- 1));
145 r8712_xmit_resource_alloc(padapter
, pxmitbuf
);
146 list_add_tail(&pxmitbuf
->list
,
147 &(pxmitpriv
->free_xmitbuf_queue
.queue
));
150 pxmitpriv
->free_xmitbuf_cnt
= NR_XMITBUFF
;
151 INIT_WORK(&padapter
->wkFilterRxFF0
, r8712_SetFilter
);
152 alloc_hwxmits(padapter
);
153 init_hwxmits(pxmitpriv
->hwxmits
, pxmitpriv
->hwxmit_entry
);
154 tasklet_init(&pxmitpriv
->xmit_tasklet
,
155 (void(*)(unsigned long))r8712_xmit_bh
,
156 (unsigned long)padapter
);
160 void _free_xmit_priv(struct xmit_priv
*pxmitpriv
)
163 struct _adapter
*padapter
= pxmitpriv
->adapter
;
164 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)
165 pxmitpriv
->pxmit_frame_buf
;
166 struct xmit_buf
*pxmitbuf
= (struct xmit_buf
*)pxmitpriv
->pxmitbuf
;
168 if (pxmitpriv
->pxmit_frame_buf
== NULL
)
170 for (i
= 0; i
< NR_XMITFRAME
; i
++) {
171 r8712_xmit_complete(padapter
, pxmitframe
);
174 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
175 r8712_xmit_resource_free(padapter
, pxmitbuf
);
176 kfree(pxmitbuf
->pallocated_buf
);
179 kfree(pxmitpriv
->pallocated_frame_buf
);
180 kfree(pxmitpriv
->pallocated_xmitbuf
);
181 free_hwxmits(padapter
);
184 sint
r8712_update_attrib(struct _adapter
*padapter
, _pkt
*pkt
,
185 struct pkt_attrib
*pattrib
)
187 struct pkt_file pktfile
;
188 struct sta_info
*psta
= NULL
;
189 struct ethhdr etherhdr
;
191 struct tx_cmd txdesc
;
194 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
195 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
196 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
197 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
199 _r8712_open_pktfile(pkt
, &pktfile
);
201 _r8712_pktfile_read(&pktfile
, (unsigned char *)ðerhdr
, ETH_HLEN
);
203 pattrib
->ether_type
= ntohs(etherhdr
.h_proto
);
206 /*If driver xmit ARP packet, driver can set ps mode to initial
207 * setting. It stands for getting DHCP or fix IP.*/
208 if (pattrib
->ether_type
== 0x0806) {
209 if (padapter
->pwrctrlpriv
.pwr_mode
!=
210 padapter
->registrypriv
.power_mgnt
) {
211 del_timer_sync(&pmlmepriv
->dhcp_timer
);
212 r8712_set_ps_mode(padapter
, padapter
->registrypriv
.
213 power_mgnt
, padapter
->registrypriv
.smart_ps
);
217 memcpy(pattrib
->dst
, ðerhdr
.h_dest
, ETH_ALEN
);
218 memcpy(pattrib
->src
, ðerhdr
.h_source
, ETH_ALEN
);
220 if (check_fwstate(pmlmepriv
, WIFI_ADHOC_STATE
) ||
221 check_fwstate(pmlmepriv
, WIFI_ADHOC_MASTER_STATE
)) {
222 memcpy(pattrib
->ra
, pattrib
->dst
, ETH_ALEN
);
223 memcpy(pattrib
->ta
, pattrib
->src
, ETH_ALEN
);
224 } else if (check_fwstate(pmlmepriv
, WIFI_STATION_STATE
)) {
225 memcpy(pattrib
->ra
, get_bssid(pmlmepriv
), ETH_ALEN
);
226 memcpy(pattrib
->ta
, pattrib
->src
, ETH_ALEN
);
227 } else if (check_fwstate(pmlmepriv
, WIFI_AP_STATE
)) {
228 memcpy(pattrib
->ra
, pattrib
->dst
, ETH_ALEN
);
229 memcpy(pattrib
->ta
, get_bssid(pmlmepriv
), ETH_ALEN
);
230 } else if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
)) {
231 /*firstly, filter packet not belongs to mp*/
232 if (pattrib
->ether_type
!= 0x8712)
234 /* for mp storing the txcmd per packet,
235 * according to the info of txcmd to update pattrib */
236 /*get MP_TXDESC_SIZE bytes txcmd per packet*/
237 _r8712_pktfile_read(&pktfile
, (u8
*)&txdesc
, TXDESC_SIZE
);
238 memcpy(pattrib
->ra
, pattrib
->dst
, ETH_ALEN
);
239 memcpy(pattrib
->ta
, pattrib
->src
, ETH_ALEN
);
242 /* r8712_xmitframe_coalesce() overwrite this!*/
243 pattrib
->pktlen
= pktfile
.pkt_len
;
244 if (pattrib
->ether_type
== ETH_P_IP
) {
245 /* The following is for DHCP and ARP packet, we use cck1M to
246 * tx these packets and let LPS awake some time
247 * to prevent DHCP protocol fail */
250 _r8712_pktfile_read(&pktfile
, &tmp
[0], 24);
251 pattrib
->dhcp_pkt
= 0;
252 if (pktfile
.pkt_len
> 282) {/*MINIMUM_DHCP_PACKET_SIZE)*/
253 if (pattrib
->ether_type
== ETH_P_IP
) {/* IP header*/
254 if (((tmp
[21] == 68) && (tmp
[23] == 67)) ||
255 ((tmp
[21] == 67) && (tmp
[23] == 68))) {
256 /* 68 : UDP BOOTP client
257 * 67 : UDP BOOTP server
258 * Use low rate to send DHCP packet.*/
259 pattrib
->dhcp_pkt
= 1;
264 bmcast
= IS_MCAST(pattrib
->ra
);
267 psta
= r8712_get_bcmc_stainfo(padapter
);
270 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
)) {
271 psta
= r8712_get_stainfo(pstapriv
,
272 get_bssid(pmlmepriv
));
275 psta
= r8712_get_stainfo(pstapriv
, pattrib
->ra
);
276 if (psta
== NULL
) /* drop the pkt */
278 if (check_fwstate(pmlmepriv
, WIFI_STATION_STATE
))
281 pattrib
->mac_id
= psta
->mac_id
;
286 pattrib
->psta
= psta
;
288 /* if we cannot get psta => drrp the pkt */
292 pattrib
->ack_policy
= 0;
293 /* get ether_hdr_len */
294 pattrib
->pkt_hdrlen
= ETH_HLEN
;
296 if (pqospriv
->qos_option
) {
297 r8712_set_qos(&pktfile
, pattrib
);
299 pattrib
->hdrlen
= WLAN_HDR_A3_LEN
;
300 pattrib
->subtype
= WIFI_DATA_TYPE
;
301 pattrib
->priority
= 0;
303 if (psta
->ieee8021x_blocked
) {
304 pattrib
->encrypt
= 0;
305 if ((pattrib
->ether_type
!= 0x888e) &&
306 !check_fwstate(pmlmepriv
, WIFI_MP_STATE
))
309 GET_ENCRY_ALGO(psecuritypriv
, psta
, pattrib
->encrypt
, bmcast
);
311 switch (pattrib
->encrypt
) {
315 pattrib
->icv_len
= 4;
319 pattrib
->icv_len
= 4;
320 if (padapter
->securitypriv
.busetkipkey
== _FAIL
)
325 pattrib
->icv_len
= 8;
329 pattrib
->icv_len
= 0;
333 if (pattrib
->encrypt
&&
334 (padapter
->securitypriv
.sw_encrypt
||
335 !psecuritypriv
->hw_decrypted
))
336 pattrib
->bswenc
= true;
338 pattrib
->bswenc
= false;
339 /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite
340 * some settings above.*/
341 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
))
342 pattrib
->priority
= (txdesc
.txdw1
>> QSEL_SHT
) & 0x1f;
346 static sint
xmitframe_addmic(struct _adapter
*padapter
,
347 struct xmit_frame
*pxmitframe
)
349 u32 curfragnum
, length
;
350 u8
*pframe
, *payload
, mic
[8];
351 struct mic_data micdata
;
352 struct sta_info
*stainfo
;
353 struct qos_priv
*pqospriv
= &(padapter
->mlmepriv
.qospriv
);
354 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
355 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
356 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
357 u8 priority
[4] = {0x0, 0x0, 0x0, 0x0};
358 sint bmcst
= IS_MCAST(pattrib
->ra
);
361 stainfo
= pattrib
->psta
;
363 stainfo
= r8712_get_stainfo(&padapter
->stapriv
,
365 if (pattrib
->encrypt
== _TKIP_
) {
367 if (stainfo
!= NULL
) {
368 u8 null_key
[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
369 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
371 pframe
= pxmitframe
->buf_addr
+ TXDESC_OFFSET
;
373 if (!memcmp(psecuritypriv
->XGrptxmickey
374 [psecuritypriv
->XGrpKeyid
].skey
,
377 /*start to calculate the mic code*/
378 r8712_secmicsetkey(&micdata
,
380 XGrptxmickey
[psecuritypriv
->
383 if (!memcmp(&stainfo
->tkiptxmickey
.skey
[0],
386 /* start to calculate the mic code */
387 r8712_secmicsetkey(&micdata
,
388 &stainfo
->tkiptxmickey
.skey
[0]);
390 if (pframe
[1] & 1) { /* ToDS==1 */
391 r8712_secmicappend(&micdata
,
392 &pframe
[16], 6); /*DA*/
393 if (pframe
[1] & 2) /* From Ds==1 */
394 r8712_secmicappend(&micdata
,
397 r8712_secmicappend(&micdata
,
399 } else { /* ToDS==0 */
400 r8712_secmicappend(&micdata
,
401 &pframe
[4], 6); /* DA */
402 if (pframe
[1] & 2) /* From Ds==1 */
403 r8712_secmicappend(&micdata
,
406 r8712_secmicappend(&micdata
,
409 if (pqospriv
->qos_option
== 1)
410 priority
[0] = (u8
)pxmitframe
->
412 r8712_secmicappend(&micdata
, &priority
[0], 4);
414 for (curfragnum
= 0; curfragnum
< pattrib
->nr_frags
;
416 payload
= (u8
*)RND4((addr_t
)(payload
));
417 payload
= payload
+ pattrib
->
418 hdrlen
+ pattrib
->iv_len
;
419 if ((curfragnum
+ 1) == pattrib
->nr_frags
) {
420 length
= pattrib
->last_txcmdsz
-
423 ((psecuritypriv
->sw_encrypt
)
424 ? pattrib
->icv_len
: 0);
425 r8712_secmicappend(&micdata
, payload
,
427 payload
= payload
+ length
;
429 length
= pxmitpriv
->frag_len
-
430 pattrib
->hdrlen
- pattrib
->iv_len
-
431 ((psecuritypriv
->sw_encrypt
) ?
432 pattrib
->icv_len
: 0);
433 r8712_secmicappend(&micdata
, payload
,
435 payload
= payload
+ length
+
439 r8712_secgetmic(&micdata
, &(mic
[0]));
440 /* add mic code and add the mic code length in
442 memcpy(payload
, &(mic
[0]), 8);
443 pattrib
->last_txcmdsz
+= 8;
444 payload
= payload
- pattrib
->last_txcmdsz
+ 8;
450 static sint
xmitframe_swencrypt(struct _adapter
*padapter
,
451 struct xmit_frame
*pxmitframe
)
453 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
455 if (pattrib
->bswenc
) {
456 switch (pattrib
->encrypt
) {
459 r8712_wep_encrypt(padapter
, (u8
*)pxmitframe
);
462 r8712_tkip_encrypt(padapter
, (u8
*)pxmitframe
);
465 r8712_aes_encrypt(padapter
, (u8
*)pxmitframe
);
474 static sint
make_wlanhdr(struct _adapter
*padapter
, u8
*hdr
,
475 struct pkt_attrib
*pattrib
)
479 struct ieee80211_hdr
*pwlanhdr
= (struct ieee80211_hdr
*)hdr
;
480 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
481 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
482 u16
*fctrl
= &pwlanhdr
->frame_ctl
;
484 memset(hdr
, 0, WLANHDR_OFFSET
);
485 SetFrameSubType(fctrl
, pattrib
->subtype
);
486 if (pattrib
->subtype
& WIFI_DATA_TYPE
) {
487 if (check_fwstate(pmlmepriv
, WIFI_STATION_STATE
)) {
488 /* to_ds = 1, fr_ds = 0; */
490 memcpy(pwlanhdr
->addr1
, get_bssid(pmlmepriv
),
492 memcpy(pwlanhdr
->addr2
, pattrib
->src
, ETH_ALEN
);
493 memcpy(pwlanhdr
->addr3
, pattrib
->dst
, ETH_ALEN
);
494 } else if (check_fwstate(pmlmepriv
, WIFI_AP_STATE
)) {
495 /* to_ds = 0, fr_ds = 1; */
497 memcpy(pwlanhdr
->addr1
, pattrib
->dst
, ETH_ALEN
);
498 memcpy(pwlanhdr
->addr2
, get_bssid(pmlmepriv
),
500 memcpy(pwlanhdr
->addr3
, pattrib
->src
, ETH_ALEN
);
501 } else if (check_fwstate(pmlmepriv
, WIFI_ADHOC_STATE
) ||
502 check_fwstate(pmlmepriv
,
503 WIFI_ADHOC_MASTER_STATE
)) {
504 memcpy(pwlanhdr
->addr1
, pattrib
->dst
, ETH_ALEN
);
505 memcpy(pwlanhdr
->addr2
, pattrib
->src
, ETH_ALEN
);
506 memcpy(pwlanhdr
->addr3
, get_bssid(pmlmepriv
),
508 } else if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
)) {
509 memcpy(pwlanhdr
->addr1
, pattrib
->dst
, ETH_ALEN
);
510 memcpy(pwlanhdr
->addr2
, pattrib
->src
, ETH_ALEN
);
511 memcpy(pwlanhdr
->addr3
, get_bssid(pmlmepriv
),
517 if (pattrib
->encrypt
)
519 if (pqospriv
->qos_option
) {
520 qc
= (unsigned short *)(hdr
+ pattrib
->hdrlen
- 2);
521 if (pattrib
->priority
)
522 SetPriority(qc
, pattrib
->priority
);
523 SetAckpolicy(qc
, pattrib
->ack_policy
);
525 /* TODO: fill HT Control Field */
526 /* Update Seq Num will be handled by f/w */
528 struct sta_info
*psta
;
529 sint bmcst
= IS_MCAST(pattrib
->ra
);
532 psta
= pattrib
->psta
;
535 psta
= r8712_get_bcmc_stainfo(padapter
);
538 r8712_get_stainfo(&padapter
->stapriv
,
542 psta
->sta_xmitpriv
.txseq_tid
543 [pattrib
->priority
]++;
544 psta
->sta_xmitpriv
.txseq_tid
[pattrib
->priority
]
546 pattrib
->seqnum
= psta
->sta_xmitpriv
.
547 txseq_tid
[pattrib
->priority
];
548 SetSeqNum(hdr
, pattrib
->seqnum
);
555 static sint
r8712_put_snap(u8
*data
, u16 h_proto
)
557 struct ieee80211_snap_hdr
*snap
;
560 snap
= (struct ieee80211_snap_hdr
*)data
;
564 if (h_proto
== 0x8137 || h_proto
== 0x80f3)
568 snap
->oui
[0] = oui
[0];
569 snap
->oui
[1] = oui
[1];
570 snap
->oui
[2] = oui
[2];
571 *(u16
*)(data
+ SNAP_SIZE
) = htons(h_proto
);
572 return SNAP_SIZE
+ sizeof(u16
);
576 * This sub-routine will perform all the following:
577 * 1. remove 802.3 header.
578 * 2. create wlan_header, based on the info in pxmitframe
579 * 3. append sta's iv/ext-iv
581 * 5. move frag chunk from pframe to pxmitframe->mem
582 * 6. apply sw-encrypt, if necessary.
584 sint
r8712_xmitframe_coalesce(struct _adapter
*padapter
, _pkt
*pkt
,
585 struct xmit_frame
*pxmitframe
)
587 struct pkt_file pktfile
;
589 sint frg_len
, mpdu_len
, llc_sz
;
593 u8
*pframe
, *mem_start
, *ptxdesc
;
594 struct sta_info
*psta
;
595 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
596 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
597 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
598 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
600 sint bmcst
= IS_MCAST(pattrib
->ra
);
602 if (pattrib
->psta
== NULL
)
604 psta
= pattrib
->psta
;
605 if (pxmitframe
->buf_addr
== NULL
)
607 pbuf_start
= pxmitframe
->buf_addr
;
608 ptxdesc
= pbuf_start
;
609 mem_start
= pbuf_start
+ TXDESC_OFFSET
;
610 if (make_wlanhdr(padapter
, mem_start
, pattrib
) == _FAIL
)
612 _r8712_open_pktfile(pkt
, &pktfile
);
613 _r8712_pktfile_read(&pktfile
, NULL
, (uint
) pattrib
->pkt_hdrlen
);
614 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
)) {
615 /* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
616 if (pattrib
->ether_type
== 0x8712) {
617 /* take care - update_txdesc overwrite this */
618 _r8712_pktfile_read(&pktfile
, ptxdesc
, TXDESC_SIZE
);
621 pattrib
->pktlen
= pktfile
.pkt_len
;
623 frg_len
= pxmitpriv
->frag_len
- 4;
629 pframe
+= pattrib
->hdrlen
;
630 mpdu_len
-= pattrib
->hdrlen
;
631 /* adding icv, if necessary...*/
632 if (pattrib
->iv_len
) {
634 switch (pattrib
->encrypt
) {
637 WEP_IV(pattrib
->iv
, psta
->txpn
,
648 TKIP_IV(pattrib
->iv
, psta
->txpn
,
653 AES_IV(pattrib
->iv
, psta
->txpn
,
657 AES_IV(pattrib
->iv
, psta
->txpn
,
662 memcpy(pframe
, pattrib
->iv
, pattrib
->iv_len
);
663 pframe
+= pattrib
->iv_len
;
664 mpdu_len
-= pattrib
->iv_len
;
667 llc_sz
= r8712_put_snap(pframe
, pattrib
->ether_type
);
671 if ((pattrib
->icv_len
> 0) && (pattrib
->bswenc
))
672 mpdu_len
-= pattrib
->icv_len
;
674 mem_sz
= _r8712_pktfile_read(&pktfile
, pframe
,
677 mem_sz
= _r8712_pktfile_read(&pktfile
, pframe
,
680 if ((pattrib
->icv_len
> 0) && (pattrib
->bswenc
)) {
681 memcpy(pframe
, pattrib
->icv
, pattrib
->icv_len
);
682 pframe
+= pattrib
->icv_len
;
685 if (bmcst
|| r8712_endofpktfile(&pktfile
)) {
686 pattrib
->nr_frags
= frg_inx
;
687 pattrib
->last_txcmdsz
= pattrib
->hdrlen
+
689 ((pattrib
->nr_frags
== 1) ?
692 pattrib
->icv_len
: 0) + mem_sz
;
693 ClearMFrag(mem_start
);
696 addr
= (addr_t
)(pframe
);
697 mem_start
= (unsigned char *)RND4(addr
) + TXDESC_OFFSET
;
698 memcpy(mem_start
, pbuf_start
+ TXDESC_OFFSET
, pattrib
->hdrlen
);
701 if (xmitframe_addmic(padapter
, pxmitframe
) == _FAIL
)
703 xmitframe_swencrypt(padapter
, pxmitframe
);
707 void r8712_update_protection(struct _adapter
*padapter
, u8
*ie
, uint ie_len
)
712 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
713 struct registry_priv
*pregistrypriv
= &padapter
->registrypriv
;
715 switch (pxmitpriv
->vcs_setting
) {
717 pxmitpriv
->vcs
= NONE_VCS
;
723 perp
= r8712_get_ie(ie
, _ERPINFO_IE_
, &erp_len
, ie_len
);
725 pxmitpriv
->vcs
= NONE_VCS
;
727 protection
= (*(perp
+ 2)) & BIT(1);
729 if (pregistrypriv
->vcs_type
== RTS_CTS
)
730 pxmitpriv
->vcs
= RTS_CTS
;
732 pxmitpriv
->vcs
= CTS_TO_SELF
;
734 pxmitpriv
->vcs
= NONE_VCS
;
741 struct xmit_buf
*r8712_alloc_xmitbuf(struct xmit_priv
*pxmitpriv
)
744 struct xmit_buf
*pxmitbuf
;
745 struct __queue
*pfree_xmitbuf_queue
= &pxmitpriv
->free_xmitbuf_queue
;
747 spin_lock_irqsave(&pfree_xmitbuf_queue
->lock
, irqL
);
748 pxmitbuf
= list_first_entry_or_null(&pfree_xmitbuf_queue
->queue
,
749 struct xmit_buf
, list
);
751 list_del_init(&pxmitbuf
->list
);
752 pxmitpriv
->free_xmitbuf_cnt
--;
754 spin_unlock_irqrestore(&pfree_xmitbuf_queue
->lock
, irqL
);
758 int r8712_free_xmitbuf(struct xmit_priv
*pxmitpriv
, struct xmit_buf
*pxmitbuf
)
761 struct __queue
*pfree_xmitbuf_queue
= &pxmitpriv
->free_xmitbuf_queue
;
763 if (pxmitbuf
== NULL
)
765 spin_lock_irqsave(&pfree_xmitbuf_queue
->lock
, irqL
);
766 list_del_init(&pxmitbuf
->list
);
767 list_add_tail(&(pxmitbuf
->list
), &pfree_xmitbuf_queue
->queue
);
768 pxmitpriv
->free_xmitbuf_cnt
++;
769 spin_unlock_irqrestore(&pfree_xmitbuf_queue
->lock
, irqL
);
776 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
778 If we turn on USE_RXTHREAD, then, no need for critical section.
779 Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
781 Must be very very cautious...
785 struct xmit_frame
*r8712_alloc_xmitframe(struct xmit_priv
*pxmitpriv
)
788 Please remember to use all the osdep_service api,
789 and lock/unlock or _enter/_exit critical to protect
793 struct xmit_frame
*pxframe
;
794 struct __queue
*pfree_xmit_queue
= &pxmitpriv
->free_xmit_queue
;
796 spin_lock_irqsave(&pfree_xmit_queue
->lock
, irqL
);
797 pxframe
= list_first_entry_or_null(&pfree_xmit_queue
->queue
,
798 struct xmit_frame
, list
);
800 list_del_init(&pxframe
->list
);
801 pxmitpriv
->free_xmitframe_cnt
--;
802 pxframe
->buf_addr
= NULL
;
803 pxframe
->pxmitbuf
= NULL
;
804 pxframe
->attrib
.psta
= NULL
;
807 spin_unlock_irqrestore(&pfree_xmit_queue
->lock
, irqL
);
811 void r8712_free_xmitframe(struct xmit_priv
*pxmitpriv
,
812 struct xmit_frame
*pxmitframe
)
815 struct __queue
*pfree_xmit_queue
= &pxmitpriv
->free_xmit_queue
;
816 struct _adapter
*padapter
= pxmitpriv
->adapter
;
818 if (pxmitframe
== NULL
)
820 spin_lock_irqsave(&pfree_xmit_queue
->lock
, irqL
);
821 list_del_init(&pxmitframe
->list
);
823 pxmitframe
->pkt
= NULL
;
824 list_add_tail(&pxmitframe
->list
, &pfree_xmit_queue
->queue
);
825 pxmitpriv
->free_xmitframe_cnt
++;
826 spin_unlock_irqrestore(&pfree_xmit_queue
->lock
, irqL
);
827 if (netif_queue_stopped(padapter
->pnetdev
))
828 netif_wake_queue(padapter
->pnetdev
);
831 void r8712_free_xmitframe_ex(struct xmit_priv
*pxmitpriv
,
832 struct xmit_frame
*pxmitframe
)
834 if (pxmitframe
== NULL
)
836 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
)
837 r8712_free_xmitframe(pxmitpriv
, pxmitframe
);
840 void r8712_free_xmitframe_queue(struct xmit_priv
*pxmitpriv
,
841 struct __queue
*pframequeue
)
844 struct list_head
*plist
, *phead
;
845 struct xmit_frame
*pxmitframe
;
847 spin_lock_irqsave(&(pframequeue
->lock
), irqL
);
848 phead
= &pframequeue
->queue
;
850 while (!end_of_queue_search(phead
, plist
)) {
851 pxmitframe
= LIST_CONTAINOR(plist
, struct xmit_frame
, list
);
853 r8712_free_xmitframe(pxmitpriv
, pxmitframe
);
855 spin_unlock_irqrestore(&(pframequeue
->lock
), irqL
);
858 static inline struct tx_servq
*get_sta_pending(struct _adapter
*padapter
,
859 struct __queue
**ppstapending
,
860 struct sta_info
*psta
, sint up
)
863 struct tx_servq
*ptxservq
;
864 struct hw_xmit
*phwxmits
= padapter
->xmitpriv
.hwxmits
;
869 ptxservq
= &(psta
->sta_xmitpriv
.bk_q
);
870 *ppstapending
= &padapter
->xmitpriv
.bk_pending
;
871 (phwxmits
+ 3)->accnt
++;
875 ptxservq
= &(psta
->sta_xmitpriv
.vi_q
);
876 *ppstapending
= &padapter
->xmitpriv
.vi_pending
;
877 (phwxmits
+ 1)->accnt
++;
881 ptxservq
= &(psta
->sta_xmitpriv
.vo_q
);
882 *ppstapending
= &padapter
->xmitpriv
.vo_pending
;
883 (phwxmits
+ 0)->accnt
++;
888 ptxservq
= &(psta
->sta_xmitpriv
.be_q
);
889 *ppstapending
= &padapter
->xmitpriv
.be_pending
;
890 (phwxmits
+ 2)->accnt
++;
897 * Will enqueue pxmitframe to the proper queue, and indicate it
898 * to xx_pending list.....
900 sint
r8712_xmit_classifier(struct _adapter
*padapter
,
901 struct xmit_frame
*pxmitframe
)
904 struct __queue
*pstapending
;
905 struct sta_info
*psta
;
906 struct tx_servq
*ptxservq
;
907 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
908 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
909 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
910 sint bmcst
= IS_MCAST(pattrib
->ra
);
913 psta
= pattrib
->psta
;
916 psta
= r8712_get_bcmc_stainfo(padapter
);
918 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
))
919 psta
= r8712_get_stainfo(pstapriv
,
920 get_bssid(pmlmepriv
));
922 psta
= r8712_get_stainfo(pstapriv
, pattrib
->ra
);
927 ptxservq
= get_sta_pending(padapter
, &pstapending
,
928 psta
, pattrib
->priority
);
929 spin_lock_irqsave(&pstapending
->lock
, irqL0
);
930 if (list_empty(&ptxservq
->tx_pending
))
931 list_add_tail(&ptxservq
->tx_pending
, &pstapending
->queue
);
932 list_add_tail(&pxmitframe
->list
, &ptxservq
->sta_pending
.queue
);
934 spin_unlock_irqrestore(&pstapending
->lock
, irqL0
);
938 static void alloc_hwxmits(struct _adapter
*padapter
)
940 struct hw_xmit
*hwxmits
;
941 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
943 pxmitpriv
->hwxmit_entry
= HWXMIT_ENTRY
;
944 pxmitpriv
->hwxmits
= kmalloc_array(pxmitpriv
->hwxmit_entry
,
945 sizeof(struct hw_xmit
), GFP_ATOMIC
);
946 if (!pxmitpriv
->hwxmits
)
948 hwxmits
= pxmitpriv
->hwxmits
;
949 if (pxmitpriv
->hwxmit_entry
== 5) {
950 pxmitpriv
->bmc_txqueue
.head
= 0;
951 hwxmits
[0] .phwtxqueue
= &pxmitpriv
->bmc_txqueue
;
952 hwxmits
[0] .sta_queue
= &pxmitpriv
->bm_pending
;
953 pxmitpriv
->vo_txqueue
.head
= 0;
954 hwxmits
[1] .phwtxqueue
= &pxmitpriv
->vo_txqueue
;
955 hwxmits
[1] .sta_queue
= &pxmitpriv
->vo_pending
;
956 pxmitpriv
->vi_txqueue
.head
= 0;
957 hwxmits
[2] .phwtxqueue
= &pxmitpriv
->vi_txqueue
;
958 hwxmits
[2] .sta_queue
= &pxmitpriv
->vi_pending
;
959 pxmitpriv
->bk_txqueue
.head
= 0;
960 hwxmits
[3] .phwtxqueue
= &pxmitpriv
->bk_txqueue
;
961 hwxmits
[3] .sta_queue
= &pxmitpriv
->bk_pending
;
962 pxmitpriv
->be_txqueue
.head
= 0;
963 hwxmits
[4] .phwtxqueue
= &pxmitpriv
->be_txqueue
;
964 hwxmits
[4] .sta_queue
= &pxmitpriv
->be_pending
;
965 } else if (pxmitpriv
->hwxmit_entry
== 4) {
966 pxmitpriv
->vo_txqueue
.head
= 0;
967 hwxmits
[0] .phwtxqueue
= &pxmitpriv
->vo_txqueue
;
968 hwxmits
[0] .sta_queue
= &pxmitpriv
->vo_pending
;
969 pxmitpriv
->vi_txqueue
.head
= 0;
970 hwxmits
[1] .phwtxqueue
= &pxmitpriv
->vi_txqueue
;
971 hwxmits
[1] .sta_queue
= &pxmitpriv
->vi_pending
;
972 pxmitpriv
->be_txqueue
.head
= 0;
973 hwxmits
[2] .phwtxqueue
= &pxmitpriv
->be_txqueue
;
974 hwxmits
[2] .sta_queue
= &pxmitpriv
->be_pending
;
975 pxmitpriv
->bk_txqueue
.head
= 0;
976 hwxmits
[3] .phwtxqueue
= &pxmitpriv
->bk_txqueue
;
977 hwxmits
[3] .sta_queue
= &pxmitpriv
->bk_pending
;
981 static void free_hwxmits(struct _adapter
*padapter
)
983 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
985 kfree(pxmitpriv
->hwxmits
);
988 static void init_hwxmits(struct hw_xmit
*phwxmit
, sint entry
)
992 for (i
= 0; i
< entry
; i
++, phwxmit
++) {
993 spin_lock_init(&phwxmit
->xmit_lock
);
994 INIT_LIST_HEAD(&phwxmit
->pending
);
995 phwxmit
->txcmdcnt
= 0;
1000 void xmitframe_xmitbuf_attach(struct xmit_frame
*pxmitframe
,
1001 struct xmit_buf
*pxmitbuf
)
1003 /* pxmitbuf attach to pxmitframe */
1004 pxmitframe
->pxmitbuf
= pxmitbuf
;
1005 /* urb and irp connection */
1006 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
1007 /* buffer addr assoc */
1008 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
;
1009 /* pxmitframe attach to pxmitbuf */
1010 pxmitbuf
->priv_data
= pxmitframe
;
1014 * tx_action == 0 == no frames to transmit
1015 * tx_action > 0 ==> we have frames to transmit
1016 * tx_action < 0 ==> we have frames to transmit, but TXFF is not even enough
1017 * to transmit 1 frame.
1020 int r8712_pre_xmit(struct _adapter
*padapter
, struct xmit_frame
*pxmitframe
)
1024 struct xmit_buf
*pxmitbuf
= NULL
;
1025 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
1026 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
1028 r8712_do_queue_select(padapter
, pattrib
);
1029 spin_lock_irqsave(&pxmitpriv
->lock
, irqL
);
1030 if (r8712_txframes_sta_ac_pending(padapter
, pattrib
) > 0) {
1032 r8712_xmit_enqueue(padapter
, pxmitframe
);
1033 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
1036 pxmitbuf
= r8712_alloc_xmitbuf(pxmitpriv
);
1037 if (pxmitbuf
== NULL
) { /*enqueue packet*/
1039 r8712_xmit_enqueue(padapter
, pxmitframe
);
1040 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
1041 } else { /*dump packet directly*/
1042 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
1044 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
1045 r8712_xmit_direct(padapter
, pxmitframe
);
This page took 0.095769 seconds and 5 git commands to generate.