tx.c 30.1 KB
Newer Older
L
Luciano Coelho 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * This file is part of wl1271
 *
 * Copyright (C) 2009 Nokia Corporation
 *
 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
26
#include <linux/etherdevice.h>
L
Luciano Coelho 已提交
27

28
#include "wlcore.h"
29
#include "debug.h"
S
Shahar Levi 已提交
30 31 32
#include "io.h"
#include "ps.h"
#include "tx.h"
33
#include "event.h"
34
#include "hw_ops.h"
L
Luciano Coelho 已提交
35

36 37 38 39 40 41
/*
 * TODO: this is here just for now, it must be removed when the data
 * operations are in place.
 */
#include "../wl12xx/reg.h"

E
Eliad Peller 已提交
42 43
static int wl1271_set_default_wep_key(struct wl1271 *wl,
				      struct wl12xx_vif *wlvif, u8 id)
44 45
{
	int ret;
E
Eliad Peller 已提交
46
	bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
47 48

	if (is_ap)
E
Eliad Peller 已提交
49
		ret = wl12xx_cmd_set_default_wep_key(wl, id,
50
						     wlvif->ap.bcast_hlid);
51
	else
E
Eliad Peller 已提交
52
		ret = wl12xx_cmd_set_default_wep_key(wl, id, wlvif->sta.hlid);
53 54 55 56 57 58 59 60

	if (ret < 0)
		return ret;

	wl1271_debug(DEBUG_CRYPT, "default wep key idx: %d", (int)id);
	return 0;
}

61
static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
L
Luciano Coelho 已提交
62
{
63 64
	int id;

65 66
	id = find_first_zero_bit(wl->tx_frames_map, wl->num_tx_desc);
	if (id >= wl->num_tx_desc)
67 68 69 70 71 72 73
		return -EBUSY;

	__set_bit(id, wl->tx_frames_map);
	wl->tx_frames[id] = skb;
	wl->tx_frames_cnt++;
	return id;
}
L
Luciano Coelho 已提交
74

75
void wl1271_free_tx_id(struct wl1271 *wl, int id)
76 77
{
	if (__test_and_clear_bit(id, wl->tx_frames_map)) {
78
		if (unlikely(wl->tx_frames_cnt == wl->num_tx_desc))
79 80
			clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);

81 82 83
		wl->tx_frames[id] = NULL;
		wl->tx_frames_cnt--;
	}
L
Luciano Coelho 已提交
84
}
85
EXPORT_SYMBOL(wl1271_free_tx_id);
L
Luciano Coelho 已提交
86

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
						 struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr;

	/*
	 * add the station to the known list before transmitting the
	 * authentication response. this way it won't get de-authed by FW
	 * when transmitting too soon.
	 */
	hdr = (struct ieee80211_hdr *)(skb->data +
				       sizeof(struct wl1271_tx_hw_descr));
	if (ieee80211_is_auth(hdr->frame_control))
		wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
}

103 104 105
static void wl1271_tx_regulate_link(struct wl1271 *wl,
				    struct wl12xx_vif *wlvif,
				    u8 hlid)
106
{
107
	bool fw_ps, single_sta;
108
	u8 tx_pkts;
109

110
	if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
111 112 113
		return;

	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
114
	tx_pkts = wl->links[hlid].allocated_pkts;
115
	single_sta = (wl->active_sta_count == 1);
116 117 118 119

	/*
	 * if in FW PS and there is enough data in FW we can put the link
	 * into high-level PS and clean out its TX queues.
120 121
	 * Make an exception if this is the only connected station. In this
	 * case FW-memory congestion is not a problem.
122
	 */
123
	if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
124
		wl12xx_ps_link_start(wl, wlvif, hlid, true);
125 126
}

127
bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
E
Eliad Peller 已提交
128 129 130
{
	return wl->dummy_packet == skb;
}
131
EXPORT_SYMBOL(wl12xx_is_dummy_packet);
E
Eliad Peller 已提交
132

133 134
u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif,
			 struct sk_buff *skb)
135 136 137 138 139 140 141 142 143 144 145 146
{
	struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb);

	if (control->control.sta) {
		struct wl1271_station *wl_sta;

		wl_sta = (struct wl1271_station *)
				control->control.sta->drv_priv;
		return wl_sta->hlid;
	} else {
		struct ieee80211_hdr *hdr;

147
		if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
E
Eliad Peller 已提交
148 149
			return wl->system_hlid;

150
		hdr = (struct ieee80211_hdr *)skb->data;
151
		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
152
			return wlvif->ap.bcast_hlid;
153 154
		else
			return wlvif->ap.global_hlid;
155 156 157
	}
}

158 159
u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
		      struct sk_buff *skb)
E
Eliad Peller 已提交
160
{
161 162
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;

E
Eliad Peller 已提交
163
	if (!wlvif || wl12xx_is_dummy_packet(wl, skb))
E
Eliad Peller 已提交
164 165
		return wl->system_hlid;

E
Eliad Peller 已提交
166
	if (wlvif->bss_type == BSS_TYPE_AP_BSS)
167
		return wl12xx_tx_get_hlid_ap(wl, wlvif, skb);
E
Eliad Peller 已提交
168

169
	if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
170
	     test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) &&
171 172
	    !ieee80211_is_auth(hdr->frame_control) &&
	    !ieee80211_is_assoc_req(hdr->frame_control))
E
Eliad Peller 已提交
173
		return wlvif->sta.hlid;
