rtl8188eu_xmit.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  4. *
  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.
  8. *
  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
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. *
  19. ******************************************************************************/
  20. #define _RTL8188E_XMIT_C_
  21. #include <osdep_service.h>
  22. #include <drv_types.h>
  23. #include <mon.h>
  24. #include <wifi.h>
  25. #include <osdep_intf.h>
  26. #include <usb_ops_linux.h>
  27. #include <rtl8188e_hal.h>
  28. s32 rtl8188eu_init_xmit_priv(struct adapter *adapt)
  29. {
  30. struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
  31. tasklet_init(&pxmitpriv->xmit_tasklet,
  32. (void(*)(unsigned long))rtl8188eu_xmit_tasklet,
  33. (unsigned long)adapt);
  34. return _SUCCESS;
  35. }
  36. static u8 urb_zero_packet_chk(struct adapter *adapt, int sz)
  37. {
  38. u8 set_tx_desc_offset;
  39. struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
  40. set_tx_desc_offset = (((sz + TXDESC_SIZE) % haldata->UsbBulkOutSize) == 0) ? 1 : 0;
  41. return set_tx_desc_offset;
  42. }
  43. static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
  44. {
  45. u16 *usptr = (u16 *)ptxdesc;
  46. u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
  47. u32 index;
  48. u16 checksum = 0;
  49. /* Clear first */
  50. ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
  51. for (index = 0; index < count; index++)
  52. checksum = checksum ^ le16_to_cpu(*(__le16 *)(usptr + index));
  53. ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff & checksum);
  54. }
  55. /* Description: In normal chip, we should send some packet to Hw which will be used by Fw */
  56. /* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */
  57. /* Fw can tell Hw to send these packet derectly. */
  58. void rtl8188e_fill_fake_txdesc(struct adapter *adapt, u8 *desc, u32 BufferLen, u8 ispspoll, u8 is_btqosnull)
  59. {
  60. struct tx_desc *ptxdesc;
  61. /* Clear all status */
  62. ptxdesc = (struct tx_desc *)desc;
  63. memset(desc, 0, TXDESC_SIZE);
  64. /* offset 0 */
  65. ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); /* own, bFirstSeg, bLastSeg; */
  66. ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); /* 32 bytes for TX Desc */
  67. ptxdesc->txdw0 |= cpu_to_le32(BufferLen&0x0000ffff); /* Buffer size + command header */
  68. /* offset 4 */
  69. ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT<<QSEL_SHT)&0x00001f00); /* Fixed queue of Mgnt queue */
  70. /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */
  71. if (ispspoll) {
  72. ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
  73. } else {
  74. ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); /* Hw set sequence number */
  75. ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
  76. }
  77. if (is_btqosnull)
  78. ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */
  79. /* offset 16 */
  80. ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
  81. /* USB interface drop packet if the checksum of descriptor isn't correct. */
  82. /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
  83. rtl8188eu_cal_txdesc_chksum(ptxdesc);
  84. }
  85. static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
  86. {
  87. if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
  88. switch (pattrib->encrypt) {
  89. /* SEC_TYPE : 0:NO_ENC,1:WEP40/TKIP,2:WAPI,3:AES */
  90. case _WEP40_:
  91. case _WEP104_:
  92. ptxdesc->txdw1 |= cpu_to_le32((0x01<<SEC_TYPE_SHT)&0x00c00000);
  93. ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
  94. break;
  95. case _TKIP_:
  96. case _TKIP_WTMIC_:
  97. ptxdesc->txdw1 |= cpu_to_le32((0x01<<SEC_TYPE_SHT)&0x00c00000);
  98. ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
  99. break;
  100. case _AES_:
  101. ptxdesc->txdw1 |= cpu_to_le32((0x03<<SEC_TYPE_SHT)&0x00c00000);
  102. ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
  103. break;
  104. case _NO_PRIVACY_:
  105. default:
  106. break;
  107. }
  108. }
  109. }
  110. static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw)
  111. {
  112. switch (pattrib->vcs_mode) {
  113. case RTS_CTS:
  114. *pdw |= cpu_to_le32(RTS_EN);
  115. break;
  116. case CTS_TO_SELF:
  117. *pdw |= cpu_to_le32(CTS_2_SELF);
  118. break;
  119. case NONE_VCS:
  120. default:
  121. break;
  122. }
  123. if (pattrib->vcs_mode) {
  124. *pdw |= cpu_to_le32(HW_RTS_EN);
  125. /* Set RTS BW */
  126. if (pattrib->ht_en) {
  127. *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
  128. if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
  129. *pdw |= cpu_to_le32((0x01 << 28) & 0x30000000);
  130. else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
  131. *pdw |= cpu_to_le32((0x02 << 28) & 0x30000000);
  132. else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
  133. *pdw |= 0;
  134. else
  135. *pdw |= cpu_to_le32((0x03 << 28) & 0x30000000);
  136. }
  137. }
  138. }
  139. static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw)
  140. {
  141. if (pattrib->ht_en) {
  142. *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
  143. if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
  144. *pdw |= cpu_to_le32((0x01 << DATA_SC_SHT) & 0x003f0000);
  145. else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
  146. *pdw |= cpu_to_le32((0x02 << DATA_SC_SHT) & 0x003f0000);
  147. else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
  148. *pdw |= 0;
  149. else
  150. *pdw |= cpu_to_le32((0x03 << DATA_SC_SHT) & 0x003f0000);
  151. }
  152. }
  153. static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
  154. {
  155. int pull = 0;
  156. uint qsel;
  157. u8 data_rate, pwr_status, offset;
  158. struct adapter *adapt = pxmitframe->padapter;
  159. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  160. struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
  161. struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
  162. struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
  163. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  164. int bmcst = IS_MCAST(pattrib->ra);
  165. if (adapt->registrypriv.mp_mode == 0) {
  166. if ((!bagg_pkt) && (urb_zero_packet_chk(adapt, sz) == 0)) {
  167. ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
  168. pull = 1;
  169. }
  170. }
  171. memset(ptxdesc, 0, sizeof(struct tx_desc));
  172. /* 4 offset 0 */
  173. ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
  174. ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);/* update TXPKTSIZE */
  175. offset = TXDESC_SIZE + OFFSET_SZ;
  176. ptxdesc->txdw0 |= cpu_to_le32(((offset) << OFFSET_SHT) & 0x00ff0000);/* 32 bytes for TX Desc */
  177. if (bmcst)
  178. ptxdesc->txdw0 |= cpu_to_le32(BMC);
  179. if (adapt->registrypriv.mp_mode == 0) {
  180. if (!bagg_pkt) {
  181. if ((pull) && (pxmitframe->pkt_offset > 0))
  182. pxmitframe->pkt_offset = pxmitframe->pkt_offset - 1;
  183. }
  184. }
  185. /* pkt_offset, unit:8 bytes padding */
  186. if (pxmitframe->pkt_offset > 0)
  187. ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
  188. /* driver uses rate */
  189. ptxdesc->txdw4 |= cpu_to_le32(USERATE);/* rate control always by driver */
  190. if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) {
  191. /* offset 4 */
  192. ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3F);
  193. qsel = (uint)(pattrib->qsel & 0x0000001f);
  194. ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
  195. ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000);
  196. fill_txdesc_sectype(pattrib, ptxdesc);
  197. if (pattrib->ampdu_en) {
  198. ptxdesc->txdw2 |= cpu_to_le32(AGG_EN);/* AGG EN */
  199. ptxdesc->txdw6 = cpu_to_le32(0x6666f800);
  200. } else {
  201. ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */
  202. }
  203. /* offset 8 */
  204. /* offset 12 */
  205. ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000);
  206. /* offset 16 , offset 20 */
  207. if (pattrib->qos_en)
  208. ptxdesc->txdw4 |= cpu_to_le32(QOS);/* QoS */
  209. /* offset 20 */
  210. if (pxmitframe->agg_num > 1)
  211. ptxdesc->txdw5 |= cpu_to_le32((pxmitframe->agg_num << USB_TXAGG_NUM_SHT) & 0xFF000000);
  212. if ((pattrib->ether_type != 0x888e) &&
  213. (pattrib->ether_type != 0x0806) &&
  214. (pattrib->ether_type != 0x88b4) &&
  215. (pattrib->dhcp_pkt != 1)) {
  216. /* Non EAP & ARP & DHCP type data packet */
  217. fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
  218. fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
  219. ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate=24M */
  220. ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */
  221. if (pattrib->ht_en) {
  222. if (ODM_RA_GetShortGI_8188E(&haldata->odmpriv, pattrib->mac_id))
  223. ptxdesc->txdw5 |= cpu_to_le32(SGI);/* SGI */
  224. }
  225. data_rate = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, pattrib->mac_id);
  226. ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F);
  227. pwr_status = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, pattrib->mac_id);
  228. ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT);
  229. } else {
  230. /* EAP data packet and ARP packet and DHCP. */
  231. /* Use the 1M data rate to send the EAP/ARP packet. */
  232. /* This will maybe make the handshake smooth. */
  233. ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */
  234. if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
  235. ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */
  236. ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
  237. }
  238. } else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) {
  239. /* offset 4 */
  240. ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3f);
  241. qsel = (uint)(pattrib->qsel&0x0000001f);
  242. ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
  243. ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000f0000);
  244. /* offset 8 */
  245. /* CCX-TXRPT ack for xmit mgmt frames. */
  246. if (pxmitframe->ack_report)
  247. ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
  248. /* offset 12 */
  249. ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0FFF0000);
  250. /* offset 20 */
  251. ptxdesc->txdw5 |= cpu_to_le32(RTY_LMT_EN);/* retry limit enable */
  252. if (pattrib->retry_ctrl)
  253. ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */
  254. else
  255. ptxdesc->txdw5 |= cpu_to_le32(0x00300000);/* retry limit = 12 */
  256. ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
  257. } else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
  258. DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
  259. } else {
  260. DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
  261. /* offset 4 */
  262. ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f);/* CAM_ID(MAC_ID) */
  263. ptxdesc->txdw1 |= cpu_to_le32((6 << RATE_ID_SHT) & 0x000f0000);/* raid */
  264. /* offset 8 */
  265. /* offset 12 */
  266. ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0fff0000);
  267. /* offset 20 */
  268. ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
  269. }
  270. /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
  271. /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */
  272. /* mgnt frame should be controlled by Hw because Fw will also send null data */
  273. /* which we cannot control when Fw LPS enable. */
  274. /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
  275. /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
  276. /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */
  277. /* 2010.06.23. Added by tynli. */
  278. if (!pattrib->qos_en) {
  279. ptxdesc->txdw3 |= cpu_to_le32(EN_HWSEQ); /* Hw set sequence number */
  280. ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */
  281. }
  282. rtl88eu_dm_set_tx_ant_by_tx_info(&haldata->odmpriv, pmem,
  283. pattrib->mac_id);
  284. rtl8188eu_cal_txdesc_chksum(ptxdesc);
  285. _dbg_dump_tx_info(adapt, pxmitframe->frame_tag, ptxdesc);
  286. return pull;
  287. }
  288. /* for non-agg data frame or management frame */
  289. static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
  290. {
  291. s32 ret = _SUCCESS;
  292. s32 inner_ret = _SUCCESS;
  293. int t, sz, w_sz, pull = 0;
  294. u8 *mem_addr;
  295. u32 ff_hwaddr;
  296. struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
  297. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  298. struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
  299. struct security_priv *psecuritypriv = &adapt->securitypriv;
  300. if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
  301. (pxmitframe->attrib.ether_type != 0x0806) &&
  302. (pxmitframe->attrib.ether_type != 0x888e) &&
  303. (pxmitframe->attrib.ether_type != 0x88b4) &&
  304. (pxmitframe->attrib.dhcp_pkt != 1))
  305. rtw_issue_addbareq_cmd(adapt, pxmitframe);
  306. mem_addr = pxmitframe->buf_addr;
  307. RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));
  308. for (t = 0; t < pattrib->nr_frags; t++) {
  309. if (inner_ret != _SUCCESS && ret == _SUCCESS)
  310. ret = _FAIL;
  311. if (t != (pattrib->nr_frags - 1)) {
  312. RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("pattrib->nr_frags=%d\n", pattrib->nr_frags));
  313. sz = pxmitpriv->frag_len;
  314. sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);
  315. } else {
  316. /* no frag */
  317. sz = pattrib->last_txcmdsz;
  318. }
  319. pull = update_txdesc(pxmitframe, mem_addr, sz, false);
  320. if (pull) {
  321. mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */
  322. pxmitframe->buf_addr = mem_addr;
  323. w_sz = sz + TXDESC_SIZE;
  324. } else {
  325. w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
  326. }
  327. ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
  328. inner_ret = usb_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf);
  329. rtw_count_tx_stats(adapt, pxmitframe, sz);
  330. RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_write_port, w_sz=%d\n", w_sz));
  331. mem_addr += w_sz;
  332. mem_addr = (u8 *)round_up((size_t)mem_addr, 4);
  333. }
  334. rtw_free_xmitframe(pxmitpriv, pxmitframe);
  335. if (ret != _SUCCESS)
  336. rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
  337. return ret;
  338. }
  339. static u32 xmitframe_need_length(struct xmit_frame *pxmitframe)
  340. {
  341. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  342. u32 len = 0;
  343. /* no consider fragement */
  344. len = pattrib->hdrlen + pattrib->iv_len +
  345. SNAP_SIZE + sizeof(u16) +
  346. pattrib->pktlen +
  347. ((pattrib->bswenc) ? pattrib->icv_len : 0);
  348. if (pattrib->encrypt == _TKIP_)
  349. len += 8;
  350. return len;
  351. }
  352. s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
  353. {
  354. struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
  355. struct xmit_frame *pxmitframe = NULL;
  356. struct xmit_frame *pfirstframe = NULL;
  357. /* aggregate variable */
  358. struct hw_xmit *phwxmit;
  359. struct sta_info *psta = NULL;
  360. struct tx_servq *ptxservq = NULL;
  361. struct list_head *xmitframe_plist = NULL, *xmitframe_phead = NULL;
  362. u32 pbuf; /* next pkt address */
  363. u32 pbuf_tail; /* last pkt tail */
  364. u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */
  365. u32 bulksize = haldata->UsbBulkOutSize;
  366. u8 desc_cnt;
  367. u32 bulkptr;
  368. /* dump frame variable */
  369. u32 ff_hwaddr;
  370. RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n"));
  371. /* check xmitbuffer is ok */
  372. if (pxmitbuf == NULL) {
  373. pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
  374. if (pxmitbuf == NULL)
  375. return false;
  376. }
  377. /* 3 1. pick up first frame */
  378. do {
  379. rtw_free_xmitframe(pxmitpriv, pxmitframe);
  380. pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
  381. if (pxmitframe == NULL) {
  382. /* no more xmit frame, release xmit buffer */
  383. rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
  384. return false;
  385. }
  386. pxmitframe->pxmitbuf = pxmitbuf;
  387. pxmitframe->buf_addr = pxmitbuf->pbuf;
  388. pxmitbuf->priv_data = pxmitframe;
  389. pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */
  390. pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */
  391. rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
  392. /* always return ndis_packet after rtw_xmitframe_coalesce */
  393. rtw_os_xmit_complete(adapt, pxmitframe);
  394. break;
  395. } while (1);
  396. /* 3 2. aggregate same priority and same DA(AP or STA) frames */
  397. pfirstframe = pxmitframe;
  398. len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset*PACKET_OFFSET_SZ);
  399. pbuf_tail = len;
  400. pbuf = round_up(pbuf_tail, 8);
  401. /* check pkt amount in one bulk */
  402. desc_cnt = 0;
  403. bulkptr = bulksize;
  404. if (pbuf < bulkptr) {
  405. desc_cnt++;
  406. } else {
  407. desc_cnt = 0;
  408. bulkptr = ((pbuf / bulksize) + 1) * bulksize; /* round to next bulksize */
  409. }
  410. /* dequeue same priority packet from station tx queue */
  411. psta = pfirstframe->attrib.psta;
  412. switch (pfirstframe->attrib.priority) {
  413. case 1:
  414. case 2:
  415. ptxservq = &(psta->sta_xmitpriv.bk_q);
  416. phwxmit = pxmitpriv->hwxmits + 3;
  417. break;
  418. case 4:
  419. case 5:
  420. ptxservq = &(psta->sta_xmitpriv.vi_q);
  421. phwxmit = pxmitpriv->hwxmits + 1;
  422. break;
  423. case 6:
  424. case 7:
  425. ptxservq = &(psta->sta_xmitpriv.vo_q);
  426. phwxmit = pxmitpriv->hwxmits;
  427. break;
  428. case 0:
  429. case 3:
  430. default:
  431. ptxservq = &(psta->sta_xmitpriv.be_q);
  432. phwxmit = pxmitpriv->hwxmits + 2;
  433. break;
  434. }
  435. spin_lock_bh(&pxmitpriv->lock);
  436. xmitframe_phead = get_list_head(&ptxservq->sta_pending);
  437. xmitframe_plist = xmitframe_phead->next;
  438. while (xmitframe_phead != xmitframe_plist) {
  439. pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
  440. xmitframe_plist = xmitframe_plist->next;
  441. pxmitframe->agg_num = 0; /* not first frame of aggregation */
  442. pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */
  443. len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset*PACKET_OFFSET_SZ);
  444. if (round_up(pbuf + len, 8) > MAX_XMITBUF_SZ) {
  445. pxmitframe->agg_num = 1;
  446. pxmitframe->pkt_offset = 1;
  447. break;
  448. }
  449. list_del_init(&pxmitframe->list);
  450. ptxservq->qcnt--;
  451. phwxmit->accnt--;
  452. pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf;
  453. rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
  454. /* always return ndis_packet after rtw_xmitframe_coalesce */
  455. rtw_os_xmit_complete(adapt, pxmitframe);
  456. /* (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz */
  457. update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, true);
  458. /* don't need xmitframe any more */
  459. rtw_free_xmitframe(pxmitpriv, pxmitframe);
  460. /* handle pointer and stop condition */
  461. pbuf_tail = pbuf + len;
  462. pbuf = round_up(pbuf_tail, 8);
  463. pfirstframe->agg_num++;
  464. if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num)
  465. break;
  466. if (pbuf < bulkptr) {
  467. desc_cnt++;
  468. if (desc_cnt == haldata->UsbTxAggDescNum)
  469. break;
  470. } else {
  471. desc_cnt = 0;
  472. bulkptr = ((pbuf / bulksize) + 1) * bulksize;
  473. }
  474. } /* end while (aggregate same priority and same DA(AP or STA) frames) */
  475. if (list_empty(&ptxservq->sta_pending.queue))
  476. list_del_init(&ptxservq->tx_pending);
  477. spin_unlock_bh(&pxmitpriv->lock);
  478. if ((pfirstframe->attrib.ether_type != 0x0806) &&
  479. (pfirstframe->attrib.ether_type != 0x888e) &&
  480. (pfirstframe->attrib.ether_type != 0x88b4) &&
  481. (pfirstframe->attrib.dhcp_pkt != 1))
  482. rtw_issue_addbareq_cmd(adapt, pfirstframe);
  483. /* 3 3. update first frame txdesc */
  484. if ((pbuf_tail % bulksize) == 0) {
  485. /* remove pkt_offset */
  486. pbuf_tail -= PACKET_OFFSET_SZ;
  487. pfirstframe->buf_addr += PACKET_OFFSET_SZ;
  488. pfirstframe->pkt_offset--;
  489. }
  490. update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, true);
  491. /* 3 4. write xmit buffer to USB FIFO */
  492. ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe);
  493. usb_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf);
  494. /* 3 5. update statisitc */
  495. pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE);
  496. pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ);
  497. rtw_count_tx_stats(adapt, pfirstframe, pbuf_tail);
  498. rtw_free_xmitframe(pxmitpriv, pfirstframe);
  499. return true;
  500. }
  501. static s32 xmitframe_direct(struct adapter *adapt, struct xmit_frame *pxmitframe)
  502. {
  503. s32 res = _SUCCESS;
  504. res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
  505. if (res == _SUCCESS)
  506. rtw_dump_xframe(adapt, pxmitframe);
  507. else
  508. DBG_88E("==> %s xmitframe_coalsece failed\n", __func__);
  509. return res;
  510. }
  511. /*
  512. * Return
  513. * true dump packet directly
  514. * false enqueue packet
  515. */
  516. static s32 pre_xmitframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
  517. {
  518. s32 res;
  519. struct xmit_buf *pxmitbuf = NULL;
  520. struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
  521. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  522. struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
  523. spin_lock_bh(&pxmitpriv->lock);
  524. if (rtw_txframes_sta_ac_pending(adapt, pattrib) > 0)
  525. goto enqueue;
  526. if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
  527. goto enqueue;
  528. pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
  529. if (!pxmitbuf)
  530. goto enqueue;
  531. spin_unlock_bh(&pxmitpriv->lock);
  532. pxmitframe->pxmitbuf = pxmitbuf;
  533. pxmitframe->buf_addr = pxmitbuf->pbuf;
  534. pxmitbuf->priv_data = pxmitframe;
  535. if (xmitframe_direct(adapt, pxmitframe) != _SUCCESS) {
  536. rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
  537. rtw_free_xmitframe(pxmitpriv, pxmitframe);
  538. }
  539. return true;
  540. enqueue:
  541. res = rtw_xmitframe_enqueue(adapt, pxmitframe);
  542. spin_unlock_bh(&pxmitpriv->lock);
  543. if (res != _SUCCESS) {
  544. RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("pre_xmitframe: enqueue xmitframe fail\n"));
  545. rtw_free_xmitframe(pxmitpriv, pxmitframe);
  546. /* Trick, make the statistics correct */
  547. pxmitpriv->tx_pkts--;
  548. pxmitpriv->tx_drop++;
  549. return true;
  550. }
  551. return false;
  552. }
  553. s32 rtl8188eu_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe)
  554. {
  555. struct xmit_priv *xmitpriv = &adapt->xmitpriv;
  556. rtl88eu_mon_xmit_hook(adapt->pmondev, pmgntframe, xmitpriv->frag_len);
  557. return rtw_dump_xframe(adapt, pmgntframe);
  558. }
  559. /*
  560. * Return
  561. * true dump packet directly ok
  562. * false temporary can't transmit packets to hardware
  563. */
  564. s32 rtl8188eu_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
  565. {
  566. return pre_xmitframe(adapt, pxmitframe);
  567. }