rtl871x_xmit.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /******************************************************************************
  2. * rtl871x_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 _RTL871X_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 const u8 P802_1H_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0xf8};
  35. static const u8 RFC1042_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0x00};
  36. static void init_hwxmits(struct hw_xmit *phwxmit, sint entry);
  37. static void alloc_hwxmits(struct _adapter *padapter);
  38. static void free_hwxmits(struct _adapter *padapter);
  39. static void _init_txservq(struct tx_servq *ptxservq)
  40. {
  41. INIT_LIST_HEAD(&ptxservq->tx_pending);
  42. _init_queue(&ptxservq->sta_pending);
  43. ptxservq->qcnt = 0;
  44. }
  45. void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
  46. {
  47. memset((unsigned char *)psta_xmitpriv, 0,
  48. sizeof(struct sta_xmit_priv));
  49. spin_lock_init(&psta_xmitpriv->lock);
  50. _init_txservq(&psta_xmitpriv->be_q);
  51. _init_txservq(&psta_xmitpriv->bk_q);
  52. _init_txservq(&psta_xmitpriv->vi_q);
  53. _init_txservq(&psta_xmitpriv->vo_q);
  54. INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
  55. INIT_LIST_HEAD(&psta_xmitpriv->apsd);
  56. }
  57. sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
  58. struct _adapter *padapter)
  59. {
  60. sint i;
  61. struct xmit_buf *pxmitbuf;
  62. struct xmit_frame *pxframe;
  63. memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv));
  64. spin_lock_init(&pxmitpriv->lock);
  65. /*
  66. Please insert all the queue initialization using _init_queue below
  67. */
  68. pxmitpriv->adapter = padapter;
  69. _init_queue(&pxmitpriv->be_pending);
  70. _init_queue(&pxmitpriv->bk_pending);
  71. _init_queue(&pxmitpriv->vi_pending);
  72. _init_queue(&pxmitpriv->vo_pending);
  73. _init_queue(&pxmitpriv->bm_pending);
  74. _init_queue(&pxmitpriv->legacy_dz_queue);
  75. _init_queue(&pxmitpriv->apsd_queue);
  76. _init_queue(&pxmitpriv->free_xmit_queue);
  77. /*
  78. Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
  79. and initialize free_xmit_frame below.
  80. Please also apply free_txobj to link_up all the xmit_frames...
  81. */
  82. pxmitpriv->pallocated_frame_buf = kmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4,
  83. GFP_ATOMIC);
  84. if (pxmitpriv->pallocated_frame_buf == NULL) {
  85. pxmitpriv->pxmit_frame_buf = NULL;
  86. return _FAIL;
  87. }
  88. pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 -
  89. ((addr_t) (pxmitpriv->pallocated_frame_buf) & 3);
  90. pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;
  91. for (i = 0; i < NR_XMITFRAME; i++) {
  92. INIT_LIST_HEAD(&(pxframe->list));
  93. pxframe->padapter = padapter;
  94. pxframe->frame_tag = DATA_FRAMETAG;
  95. pxframe->pkt = NULL;
  96. pxframe->buf_addr = NULL;
  97. pxframe->pxmitbuf = NULL;
  98. list_add_tail(&(pxframe->list),
  99. &(pxmitpriv->free_xmit_queue.queue));
  100. pxframe++;
  101. }
  102. pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
  103. /*
  104. init xmit hw_txqueue
  105. */
  106. _r8712_init_hw_txqueue(&pxmitpriv->be_txqueue, BE_QUEUE_INX);
  107. _r8712_init_hw_txqueue(&pxmitpriv->bk_txqueue, BK_QUEUE_INX);
  108. _r8712_init_hw_txqueue(&pxmitpriv->vi_txqueue, VI_QUEUE_INX);
  109. _r8712_init_hw_txqueue(&pxmitpriv->vo_txqueue, VO_QUEUE_INX);
  110. _r8712_init_hw_txqueue(&pxmitpriv->bmc_txqueue, BMC_QUEUE_INX);
  111. pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
  112. pxmitpriv->txirp_cnt = 1;
  113. /*per AC pending irp*/
  114. pxmitpriv->beq_cnt = 0;
  115. pxmitpriv->bkq_cnt = 0;
  116. pxmitpriv->viq_cnt = 0;
  117. pxmitpriv->voq_cnt = 0;
  118. /*init xmit_buf*/
  119. _init_queue(&pxmitpriv->free_xmitbuf_queue);
  120. _init_queue(&pxmitpriv->pending_xmitbuf_queue);
  121. pxmitpriv->pallocated_xmitbuf = kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4,
  122. GFP_ATOMIC);
  123. if (pxmitpriv->pallocated_xmitbuf == NULL)
  124. return _FAIL;
  125. pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 -
  126. ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3);
  127. pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
  128. for (i = 0; i < NR_XMITBUFF; i++) {
  129. INIT_LIST_HEAD(&pxmitbuf->list);
  130. pxmitbuf->pallocated_buf = kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ,
  131. GFP_ATOMIC);
  132. if (pxmitbuf->pallocated_buf == NULL)
  133. return _FAIL;
  134. pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ -
  135. ((addr_t) (pxmitbuf->pallocated_buf) &
  136. (XMITBUF_ALIGN_SZ - 1));
  137. r8712_xmit_resource_alloc(padapter, pxmitbuf);
  138. list_add_tail(&pxmitbuf->list,
  139. &(pxmitpriv->free_xmitbuf_queue.queue));
  140. pxmitbuf++;
  141. }
  142. pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
  143. INIT_WORK(&padapter->wkFilterRxFF0, r8712_SetFilter);
  144. alloc_hwxmits(padapter);
  145. init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
  146. tasklet_init(&pxmitpriv->xmit_tasklet,
  147. (void(*)(unsigned long))r8712_xmit_bh,
  148. (unsigned long)padapter);
  149. return _SUCCESS;
  150. }
  151. void _free_xmit_priv(struct xmit_priv *pxmitpriv)
  152. {
  153. int i;
  154. struct _adapter *padapter = pxmitpriv->adapter;
  155. struct xmit_frame *pxmitframe = (struct xmit_frame *)
  156. pxmitpriv->pxmit_frame_buf;
  157. struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
  158. if (pxmitpriv->pxmit_frame_buf == NULL)
  159. return;
  160. for (i = 0; i < NR_XMITFRAME; i++) {
  161. r8712_xmit_complete(padapter, pxmitframe);
  162. pxmitframe++;
  163. }
  164. for (i = 0; i < NR_XMITBUFF; i++) {
  165. r8712_xmit_resource_free(padapter, pxmitbuf);
  166. kfree(pxmitbuf->pallocated_buf);
  167. pxmitbuf++;
  168. }
  169. kfree(pxmitpriv->pallocated_frame_buf);
  170. kfree(pxmitpriv->pallocated_xmitbuf);
  171. free_hwxmits(padapter);
  172. }
  173. sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
  174. struct pkt_attrib *pattrib)
  175. {
  176. struct pkt_file pktfile;
  177. struct sta_info *psta = NULL;
  178. struct ethhdr etherhdr;
  179. struct tx_cmd txdesc;
  180. sint bmcast;
  181. struct sta_priv *pstapriv = &padapter->stapriv;
  182. struct security_priv *psecuritypriv = &padapter->securitypriv;
  183. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  184. struct qos_priv *pqospriv = &pmlmepriv->qospriv;
  185. _r8712_open_pktfile(pkt, &pktfile);
  186. _r8712_pktfile_read(&pktfile, (unsigned char *)&etherhdr, ETH_HLEN);
  187. pattrib->ether_type = ntohs(etherhdr.h_proto);
  188. {
  189. /*If driver xmit ARP packet, driver can set ps mode to initial
  190. * setting. It stands for getting DHCP or fix IP.*/
  191. if (pattrib->ether_type == 0x0806) {
  192. if (padapter->pwrctrlpriv.pwr_mode !=
  193. padapter->registrypriv.power_mgnt) {
  194. del_timer_sync(&pmlmepriv->dhcp_timer);
  195. r8712_set_ps_mode(padapter, padapter->registrypriv.
  196. power_mgnt, padapter->registrypriv.smart_ps);
  197. }
  198. }
  199. }
  200. memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
  201. memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
  202. pattrib->pctrl = 0;
  203. if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
  204. check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
  205. memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
  206. memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
  207. } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
  208. memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
  209. memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
  210. } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
  211. memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
  212. memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
  213. } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
  214. /*firstly, filter packet not belongs to mp*/
  215. if (pattrib->ether_type != 0x8712)
  216. return _FAIL;
  217. /* for mp storing the txcmd per packet,
  218. * according to the info of txcmd to update pattrib */
  219. /*get MP_TXDESC_SIZE bytes txcmd per packet*/
  220. _r8712_pktfile_read(&pktfile, (u8 *)&txdesc, TXDESC_SIZE);
  221. memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
  222. memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
  223. pattrib->pctrl = 1;
  224. }
  225. /* r8712_xmitframe_coalesce() overwrite this!*/
  226. pattrib->pktlen = pktfile.pkt_len;
  227. if (ETH_P_IP == pattrib->ether_type) {
  228. /* The following is for DHCP and ARP packet, we use cck1M to
  229. * tx these packets and let LPS awake some time
  230. * to prevent DHCP protocol fail */
  231. u8 tmp[24];
  232. _r8712_pktfile_read(&pktfile, &tmp[0], 24);
  233. pattrib->dhcp_pkt = 0;
  234. if (pktfile.pkt_len > 282) {/*MINIMUM_DHCP_PACKET_SIZE)*/
  235. if (ETH_P_IP == pattrib->ether_type) {/* IP header*/
  236. if (((tmp[21] == 68) && (tmp[23] == 67)) ||
  237. ((tmp[21] == 67) && (tmp[23] == 68))) {
  238. /* 68 : UDP BOOTP client
  239. * 67 : UDP BOOTP server
  240. * Use low rate to send DHCP packet.*/
  241. pattrib->dhcp_pkt = 1;
  242. }
  243. }
  244. }
  245. }
  246. bmcast = IS_MCAST(pattrib->ra);
  247. /* get sta_info*/
  248. if (bmcast) {
  249. psta = r8712_get_bcmc_stainfo(padapter);
  250. pattrib->mac_id = 4;
  251. } else {
  252. if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
  253. psta = r8712_get_stainfo(pstapriv,
  254. get_bssid(pmlmepriv));
  255. pattrib->mac_id = 5;
  256. } else {
  257. psta = r8712_get_stainfo(pstapriv, pattrib->ra);
  258. if (psta == NULL) /* drop the pkt */
  259. return _FAIL;
  260. if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
  261. pattrib->mac_id = 5;
  262. else
  263. pattrib->mac_id = psta->mac_id;
  264. }
  265. }
  266. if (psta) {
  267. pattrib->psta = psta;
  268. } else {
  269. /* if we cannot get psta => drrp the pkt */
  270. return _FAIL;
  271. }
  272. pattrib->ack_policy = 0;
  273. /* get ether_hdr_len */
  274. pattrib->pkt_hdrlen = ETH_HLEN;
  275. if (pqospriv->qos_option) {
  276. r8712_set_qos(&pktfile, pattrib);
  277. } else {
  278. pattrib->hdrlen = WLAN_HDR_A3_LEN;
  279. pattrib->subtype = WIFI_DATA_TYPE;
  280. pattrib->priority = 0;
  281. }
  282. if (psta->ieee8021x_blocked) {
  283. pattrib->encrypt = 0;
  284. if ((pattrib->ether_type != 0x888e) &&
  285. !check_fwstate(pmlmepriv, WIFI_MP_STATE))
  286. return _FAIL;
  287. } else {
  288. GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
  289. }
  290. switch (pattrib->encrypt) {
  291. case _WEP40_:
  292. case _WEP104_:
  293. pattrib->iv_len = 4;
  294. pattrib->icv_len = 4;
  295. break;
  296. case _TKIP_:
  297. pattrib->iv_len = 8;
  298. pattrib->icv_len = 4;
  299. if (padapter->securitypriv.busetkipkey == _FAIL)
  300. return _FAIL;
  301. break;
  302. case _AES_:
  303. pattrib->iv_len = 8;
  304. pattrib->icv_len = 8;
  305. break;
  306. default:
  307. pattrib->iv_len = 0;
  308. pattrib->icv_len = 0;
  309. break;
  310. }
  311. if (pattrib->encrypt &&
  312. (padapter->securitypriv.sw_encrypt ||
  313. !psecuritypriv->hw_decrypted))
  314. pattrib->bswenc = true;
  315. else
  316. pattrib->bswenc = false;
  317. /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite
  318. * some settings above.*/
  319. if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
  320. pattrib->priority =
  321. (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f;
  322. return _SUCCESS;
  323. }
  324. static sint xmitframe_addmic(struct _adapter *padapter,
  325. struct xmit_frame *pxmitframe)
  326. {
  327. u32 curfragnum, length;
  328. u8 *pframe, *payload, mic[8];
  329. struct mic_data micdata;
  330. struct sta_info *stainfo;
  331. struct qos_priv *pqospriv = &(padapter->mlmepriv.qospriv);
  332. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  333. struct security_priv *psecuritypriv = &padapter->securitypriv;
  334. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  335. u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
  336. sint bmcst = IS_MCAST(pattrib->ra);
  337. if (pattrib->psta)
  338. stainfo = pattrib->psta;
  339. else
  340. stainfo = r8712_get_stainfo(&padapter->stapriv,
  341. &pattrib->ra[0]);
  342. if (pattrib->encrypt == _TKIP_) {
  343. /*encode mic code*/
  344. if (stainfo != NULL) {
  345. u8 null_key[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  346. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  347. 0x0, 0x0};
  348. pframe = pxmitframe->buf_addr + TXDESC_OFFSET;
  349. if (bmcst) {
  350. if (!memcmp(psecuritypriv->XGrptxmickey
  351. [psecuritypriv->XGrpKeyid].skey,
  352. null_key, 16))
  353. return _FAIL;
  354. /*start to calculate the mic code*/
  355. r8712_secmicsetkey(&micdata,
  356. psecuritypriv->
  357. XGrptxmickey[psecuritypriv->
  358. XGrpKeyid].skey);
  359. } else {
  360. if (!memcmp(&stainfo->tkiptxmickey.skey[0],
  361. null_key, 16))
  362. return _FAIL;
  363. /* start to calculate the mic code */
  364. r8712_secmicsetkey(&micdata,
  365. &stainfo->tkiptxmickey.skey[0]);
  366. }
  367. if (pframe[1] & 1) { /* ToDS==1 */
  368. r8712_secmicappend(&micdata,
  369. &pframe[16], 6); /*DA*/
  370. if (pframe[1] & 2) /* From Ds==1 */
  371. r8712_secmicappend(&micdata,
  372. &pframe[24], 6);
  373. else
  374. r8712_secmicappend(&micdata,
  375. &pframe[10], 6);
  376. } else { /* ToDS==0 */
  377. r8712_secmicappend(&micdata,
  378. &pframe[4], 6); /* DA */
  379. if (pframe[1] & 2) /* From Ds==1 */
  380. r8712_secmicappend(&micdata,
  381. &pframe[16], 6);
  382. else
  383. r8712_secmicappend(&micdata,
  384. &pframe[10], 6);
  385. }
  386. if (pqospriv->qos_option == 1)
  387. priority[0] = (u8)pxmitframe->
  388. attrib.priority;
  389. r8712_secmicappend(&micdata, &priority[0], 4);
  390. payload = pframe;
  391. for (curfragnum = 0; curfragnum < pattrib->nr_frags;
  392. curfragnum++) {
  393. payload = (u8 *)RND4((addr_t)(payload));
  394. payload = payload + pattrib->
  395. hdrlen + pattrib->iv_len;
  396. if ((curfragnum + 1) == pattrib->nr_frags) {
  397. length = pattrib->last_txcmdsz -
  398. pattrib->hdrlen -
  399. pattrib->iv_len -
  400. ((psecuritypriv->sw_encrypt)
  401. ? pattrib->icv_len : 0);
  402. r8712_secmicappend(&micdata, payload,
  403. length);
  404. payload = payload + length;
  405. } else{
  406. length = pxmitpriv->frag_len -
  407. pattrib->hdrlen - pattrib->iv_len -
  408. ((psecuritypriv->sw_encrypt) ?
  409. pattrib->icv_len : 0);
  410. r8712_secmicappend(&micdata, payload,
  411. length);
  412. payload = payload + length +
  413. pattrib->icv_len;
  414. }
  415. }
  416. r8712_secgetmic(&micdata, &(mic[0]));
  417. /* add mic code and add the mic code length in
  418. * last_txcmdsz */
  419. memcpy(payload, &(mic[0]), 8);
  420. pattrib->last_txcmdsz += 8;
  421. payload = payload - pattrib->last_txcmdsz + 8;
  422. }
  423. }
  424. return _SUCCESS;
  425. }
  426. static sint xmitframe_swencrypt(struct _adapter *padapter,
  427. struct xmit_frame *pxmitframe)
  428. {
  429. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  430. if (pattrib->bswenc) {
  431. switch (pattrib->encrypt) {
  432. case _WEP40_:
  433. case _WEP104_:
  434. r8712_wep_encrypt(padapter, (u8 *)pxmitframe);
  435. break;
  436. case _TKIP_:
  437. r8712_tkip_encrypt(padapter, (u8 *)pxmitframe);
  438. break;
  439. case _AES_:
  440. r8712_aes_encrypt(padapter, (u8 *)pxmitframe);
  441. break;
  442. default:
  443. break;
  444. }
  445. }
  446. return _SUCCESS;
  447. }
  448. static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr,
  449. struct pkt_attrib *pattrib)
  450. {
  451. u16 *qc;
  452. struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
  453. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  454. struct qos_priv *pqospriv = &pmlmepriv->qospriv;
  455. __le16 *fctrl = &pwlanhdr->frame_ctl;
  456. memset(hdr, 0, WLANHDR_OFFSET);
  457. SetFrameSubType(fctrl, pattrib->subtype);
  458. if (pattrib->subtype & WIFI_DATA_TYPE) {
  459. if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
  460. /* to_ds = 1, fr_ds = 0; */
  461. SetToDs(fctrl);
  462. memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv),
  463. ETH_ALEN);
  464. memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
  465. memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
  466. } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
  467. /* to_ds = 0, fr_ds = 1; */
  468. SetFrDs(fctrl);
  469. memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
  470. memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv),
  471. ETH_ALEN);
  472. memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
  473. } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
  474. check_fwstate(pmlmepriv,
  475. WIFI_ADHOC_MASTER_STATE)) {
  476. memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
  477. memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
  478. memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv),
  479. ETH_ALEN);
  480. } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
  481. memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
  482. memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
  483. memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv),
  484. ETH_ALEN);
  485. } else {
  486. return _FAIL;
  487. }
  488. if (pattrib->encrypt)
  489. SetPrivacy(fctrl);
  490. if (pqospriv->qos_option) {
  491. qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
  492. if (pattrib->priority)
  493. SetPriority(qc, pattrib->priority);
  494. SetAckpolicy(qc, pattrib->ack_policy);
  495. }
  496. /* TODO: fill HT Control Field */
  497. /* Update Seq Num will be handled by f/w */
  498. {
  499. struct sta_info *psta;
  500. sint bmcst = IS_MCAST(pattrib->ra);
  501. if (pattrib->psta) {
  502. psta = pattrib->psta;
  503. } else {
  504. if (bmcst)
  505. psta = r8712_get_bcmc_stainfo(padapter);
  506. else
  507. psta =
  508. r8712_get_stainfo(&padapter->stapriv,
  509. pattrib->ra);
  510. }
  511. if (psta) {
  512. psta->sta_xmitpriv.txseq_tid
  513. [pattrib->priority]++;
  514. psta->sta_xmitpriv.txseq_tid[pattrib->priority]
  515. &= 0xFFF;
  516. pattrib->seqnum = psta->sta_xmitpriv.
  517. txseq_tid[pattrib->priority];
  518. SetSeqNum(hdr, pattrib->seqnum);
  519. }
  520. }
  521. }
  522. return _SUCCESS;
  523. }
  524. static sint r8712_put_snap(u8 *data, u16 h_proto)
  525. {
  526. struct ieee80211_snap_hdr *snap;
  527. const u8 *oui;
  528. snap = (struct ieee80211_snap_hdr *)data;
  529. snap->dsap = 0xaa;
  530. snap->ssap = 0xaa;
  531. snap->ctrl = 0x03;
  532. if (h_proto == 0x8137 || h_proto == 0x80f3)
  533. oui = P802_1H_OUI;
  534. else
  535. oui = RFC1042_OUI;
  536. snap->oui[0] = oui[0];
  537. snap->oui[1] = oui[1];
  538. snap->oui[2] = oui[2];
  539. *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
  540. return SNAP_SIZE + sizeof(u16);
  541. }
  542. /*
  543. * This sub-routine will perform all the following:
  544. * 1. remove 802.3 header.
  545. * 2. create wlan_header, based on the info in pxmitframe
  546. * 3. append sta's iv/ext-iv
  547. * 4. append LLC
  548. * 5. move frag chunk from pframe to pxmitframe->mem
  549. * 6. apply sw-encrypt, if necessary.
  550. */
  551. sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
  552. struct xmit_frame *pxmitframe)
  553. {
  554. struct pkt_file pktfile;
  555. sint frg_len, mpdu_len, llc_sz;
  556. u32 mem_sz;
  557. u8 frg_inx;
  558. addr_t addr;
  559. u8 *pframe, *mem_start, *ptxdesc;
  560. struct sta_info *psta;
  561. struct security_priv *psecuritypriv = &padapter->securitypriv;
  562. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  563. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  564. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  565. u8 *pbuf_start;
  566. sint bmcst = IS_MCAST(pattrib->ra);
  567. if (pattrib->psta == NULL)
  568. return _FAIL;
  569. psta = pattrib->psta;
  570. if (pxmitframe->buf_addr == NULL)
  571. return _FAIL;
  572. pbuf_start = pxmitframe->buf_addr;
  573. ptxdesc = pbuf_start;
  574. mem_start = pbuf_start + TXDESC_OFFSET;
  575. if (make_wlanhdr(padapter, mem_start, pattrib) == _FAIL)
  576. return _FAIL;
  577. _r8712_open_pktfile(pkt, &pktfile);
  578. _r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen);
  579. if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
  580. /* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
  581. if (pattrib->ether_type == 0x8712) {
  582. /* take care - update_txdesc overwrite this */
  583. _r8712_pktfile_read(&pktfile, ptxdesc, TXDESC_SIZE);
  584. }
  585. }
  586. pattrib->pktlen = pktfile.pkt_len;
  587. frg_inx = 0;
  588. frg_len = pxmitpriv->frag_len - 4;
  589. while (1) {
  590. llc_sz = 0;
  591. mpdu_len = frg_len;
  592. pframe = mem_start;
  593. SetMFrag(mem_start);
  594. pframe += pattrib->hdrlen;
  595. mpdu_len -= pattrib->hdrlen;
  596. /* adding icv, if necessary...*/
  597. if (pattrib->iv_len) {
  598. if (psta != NULL) {
  599. switch (pattrib->encrypt) {
  600. case _WEP40_:
  601. case _WEP104_:
  602. WEP_IV(pattrib->iv, psta->txpn,
  603. (u8)psecuritypriv->
  604. PrivacyKeyIndex);
  605. break;
  606. case _TKIP_:
  607. if (bmcst)
  608. TKIP_IV(pattrib->iv,
  609. psta->txpn,
  610. (u8)psecuritypriv->
  611. XGrpKeyid);
  612. else
  613. TKIP_IV(pattrib->iv, psta->txpn,
  614. 0);
  615. break;
  616. case _AES_:
  617. if (bmcst)
  618. AES_IV(pattrib->iv, psta->txpn,
  619. (u8)psecuritypriv->
  620. XGrpKeyid);
  621. else
  622. AES_IV(pattrib->iv, psta->txpn,
  623. 0);
  624. break;
  625. }
  626. }
  627. memcpy(pframe, pattrib->iv, pattrib->iv_len);
  628. pframe += pattrib->iv_len;
  629. mpdu_len -= pattrib->iv_len;
  630. }
  631. if (frg_inx == 0) {
  632. llc_sz = r8712_put_snap(pframe, pattrib->ether_type);
  633. pframe += llc_sz;
  634. mpdu_len -= llc_sz;
  635. }
  636. if ((pattrib->icv_len > 0) && (pattrib->bswenc))
  637. mpdu_len -= pattrib->icv_len;
  638. if (bmcst)
  639. mem_sz = _r8712_pktfile_read(&pktfile, pframe,
  640. pattrib->pktlen);
  641. else
  642. mem_sz = _r8712_pktfile_read(&pktfile, pframe,
  643. mpdu_len);
  644. pframe += mem_sz;
  645. if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
  646. memcpy(pframe, pattrib->icv, pattrib->icv_len);
  647. pframe += pattrib->icv_len;
  648. }
  649. frg_inx++;
  650. if (bmcst || r8712_endofpktfile(&pktfile)) {
  651. pattrib->nr_frags = frg_inx;
  652. pattrib->last_txcmdsz = pattrib->hdrlen +
  653. pattrib->iv_len +
  654. ((pattrib->nr_frags == 1) ?
  655. llc_sz : 0) +
  656. ((pattrib->bswenc) ?
  657. pattrib->icv_len : 0) + mem_sz;
  658. ClearMFrag(mem_start);
  659. break;
  660. }
  661. addr = (addr_t)(pframe);
  662. mem_start = (unsigned char *)RND4(addr) + TXDESC_OFFSET;
  663. memcpy(mem_start, pbuf_start + TXDESC_OFFSET, pattrib->hdrlen);
  664. }
  665. if (xmitframe_addmic(padapter, pxmitframe) == _FAIL)
  666. return _FAIL;
  667. xmitframe_swencrypt(padapter, pxmitframe);
  668. return _SUCCESS;
  669. }
  670. void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len)
  671. {
  672. uint protection;
  673. u8 *perp;
  674. sint erp_len;
  675. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  676. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  677. switch (pxmitpriv->vcs_setting) {
  678. case DISABLE_VCS:
  679. pxmitpriv->vcs = NONE_VCS;
  680. break;
  681. case ENABLE_VCS:
  682. break;
  683. case AUTO_VCS:
  684. default:
  685. perp = r8712_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);
  686. if (perp == NULL) {
  687. pxmitpriv->vcs = NONE_VCS;
  688. } else {
  689. protection = (*(perp + 2)) & BIT(1);
  690. if (protection) {
  691. if (pregistrypriv->vcs_type == RTS_CTS)
  692. pxmitpriv->vcs = RTS_CTS;
  693. else
  694. pxmitpriv->vcs = CTS_TO_SELF;
  695. } else {
  696. pxmitpriv->vcs = NONE_VCS;
  697. }
  698. }
  699. break;
  700. }
  701. }
  702. struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
  703. {
  704. unsigned long irqL;
  705. struct xmit_buf *pxmitbuf = NULL;
  706. struct list_head *plist, *phead;
  707. struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
  708. spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
  709. if (list_empty(&pfree_xmitbuf_queue->queue)) {
  710. pxmitbuf = NULL;
  711. } else {
  712. phead = &pfree_xmitbuf_queue->queue;
  713. plist = phead->next;
  714. pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
  715. list_del_init(&(pxmitbuf->list));
  716. }
  717. if (pxmitbuf != NULL)
  718. pxmitpriv->free_xmitbuf_cnt--;
  719. spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
  720. return pxmitbuf;
  721. }
  722. int r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
  723. {
  724. unsigned long irqL;
  725. struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
  726. if (pxmitbuf == NULL)
  727. return _FAIL;
  728. spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
  729. list_del_init(&pxmitbuf->list);
  730. list_add_tail(&(pxmitbuf->list), &pfree_xmitbuf_queue->queue);
  731. pxmitpriv->free_xmitbuf_cnt++;
  732. spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
  733. return _SUCCESS;
  734. }
  735. /*
  736. Calling context:
  737. 1. OS_TXENTRY
  738. 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
  739. If we turn on USE_RXTHREAD, then, no need for critical section.
  740. Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
  741. Must be very very cautious...
  742. */
  743. struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv)
  744. {
  745. /*
  746. Please remember to use all the osdep_service api,
  747. and lock/unlock or _enter/_exit critical to protect
  748. pfree_xmit_queue
  749. */
  750. unsigned long irqL;
  751. struct xmit_frame *pxframe = NULL;
  752. struct list_head *plist, *phead;
  753. struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
  754. spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
  755. if (list_empty(&pfree_xmit_queue->queue)) {
  756. pxframe = NULL;
  757. } else {
  758. phead = &pfree_xmit_queue->queue;
  759. plist = phead->next;
  760. pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
  761. list_del_init(&(pxframe->list));
  762. }
  763. if (pxframe != NULL) {
  764. pxmitpriv->free_xmitframe_cnt--;
  765. pxframe->buf_addr = NULL;
  766. pxframe->pxmitbuf = NULL;
  767. pxframe->attrib.psta = NULL;
  768. pxframe->pkt = NULL;
  769. }
  770. spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
  771. return pxframe;
  772. }
  773. void r8712_free_xmitframe(struct xmit_priv *pxmitpriv,
  774. struct xmit_frame *pxmitframe)
  775. {
  776. unsigned long irqL;
  777. struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
  778. struct _adapter *padapter = pxmitpriv->adapter;
  779. if (pxmitframe == NULL)
  780. return;
  781. spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
  782. list_del_init(&pxmitframe->list);
  783. if (pxmitframe->pkt)
  784. pxmitframe->pkt = NULL;
  785. list_add_tail(&pxmitframe->list, &pfree_xmit_queue->queue);
  786. pxmitpriv->free_xmitframe_cnt++;
  787. spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
  788. if (netif_queue_stopped(padapter->pnetdev))
  789. netif_wake_queue(padapter->pnetdev);
  790. }
  791. void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv,
  792. struct xmit_frame *pxmitframe)
  793. {
  794. if (pxmitframe == NULL)
  795. return;
  796. if (pxmitframe->frame_tag == DATA_FRAMETAG)
  797. r8712_free_xmitframe(pxmitpriv, pxmitframe);
  798. }
  799. void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv,
  800. struct __queue *pframequeue)
  801. {
  802. unsigned long irqL;
  803. struct list_head *plist, *phead;
  804. struct xmit_frame *pxmitframe;
  805. spin_lock_irqsave(&(pframequeue->lock), irqL);
  806. phead = &pframequeue->queue;
  807. plist = phead->next;
  808. while (!end_of_queue_search(phead, plist)) {
  809. pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
  810. plist = plist->next;
  811. r8712_free_xmitframe(pxmitpriv, pxmitframe);
  812. }
  813. spin_unlock_irqrestore(&(pframequeue->lock), irqL);
  814. }
  815. static inline struct tx_servq *get_sta_pending(struct _adapter *padapter,
  816. struct __queue **ppstapending,
  817. struct sta_info *psta, sint up)
  818. {
  819. struct tx_servq *ptxservq;
  820. struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
  821. switch (up) {
  822. case 1:
  823. case 2:
  824. ptxservq = &(psta->sta_xmitpriv.bk_q);
  825. *ppstapending = &padapter->xmitpriv.bk_pending;
  826. (phwxmits + 3)->accnt++;
  827. break;
  828. case 4:
  829. case 5:
  830. ptxservq = &(psta->sta_xmitpriv.vi_q);
  831. *ppstapending = &padapter->xmitpriv.vi_pending;
  832. (phwxmits + 1)->accnt++;
  833. break;
  834. case 6:
  835. case 7:
  836. ptxservq = &(psta->sta_xmitpriv.vo_q);
  837. *ppstapending = &padapter->xmitpriv.vo_pending;
  838. (phwxmits + 0)->accnt++;
  839. break;
  840. case 0:
  841. case 3:
  842. default:
  843. ptxservq = &(psta->sta_xmitpriv.be_q);
  844. *ppstapending = &padapter->xmitpriv.be_pending;
  845. (phwxmits + 2)->accnt++;
  846. break;
  847. }
  848. return ptxservq;
  849. }
  850. /*
  851. * Will enqueue pxmitframe to the proper queue, and indicate it
  852. * to xx_pending list.....
  853. */
  854. sint r8712_xmit_classifier(struct _adapter *padapter,
  855. struct xmit_frame *pxmitframe)
  856. {
  857. unsigned long irqL0;
  858. struct __queue *pstapending;
  859. struct sta_info *psta;
  860. struct tx_servq *ptxservq;
  861. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  862. struct sta_priv *pstapriv = &padapter->stapriv;
  863. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  864. sint bmcst = IS_MCAST(pattrib->ra);
  865. if (pattrib->psta) {
  866. psta = pattrib->psta;
  867. } else {
  868. if (bmcst) {
  869. psta = r8712_get_bcmc_stainfo(padapter);
  870. } else {
  871. if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
  872. psta = r8712_get_stainfo(pstapriv,
  873. get_bssid(pmlmepriv));
  874. else
  875. psta = r8712_get_stainfo(pstapriv, pattrib->ra);
  876. }
  877. }
  878. if (psta == NULL)
  879. return _FAIL;
  880. ptxservq = get_sta_pending(padapter, &pstapending,
  881. psta, pattrib->priority);
  882. spin_lock_irqsave(&pstapending->lock, irqL0);
  883. if (list_empty(&ptxservq->tx_pending))
  884. list_add_tail(&ptxservq->tx_pending, &pstapending->queue);
  885. list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue);
  886. ptxservq->qcnt++;
  887. spin_unlock_irqrestore(&pstapending->lock, irqL0);
  888. return _SUCCESS;
  889. }
  890. static void alloc_hwxmits(struct _adapter *padapter)
  891. {
  892. struct hw_xmit *hwxmits;
  893. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  894. pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
  895. pxmitpriv->hwxmits = kmalloc_array(pxmitpriv->hwxmit_entry,
  896. sizeof(struct hw_xmit), GFP_ATOMIC);
  897. if (pxmitpriv->hwxmits == NULL)
  898. return;
  899. hwxmits = pxmitpriv->hwxmits;
  900. if (pxmitpriv->hwxmit_entry == 5) {
  901. pxmitpriv->bmc_txqueue.head = 0;
  902. hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue;
  903. hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
  904. pxmitpriv->vo_txqueue.head = 0;
  905. hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue;
  906. hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
  907. pxmitpriv->vi_txqueue.head = 0;
  908. hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue;
  909. hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
  910. pxmitpriv->bk_txqueue.head = 0;
  911. hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
  912. hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
  913. pxmitpriv->be_txqueue.head = 0;
  914. hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue;
  915. hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
  916. } else if (pxmitpriv->hwxmit_entry == 4) {
  917. pxmitpriv->vo_txqueue.head = 0;
  918. hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue;
  919. hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
  920. pxmitpriv->vi_txqueue.head = 0;
  921. hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue;
  922. hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
  923. pxmitpriv->be_txqueue.head = 0;
  924. hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue;
  925. hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
  926. pxmitpriv->bk_txqueue.head = 0;
  927. hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
  928. hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
  929. }
  930. }
  931. static void free_hwxmits(struct _adapter *padapter)
  932. {
  933. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  934. kfree(pxmitpriv->hwxmits);
  935. }
  936. static void init_hwxmits(struct hw_xmit *phwxmit, sint entry)
  937. {
  938. sint i;
  939. for (i = 0; i < entry; i++, phwxmit++) {
  940. spin_lock_init(&phwxmit->xmit_lock);
  941. INIT_LIST_HEAD(&phwxmit->pending);
  942. phwxmit->txcmdcnt = 0;
  943. phwxmit->accnt = 0;
  944. }
  945. }
  946. void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe,
  947. struct xmit_buf *pxmitbuf)
  948. {
  949. /* pxmitbuf attach to pxmitframe */
  950. pxmitframe->pxmitbuf = pxmitbuf;
  951. /* urb and irp connection */
  952. pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
  953. /* buffer addr assoc */
  954. pxmitframe->buf_addr = pxmitbuf->pbuf;
  955. /* pxmitframe attach to pxmitbuf */
  956. pxmitbuf->priv_data = pxmitframe;
  957. }
  958. /*
  959. * tx_action == 0 == no frames to transmit
  960. * tx_action > 0 ==> we have frames to transmit
  961. * tx_action < 0 ==> we have frames to transmit, but TXFF is not even enough
  962. * to transmit 1 frame.
  963. */
  964. int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe)
  965. {
  966. unsigned long irqL;
  967. int ret;
  968. struct xmit_buf *pxmitbuf = NULL;
  969. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  970. struct pkt_attrib *pattrib = &pxmitframe->attrib;
  971. r8712_do_queue_select(padapter, pattrib);
  972. spin_lock_irqsave(&pxmitpriv->lock, irqL);
  973. if (r8712_txframes_sta_ac_pending(padapter, pattrib) > 0) {
  974. ret = false;
  975. r8712_xmit_enqueue(padapter, pxmitframe);
  976. spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
  977. return ret;
  978. }
  979. pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv);
  980. if (pxmitbuf == NULL) { /*enqueue packet*/
  981. ret = false;
  982. r8712_xmit_enqueue(padapter, pxmitframe);
  983. spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
  984. } else { /*dump packet directly*/
  985. spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
  986. ret = true;
  987. xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
  988. r8712_xmit_direct(padapter, pxmitframe);
  989. }
  990. return ret;
  991. }