txrx.c 11.2 KB
Newer Older
1 2 3
/*
 * Marvell Wireless LAN device driver: generic TX/RX data handling
 *
X
Xinming Hu 已提交
4
 * Copyright (C) 2011-2014, Marvell International Ltd.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
 *
 * This software file (the "File") is distributed by Marvell International
 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
 * (the "License").  You may use, redistribute and/or modify this File in
 * accordance with the terms and conditions of the License, a copy of which
 * is available by writing to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
 * this warranty disclaimer.
 */

#include "decl.h"
#include "ioctl.h"
#include "util.h"
#include "fw.h"
#include "main.h"
#include "wmm.h"

/*
 * This function processes the received buffer.
 *
 * Main responsibility of this function is to parse the RxPD to
 * identify the correct interface this packet is headed for and
 * forwarding it to the associated handling function, where the
 * packet will be further processed and sent to kernel/upper layer
 * if required.
 */
int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
			     struct sk_buff *skb)
{
	struct mwifiex_private *priv =
		mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
	struct rxpd *local_rx_pd;
	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
43
	int ret;
44 45 46 47 48 49 50 51

	local_rx_pd = (struct rxpd *) (skb->data);
	/* Get the BSS number from rxpd, get corresponding priv */
	priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num &
				      BSS_NUM_MASK, local_rx_pd->bss_type);
	if (!priv)
		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);

52
	if (!priv) {
53 54
		mwifiex_dbg(adapter, ERROR,
			    "data: priv not found. Drop RX packet\n");
55 56 57 58
		dev_kfree_skb_any(skb);
		return -1;
	}

59 60 61
	mwifiex_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data,
			 min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));

62
	memset(rx_info, 0, sizeof(*rx_info));
63 64
	rx_info->bss_num = priv->bss_num;
	rx_info->bss_type = priv->bss_type;
65

A
Avinash Patil 已提交
66
	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
67 68 69
		ret = mwifiex_process_uap_rx_packet(priv, skb);
	else
		ret = mwifiex_process_sta_rx_packet(priv, skb);
A
Avinash Patil 已提交
70

71
	return ret;
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
}
EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);

/*
 * This function sends a packet to device.
 *
 * It processes the packet to add the TxPD, checks condition and
 * sends the processed packet to firmware for transmission.
 *
 * On successful completion, the function calls the completion callback
 * and logs the time.
 */
int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
		       struct mwifiex_tx_param *tx_param)
{
87
	int hroom, ret = -1;
88
	struct mwifiex_adapter *adapter = priv->adapter;
89
	u8 *head_ptr;
90
	struct txpd *local_tx_pd = NULL;
91 92
	struct mwifiex_sta_node *dest_node;
	struct ethhdr *hdr = (void *)skb->data;
93

94 95
	hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;

96 97 98 99 100 101 102
	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
		dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
		if (dest_node) {
			dest_node->stats.tx_bytes += skb->len;
			dest_node->stats.tx_packets++;
		}

103
		head_ptr = mwifiex_process_uap_txpd(priv, skb);
104
	} else {
105
		head_ptr = mwifiex_process_sta_txpd(priv, skb);
106
	}
107

108 109 110 111 112 113
	if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) {
		skb_queue_tail(&adapter->tx_data_q, skb);
		atomic_inc(&adapter->tx_queued);
		return 0;
	}

114 115
	if (head_ptr) {
		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
116
			local_tx_pd = (struct txpd *)(head_ptr + hroom);
117 118 119 120 121 122 123 124 125 126
		if (adapter->iface_type == MWIFIEX_USB) {
			adapter->data_sent = true;
			ret = adapter->if_ops.host_to_card(adapter,
							   MWIFIEX_USB_EP_DATA,
							   skb, NULL);
		} else {
			ret = adapter->if_ops.host_to_card(adapter,
							   MWIFIEX_TYPE_DATA,
							   skb, tx_param);
		}
127
	}
128 129
	mwifiex_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data,
			 min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
