tx.c 14.8 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

S
Shahar Levi 已提交
28 29 30 31 32
#include "wl12xx.h"
#include "io.h"
#include "reg.h"
#include "ps.h"
#include "tx.h"
L
Luciano Coelho 已提交
33

34
static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
L
Luciano Coelho 已提交
35
{
36 37 38 39 40 41 42 43 44 45 46
	int id;

	id = find_first_zero_bit(wl->tx_frames_map, ACX_TX_DESCRIPTORS);
	if (id >= ACX_TX_DESCRIPTORS)
		return -EBUSY;

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

48 49 50 51 52 53
static void wl1271_free_tx_id(struct wl1271 *wl, int id)
{
	if (__test_and_clear_bit(id, wl->tx_frames_map)) {
		wl->tx_frames[id] = NULL;
		wl->tx_frames_cnt--;
	}
L
Luciano Coelho 已提交
54 55
}

56 57
static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
				u32 buf_offset)
L
Luciano Coelho 已提交
58 59 60
{
	struct wl1271_tx_hw_descr *desc;
	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
61
	u32 total_blocks;
L
Luciano Coelho 已提交
62 63
	int id, ret = -EBUSY;

64
	if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
I
Ido Yariv 已提交
65
		return -EAGAIN;
66

L
Luciano Coelho 已提交
67
	/* allocate free identifier for the packet */
68
	id = wl1271_alloc_tx_id(wl, skb);
L
Luciano Coelho 已提交
69 70 71 72 73
	if (id < 0)
		return id;

	/* approximate the number of blocks required for this packet
	   in the firmware */
74 75
	total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
	total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE;
L
Luciano Coelho 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
	if (total_blocks <= wl->tx_blocks_available) {
		desc = (struct wl1271_tx_hw_descr *)skb_push(
			skb, total_len - skb->len);

		desc->extra_mem_blocks = TX_HW_BLOCK_SPARE;
		desc->total_mem_blocks = total_blocks;
		desc->id = id;

		wl->tx_blocks_available -= total_blocks;

		ret = 0;

		wl1271_debug(DEBUG_TX,
			     "tx_allocate: size: %d, blocks: %d, id: %d",
			     total_len, total_blocks, id);
91
	} else {
92
		wl1271_free_tx_id(wl, id);
93
	}
L
Luciano Coelho 已提交
94 95 96 97

	return ret;
}

98
static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
L
Luciano Coelho 已提交
99 100
			      u32 extra, struct ieee80211_tx_info *control)
{
101
	struct timespec ts;
L
Luciano Coelho 已提交
102
	struct wl1271_tx_hw_descr *desc;
103
	int pad, ac, rate_idx;
104
	s64 hosttime;
L
Luciano Coelho 已提交
105
	u16 tx_attr;
L
Luciano Coelho 已提交
106 107 108

	desc = (struct wl1271_tx_hw_descr *) skb->data;

109 110 111 112
	/* relocate space for security header */
	if (extra) {
		void *framestart = skb->data + sizeof(*desc);
		u16 fc = *(u16 *)(framestart + extra);
L
Luciano Coelho 已提交
113
		int hdrlen = ieee80211_hdrlen(cpu_to_le16(fc));
114 115 116
		memmove(framestart, framestart + extra, hdrlen);
	}

L
Luciano Coelho 已提交
117
	/* configure packet life time */
118 119 120
	getnstimeofday(&ts);
	hosttime = (timespec_to_ns(&ts) >> 10);
	desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
121 122 123 124 125

	if (wl->bss_type != BSS_TYPE_AP_BSS)
		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 已提交
126 127

	/* configure the tx attributes */
L
Luciano Coelho 已提交
128
	tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
K
Kalle Valo 已提交
129

130
	/* queue (we use same identifiers for tid's and ac's */
K
Kalle Valo 已提交
131
	ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
132
	desc->tid = ac;
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

	if (wl->bss_type != BSS_TYPE_AP_BSS) {
		desc->aid = TX_HW_DEFAULT_AID;

		/* if the packets are destined for AP (have a STA entry)
		   send them with AP rate policies, otherwise use default
		   basic rates */
		if (control->control.sta)
			rate_idx = ACX_TX_AP_FULL_RATE;
		else
			rate_idx = ACX_TX_BASIC_RATE;
	} else {
		if (control->control.sta) {
			struct wl1271_station *wl_sta;

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

			hdr = (struct ieee80211_hdr *)
						(skb->data + sizeof(*desc));
			if (ieee80211_is_mgmt(hdr->frame_control)) {
				desc->hlid = WL1271_AP_GLOBAL_HLID;
				rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
			} else {
				desc->hlid = WL1271_AP_BROADCAST_HLID;
				rate_idx = ACX_TX_AP_MODE_BCST_RATE;
			}
		}
	}

	tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
L
Luciano Coelho 已提交
168 169 170 171
	desc->reserved = 0;

	/* align the length (and store in terms of words) */
	pad = WL1271_TX_ALIGN(skb->len);
L
Luciano Coelho 已提交
172
	desc->length = cpu_to_le16(pad >> 2);
L
Luciano Coelho 已提交
173 174 175

	/* calculate number of padding bytes */
	pad = pad - skb->len;
L
Luciano Coelho 已提交
176 177 178
	tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;

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

180 181 182 183
	wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
		"tx_attr: 0x%x len: %d life: %d mem: %d", pad, (int)desc->hlid,
		(int)desc->tx_attr, (int)desc->length, (int)desc->life_time,
		(int)desc->total_mem_blocks);