E
Eliad Peller 已提交
174
	else
E
Eliad Peller 已提交
175
		return wlvif->dev_hlid;
E
Eliad Peller 已提交
176 177
}

178 179
unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl,
					  unsigned int packet_length)
180
{
181 182
	if ((wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) ||
	    !(wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN))
183
		return ALIGN(packet_length, WL1271_TX_ALIGN_TO);
184 185
	else
		return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE);
186
}
187
EXPORT_SYMBOL(wlcore_calc_packet_alignment);
188

189
static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
E
Eliad Peller 已提交
190
			      struct sk_buff *skb, u32 extra, u32 buf_offset,
191
			      u8 hlid, bool is_gem)
L
Luciano Coelho 已提交
192 193 194
{
	struct wl1271_tx_hw_descr *desc;
	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
195
	u32 total_blocks;
196
	int id, ret = -EBUSY, ac;
197
	u32 spare_blocks;
L
Luciano Coelho 已提交
198

199
	if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
I
Ido Yariv 已提交
200
		return -EAGAIN;
201

202 203
	spare_blocks = wlcore_hw_get_spare_blocks(wl, is_gem);

L
Luciano Coelho 已提交
204
	/* allocate free identifier for the packet */
205
	id = wl1271_alloc_tx_id(wl, skb);
L
Luciano Coelho 已提交
206 207 208
	if (id < 0)
		return id;

209
	total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks);
210

L
Luciano Coelho 已提交
211 212 213 214
	if (total_blocks <= wl->tx_blocks_available) {
		desc = (struct wl1271_tx_hw_descr *)skb_push(
			skb, total_len - skb->len);

215 216
		wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks,
					     spare_blocks);
217

L
Luciano Coelho 已提交
218 219 220
		desc->id = id;

		wl->tx_blocks_available -= total_blocks;
221
		wl->tx_allocated_blocks += total_blocks;
L
Luciano Coelho 已提交
222

A
Arik Nemtsov 已提交
223 224 225 226
		/* If the FW was empty before, arm the Tx watchdog */
		if (wl->tx_allocated_blocks == total_blocks)
			wl12xx_rearm_tx_watchdog_locked(wl);

227 228
		ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
		wl->tx_allocated_pkts[ac]++;
229

230
		if (!wl12xx_is_dummy_packet(wl, skb) && wlvif &&
E
Eliad Peller 已提交
231
		    wlvif->bss_type == BSS_TYPE_AP_BSS &&
232
		    test_bit(hlid, wlvif->ap.sta_hlid_map))
233
			wl->links[hlid].allocated_pkts++;
234

L
Luciano Coelho 已提交
235 236 237 238 239
		ret = 0;

		wl1271_debug(DEBUG_TX,
			     "tx_allocate: size: %d, blocks: %d, id: %d",
			     total_len, total_blocks, id);
240
	} else {
241
		wl1271_free_tx_id(wl, id);
242
	}
L
Luciano Coelho 已提交
243 244 245 246

	return ret;
}

247
static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
E
Eliad Peller 已提交
248 249
			       struct sk_buff *skb, u32 extra,
			       struct ieee80211_tx_info *control, u8 hlid)
L
Luciano Coelho 已提交
250
{
251
	struct timespec ts;
L
Luciano Coelho 已提交
252
	struct wl1271_tx_hw_descr *desc;
253
	int ac, rate_idx;
254
	s64 hosttime;
255
	u16 tx_attr = 0;
256 257 258
	__le16 frame_control;
	struct ieee80211_hdr *hdr;
	u8 *frame_start;
259
	bool is_dummy;
L
Luciano Coelho 已提交
260 261

	desc = (struct wl1271_tx_hw_descr *) skb->data;
262 263 264
	frame_start = (u8 *)(desc + 1);
	hdr = (struct ieee80211_hdr *)(frame_start + extra);
	frame_control = hdr->frame_control;
L
Luciano Coelho 已提交
265

266 267
	/* relocate space for security header */
	if (extra) {
268 269
		int hdrlen = ieee80211_hdrlen(frame_control);
		memmove(frame_start, hdr, hdrlen);
270
		skb_set_network_header(skb, skb_network_offset(skb) + extra);
271 272
	}

L
Luciano Coelho 已提交
273
	/* configure packet life time */
274 275 276
	getnstimeofday(&ts);
	hosttime = (timespec_to_ns(&ts) >> 10);
	desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
277

278
	is_dummy = wl12xx_is_dummy_packet(wl, skb);
E
Eliad Peller 已提交
279
	if (is_dummy || !wlvif || wlvif->bss_type != BSS_TYPE_AP_BSS)
280 281 282
		desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
	else
		desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
L
Luciano Coelho 已提交
283

284
	/* queue */
K
Kalle Valo 已提交
285
	ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
286
	desc->tid = skb->priority;
287

288
	if (is_dummy) {
289 290 291 292
		/*
		 * FW expects the dummy packet to have an invalid session id -
		 * any session id that is different than the one set in the join
		 */
293
		tx_attr = (SESSION_COUNTER_INVALID <<
294 295 296 297
			   TX_HW_ATTR_OFST_SESSION_COUNTER) &
			   TX_HW_ATTR_SESSION_COUNTER;

		tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ;
E
Eliad Peller 已提交
298
	} else if (wlvif) {
299
		/* configure the tx attributes */
300 301
		tx_attr = wlvif->session_counter <<
			  TX_HW_ATTR_OFST_SESSION_COUNTER;
302 303
	}

E
Eliad Peller 已提交
304
	desc->hlid = hlid;
E
Eliad Peller 已提交
305
	if (is_dummy || !wlvif)
306 307
		rate_idx = 0;
	else if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
308 309 310 311 312
		/*
		 * if the packets are destined for AP (have a STA entry)
		 * send them with AP rate policies (EAPOLs are an exception),
		 * otherwise use default basic rates
		 */
313 314
		if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
			rate_idx = wlvif->sta.p2p_rate_idx;
315 316
		else if (skb->protocol == cpu_to_be16(ETH_P_PAE))
			rate_idx = wlvif->sta.basic_rate_idx;
317
		else if (control->control.sta)
E
Eliad Peller 已提交
318
			rate_idx = wlvif->sta.ap_rate_idx;
319
		else
E
Eliad Peller 已提交
320
			rate_idx = wlvif->sta.basic_rate_idx;
321
	} else {
322
		if (hlid == wlvif->ap.global_hlid)
E
Eliad Peller 已提交
323
			rate_idx = wlvif->ap.mgmt_rate_idx;
324
		else if (hlid == wlvif->ap.bcast_hlid)
E
Eliad Peller 已提交
325
			rate_idx = wlvif->ap.bcast_rate_idx;
326
		else
E
Eliad Peller 已提交
327
			rate_idx = wlvif->ap.ucast_rate_idx[ac];
328 329 330
	}

	tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