130 131

	switch (ret) {
132
	case -ENOSR:
133
		mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n");
134
		break;
135 136
	case -EBUSY:
		if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
137
		    (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) {
138
				priv->adapter->tx_lock_flag = false;
Y
Yogesh Ashok Powar 已提交
139 140
				if (local_tx_pd)
					local_tx_pd->flags = 0;
141
		}
142
		mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
143 144
		break;
	case -1:
145
		if (adapter->iface_type == MWIFIEX_USB)
146
			adapter->data_sent = false;
147 148 149
		mwifiex_dbg(adapter, ERROR,
			    "mwifiex_write_data_async failed: 0x%X\n",
			    ret);
150
		adapter->dbg.num_tx_host_to_card_failure++;
A
Avinash Patil 已提交
151
		mwifiex_write_data_complete(adapter, skb, 0, ret);
152 153
		break;
	case -EINPROGRESS:
154
		if (adapter->iface_type == MWIFIEX_USB)
155
			adapter->data_sent = false;
156 157
		break;
	case 0:
A
Avinash Patil 已提交
158
		mwifiex_write_data_complete(adapter, skb, 0, ret);
159 160 161 162 163 164 165 166
		break;
	default:
		break;
	}

	return ret;
}

167 168 169 170 171 172 173 174 175 176 177 178 179 180
static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
				struct sk_buff *skb,
				struct mwifiex_tx_param *tx_param)
{
	struct txpd *local_tx_pd = NULL;
	u8 *head_ptr = skb->data;
	int ret = 0;
	struct mwifiex_private *priv;
	struct mwifiex_txinfo *tx_info;

	tx_info = MWIFIEX_SKB_TXCB(skb);
	priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
				      tx_info->bss_type);
	if (!priv) {
181 182
		mwifiex_dbg(adapter, ERROR,
			    "data: priv not found. Drop TX packet\n");
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
		adapter->dbg.num_tx_host_to_card_failure++;
		mwifiex_write_data_complete(adapter, skb, 0, 0);
		return ret;
	}
	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
		if (adapter->iface_type == MWIFIEX_USB)
			local_tx_pd = (struct txpd *)head_ptr;
		else
			local_tx_pd = (struct txpd *) (head_ptr +
				INTF_HEADER_LEN);
	}

	if (adapter->iface_type == MWIFIEX_USB) {
		adapter->data_sent = true;
		ret = adapter->if_ops.host_to_card(adapter,
						   MWIFIEX_USB_EP_DATA,
						   skb, NULL);
	} else {
		ret = adapter->if_ops.host_to_card(adapter,
						   MWIFIEX_TYPE_DATA,
						   skb, tx_param);
	}
	switch (ret) {
	case -ENOSR:
207
		mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
208 209 210 211 212 213 214 215 216 217 218 219 220 221
		break;
	case -EBUSY:
		if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
		    (adapter->pps_uapsd_mode) &&
		    (adapter->tx_lock_flag)) {
			priv->adapter->tx_lock_flag = false;
			if (local_tx_pd)
				local_tx_pd->flags = 0;
		}
		skb_queue_head(&adapter->tx_data_q, skb);
		if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
			atomic_add(tx_info->aggr_num, &adapter->tx_queued);
		else
			atomic_inc(&adapter->tx_queued);
222
		mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
223 224
		break;
	case -1:
225
		if (adapter->iface_type == MWIFIEX_USB)
226
			adapter->data_sent = false;
227 228
		mwifiex_dbg(adapter, ERROR,
			    "mwifiex_write_data_async failed: 0x%X\n", ret);
229 230 231 232
		adapter->dbg.num_tx_host_to_card_failure++;
		mwifiex_write_data_complete(adapter, skb, 0, ret);
		break;
	case -EINPROGRESS:
233
		if (adapter->iface_type == MWIFIEX_USB)
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
			adapter->data_sent = false;
		break;
	case 0:
		mwifiex_write_data_complete(adapter, skb, 0, ret);
		break;
	default:
		break;
	}
	return ret;
}

static int
mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter)
{
	struct sk_buff *skb, *skb_next;
	struct mwifiex_txinfo *tx_info;
	struct mwifiex_tx_param tx_param;

	skb = skb_dequeue(&adapter->tx_data_q);
	if (!skb)
		return -1;

	tx_info = MWIFIEX_SKB_TXCB(skb);
	if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
		atomic_sub(tx_info->aggr_num, &adapter->tx_queued);
	else
		atomic_dec(&adapter->tx_queued);

	if (!skb_queue_empty(&adapter->tx_data_q))
		skb_next = skb_peek(&adapter->tx_data_q);
	else
		skb_next = NULL;
	tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0);
	if (!tx_param.next_pkt_len) {
		if (!mwifiex_wmm_lists_empty(adapter))
			tx_param.next_pkt_len = 1;
	}
	return mwifiex_host_to_card(adapter, skb, &tx_param);
}

