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 _RTL8712_XMIT_C_
31 #include "osdep_service.h"
32 #include "drv_types.h"
33 #include "rtl871x_byteorder.h"
35 #include "osdep_intf.h"
38 static void dump_xframe(struct _adapter
*padapter
,
39 struct xmit_frame
*pxmitframe
);
40 static void update_txdesc(struct xmit_frame
*pxmitframe
, uint
*pmem
, int sz
);
42 sint
_r8712_init_hw_txqueue(struct hw_txqueue
*phw_txqueue
, u8 ac_tag
)
44 phw_txqueue
->ac_tag
= ac_tag
;
47 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_BEQ
;
50 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_BKQ
;
53 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_VIQ
;
56 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_VOQ
;
59 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_BEQ
;
65 int r8712_txframes_sta_ac_pending(struct _adapter
*padapter
,
66 struct pkt_attrib
*pattrib
)
68 struct sta_info
*psta
;
69 struct tx_servq
*ptxservq
;
70 int priority
= pattrib
->priority
;
76 ptxservq
= &(psta
->sta_xmitpriv
.bk_q
);
80 ptxservq
= &(psta
->sta_xmitpriv
.vi_q
);
84 ptxservq
= &(psta
->sta_xmitpriv
.vo_q
);
89 ptxservq
= &(psta
->sta_xmitpriv
.be_q
);
92 return ptxservq
->qcnt
;
95 static u32
get_ff_hwaddr(struct xmit_frame
*pxmitframe
)
98 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
99 struct _adapter
*padapter
= pxmitframe
->padapter
;
100 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
102 if (pxmitframe
->frame_tag
== TXAGG_FRAMETAG
)
103 addr
= RTL8712_DMA_H2CCMD
;
104 else if (pxmitframe
->frame_tag
== MGNT_FRAMETAG
)
105 addr
= RTL8712_DMA_MGTQ
;
106 else if (pdvobj
->nr_endpoint
== 6) {
107 switch (pattrib
->priority
) {
110 addr
= RTL8712_DMA_BEQ
;
114 addr
= RTL8712_DMA_BKQ
;
118 addr
= RTL8712_DMA_VIQ
;
122 addr
= RTL8712_DMA_VOQ
;
128 addr
= RTL8712_DMA_H2CCMD
;
131 addr
= RTL8712_DMA_BEQ
;
134 } else if (pdvobj
->nr_endpoint
== 4) {
135 switch (pattrib
->qsel
) {
140 addr
= RTL8712_DMA_BEQ
;/*RTL8712_EP_LO;*/
146 addr
= RTL8712_DMA_VOQ
;/*RTL8712_EP_HI;*/
152 addr
= RTL8712_DMA_H2CCMD
;
155 addr
= RTL8712_DMA_BEQ
;/*RTL8712_EP_LO;*/
162 static struct xmit_frame
*dequeue_one_xmitframe(struct xmit_priv
*pxmitpriv
,
163 struct hw_xmit
*phwxmit
,
164 struct tx_servq
*ptxservq
,
165 struct __queue
*pframe_queue
)
167 struct list_head
*xmitframe_plist
, *xmitframe_phead
;
168 struct xmit_frame
*pxmitframe
= NULL
;
170 xmitframe_phead
= get_list_head(pframe_queue
);
171 xmitframe_plist
= get_next(xmitframe_phead
);
172 if ((end_of_queue_search(xmitframe_phead
, xmitframe_plist
)) == false) {
173 pxmitframe
= LIST_CONTAINOR(xmitframe_plist
,
174 struct xmit_frame
, list
);
175 list_delete(&pxmitframe
->list
);
182 static struct xmit_frame
*dequeue_xframe_ex(struct xmit_priv
*pxmitpriv
,
183 struct hw_xmit
*phwxmit_i
, sint entry
)
186 struct list_head
*sta_plist
, *sta_phead
;
187 struct hw_xmit
*phwxmit
;
188 struct tx_servq
*ptxservq
= NULL
;
189 struct __queue
*pframe_queue
= NULL
;
190 struct xmit_frame
*pxmitframe
= NULL
;
192 int j
, tmp
, acirp_cnt
[4];
194 /*entry indx: 0->vo, 1->vi, 2->be, 3->bk.*/
195 inx
[0] = 0; acirp_cnt
[0] = pxmitpriv
->voq_cnt
;
196 inx
[1] = 1; acirp_cnt
[1] = pxmitpriv
->viq_cnt
;
197 inx
[2] = 2; acirp_cnt
[2] = pxmitpriv
->beq_cnt
;
198 inx
[3] = 3; acirp_cnt
[3] = pxmitpriv
->bkq_cnt
;
199 for (i
= 0; i
< 4; i
++) {
200 for (j
= i
+ 1; j
< 4; j
++) {
201 if (acirp_cnt
[j
] < acirp_cnt
[i
]) {
203 acirp_cnt
[i
] = acirp_cnt
[j
];
211 spin_lock_irqsave(&pxmitpriv
->lock
, irqL0
);
212 for (i
= 0; i
< entry
; i
++) {
213 phwxmit
= phwxmit_i
+ inx
[i
];
214 sta_phead
= get_list_head(phwxmit
->sta_queue
);
215 sta_plist
= get_next(sta_phead
);
216 while ((end_of_queue_search(sta_phead
, sta_plist
)) == false) {
217 ptxservq
= LIST_CONTAINOR(sta_plist
, struct tx_servq
,
219 pframe_queue
= &ptxservq
->sta_pending
;
220 pxmitframe
= dequeue_one_xmitframe(pxmitpriv
, phwxmit
,
221 ptxservq
, pframe_queue
);
224 goto exit_dequeue_xframe_ex
;
226 sta_plist
= get_next(sta_plist
);
227 /*Remove sta node when there are no pending packets.*/
228 if (_queue_empty(pframe_queue
)) {
229 /*must be done after get_next and before break*/
230 list_delete(&ptxservq
->tx_pending
);
234 exit_dequeue_xframe_ex
:
235 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL0
);
239 void r8712_do_queue_select(struct _adapter
*padapter
,
240 struct pkt_attrib
*pattrib
)
242 unsigned int qsel
= 0;
243 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
245 if (pdvobj
->nr_endpoint
== 6)
246 qsel
= (unsigned int) pattrib
->priority
;
247 else if (pdvobj
->nr_endpoint
== 4) {
248 qsel
= (unsigned int) pattrib
->priority
;
249 if (qsel
== 0 || qsel
== 3)
251 else if (qsel
== 1 || qsel
== 2)
253 else if (qsel
== 4 || qsel
== 5)
255 else if (qsel
== 6 || qsel
== 7)
260 pattrib
->qsel
= qsel
;
263 #ifdef CONFIG_R8712_TX_AGGR
264 u8
r8712_construct_txaggr_cmd_desc(struct xmit_buf
*pxmitbuf
)
266 struct tx_desc
*ptx_desc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
268 /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/
270 ptx_desc
->txdw0
= cpu_to_le32(CMD_HDR_SZ
&0xffff);
272 cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
)<<OFFSET_SHT
)&0x00ff0000);
273 ptx_desc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
276 ptx_desc
->txdw1
|= cpu_to_le32((0x13<<QSEL_SHT
)&0x00001f00);
281 u8
r8712_construct_txaggr_cmd_hdr(struct xmit_buf
*pxmitbuf
)
283 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)
285 struct _adapter
*padapter
= pxmitframe
->padapter
;
286 struct cmd_priv
*pcmdpriv
= &(padapter
->cmdpriv
);
287 struct cmd_hdr
*pcmd_hdr
= (struct cmd_hdr
*)
288 (pxmitbuf
->pbuf
+ TXDESC_SIZE
);
290 /* Fill up Cmd Header for USB FW Tx Aggregation.*/
292 pcmd_hdr
->cmd_dw0
= cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU
) << 16) |
293 (pcmdpriv
->cmd_seq
<< 24));
299 u8
r8712_append_mpdu_unit(struct xmit_buf
*pxmitbuf
,
300 struct xmit_frame
*pxmitframe
)
302 struct _adapter
*padapter
= pxmitframe
->padapter
;
303 struct tx_desc
*ptx_desc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
304 int last_txcmdsz
= 0;
307 /* 802.3->802.11 convertor */
308 r8712_xmitframe_coalesce(padapter
, pxmitframe
->pkt
, pxmitframe
);
309 /* free skb struct */
310 r8712_xmit_complete(padapter
, pxmitframe
);
311 if (pxmitframe
->attrib
.ether_type
!= 0x0806) {
312 if ((pxmitframe
->attrib
.ether_type
!= 0x888e) &&
313 (pxmitframe
->attrib
.dhcp_pkt
!= 1)) {
314 r8712_issue_addbareq_cmd(padapter
,
315 pxmitframe
->attrib
.priority
);
318 pxmitframe
->last
[0] = 1;
319 update_txdesc(pxmitframe
, (uint
*)(pxmitframe
->buf_addr
),
320 pxmitframe
->attrib
.last_txcmdsz
);
322 last_txcmdsz
= pxmitframe
->attrib
.last_txcmdsz
;
323 padding_sz
= (8 - (last_txcmdsz
% 8));
324 if ((last_txcmdsz
% 8) != 0) {
326 for (i
= 0; i
< padding_sz
; i
++)
327 *(pxmitframe
->buf_addr
+TXDESC_SIZE
+last_txcmdsz
+i
) = 0;
329 /* Add the new mpdu's length */
330 ptx_desc
->txdw0
= cpu_to_le32((ptx_desc
->txdw0
&0xffff0000) |
331 ((ptx_desc
->txdw0
&0x0000ffff)+
332 ((TXDESC_SIZE
+last_txcmdsz
+padding_sz
)&0x0000ffff)));
338 u8
r8712_xmitframe_aggr_1st(struct xmit_buf
*pxmitbuf
,
339 struct xmit_frame
*pxmitframe
)
341 /* linux complete context doesnt need to protect */
342 pxmitframe
->pxmitbuf
= pxmitbuf
;
343 pxmitbuf
->priv_data
= pxmitframe
;
344 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
345 /* buffer addr assoc */
346 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+TXDESC_SIZE
+CMD_HDR_SZ
;
347 /*RTL8712_DMA_H2CCMD */
348 r8712_construct_txaggr_cmd_desc(pxmitbuf
);
349 r8712_construct_txaggr_cmd_hdr(pxmitbuf
);
350 if (r8712_append_mpdu_unit(pxmitbuf
, pxmitframe
) == _SUCCESS
)
351 pxmitbuf
->aggr_nr
= 1;
356 u16
r8712_xmitframe_aggr_next(struct xmit_buf
*pxmitbuf
,
357 struct xmit_frame
*pxmitframe
)
359 pxmitframe
->pxmitbuf
= pxmitbuf
;
360 pxmitbuf
->priv_data
= pxmitframe
;
361 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
362 /* buffer addr assoc */
363 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+ TXDESC_SIZE
+
364 (((struct tx_desc
*)pxmitbuf
->pbuf
)->txdw0
& 0x0000ffff);
365 if (r8712_append_mpdu_unit(pxmitbuf
, pxmitframe
) == _SUCCESS
) {
366 r8712_free_xmitframe_ex(&pxmitframe
->padapter
->xmitpriv
,
372 (((struct tx_desc
*)pxmitbuf
->pbuf
)->txdw0
& 0x0000ffff);
375 u8
r8712_dump_aggr_xframe(struct xmit_buf
*pxmitbuf
,
376 struct xmit_frame
*pxmitframe
)
378 struct _adapter
*padapter
= pxmitframe
->padapter
;
379 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*) &padapter
->dvobjpriv
;
380 struct tx_desc
* ptxdesc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
381 struct cmd_hdr
*pcmd_hdr
= (struct cmd_hdr
*)
382 (pxmitbuf
->pbuf
+ TXDESC_SIZE
);
383 u16 total_length
= (u16
) (ptxdesc
->txdw0
& 0xffff);
385 /* use 1st xmitframe as media */
386 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
387 pcmd_hdr
->cmd_dw0
= cpu_to_le32(((total_length
-CMD_HDR_SZ
)&0x0000ffff)|
388 (pcmd_hdr
->cmd_dw0
&0xffff0000));
390 /* urb length in cmd_dw1 */
391 pcmd_hdr
->cmd_dw1
= cpu_to_le32((pxmitbuf
->aggr_nr
& 0xff)|
392 ((total_length
+TXDESC_SIZE
) << 16));
393 pxmitframe
->last
[0] = 1;
394 pxmitframe
->bpending
[0] = false;
395 pxmitframe
->mem_addr
= pxmitbuf
->pbuf
;
397 if ((pdvobj
->ishighspeed
&& ((total_length
+TXDESC_SIZE
)%0x200) == 0) ||
398 ((!pdvobj
->ishighspeed
&&
399 ((total_length
+TXDESC_SIZE
)%0x40) == 0))) {
400 ptxdesc
->txdw0
|= cpu_to_le32
401 (((TXDESC_SIZE
+OFFSET_SZ
+8)<<OFFSET_SHT
)&0x00ff0000);
402 /*32 bytes for TX Desc + 8 bytes pending*/
404 ptxdesc
->txdw0
|= cpu_to_le32
405 (((TXDESC_SIZE
+OFFSET_SZ
)<<OFFSET_SHT
)&0x00ff0000);
406 /*default = 32 bytes for TX Desc*/
408 r8712_write_port(pxmitframe
->padapter
, RTL8712_DMA_H2CCMD
,
409 total_length
+TXDESC_SIZE
, (u8
*)pxmitframe
);
416 static void update_txdesc(struct xmit_frame
*pxmitframe
, uint
*pmem
, int sz
)
419 struct _adapter
*padapter
= pxmitframe
->padapter
;
420 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
421 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
422 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
423 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
424 struct tx_desc
*ptxdesc
= (struct tx_desc
*)pmem
;
425 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
426 #ifdef CONFIG_R8712_TX_AGGR
427 struct cmd_priv
*pcmdpriv
= (struct cmd_priv
*)&padapter
->cmdpriv
;
429 u8 blnSetTxDescOffset
;
430 sint bmcst
= IS_MCAST(pattrib
->ra
);
431 struct ht_priv
*phtpriv
= &pmlmepriv
->htpriv
;
432 struct tx_desc txdesc_mp
;
434 memcpy(&txdesc_mp
, ptxdesc
, sizeof(struct tx_desc
));
435 memset(ptxdesc
, 0, sizeof(struct tx_desc
));
437 ptxdesc
->txdw0
|= cpu_to_le32(sz
&0x0000ffff);
438 if (pdvobj
->ishighspeed
) {
439 if (((sz
+ TXDESC_SIZE
) % 512) == 0)
440 blnSetTxDescOffset
= 1;
442 blnSetTxDescOffset
= 0;
444 if (((sz
+ TXDESC_SIZE
) % 64) == 0)
445 blnSetTxDescOffset
= 1;
447 blnSetTxDescOffset
= 0;
449 if (blnSetTxDescOffset
) {
450 /* 32 bytes for TX Desc + 8 bytes pending */
451 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
+ 8) <<
452 OFFSET_SHT
) & 0x00ff0000);
454 /* default = 32 bytes for TX Desc */
455 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
) <<
456 OFFSET_SHT
) & 0x00ff0000);
458 ptxdesc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
459 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
) {
461 ptxdesc
->txdw1
|= cpu_to_le32((pattrib
->mac_id
)&0x1f);
463 #ifdef CONFIG_R8712_TX_AGGR
464 /* dirty workaround, need to check if it is aggr cmd. */
465 if ((u8
*)pmem
!= (u8
*)pxmitframe
->pxmitbuf
->pbuf
) {
466 ptxdesc
->txdw0
|= cpu_to_le32
467 ((0x3 << TYPE_SHT
)&TYPE_MSK
);
468 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
471 ptxdesc
->txdw1
|= cpu_to_le32
472 ((qsel
<< QSEL_SHT
) & 0x00001f00);
473 ptxdesc
->txdw2
= cpu_to_le32
474 ((qsel
<< RTS_RC_SHT
)&0x001f0000);
475 ptxdesc
->txdw6
|= cpu_to_le32
476 ((0x5 << RSVD6_SHT
)&RSVD6_MSK
);
478 ptxdesc
->txdw0
|= cpu_to_le32
479 ((0x3 << TYPE_SHT
)&TYPE_MSK
);
480 ptxdesc
->txdw1
|= cpu_to_le32
481 ((0x13 << QSEL_SHT
) & 0x00001f00);
482 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
485 ptxdesc
->txdw2
= cpu_to_le32
486 ((qsel
<< RTS_RC_SHT
)&0x0001f000);
487 ptxdesc
->txdw7
|= cpu_to_le32
488 (pcmdpriv
->cmd_seq
<< 24);
491 pattrib
->qsel
= 0x13;
493 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
494 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
496 if (!pqospriv
->qos_option
)
497 ptxdesc
->txdw1
|= cpu_to_le32(BIT(16));/*Non-QoS*/
498 if ((pattrib
->encrypt
> 0) && !pattrib
->bswenc
) {
499 switch (pattrib
->encrypt
) { /*SEC_TYPE*/
502 ptxdesc
->txdw1
|= cpu_to_le32((0x01 << 22) &
504 /*KEY_ID when WEP is used;*/
505 ptxdesc
->txdw1
|= cpu_to_le32((psecuritypriv
->
506 PrivacyKeyIndex
<< 17) &
511 ptxdesc
->txdw1
|= cpu_to_le32((0x02 << 22) &
515 ptxdesc
->txdw1
|= cpu_to_le32((0x03 << 22) &
525 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
528 /* f/w will increase the seqnum by itself, driver pass the
529 * correct priority to fw
530 * fw will check the correct priority for increasing the
531 * seqnum per tid. about usb using 4-endpoint, qsel points out
532 * the correct mapping between AC&Endpoint,
533 * the purpose is that correct mapping lets the MAC release
534 * the AC Queue list correctly. */
535 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->priority
<< SEQ_SHT
) &
537 if ((pattrib
->ether_type
!= 0x888e) &&
538 (pattrib
->ether_type
!= 0x0806) &&
539 (pattrib
->dhcp_pkt
!= 1)) {
540 /*Not EAP & ARP type data packet*/
541 if (phtpriv
->ht_option
== 1) { /*B/G/N Mode*/
542 if (phtpriv
->ampdu_enable
!= true)
543 ptxdesc
->txdw2
|= cpu_to_le32(BK
);
546 /* EAP data packet and ARP packet.
547 * Use the 1M data rate to send the EAP/ARP packet.
548 * This will maybe make the handshake smooth.
550 /*driver uses data rate*/
551 ptxdesc
->txdw4
= cpu_to_le32(0x80000000);
552 ptxdesc
->txdw5
= cpu_to_le32(0x001f8000);/*1M*/
554 if (pattrib
->pctrl
== 1) { /* mp tx packets */
555 struct tx_desc
*ptxdesc_mp
;
556 ptxdesc_mp
= &txdesc_mp
;
558 ptxdesc
->txdw2
= cpu_to_le32(ptxdesc_mp
->txdw2
);
560 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
561 ptxdesc
->txdw2
|= cpu_to_le32(BK
);
563 ptxdesc
->txdw4
= cpu_to_le32(ptxdesc_mp
->txdw4
);
565 ptxdesc
->txdw5
= cpu_to_le32(ptxdesc_mp
->txdw5
);
566 pattrib
->pctrl
= 0;/* reset to zero; */
568 } else if (pxmitframe
->frame_tag
== MGNT_FRAMETAG
) {
570 ptxdesc
->txdw1
|= (0x05) & 0x1f;/*CAM_ID(MAC_ID), default=5;*/
571 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
572 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
573 ptxdesc
->txdw1
|= cpu_to_le32(BIT(16));/* Non-QoS */
576 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
578 /* f/w will increase the seqnum by itself, driver pass the
579 * correct priority to fw
580 * fw will check the correct priority for increasing the seqnum
581 * per tid. about usb using 4-endpoint, qsel points out the
582 * correct mapping between AC&Endpoint,
583 * the purpose is that correct mapping let the MAC releases
584 * the AC Queue list correctly. */
585 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->priority
<< SEQ_SHT
) &
588 ptxdesc
->txdw4
= cpu_to_le32(0x80002040);/*gtest*/
590 ptxdesc
->txdw5
= cpu_to_le32(0x001f8000);/* gtest 1M */
591 } else if (pxmitframe
->frame_tag
== TXAGG_FRAMETAG
) {
594 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
597 qsel
= (uint
)(pattrib
->priority
&0x0000001f);
598 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
601 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->seqnum
<< SEQ_SHT
) &
604 ptxdesc
->txdw4
= cpu_to_le32(0x80002040);/*gtest*/
606 ptxdesc
->txdw5
= cpu_to_le32(0x001f9600);/*gtest*/
610 int r8712_xmitframe_complete(struct _adapter
*padapter
,
611 struct xmit_priv
*pxmitpriv
,
612 struct xmit_buf
*pxmitbuf
)
614 struct hw_xmit
*phwxmits
;
616 struct xmit_frame
*pxmitframe
= NULL
;
617 #ifdef CONFIG_R8712_TX_AGGR
618 struct xmit_frame
*p2ndxmitframe
= NULL
;
620 int res
= _SUCCESS
, xcnt
= 0;
623 phwxmits
= pxmitpriv
->hwxmits
;
624 hwentry
= pxmitpriv
->hwxmit_entry
;
625 if (pxmitbuf
== NULL
) {
626 pxmitbuf
= r8712_alloc_xmitbuf(pxmitpriv
);
629 #ifdef CONFIG_R8712_TX_AGGR
630 pxmitbuf
->aggr_nr
= 0;
633 /* 1st frame dequeued */
634 pxmitframe
= dequeue_xframe_ex(pxmitpriv
, phwxmits
, hwentry
);
635 /* need to remember the 1st frame */
636 if (pxmitframe
!= NULL
) {
638 #ifdef CONFIG_R8712_TX_AGGR
639 /* 1. dequeue 2nd frame
640 * 2. aggr if 2nd xframe is dequeued, else dump directly
642 if (AGGR_NR_HIGH_BOUND
> 1)
643 p2ndxmitframe
= dequeue_xframe_ex(pxmitpriv
, phwxmits
,
645 if (pxmitframe
->frame_tag
!= DATA_FRAMETAG
) {
646 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
649 if (p2ndxmitframe
!= NULL
)
650 if (p2ndxmitframe
->frame_tag
!= DATA_FRAMETAG
) {
651 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
654 r8712_xmitframe_aggr_1st(pxmitbuf
, pxmitframe
);
655 if (p2ndxmitframe
!= NULL
) {
657 total_length
= r8712_xmitframe_aggr_next(
658 pxmitbuf
, p2ndxmitframe
);
660 p2ndxmitframe
= dequeue_xframe_ex(
661 pxmitpriv
, phwxmits
, hwentry
);
662 if (p2ndxmitframe
!= NULL
)
664 r8712_xmitframe_aggr_next(
669 } while (total_length
<= 0x1800 &&
670 pxmitbuf
->aggr_nr
<= AGGR_NR_HIGH_BOUND
);
672 if (pxmitbuf
->aggr_nr
> 0)
673 r8712_dump_aggr_xframe(pxmitbuf
, pxmitframe
);
677 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
678 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
) {
679 if (pxmitframe
->attrib
.priority
<= 15)
680 res
= r8712_xmitframe_coalesce(padapter
,
681 pxmitframe
->pkt
, pxmitframe
);
682 /* always return ndis_packet after
683 * r8712_xmitframe_coalesce */
684 r8712_xmit_complete(padapter
, pxmitframe
);
687 dump_xframe(padapter
, pxmitframe
);
689 r8712_free_xmitframe_ex(pxmitpriv
, pxmitframe
);
693 } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */
694 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
700 static void dump_xframe(struct _adapter
*padapter
,
701 struct xmit_frame
*pxmitframe
)
706 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
707 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
708 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
710 if (pxmitframe
->attrib
.ether_type
!= 0x0806) {
711 if (pxmitframe
->attrib
.ether_type
!= 0x888e)
712 r8712_issue_addbareq_cmd(padapter
, pattrib
->priority
);
714 mem_addr
= pxmitframe
->buf_addr
;
715 for (t
= 0; t
< pattrib
->nr_frags
; t
++) {
716 if (t
!= (pattrib
->nr_frags
- 1)) {
717 sz
= pxmitpriv
->frag_len
;
718 sz
= sz
- 4 - (psecuritypriv
->sw_encrypt
? 0 :
720 pxmitframe
->last
[t
] = 0;
722 sz
= pattrib
->last_txcmdsz
;
723 pxmitframe
->last
[t
] = 1;
725 update_txdesc(pxmitframe
, (uint
*)mem_addr
, sz
);
726 w_sz
= sz
+ TXDESC_SIZE
;
727 pxmitframe
->mem_addr
= mem_addr
;
728 pxmitframe
->bpending
[t
] = false;
729 ff_hwaddr
= get_ff_hwaddr(pxmitframe
);
730 #ifdef CONFIG_R8712_TX_AGGR
731 r8712_write_port(padapter
, RTL8712_DMA_H2CCMD
, w_sz
,
732 (unsigned char *)pxmitframe
);
734 r8712_write_port(padapter
, ff_hwaddr
, w_sz
,
735 (unsigned char *)pxmitframe
);
738 mem_addr
= (u8
*)RND4(((addr_t
)(mem_addr
)));
742 int r8712_xmit_direct(struct _adapter
*padapter
, struct xmit_frame
*pxmitframe
)
746 res
= r8712_xmitframe_coalesce(padapter
, pxmitframe
->pkt
, pxmitframe
);
747 pxmitframe
->pkt
= NULL
;
749 dump_xframe(padapter
, pxmitframe
);
753 int r8712_xmit_enqueue(struct _adapter
*padapter
, struct xmit_frame
*pxmitframe
)
755 if (r8712_xmit_classifier(padapter
, pxmitframe
) == _FAIL
) {
756 pxmitframe
->pkt
= NULL
;