L
Luciano Coelho 已提交
184 185 186
}

/* caller must hold wl->mutex */
187 188
static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
							u32 buf_offset)
L
Luciano Coelho 已提交
189 190 191 192 193
{
	struct ieee80211_tx_info *info;
	u32 extra = 0;
	int ret = 0;
	u8 idx;
194
	u32 total_len;
L
Luciano Coelho 已提交
195 196 197 198 199 200 201

	if (!skb)
		return -EINVAL;

	info = IEEE80211_SKB_CB(skb);

	if (info->control.hw_key &&
202
	    info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
L
Luciano Coelho 已提交
203 204 205 206 207 208 209
		extra = WL1271_TKIP_IV_SPACE;

	if (info->control.hw_key) {
		idx = info->control.hw_key->hw_key_idx;

		/* FIXME: do we have to do this if we're not using WEP? */
		if (unlikely(wl->default_key != idx)) {
210
			ret = wl1271_cmd_set_sta_default_wep_key(wl, idx);
L
Luciano Coelho 已提交
211 212
			if (ret < 0)
				return ret;
J
Juuso Oikarinen 已提交
213
			wl->default_key = idx;
L
Luciano Coelho 已提交
214 215 216
		}
	}

217
	ret = wl1271_tx_allocate(wl, skb, extra, buf_offset);
L
Luciano Coelho 已提交
218 219 220
	if (ret < 0)
		return ret;

221
	wl1271_tx_fill_hdr(wl, skb, extra, info);
L
Luciano Coelho 已提交
222

223 224 225 226 227 228 229 230
	/*
	 * 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
	 */
	total_len = WL1271_TX_ALIGN(skb->len);
	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 已提交
231

232
	return total_len;
L
Luciano Coelho 已提交
233 234
}

235
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
236 237 238 239 240 241 242 243 244 245 246 247
{
	struct ieee80211_supported_band *band;
	u32 enabled_rates = 0;
	int bit;

	band = wl->hw->wiphy->bands[wl->band];
	for (bit = 0; bit < band->n_bitrates; bit++) {
		if (rate_set & 0x1)
			enabled_rates |= band->bitrates[bit].hw_value;
		rate_set >>= 1;
	}

S
Shahar Levi 已提交
248
#ifdef CONFIG_WL12XX_HT
249 250 251 252 253 254 255 256 257 258
	/* MCS rates indication are on bits 16 - 23 */
	rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates;

	for (bit = 0; bit < 8; bit++) {
		if (rate_set & 0x1)
			enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit);
		rate_set >>= 1;
	}
#endif

259 260 261
	return enabled_rates;
}

262 263 264 265 266
static void handle_tx_low_watermark(struct wl1271 *wl)
{
	unsigned long flags;

	if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) &&
267
	    wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) {
268 269 270 271 272 273 274 275
		/* firmware buffer has space, restart queues */
		spin_lock_irqsave(&wl->wl_lock, flags);
		ieee80211_wake_queues(wl->hw);
		clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
		spin_unlock_irqrestore(&wl->wl_lock, flags);
	}
}

276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
{
	struct sk_buff *skb = NULL;
	unsigned long flags;

	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]);
	if (skb)
		goto out;
	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]);
	if (skb)
		goto out;
	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]);
	if (skb)
		goto out;
	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]);

out:
	if (skb) {
		spin_lock_irqsave(&wl->wl_lock, flags);
		wl->tx_queue_count--;
		spin_unlock_irqrestore(&wl->wl_lock, flags);
	}

	return skb;
}

static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
{
	unsigned long flags;
	int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));

	skb_queue_head(&wl->tx_queue[q], skb);
	spin_lock_irqsave(&wl->wl_lock, flags);
	wl->tx_queue_count++;
	spin_unlock_irqrestore(&wl->wl_lock, flags);
}

