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