L
Luciano Coelho 已提交
331

332 333 334 335 336
	/* for WEP shared auth - no fw encryption is needed */
	if (ieee80211_is_auth(frame_control) &&
	    ieee80211_has_protected(frame_control))
		tx_attr |= TX_HW_ATTR_HOST_ENCRYPT;

L
Luciano Coelho 已提交
337
	desc->tx_attr = cpu_to_le16(tx_attr);
338

339
	wlcore_hw_set_tx_desc_csum(wl, desc, skb);
340
	wlcore_hw_set_tx_desc_data_len(wl, desc, skb);
L
Luciano Coelho 已提交
341 342 343
}

/* caller must hold wl->mutex */
344 345
static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
				   struct sk_buff *skb, u32 buf_offset)
L
Luciano Coelho 已提交
346 347 348 349
{
	struct ieee80211_tx_info *info;
	u32 extra = 0;
	int ret = 0;
350
	u32 total_len;
351
	u8 hlid;
E
Eliad Peller 已提交
352
	bool is_dummy;
353
	bool is_gem = false;
L
Luciano Coelho 已提交
354 355 356 357 358 359

	if (!skb)
		return -EINVAL;

	info = IEEE80211_SKB_CB(skb);

E
Eliad Peller 已提交
360 361 362
	/* TODO: handle dummy packets on multi-vifs */
	is_dummy = wl12xx_is_dummy_packet(wl, skb);

363 364
	if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) &&
	    info->control.hw_key &&
365
	    info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
366
		extra = WL1271_EXTRA_SPACE_TKIP;
L
Luciano Coelho 已提交
367 368

	if (info->control.hw_key) {
369 370 371 372 373 374
		bool is_wep;
		u8 idx = info->control.hw_key->hw_key_idx;
		u32 cipher = info->control.hw_key->cipher;

		is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) ||
			 (cipher == WLAN_CIPHER_SUITE_WEP104);
L
Luciano Coelho 已提交
375

E
Eliad Peller 已提交
376
		if (unlikely(is_wep && wlvif->default_key != idx)) {
E
Eliad Peller 已提交
377
			ret = wl1271_set_default_wep_key(wl, wlvif, idx);
L
Luciano Coelho 已提交
378 379
			if (ret < 0)
				return ret;
E
Eliad Peller 已提交
380
			wlvif->default_key = idx;
L
Luciano Coelho 已提交
381
		}
382 383

		is_gem = (cipher == WL1271_CIPHER_SUITE_GEM);
L
Luciano Coelho 已提交
384
	}
385
	hlid = wl12xx_tx_get_hlid(wl, wlvif, skb);
E
Eliad Peller 已提交
386
	if (hlid == WL12XX_INVALID_LINK_ID) {
387
		wl1271_error("invalid hlid. dropping skb 0x%p", skb);
E
Eliad Peller 已提交
388 389
		return -EINVAL;
	}
390

391 392
	ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid,
				 is_gem);
L
Luciano Coelho 已提交
393 394 395
	if (ret < 0)
		return ret;

396
	wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid);
397

E
Eliad Peller 已提交
398
	if (!is_dummy && wlvif && wlvif->bss_type == BSS_TYPE_AP_BSS) {
399
		wl1271_tx_ap_update_inconnection_sta(wl, skb);
400
		wl1271_tx_regulate_link(wl, wlvif, hlid);
401
	}
402

403
	/*
404 405 406 407 408 409
	 * The length of each packet is stored in terms of
	 * words. Thus, we must pad the skb data to make sure its
	 * length is aligned.  The number of padding bytes is computed
	 * and set in wl1271_tx_fill_hdr.
	 * In special cases, we want to align to a specific block size
	 * (eg. for wl128x with SDIO we align to 256).
410
	 */
411
	total_len = wlcore_calc_packet_alignment(wl, skb->len);
412

413 414
	memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
	memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
L
Luciano Coelho 已提交
415

416
	/* Revert side effects in the dummy packet skb, so it can be reused */
E
Eliad Peller 已提交
417
	if (is_dummy)
418 419
		skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));

