]>
git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - drivers/staging/rtl8712/rtl8712_xmit.c
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"
34 #include "osdep_intf.h"
37 static void dump_xframe(struct _adapter
*padapter
,
38 struct xmit_frame
*pxmitframe
);
39 static void update_txdesc(struct xmit_frame
*pxmitframe
, uint
*pmem
, int sz
);
41 sint
_r8712_init_hw_txqueue(struct hw_txqueue
*phw_txqueue
, u8 ac_tag
)
43 phw_txqueue
->ac_tag
= ac_tag
;
46 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_BEQ
;
49 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_BKQ
;
52 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_VIQ
;
55 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_VOQ
;
58 phw_txqueue
->ff_hwaddr
= RTL8712_DMA_BEQ
;
64 int r8712_txframes_sta_ac_pending(struct _adapter
*padapter
,
65 struct pkt_attrib
*pattrib
)
67 struct sta_info
*psta
;
68 struct tx_servq
*ptxservq
;
69 int priority
= pattrib
->priority
;
75 ptxservq
= &(psta
->sta_xmitpriv
.bk_q
);
79 ptxservq
= &(psta
->sta_xmitpriv
.vi_q
);
83 ptxservq
= &(psta
->sta_xmitpriv
.vo_q
);
88 ptxservq
= &(psta
->sta_xmitpriv
.be_q
);
91 return ptxservq
->qcnt
;
94 static u32
get_ff_hwaddr(struct xmit_frame
*pxmitframe
)
97 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
98 struct _adapter
*padapter
= pxmitframe
->padapter
;
99 struct dvobj_priv
*pdvobj
= &padapter
->dvobjpriv
;
101 if (pxmitframe
->frame_tag
== TXAGG_FRAMETAG
) {
102 addr
= RTL8712_DMA_H2CCMD
;
103 } else if (pxmitframe
->frame_tag
== MGNT_FRAMETAG
) {
104 addr
= RTL8712_DMA_MGTQ
;
105 } else if (pdvobj
->nr_endpoint
== 6) {
106 switch (pattrib
->priority
) {
109 addr
= RTL8712_DMA_BEQ
;
113 addr
= RTL8712_DMA_BKQ
;
117 addr
= RTL8712_DMA_VIQ
;
121 addr
= RTL8712_DMA_VOQ
;
127 addr
= RTL8712_DMA_H2CCMD
;
130 addr
= RTL8712_DMA_BEQ
;
133 } else if (pdvobj
->nr_endpoint
== 4) {
134 switch (pattrib
->qsel
) {
139 addr
= RTL8712_DMA_BEQ
;/*RTL8712_EP_LO;*/
145 addr
= RTL8712_DMA_VOQ
;/*RTL8712_EP_HI;*/
151 addr
= RTL8712_DMA_H2CCMD
;
154 addr
= RTL8712_DMA_BEQ
;/*RTL8712_EP_LO;*/
161 static struct xmit_frame
*dequeue_one_xmitframe(struct xmit_priv
*pxmitpriv
,
162 struct hw_xmit
*phwxmit
,
163 struct tx_servq
*ptxservq
,
164 struct __queue
*pframe_queue
)
166 struct list_head
*xmitframe_plist
, *xmitframe_phead
;
167 struct xmit_frame
*pxmitframe
= NULL
;
169 xmitframe_phead
= &pframe_queue
->queue
;
170 xmitframe_plist
= xmitframe_phead
->next
;
171 if (!end_of_queue_search(xmitframe_phead
, xmitframe_plist
)) {
172 pxmitframe
= LIST_CONTAINOR(xmitframe_plist
,
173 struct xmit_frame
, list
);
174 list_del_init(&pxmitframe
->list
);
181 static struct xmit_frame
*dequeue_xframe_ex(struct xmit_priv
*pxmitpriv
,
182 struct hw_xmit
*phwxmit_i
, sint entry
)
185 struct list_head
*sta_plist
, *sta_phead
;
186 struct hw_xmit
*phwxmit
;
187 struct tx_servq
*ptxservq
= NULL
;
188 struct __queue
*pframe_queue
= NULL
;
189 struct xmit_frame
*pxmitframe
= NULL
;
193 /*entry indx: 0->vo, 1->vi, 2->be, 3->bk.*/
194 inx
[0] = 0; acirp_cnt
[0] = pxmitpriv
->voq_cnt
;
195 inx
[1] = 1; acirp_cnt
[1] = pxmitpriv
->viq_cnt
;
196 inx
[2] = 2; acirp_cnt
[2] = pxmitpriv
->beq_cnt
;
197 inx
[3] = 3; acirp_cnt
[3] = pxmitpriv
->bkq_cnt
;
198 for (i
= 0; i
< 4; i
++) {
199 for (j
= i
+ 1; j
< 4; j
++) {
200 if (acirp_cnt
[j
] < acirp_cnt
[i
]) {
201 swap(acirp_cnt
[i
], acirp_cnt
[j
]);
202 swap(inx
[i
], inx
[j
]);
206 spin_lock_irqsave(&pxmitpriv
->lock
, irqL0
);
207 for (i
= 0; i
< entry
; i
++) {
208 phwxmit
= phwxmit_i
+ inx
[i
];
209 sta_phead
= &phwxmit
->sta_queue
->queue
;
210 sta_plist
= sta_phead
->next
;
211 while (!end_of_queue_search(sta_phead
, sta_plist
)) {
212 ptxservq
= LIST_CONTAINOR(sta_plist
, struct tx_servq
,
214 pframe_queue
= &ptxservq
->sta_pending
;
215 pxmitframe
= dequeue_one_xmitframe(pxmitpriv
, phwxmit
,
216 ptxservq
, pframe_queue
);
219 goto exit_dequeue_xframe_ex
;
221 sta_plist
= sta_plist
->next
;
222 /*Remove sta node when there are no pending packets.*/
223 if (list_empty(&pframe_queue
->queue
)) {
224 /* must be done after sta_plist->next
227 list_del_init(&ptxservq
->tx_pending
);
231 exit_dequeue_xframe_ex
:
232 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL0
);
236 void r8712_do_queue_select(struct _adapter
*padapter
,
237 struct pkt_attrib
*pattrib
)
239 unsigned int qsel
= 0;
240 struct dvobj_priv
*pdvobj
= &padapter
->dvobjpriv
;
242 if (pdvobj
->nr_endpoint
== 6) {
243 qsel
= (unsigned int) pattrib
->priority
;
244 } else if (pdvobj
->nr_endpoint
== 4) {
245 qsel
= (unsigned int) pattrib
->priority
;
246 if (qsel
== 0 || qsel
== 3)
248 else if (qsel
== 1 || qsel
== 2)
250 else if (qsel
== 4 || qsel
== 5)
252 else if (qsel
== 6 || qsel
== 7)
257 pattrib
->qsel
= qsel
;
260 #ifdef CONFIG_R8712_TX_AGGR
261 u8
r8712_construct_txaggr_cmd_desc(struct xmit_buf
*pxmitbuf
)
263 struct tx_desc
*ptx_desc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
265 /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/
267 ptx_desc
->txdw0
= cpu_to_le32(CMD_HDR_SZ
& 0xffff);
269 cpu_to_le32(((TXDESC_SIZE
+ OFFSET_SZ
) << OFFSET_SHT
) &
271 ptx_desc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
274 ptx_desc
->txdw1
|= cpu_to_le32((0x13 << QSEL_SHT
) & 0x00001f00);
279 u8
r8712_construct_txaggr_cmd_hdr(struct xmit_buf
*pxmitbuf
)
281 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)
283 struct _adapter
*padapter
= pxmitframe
->padapter
;
284 struct cmd_priv
*pcmdpriv
= &(padapter
->cmdpriv
);
285 struct cmd_hdr
*pcmd_hdr
= (struct cmd_hdr
*)
286 (pxmitbuf
->pbuf
+ TXDESC_SIZE
);
288 /* Fill up Cmd Header for USB FW Tx Aggregation.*/
290 pcmd_hdr
->cmd_dw0
= cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU
) << 16) |
291 (pcmdpriv
->cmd_seq
<< 24));
297 u8
r8712_append_mpdu_unit(struct xmit_buf
*pxmitbuf
,
298 struct xmit_frame
*pxmitframe
)
300 struct _adapter
*padapter
= pxmitframe
->padapter
;
301 struct tx_desc
*ptx_desc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
302 int last_txcmdsz
= 0;
305 /* 802.3->802.11 convertor */
306 r8712_xmitframe_coalesce(padapter
, pxmitframe
->pkt
, pxmitframe
);
307 /* free skb struct */
308 r8712_xmit_complete(padapter
, pxmitframe
);
309 if (pxmitframe
->attrib
.ether_type
!= 0x0806) {
310 if ((pxmitframe
->attrib
.ether_type
!= 0x888e) &&
311 (pxmitframe
->attrib
.dhcp_pkt
!= 1)) {
312 r8712_issue_addbareq_cmd(padapter
,
313 pxmitframe
->attrib
.priority
);
316 pxmitframe
->last
[0] = 1;
317 update_txdesc(pxmitframe
, (uint
*)(pxmitframe
->buf_addr
),
318 pxmitframe
->attrib
.last_txcmdsz
);
320 last_txcmdsz
= pxmitframe
->attrib
.last_txcmdsz
;
321 padding_sz
= (8 - (last_txcmdsz
% 8));
322 if ((last_txcmdsz
% 8) != 0) {
325 for (i
= 0; i
< padding_sz
; i
++)
326 *(pxmitframe
->buf_addr
+ TXDESC_SIZE
+ last_txcmdsz
+
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
) &
339 u8
r8712_xmitframe_aggr_1st(struct xmit_buf
*pxmitbuf
,
340 struct xmit_frame
*pxmitframe
)
342 /* linux complete context doesn't need to protect */
343 pxmitframe
->pxmitbuf
= pxmitbuf
;
344 pxmitbuf
->priv_data
= pxmitframe
;
345 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
346 /* buffer addr assoc */
347 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+ TXDESC_SIZE
+ CMD_HDR_SZ
;
348 /*RTL8712_DMA_H2CCMD */
349 r8712_construct_txaggr_cmd_desc(pxmitbuf
);
350 r8712_construct_txaggr_cmd_hdr(pxmitbuf
);
351 if (r8712_append_mpdu_unit(pxmitbuf
, pxmitframe
) == _SUCCESS
)
352 pxmitbuf
->aggr_nr
= 1;
357 u16
r8712_xmitframe_aggr_next(struct xmit_buf
*pxmitbuf
,
358 struct xmit_frame
*pxmitframe
)
360 pxmitframe
->pxmitbuf
= pxmitbuf
;
361 pxmitbuf
->priv_data
= pxmitframe
;
362 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
363 /* buffer addr assoc */
364 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+ TXDESC_SIZE
+
365 (((struct tx_desc
*)pxmitbuf
->pbuf
)->txdw0
& 0x0000ffff);
366 if (r8712_append_mpdu_unit(pxmitbuf
, pxmitframe
) == _SUCCESS
) {
367 r8712_free_xmitframe_ex(&pxmitframe
->padapter
->xmitpriv
,
373 (((struct tx_desc
*)pxmitbuf
->pbuf
)->txdw0
& 0x0000ffff);
376 u8
r8712_dump_aggr_xframe(struct xmit_buf
*pxmitbuf
,
377 struct xmit_frame
*pxmitframe
)
379 struct _adapter
*padapter
= pxmitframe
->padapter
;
380 struct dvobj_priv
*pdvobj
= &padapter
->dvobjpriv
;
381 struct tx_desc
*ptxdesc
= pxmitbuf
->pbuf
;
382 struct cmd_hdr
*pcmd_hdr
= (struct cmd_hdr
*)
383 (pxmitbuf
->pbuf
+ TXDESC_SIZE
);
384 u16 total_length
= (u16
) (ptxdesc
->txdw0
& 0xffff);
386 /* use 1st xmitframe as media */
387 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
388 pcmd_hdr
->cmd_dw0
= cpu_to_le32(((total_length
- CMD_HDR_SZ
) &
389 0x0000ffff) | (pcmd_hdr
->cmd_dw0
&
392 /* urb length in cmd_dw1 */
393 pcmd_hdr
->cmd_dw1
= cpu_to_le32((pxmitbuf
->aggr_nr
& 0xff)|
394 ((total_length
+ TXDESC_SIZE
) << 16));
395 pxmitframe
->last
[0] = 1;
396 pxmitframe
->bpending
[0] = false;
397 pxmitframe
->mem_addr
= pxmitbuf
->pbuf
;
399 if ((pdvobj
->ishighspeed
&& ((total_length
+ TXDESC_SIZE
) % 0x200) ==
400 0) || ((!pdvobj
->ishighspeed
&& ((total_length
+ TXDESC_SIZE
) %
402 ptxdesc
->txdw0
|= cpu_to_le32
403 (((TXDESC_SIZE
+ OFFSET_SZ
+ 8) << OFFSET_SHT
) &
405 /*32 bytes for TX Desc + 8 bytes pending*/
407 ptxdesc
->txdw0
|= cpu_to_le32
408 (((TXDESC_SIZE
+ OFFSET_SZ
) << OFFSET_SHT
) &
410 /*default = 32 bytes for TX Desc*/
412 r8712_write_port(pxmitframe
->padapter
, RTL8712_DMA_H2CCMD
,
413 total_length
+ TXDESC_SIZE
, (u8
*)pxmitframe
);
420 static void update_txdesc(struct xmit_frame
*pxmitframe
, uint
*pmem
, int sz
)
423 struct _adapter
*padapter
= pxmitframe
->padapter
;
424 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
425 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
426 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
427 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
428 struct tx_desc
*ptxdesc
= (struct tx_desc
*)pmem
;
429 struct dvobj_priv
*pdvobj
= &padapter
->dvobjpriv
;
430 #ifdef CONFIG_R8712_TX_AGGR
431 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
433 u8 blnSetTxDescOffset
;
434 sint bmcst
= IS_MCAST(pattrib
->ra
);
435 struct ht_priv
*phtpriv
= &pmlmepriv
->htpriv
;
436 struct tx_desc txdesc_mp
;
438 memcpy(&txdesc_mp
, ptxdesc
, sizeof(struct tx_desc
));
439 memset(ptxdesc
, 0, sizeof(struct tx_desc
));
441 ptxdesc
->txdw0
|= cpu_to_le32(sz
& 0x0000ffff);
442 if (pdvobj
->ishighspeed
) {
443 if (((sz
+ TXDESC_SIZE
) % 512) == 0)
444 blnSetTxDescOffset
= 1;
446 blnSetTxDescOffset
= 0;
448 if (((sz
+ TXDESC_SIZE
) % 64) == 0)
449 blnSetTxDescOffset
= 1;
451 blnSetTxDescOffset
= 0;
453 if (blnSetTxDescOffset
) {
454 /* 32 bytes for TX Desc + 8 bytes pending */
455 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+ OFFSET_SZ
+ 8) <<
456 OFFSET_SHT
) & 0x00ff0000);
458 /* default = 32 bytes for TX Desc */
459 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+ OFFSET_SZ
) <<
460 OFFSET_SHT
) & 0x00ff0000);
462 ptxdesc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
463 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
) {
465 ptxdesc
->txdw1
|= cpu_to_le32((pattrib
->mac_id
) & 0x1f);
467 #ifdef CONFIG_R8712_TX_AGGR
468 /* dirty workaround, need to check if it is aggr cmd. */
469 if ((u8
*)pmem
!= (u8
*)pxmitframe
->pxmitbuf
->pbuf
) {
470 ptxdesc
->txdw0
|= cpu_to_le32
471 ((0x3 << TYPE_SHT
) & TYPE_MSK
);
472 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
475 ptxdesc
->txdw1
|= cpu_to_le32
476 ((qsel
<< QSEL_SHT
) & 0x00001f00);
477 ptxdesc
->txdw2
= cpu_to_le32
478 ((qsel
<< RTS_RC_SHT
) & 0x001f0000);
479 ptxdesc
->txdw6
|= cpu_to_le32
480 ((0x5 << RSVD6_SHT
) & RSVD6_MSK
);
482 ptxdesc
->txdw0
|= cpu_to_le32
483 ((0x3 << TYPE_SHT
) & TYPE_MSK
);
484 ptxdesc
->txdw1
|= cpu_to_le32
485 ((0x13 << QSEL_SHT
) & 0x00001f00);
486 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
489 ptxdesc
->txdw2
= cpu_to_le32
490 ((qsel
<< RTS_RC_SHT
) & 0x0001f000);
491 ptxdesc
->txdw7
|= cpu_to_le32
492 (pcmdpriv
->cmd_seq
<< 24);
495 pattrib
->qsel
= 0x13;
497 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
498 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
500 if (!pqospriv
->qos_option
)
501 ptxdesc
->txdw1
|= cpu_to_le32(BIT(16));/*Non-QoS*/
502 if ((pattrib
->encrypt
> 0) && !pattrib
->bswenc
) {
503 switch (pattrib
->encrypt
) { /*SEC_TYPE*/
506 ptxdesc
->txdw1
|= cpu_to_le32((0x01 << 22) &
508 /*KEY_ID when WEP is used;*/
509 ptxdesc
->txdw1
|= cpu_to_le32((psecuritypriv
->
510 PrivacyKeyIndex
<< 17) &
515 ptxdesc
->txdw1
|= cpu_to_le32((0x02 << 22) &
519 ptxdesc
->txdw1
|= cpu_to_le32((0x03 << 22) &
529 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
532 /* f/w will increase the seqnum by itself, driver pass the
533 * correct priority to fw
534 * fw will check the correct priority for increasing the
535 * seqnum per tid. about usb using 4-endpoint, qsel points out
536 * the correct mapping between AC&Endpoint,
537 * the purpose is that correct mapping lets the MAC release
538 * the AC Queue list correctly. */
539 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->priority
<< SEQ_SHT
) &
541 if ((pattrib
->ether_type
!= 0x888e) &&
542 (pattrib
->ether_type
!= 0x0806) &&
543 (pattrib
->dhcp_pkt
!= 1)) {
544 /*Not EAP & ARP type data packet*/
545 if (phtpriv
->ht_option
== 1) { /*B/G/N Mode*/
546 if (phtpriv
->ampdu_enable
!= true)
547 ptxdesc
->txdw2
|= cpu_to_le32(BK
);
550 /* EAP data packet and ARP packet.
551 * Use the 1M data rate to send the EAP/ARP packet.
552 * This will maybe make the handshake smooth.
554 /*driver uses data rate*/
555 ptxdesc
->txdw4
= cpu_to_le32(0x80000000);
556 ptxdesc
->txdw5
= cpu_to_le32(0x001f8000);/*1M*/
558 if (pattrib
->pctrl
== 1) { /* mp tx packets */
559 struct tx_desc
*ptxdesc_mp
;
561 ptxdesc_mp
= &txdesc_mp
;
563 ptxdesc
->txdw2
= cpu_to_le32(ptxdesc_mp
->txdw2
);
565 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
566 ptxdesc
->txdw2
|= cpu_to_le32(BK
);
568 ptxdesc
->txdw4
= cpu_to_le32(ptxdesc_mp
->txdw4
);
570 ptxdesc
->txdw5
= cpu_to_le32(ptxdesc_mp
->txdw5
);
571 pattrib
->pctrl
= 0;/* reset to zero; */
573 } else if (pxmitframe
->frame_tag
== MGNT_FRAMETAG
) {
575 ptxdesc
->txdw1
|= (0x05) & 0x1f;/*CAM_ID(MAC_ID), default=5;*/
576 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
577 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
578 ptxdesc
->txdw1
|= cpu_to_le32(BIT(16));/* Non-QoS */
581 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
583 /* f/w will increase the seqnum by itself, driver pass the
584 * correct priority to fw
585 * fw will check the correct priority for increasing the seqnum
586 * per tid. about usb using 4-endpoint, qsel points out the
587 * correct mapping between AC&Endpoint,
588 * the purpose is that correct mapping let the MAC releases
589 * the AC Queue list correctly. */
590 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->priority
<< SEQ_SHT
) &
593 ptxdesc
->txdw4
= cpu_to_le32(0x80002040);/*gtest*/
595 ptxdesc
->txdw5
= cpu_to_le32(0x001f8000);/* gtest 1M */
596 } else if (pxmitframe
->frame_tag
== TXAGG_FRAMETAG
) {
599 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
602 qsel
= (uint
)(pattrib
->priority
& 0x0000001f);
603 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
606 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->seqnum
<< SEQ_SHT
) &
609 ptxdesc
->txdw4
= cpu_to_le32(0x80002040);/*gtest*/
611 ptxdesc
->txdw5
= cpu_to_le32(0x001f9600);/*gtest*/
615 int r8712_xmitframe_complete(struct _adapter
*padapter
,
616 struct xmit_priv
*pxmitpriv
,
617 struct xmit_buf
*pxmitbuf
)
619 struct hw_xmit
*phwxmits
;
621 struct xmit_frame
*pxmitframe
= NULL
;
622 #ifdef CONFIG_R8712_TX_AGGR
623 struct xmit_frame
*p2ndxmitframe
= NULL
;
625 int res
= _SUCCESS
, xcnt
= 0;
628 phwxmits
= pxmitpriv
->hwxmits
;
629 hwentry
= pxmitpriv
->hwxmit_entry
;
630 if (pxmitbuf
== NULL
) {
631 pxmitbuf
= r8712_alloc_xmitbuf(pxmitpriv
);
634 #ifdef CONFIG_R8712_TX_AGGR
635 pxmitbuf
->aggr_nr
= 0;
638 /* 1st frame dequeued */
639 pxmitframe
= dequeue_xframe_ex(pxmitpriv
, phwxmits
, hwentry
);
640 /* need to remember the 1st frame */
641 if (pxmitframe
!= NULL
) {
643 #ifdef CONFIG_R8712_TX_AGGR
644 /* 1. dequeue 2nd frame
645 * 2. aggr if 2nd xframe is dequeued, else dump directly
647 if (AGGR_NR_HIGH_BOUND
> 1)
648 p2ndxmitframe
= dequeue_xframe_ex(pxmitpriv
, phwxmits
,
650 if (pxmitframe
->frame_tag
!= DATA_FRAMETAG
) {
651 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
654 if (p2ndxmitframe
!= NULL
)
655 if (p2ndxmitframe
->frame_tag
!= DATA_FRAMETAG
) {
656 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
659 r8712_xmitframe_aggr_1st(pxmitbuf
, pxmitframe
);
660 if (p2ndxmitframe
!= NULL
) {
663 total_length
= r8712_xmitframe_aggr_next(
664 pxmitbuf
, p2ndxmitframe
);
666 p2ndxmitframe
= dequeue_xframe_ex(
667 pxmitpriv
, phwxmits
, hwentry
);
668 if (p2ndxmitframe
!= NULL
)
670 r8712_xmitframe_aggr_next(
675 } while (total_length
<= 0x1800 &&
676 pxmitbuf
->aggr_nr
<= AGGR_NR_HIGH_BOUND
);
678 if (pxmitbuf
->aggr_nr
> 0)
679 r8712_dump_aggr_xframe(pxmitbuf
, pxmitframe
);
683 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
684 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
) {
685 if (pxmitframe
->attrib
.priority
<= 15)
686 res
= r8712_xmitframe_coalesce(padapter
,
687 pxmitframe
->pkt
, pxmitframe
);
688 /* always return ndis_packet after
689 * r8712_xmitframe_coalesce */
690 r8712_xmit_complete(padapter
, pxmitframe
);
693 dump_xframe(padapter
, pxmitframe
);
695 r8712_free_xmitframe_ex(pxmitpriv
, pxmitframe
);
699 } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */
700 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
706 static void dump_xframe(struct _adapter
*padapter
,
707 struct xmit_frame
*pxmitframe
)
712 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
713 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
714 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
716 if (pxmitframe
->attrib
.ether_type
!= 0x0806) {
717 if (pxmitframe
->attrib
.ether_type
!= 0x888e)
718 r8712_issue_addbareq_cmd(padapter
, pattrib
->priority
);
720 mem_addr
= pxmitframe
->buf_addr
;
721 for (t
= 0; t
< pattrib
->nr_frags
; t
++) {
722 if (t
!= (pattrib
->nr_frags
- 1)) {
723 sz
= pxmitpriv
->frag_len
;
724 sz
= sz
- 4 - (psecuritypriv
->sw_encrypt
? 0 :
726 pxmitframe
->last
[t
] = 0;
728 sz
= pattrib
->last_txcmdsz
;
729 pxmitframe
->last
[t
] = 1;
731 update_txdesc(pxmitframe
, (uint
*)mem_addr
, sz
);
732 w_sz
= sz
+ TXDESC_SIZE
;
733 pxmitframe
->mem_addr
= mem_addr
;
734 pxmitframe
->bpending
[t
] = false;
735 ff_hwaddr
= get_ff_hwaddr(pxmitframe
);
736 #ifdef CONFIG_R8712_TX_AGGR
737 r8712_write_port(padapter
, RTL8712_DMA_H2CCMD
, w_sz
,
738 (unsigned char *)pxmitframe
);
740 r8712_write_port(padapter
, ff_hwaddr
, w_sz
,
741 (unsigned char *)pxmitframe
);
744 mem_addr
= (u8
*)RND4(((addr_t
)(mem_addr
)));
748 int r8712_xmit_direct(struct _adapter
*padapter
, struct xmit_frame
*pxmitframe
)
752 res
= r8712_xmitframe_coalesce(padapter
, pxmitframe
->pkt
, pxmitframe
);
753 pxmitframe
->pkt
= NULL
;
755 dump_xframe(padapter
, pxmitframe
);
759 int r8712_xmit_enqueue(struct _adapter
*padapter
, struct xmit_frame
*pxmitframe
)
761 if (r8712_xmit_classifier(padapter
, pxmitframe
) == _FAIL
) {
762 pxmitframe
->pkt
= NULL
;