void
mwifiex_process_tx_queue(struct mwifiex_adapter *adapter)
{
	do {
		if (adapter->data_sent || adapter->tx_lock_flag)
			break;
		if (mwifiex_dequeue_tx_queue(adapter))
			break;
	} while (!skb_queue_empty(&adapter->tx_data_q));
}

285 286 287 288 289 290 291 292
/*
 * Packet send completion callback handler.
 *
 * It either frees the buffer directly or forwards it to another
 * completion callback which checks conditions, updates statistics,
 * wakes up stalled traffic queue if required, and then frees the buffer.
 */
int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
A
Avinash Patil 已提交
293
				struct sk_buff *skb, int aggr, int status)
294
{
A
Avinash Patil 已提交
295
	struct mwifiex_private *priv;
296
	struct mwifiex_txinfo *tx_info;
A
Avinash Patil 已提交
297 298
	struct netdev_queue *txq;
	int index;
299 300 301 302 303

	if (!skb)
		return 0;

	tx_info = MWIFIEX_SKB_TXCB(skb);
304
	priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
305
				      tx_info->bss_type);
306 307 308
	if (!priv)
		goto done;

309 310 311
	if (adapter->iface_type == MWIFIEX_USB)
		adapter->data_sent = false;

312
	mwifiex_set_trans_start(priv->netdev);
313 314
	if (!status) {
		priv->stats.tx_packets++;
315
		priv->stats.tx_bytes += tx_info->pkt_len;
316 317
		if (priv->tx_timeout_cnt)
			priv->tx_timeout_cnt = 0;
318 319 320
	} else {
		priv->stats.tx_errors++;
	}
321

322
	if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
A
Avinash Patil 已提交
323
		atomic_dec_return(&adapter->pending_bridged_pkts);
324 325 326

	if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
		goto done;
A
Avinash Patil 已提交
327 328 329

	if (aggr)
		/* For skb_aggr, do not wake up tx queue */
330
		goto done;
331

A
Avinash Patil 已提交
332
	atomic_dec(&adapter->tx_pending);
333

A
Avinash Patil 已提交
334 335 336 337 338
	index = mwifiex_1d_to_wmm_queue[skb->priority];
	if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
		txq = netdev_get_tx_queue(priv->netdev, index);
		if (netif_tx_queue_stopped(txq)) {
			netif_tx_wake_queue(txq);
339
			mwifiex_dbg(adapter, DATA, "wake queue: %d\n", index);
A
Avinash Patil 已提交
340
		}
341 342 343 344 345 346
	}
done:
	dev_kfree_skb_any(skb);

	return 0;
}
347
EXPORT_SYMBOL_GPL(mwifiex_write_data_complete);
348

349 350 351 352 353 354
void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
				   void *event_body)
{
	struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
	struct sk_buff *ack_skb;
	unsigned long flags;
355
	struct mwifiex_txinfo *tx_info;
356 357 358 359 360 361 362 363 364 365

	if (!tx_status->tx_token_id)
		return;

	spin_lock_irqsave(&priv->ack_status_lock, flags);
	ack_skb = idr_find(&priv->ack_status_frames, tx_status->tx_token_id);
	if (ack_skb)
		idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
	spin_unlock_irqrestore(&priv->ack_status_lock, flags);

366 367 368 369 370 371 372
	if (ack_skb) {
		tx_info = MWIFIEX_SKB_TXCB(ack_skb);

		if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) {
			/* consumes ack_skb */
			skb_complete_wifi_ack(ack_skb, !tx_status->status);
		} else {
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
			/* Remove broadcast address which was added by driver */
			memmove(ack_skb->data +
				sizeof(struct ieee80211_hdr_3addr) +
				MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16),
				ack_skb->data +
				sizeof(struct ieee80211_hdr_3addr) +
				MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
				ETH_ALEN, ack_skb->len -
				(sizeof(struct ieee80211_hdr_3addr) +
				MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
				ETH_ALEN));
			ack_skb->len = ack_skb->len - ETH_ALEN;
			/* Remove driver's proprietary header including 2 bytes
			 * of packet length and pass actual management frame buffer
			 * to cfg80211.
			 */
389
			cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie,
390 391 392 393 394
						ack_skb->data +
						MWIFIEX_MGMT_FRAME_HEADER_SIZE +
						sizeof(u16), ack_skb->len -
						(MWIFIEX_MGMT_FRAME_HEADER_SIZE
						 + sizeof(u16)),
395 396 397 398
						!tx_status->status, GFP_ATOMIC);
			dev_kfree_skb_any(ack_skb);
		}
	}
399
}