1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 ******************************************************************************/
15 #define _RTL8188E_XMIT_C_
16 #include <osdep_service.h>
17 #include <drv_types.h>
20 #include <osdep_intf.h>
21 #include <usb_ops_linux.h>
22 #include <rtl8188e_hal.h>
24 s32
rtw_hal_init_xmit_priv(struct adapter
*adapt
)
26 struct xmit_priv
*pxmitpriv
= &adapt
->xmitpriv
;
28 tasklet_init(&pxmitpriv
->xmit_tasklet
,
29 (void(*)(unsigned long))rtl8188eu_xmit_tasklet
,
30 (unsigned long)adapt
);
34 static u8
urb_zero_packet_chk(struct adapter
*adapt
, int sz
)
36 u8 set_tx_desc_offset
;
37 struct hal_data_8188e
*haldata
= GET_HAL_DATA(adapt
);
38 set_tx_desc_offset
= (((sz
+ TXDESC_SIZE
) % haldata
->UsbBulkOutSize
) == 0) ? 1 : 0;
40 return set_tx_desc_offset
;
43 static void rtl8188eu_cal_txdesc_chksum(struct tx_desc
*ptxdesc
)
45 u16
*usptr
= (u16
*)ptxdesc
;
46 u32 count
= 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
51 ptxdesc
->txdw7
&= cpu_to_le32(0xffff0000);
53 for (index
= 0; index
< count
; index
++)
54 checksum
= checksum
^ le16_to_cpu(*(__le16
*)(usptr
+ index
));
55 ptxdesc
->txdw7
|= cpu_to_le32(0x0000ffff & checksum
);
58 /* Description: In normal chip, we should send some packet to Hw which will be used by Fw */
59 /* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */
60 /* Fw can tell Hw to send these packet derectly. */
61 void rtl8188e_fill_fake_txdesc(struct adapter
*adapt
, u8
*desc
, u32 BufferLen
, u8 ispspoll
, u8 is_btqosnull
)
63 struct tx_desc
*ptxdesc
;
65 /* Clear all status */
66 ptxdesc
= (struct tx_desc
*)desc
;
67 memset(desc
, 0, TXDESC_SIZE
);
70 ptxdesc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
); /* own, bFirstSeg, bLastSeg; */
72 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
)<<OFFSET_SHT
)&0x00ff0000); /* 32 bytes for TX Desc */
74 ptxdesc
->txdw0
|= cpu_to_le32(BufferLen
&0x0000ffff); /* Buffer size + command header */
77 ptxdesc
->txdw1
|= cpu_to_le32((QSLT_MGNT
<<QSEL_SHT
)&0x00001f00); /* Fixed queue of Mgnt queue */
79 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */
81 ptxdesc
->txdw1
|= cpu_to_le32(NAVUSEHDR
);
83 ptxdesc
->txdw4
|= cpu_to_le32(BIT(7)); /* Hw set sequence number */
84 ptxdesc
->txdw3
|= cpu_to_le32((8 << 28)); /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
88 ptxdesc
->txdw2
|= cpu_to_le32(BIT(23)); /* BT NULL */
91 ptxdesc
->txdw4
|= cpu_to_le32(BIT(8));/* driver uses rate */
93 /* USB interface drop packet if the checksum of descriptor isn't correct. */
94 /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
95 rtl8188eu_cal_txdesc_chksum(ptxdesc
);
98 static void fill_txdesc_sectype(struct pkt_attrib
*pattrib
, struct tx_desc
*ptxdesc
)
100 if ((pattrib
->encrypt
> 0) && !pattrib
->bswenc
) {
101 switch (pattrib
->encrypt
) {
102 /* SEC_TYPE : 0:NO_ENC,1:WEP40/TKIP,2:WAPI,3:AES */
105 ptxdesc
->txdw1
|= cpu_to_le32((0x01<<SEC_TYPE_SHT
)&0x00c00000);
106 ptxdesc
->txdw2
|= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT
);
110 ptxdesc
->txdw1
|= cpu_to_le32((0x01<<SEC_TYPE_SHT
)&0x00c00000);
111 ptxdesc
->txdw2
|= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT
);
114 ptxdesc
->txdw1
|= cpu_to_le32((0x03<<SEC_TYPE_SHT
)&0x00c00000);
115 ptxdesc
->txdw2
|= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT
);
124 static void fill_txdesc_vcs(struct pkt_attrib
*pattrib
, __le32
*pdw
)
126 switch (pattrib
->vcs_mode
) {
128 *pdw
|= cpu_to_le32(RTS_EN
);
131 *pdw
|= cpu_to_le32(CTS_2_SELF
);
137 if (pattrib
->vcs_mode
) {
138 *pdw
|= cpu_to_le32(HW_RTS_EN
);
140 if (pattrib
->ht_en
) {
141 *pdw
|= (pattrib
->bwmode
&HT_CHANNEL_WIDTH_40
) ? cpu_to_le32(BIT(27)) : 0;
143 if (pattrib
->ch_offset
== HAL_PRIME_CHNL_OFFSET_LOWER
)
144 *pdw
|= cpu_to_le32((0x01 << 28) & 0x30000000);
145 else if (pattrib
->ch_offset
== HAL_PRIME_CHNL_OFFSET_UPPER
)
146 *pdw
|= cpu_to_le32((0x02 << 28) & 0x30000000);
147 else if (pattrib
->ch_offset
== HAL_PRIME_CHNL_OFFSET_DONT_CARE
)
150 *pdw
|= cpu_to_le32((0x03 << 28) & 0x30000000);
155 static void fill_txdesc_phy(struct pkt_attrib
*pattrib
, __le32
*pdw
)
157 if (pattrib
->ht_en
) {
158 *pdw
|= (pattrib
->bwmode
&HT_CHANNEL_WIDTH_40
) ? cpu_to_le32(BIT(25)) : 0;
160 if (pattrib
->ch_offset
== HAL_PRIME_CHNL_OFFSET_LOWER
)
161 *pdw
|= cpu_to_le32((0x01 << DATA_SC_SHT
) & 0x003f0000);
162 else if (pattrib
->ch_offset
== HAL_PRIME_CHNL_OFFSET_UPPER
)
163 *pdw
|= cpu_to_le32((0x02 << DATA_SC_SHT
) & 0x003f0000);
164 else if (pattrib
->ch_offset
== HAL_PRIME_CHNL_OFFSET_DONT_CARE
)
167 *pdw
|= cpu_to_le32((0x03 << DATA_SC_SHT
) & 0x003f0000);
171 static s32
update_txdesc(struct xmit_frame
*pxmitframe
, u8
*pmem
, s32 sz
, u8 bagg_pkt
)
175 u8 data_rate
, pwr_status
, offset
;
176 struct adapter
*adapt
= pxmitframe
->padapter
;
177 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
178 struct hal_data_8188e
*haldata
= GET_HAL_DATA(adapt
);
179 struct tx_desc
*ptxdesc
= (struct tx_desc
*)pmem
;
180 struct mlme_ext_priv
*pmlmeext
= &adapt
->mlmeextpriv
;
181 struct mlme_ext_info
*pmlmeinfo
= &(pmlmeext
->mlmext_info
);
182 int bmcst
= IS_MCAST(pattrib
->ra
);
184 if (adapt
->registrypriv
.mp_mode
== 0) {
185 if ((!bagg_pkt
) && (urb_zero_packet_chk(adapt
, sz
) == 0)) {
186 ptxdesc
= (struct tx_desc
*)(pmem
+PACKET_OFFSET_SZ
);
191 memset(ptxdesc
, 0, sizeof(struct tx_desc
));
194 ptxdesc
->txdw0
|= cpu_to_le32(OWN
| FSG
| LSG
);
195 ptxdesc
->txdw0
|= cpu_to_le32(sz
& 0x0000ffff);/* update TXPKTSIZE */
197 offset
= TXDESC_SIZE
+ OFFSET_SZ
;
199 ptxdesc
->txdw0
|= cpu_to_le32(((offset
) << OFFSET_SHT
) & 0x00ff0000);/* 32 bytes for TX Desc */
202 ptxdesc
->txdw0
|= cpu_to_le32(BMC
);
204 if (adapt
->registrypriv
.mp_mode
== 0) {
206 if ((pull
) && (pxmitframe
->pkt_offset
> 0))
207 pxmitframe
->pkt_offset
= pxmitframe
->pkt_offset
- 1;
211 /* pkt_offset, unit:8 bytes padding */
212 if (pxmitframe
->pkt_offset
> 0)
213 ptxdesc
->txdw1
|= cpu_to_le32((pxmitframe
->pkt_offset
<< 26) & 0x7c000000);
215 /* driver uses rate */
216 ptxdesc
->txdw4
|= cpu_to_le32(USERATE
);/* rate control always by driver */
218 if ((pxmitframe
->frame_tag
& 0x0f) == DATA_FRAMETAG
) {
220 ptxdesc
->txdw1
|= cpu_to_le32(pattrib
->mac_id
& 0x3F);
222 qsel
= (uint
)(pattrib
->qsel
& 0x0000001f);
223 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
225 ptxdesc
->txdw1
|= cpu_to_le32((pattrib
->raid
<< RATE_ID_SHT
) & 0x000F0000);
227 fill_txdesc_sectype(pattrib
, ptxdesc
);
229 if (pattrib
->ampdu_en
) {
230 ptxdesc
->txdw2
|= cpu_to_le32(AGG_EN
);/* AGG EN */
231 ptxdesc
->txdw6
= cpu_to_le32(0x6666f800);
233 ptxdesc
->txdw2
|= cpu_to_le32(AGG_BK
);/* AGG BK */
239 ptxdesc
->txdw3
|= cpu_to_le32((pattrib
->seqnum
<< SEQ_SHT
) & 0x0FFF0000);
241 /* offset 16 , offset 20 */
243 ptxdesc
->txdw4
|= cpu_to_le32(QOS
);/* QoS */
246 if (pxmitframe
->agg_num
> 1)
247 ptxdesc
->txdw5
|= cpu_to_le32((pxmitframe
->agg_num
<< USB_TXAGG_NUM_SHT
) & 0xFF000000);
249 if ((pattrib
->ether_type
!= 0x888e) &&
250 (pattrib
->ether_type
!= 0x0806) &&
251 (pattrib
->ether_type
!= 0x88b4) &&
252 (pattrib
->dhcp_pkt
!= 1)) {
253 /* Non EAP & ARP & DHCP type data packet */
255 fill_txdesc_vcs(pattrib
, &ptxdesc
->txdw4
);
256 fill_txdesc_phy(pattrib
, &ptxdesc
->txdw4
);
258 ptxdesc
->txdw4
|= cpu_to_le32(0x00000008);/* RTS Rate=24M */
259 ptxdesc
->txdw5
|= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */
261 if (pattrib
->ht_en
) {
262 if (ODM_RA_GetShortGI_8188E(&haldata
->odmpriv
, pattrib
->mac_id
))
263 ptxdesc
->txdw5
|= cpu_to_le32(SGI
);/* SGI */
265 data_rate
= ODM_RA_GetDecisionRate_8188E(&haldata
->odmpriv
, pattrib
->mac_id
);
266 ptxdesc
->txdw5
|= cpu_to_le32(data_rate
& 0x3F);
267 pwr_status
= ODM_RA_GetHwPwrStatus_8188E(&haldata
->odmpriv
, pattrib
->mac_id
);
268 ptxdesc
->txdw4
|= cpu_to_le32((pwr_status
& 0x7) << PWR_STATUS_SHT
);
270 /* EAP data packet and ARP packet and DHCP. */
271 /* Use the 1M data rate to send the EAP/ARP packet. */
272 /* This will maybe make the handshake smooth. */
273 ptxdesc
->txdw2
|= cpu_to_le32(AGG_BK
);/* AGG BK */
274 if (pmlmeinfo
->preamble_mode
== PREAMBLE_SHORT
)
275 ptxdesc
->txdw4
|= cpu_to_le32(BIT(24));/* DATA_SHORT */
276 ptxdesc
->txdw5
|= cpu_to_le32(MRateToHwRate(pmlmeext
->tx_rate
));
278 } else if ((pxmitframe
->frame_tag
&0x0f) == MGNT_FRAMETAG
) {
280 ptxdesc
->txdw1
|= cpu_to_le32(pattrib
->mac_id
& 0x3f);
282 qsel
= (uint
)(pattrib
->qsel
&0x0000001f);
283 ptxdesc
->txdw1
|= cpu_to_le32((qsel
<< QSEL_SHT
) & 0x00001f00);
285 ptxdesc
->txdw1
|= cpu_to_le32((pattrib
->raid
<< RATE_ID_SHT
) & 0x000f0000);
288 /* CCX-TXRPT ack for xmit mgmt frames. */
289 if (pxmitframe
->ack_report
)
290 ptxdesc
->txdw2
|= cpu_to_le32(BIT(19));
293 ptxdesc
->txdw3
|= cpu_to_le32((pattrib
->seqnum
<<SEQ_SHT
)&0x0FFF0000);
296 ptxdesc
->txdw5
|= cpu_to_le32(RTY_LMT_EN
);/* retry limit enable */
297 if (pattrib
->retry_ctrl
)
298 ptxdesc
->txdw5
|= cpu_to_le32(0x00180000);/* retry limit = 6 */
300 ptxdesc
->txdw5
|= cpu_to_le32(0x00300000);/* retry limit = 12 */
302 ptxdesc
->txdw5
|= cpu_to_le32(MRateToHwRate(pmlmeext
->tx_rate
));
303 } else if ((pxmitframe
->frame_tag
&0x0f) == TXAGG_FRAMETAG
) {
304 DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
306 DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe
->frame_tag
);
309 ptxdesc
->txdw1
|= cpu_to_le32((4) & 0x3f);/* CAM_ID(MAC_ID) */
311 ptxdesc
->txdw1
|= cpu_to_le32((6 << RATE_ID_SHT
) & 0x000f0000);/* raid */
316 ptxdesc
->txdw3
|= cpu_to_le32((pattrib
->seqnum
<<SEQ_SHT
)&0x0fff0000);
319 ptxdesc
->txdw5
|= cpu_to_le32(MRateToHwRate(pmlmeext
->tx_rate
));
322 /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
323 /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */
324 /* mgnt frame should be controlled by Hw because Fw will also send null data */
325 /* which we cannot control when Fw LPS enable. */
326 /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
327 /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
328 /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */
329 /* 2010.06.23. Added by tynli. */
330 if (!pattrib
->qos_en
) {
331 ptxdesc
->txdw3
|= cpu_to_le32(EN_HWSEQ
); /* Hw set sequence number */
332 ptxdesc
->txdw4
|= cpu_to_le32(HW_SSN
); /* Hw set sequence number */
335 rtl88eu_dm_set_tx_ant_by_tx_info(&haldata
->odmpriv
, pmem
,
338 rtl8188eu_cal_txdesc_chksum(ptxdesc
);
339 _dbg_dump_tx_info(adapt
, pxmitframe
->frame_tag
, ptxdesc
);
343 /* for non-agg data frame or management frame */
344 static s32
rtw_dump_xframe(struct adapter
*adapt
, struct xmit_frame
*pxmitframe
)
347 s32 inner_ret
= _SUCCESS
;
348 int t
, sz
, w_sz
, pull
= 0;
351 struct xmit_buf
*pxmitbuf
= pxmitframe
->pxmitbuf
;
352 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
353 struct xmit_priv
*pxmitpriv
= &adapt
->xmitpriv
;
354 struct security_priv
*psecuritypriv
= &adapt
->securitypriv
;
355 if ((pxmitframe
->frame_tag
== DATA_FRAMETAG
) &&
356 (pxmitframe
->attrib
.ether_type
!= 0x0806) &&
357 (pxmitframe
->attrib
.ether_type
!= 0x888e) &&
358 (pxmitframe
->attrib
.ether_type
!= 0x88b4) &&
359 (pxmitframe
->attrib
.dhcp_pkt
!= 1))
360 rtw_issue_addbareq_cmd(adapt
, pxmitframe
);
361 mem_addr
= pxmitframe
->buf_addr
;
363 RT_TRACE(_module_rtl871x_xmit_c_
, _drv_info_
, ("rtw_dump_xframe()\n"));
365 for (t
= 0; t
< pattrib
->nr_frags
; t
++) {
366 if (inner_ret
!= _SUCCESS
&& ret
== _SUCCESS
)
369 if (t
!= (pattrib
->nr_frags
- 1)) {
370 RT_TRACE(_module_rtl871x_xmit_c_
, _drv_err_
, ("pattrib->nr_frags=%d\n", pattrib
->nr_frags
));
372 sz
= pxmitpriv
->frag_len
;
373 sz
= sz
- 4 - (psecuritypriv
->sw_encrypt
? 0 : pattrib
->icv_len
);
376 sz
= pattrib
->last_txcmdsz
;
379 pull
= update_txdesc(pxmitframe
, mem_addr
, sz
, false);
382 mem_addr
+= PACKET_OFFSET_SZ
; /* pull txdesc head */
383 pxmitframe
->buf_addr
= mem_addr
;
384 w_sz
= sz
+ TXDESC_SIZE
;
386 w_sz
= sz
+ TXDESC_SIZE
+ PACKET_OFFSET_SZ
;
388 ff_hwaddr
= rtw_get_ff_hwaddr(pxmitframe
);
390 inner_ret
= usb_write_port(adapt
, ff_hwaddr
, w_sz
, (unsigned char *)pxmitbuf
);
392 rtw_count_tx_stats(adapt
, pxmitframe
, sz
);
394 RT_TRACE(_module_rtl871x_xmit_c_
, _drv_info_
, ("rtw_write_port, w_sz=%d\n", w_sz
));
398 mem_addr
= (u8
*)round_up((size_t)mem_addr
, 4);
401 rtw_free_xmitframe(pxmitpriv
, pxmitframe
);
404 rtw_sctx_done_err(&pxmitbuf
->sctx
, RTW_SCTX_DONE_UNKNOWN
);
409 static u32
xmitframe_need_length(struct xmit_frame
*pxmitframe
)
411 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
415 /* no consider fragement */
416 len
= pattrib
->hdrlen
+ pattrib
->iv_len
+
417 SNAP_SIZE
+ sizeof(u16
) +
419 ((pattrib
->bswenc
) ? pattrib
->icv_len
: 0);
421 if (pattrib
->encrypt
== _TKIP_
)
427 s32
rtl8188eu_xmitframe_complete(struct adapter
*adapt
, struct xmit_priv
*pxmitpriv
)
429 struct hal_data_8188e
*haldata
= GET_HAL_DATA(adapt
);
430 struct xmit_frame
*pxmitframe
= NULL
;
431 struct xmit_frame
*pfirstframe
= NULL
;
432 struct xmit_buf
*pxmitbuf
;
434 /* aggregate variable */
435 struct hw_xmit
*phwxmit
;
436 struct sta_info
*psta
= NULL
;
437 struct tx_servq
*ptxservq
= NULL
;
439 struct list_head
*xmitframe_plist
= NULL
, *xmitframe_phead
= NULL
;
441 u32 pbuf
; /* next pkt address */
442 u32 pbuf_tail
; /* last pkt tail */
443 u32 len
; /* packet length, except TXDESC_SIZE and PKT_OFFSET */
445 u32 bulksize
= haldata
->UsbBulkOutSize
;
449 /* dump frame variable */
452 RT_TRACE(_module_rtl8192c_xmit_c_
, _drv_info_
, ("+xmitframe_complete\n"));
454 pxmitbuf
= rtw_alloc_xmitbuf(pxmitpriv
);
455 if (pxmitbuf
== NULL
)
458 /* 3 1. pick up first frame */
459 rtw_free_xmitframe(pxmitpriv
, pxmitframe
);
461 pxmitframe
= rtw_dequeue_xframe(pxmitpriv
, pxmitpriv
->hwxmits
, pxmitpriv
->hwxmit_entry
);
462 if (pxmitframe
== NULL
) {
463 /* no more xmit frame, release xmit buffer */
464 rtw_free_xmitbuf(pxmitpriv
, pxmitbuf
);
468 pxmitframe
->pxmitbuf
= pxmitbuf
;
469 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
;
470 pxmitbuf
->priv_data
= pxmitframe
;
472 pxmitframe
->agg_num
= 1; /* alloc xmitframe should assign to 1. */
473 pxmitframe
->pkt_offset
= 1; /* first frame of aggregation, reserve offset */
475 rtw_xmitframe_coalesce(adapt
, pxmitframe
->pkt
, pxmitframe
);
477 /* always return ndis_packet after rtw_xmitframe_coalesce */
478 rtw_os_xmit_complete(adapt
, pxmitframe
);
480 /* 3 2. aggregate same priority and same DA(AP or STA) frames */
481 pfirstframe
= pxmitframe
;
482 len
= xmitframe_need_length(pfirstframe
) + TXDESC_SIZE
+ (pfirstframe
->pkt_offset
*PACKET_OFFSET_SZ
);
484 pbuf
= round_up(pbuf_tail
, 8);
486 /* check pkt amount in one bulk */
489 if (pbuf
< bulkptr
) {
493 bulkptr
= ((pbuf
/ bulksize
) + 1) * bulksize
; /* round to next bulksize */
496 /* dequeue same priority packet from station tx queue */
497 psta
= pfirstframe
->attrib
.psta
;
498 switch (pfirstframe
->attrib
.priority
) {
501 ptxservq
= &(psta
->sta_xmitpriv
.bk_q
);
502 phwxmit
= pxmitpriv
->hwxmits
+ 3;
506 ptxservq
= &(psta
->sta_xmitpriv
.vi_q
);
507 phwxmit
= pxmitpriv
->hwxmits
+ 1;
511 ptxservq
= &(psta
->sta_xmitpriv
.vo_q
);
512 phwxmit
= pxmitpriv
->hwxmits
;
517 ptxservq
= &(psta
->sta_xmitpriv
.be_q
);
518 phwxmit
= pxmitpriv
->hwxmits
+ 2;
521 spin_lock_bh(&pxmitpriv
->lock
);
523 xmitframe_phead
= get_list_head(&ptxservq
->sta_pending
);
524 xmitframe_plist
= xmitframe_phead
->next
;
526 while (xmitframe_phead
!= xmitframe_plist
) {
527 pxmitframe
= container_of(xmitframe_plist
, struct xmit_frame
, list
);
528 xmitframe_plist
= xmitframe_plist
->next
;
530 pxmitframe
->agg_num
= 0; /* not first frame of aggregation */
531 pxmitframe
->pkt_offset
= 0; /* not first frame of aggregation, no need to reserve offset */
533 len
= xmitframe_need_length(pxmitframe
) + TXDESC_SIZE
+ (pxmitframe
->pkt_offset
*PACKET_OFFSET_SZ
);
535 if (round_up(pbuf
+ len
, 8) > MAX_XMITBUF_SZ
) {
536 pxmitframe
->agg_num
= 1;
537 pxmitframe
->pkt_offset
= 1;
540 list_del_init(&pxmitframe
->list
);
544 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
+ pbuf
;
546 rtw_xmitframe_coalesce(adapt
, pxmitframe
->pkt
, pxmitframe
);
547 /* always return ndis_packet after rtw_xmitframe_coalesce */
548 rtw_os_xmit_complete(adapt
, pxmitframe
);
550 /* (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz */
551 update_txdesc(pxmitframe
, pxmitframe
->buf_addr
, pxmitframe
->attrib
.last_txcmdsz
, true);
553 /* don't need xmitframe any more */
554 rtw_free_xmitframe(pxmitpriv
, pxmitframe
);
556 /* handle pointer and stop condition */
557 pbuf_tail
= pbuf
+ len
;
558 pbuf
= round_up(pbuf_tail
, 8);
560 pfirstframe
->agg_num
++;
561 if (MAX_TX_AGG_PACKET_NUMBER
== pfirstframe
->agg_num
)
564 if (pbuf
< bulkptr
) {
566 if (desc_cnt
== haldata
->UsbTxAggDescNum
)
570 bulkptr
= ((pbuf
/ bulksize
) + 1) * bulksize
;
572 } /* end while (aggregate same priority and same DA(AP or STA) frames) */
574 if (list_empty(&ptxservq
->sta_pending
.queue
))
575 list_del_init(&ptxservq
->tx_pending
);
577 spin_unlock_bh(&pxmitpriv
->lock
);
578 if ((pfirstframe
->attrib
.ether_type
!= 0x0806) &&
579 (pfirstframe
->attrib
.ether_type
!= 0x888e) &&
580 (pfirstframe
->attrib
.ether_type
!= 0x88b4) &&
581 (pfirstframe
->attrib
.dhcp_pkt
!= 1))
582 rtw_issue_addbareq_cmd(adapt
, pfirstframe
);
583 /* 3 3. update first frame txdesc */
584 if ((pbuf_tail
% bulksize
) == 0) {
585 /* remove pkt_offset */
586 pbuf_tail
-= PACKET_OFFSET_SZ
;
587 pfirstframe
->buf_addr
+= PACKET_OFFSET_SZ
;
588 pfirstframe
->pkt_offset
--;
591 update_txdesc(pfirstframe
, pfirstframe
->buf_addr
, pfirstframe
->attrib
.last_txcmdsz
, true);
593 /* 3 4. write xmit buffer to USB FIFO */
594 ff_hwaddr
= rtw_get_ff_hwaddr(pfirstframe
);
595 usb_write_port(adapt
, ff_hwaddr
, pbuf_tail
, (u8
*)pxmitbuf
);
597 /* 3 5. update statisitc */
598 pbuf_tail
-= (pfirstframe
->agg_num
* TXDESC_SIZE
);
599 pbuf_tail
-= (pfirstframe
->pkt_offset
* PACKET_OFFSET_SZ
);
601 rtw_count_tx_stats(adapt
, pfirstframe
, pbuf_tail
);
603 rtw_free_xmitframe(pxmitpriv
, pfirstframe
);
608 static s32
xmitframe_direct(struct adapter
*adapt
, struct xmit_frame
*pxmitframe
)
612 res
= rtw_xmitframe_coalesce(adapt
, pxmitframe
->pkt
, pxmitframe
);
614 rtw_dump_xframe(adapt
, pxmitframe
);
616 DBG_88E("==> %s xmitframe_coalsece failed\n", __func__
);
622 * true dump packet directly
623 * false enqueue packet
625 s32
rtw_hal_xmit(struct adapter
*adapt
, struct xmit_frame
*pxmitframe
)
628 struct xmit_buf
*pxmitbuf
= NULL
;
629 struct xmit_priv
*pxmitpriv
= &adapt
->xmitpriv
;
630 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
631 struct mlme_priv
*pmlmepriv
= &adapt
->mlmepriv
;
633 spin_lock_bh(&pxmitpriv
->lock
);
635 if (rtw_txframes_sta_ac_pending(adapt
, pattrib
) > 0)
638 if (check_fwstate(pmlmepriv
, _FW_UNDER_SURVEY
|_FW_UNDER_LINKING
) == true)
641 pxmitbuf
= rtw_alloc_xmitbuf(pxmitpriv
);
645 spin_unlock_bh(&pxmitpriv
->lock
);
647 pxmitframe
->pxmitbuf
= pxmitbuf
;
648 pxmitframe
->buf_addr
= pxmitbuf
->pbuf
;
649 pxmitbuf
->priv_data
= pxmitframe
;
651 if (xmitframe_direct(adapt
, pxmitframe
) != _SUCCESS
) {
652 rtw_free_xmitbuf(pxmitpriv
, pxmitbuf
);
653 rtw_free_xmitframe(pxmitpriv
, pxmitframe
);
659 res
= rtw_xmitframe_enqueue(adapt
, pxmitframe
);
660 spin_unlock_bh(&pxmitpriv
->lock
);
662 if (res
!= _SUCCESS
) {
663 RT_TRACE(_module_xmit_osdep_c_
, _drv_err_
, ("pre_xmitframe: enqueue xmitframe fail\n"));
664 rtw_free_xmitframe(pxmitpriv
, pxmitframe
);
666 /* Trick, make the statistics correct */
667 pxmitpriv
->tx_pkts
--;
668 pxmitpriv
->tx_drop
++;
675 s32
rtw_hal_mgnt_xmit(struct adapter
*adapt
, struct xmit_frame
*pmgntframe
)
677 struct xmit_priv
*xmitpriv
= &adapt
->xmitpriv
;
679 rtl88eu_mon_xmit_hook(adapt
->pmondev
, pmgntframe
, xmitpriv
->frag_len
);
680 return rtw_dump_xframe(adapt
, pmgntframe
);