420
	return total_len;
L
Luciano Coelho 已提交
421 422
}

423 424
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
				enum ieee80211_band rate_band)
425 426 427 428 429
{
	struct ieee80211_supported_band *band;
	u32 enabled_rates = 0;
	int bit;

430
	band = wl->hw->wiphy->bands[rate_band];
431 432 433 434 435 436
	for (bit = 0; bit < band->n_bitrates; bit++) {
		if (rate_set & 0x1)
			enabled_rates |= band->bitrates[bit].hw_value;
		rate_set >>= 1;
	}

A
Arik Nemtsov 已提交
437
	/* MCS rates indication are on bits 16 - 31 */
438 439
	rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates;

A
Arik Nemtsov 已提交
440
	for (bit = 0; bit < 16; bit++) {
441 442 443 444 445
		if (rate_set & 0x1)
			enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit);
		rate_set >>= 1;
	}

446 447 448
	return enabled_rates;
}

449
void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
450
{
451
	int i;
452

453
	for (i = 0; i < NUM_TX_QUEUES; i++) {
454 455
		if (wlcore_is_queue_stopped_by_reason(wl, i,
			WLCORE_QUEUE_STOP_REASON_WATERMARK) &&
456
		    wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) {
457
			/* firmware buffer has space, restart queues */
458 459
			wlcore_wake_queue(wl, i,
					  WLCORE_QUEUE_STOP_REASON_WATERMARK);
460
		}
461 462 463
	}
}

464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
						struct sk_buff_head *queues)
{
	int i, q = -1, ac;
	u32 min_pkts = 0xffffffff;

	/*
	 * Find a non-empty ac where:
	 * 1. There are packets to transmit
	 * 2. The FW has the least allocated blocks
	 *
	 * We prioritize the ACs according to VO>VI>BE>BK
	 */
	for (i = 0; i < NUM_TX_QUEUES; i++) {
		ac = wl1271_tx_get_queue(i);
		if (!skb_queue_empty(&queues[ac]) &&
		    (wl->tx_allocated_pkts[ac] < min_pkts)) {
			q = ac;
			min_pkts = wl->tx_allocated_pkts[q];
		}
	}

	if (q == -1)
		return NULL;

	return &queues[q];
}

492 493
static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl,
					      struct wl1271_link *lnk)
494
{
495
	struct sk_buff *skb;
496
	unsigned long flags;
497
	struct sk_buff_head *queue;
498

499
	queue = wl1271_select_queue(wl, lnk->tx_queue);
500
	if (!queue)
501
		return NULL;
502 503

	skb = skb_dequeue(queue);
504
	if (skb) {
505
		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
506
		spin_lock_irqsave(&wl->wl_lock, flags);
507
		WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
508
		wl->tx_queue_count[q]--;
509 510 511 512 513 514
		spin_unlock_irqrestore(&wl->wl_lock, flags);
	}

	return skb;
}

515 516
static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl,
					      struct wl12xx_vif *wlvif)
517 518 519 520 521
{
	struct sk_buff *skb = NULL;
	int i, h, start_hlid;

	/* start from the link after the last one */
522
	start_hlid = (wlvif->last_tx_hlid + 1) % WL12XX_MAX_LINKS;
523 524

	/* dequeue according to AC, round robin on each link */
525 526
	for (i = 0; i < WL12XX_MAX_LINKS; i++) {
		h = (start_hlid + i) % WL12XX_MAX_LINKS;
527

528
		/* only consider connected stations */
529
		if (!test_bit(h, wlvif->links_map))
530 531
			continue;

532 533
		skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[h]);
		if (!skb)
534 535
			continue;

536 537
		wlvif->last_tx_hlid = h;
		break;
538 539
	}

540
	if (!skb)
541
		wlvif->last_tx_hlid = 0;
542 543 544 545

	return skb;
}

546
static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
547
{
548
	unsigned long flags;
549
	struct wl12xx_vif *wlvif = wl->last_wlvif;
550 551
	struct sk_buff *skb = NULL;

552
	/* continue from last wlvif (round robin) */
553 554 555 556 557 558 559 560 561 562
	if (wlvif) {
		wl12xx_for_each_wlvif_continue(wl, wlvif) {
			skb = wl12xx_vif_skb_dequeue(wl, wlvif);
			if (skb) {
				wl->last_wlvif = wlvif;
				break;
			}
		}
	}

563 564 565 566 567
	/* dequeue from the system HLID before the restarting wlvif list */
	if (!skb)
		skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]);

	/* do a new pass over the wlvif list */
568 569 570 571 572 573 574
	if (!skb) {
		wl12xx_for_each_wlvif(wl, wlvif) {
			skb = wl12xx_vif_skb_dequeue(wl, wlvif);
			if (skb) {
				wl->last_wlvif = wlvif;
				break;
			}
575 576 577 578 579 580 581

			/*
			 * No need to continue after last_wlvif. The previous
			 * pass should have found it.
			 */
			if (wlvif == wl->last_wlvif)
				break;
582
		}
583 584
	}

585 586
	if (!skb &&
	    test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
587 588
		int q;

589
		skb = wl->dummy_packet;
590
		q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
591
		spin_lock_irqsave(&wl->wl_lock, flags);
592
		WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
593
		wl->tx_queue_count[q]--;
594 595 596 597
		spin_unlock_irqrestore(&wl->wl_lock, flags);
	}

	return skb;
598 599
}

