]>
git.proxmox.com Git - mirror_ubuntu-artful-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
= (struct dvobj_priv
*)&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
)) == false) {
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
;
191 int j
, tmp
, acirp_cnt
[4];
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
]) {
202 acirp_cnt
[i
] = acirp_cnt
[j
];
210 spin_lock_irqsave(&pxmitpriv
->lock
, irqL0
);
211 for (i
= 0; i
< entry
; i
++) {
212 phwxmit
= phwxmit_i
+ inx
[i
];
213 sta_phead
= &phwxmit
->sta_queue
->queue
;
214 sta_plist
= sta_phead
->next
;
215 while ((end_of_queue_search(sta_phead
, sta_plist
)) == false) {
216 ptxservq
= LIST_CONTAINOR(sta_plist
, struct tx_servq
,
218 pframe_queue
= &ptxservq
->sta_pending
;
219 pxmitframe
= dequeue_one_xmitframe(pxmitpriv
, phwxmit
,
220 ptxservq
, pframe_queue
);
223 goto exit_dequeue_xframe_ex
;
225 sta_plist
= sta_plist
->next
;
226 /*Remove sta node when there are no pending packets.*/
227 if (list_empty(&pframe_queue
->queue
)) {
228 /* must be done after sta_plist->next
231 list_del_init(&ptxservq
->tx_pending
);
235 exit_dequeue_xframe_ex
:
236 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL0
);
240 void r8712_do_queue_select(struct _adapter
*padapter
,
241 struct pkt_attrib
*pattrib
)
243 unsigned int qsel
= 0;
244 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
246 if (pdvobj
->nr_endpoint
== 6)
247 qsel
= (unsigned int) pattrib
->priority
;
248 else if (pdvobj
->nr_endpoint
== 4) {
249 qsel
= (unsigned int) pattrib
->priority
;
250 if (qsel
== 0 || qsel
== 3)
252 else if (qsel
== 1 || qsel
== 2)
254 else if (qsel
== 4 || qsel
== 5)
256 else if (qsel
== 6 || qsel
== 7)
261 pattrib
->qsel
= qsel
;
264 #ifdef CONFIG_R8712_TX_AGGR
265 u8
r8712_construct_txaggr_cmd_desc(struct xmit_buf
*pxmitbuf
)
267 struct tx_desc
*ptx_desc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
269 /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/
271 ptx_desc
->txdw0
= cpu_to_le32(CMD_HDR_SZ
&0xffff);
273 cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
)<<OFFSET_SHT
)&0x00ff0000);
274 ptx_desc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
277 ptx_desc
->txdw1
|= cpu_to_le32((0x13<<QSEL_SHT
)&0x00001f00);
282 u8
r8712_construct_txaggr_cmd_hdr(struct xmit_buf
*pxmitbuf
)
284 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)
286 struct _adapter
*padapter
= pxmitframe
->padapter
;
287 struct cmd_priv
*pcmdpriv
= &(padapter
->cmdpriv
);
288 struct cmd_hdr
*pcmd_hdr
= (struct cmd_hdr
*)
289 (pxmitbuf
->pbuf
+ TXDESC_SIZE
);
291 /* Fill up Cmd Header for USB FW Tx Aggregation.*/
293 pcmd_hdr
->cmd_dw0
= cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU
) << 16) |
294 (pcmdpriv
->cmd_seq
<< 24));
300 u8
r8712_append_mpdu_unit(struct xmit_buf
*pxmitbuf
,
301 struct xmit_frame
*pxmitframe
)
303 struct _adapter
*padapter
= pxmitframe
->padapter
;
304 struct tx_desc
*ptx_desc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
305 int last_txcmdsz
= 0;
308 /* 802.3->802.11 convertor */
309 r8712_xmitframe_coalesce(padapter
, pxmitframe
->pkt
, pxmitframe
);
310 /* free skb struct */
311 r8712_xmit_complete(padapter
, pxmitframe
);
312 if (pxmitframe
->attrib
.ether_type
!= 0x0806) {
313 if ((pxmitframe
->attrib
.ether_type
!= 0x888e) &&
314 (pxmitframe
->attrib
.dhcp_pkt
!= 1)) {
315 r8712_issue_addbareq_cmd(padapter
,
316 pxmitframe
->attrib
.priority
);
319 pxmitframe
->last
[0] = 1;
320 update_txdesc(pxmitframe
, (uint
*)(pxmitframe
->buf_addr
),
321 pxmitframe
->attrib
.last_txcmdsz
);
323 last_txcmdsz
= pxmitframe
->attrib
.last_txcmdsz
;
324 padding_sz
= (8 - (last_txcmdsz
% 8));
325 if ((last_txcmdsz
% 8) != 0) {
328 for (i
= 0; i
< padding_sz
; i
++)
329 *(pxmitframe
->buf_addr
+TXDESC_SIZE
+last_txcmdsz
+i
) = 0;
331 /* Add the new mpdu's length */
332 ptx_desc
->txdw0
= cpu_to_le32((ptx_desc
->txdw0
&0xffff0000) |
333 ((ptx_desc
->txdw0
&0x0000ffff)+
334 ((TXDESC_SIZE
+last_txcmdsz
+padding_sz
)&0x0000ffff)));
340 u8
r8712_xmitframe_aggr_1st(struct xmit_buf
*pxmitbuf
,
341 struct xmit_frame
*pxmitframe
)
343 /* linux complete context doesnt need to protect */
344 pxmitframe
->pxmitbuf
= pxmitbuf
;
345 pxmitbuf
->priv_data
= pxmitframe
;
346 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
347 /* buffer addr assoc */
348 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+TXDESC_SIZE
+CMD_HDR_SZ
;
349 /*RTL8712_DMA_H2CCMD */
350 r8712_construct_txaggr_cmd_desc(pxmitbuf
);
351 r8712_construct_txaggr_cmd_hdr(pxmitbuf
);
352 if (r8712_append_mpdu_unit(pxmitbuf
, pxmitframe
) == _SUCCESS
)
353 pxmitbuf
->aggr_nr
= 1;
358 u16
r8712_xmitframe_aggr_next(struct xmit_buf
*pxmitbuf
,
359 struct xmit_frame
*pxmitframe
)
361 pxmitframe
->pxmitbuf
= pxmitbuf
;
362 pxmitbuf
->priv_data
= pxmitframe
;
363 pxmitframe
->pxmit_urb
[0] = pxmitbuf
->pxmit_urb
[0];
364 /* buffer addr assoc */
365 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+ TXDESC_SIZE
+
366 (((struct tx_desc
*)pxmitbuf
->pbuf
)->txdw0
& 0x0000ffff);
367 if (r8712_append_mpdu_unit(pxmitbuf
, pxmitframe
) == _SUCCESS
) {
368 r8712_free_xmitframe_ex(&pxmitframe
->padapter
->xmitpriv
,
374 (((struct tx_desc
*)pxmitbuf
->pbuf
)->txdw0
& 0x0000ffff);
377 u8
r8712_dump_aggr_xframe(struct xmit_buf
*pxmitbuf
,
378 struct xmit_frame
*pxmitframe
)
380 struct _adapter
*padapter
= pxmitframe
->padapter
;
381 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*) &padapter
->dvobjpriv
;
382 struct tx_desc
*ptxdesc
= (struct tx_desc
*)pxmitbuf
->pbuf
;
383 struct cmd_hdr
*pcmd_hdr
= (struct cmd_hdr
*)
384 (pxmitbuf
->pbuf
+ TXDESC_SIZE
);
385 u16 total_length
= (u16
) (ptxdesc
->txdw0
& 0xffff);
387 /* use 1st xmitframe as media */
388 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
389 pcmd_hdr
->cmd_dw0
= cpu_to_le32(((total_length
-CMD_HDR_SZ
)&0x0000ffff)|
390 (pcmd_hdr
->cmd_dw0
&0xffff0000));
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) == 0) ||
400 ((!pdvobj
->ishighspeed
&&
401 ((total_length
+TXDESC_SIZE
)%0x40) == 0))) {
402 ptxdesc
->txdw0
|= cpu_to_le32
403 (((TXDESC_SIZE
+OFFSET_SZ
+8)<<OFFSET_SHT
)&0x00ff0000);
404 /*32 bytes for TX Desc + 8 bytes pending*/
406 ptxdesc
->txdw0
|= cpu_to_le32
407 (((TXDESC_SIZE
+OFFSET_SZ
)<<OFFSET_SHT
)&0x00ff0000);
408 /*default = 32 bytes for TX Desc*/
410 r8712_write_port(pxmitframe
->padapter
, RTL8712_DMA_H2CCMD
,
411 total_length
+TXDESC_SIZE
, (u8
*)pxmitframe
);
418 static void update_txdesc(struct xmit_frame
*pxmitframe
, uint
*pmem
, int sz
)
421 struct _adapter
*padapter
= pxmitframe
->padapter
;
422 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
423 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
424 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
425 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
426 struct tx_desc
*ptxdesc
= (struct tx_desc
*)pmem
;
427 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
428 #ifdef CONFIG_R8712_TX_AGGR
429 struct cmd_priv
*pcmdpriv
= (struct cmd_priv
*)&padapter
->cmdpriv
;
431 u8 blnSetTxDescOffset
;
432 sint bmcst
= IS_MCAST(pattrib
->ra
);
433 struct ht_priv
*phtpriv
= &pmlmepriv
->htpriv
;
434 struct tx_desc txdesc_mp
;
436 memcpy(&txdesc_mp
, ptxdesc
, sizeof(struct tx_desc
));
437 memset(ptxdesc
, 0, sizeof(struct tx_desc
));
439 ptxdesc
->txdw0
|= cpu_to_le32(sz
&0x0000ffff);
440 if (pdvobj
->ishighspeed
) {
441 if (((sz
+ TXDESC_SIZE
) % 512) == 0)
442 blnSetTxDescOffset
= 1;
444 blnSetTxDescOffset
= 0;
446 if (((sz
+ TXDESC_SIZE
) % 64) == 0)
447 blnSetTxDescOffset
= 1;
449 blnSetTxDescOffset
= 0;
451 if (blnSetTxDescOffset
) {
452 /* 32 bytes for TX Desc + 8 bytes pending */
453 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
+ 8) <<
454 OFFSET_SHT
) & 0x00ff0000);
456 /* default = 32 bytes for TX Desc */
457 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
) <<
458 OFFSET_SHT
) & 0x00ff0000);
460 ptxdesc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
461 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
) {
463 ptxdesc
->txdw1
|= cpu_to_le32((pattrib
->mac_id
)&0x1f);
465 #ifdef CONFIG_R8712_TX_AGGR
466 /* dirty workaround, need to check if it is aggr cmd. */
467 if ((u8
*)pmem
!= (u8
*)pxmitframe
->pxmitbuf
->pbuf
) {
468 ptxdesc
->txdw0
|= cpu_to_le32
469 ((0x3 << TYPE_SHT
)&TYPE_MSK
);
470 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
473 ptxdesc
->txdw1
|= cpu_to_le32
474 ((qsel
<< QSEL_SHT
) & 0x00001f00);
475 ptxdesc
->txdw2
= cpu_to_le32
476 ((qsel
<< RTS_RC_SHT
)&0x001f0000);
477 ptxdesc
->txdw6
|= cpu_to_le32
478 ((0x5 << RSVD6_SHT
)&RSVD6_MSK
);
480 ptxdesc
->txdw0
|= cpu_to_le32
481 ((0x3 << TYPE_SHT
)&TYPE_MSK
);
482 ptxdesc
->txdw1
|= cpu_to_le32
483 ((0x13 << QSEL_SHT
) & 0x00001f00);
484 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
487 ptxdesc
->txdw2
= cpu_to_le32
488 ((qsel
<< RTS_RC_SHT
)&0x0001f000);
489 ptxdesc
->txdw7
|= cpu_to_le32
490 (pcmdpriv
->cmd_seq
<< 24);
493 pattrib
->qsel
= 0x13;
495 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
496 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
498 if (!pqospriv
->qos_option
)
499 ptxdesc
->txdw1
|= cpu_to_le32(BIT(16));/*Non-QoS*/
500 if ((pattrib
->encrypt
> 0) && !pattrib
->bswenc
) {
501 switch (pattrib
->encrypt
) { /*SEC_TYPE*/
504 ptxdesc
->txdw1
|= cpu_to_le32((0x01 << 22) &
506 /*KEY_ID when WEP is used;*/
507 ptxdesc
->txdw1
|= cpu_to_le32((psecuritypriv
->
508 PrivacyKeyIndex
<< 17) &
513 ptxdesc
->txdw1
|= cpu_to_le32((0x02 << 22) &
517 ptxdesc
->txdw1
|= cpu_to_le32((0x03 << 22) &
527 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
530 /* f/w will increase the seqnum by itself, driver pass the
531 * correct priority to fw
532 * fw will check the correct priority for increasing the
533 * seqnum per tid. about usb using 4-endpoint, qsel points out
534 * the correct mapping between AC&Endpoint,
535 * the purpose is that correct mapping lets the MAC release
536 * the AC Queue list correctly. */
537 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->priority
<< SEQ_SHT
) &
539 if ((pattrib
->ether_type
!= 0x888e) &&
540 (pattrib
->ether_type
!= 0x0806) &&
541 (pattrib
->dhcp_pkt
!= 1)) {
542 /*Not EAP & ARP type data packet*/
543 if (phtpriv
->ht_option
== 1) { /*B/G/N Mode*/
544 if (phtpriv
->ampdu_enable
!= true)
545 ptxdesc
->txdw2
|= cpu_to_le32(BK
);
548 /* EAP data packet and ARP packet.
549 * Use the 1M data rate to send the EAP/ARP packet.
550 * This will maybe make the handshake smooth.
552 /*driver uses data rate*/
553 ptxdesc
->txdw4
= cpu_to_le32(0x80000000);
554 ptxdesc
->txdw5
= cpu_to_le32(0x001f8000);/*1M*/
556 if (pattrib
->pctrl
== 1) { /* mp tx packets */
557 struct tx_desc
*ptxdesc_mp
;
559 ptxdesc_mp
= &txdesc_mp
;
561 ptxdesc
->txdw2
= cpu_to_le32(ptxdesc_mp
->txdw2
);
563 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
564 ptxdesc
->txdw2
|= cpu_to_le32(BK
);
566 ptxdesc
->txdw4
= cpu_to_le32(ptxdesc_mp
->txdw4
);
568 ptxdesc
->txdw5
= cpu_to_le32(ptxdesc_mp
->txdw5
);
569 pattrib
->pctrl
= 0;/* reset to zero; */
571 } else if (pxmitframe
->frame_tag
== MGNT_FRAMETAG
) {
573 ptxdesc
->txdw1
|= (0x05) & 0x1f;/*CAM_ID(MAC_ID), default=5;*/
574 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
575 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
576 ptxdesc
->txdw1
|= cpu_to_le32(BIT(16));/* Non-QoS */
579 ptxdesc
->txdw2
|= cpu_to_le32(BMC
);
581 /* f/w will increase the seqnum by itself, driver pass the
582 * correct priority to fw
583 * fw will check the correct priority for increasing the seqnum
584 * per tid. about usb using 4-endpoint, qsel points out the
585 * correct mapping between AC&Endpoint,
586 * the purpose is that correct mapping let the MAC releases
587 * the AC Queue list correctly. */
588 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->priority
<< SEQ_SHT
) &
591 ptxdesc
->txdw4
= cpu_to_le32(0x80002040);/*gtest*/
593 ptxdesc
->txdw5
= cpu_to_le32(0x001f8000);/* gtest 1M */
594 } else if (pxmitframe
->frame_tag
== TXAGG_FRAMETAG
) {
597 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
600 qsel
= (uint
)(pattrib
->priority
&0x0000001f);
601 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
604 ptxdesc
->txdw3
= cpu_to_le32((pattrib
->seqnum
<< SEQ_SHT
) &
607 ptxdesc
->txdw4
= cpu_to_le32(0x80002040);/*gtest*/
609 ptxdesc
->txdw5
= cpu_to_le32(0x001f9600);/*gtest*/
613 int r8712_xmitframe_complete(struct _adapter
*padapter
,
614 struct xmit_priv
*pxmitpriv
,
615 struct xmit_buf
*pxmitbuf
)
617 struct hw_xmit
*phwxmits
;
619 struct xmit_frame
*pxmitframe
= NULL
;
620 #ifdef CONFIG_R8712_TX_AGGR
621 struct xmit_frame
*p2ndxmitframe
= NULL
;
623 int res
= _SUCCESS
, xcnt
= 0;
626 phwxmits
= pxmitpriv
->hwxmits
;
627 hwentry
= pxmitpriv
->hwxmit_entry
;
628 if (pxmitbuf
== NULL
) {
629 pxmitbuf
= r8712_alloc_xmitbuf(pxmitpriv
);
632 #ifdef CONFIG_R8712_TX_AGGR
633 pxmitbuf
->aggr_nr
= 0;
636 /* 1st frame dequeued */
637 pxmitframe
= dequeue_xframe_ex(pxmitpriv
, phwxmits
, hwentry
);
638 /* need to remember the 1st frame */
639 if (pxmitframe
!= NULL
) {
641 #ifdef CONFIG_R8712_TX_AGGR
642 /* 1. dequeue 2nd frame
643 * 2. aggr if 2nd xframe is dequeued, else dump directly
645 if (AGGR_NR_HIGH_BOUND
> 1)
646 p2ndxmitframe
= dequeue_xframe_ex(pxmitpriv
, phwxmits
,
648 if (pxmitframe
->frame_tag
!= DATA_FRAMETAG
) {
649 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
652 if (p2ndxmitframe
!= NULL
)
653 if (p2ndxmitframe
->frame_tag
!= DATA_FRAMETAG
) {
654 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
657 r8712_xmitframe_aggr_1st(pxmitbuf
, pxmitframe
);
658 if (p2ndxmitframe
!= NULL
) {
661 total_length
= r8712_xmitframe_aggr_next(
662 pxmitbuf
, p2ndxmitframe
);
664 p2ndxmitframe
= dequeue_xframe_ex(
665 pxmitpriv
, phwxmits
, hwentry
);
666 if (p2ndxmitframe
!= NULL
)
668 r8712_xmitframe_aggr_next(
673 } while (total_length
<= 0x1800 &&
674 pxmitbuf
->aggr_nr
<= AGGR_NR_HIGH_BOUND
);
676 if (pxmitbuf
->aggr_nr
> 0)
677 r8712_dump_aggr_xframe(pxmitbuf
, pxmitframe
);
681 xmitframe_xmitbuf_attach(pxmitframe
, pxmitbuf
);
682 if (pxmitframe
->frame_tag
== DATA_FRAMETAG
) {
683 if (pxmitframe
->attrib
.priority
<= 15)
684 res
= r8712_xmitframe_coalesce(padapter
,
685 pxmitframe
->pkt
, pxmitframe
);
686 /* always return ndis_packet after
687 * r8712_xmitframe_coalesce */
688 r8712_xmit_complete(padapter
, pxmitframe
);
691 dump_xframe(padapter
, pxmitframe
);
693 r8712_free_xmitframe_ex(pxmitpriv
, pxmitframe
);
697 } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */
698 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
704 static void dump_xframe(struct _adapter
*padapter
,
705 struct xmit_frame
*pxmitframe
)
710 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
711 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
712 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
714 if (pxmitframe
->attrib
.ether_type
!= 0x0806) {
715 if (pxmitframe
->attrib
.ether_type
!= 0x888e)
716 r8712_issue_addbareq_cmd(padapter
, pattrib
->priority
);
718 mem_addr
= pxmitframe
->buf_addr
;
719 for (t
= 0; t
< pattrib
->nr_frags
; t
++) {
720 if (t
!= (pattrib
->nr_frags
- 1)) {
721 sz
= pxmitpriv
->frag_len
;
722 sz
= sz
- 4 - (psecuritypriv
->sw_encrypt
? 0 :
724 pxmitframe
->last
[t
] = 0;
726 sz
= pattrib
->last_txcmdsz
;
727 pxmitframe
->last
[t
] = 1;
729 update_txdesc(pxmitframe
, (uint
*)mem_addr
, sz
);
730 w_sz
= sz
+ TXDESC_SIZE
;
731 pxmitframe
->mem_addr
= mem_addr
;
732 pxmitframe
->bpending
[t
] = false;
733 ff_hwaddr
= get_ff_hwaddr(pxmitframe
);
734 #ifdef CONFIG_R8712_TX_AGGR
735 r8712_write_port(padapter
, RTL8712_DMA_H2CCMD
, w_sz
,
736 (unsigned char *)pxmitframe
);
738 r8712_write_port(padapter
, ff_hwaddr
, w_sz
,
739 (unsigned char *)pxmitframe
);
742 mem_addr
= (u8
*)RND4(((addr_t
)(mem_addr
)));
746 int r8712_xmit_direct(struct _adapter
*padapter
, struct xmit_frame
*pxmitframe
)
750 res
= r8712_xmitframe_coalesce(padapter
, pxmitframe
->pkt
, pxmitframe
);
751 pxmitframe
->pkt
= NULL
;
753 dump_xframe(padapter
, pxmitframe
);
757 int r8712_xmit_enqueue(struct _adapter
*padapter
, struct xmit_frame
*pxmitframe
)
759 if (r8712_xmit_classifier(padapter
, pxmitframe
) == _FAIL
) {
760 pxmitframe
->pkt
= NULL
;