I
Ido Yariv 已提交
313
void wl1271_tx_work_locked(struct wl1271 *wl)
L
Luciano Coelho 已提交
314 315 316
{
	struct sk_buff *skb;
	bool woken_up = false;
317
	u32 sta_rates = 0;
I
Ido Yariv 已提交
318 319
	u32 buf_offset = 0;
	bool sent_packets = false;
L
Luciano Coelho 已提交
320 321
	int ret;

322 323 324 325
	/* check if the rates supported by the AP have changed */
	if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED,
					&wl->flags))) {
		unsigned long flags;
326

327 328 329 330 331
		spin_lock_irqsave(&wl->wl_lock, flags);
		sta_rates = wl->sta_rate_set;
		spin_unlock_irqrestore(&wl->wl_lock, flags);
	}

L
Luciano Coelho 已提交
332 333 334
	if (unlikely(wl->state == WL1271_STATE_OFF))
		goto out;

335 336
	/* if rates have changed, re-configure the rate policy */
	if (unlikely(sta_rates)) {
337 338 339 340 341
		ret = wl1271_ps_elp_wakeup(wl, false);
		if (ret < 0)
			goto out;
		woken_up = true;

342
		wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
343
		wl1271_acx_sta_rate_policies(wl);
344 345
	}

346
	while ((skb = wl1271_skb_dequeue(wl))) {
L
Luciano Coelho 已提交
347 348 349
		if (!woken_up) {
			ret = wl1271_ps_elp_wakeup(wl, false);
			if (ret < 0)
350
				goto out_ack;
L
Luciano Coelho 已提交
351 352 353
			woken_up = true;
		}

354
		ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
I
Ido Yariv 已提交
355
		if (ret == -EAGAIN) {
356
			/*
I
Ido Yariv 已提交
357 358 359
			 * Aggregation buffer is full.
			 * Flush buffer and try again.
			 */
360
			wl1271_skb_queue_head(wl, skb);
I
Ido Yariv 已提交
361
			wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
362
				     buf_offset, true);
I
Ido Yariv 已提交
363 364 365 366 367 368
			sent_packets = true;
			buf_offset = 0;
			continue;
		} else if (ret == -EBUSY) {
			/*
			 * Firmware buffer is full.
369 370
			 * Queue back last skb, and stop aggregating.
			 */
371
			wl1271_skb_queue_head(wl, skb);
I
Ido Yariv 已提交
372 373
			/* No work left, avoid scheduling redundant tx work */
			set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
374
			goto out_ack;
L
Luciano Coelho 已提交
375 376
		} else if (ret < 0) {
			dev_kfree_skb(skb);
377
			goto out_ack;
L
Luciano Coelho 已提交
378
		}
379 380
		buf_offset += ret;
		wl->tx_packets_count++;
L
Luciano Coelho 已提交
381 382
	}

383
out_ack:
384 385 386
	if (buf_offset) {
		wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
				buf_offset, true);
I
Ido Yariv 已提交
387 388 389
		sent_packets = true;
	}
	if (sent_packets) {
390
		/* interrupt the firmware with the new packets */
391
		wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
392
		handle_tx_low_watermark(wl);
393
	}
394

L
Luciano Coelho 已提交
395 396 397
out:
	if (woken_up)
		wl1271_ps_elp_sleep(wl);
I
Ido Yariv 已提交
398
}
L
Luciano Coelho 已提交
399

I
Ido Yariv 已提交
400 401 402 403 404 405
void wl1271_tx_work(struct work_struct *work)
{
	struct wl1271 *wl = container_of(work, struct wl1271, tx_work);

	mutex_lock(&wl->mutex);
	wl1271_tx_work_locked(wl);
L
Luciano Coelho 已提交
406 407 408 409 410 411 412 413 414
	mutex_unlock(&wl->mutex);
}

static void wl1271_tx_complete_packet(struct wl1271 *wl,
				      struct wl1271_tx_hw_res_descr *result)
{
	struct ieee80211_tx_info *info;
	struct sk_buff *skb;
	int id = result->id;
J
Juuso Oikarinen 已提交
415 416
	int rate = -1;
	u8 retries = 0;
L
Luciano Coelho 已提交
417 418

	/* check for id legality */
419
	if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) {
L
Luciano Coelho 已提交
420 421 422 423 424 425 426
		wl1271_warning("TX result illegal id: %d", id);
		return;
	}

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