600
static void wl1271_skb_queue_head(struct wl1271 *wl, struct wl12xx_vif *wlvif,
E
Eliad Peller 已提交
601
				  struct sk_buff *skb)
602 603 604 605
{
	unsigned long flags;
	int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));

606 607
	if (wl12xx_is_dummy_packet(wl, skb)) {
		set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
608 609
	} else {
		u8 hlid = wl12xx_tx_get_hlid(wl, wlvif, skb);
610 611 612
		skb_queue_head(&wl->links[hlid].tx_queue[q], skb);

		/* make sure we dequeue the same packet next time */
613
		wlvif->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) %
614
				      WL12XX_MAX_LINKS;
615 616
	}

617
	spin_lock_irqsave(&wl->wl_lock, flags);
618
	wl->tx_queue_count[q]++;
619 620 621
	spin_unlock_irqrestore(&wl->wl_lock, flags);
}

622 623 624 625 626 627 628
static bool wl1271_tx_is_data_present(struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);

	return ieee80211_is_data_present(hdr->frame_control);
}

E
Eliad Peller 已提交
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
{
	struct wl12xx_vif *wlvif;
	u32 timeout;
	u8 hlid;

	if (!wl->conf.rx_streaming.interval)
		return;

	if (!wl->conf.rx_streaming.always &&
	    !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))
		return;

	timeout = wl->conf.rx_streaming.duration;
	wl12xx_for_each_wlvif_sta(wl, wlvif) {
		bool found = false;
		for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) {
			if (test_bit(hlid, wlvif->links_map)) {
				found  = true;
				break;
			}
		}

		if (!found)
			continue;

		/* enable rx streaming */
656
		if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags))
E
Eliad Peller 已提交
657 658 659 660 661 662 663 664
			ieee80211_queue_work(wl->hw,
					     &wlvif->rx_streaming_enable_work);

		mod_timer(&wlvif->rx_streaming_timer,
			  jiffies + msecs_to_jiffies(timeout));
	}
}

665
void wl1271_tx_work_locked(struct wl1271 *wl)
L
Luciano Coelho 已提交
666
{
667
	struct wl12xx_vif *wlvif;
L
Luciano Coelho 已提交
668
	struct sk_buff *skb;
E
Eliad Peller 已提交
669
	struct wl1271_tx_hw_descr *desc;
670
	u32 buf_offset = 0, last_len = 0;
I
Ido Yariv 已提交
671
	bool sent_packets = false;
E
Eliad Peller 已提交
672
	unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
L
Luciano Coelho 已提交
673 674 675
	int ret;

	if (unlikely(wl->state == WL1271_STATE_OFF))
676
		return;
L
Luciano Coelho 已提交
677

678
	while ((skb = wl1271_skb_dequeue(wl))) {
E
Eliad Peller 已提交
679
		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
E
Eliad Peller 已提交
680 681
		bool has_data = false;

682
		wlvif = NULL;
E
Eliad Peller 已提交
683 684
		if (!wl12xx_is_dummy_packet(wl, skb) && info->control.vif)
			wlvif = wl12xx_vif_to_data(info->control.vif);
685

E
Eliad Peller 已提交
686
		has_data = wlvif && wl1271_tx_is_data_present(skb);
687
		ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset);
I
Ido Yariv 已提交
688
		if (ret == -EAGAIN) {
689
			/*
I
Ido Yariv 已提交
690 691 692
			 * Aggregation buffer is full.
			 * Flush buffer and try again.
			 */
693
			wl1271_skb_queue_head(wl, wlvif, skb);
694 695 696

			buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset,
							    last_len);
697 698
			wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
					  buf_offset, true);
I
Ido Yariv 已提交
699 700 701 702 703 704
			sent_packets = true;
			buf_offset = 0;
			continue;
		} else if (ret == -EBUSY) {
			/*
			 * Firmware buffer is full.
705 706
			 * Queue back last skb, and stop aggregating.
			 */
707
			wl1271_skb_queue_head(wl, wlvif, skb);
I
Ido Yariv 已提交
708 709
			/* No work left, avoid scheduling redundant tx work */
			set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
710
			goto out_ack;
L
Luciano Coelho 已提交
711
		} else if (ret < 0) {
E
Eliad Peller 已提交
712 713 714 715 716 717 718 719
			if (wl12xx_is_dummy_packet(wl, skb))
				/*
				 * fw still expects dummy packet,
				 * so re-enqueue it
				 */
				wl1271_skb_queue_head(wl, wlvif, skb);
			else
				ieee80211_free_txskb(wl->hw, skb);
720
			goto out_ack;
L
Luciano Coelho 已提交
721
		}
722 723
		last_len = ret;
		buf_offset += last_len;
724
		wl->tx_packets_count++;
E
Eliad Peller 已提交
725 726 727 728
		if (has_data) {
			desc = (struct wl1271_tx_hw_descr *) skb->data;
			__set_bit(desc->hlid, active_hlids);
		}
L
Luciano Coelho 已提交
729 730
	}

731
out_ack:
732
	if (buf_offset) {
733
		buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len);
734 735
		wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
				  buf_offset, true);
I
Ido Yariv 已提交
736 737 738
		sent_packets = true;
	}
	if (sent_packets) {
739 740 741 742
		/*
		 * Interrupt the firmware with the new packets. This is only
		 * required for older hardware revisions
		 */
743
		if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION)
744
			wl1271_write32(wl, WL12XX_HOST_WR_ACCESS,
745 746
				       wl->tx_packets_count);

