rtl8712_xmit.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /******************************************************************************
  2. * rtl8712_xmit.c
  3. *
  4. * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
  5. * Linux device driver for RTL8192SU
  6. *
  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.
  10. *
  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
  14. * more details.
  15. *
  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
  19. *
  20. * Modifications for inclusion into the Linux staging tree are
  21. * Copyright(c) 2010 Larry Finger. All rights reserved.
  22. *
  23. * Contact information:
  24. * WLAN FAE <wlanfae@realtek.com>
  25. * Larry Finger <Larry.Finger@lwfinger.net>
  26. *
  27. ******************************************************************************/
  28. #define _RTL8712_XMIT_C_
  29. #include "osdep_service.h"
  30. #include "drv_types.h"
  31. #include "wifi.h"
  32. #include "osdep_intf.h"
  33. #include "usb_ops.h"
  34. static void dump_xframe(struct _adapter *padapter,
  35. struct xmit_frame *pxmitframe);
  36. static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz);
  37. sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag)
  38. {
  39. phw_txqueue->ac_tag = ac_tag;
  40. switch (ac_tag) {
  41. case BE_QUEUE_INX:
  42. phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ;
  43. break;
  44. case BK_QUEUE_INX:
  45. phw_txqueue->ff_hwaddr = RTL8712_DMA_BKQ;
  46. break;
  47. case VI_QUEUE_INX:
  48. phw_txqueue->ff_hwaddr = RTL8712_DMA_VIQ;
  49. break;
  50. case VO_QUEUE_INX:
  51. phw_txqueue->ff_hwaddr = RTL8712_DMA_VOQ;
  52. break;
  53. case BMC_QUEUE_INX:
  54. phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ;
  55. break;
  56. }
  57. return _SUCCESS;
  58. }
  59. int r8712_txframes_sta_ac_pending(struct _adapter *padapter,
  60. struct pkt_attrib *pattrib)
  61. {
  62. struct sta_info *psta;
  63. struct tx_servq *ptxservq;
  64. int priority = pattrib->priority;
  65. psta = pattrib->psta;
  66. switch (priority) {
  67. case 1:
  68. case 2:
  69. ptxservq = &(psta->sta_xmitpriv.bk_q);
  70. break;
  71. case 4:
  72. case 5:
  73. ptxservq = &(psta->sta_xmitpriv.vi_q);
  74. break;
  75. case 6:
  76. case 7:
  77. ptxservq = &(psta->sta_xmitpriv.vo_q);
  78. break;
  79. case 0:
  80. case 3:
  81. default:
  82. ptxservq = &(psta->sta_xmitpriv.be_q);
  83. break;
  84. }
  85. return ptxservq->qcnt;
  86. }
  87. static u32 get_ff_hwaddr(struct xmit_frame *pxmitframe)
  88. {
  89. u32 addr = 0;
  90. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  91. struct _adapter *padapter = pxmitframe->padapter;
  92. struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
  93. if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
  94. addr = RTL8712_DMA_H2CCMD;
  95. } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
  96. addr = RTL8712_DMA_MGTQ;
  97. } else if (pdvobj->nr_endpoint == 6) {
  98. switch (pattrib->priority) {
  99. case 0:
  100. case 3:
  101. addr = RTL8712_DMA_BEQ;
  102. break;
  103. case 1:
  104. case 2:
  105. addr = RTL8712_DMA_BKQ;
  106. break;
  107. case 4:
  108. case 5:
  109. addr = RTL8712_DMA_VIQ;
  110. break;
  111. case 6:
  112. case 7:
  113. addr = RTL8712_DMA_VOQ;
  114. break;
  115. case 0x10:
  116. case 0x11:
  117. case 0x12:
  118. case 0x13:
  119. addr = RTL8712_DMA_H2CCMD;
  120. break;
  121. default:
  122. addr = RTL8712_DMA_BEQ;
  123. break;
  124. }
  125. } else if (pdvobj->nr_endpoint == 4) {
  126. switch (pattrib->qsel) {
  127. case 0:
  128. case 3:
  129. case 1:
  130. case 2:
  131. addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/
  132. break;
  133. case 4:
  134. case 5:
  135. case 6:
  136. case 7:
  137. addr = RTL8712_DMA_VOQ;/*RTL8712_EP_HI;*/
  138. break;
  139. case 0x10:
  140. case 0x11:
  141. case 0x12:
  142. case 0x13:
  143. addr = RTL8712_DMA_H2CCMD;
  144. break;
  145. default:
  146. addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/
  147. break;
  148. }
  149. }
  150. return addr;
  151. }
  152. static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv,
  153. struct hw_xmit *phwxmit,
  154. struct tx_servq *ptxservq,
  155. struct __queue *pframe_queue)
  156. {
  157. struct list_head *xmitframe_plist, *xmitframe_phead;
  158. struct xmit_frame *pxmitframe = NULL;
  159. xmitframe_phead = &pframe_queue->queue;
  160. xmitframe_plist = xmitframe_phead->next;
  161. if (!end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
  162. pxmitframe = LIST_CONTAINOR(xmitframe_plist,
  163. struct xmit_frame, list);
  164. list_del_init(&pxmitframe->list);
  165. ptxservq->qcnt--;
  166. phwxmit->txcmdcnt++;
  167. }
  168. return pxmitframe;
  169. }
  170. static struct xmit_frame *dequeue_xframe_ex(struct xmit_priv *pxmitpriv,
  171. struct hw_xmit *phwxmit_i, sint entry)
  172. {
  173. unsigned long irqL0;
  174. struct list_head *sta_plist, *sta_phead;
  175. struct hw_xmit *phwxmit;
  176. struct tx_servq *ptxservq = NULL;
  177. struct __queue *pframe_queue = NULL;
  178. struct xmit_frame *pxmitframe = NULL;
  179. int i, inx[4];
  180. int j, acirp_cnt[4];
  181. /*entry indx: 0->vo, 1->vi, 2->be, 3->bk.*/
  182. inx[0] = 0; acirp_cnt[0] = pxmitpriv->voq_cnt;
  183. inx[1] = 1; acirp_cnt[1] = pxmitpriv->viq_cnt;
  184. inx[2] = 2; acirp_cnt[2] = pxmitpriv->beq_cnt;
  185. inx[3] = 3; acirp_cnt[3] = pxmitpriv->bkq_cnt;
  186. for (i = 0; i < 4; i++) {
  187. for (j = i + 1; j < 4; j++) {
  188. if (acirp_cnt[j] < acirp_cnt[i]) {
  189. swap(acirp_cnt[i], acirp_cnt[j]);
  190. swap(inx[i], inx[j]);
  191. }
  192. }
  193. }
  194. spin_lock_irqsave(&pxmitpriv->lock, irqL0);
  195. for (i = 0; i < entry; i++) {
  196. phwxmit = phwxmit_i + inx[i];
  197. sta_phead = &phwxmit->sta_queue->queue;
  198. sta_plist = sta_phead->next;
  199. while (!end_of_queue_search(sta_phead, sta_plist)) {
  200. ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq,
  201. tx_pending);
  202. pframe_queue = &ptxservq->sta_pending;
  203. pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit,
  204. ptxservq, pframe_queue);
  205. if (pxmitframe) {
  206. phwxmit->accnt--;
  207. goto exit_dequeue_xframe_ex;
  208. }
  209. sta_plist = sta_plist->next;
  210. /*Remove sta node when there are no pending packets.*/
  211. if (list_empty(&pframe_queue->queue)) {
  212. /* must be done after sta_plist->next
  213. * and before break
  214. */
  215. list_del_init(&ptxservq->tx_pending);
  216. }
  217. }
  218. }
  219. exit_dequeue_xframe_ex:
  220. spin_unlock_irqrestore(&pxmitpriv->lock, irqL0);
  221. return pxmitframe;
  222. }
  223. void r8712_do_queue_select(struct _adapter *padapter,
  224. struct pkt_attrib *pattrib)
  225. {
  226. unsigned int qsel = 0;
  227. struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
  228. if (pdvobj->nr_endpoint == 6) {
  229. qsel = (unsigned int) pattrib->priority;
  230. } else if (pdvobj->nr_endpoint == 4) {
  231. qsel = (unsigned int) pattrib->priority;
  232. if (qsel == 0 || qsel == 3)
  233. qsel = 3;
  234. else if (qsel == 1 || qsel == 2)
  235. qsel = 1;
  236. else if (qsel == 4 || qsel == 5)
  237. qsel = 5;
  238. else if (qsel == 6 || qsel == 7)
  239. qsel = 7;
  240. else
  241. qsel = 3;
  242. }
  243. pattrib->qsel = qsel;
  244. }
  245. #ifdef CONFIG_R8712_TX_AGGR
  246. u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf)
  247. {
  248. struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
  249. /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/
  250. /* dw0 */
  251. ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ & 0xffff);
  252. ptx_desc->txdw0 |=
  253. cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
  254. 0x00ff0000);
  255. ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
  256. /* dw1 */
  257. ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00);
  258. return _SUCCESS;
  259. }
  260. u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf)
  261. {
  262. struct xmit_frame *pxmitframe = (struct xmit_frame *)
  263. pxmitbuf->priv_data;
  264. struct _adapter *padapter = pxmitframe->padapter;
  265. struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
  266. struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
  267. (pxmitbuf->pbuf + TXDESC_SIZE);
  268. /* Fill up Cmd Header for USB FW Tx Aggregation.*/
  269. /* dw0 */
  270. pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) |
  271. (pcmdpriv->cmd_seq << 24));
  272. pcmdpriv->cmd_seq++;
  273. return _SUCCESS;
  274. }
  275. u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf,
  276. struct xmit_frame *pxmitframe)
  277. {
  278. struct _adapter *padapter = pxmitframe->padapter;
  279. struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
  280. int last_txcmdsz = 0;
  281. int padding_sz = 0;
  282. /* 802.3->802.11 convertor */
  283. r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
  284. /* free skb struct */
  285. r8712_xmit_complete(padapter, pxmitframe);
  286. if (pxmitframe->attrib.ether_type != 0x0806) {
  287. if ((pxmitframe->attrib.ether_type != 0x888e) &&
  288. (pxmitframe->attrib.dhcp_pkt != 1)) {
  289. r8712_issue_addbareq_cmd(padapter,
  290. pxmitframe->attrib.priority);
  291. }
  292. }
  293. pxmitframe->last[0] = 1;
  294. update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr),
  295. pxmitframe->attrib.last_txcmdsz);
  296. /*padding zero */
  297. last_txcmdsz = pxmitframe->attrib.last_txcmdsz;
  298. padding_sz = (8 - (last_txcmdsz % 8));
  299. if ((last_txcmdsz % 8) != 0) {
  300. int i;
  301. for (i = 0; i < padding_sz; i++)
  302. *(pxmitframe->buf_addr + TXDESC_SIZE + last_txcmdsz +
  303. i) = 0;
  304. }
  305. /* Add the new mpdu's length */
  306. ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0 & 0xffff0000) |
  307. ((ptx_desc->txdw0 & 0x0000ffff) +
  308. ((TXDESC_SIZE + last_txcmdsz + padding_sz) &
  309. 0x0000ffff)));
  310. return _SUCCESS;
  311. }
  312. u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
  313. struct xmit_frame *pxmitframe)
  314. {
  315. /* linux complete context doesn't need to protect */
  316. pxmitframe->pxmitbuf = pxmitbuf;
  317. pxmitbuf->priv_data = pxmitframe;
  318. pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
  319. /* buffer addr assoc */
  320. pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + CMD_HDR_SZ;
  321. /*RTL8712_DMA_H2CCMD */
  322. r8712_construct_txaggr_cmd_desc(pxmitbuf);
  323. r8712_construct_txaggr_cmd_hdr(pxmitbuf);
  324. if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS)
  325. pxmitbuf->aggr_nr = 1;
  326. return _SUCCESS;
  327. }
  328. u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf,
  329. struct xmit_frame *pxmitframe)
  330. {
  331. pxmitframe->pxmitbuf = pxmitbuf;
  332. pxmitbuf->priv_data = pxmitframe;
  333. pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
  334. /* buffer addr assoc */
  335. pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE +
  336. (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
  337. if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) {
  338. r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv,
  339. pxmitframe);
  340. pxmitbuf->aggr_nr++;
  341. }
  342. return TXDESC_SIZE +
  343. (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
  344. }
  345. u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
  346. struct xmit_frame *pxmitframe)
  347. {
  348. struct _adapter *padapter = pxmitframe->padapter;
  349. struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
  350. struct tx_desc *ptxdesc = pxmitbuf->pbuf;
  351. struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
  352. (pxmitbuf->pbuf + TXDESC_SIZE);
  353. u16 total_length = (u16) (ptxdesc->txdw0 & 0xffff);
  354. /* use 1st xmitframe as media */
  355. xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
  356. pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length - CMD_HDR_SZ) &
  357. 0x0000ffff) | (pcmd_hdr->cmd_dw0 &
  358. 0xffff0000));
  359. /* urb length in cmd_dw1 */
  360. pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff)|
  361. ((total_length + TXDESC_SIZE) << 16));
  362. pxmitframe->last[0] = 1;
  363. pxmitframe->bpending[0] = false;
  364. pxmitframe->mem_addr = pxmitbuf->pbuf;
  365. if ((pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % 0x200) ==
  366. 0) || ((!pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) %
  367. 0x40) == 0))) {
  368. ptxdesc->txdw0 |= cpu_to_le32
  369. (((TXDESC_SIZE + OFFSET_SZ + 8) << OFFSET_SHT) &
  370. 0x00ff0000);
  371. /*32 bytes for TX Desc + 8 bytes pending*/
  372. } else {
  373. ptxdesc->txdw0 |= cpu_to_le32
  374. (((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
  375. 0x00ff0000);
  376. /*default = 32 bytes for TX Desc*/
  377. }
  378. r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD,
  379. total_length + TXDESC_SIZE, (u8 *)pxmitframe);
  380. return _SUCCESS;
  381. }
  382. #endif
  383. static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
  384. {
  385. uint qsel;
  386. struct _adapter *padapter = pxmitframe->padapter;
  387. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  388. struct qos_priv *pqospriv = &pmlmepriv->qospriv;
  389. struct security_priv *psecuritypriv = &padapter->securitypriv;
  390. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  391. struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
  392. struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
  393. #ifdef CONFIG_R8712_TX_AGGR
  394. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  395. #endif
  396. u8 blnSetTxDescOffset;
  397. sint bmcst = IS_MCAST(pattrib->ra);
  398. struct ht_priv *phtpriv = &pmlmepriv->htpriv;
  399. struct tx_desc txdesc_mp;
  400. memcpy(&txdesc_mp, ptxdesc, sizeof(struct tx_desc));
  401. memset(ptxdesc, 0, sizeof(struct tx_desc));
  402. /* offset 0 */
  403. ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);
  404. if (pdvobj->ishighspeed) {
  405. if (((sz + TXDESC_SIZE) % 512) == 0)
  406. blnSetTxDescOffset = 1;
  407. else
  408. blnSetTxDescOffset = 0;
  409. } else {
  410. if (((sz + TXDESC_SIZE) % 64) == 0)
  411. blnSetTxDescOffset = 1;
  412. else
  413. blnSetTxDescOffset = 0;
  414. }
  415. if (blnSetTxDescOffset) {
  416. /* 32 bytes for TX Desc + 8 bytes pending */
  417. ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ + 8) <<
  418. OFFSET_SHT) & 0x00ff0000);
  419. } else {
  420. /* default = 32 bytes for TX Desc */
  421. ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
  422. OFFSET_SHT) & 0x00ff0000);
  423. }
  424. ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
  425. if (pxmitframe->frame_tag == DATA_FRAMETAG) {
  426. /* offset 4 */
  427. ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x1f);
  428. #ifdef CONFIG_R8712_TX_AGGR
  429. /* dirty workaround, need to check if it is aggr cmd. */
  430. if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) {
  431. ptxdesc->txdw0 |= cpu_to_le32
  432. ((0x3 << TYPE_SHT) & TYPE_MSK);
  433. qsel = (uint)(pattrib->qsel & 0x0000001f);
  434. if (qsel == 2)
  435. qsel = 0;
  436. ptxdesc->txdw1 |= cpu_to_le32
  437. ((qsel << QSEL_SHT) & 0x00001f00);
  438. ptxdesc->txdw2 = cpu_to_le32
  439. ((qsel << RTS_RC_SHT) & 0x001f0000);
  440. ptxdesc->txdw6 |= cpu_to_le32
  441. ((0x5 << RSVD6_SHT) & RSVD6_MSK);
  442. } else {
  443. ptxdesc->txdw0 |= cpu_to_le32
  444. ((0x3 << TYPE_SHT) & TYPE_MSK);
  445. ptxdesc->txdw1 |= cpu_to_le32
  446. ((0x13 << QSEL_SHT) & 0x00001f00);
  447. qsel = (uint)(pattrib->qsel & 0x0000001f);
  448. if (qsel == 2)
  449. qsel = 0;
  450. ptxdesc->txdw2 = cpu_to_le32
  451. ((qsel << RTS_RC_SHT) & 0x0001f000);
  452. ptxdesc->txdw7 |= cpu_to_le32
  453. (pcmdpriv->cmd_seq << 24);
  454. pcmdpriv->cmd_seq++;
  455. }
  456. pattrib->qsel = 0x13;
  457. #else
  458. qsel = (uint)(pattrib->qsel & 0x0000001f);
  459. ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
  460. #endif
  461. if (!pqospriv->qos_option)
  462. ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/*Non-QoS*/
  463. if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
  464. switch (pattrib->encrypt) { /*SEC_TYPE*/
  465. case _WEP40_:
  466. case _WEP104_:
  467. ptxdesc->txdw1 |= cpu_to_le32((0x01 << 22) &
  468. 0x00c00000);
  469. /*KEY_ID when WEP is used;*/
  470. ptxdesc->txdw1 |= cpu_to_le32((psecuritypriv->
  471. PrivacyKeyIndex << 17) &
  472. 0x00060000);
  473. break;
  474. case _TKIP_:
  475. case _TKIP_WTMIC_:
  476. ptxdesc->txdw1 |= cpu_to_le32((0x02 << 22) &
  477. 0x00c00000);
  478. break;
  479. case _AES_:
  480. ptxdesc->txdw1 |= cpu_to_le32((0x03 << 22) &
  481. 0x00c00000);
  482. break;
  483. case _NO_PRIVACY_:
  484. default:
  485. break;
  486. }
  487. }
  488. /*offset 8*/
  489. if (bmcst)
  490. ptxdesc->txdw2 |= cpu_to_le32(BMC);
  491. /*offset 12*/
  492. /* f/w will increase the seqnum by itself, driver pass the
  493. * correct priority to fw
  494. * fw will check the correct priority for increasing the
  495. * seqnum per tid. about usb using 4-endpoint, qsel points out
  496. * the correct mapping between AC&Endpoint,
  497. * the purpose is that correct mapping lets the MAC release
  498. * the AC Queue list correctly. */
  499. ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) &
  500. 0x0fff0000);
  501. if ((pattrib->ether_type != 0x888e) &&
  502. (pattrib->ether_type != 0x0806) &&
  503. (pattrib->dhcp_pkt != 1)) {
  504. /*Not EAP & ARP type data packet*/
  505. if (phtpriv->ht_option == 1) { /*B/G/N Mode*/
  506. if (phtpriv->ampdu_enable != true)
  507. ptxdesc->txdw2 |= cpu_to_le32(BK);
  508. }
  509. } else {
  510. /* EAP data packet and ARP packet.
  511. * Use the 1M data rate to send the EAP/ARP packet.
  512. * This will maybe make the handshake smooth.
  513. */
  514. /*driver uses data rate*/
  515. ptxdesc->txdw4 = cpu_to_le32(0x80000000);
  516. ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/*1M*/
  517. }
  518. if (pattrib->pctrl == 1) { /* mp tx packets */
  519. struct tx_desc *ptxdesc_mp;
  520. ptxdesc_mp = &txdesc_mp;
  521. /* offset 8 */
  522. ptxdesc->txdw2 = cpu_to_le32(ptxdesc_mp->txdw2);
  523. if (bmcst)
  524. ptxdesc->txdw2 |= cpu_to_le32(BMC);
  525. ptxdesc->txdw2 |= cpu_to_le32(BK);
  526. /* offset 16 */
  527. ptxdesc->txdw4 = cpu_to_le32(ptxdesc_mp->txdw4);
  528. /* offset 20 */
  529. ptxdesc->txdw5 = cpu_to_le32(ptxdesc_mp->txdw5);
  530. pattrib->pctrl = 0;/* reset to zero; */
  531. }
  532. } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
  533. /* offset 4 */
  534. ptxdesc->txdw1 |= (0x05) & 0x1f;/*CAM_ID(MAC_ID), default=5;*/
  535. qsel = (uint)(pattrib->qsel & 0x0000001f);
  536. ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
  537. ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/* Non-QoS */
  538. /* offset 8 */
  539. if (bmcst)
  540. ptxdesc->txdw2 |= cpu_to_le32(BMC);
  541. /* offset 12 */
  542. /* f/w will increase the seqnum by itself, driver pass the
  543. * correct priority to fw
  544. * fw will check the correct priority for increasing the seqnum
  545. * per tid. about usb using 4-endpoint, qsel points out the
  546. * correct mapping between AC&Endpoint,
  547. * the purpose is that correct mapping let the MAC releases
  548. * the AC Queue list correctly. */
  549. ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) &
  550. 0x0fff0000);
  551. /* offset 16 */
  552. ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/
  553. /* offset 20 */
  554. ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/* gtest 1M */
  555. } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
  556. /* offset 4 */
  557. qsel = 0x13;
  558. ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
  559. } else {
  560. /* offset 4 */
  561. qsel = (uint)(pattrib->priority & 0x0000001f);
  562. ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
  563. /*offset 8*/
  564. /*offset 12*/
  565. ptxdesc->txdw3 = cpu_to_le32((pattrib->seqnum << SEQ_SHT) &
  566. 0x0fff0000);
  567. /*offset 16*/
  568. ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/
  569. /*offset 20*/
  570. ptxdesc->txdw5 = cpu_to_le32(0x001f9600);/*gtest*/
  571. }
  572. }
  573. int r8712_xmitframe_complete(struct _adapter *padapter,
  574. struct xmit_priv *pxmitpriv,
  575. struct xmit_buf *pxmitbuf)
  576. {
  577. struct hw_xmit *phwxmits;
  578. sint hwentry;
  579. struct xmit_frame *pxmitframe = NULL;
  580. #ifdef CONFIG_R8712_TX_AGGR
  581. struct xmit_frame *p2ndxmitframe = NULL;
  582. #else
  583. int res = _SUCCESS, xcnt = 0;
  584. #endif
  585. phwxmits = pxmitpriv->hwxmits;
  586. hwentry = pxmitpriv->hwxmit_entry;
  587. if (pxmitbuf == NULL) {
  588. pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv);
  589. if (!pxmitbuf)
  590. return false;
  591. #ifdef CONFIG_R8712_TX_AGGR
  592. pxmitbuf->aggr_nr = 0;
  593. #endif
  594. }
  595. /* 1st frame dequeued */
  596. pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
  597. /* need to remember the 1st frame */
  598. if (pxmitframe != NULL) {
  599. #ifdef CONFIG_R8712_TX_AGGR
  600. /* 1. dequeue 2nd frame
  601. * 2. aggr if 2nd xframe is dequeued, else dump directly
  602. */
  603. if (AGGR_NR_HIGH_BOUND > 1)
  604. p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits,
  605. hwentry);
  606. if (pxmitframe->frame_tag != DATA_FRAMETAG) {
  607. r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
  608. return false;
  609. }
  610. if (p2ndxmitframe != NULL)
  611. if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) {
  612. r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
  613. return false;
  614. }
  615. r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe);
  616. if (p2ndxmitframe != NULL) {
  617. u16 total_length;
  618. total_length = r8712_xmitframe_aggr_next(
  619. pxmitbuf, p2ndxmitframe);
  620. do {
  621. p2ndxmitframe = dequeue_xframe_ex(
  622. pxmitpriv, phwxmits, hwentry);
  623. if (p2ndxmitframe != NULL)
  624. total_length =
  625. r8712_xmitframe_aggr_next(
  626. pxmitbuf,
  627. p2ndxmitframe);
  628. else
  629. break;
  630. } while (total_length <= 0x1800 &&
  631. pxmitbuf->aggr_nr <= AGGR_NR_HIGH_BOUND);
  632. }
  633. if (pxmitbuf->aggr_nr > 0)
  634. r8712_dump_aggr_xframe(pxmitbuf, pxmitframe);
  635. #else
  636. xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
  637. if (pxmitframe->frame_tag == DATA_FRAMETAG) {
  638. if (pxmitframe->attrib.priority <= 15)
  639. res = r8712_xmitframe_coalesce(padapter,
  640. pxmitframe->pkt, pxmitframe);
  641. /* always return ndis_packet after
  642. * r8712_xmitframe_coalesce */
  643. r8712_xmit_complete(padapter, pxmitframe);
  644. }
  645. if (res == _SUCCESS)
  646. dump_xframe(padapter, pxmitframe);
  647. else
  648. r8712_free_xmitframe_ex(pxmitpriv, pxmitframe);
  649. xcnt++;
  650. #endif
  651. } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */
  652. r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
  653. return false;
  654. }
  655. return true;
  656. }
  657. static void dump_xframe(struct _adapter *padapter,
  658. struct xmit_frame *pxmitframe)
  659. {
  660. int t, sz, w_sz;
  661. u8 *mem_addr;
  662. u32 ff_hwaddr;
  663. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  664. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  665. struct security_priv *psecuritypriv = &padapter->securitypriv;
  666. if (pxmitframe->attrib.ether_type != 0x0806) {
  667. if (pxmitframe->attrib.ether_type != 0x888e)
  668. r8712_issue_addbareq_cmd(padapter, pattrib->priority);
  669. }
  670. mem_addr = pxmitframe->buf_addr;
  671. for (t = 0; t < pattrib->nr_frags; t++) {
  672. if (t != (pattrib->nr_frags - 1)) {
  673. sz = pxmitpriv->frag_len;
  674. sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 :
  675. pattrib->icv_len);
  676. pxmitframe->last[t] = 0;
  677. } else {
  678. sz = pattrib->last_txcmdsz;
  679. pxmitframe->last[t] = 1;
  680. }
  681. update_txdesc(pxmitframe, (uint *)mem_addr, sz);
  682. w_sz = sz + TXDESC_SIZE;
  683. pxmitframe->mem_addr = mem_addr;
  684. pxmitframe->bpending[t] = false;
  685. ff_hwaddr = get_ff_hwaddr(pxmitframe);
  686. #ifdef CONFIG_R8712_TX_AGGR
  687. r8712_write_port(padapter, RTL8712_DMA_H2CCMD, w_sz,
  688. (unsigned char *)pxmitframe);
  689. #else
  690. r8712_write_port(padapter, ff_hwaddr, w_sz,
  691. (unsigned char *)pxmitframe);
  692. #endif
  693. mem_addr += w_sz;
  694. mem_addr = (u8 *)RND4(((addr_t)(mem_addr)));
  695. }
  696. }
  697. int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe)
  698. {
  699. int res = _SUCCESS;
  700. res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
  701. pxmitframe->pkt = NULL;
  702. if (res == _SUCCESS)
  703. dump_xframe(padapter, pxmitframe);
  704. return res;
  705. }
  706. int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe)
  707. {
  708. if (r8712_xmit_classifier(padapter, pxmitframe) == _FAIL) {
  709. pxmitframe->pkt = NULL;
  710. return _FAIL;
  711. }
  712. return _SUCCESS;
  713. }