J
Juuso Oikarinen 已提交
427 428 429
	/* update the TX status info */
	if (result->status == TX_SUCCESS) {
		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
L
Luciano Coelho 已提交
430
			info->flags |= IEEE80211_TX_STAT_ACK;
431
		rate = wl1271_rate_to_idx(result->rate_class_index, wl->band);
J
Juuso Oikarinen 已提交
432 433 434 435
		retries = result->ack_failures;
	} else if (result->status == TX_RETRY_EXCEEDED) {
		wl->stats.excessive_retries++;
		retries = result->ack_failures;
L
Luciano Coelho 已提交
436 437
	}

J
Juuso Oikarinen 已提交
438 439 440 441 442
	info->status.rates[0].idx = rate;
	info->status.rates[0].count = retries;
	info->status.rates[0].flags = 0;
	info->status.ack_signal = -1;

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

445
	/* update security sequence number */
446 447
	wl->tx_security_seq += (result->lsb_security_sequence_number -
				wl->tx_security_last_seq);
448 449
	wl->tx_security_last_seq = result->lsb_security_sequence_number;

450 451 452 453
	/* remove private header from packet */
	skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));

	/* remove TKIP header space if present */
L
Luciano Coelho 已提交
454
	if (info->control.hw_key &&
455
	    info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
456 457 458 459
		int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
		memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen);
		skb_pull(skb, WL1271_TKIP_IV_SPACE);
	}
L
Luciano Coelho 已提交
460 461 462 463 464 465 466 467

	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 */
	ieee80211_tx_status(wl->hw, skb);
468
	wl1271_free_tx_id(wl, result->id);
L
Luciano Coelho 已提交
469 470 471
}

/* Called upon reception of a TX complete interrupt */
472
void wl1271_tx_complete(struct wl1271 *wl)
L
Luciano Coelho 已提交
473 474 475
{
	struct wl1271_acx_mem_map *memmap =
		(struct wl1271_acx_mem_map *)wl->target_mem_map;
476
	u32 count, fw_counter;
L
Luciano Coelho 已提交
477 478 479
	u32 i;

	/* read the tx results from the chipset */
T
Teemu Paasikivi 已提交
480 481
	wl1271_read(wl, le32_to_cpu(memmap->tx_result),
		    wl->tx_res_if, sizeof(*wl->tx_res_if), false);
482 483 484 485 486 487 488 489
	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;
490
	wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
L
Luciano Coelho 已提交
491 492

	/* verify that the result buffer is not getting overrun */
493
	if (unlikely(count > TX_HW_RESULT_QUEUE_LEN))
L
Luciano Coelho 已提交
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
		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++;
	}
}

/* caller must hold wl->mutex */
510
void wl1271_tx_reset(struct wl1271 *wl)
L
Luciano Coelho 已提交
511 512 513 514 515
{
	int i;
	struct sk_buff *skb;

	/* TX failure */
516 517 518 519 520
	for (i = 0; i < NUM_TX_QUEUES; i++) {
		while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
			wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
			ieee80211_tx_status(wl->hw, skb);
		}
L
Luciano Coelho 已提交
521
	}
522
	wl->tx_queue_count = 0;
L
Luciano Coelho 已提交
523

524 525 526 527 528 529
	/*
	 * Make sure the driver is at a consistent state, in case this
	 * function is called from a context other than interface removal.
	 */
	handle_tx_low_watermark(wl);

J
Juuso Oikarinen 已提交
530
	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
L
Luciano Coelho 已提交
531 532
		if (wl->tx_frames[i] != NULL) {
			skb = wl->tx_frames[i];
533
			wl1271_free_tx_id(wl, i);
534
			wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
J
Juuso Oikarinen 已提交
535
			ieee80211_tx_status(wl->hw, skb);
L
Luciano Coelho 已提交
536
		}
537 538 539 540 541 542 543 544 545 546 547 548 549 550
}

#define WL1271_TX_FLUSH_TIMEOUT 500000

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

	while (!time_after(jiffies, timeout)) {
		mutex_lock(&wl->mutex);
		wl1271_debug(DEBUG_TX, "flushing tx buffer: %d",
			     wl->tx_frames_cnt);
551
		if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) {
552 553 554 555 556 557 558 559
			mutex_unlock(&wl->mutex);
			return;
		}
		mutex_unlock(&wl->mutex);
		msleep(1);
	}

	wl1271_warning("Unable to flush all TX buffers, timed out.");
L
Luciano Coelho 已提交
560
}
A
Arik Nemtsov 已提交
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578

u32 wl1271_tx_min_rate_get(struct wl1271 *wl)
{
	int i;
	u32 rate = 0;

	if (!wl->basic_rate_set) {
		WARN_ON(1);
		wl->basic_rate_set = wl->conf.tx.basic_rate;
	}

	for (i = 0; !rate; i++) {
		if ((wl->basic_rate_set >> i) & 0x1)
			rate = 1 << i;
	}

	return rate;
}