747
		wl1271_handle_tx_low_watermark(wl);
748
	}
E
Eliad Peller 已提交
749
	wl12xx_rearm_rx_streaming(wl, active_hlids);
I
Ido Yariv 已提交
750
}
L
Luciano Coelho 已提交
751

I
Ido Yariv 已提交
752 753 754
void wl1271_tx_work(struct work_struct *work)
{
	struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
755
	int ret;
I
Ido Yariv 已提交
756 757

	mutex_lock(&wl->mutex);
758 759 760 761
	ret = wl1271_ps_elp_wakeup(wl);
	if (ret < 0)
		goto out;

762
	wl1271_tx_work_locked(wl);
763

764
	wl1271_ps_elp_sleep(wl);
765
out:
L
Luciano Coelho 已提交
766 767 768
	mutex_unlock(&wl->mutex);
}

769 770
static u8 wl1271_tx_get_rate_flags(u8 rate_class_index)
{
771 772
	u8 flags = 0;

773 774 775 776 777
	/*
	 * TODO: use wl12xx constants when this code is moved to wl12xx, as
	 * only it uses Tx-completion.
	 */
	if (rate_class_index <= 8)
778
		flags |= IEEE80211_TX_RC_MCS;
779 780 781 782 783 784

	/*
	 * TODO: use wl12xx constants when this code is moved to wl12xx, as
	 * only it uses Tx-completion.
	 */
	if (rate_class_index == 0)
785
		flags |= IEEE80211_TX_RC_SHORT_GI;
786

787
	return flags;
788 789
}

L
Luciano Coelho 已提交
790 791 792 793
static void wl1271_tx_complete_packet(struct wl1271 *wl,
				      struct wl1271_tx_hw_res_descr *result)
{
	struct ieee80211_tx_info *info;
794 795
	struct ieee80211_vif *vif;
	struct wl12xx_vif *wlvif;
L
Luciano Coelho 已提交
796 797
	struct sk_buff *skb;
	int id = result->id;
J
Juuso Oikarinen 已提交
798
	int rate = -1;
799
	u8 rate_flags = 0;
J
Juuso Oikarinen 已提交
800
	u8 retries = 0;
L
Luciano Coelho 已提交
801 802

	/* check for id legality */
803
	if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) {
L
Luciano Coelho 已提交
804 805 806 807 808 809 810
		wl1271_warning("TX result illegal id: %d", id);
		return;
	}

	skb = wl->tx_frames[id];
	info = IEEE80211_SKB_CB(skb);

811
	if (wl12xx_is_dummy_packet(wl, skb)) {
812 813 814 815
		wl1271_free_tx_id(wl, id);
		return;
	}

816 817 818 819
	/* info->control is valid as long as we don't update info->status */
	vif = info->control.vif;
	wlvif = wl12xx_vif_to_data(vif);

J
Juuso Oikarinen 已提交
820 821 822
	/* update the TX status info */
	if (result->status == TX_SUCCESS) {
		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
L
Luciano Coelho 已提交
823
			info->flags |= IEEE80211_TX_STAT_ACK;
824
		rate = wlcore_rate_to_idx(wl, result->rate_class_index,
E
Eliad Peller 已提交
825
					  wlvif->band);
826
		rate_flags = wl1271_tx_get_rate_flags(result->rate_class_index);
J
Juuso Oikarinen 已提交
827 828 829 830
		retries = result->ack_failures;
	} else if (result->status == TX_RETRY_EXCEEDED) {
		wl->stats.excessive_retries++;
		retries = result->ack_failures;
L
Luciano Coelho 已提交
831 832
	}

J
Juuso Oikarinen 已提交
833 834
	info->status.rates[0].idx = rate;
	info->status.rates[0].count = retries;
835
	info->status.rates[0].flags = rate_flags;
J
Juuso Oikarinen 已提交
836 837
	info->status.ack_signal = -1;

L
Luciano Coelho 已提交
838 839
	wl->stats.retry_count += result->ack_failures;

840 841 842 843 844 845 846 847 848
	/*
	 * update sequence number only when relevant, i.e. only in
	 * sessions of TKIP, AES and GEM (not in open or WEP sessions)
	 */
	if (info->control.hw_key &&
	    (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP ||
	     info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP ||
	     info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) {
		u8 fw_lsb = result->tx_security_sequence_number_lsb;
849
		u8 cur_lsb = wlvif->tx_security_last_seq_lsb;
850 851 852 853 854

		/*
		 * update security sequence number, taking care of potential
		 * wrap-around
		 */
855 856
		wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff;
		wlvif->tx_security_last_seq_lsb = fw_lsb;
857
	}
858

859 860 861 862
	/* remove private header from packet */
	skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));

	/* remove TKIP header space if present */
863 864
	if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) &&
	    info->control.hw_key &&
865
	    info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
866
		int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
867 868 869
		memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data,
			hdrlen);
		skb_pull(skb, WL1271_EXTRA_SPACE_TKIP);
870
	}
L
Luciano Coelho 已提交
871 872 873 874 875 876 877

	wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
		     " status 0x%x",
		     result->id, skb, result->ack_failures,
		     result->rate_class_index, result->status);

	/* return the packet to the stack */
878
	skb_queue_tail(&wl->deferred_tx_queue, skb);
879
	queue_work(wl->freezable_wq, &wl->netstack_work);
880
	wl1271_free_tx_id(wl, result->id);
L
Luciano Coelho 已提交
881 882 883
}

