tx.c revision 01d77d8d4747d73cfb6daf35cdc906a2db8ded9d
1876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/**
2876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti  * This file contains the handling of TX in wlan driver.
3876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti  */
4876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include <linux/netdevice.h>
5876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
6876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "hostcmd.h"
7876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "radiotap.h"
8876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "decl.h"
9876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "defs.h"
10876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "dev.h"
11876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "wext.h"
12876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
13876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/**
14876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
15876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1)
16876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *
17876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @param rate    Input rate
18876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @return      Output Rate (0 if invalid)
19876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */
20876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattistatic u32 convert_radiotap_rate_to_mv(u8 rate)
21876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{
22876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	switch (rate) {
23876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 2:		/*   1 Mbps */
24876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 0 | (1 << 4);
25876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 4:		/*   2 Mbps */
26876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 1 | (1 << 4);
27876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 11:		/* 5.5 Mbps */
28876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 2 | (1 << 4);
29876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 22:		/*  11 Mbps */
30876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 3 | (1 << 4);
31876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 12:		/*   6 Mbps */
32876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 4 | (1 << 4);
33876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 18:		/*   9 Mbps */
34876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 5 | (1 << 4);
35876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 24:		/*  12 Mbps */
36876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 6 | (1 << 4);
37876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 36:		/*  18 Mbps */
38876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 7 | (1 << 4);
39876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 48:		/*  24 Mbps */
40876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 8 | (1 << 4);
41876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 72:		/*  36 Mbps */
42876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 9 | (1 << 4);
43876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 96:		/*  48 Mbps */
44876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 10 | (1 << 4);
45876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	case 108:		/*  54 Mbps */
46876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return 11 | (1 << 4);
47876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
48876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	return 0;
49876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}
50876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
51876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/**
52876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @brief This function processes a single packet and sends
53876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  to IF layer
54876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *
551007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig *  @param priv    A pointer to lbs_private structure
56876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @param skb     A pointer to skb which includes TX packet
57876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @return 	   0 or -1
58876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */
591007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic int SendSinglePacket(lbs_private *priv, struct sk_buff *skb)
60876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{
61876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	int ret = 0;
62876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	struct txpd localtxpd;
63876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	struct txpd *plocaltxpd = &localtxpd;
64876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	u8 *p802x_hdr;
65876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	struct tx_radiotap_hdr *pradiotap_hdr;
66876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	u32 new_rate;
67876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	u8 *ptr = priv->adapter->tmptxbuf;
68876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
699012b28a407511fb355f6d2176a12d4653489672Holger Schurig	lbs_deb_enter(LBS_DEB_TX);
70876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
71876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	if (priv->adapter->surpriseremoved)
72876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return -1;
73876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
74876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
759012b28a407511fb355f6d2176a12d4653489672Holger Schurig		lbs_deb_tx("tx err: skb length %d 0 or > %zd\n",
76876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		       skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
77876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		ret = -1;
78876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		goto done;
79876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
80876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
81876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	memset(plocaltxpd, 0, sizeof(struct txpd));
82876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
83981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse	plocaltxpd->tx_packet_length = cpu_to_le16(skb->len);
84876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
85876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	/* offset of actual data */
86981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse	plocaltxpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
87876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
88876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	p802x_hdr = skb->data;
891007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig	if (priv->adapter->monitormode != LBS_MONITOR_OFF) {
90876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
91876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		/* locate radiotap header */
92876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		pradiotap_hdr = (struct tx_radiotap_hdr *)skb->data;
93876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
94876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		/* set txpd fields from the radiotap header */
95876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate);
96876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		if (new_rate != 0) {
97981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse			/* use new tx_control[4:0] */
98981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse			plocaltxpd->tx_control = cpu_to_le32(new_rate);
99876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		}
100876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
101876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		/* skip the radiotap header */
102876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		p802x_hdr += sizeof(struct tx_radiotap_hdr);
103981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse		plocaltxpd->tx_packet_length =
10486760088a7c51ccc263ec3b8039ec9a7400a6d70David Woodhouse			cpu_to_le16(le16_to_cpu(plocaltxpd->tx_packet_length)
105981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse				    - sizeof(struct tx_radiotap_hdr));
106876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
107876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
108876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	/* copy destination address from 802.3 or 802.11 header */
1091007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig	if (priv->adapter->monitormode != LBS_MONITOR_OFF)
110876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
111876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	else
112876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
113876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
114ece561919326236c7fb791a5e883f0eb76af029eHolger Schurig	lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) plocaltxpd, sizeof(struct txpd));
115876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
116876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	if (IS_MESH_FRAME(skb)) {
117981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse		plocaltxpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
118876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
119876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
120876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	memcpy(ptr, plocaltxpd, sizeof(struct txpd));
121876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
122876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	ptr += sizeof(struct txpd);
123876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
124ece561919326236c7fb791a5e883f0eb76af029eHolger Schurig	lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length));
12586760088a7c51ccc263ec3b8039ec9a7400a6d70David Woodhouse	memcpy(ptr, p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length));
126208fdd2f447899164bd139452c291b155e53cee9Holger Schurig	ret = priv->hw_host_to_card(priv, MVMS_DAT,
127981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse				    priv->adapter->tmptxbuf,
12886760088a7c51ccc263ec3b8039ec9a7400a6d70David Woodhouse				    le16_to_cpu(plocaltxpd->tx_packet_length) +
129981f187b7c4b237011d4175cae0120d5d203c0fdDavid Woodhouse				    sizeof(struct txpd));
130876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
131876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	if (ret) {
132208fdd2f447899164bd139452c291b155e53cee9Holger Schurig		lbs_deb_tx("tx err: hw_host_to_card returned 0x%X\n", ret);
133876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		goto done;
134876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
135876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
1369012b28a407511fb355f6d2176a12d4653489672Holger Schurig	lbs_deb_tx("SendSinglePacket succeeds\n");
137876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
1389012b28a407511fb355f6d2176a12d4653489672Holger Schurigdone:
139876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	if (!ret) {
140876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		priv->stats.tx_packets++;
141876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		priv->stats.tx_bytes += skb->len;
142876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	} else {
143876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		priv->stats.tx_dropped++;
144876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		priv->stats.tx_errors++;
145876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
146876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
1471007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig	if (!ret && priv->adapter->monitormode != LBS_MONITOR_OFF) {
148876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		/* Keep the skb to echo it back once Tx feedback is
149876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		   received from FW */
150876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		skb_orphan(skb);
151876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		/* stop processing outgoing pkts */
152634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig		netif_stop_queue(priv->dev);
1533cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig		if (priv->mesh_dev)
1543cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig			netif_stop_queue(priv->mesh_dev);
155876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		/* freeze any packets already in our queues */
156876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		priv->adapter->TxLockFlag = 1;
157876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	} else {
158876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		dev_kfree_skb_any(skb);
159876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		priv->adapter->currenttxskb = NULL;
160876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
161876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
1629012b28a407511fb355f6d2176a12d4653489672Holger Schurig	lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
163876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	return ret;
164876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}
165876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
166876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
1671007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigvoid lbs_tx_runqueue(lbs_private *priv)
168876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{
1691007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig	lbs_adapter *adapter = priv->adapter;
170876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	int i;
171876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
172876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	spin_lock(&adapter->txqueue_lock);
173876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	for (i = 0; i < adapter->tx_queue_idx; i++) {
174876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		struct sk_buff *skb = adapter->tx_queue_ps[i];
175876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		spin_unlock(&adapter->txqueue_lock);
176876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		SendSinglePacket(priv, skb);
177876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		spin_lock(&adapter->txqueue_lock);
178876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
179876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	adapter->tx_queue_idx = 0;
180876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	spin_unlock(&adapter->txqueue_lock);
181876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}
182876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
1831007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic void lbs_tx_queue(lbs_private *priv, struct sk_buff *skb)
184876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{
1851007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig	lbs_adapter *adapter = priv->adapter;
186876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
187876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	spin_lock(&adapter->txqueue_lock);
188876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
189876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE);
190876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb;
19151d84f501684db22f5fcc30821cbbde2a0a2f264Javier Cardona	if (adapter->tx_queue_idx == NR_TX_QUEUE) {
192634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig		netif_stop_queue(priv->dev);
1933cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig		if (priv->mesh_dev)
1943cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig			netif_stop_queue(priv->mesh_dev);
19551d84f501684db22f5fcc30821cbbde2a0a2f264Javier Cardona	} else {
196634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig		netif_start_queue(priv->dev);
1973cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig		if (priv->mesh_dev)
1983cf840914bd467fa4cc76af1a01bba4d2813131cHolger Schurig			netif_start_queue(priv->mesh_dev);
19951d84f501684db22f5fcc30821cbbde2a0a2f264Javier Cardona	}
200876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
201876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	spin_unlock(&adapter->txqueue_lock);
202876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}
203876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
204876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/**
205876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @brief This function checks the conditions and sends packet to IF
206876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  layer if everything is ok.
207876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *
2081007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig *  @param priv    A pointer to lbs_private structure
209876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @return 	   n/a
210876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */
2111007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigint lbs_process_tx(lbs_private *priv, struct sk_buff *skb)
212876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{
213876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	int ret = -1;
214876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
2159012b28a407511fb355f6d2176a12d4653489672Holger Schurig	lbs_deb_enter(LBS_DEB_TX);
216ece561919326236c7fb791a5e883f0eb76af029eHolger Schurig	lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
217876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
218634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig	if (priv->dnld_sent) {
219876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n",
220634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig		       priv->dnld_sent);
221876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		goto done;
222876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
223876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
224876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	if ((priv->adapter->psstate == PS_STATE_SLEEP) ||
225876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	    (priv->adapter->psstate == PS_STATE_PRE_SLEEP)) {
2261007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig		lbs_tx_queue(priv, skb);
227876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return ret;
228876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	}
229876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
230876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	priv->adapter->currenttxskb = skb;
231876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
232876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	ret = SendSinglePacket(priv, skb);
233876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattidone:
2349012b28a407511fb355f6d2176a12d4653489672Holger Schurig	lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
235876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	return ret;
236876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}
237876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
238876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/**
239876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @brief This function sends to the host the last transmitted packet,
240876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  filling the radiotap headers with transmission information.
241876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *
2421007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig *  @param priv     A pointer to lbs_private structure
243876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @param status   A 32 bit value containing transmission status.
244876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *
245876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *  @returns void
246876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */
2471007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigvoid lbs_send_tx_feedback(lbs_private *priv)
248876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{
2491007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig	lbs_adapter *adapter = priv->adapter;
250876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	struct tx_radiotap_hdr *radiotap_hdr;
251876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	u32 status = adapter->eventcause;
252876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	int txfail;
253876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	int try_count;
254876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
2551007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig	if (adapter->monitormode == LBS_MONITOR_OFF ||
256876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	    adapter->currenttxskb == NULL)
257876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		return;
258876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
259876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	radiotap_hdr = (struct tx_radiotap_hdr *)adapter->currenttxskb->data;
260876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
261876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	txfail = (status >> 24);
262876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti
263876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#if 0
264876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	/* The version of roofnet that we've tested does not use this yet
265876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	 * But it may be used in the future.
266876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	 */
267876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	if (txfail)
268876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti		radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
269876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#endif
270876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	try_count = (status >> 16) & 0xff;
271876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	radiotap_hdr->data_retries = (try_count) ?
272876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	    (1 + adapter->txretrycount - try_count) : 0;
2731007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig	lbs_upload_rx_packet(priv, adapter->currenttxskb);
274876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	adapter->currenttxskb = NULL;
275876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti	priv->adapter->TxLockFlag = 0;
27601d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave
27701d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave	if (adapter->connect_status == LBS_CONNECTED)
278634b8f49c11f49272b09d13a34b22a17b8c3d419Holger Schurig		netif_wake_queue(priv->dev);
27901d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave
28001d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave	if (priv->mesh_dev && (adapter->mesh_connect_status == LBS_CONNECTED))
28101d77d8d4747d73cfb6daf35cdc906a2db8ded9dBrajesh Dave		netif_wake_queue(priv->mesh_dev);
282876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}
2831007832103d016d1563fab71d4cf2b057a0bccebHolger SchurigEXPORT_SYMBOL_GPL(lbs_send_tx_feedback);
284