]>
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
)&0x00ff0000);
270 ptx_desc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
273 ptx_desc
->txdw1
|= cpu_to_le32((0x13<<QSEL_SHT
)&0x00001f00);
278 u8
r8712_construct_txaggr_cmd_hdr(struct xmit_buf
*pxmitbuf
)
280 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)
282 struct _adapter
*padapter
= pxmitframe
->padapter
;
283 struct cmd_priv
*pcmdpriv
= &(padapter
->cmdpriv
);
284 struct cmd_hdr
*pcmd_hdr
= (struct cmd_hdr
*)
285 (pxmitbuf
->pbuf
+ TXDESC_SIZE
);
287 /* Fill up Cmd Header for USB FW Tx Aggregation.*/
289 pcmd_hdr
->cmd_dw0
= cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU
) << 16) |
290 (pcmdpriv
->cmd_seq
<< 24));
296 u8
r8712_append_mpdu_unit(struct xmit_buf
*pxmitbuf
,
297 struct xmit_frame
*pxmitframe
)
299 struct _adapter
*padapter
= pxmitframe
->padapter
;
300 struct tx_desc
*ptx_desc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
301 int last_txcmdsz
= 0;
304 /* 802.3->802.11 convertor */
305 r8712_xmitframe_coalesce(padapter
, pxmitframe
->pkt
, pxmitframe
);
306 /* free skb struct */
307 r8712_xmit_complete(padapter
, pxmitframe
);
308 if (pxmitframe
->attrib
.ether_type
!= 0x0806) {
309 if ((pxmitframe
->attrib
.ether_type
!= 0x888e) &&
310 (pxmitframe
->attrib
.dhcp_pkt
!= 1)) {
311 r8712_issue_addbareq_cmd(padapter
,
312 pxmitframe
->attrib
.priority
);
315 pxmitframe
->last
[0] = 1;
316 update_txdesc(pxmitframe
, (uint
*)(pxmitframe
->buf_addr
),
317 pxmitframe
->attrib
.last_txcmdsz
);
319 last_txcmdsz
= pxmitframe
->attrib
.last_txcmdsz
;
320 padding_sz
= (8 - (last_txcmdsz
% 8));
321 if ((last_txcmdsz
% 8) != 0) {
324 for (i
= 0; i
< padding_sz
; i
++)
325 *(pxmitframe
->buf_addr
+TXDESC_SIZE
+last_txcmdsz
+i
) = 0;
327 /* Add the new mpdu's length */
328 ptx_desc
->txdw0
= cpu_to_le32((ptx_desc
->txdw0
&0xffff0000) |
329 ((ptx_desc
->txdw0
&0x0000ffff)+
330 ((TXDESC_SIZE
+last_txcmdsz
+padding_sz
)&0x0000ffff)));
336 u8
r8712_xmitframe_aggr_1st(struct xmit_buf
*pxmitbuf
,
337 struct xmit_frame
*pxmitframe
)
339 /* linux complete context doesn't need to protect */
340 pxmitframe
->pxmitbuf
= pxmitbuf
;
341 pxmitbuf
->priv_data
= pxmitframe
;
342 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
343 /* buffer addr assoc */
344 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+TXDESC_SIZE
+CMD_HDR_SZ
;
345 /*RTL8712_DMA_H2CCMD */
346 r8712_construct_txaggr_cmd_desc(pxmitbuf
);
347 r8712_construct_txaggr_cmd_hdr(pxmitbuf
);
348 if (r8712_append_mpdu_unit(pxmitbuf
, pxmitframe
) == _SUCCESS
)
349 pxmitbuf
->aggr_nr
= 1;
354 u16
r8712_xmitframe_aggr_next(struct xmit_buf
*pxmitbuf
,
355 struct xmit_frame
*pxmitframe
)
357 pxmitframe
->pxmitbuf
= pxmitbuf
;
358 pxmitbuf
->priv_data
= pxmitframe
;
359 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
360 /* buffer addr assoc */
361 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+ TXDESC_SIZE
+
362 (((struct tx_desc
*)pxmitbuf
->pbuf
)->txdw0
& 0x0000ffff);
363 if (r8712_append_mpdu_unit(pxmitbuf
, pxmitframe
) == _SUCCESS
) {
364 r8712_free_xmitframe_ex(&pxmitframe
->padapter
->xmitpriv
,
370 (((struct tx_desc
*)pxmitbuf
->pbuf
)->txdw0
& 0x0000ffff);
373 u8
r8712_dump_aggr_xframe(struct xmit_buf
*pxmitbuf
,
374 struct xmit_frame
*pxmitframe
)
376 struct _adapter
*padapter
= pxmitframe
->padapter
;
377 struct dvobj_priv
*pdvobj
= &padapter
->dvobjpriv
;
378 struct tx_desc
*ptxdesc
= pxmitbuf
->pbuf
;
379 struct cmd_hdr
*pcmd_hdr
= (struct cmd_hdr
*)
380 (pxmitbuf
->pbuf
+ TXDESC_SIZE
);
381 u16 total_length
= (u16
) (ptxdesc
->txdw0
& 0xffff);
383 /* use 1st xmitframe as media */
384 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
385 pcmd_hdr
->cmd_dw0
= cpu_to_le32(((total_length
-CMD_HDR_SZ
)&0x0000ffff)|
386 (pcmd_hdr
->cmd_dw0
&0xffff0000));
388 /* urb length in cmd_dw1 */
389 pcmd_hdr
->cmd_dw1
= cpu_to_le32((pxmitbuf
->aggr_nr
& 0xff)|
390 ((total_length
+TXDESC_SIZE
) << 16));
391 pxmitframe
->last
[0] = 1;
392 pxmitframe
->bpending
[0] = false;
393 pxmitframe
->mem_addr
= pxmitbuf
->pbuf
;
395 if ((pdvobj
->ishighspeed
&& ((total_length
+TXDESC_SIZE
)%0x200) == 0) ||
396 ((!pdvobj
->ishighspeed
&&
397 ((total_length
+TXDESC_SIZE
)%0x40) == 0))) {
398 ptxdesc
->txdw0
|= cpu_to_le32
399 (((TXDESC_SIZE
+OFFSET_SZ
+8)<<OFFSET_SHT
)&0x00ff0000);
400 /*32 bytes for TX Desc + 8 bytes pending*/
402 ptxdesc
->txdw0
|= cpu_to_le32
403 (((TXDESC_SIZE
+OFFSET_SZ
)<<OFFSET_SHT
)&0x00ff0000);
404 /*default = 32 bytes for TX Desc*/
406 r8712_write_port(pxmitframe
->padapter
, RTL8712_DMA_H2CCMD
,
407 total_length
+TXDESC_SIZE
, (u8
*)pxmitframe
);
414 static void update_txdesc(struct xmit_frame
*pxmitframe
, uint
*pmem
, int sz
)
417 struct _adapter
*padapter
= pxmitframe
->padapter
;
418 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
419 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
420 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
421 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
422 struct tx_desc
*ptxdesc
= (struct tx_desc
*)pmem
;
423 struct dvobj_priv
*pdvobj
= &padapter
->dvobjpriv
;
424 #ifdef CONFIG_R8712_TX_AGGR
425 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
427 u8 blnSetTxDescOffset
;
428 sint bmcst
= IS_MCAST(pattrib
->ra
);
429 struct ht_priv
*phtpriv
= &pmlmepriv
->htpriv
;
430 struct tx_desc txdesc_mp
;
432 memcpy(&txdesc_mp
, ptxdesc
, sizeof(struct tx_desc
));
433 memset(ptxdesc
, 0, sizeof(struct tx_desc
));
435 ptxdesc
->txdw0
|= cpu_to_le32(sz
&0x0000ffff);
436 if (pdvobj
->ishighspeed
) {
437 if (((sz
+ TXDESC_SIZE
) % 512) == 0)
438 blnSetTxDescOffset
= 1;
440 blnSetTxDescOffset
= 0;
442 if (((sz
+ TXDESC_SIZE
) % 64) == 0)
443 blnSetTxDescOffset
= 1;
445 blnSetTxDescOffset
= 0;
447 if (blnSetTxDescOffset
) {
448 /* 32 bytes for TX Desc + 8 bytes pending */
449 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
+ 8) <<
450 OFFSET_SHT
) & 0x00ff0000);
452 /* default = 32 bytes for TX Desc */
453 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
) <<
454 OFFSET_SHT
) & 0x00ff0000);
456 ptxdesc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
457 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
) {
459 ptxdesc
->txdw1
|= cpu_to_le32((pattrib
->mac_id
)&0x1f);
461 #ifdef CONFIG_R8712_TX_AGGR
462 /* dirty workaround, need to check if it is aggr cmd. */
463 if ((u8
*)pmem
!= (u8
*)pxmitframe
->pxmitbuf
->pbuf
) {
464 ptxdesc
->txdw0
|= cpu_to_le32
465 ((0x3 << TYPE_SHT
)&TYPE_MSK
);
466 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
469 ptxdesc
->txdw1
|= cpu_to_le32
470 ((qsel
<< QSEL_SHT
) & 0x00001f00);
471 ptxdesc
->txdw2
= cpu_to_le32
472 ((qsel
<< RTS_RC_SHT
)&0x001f0000);
473 ptxdesc
->txdw6
|= cpu_to_le32
474 ((0x5 << RSVD6_SHT
)&RSVD6_MSK
);
476 ptxdesc
->txdw0
|= cpu_to_le32
477 ((0x3 << TYPE_SHT
)&TYPE_MSK
);
478 ptxdesc
->txdw1
|= cpu_to_le32
479 ((0x13 << QSEL_SHT
) & 0x00001f00);
480 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
483 ptxdesc
->txdw2
= cpu_to_le32
484 ((qsel
<< RTS_RC_SHT
)&0x0001f000);
485 ptxdesc
->txdw7
|= cpu_to_le32
486 (pcmdpriv
->cmd_seq
<< 24);
489 pattrib
->qsel
= 0x13;
491 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
492 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
494 if (!pqospriv
->qos_option
)
495 ptxdesc
->txdw1
|= cpu_to_le32(BIT(16));/*Non-QoS*/
496 if ((pattrib
->encrypt
> 0) && !pattrib
->bswenc
) {
497 switch (pattrib
->encrypt
) { /*SEC_TYPE*/
500 ptxdesc
->txdw1
|= cpu_to_le32((0x01 << 22) &
502 /*KEY_ID when WEP is used;*/
503 ptxdesc
->txdw1
|= cpu_to_le32((psecuritypriv
->
504 PrivacyKeyIndex
<< 17) &
509 ptxdesc
->txdw1
|= cpu_to_le32((0x02 << 22) &
513 ptxdesc
->txdw1
|= cpu_to_le32((0x03 << 22) &
523 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
526 /* f/w will increase the seqnum by itself, driver pass the
527 * correct priority to fw
528 * fw will check the correct priority for increasing the
529 * seqnum per tid. about usb using 4-endpoint, qsel points out
530 * the correct mapping between AC&Endpoint,
531 * the purpose is that correct mapping lets the MAC release
532 * the AC Queue list correctly. */
533 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->priority
<< SEQ_SHT
) &
535 if ((pattrib
->ether_type
!= 0x888e) &&
536 (pattrib
->ether_type
!= 0x0806) &&
537 (pattrib
->dhcp_pkt
!= 1)) {
538 /*Not EAP & ARP type data packet*/
539 if (phtpriv
->ht_option
== 1) { /*B/G/N Mode*/
540 if (phtpriv
->ampdu_enable
!= true)
541 ptxdesc
->txdw2
|= cpu_to_le32(BK
);
544 /* EAP data packet and ARP packet.
545 * Use the 1M data rate to send the EAP/ARP packet.
546 * This will maybe make the handshake smooth.
548 /*driver uses data rate*/
549 ptxdesc
->txdw4
= cpu_to_le32(0x80000000);
550 ptxdesc
->txdw5
= cpu_to_le32(0x001f8000);/*1M*/
552 if (pattrib
->pctrl
== 1) { /* mp tx packets */
553 struct tx_desc
*ptxdesc_mp
;
555 ptxdesc_mp
= &txdesc_mp
;
557 ptxdesc
->txdw2
= cpu_to_le32(ptxdesc_mp
->txdw2
);
559 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
560 ptxdesc
->txdw2
|= cpu_to_le32(BK
);
562 ptxdesc
->txdw4
= cpu_to_le32(ptxdesc_mp
->txdw4
);
564 ptxdesc
->txdw5
= cpu_to_le32(ptxdesc_mp
->txdw5
);
565 pattrib
->pctrl
= 0;/* reset to zero; */
567 } else if (pxmitframe
->frame_tag
== MGNT_FRAMETAG
) {
569 ptxdesc
->txdw1
|= (0x05) & 0x1f;/*CAM_ID(MAC_ID), default=5;*/
570 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
571 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
572 ptxdesc
->txdw1
|= cpu_to_le32(BIT(16));/* Non-QoS */
575 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
577 /* f/w will increase the seqnum by itself, driver pass the
578 * correct priority to fw
579 * fw will check the correct priority for increasing the seqnum
580 * per tid. about usb using 4-endpoint, qsel points out the
581 * correct mapping between AC&Endpoint,
582 * the purpose is that correct mapping let the MAC releases
583 * the AC Queue list correctly. */
584 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->priority
<< SEQ_SHT
) &
587 ptxdesc
->txdw4
= cpu_to_le32(0x80002040);/*gtest*/
589 ptxdesc
->txdw5
= cpu_to_le32(0x001f8000);/* gtest 1M */
590 } else if (pxmitframe
->frame_tag
== TXAGG_FRAMETAG
) {
593 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
596 qsel
= (uint
)(pattrib
->priority
&0x0000001f);
597 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
600 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->seqnum
<< SEQ_SHT
) &
603 ptxdesc
->txdw4
= cpu_to_le32(0x80002040);/*gtest*/
605 ptxdesc
->txdw5
= cpu_to_le32(0x001f9600);/*gtest*/
609 int r8712_xmitframe_complete(struct _adapter
*padapter
,
610 struct xmit_priv
*pxmitpriv
,
611 struct xmit_buf
*pxmitbuf
)
613 struct hw_xmit
*phwxmits
;
615 struct xmit_frame
*pxmitframe
= NULL
;
616 #ifdef CONFIG_R8712_TX_AGGR
617 struct xmit_frame
*p2ndxmitframe
= NULL
;
619 int res
= _SUCCESS
, xcnt
= 0;
622 phwxmits
= pxmitpriv
->hwxmits
;
623 hwentry
= pxmitpriv
->hwxmit_entry
;
624 if (pxmitbuf
== NULL
) {
625 pxmitbuf
= r8712_alloc_xmitbuf(pxmitpriv
);
628 #ifdef CONFIG_R8712_TX_AGGR
629 pxmitbuf
->aggr_nr
= 0;
632 /* 1st frame dequeued */
633 pxmitframe
= dequeue_xframe_ex(pxmitpriv
, phwxmits
, hwentry
);
634 /* need to remember the 1st frame */
635 if (pxmitframe
!= NULL
) {
637 #ifdef CONFIG_R8712_TX_AGGR
638 /* 1. dequeue 2nd frame
639 * 2. aggr if 2nd xframe is dequeued, else dump directly
641 if (AGGR_NR_HIGH_BOUND
> 1)
642 p2ndxmitframe
= dequeue_xframe_ex(pxmitpriv
, phwxmits
,
644 if (pxmitframe
->frame_tag
!= DATA_FRAMETAG
) {
645 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
648 if (p2ndxmitframe
!= NULL
)
649 if (p2ndxmitframe
->frame_tag
!= DATA_FRAMETAG
) {
650 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
653 r8712_xmitframe_aggr_1st(pxmitbuf
, pxmitframe
);
654 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
;