/* Called upon reception of a TX complete interrupt */
884
void wl1271_tx_complete(struct wl1271 *wl)
L
Luciano Coelho 已提交
885 886 887
{
	struct wl1271_acx_mem_map *memmap =
		(struct wl1271_acx_mem_map *)wl->target_mem_map;
888
	u32 count, fw_counter;
L
Luciano Coelho 已提交
889 890 891
	u32 i;

	/* read the tx results from the chipset */
T
Teemu Paasikivi 已提交
892 893
	wl1271_read(wl, le32_to_cpu(memmap->tx_result),
		    wl->tx_res_if, sizeof(*wl->tx_res_if), false);
894 895 896 897 898 899 900 901
	fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter);

	/* write host counter to chipset (to ack) */
	wl1271_write32(wl, le32_to_cpu(memmap->tx_result) +
		       offsetof(struct wl1271_tx_hw_res_if,
				tx_result_host_counter), fw_counter);

	count = fw_counter - wl->tx_results_count;
902
	wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
L
Luciano Coelho 已提交
903 904

	/* verify that the result buffer is not getting overrun */
905
	if (unlikely(count > TX_HW_RESULT_QUEUE_LEN))
L
Luciano Coelho 已提交
906 907 908 909 910 911 912 913 914 915 916 917 918 919
		wl1271_warning("TX result overflow from chipset: %d", count);

	/* process the results */
	for (i = 0; i < count; i++) {
		struct wl1271_tx_hw_res_descr *result;
		u8 offset = wl->tx_results_count & TX_HW_RESULT_QUEUE_LEN_MASK;

		/* process the packet */
		result =  &(wl->tx_res_if->tx_results_queue[offset]);
		wl1271_tx_complete_packet(wl, result);

		wl->tx_results_count++;
	}
}
920
EXPORT_SYMBOL(wl1271_tx_complete);
L
Luciano Coelho 已提交
921

922 923 924
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
{
	struct sk_buff *skb;
925
	int i;
926
	unsigned long flags;
927
	struct ieee80211_tx_info *info;
928
	int total[NUM_TX_QUEUES];
929 930

	for (i = 0; i < NUM_TX_QUEUES; i++) {
931
		total[i] = 0;
932 933
		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
			wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);
934 935 936 937 938 939 940 941

			if (!wl12xx_is_dummy_packet(wl, skb)) {
				info = IEEE80211_SKB_CB(skb);
				info->status.rates[0].idx = -1;
				info->status.rates[0].count = 0;
				ieee80211_tx_status_ni(wl->hw, skb);
			}

942
			total[i]++;
943 944 945 946
		}
	}

	spin_lock_irqsave(&wl->wl_lock, flags);
947 948
	for (i = 0; i < NUM_TX_QUEUES; i++)
		wl->tx_queue_count[i] -= total[i];
949 950 951 952 953
	spin_unlock_irqrestore(&wl->wl_lock, flags);

	wl1271_handle_tx_low_watermark(wl);
}

954
/* caller must hold wl->mutex and TX must be stopped */
955
void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
L
Luciano Coelho 已提交
956 957 958 959
{
	int i;

	/* TX failure */
960 961
	for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) {
		if (wlvif->bss_type == BSS_TYPE_AP_BSS)
962
			wl1271_free_sta(wl, wlvif, i);
963 964
		else
			wlvif->sta.ba_rx_bitmap = 0;
965

966 967
		wl->links[i].allocated_pkts = 0;
		wl->links[i].prev_freed_pkts = 0;
L
Luciano Coelho 已提交
968
	}
969 970 971 972
	wlvif->last_tx_hlid = 0;

}
/* caller must hold wl->mutex and TX must be stopped */
973
void wl12xx_tx_reset(struct wl1271 *wl)
974 975 976 977
{
	int i;
	struct sk_buff *skb;
	struct ieee80211_tx_info *info;
978

979 980 981 982 983 984 985 986
	/* only reset the queues if something bad happened */
	if (WARN_ON_ONCE(wl1271_tx_total_queue_count(wl) != 0)) {
		for (i = 0; i < WL12XX_MAX_LINKS; i++)
			wl1271_tx_reset_link_queues(wl, i);

		for (i = 0; i < NUM_TX_QUEUES; i++)
			wl->tx_queue_count[i] = 0;
	}
987

988 989 990
	/*
	 * Make sure the driver is at a consistent state, in case this
	 * function is called from a context other than interface removal.
991
	 * This call will always wake the TX queues.
992
	 */
993
	wl1271_handle_tx_low_watermark(wl);
994

995
	for (i = 0; i < wl->num_tx_desc; i++) {
996 997 998 999 1000 1001 1002
		if (wl->tx_frames[i] == NULL)
			continue;

		skb = wl->tx_frames[i];
		wl1271_free_tx_id(wl, i);
		wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);

1003
		if (!wl12xx_is_dummy_packet(wl, skb)) {
1004 1005 1006 1007 1008 1009
			/*
			 * Remove private headers before passing the skb to
			 * mac80211
			 */
			info = IEEE80211_SKB_CB(skb);
			skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
1010 1011
			if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) &&
			    info->control.hw_key &&
1012 1013 1014
			    info->control.hw_key->cipher ==
			    WLAN_CIPHER_SUITE_TKIP) {
				int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1015
				memmove(skb->data + WL1271_EXTRA_SPACE_TKIP,
1016
					skb->data, hdrlen);
1017
				skb_pull(skb, WL1271_EXTRA_SPACE_TKIP);
1018
			}
1019

1020 1021
			info->status.rates[0].idx = -1;
			info->status.rates[0].count = 0;
1022

1023
			ieee80211_tx_status_ni(wl->hw, skb);
1024
		}
1025
	}
1026 1027 1028 1029 1030 1031 1032 1033
}

#define WL1271_TX_FLUSH_TIMEOUT 500000

/* caller must *NOT* hold wl->mutex */
void wl1271_tx_flush(struct wl1271 *wl)
{
	unsigned long timeout;
1034
	int i;
1035 1036
	timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT);

A
Arik Nemtsov 已提交
1037 1038 1039 1040 1041
	/* only one flush should be in progress, for consistent queue state */
	mutex_lock(&wl->flush_mutex);

	wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH);

1042 1043
	while (!time_after(jiffies, timeout)) {
		mutex_lock(&wl->mutex);
1044
		wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d",
1045 1046 1047 1048
			     wl->tx_frames_cnt,
			     wl1271_tx_total_queue_count(wl));
		if ((wl->tx_frames_cnt == 0) &&
		    (wl1271_tx_total_queue_count(wl) == 0)) {
1049
			mutex_unlock(&wl->mutex);
A
Arik Nemtsov 已提交
1050
			goto out;
1051 1052 1053 1054 1055 1056
		}
		mutex_unlock(&wl->mutex);
		msleep(1);
	}

	wl1271_warning("Unable to flush all TX buffers, timed out.");
1057 1058 1059 1060 1061 1062

	/* forcibly flush all Tx buffers on our queues */
	mutex_lock(&wl->mutex);
	for (i = 0; i < WL12XX_MAX_LINKS; i++)
		wl1271_tx_reset_link_queues(wl, i);
	mutex_unlock(&wl->mutex);
A
Arik Nemtsov 已提交
1063 1064 1065 1066

out:
	wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH);
	mutex_unlock(&wl->flush_mutex);
L
Luciano Coelho 已提交
1067
}
1068
EXPORT_SYMBOL_GPL(wl1271_tx_flush);
A
Arik Nemtsov 已提交
1069

1070
u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set)
A
Arik Nemtsov 已提交
1071
{
1072 1073
	if (WARN_ON(!rate_set))
		return 0;
A
Arik Nemtsov 已提交
1074

1075
	return BIT(__ffs(rate_set));
A
Arik Nemtsov 已提交
1076
}
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128

void wlcore_stop_queue_locked(struct wl1271 *wl, u8 queue,
			      enum wlcore_queue_stop_reason reason)
{
	bool stopped = !!wl->queue_stop_reasons[queue];

	/* queue should not be stopped for this reason */
	WARN_ON(test_and_set_bit(reason, &wl->queue_stop_reasons[queue]));

	if (stopped)
		return;

	ieee80211_stop_queue(wl->hw, wl1271_tx_get_mac80211_queue(queue));
}

void wlcore_stop_queue(struct wl1271 *wl, u8 queue,
		       enum wlcore_queue_stop_reason reason)
{
	unsigned long flags;

	spin_lock_irqsave(&wl->wl_lock, flags);
	wlcore_stop_queue_locked(wl, queue, reason);
	spin_unlock_irqrestore(&wl->wl_lock, flags);
}

void wlcore_wake_queue(struct wl1271 *wl, u8 queue,
		       enum wlcore_queue_stop_reason reason)
{
	unsigned long flags;

	spin_lock_irqsave(&wl->wl_lock, flags);

	/* queue should not be clear for this reason */
	WARN_ON(!test_and_clear_bit(reason, &wl->queue_stop_reasons[queue]));

	if (wl->queue_stop_reasons[queue])
		goto out;

	ieee80211_wake_queue(wl->hw, wl1271_tx_get_mac80211_queue(queue));

out:
	spin_unlock_irqrestore(&wl->wl_lock, flags);
}

void wlcore_stop_queues(struct wl1271 *wl,
			enum wlcore_queue_stop_reason reason)
{
	int i;

	for (i = 0; i < NUM_TX_QUEUES; i++)
		wlcore_stop_queue(wl, i, reason);
}
1129
EXPORT_SYMBOL_GPL(wlcore_stop_queues);
1130 1131 1132 1133 1134 1135 1136 1137 1138

void wlcore_wake_queues(struct wl1271 *wl,
			enum wlcore_queue_stop_reason reason)
{
	int i;

	for (i = 0; i < NUM_TX_QUEUES; i++)
		wlcore_wake_queue(wl, i, reason);
}
1139
EXPORT_SYMBOL_GPL(wlcore_wake_queues);
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169

void wlcore_reset_stopped_queues(struct wl1271 *wl)
{
	int i;
	unsigned long flags;

	spin_lock_irqsave(&wl->wl_lock, flags);

	for (i = 0; i < NUM_TX_QUEUES; i++) {
		if (!wl->queue_stop_reasons[i])
			continue;

		wl->queue_stop_reasons[i] = 0;
		ieee80211_wake_queue(wl->hw,
				     wl1271_tx_get_mac80211_queue(i));
	}

	spin_unlock_irqrestore(&wl->wl_lock, flags);
}

bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, u8 queue,
			     enum wlcore_queue_stop_reason reason)
{
	return test_bit(reason, &wl->queue_stop_reasons[queue]);
}

bool wlcore_is_queue_stopped(struct wl1271 *wl, u8 queue)
{
	return !!wl->queue_stop_reasons[queue];
}