htc_drv_main.c 45.2 KB
Newer Older
S
Sujith 已提交
1
/*
2
 * Copyright (c) 2010-2011 Atheros Communications Inc.
S
Sujith 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "htc.h"

/*************/
/* Utilities */
/*************/

/* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */
static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
					      struct ath9k_channel *ichan)
{
	enum htc_phymode mode;

S
Sujith Manoharan 已提交
29
	mode = -EINVAL;
S
Sujith 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

	switch (ichan->chanmode) {
	case CHANNEL_G:
	case CHANNEL_G_HT20:
	case CHANNEL_G_HT40PLUS:
	case CHANNEL_G_HT40MINUS:
		mode = HTC_MODE_11NG;
		break;
	case CHANNEL_A:
	case CHANNEL_A_HT20:
	case CHANNEL_A_HT40PLUS:
	case CHANNEL_A_HT40MINUS:
		mode = HTC_MODE_11NA;
		break;
	default:
		break;
	}

S
Sujith Manoharan 已提交
48 49
	WARN_ON(mode < 0);

S
Sujith 已提交
50 51 52
	return mode;
}

S
Sujith Manoharan 已提交
53 54
bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
			enum ath9k_power_mode mode)
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
{
	bool ret;

	mutex_lock(&priv->htc_pm_lock);
	ret = ath9k_hw_setpower(priv->ah, mode);
	mutex_unlock(&priv->htc_pm_lock);

	return ret;
}

void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv)
{
	mutex_lock(&priv->htc_pm_lock);
	if (++priv->ps_usecount != 1)
		goto unlock;
	ath9k_hw_setpower(priv->ah, ATH9K_PM_AWAKE);

unlock:
	mutex_unlock(&priv->htc_pm_lock);
}

void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
{
78 79
	bool reset;

80 81 82 83
	mutex_lock(&priv->htc_pm_lock);
	if (--priv->ps_usecount != 0)
		goto unlock;

84 85 86
	if (priv->ps_idle) {
		ath9k_hw_setrxabort(priv->ah, true);
		ath9k_hw_stopdmarecv(priv->ah, &reset);
87
		ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
88
	} else if (priv->ps_enabled) {
89
		ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
90
	}
91

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
unlock:
	mutex_unlock(&priv->htc_pm_lock);
}

void ath9k_ps_work(struct work_struct *work)
{
	struct ath9k_htc_priv *priv =
		container_of(work, struct ath9k_htc_priv,
			     ps_work);
	ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);

	/* The chip wakes up after receiving the first beacon
	   while network sleep is enabled. For the driver to
	   be in sync with the hw, set the chip to awake and
	   only then set it to sleep.
	 */
	ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
}

111 112 113 114 115
static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
	struct ath9k_htc_priv *priv = data;
	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;

116 117 118
	if ((vif->type == NL80211_IFTYPE_AP) && bss_conf->enable_beacon)
		priv->reconfig_beacon = true;

119 120 121 122 123 124 125 126 127 128 129
	if (bss_conf->assoc) {
		priv->rearm_ani = true;
		priv->reconfig_beacon = true;
	}
}

static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv)
{
	priv->rearm_ani = false;
	priv->reconfig_beacon = false;

130 131 132
	ieee80211_iterate_active_interfaces_atomic(
		priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
		ath9k_htc_vif_iter, priv);
133
	if (priv->rearm_ani)
134
		ath9k_htc_start_ani(priv);
135 136 137 138 139 140 141 142

	if (priv->reconfig_beacon) {
		ath9k_htc_ps_wakeup(priv);
		ath9k_htc_beacon_reconfig(priv);
		ath9k_htc_ps_restore(priv);
	}
}

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 168
static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
	struct ath9k_vif_iter_data *iter_data = data;
	int i;

	for (i = 0; i < ETH_ALEN; i++)
		iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
}

static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
				     struct ieee80211_vif *vif)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_vif_iter_data iter_data;

	/*
	 * Use the hardware MAC address as reference, the hardware uses it
	 * together with the BSSID mask when matching addresses.
	 */
	iter_data.hw_macaddr = common->macaddr;
	memset(&iter_data.mask, 0xff, ETH_ALEN);

	if (vif)
		ath9k_htc_bssid_iter(&iter_data, vif->addr, vif);

	/* Get list of all active MAC addresses */
169 170 171
	ieee80211_iterate_active_interfaces_atomic(
		priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
		ath9k_htc_bssid_iter, &iter_data);
172 173 174 175 176

	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
	ath_hw_setbssidmask(common);
}

177 178 179 180 181 182 183 184 185 186 187 188
static void ath9k_htc_set_opmode(struct ath9k_htc_priv *priv)
{
	if (priv->num_ibss_vif)
		priv->ah->opmode = NL80211_IFTYPE_ADHOC;
	else if (priv->num_ap_vif)
		priv->ah->opmode = NL80211_IFTYPE_AP;
	else
		priv->ah->opmode = NL80211_IFTYPE_STATION;

	ath9k_hw_setopmode(priv->ah);
}

189 190 191 192 193
void ath9k_htc_reset(struct ath9k_htc_priv *priv)
{
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
	struct ieee80211_channel *channel = priv->hw->conf.channel;
194
	struct ath9k_hw_cal_data *caldata = NULL;
195 196 197 198 199 200 201 202
	enum htc_phymode mode;
	__be16 htc_mode;
	u8 cmd_rsp;
	int ret;

	mutex_lock(&priv->mutex);
	ath9k_htc_ps_wakeup(priv);

203
	ath9k_htc_stop_ani(priv);
204
	ieee80211_stop_queues(priv->hw);
205

206
	del_timer_sync(&priv->tx.cleanup_timer);
207 208
	ath9k_htc_tx_drain(priv);

209 210 211 212
	WMI_CMD(WMI_DISABLE_INTR_CMDID);
	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
	WMI_CMD(WMI_STOP_RECV_CMDID);

S
Sujith Manoharan 已提交
213 214
	ath9k_wmi_event_drain(priv);

215
	caldata = &priv->caldata;
216 217 218 219 220 221 222
	ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
	if (ret) {
		ath_err(common,
			"Unable to reset device (%u Mhz) reset status %d\n",
			channel->center_freq, ret);
	}

223 224
	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
			       &priv->curtxpow);
225 226 227 228 229 230 231 232 233 234

	WMI_CMD(WMI_START_RECV_CMDID);
	ath9k_host_rx_init(priv);

	mode = ath9k_htc_get_curmode(priv, ah->curchan);
	htc_mode = cpu_to_be16(mode);
	WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);

	WMI_CMD(WMI_ENABLE_INTR_CMDID);
	htc_start(priv->htc);
235
	ath9k_htc_vif_reconfig(priv);
236 237
	ieee80211_wake_queues(priv->hw);

238 239 240
	mod_timer(&priv->tx.cleanup_timer,
		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));

241 242 243 244
	ath9k_htc_ps_restore(priv);
	mutex_unlock(&priv->mutex);
}

S
Sujith 已提交
245 246 247 248 249 250 251
static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
				 struct ieee80211_hw *hw,
				 struct ath9k_channel *hchan)
{
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
	struct ieee80211_conf *conf = &common->hw->conf;
252
	bool fastcc;
S
Sujith 已提交
253
	struct ieee80211_channel *channel = hw->conf.channel;
254
	struct ath9k_hw_cal_data *caldata = NULL;
S
Sujith 已提交
255
	enum htc_phymode mode;
S
Sujith 已提交
256
	__be16 htc_mode;
S
Sujith 已提交
257 258 259
	u8 cmd_rsp;
	int ret;

260
	if (test_bit(OP_INVALID, &priv->op_flags))
S
Sujith 已提交
261 262
		return -EIO;

263
	fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
S
Sujith 已提交
264

265
	ath9k_htc_ps_wakeup(priv);
266

267
	del_timer_sync(&priv->tx.cleanup_timer);
268 269
	ath9k_htc_tx_drain(priv);

S
Sujith 已提交
270 271 272 273
	WMI_CMD(WMI_DISABLE_INTR_CMDID);
	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
	WMI_CMD(WMI_STOP_RECV_CMDID);

S
Sujith Manoharan 已提交
274 275
	ath9k_wmi_event_drain(priv);

276
	ath_dbg(common, CONFIG,
J
Joe Perches 已提交
277 278 279 280
		"(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",
		priv->ah->curchan->channel,
		channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
		fastcc);
S
Sujith 已提交
281

282 283
	if (!fastcc)
		caldata = &priv->caldata;
284

285
	ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
S
Sujith 已提交
286
	if (ret) {
287 288 289
		ath_err(common,
			"Unable to reset channel (%u Mhz) reset status %d\n",
			channel->center_freq, ret);
S
Sujith 已提交
290 291 292
		goto err;
	}

293 294
	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
			       &priv->curtxpow);
S
Sujith 已提交
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312

	WMI_CMD(WMI_START_RECV_CMDID);
	if (ret)
		goto err;

	ath9k_host_rx_init(priv);

	mode = ath9k_htc_get_curmode(priv, hchan);
	htc_mode = cpu_to_be16(mode);
	WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
	if (ret)
		goto err;

	WMI_CMD(WMI_ENABLE_INTR_CMDID);
	if (ret)
		goto err;

	htc_start(priv->htc);
313

314
	if (!test_bit(OP_SCANNING, &priv->op_flags) &&
315 316 317
	    !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
		ath9k_htc_vif_reconfig(priv);

318 319 320
	mod_timer(&priv->tx.cleanup_timer,
		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));

S
Sujith 已提交
321
err:
322
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
323 324 325
	return ret;
}

326 327 328 329 330 331 332
/*
 * Monitor mode handling is a tad complicated because the firmware requires
 * an interface to be created exclusively, while mac80211 doesn't associate
 * an interface with the mode.
 *
 * So, for now, only one monitor interface can be configured.
 */
333 334 335 336 337 338 339 340 341
static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_vif hvif;
	int ret = 0;
	u8 cmd_rsp;

	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
342
	hvif.index = priv->mon_vif_idx;
343
	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
344 345 346 347 348
	if (ret) {
		ath_err(common, "Unable to remove monitor interface at idx: %d\n",
			priv->mon_vif_idx);
	}

349
	priv->nvifs--;
350
	priv->vif_slot &= ~(1 << priv->mon_vif_idx);
351 352
}

353 354 355 356
static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_vif hvif;
357
	struct ath9k_htc_target_sta tsta;
358
	int ret = 0, sta_idx;
359 360
	u8 cmd_rsp;

361 362 363 364 365
	if ((priv->nvifs >= ATH9K_HTC_MAX_VIF) ||
	    (priv->nstations >= ATH9K_HTC_MAX_STA)) {
		ret = -ENOBUFS;
		goto err_vif;
	}
366

367 368 369 370 371
	sta_idx = ffz(priv->sta_slot);
	if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) {
		ret = -ENOBUFS;
		goto err_vif;
	}
372 373 374 375

	/*
	 * Add an interface.
	 */
376 377 378
	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);

379
	hvif.opmode = HTC_M_MONITOR;
380
	hvif.index = ffz(priv->vif_slot);
381 382 383

	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
	if (ret)
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
		goto err_vif;

	/*
	 * Assign the monitor interface index as a special case here.
	 * This is needed when the interface is brought down.
	 */
	priv->mon_vif_idx = hvif.index;
	priv->vif_slot |= (1 << hvif.index);

	/*
	 * Set the hardware mode to monitor only if there are no
	 * other interfaces.
	 */
	if (!priv->nvifs)
		priv->ah->opmode = NL80211_IFTYPE_MONITOR;
399 400

	priv->nvifs++;
401 402 403 404 405 406 407 408 409

	/*
	 * Associate a station with the interface for packet injection.
	 */
	memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));

	memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN);

	tsta.is_vif_sta = 1;
410
	tsta.sta_index = sta_idx;
411
	tsta.vif_index = hvif.index;
412
	tsta.maxampdu = cpu_to_be16(0xffff);
413 414 415 416

	WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
	if (ret) {
		ath_err(common, "Unable to add station entry for monitor mode\n");
417
		goto err_sta;
418 419
	}

420
	priv->sta_slot |= (1 << sta_idx);
421
	priv->nstations++;
422
	priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx;
423 424
	priv->ah->is_monitoring = true;

425
	ath_dbg(common, CONFIG,
426 427 428
		"Attached a monitor interface at idx: %d, sta idx: %d\n",
		priv->mon_vif_idx, sta_idx);

429
	return 0;
430

431
err_sta:
432 433 434 435
	/*
	 * Remove the interface from the target.
	 */
	__ath9k_htc_remove_monitor_interface(priv);
436
err_vif:
437
	ath_dbg(common, FATAL, "Unable to attach a monitor interface\n");
438

439
	return ret;
440 441 442 443 444 445
}

static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	int ret = 0;
446
	u8 cmd_rsp, sta_idx;
447

448
	__ath9k_htc_remove_monitor_interface(priv);
449

450
	sta_idx = priv->vif_sta_pos[priv->mon_vif_idx];
451 452 453 454 455 456 457

	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
	if (ret) {
		ath_err(common, "Unable to remove station entry for monitor mode\n");
		return ret;
	}

458
	priv->sta_slot &= ~(1 << sta_idx);
459
	priv->nstations--;
460
	priv->ah->is_monitoring = false;
461

462
	ath_dbg(common, CONFIG,
463 464 465
		"Removed a monitor interface at idx: %d, sta idx: %d\n",
		priv->mon_vif_idx, sta_idx);

466
	return 0;
467 468
}

S
Sujith 已提交
469 470 471 472 473 474 475 476
static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
				 struct ieee80211_vif *vif,
				 struct ieee80211_sta *sta)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_sta tsta;
	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
	struct ath9k_htc_sta *ista;
477
	int ret, sta_idx;
S
Sujith 已提交
478
	u8 cmd_rsp;
479
	u16 maxampdu;
S
Sujith 已提交
480 481 482 483

	if (priv->nstations >= ATH9K_HTC_MAX_STA)
		return -ENOBUFS;

484 485 486 487
	sta_idx = ffz(priv->sta_slot);
	if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA))
		return -ENOBUFS;

S
Sujith 已提交
488 489 490 491 492 493
	memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));

	if (sta) {
		ista = (struct ath9k_htc_sta *) sta->drv_priv;
		memcpy(&tsta.macaddr, sta->addr, ETH_ALEN);
		memcpy(&tsta.bssid, common->curbssid, ETH_ALEN);
494
		ista->index = sta_idx;
495 496 497 498
		tsta.is_vif_sta = 0;
		maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
				 sta->ht_cap.ampdu_factor);
		tsta.maxampdu = cpu_to_be16(maxampdu);
S
Sujith 已提交
499 500 501
	} else {
		memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
		tsta.is_vif_sta = 1;
502
		tsta.maxampdu = cpu_to_be16(0xffff);
S
Sujith 已提交
503 504
	}

505
	tsta.sta_index = sta_idx;
S
Sujith 已提交
506
	tsta.vif_index = avp->index;
507

S
Sujith 已提交
508 509 510
	WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
	if (ret) {
		if (sta)
511 512 513
			ath_err(common,
				"Unable to add station entry for: %pM\n",
				sta->addr);
S
Sujith 已提交
514 515 516
		return ret;
	}

517
	if (sta) {
518
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
519 520
			"Added a station entry for: %pM (idx: %d)\n",
			sta->addr, tsta.sta_index);
521
	} else {
522
		ath_dbg(common, CONFIG,
523 524 525
			"Added a station entry for VIF %d (idx: %d)\n",
			avp->index, tsta.sta_index);
	}
S
Sujith 已提交
526

527
	priv->sta_slot |= (1 << sta_idx);
S
Sujith 已提交
528
	priv->nstations++;
529 530 531
	if (!sta)
		priv->vif_sta_pos[avp->index] = sta_idx;

S
Sujith 已提交
532 533 534 535 536 537 538 539
	return 0;
}

static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
				    struct ieee80211_vif *vif,
				    struct ieee80211_sta *sta)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
540
	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
S
Sujith 已提交
541 542 543 544 545 546 547 548
	struct ath9k_htc_sta *ista;
	int ret;
	u8 cmd_rsp, sta_idx;

	if (sta) {
		ista = (struct ath9k_htc_sta *) sta->drv_priv;
		sta_idx = ista->index;
	} else {
549
		sta_idx = priv->vif_sta_pos[avp->index];
S
Sujith 已提交
550 551 552 553 554
	}

	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
	if (ret) {
		if (sta)
555 556 557
			ath_err(common,
				"Unable to remove station entry for: %pM\n",
				sta->addr);
S
Sujith 已提交
558 559 560
		return ret;
	}

561
	if (sta) {
562
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
563 564
			"Removed a station entry for: %pM (idx: %d)\n",
			sta->addr, sta_idx);
565
	} else {
566
		ath_dbg(common, CONFIG,
567 568 569
			"Removed a station entry for VIF %d (idx: %d)\n",
			avp->index, sta_idx);
	}
S
Sujith 已提交
570

571
	priv->sta_slot &= ~(1 << sta_idx);
S
Sujith 已提交
572
	priv->nstations--;
573

S
Sujith 已提交
574 575 576
	return 0;
}

577 578
int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv,
				u8 enable_coex)
S
Sujith 已提交
579 580 581 582 583 584 585
{
	struct ath9k_htc_cap_target tcap;
	int ret;
	u8 cmd_rsp;

	memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target));

586
	tcap.ampdu_limit = cpu_to_be32(0xffff);
587
	tcap.ampdu_subframes = 0xff;
588
	tcap.enable_coex = enable_coex;
S
Sujith 已提交
589
	tcap.tx_chainmask = priv->ah->caps.tx_chainmask;
S
Sujith 已提交
590 591 592 593 594 595

	WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap);

	return ret;
}

S
Sujith 已提交
596 597 598
static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv,
				 struct ieee80211_sta *sta,
				 struct ath9k_htc_target_rate *trate)
S
Sujith 已提交
599 600 601 602
{
	struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
	struct ieee80211_supported_band *sband;
	u32 caps = 0;
S
Sujith 已提交
603
	int i, j;
S
Sujith 已提交
604

S
Sujith 已提交
605
	sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
S
Sujith 已提交
606 607 608

	for (i = 0, j = 0; i < sband->n_bitrates; i++) {
		if (sta->supp_rates[sband->band] & BIT(i)) {
S
Sujith 已提交
609
			trate->rates.legacy_rates.rs_rates[j]
S
Sujith 已提交
610 611 612 613
				= (sband->bitrates[i].bitrate * 2) / 10;
			j++;
		}
	}
S
Sujith 已提交
614
	trate->rates.legacy_rates.rs_nrates = j;
S
Sujith 已提交
615 616 617 618

	if (sta->ht_cap.ht_supported) {
		for (i = 0, j = 0; i < 77; i++) {
			if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
S
Sujith 已提交
619
				trate->rates.ht_rates.rs_rates[j++] = i;
S
Sujith 已提交
620 621 622
			if (j == ATH_HTC_RATE_MAX)
				break;
		}
S
Sujith 已提交
623
		trate->rates.ht_rates.rs_nrates = j;
S
Sujith 已提交
624 625

		caps = WLAN_RC_HT_FLAG;
626 627
		if (sta->ht_cap.mcs.rx_mask[1])
			caps |= WLAN_RC_DS_FLAG;
628 629
		if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
		     (conf_is_ht40(&priv->hw->conf)))
S
Sujith 已提交
630
			caps |= WLAN_RC_40_FLAG;
631 632 633 634 635
		if (conf_is_ht40(&priv->hw->conf) &&
		    (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40))
			caps |= WLAN_RC_SGI_FLAG;
		else if (conf_is_ht20(&priv->hw->conf) &&
			 (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20))
S
Sujith 已提交
636 637 638
			caps |= WLAN_RC_SGI_FLAG;
	}

S
Sujith 已提交
639 640 641 642 643 644 645 646 647 648 649
	trate->sta_index = ista->index;
	trate->isnew = 1;
	trate->capflags = cpu_to_be32(caps);
}

static int ath9k_htc_send_rate_cmd(struct ath9k_htc_priv *priv,
				    struct ath9k_htc_target_rate *trate)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	int ret;
	u8 cmd_rsp;
S
Sujith 已提交
650

S
Sujith 已提交
651
	WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate);
S
Sujith 已提交
652
	if (ret) {
653 654
		ath_err(common,
			"Unable to initialize Rate information on target\n");
S
Sujith 已提交
655 656
	}

S
Sujith 已提交
657
	return ret;
S
Sujith 已提交
658 659
}

S
Sujith 已提交
660 661
static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv,
				struct ieee80211_sta *sta)
S
Sujith 已提交
662 663
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
S
Sujith 已提交
664
	struct ath9k_htc_target_rate trate;
S
Sujith 已提交
665 666
	int ret;

S
Sujith 已提交
667 668 669 670
	memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
	ath9k_htc_setup_rate(priv, sta, &trate);
	ret = ath9k_htc_send_rate_cmd(priv, &trate);
	if (!ret)
671
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
672 673
			"Updated target sta: %pM, rate caps: 0x%X\n",
			sta->addr, be32_to_cpu(trate.capflags));
S
Sujith 已提交
674 675
}

676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv,
				  struct ieee80211_vif *vif,
				  struct ieee80211_bss_conf *bss_conf)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_rate trate;
	struct ieee80211_sta *sta;
	int ret;

	memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));

	rcu_read_lock();
	sta = ieee80211_find_sta(vif, bss_conf->bssid);
	if (!sta) {
		rcu_read_unlock();
		return;
	}
	ath9k_htc_setup_rate(priv, sta, &trate);
	rcu_read_unlock();

	ret = ath9k_htc_send_rate_cmd(priv, &trate);
	if (!ret)
698
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
699 700
			"Updated target sta: %pM, rate caps: 0x%X\n",
			bss_conf->bssid, be32_to_cpu(trate.capflags));
701 702
}

703 704 705 706 707
static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,
				  struct ieee80211_vif *vif,
				  struct ieee80211_sta *sta,
				  enum ieee80211_ampdu_mlme_action action,
				  u16 tid)
S
Sujith 已提交
708 709 710
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_aggr aggr;
711
	struct ath9k_htc_sta *ista;
S
Sujith 已提交
712 713 714
	int ret = 0;
	u8 cmd_rsp;

715
	if (tid >= ATH9K_HTC_MAX_TID)
S
Sujith 已提交
716 717
		return -EINVAL;

718 719
	memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));
	ista = (struct ath9k_htc_sta *) sta->drv_priv;
S
Sujith 已提交
720 721

	aggr.sta_index = ista->index;
S
Sujith 已提交
722 723
	aggr.tidno = tid & 0xf;
	aggr.aggr_enable = (action == IEEE80211_AMPDU_TX_START) ? true : false;
S
Sujith 已提交
724 725 726

	WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr);
	if (ret)
727
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
728 729
			"Unable to %s TX aggregation for (%pM, %d)\n",
			(aggr.aggr_enable) ? "start" : "stop", sta->addr, tid);
S
Sujith 已提交
730
	else
731
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
732 733 734
			"%s TX aggregation for (%pM, %d)\n",
			(aggr.aggr_enable) ? "Starting" : "Stopping",
			sta->addr, tid);
S
Sujith 已提交
735

736
	spin_lock_bh(&priv->tx.tx_lock);
S
Sujith 已提交
737
	ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP;
738
	spin_unlock_bh(&priv->tx.tx_lock);
S
Sujith 已提交
739

S
Sujith 已提交
740
	return ret;
S
Sujith 已提交
741 742 743 744 745 746
}

/*******/
/* ANI */
/*******/

747
void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
S
Sujith 已提交
748 749 750 751 752 753 754 755
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	unsigned long timestamp = jiffies_to_msecs(jiffies);

	common->ani.longcal_timer = timestamp;
	common->ani.shortcal_timer = timestamp;
	common->ani.checkani_timer = timestamp;

756
	set_bit(OP_ANI_RUNNING, &priv->op_flags);
757 758

	ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
S
Sujith 已提交
759 760 761
				     msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
}

762 763 764
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv)
{
	cancel_delayed_work_sync(&priv->ani_work);
765
	clear_bit(OP_ANI_RUNNING, &priv->op_flags);
766 767 768
}

void ath9k_htc_ani_work(struct work_struct *work)
S
Sujith 已提交
769 770
{
	struct ath9k_htc_priv *priv =
771
		container_of(work, struct ath9k_htc_priv, ani_work.work);
S
Sujith 已提交
772 773 774 775 776 777 778 779
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
	bool longcal = false;
	bool shortcal = false;
	bool aniflag = false;
	unsigned int timestamp = jiffies_to_msecs(jiffies);
	u32 cal_interval, short_cal_interval;

780 781
	short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
S
Sujith 已提交
782

783 784 785 786
	/* Only calibrate if awake */
	if (ah->power_mode != ATH9K_PM_AWAKE)
		goto set_timer;

S
Sujith 已提交
787 788 789
	/* Long calibration runs independently of short calibration. */
	if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
		longcal = true;
790
		ath_dbg(common, ANI, "longcal @%lu\n", jiffies);
S
Sujith 已提交
791 792 793 794 795 796 797 798
		common->ani.longcal_timer = timestamp;
	}

	/* Short calibration applies only while caldone is false */
	if (!common->ani.caldone) {
		if ((timestamp - common->ani.shortcal_timer) >=
		    short_cal_interval) {
			shortcal = true;
799
			ath_dbg(common, ANI, "shortcal @%lu\n", jiffies);
S
Sujith 已提交
800 801 802 803 804 805 806 807 808 809 810 811 812
			common->ani.shortcal_timer = timestamp;
			common->ani.resetcal_timer = timestamp;
		}
	} else {
		if ((timestamp - common->ani.resetcal_timer) >=
		    ATH_RESTART_CALINTERVAL) {
			common->ani.caldone = ath9k_hw_reset_calvalid(ah);
			if (common->ani.caldone)
				common->ani.resetcal_timer = timestamp;
		}
	}

	/* Verify whether we must check ANI */
813 814
	if (ah->config.enable_ani &&
	    (timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
S
Sujith 已提交
815 816 817 818 819 820
		aniflag = true;
		common->ani.checkani_timer = timestamp;
	}

	/* Skip all processing if there's nothing to do. */
	if (longcal || shortcal || aniflag) {
821 822 823

		ath9k_htc_ps_wakeup(priv);

S
Sujith 已提交
824 825 826 827 828
		/* Call ANI routine if necessary */
		if (aniflag)
			ath9k_hw_ani_monitor(ah, ah->curchan);

		/* Perform calibration if necessary */
829
		if (longcal || shortcal)
S
Sujith 已提交
830 831
			common->ani.caldone =
				ath9k_hw_calibrate(ah, ah->curchan,
832
						   ah->rxchainmask, longcal);
S
Sujith 已提交
833

834
		ath9k_htc_ps_restore(priv);
S
Sujith 已提交
835 836
	}

837
set_timer:
S
Sujith 已提交
838 839 840 841 842 843
	/*
	* Set timer interval based on previous results.
	* The interval must be the shortest necessary to satisfy ANI,
	* short calibration and long calibration.
	*/
	cal_interval = ATH_LONG_CALINTERVAL;
844
	if (ah->config.enable_ani)
S
Sujith 已提交
845 846 847 848
		cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
	if (!common->ani.caldone)
		cal_interval = min(cal_interval, (u32)short_cal_interval);

849
	ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
S
Sujith 已提交
850 851 852 853 854 855 856
				     msecs_to_jiffies(cal_interval));
}

/**********************/
/* mac80211 Callbacks */
/**********************/

857 858 859
static void ath9k_htc_tx(struct ieee80211_hw *hw,
			 struct ieee80211_tx_control *control,
			 struct sk_buff *skb)
S
Sujith 已提交
860 861 862
{
	struct ieee80211_hdr *hdr;
	struct ath9k_htc_priv *priv = hw->priv;
863
	struct ath_common *common = ath9k_hw_common(priv->ah);
S
Sujith Manoharan 已提交
864
	int padpos, padsize, ret, slot;
S
Sujith 已提交
865 866 867 868 869 870 871

	hdr = (struct ieee80211_hdr *) skb->data;

	/* Add the padding after the header if this is not already done */
	padpos = ath9k_cmn_padpos(hdr->frame_control);
	padsize = padpos & 3;
	if (padsize && skb->len > padpos) {
872
		if (skb_headroom(skb) < padsize) {
873
			ath_dbg(common, XMIT, "No room for padding\n");
874
			goto fail_tx;
875
		}
S
Sujith 已提交
876 877 878 879
		skb_push(skb, padsize);
		memmove(skb->data, skb->data + padsize, padpos);
	}

S
Sujith Manoharan 已提交
880 881
	slot = ath9k_htc_tx_get_slot(priv);
	if (slot < 0) {
882
		ath_dbg(common, XMIT, "No free TX slot\n");
S
Sujith Manoharan 已提交
883 884 885
		goto fail_tx;
	}

886
	ret = ath9k_htc_tx_start(priv, control->sta, skb, slot, false);
S
Sujith 已提交
887
	if (ret != 0) {
888
		ath_dbg(common, XMIT, "Tx failed\n");
S
Sujith Manoharan 已提交
889
		goto clear_slot;
S
Sujith 已提交
890 891
	}

892 893
	ath9k_htc_check_stop_queues(priv);

894
	return;
S
Sujith 已提交
895

S
Sujith Manoharan 已提交
896 897
clear_slot:
	ath9k_htc_tx_clear_slot(priv, slot);
S
Sujith 已提交
898 899 900 901
fail_tx:
	dev_kfree_skb_any(skb);
}

S
Sujith 已提交
902
static int ath9k_htc_start(struct ieee80211_hw *hw)
S
Sujith 已提交
903 904 905 906 907 908 909 910
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
	struct ieee80211_channel *curchan = hw->conf.channel;
	struct ath9k_channel *init_channel;
	int ret = 0;
	enum htc_phymode mode;
S
Sujith 已提交
911
	__be16 htc_mode;
S
Sujith 已提交
912 913
	u8 cmd_rsp;

S
Sujith 已提交
914 915
	mutex_lock(&priv->mutex);

916
	ath_dbg(common, CONFIG,
J
Joe Perches 已提交
917 918
		"Starting driver with initial channel: %d MHz\n",
		curchan->center_freq);
S
Sujith 已提交
919

S
Sujith 已提交
920 921 922 923
	/* Ensure that HW is awake before flushing RX */
	ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
	WMI_CMD(WMI_FLUSH_RECV_CMDID);

S
Sujith 已提交
924 925 926
	/* setup initial channel */
	init_channel = ath9k_cmn_get_curchannel(hw, ah);

927
	ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
S
Sujith 已提交
928
	if (ret) {
929 930 931
		ath_err(common,
			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
			ret, curchan->center_freq);
S
Sujith 已提交
932
		mutex_unlock(&priv->mutex);
933
		return ret;
S
Sujith 已提交
934 935
	}

936 937
	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
			       &priv->curtxpow);
S
Sujith 已提交
938 939 940 941 942 943 944 945 946

	mode = ath9k_htc_get_curmode(priv, init_channel);
	htc_mode = cpu_to_be16(mode);
	WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
	WMI_CMD(WMI_ATH_INIT_CMDID);
	WMI_CMD(WMI_START_RECV_CMDID);

	ath9k_host_rx_init(priv);

947
	ret = ath9k_htc_update_cap_target(priv, 0);
948
	if (ret)
949
		ath_dbg(common, CONFIG,
950 951
			"Failed to update capability in target\n");

952
	clear_bit(OP_INVALID, &priv->op_flags);
S
Sujith 已提交
953 954
	htc_start(priv->htc);

955
	spin_lock_bh(&priv->tx.tx_lock);
956
	priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
957
	spin_unlock_bh(&priv->tx.tx_lock);
S
Sujith 已提交
958 959 960

	ieee80211_wake_queues(hw);

961 962 963
	mod_timer(&priv->tx.cleanup_timer,
		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));

964 965
	ath9k_htc_start_btcoex(priv);

S
Sujith 已提交
966
	mutex_unlock(&priv->mutex);
967

S
Sujith 已提交
968 969 970
	return ret;
}

S
Sujith 已提交
971
static void ath9k_htc_stop(struct ieee80211_hw *hw)
S
Sujith 已提交
972 973 974 975
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
976
	int ret __attribute__ ((unused));
S
Sujith 已提交
977 978
	u8 cmd_rsp;

S
Sujith 已提交
979 980
	mutex_lock(&priv->mutex);

981
	if (test_bit(OP_INVALID, &priv->op_flags)) {
982
		ath_dbg(common, ANY, "Device not present\n");
S
Sujith 已提交
983
		mutex_unlock(&priv->mutex);
S
Sujith 已提交
984 985 986
		return;
	}

987
	ath9k_htc_ps_wakeup(priv);
988

S
Sujith 已提交
989 990 991
	WMI_CMD(WMI_DISABLE_INTR_CMDID);
	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
	WMI_CMD(WMI_STOP_RECV_CMDID);
992 993

	tasklet_kill(&priv->rx_tasklet);
S
Sujith 已提交
994

995
	del_timer_sync(&priv->tx.cleanup_timer);
996
	ath9k_htc_tx_drain(priv);
S
Sujith Manoharan 已提交
997 998
	ath9k_wmi_event_drain(priv);

999 1000 1001 1002 1003
	mutex_unlock(&priv->mutex);

	/* Cancel all the running timers/work .. */
	cancel_work_sync(&priv->fatal_work);
	cancel_work_sync(&priv->ps_work);
1004 1005 1006 1007

#ifdef CONFIG_MAC80211_LEDS
	cancel_work_sync(&priv->led_work);
#endif
1008
	ath9k_htc_stop_ani(priv);
1009 1010 1011

	mutex_lock(&priv->mutex);

1012
	ath9k_htc_stop_btcoex(priv);
1013

1014 1015 1016 1017
	/* Remove a monitor interface if it's present. */
	if (priv->ah->is_monitoring)
		ath9k_htc_remove_monitor_interface(priv);

1018 1019 1020 1021 1022
	ath9k_hw_phy_disable(ah);
	ath9k_hw_disable(ah);
	ath9k_htc_ps_restore(priv);
	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);

1023
	set_bit(OP_INVALID, &priv->op_flags);
S
Sujith 已提交
1024

1025
	ath_dbg(common, CONFIG, "Driver halt\n");
1026 1027 1028
	mutex_unlock(&priv->mutex);
}

S
Sujith 已提交
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath9k_htc_vif *avp = (void *)vif->drv_priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_vif hvif;
	int ret = 0;
	u8 cmd_rsp;

	mutex_lock(&priv->mutex);

1041
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1042 1043 1044 1045 1046
	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
	memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);

	switch (vif->type) {
	case NL80211_IFTYPE_STATION:
1047
		hvif.opmode = HTC_M_STA;
S
Sujith 已提交
1048 1049
		break;
	case NL80211_IFTYPE_ADHOC:
1050
		hvif.opmode = HTC_M_IBSS;
S
Sujith 已提交
1051
		break;
1052
	case NL80211_IFTYPE_AP:
1053
		hvif.opmode = HTC_M_HOSTAP;
1054
		break;
S
Sujith 已提交
1055
	default:
1056
		ath_err(common,
S
Sujith 已提交
1057 1058 1059 1060 1061 1062
			"Interface type %d not yet supported\n", vif->type);
		ret = -EOPNOTSUPP;
		goto out;
	}

	/* Index starts from zero on the target */
1063
	avp->index = hvif.index = ffz(priv->vif_slot);
S
Sujith 已提交
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
	hvif.rtsthreshold = cpu_to_be16(2304);
	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
	if (ret)
		goto out;

	/*
	 * We need a node in target to tx mgmt frames
	 * before association.
	 */
	ret = ath9k_htc_add_station(priv, vif, NULL);
1074 1075
	if (ret) {
		WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
S
Sujith 已提交
1076
		goto out;
1077
	}
S
Sujith 已提交
1078

1079 1080
	ath9k_htc_set_bssid_mask(priv, vif);

1081
	priv->vif_slot |= (1 << avp->index);
1082
	priv->nvifs++;
1083

1084
	INC_VIF(priv, vif->type);
S
Sujith Manoharan 已提交
1085 1086 1087 1088 1089

	if ((vif->type == NL80211_IFTYPE_AP) ||
	    (vif->type == NL80211_IFTYPE_ADHOC))
		ath9k_htc_assign_bslot(priv, vif);

1090
	ath9k_htc_set_opmode(priv);
1091

1092
	if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
1093
	    !test_bit(OP_ANI_RUNNING, &priv->op_flags)) {
1094
		ath9k_hw_set_tsfadjust(priv->ah, true);
1095
		ath9k_htc_start_ani(priv);
1096
	}
1097

1098 1099
	ath_dbg(common, CONFIG, "Attach a VIF of type: %d at idx: %d\n",
		vif->type, avp->index);
1100

S
Sujith 已提交
1101
out:
1102
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1103
	mutex_unlock(&priv->mutex);
S
Sujith 已提交
1104

S
Sujith 已提交
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
	return ret;
}

static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
				       struct ieee80211_vif *vif)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_vif *avp = (void *)vif->drv_priv;
	struct ath9k_htc_target_vif hvif;
	int ret = 0;
	u8 cmd_rsp;

	mutex_lock(&priv->mutex);
S
Sujith 已提交
1119
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1120 1121 1122 1123 1124

	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
	memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
	hvif.index = avp->index;
	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
1125 1126 1127 1128
	if (ret) {
		ath_err(common, "Unable to remove interface at idx: %d\n",
			avp->index);
	}
S
Sujith 已提交
1129
	priv->nvifs--;
1130
	priv->vif_slot &= ~(1 << avp->index);
S
Sujith 已提交
1131 1132 1133

	ath9k_htc_remove_station(priv, vif, NULL);

1134
	DEC_VIF(priv, vif->type);
S
Sujith Manoharan 已提交
1135 1136 1137 1138 1139

	if ((vif->type == NL80211_IFTYPE_AP) ||
	    (vif->type == NL80211_IFTYPE_ADHOC))
		ath9k_htc_remove_bslot(priv, vif);

1140
	ath9k_htc_set_opmode(priv);
1141

1142 1143
	ath9k_htc_set_bssid_mask(priv, vif);

1144 1145 1146 1147 1148
	/*
	 * Stop ANI only if there are no associated station interfaces.
	 */
	if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) {
		priv->rearm_ani = false;
1149 1150 1151
		ieee80211_iterate_active_interfaces_atomic(
			priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
			ath9k_htc_vif_iter, priv);
1152 1153 1154 1155
		if (!priv->rearm_ani)
			ath9k_htc_stop_ani(priv);
	}

1156
	ath_dbg(common, CONFIG, "Detach Interface at idx: %d\n", avp->index);
1157

S
Sujith 已提交
1158
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1159 1160 1161 1162 1163 1164 1165 1166
	mutex_unlock(&priv->mutex);
}

static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ieee80211_conf *conf = &hw->conf;
1167 1168
	bool chip_reset = false;
	int ret = 0;
S
Sujith 已提交
1169 1170

	mutex_lock(&priv->mutex);
1171
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1172

1173
	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
S
Sujith 已提交
1174
		mutex_lock(&priv->htc_pm_lock);
1175

1176 1177 1178 1179 1180
		priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
		if (priv->ps_idle)
			chip_reset = true;

		mutex_unlock(&priv->htc_pm_lock);
1181 1182
	}

1183 1184 1185 1186 1187
	/*
	 * Monitor interface should be added before
	 * IEEE80211_CONF_CHANGE_CHANNEL is handled.
	 */
	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1188 1189 1190 1191 1192
		if ((conf->flags & IEEE80211_CONF_MONITOR) &&
		    !priv->ah->is_monitoring)
			ath9k_htc_add_monitor_interface(priv);
		else if (priv->ah->is_monitoring)
			ath9k_htc_remove_monitor_interface(priv);
1193 1194
	}

1195
	if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
S
Sujith 已提交
1196 1197 1198
		struct ieee80211_channel *curchan = hw->conf.channel;
		int pos = curchan->hw_value;

1199
		ath_dbg(common, CONFIG, "Set channel: %d MHz\n",
J
Joe Perches 已提交
1200
			curchan->center_freq);
S
Sujith 已提交
1201

1202 1203 1204
		ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
					  hw->conf.channel,
					  hw->conf.channel_type);
S
Sujith 已提交
1205 1206

		if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
1207
			ath_err(common, "Unable to set channel\n");
1208 1209
			ret = -EINVAL;
			goto out;
S
Sujith 已提交
1210 1211 1212
		}

	}
1213

1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
	if (changed & IEEE80211_CONF_CHANGE_PS) {
		if (conf->flags & IEEE80211_CONF_PS) {
			ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
			priv->ps_enabled = true;
		} else {
			priv->ps_enabled = false;
			cancel_work_sync(&priv->ps_work);
			ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
		}
	}
S
Sujith 已提交
1224

1225 1226
	if (changed & IEEE80211_CONF_CHANGE_POWER) {
		priv->txpowlimit = 2 * conf->power_level;
1227 1228
		ath9k_cmn_update_txpow(priv->ah, priv->curtxpow,
				       priv->txpowlimit, &priv->curtxpow);
1229 1230
	}

S
Sujith 已提交
1231
out:
1232
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1233
	mutex_unlock(&priv->mutex);
1234
	return ret;
S
Sujith 已提交
1235 1236 1237 1238 1239 1240 1241 1242 1243
}

#define SUPPORTED_FILTERS			\
	(FIF_PROMISC_IN_BSS |			\
	FIF_ALLMULTI |				\
	FIF_CONTROL |				\
	FIF_PSPOLL |				\
	FIF_OTHER_BSS |				\
	FIF_BCN_PRBRESP_PROMISC |		\
1244
	FIF_PROBE_REQ |				\
S
Sujith 已提交
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
	FIF_FCSFAIL)

static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
				       unsigned int changed_flags,
				       unsigned int *total_flags,
				       u64 multicast)
{
	struct ath9k_htc_priv *priv = hw->priv;
	u32 rfilt;

	mutex_lock(&priv->mutex);
	changed_flags &= SUPPORTED_FILTERS;
	*total_flags &= SUPPORTED_FILTERS;

1259
	if (test_bit(OP_INVALID, &priv->op_flags)) {
1260
		ath_dbg(ath9k_hw_common(priv->ah), ANY,
1261
			"Unable to configure filter on invalid state\n");
L
Larry Finger 已提交
1262
		mutex_unlock(&priv->mutex);
1263 1264 1265 1266
		return;
	}
	ath9k_htc_ps_wakeup(priv);

S
Sujith 已提交
1267
	priv->rxfilter = *total_flags;
1268
	rfilt = ath9k_htc_calcrxfilter(priv);
S
Sujith 已提交
1269 1270
	ath9k_hw_setrxfilter(priv->ah, rfilt);

1271 1272
	ath_dbg(ath9k_hw_common(priv->ah), CONFIG, "Set HW RX filter: 0x%x\n",
		rfilt);
S
Sujith 已提交
1273

1274
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1275 1276 1277
	mutex_unlock(&priv->mutex);
}

1278 1279 1280
static int ath9k_htc_sta_add(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif,
			     struct ieee80211_sta *sta)
S
Sujith 已提交
1281 1282 1283 1284
{
	struct ath9k_htc_priv *priv = hw->priv;
	int ret;

1285
	mutex_lock(&priv->mutex);
S
Sujith 已提交
1286
	ath9k_htc_ps_wakeup(priv);
1287 1288 1289 1290 1291
	ret = ath9k_htc_add_station(priv, vif, sta);
	if (!ret)
		ath9k_htc_init_rate(priv, sta);
	ath9k_htc_ps_restore(priv);
	mutex_unlock(&priv->mutex);
1292

1293 1294 1295 1296 1297 1298 1299 1300
	return ret;
}

static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
				struct ieee80211_vif *vif,
				struct ieee80211_sta *sta)
{
	struct ath9k_htc_priv *priv = hw->priv;
1301
	struct ath9k_htc_sta *ista;
1302
	int ret;
1303

1304 1305
	mutex_lock(&priv->mutex);
	ath9k_htc_ps_wakeup(priv);
1306 1307
	ista = (struct ath9k_htc_sta *) sta->drv_priv;
	htc_sta_drain(priv->htc, ista->index);
1308
	ret = ath9k_htc_remove_station(priv, vif, sta);
S
Sujith 已提交
1309
	ath9k_htc_ps_restore(priv);
1310
	mutex_unlock(&priv->mutex);
1311 1312

	return ret;
S
Sujith 已提交
1313 1314
}

1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
				    struct ieee80211_vif *vif,
				    struct ieee80211_sta *sta, u32 changed)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_rate trate;

	mutex_lock(&priv->mutex);
	ath9k_htc_ps_wakeup(priv);

	if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
		memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
		ath9k_htc_setup_rate(priv, sta, &trate);
		if (!ath9k_htc_send_rate_cmd(priv, &trate))
			ath_dbg(common, CONFIG,
				"Supported rates for sta: %pM updated, rate caps: 0x%X\n",
				sta->addr, be32_to_cpu(trate.capflags));
		else
			ath_dbg(common, CONFIG,
				"Unable to update supported rates for sta: %pM\n",
				sta->addr);
	}

	ath9k_htc_ps_restore(priv);
	mutex_unlock(&priv->mutex);
}

1343 1344
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif, u16 queue,
S
Sujith 已提交
1345 1346 1347 1348 1349 1350 1351
			     const struct ieee80211_tx_queue_params *params)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_tx_queue_info qi;
	int ret = 0, qnum;

1352
	if (queue >= IEEE80211_NUM_ACS)
S
Sujith 已提交
1353 1354 1355
		return 0;

	mutex_lock(&priv->mutex);
S
Sujith 已提交
1356
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1357 1358 1359 1360 1361 1362

	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));

	qi.tqi_aifs = params->aifs;
	qi.tqi_cwmin = params->cw_min;
	qi.tqi_cwmax = params->cw_max;
1363
	qi.tqi_burstTime = params->txop * 32;
S
Sujith 已提交
1364 1365 1366

	qnum = get_hw_qnum(queue, priv->hwq_map);

1367
	ath_dbg(common, CONFIG,
J
Joe Perches 已提交
1368 1369 1370
		"Configure tx [queue/hwq] [%d/%d],  aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
		queue, qnum, params->aifs, params->cw_min,
		params->cw_max, params->txop);
S
Sujith 已提交
1371

1372
	ret = ath_htc_txq_update(priv, qnum, &qi);
S
Sujith 已提交
1373
	if (ret) {
1374
		ath_err(common, "TXQ Update failed\n");
S
Sujith 已提交
1375 1376
		goto out;
	}
S
Sujith 已提交
1377

S
Sujith 已提交
1378
	if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
1379
	    (qnum == priv->hwq_map[IEEE80211_AC_BE]))
S
Sujith 已提交
1380 1381
		    ath9k_htc_beaconq_config(priv);
out:
S
Sujith 已提交
1382
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
	mutex_unlock(&priv->mutex);

	return ret;
}

static int ath9k_htc_set_key(struct ieee80211_hw *hw,
			     enum set_key_cmd cmd,
			     struct ieee80211_vif *vif,
			     struct ieee80211_sta *sta,
			     struct ieee80211_key_conf *key)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	int ret = 0;

1398
	if (htc_modparam_nohwcrypt)
S
Sujith 已提交
1399 1400
		return -ENOSPC;

1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
	if ((vif->type == NL80211_IFTYPE_ADHOC ||
	     vif->type == NL80211_IFTYPE_MESH_POINT) &&
	    (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
	     key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
		/*
		 * For now, disable hw crypto for the RSN IBSS group keys. This
		 * could be optimized in the future to use a modified key cache
		 * design to support per-STA RX GTK, but until that gets
		 * implemented, use of software crypto for group addressed
		 * frames is a acceptable to allow RSN IBSS to be used.
		 */
		return -EOPNOTSUPP;
	}

S
Sujith 已提交
1416
	mutex_lock(&priv->mutex);
1417
	ath_dbg(common, CONFIG, "Set HW Key\n");
1418
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1419 1420 1421

	switch (cmd) {
	case SET_KEY:
1422
		ret = ath_key_config(common, vif, sta, key);
S
Sujith 已提交
1423 1424 1425 1426
		if (ret >= 0) {
			key->hw_key_idx = ret;
			/* push IV and Michael MIC generation to stack */
			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
1427
			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
S
Sujith 已提交
1428
				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
1429 1430
			if (priv->ah->sw_mgmt_crypto &&
			    key->cipher == WLAN_CIPHER_SUITE_CCMP)
1431
				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
S
Sujith 已提交
1432 1433 1434 1435
			ret = 0;
		}
		break;
	case DISABLE_KEY:
1436
		ath_key_delete(common, key);
S
Sujith 已提交
1437 1438 1439 1440 1441
		break;
	default:
		ret = -EINVAL;
	}

1442
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1443 1444 1445 1446 1447
	mutex_unlock(&priv->mutex);

	return ret;
}

1448 1449 1450 1451 1452
static void ath9k_htc_set_bssid(struct ath9k_htc_priv *priv)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);

	ath9k_hw_write_associd(priv->ah);
1453
	ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
		common->curbssid, common->curaid);
}

static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;

	if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) {
		common->curaid = bss_conf->aid;
		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
	}
}

static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv)
{
	if (priv->num_sta_assoc_vif == 1) {
1472 1473 1474
		ieee80211_iterate_active_interfaces_atomic(
			priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
			ath9k_htc_bss_iter, priv);
1475 1476 1477 1478
		ath9k_htc_set_bssid(priv);
	}
}

S
Sujith 已提交
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
				       struct ieee80211_vif *vif,
				       struct ieee80211_bss_conf *bss_conf,
				       u32 changed)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);

	mutex_lock(&priv->mutex);
1489
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1490 1491

	if (changed & BSS_CHANGED_ASSOC) {
1492
		ath_dbg(common, CONFIG, "BSS Changed ASSOC %d\n",
1493
			bss_conf->assoc);
1494

1495 1496
		bss_conf->assoc ?
			priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--;
1497

1498
		if (priv->ah->opmode == NL80211_IFTYPE_STATION) {
1499
			ath9k_htc_choose_set_bssid(priv);
1500
			if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1))
1501
				ath9k_htc_start_ani(priv);
1502
			else if (priv->num_sta_assoc_vif == 0)
1503 1504
				ath9k_htc_stop_ani(priv);
		}
S
Sujith 已提交
1505 1506
	}

1507
	if (changed & BSS_CHANGED_IBSS) {
1508 1509
		if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) {
			common->curaid = bss_conf->aid;
1510
			memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
1511
			ath9k_htc_set_bssid(priv);
1512
		}
S
Sujith 已提交
1513 1514
	}

1515
	if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
1516 1517
		ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n",
			bss_conf->bssid);
1518
		ath9k_htc_set_tsfadjust(priv, vif);
1519
		set_bit(OP_ENABLE_BEACON, &priv->op_flags);
1520
		ath9k_htc_beacon_config(priv, vif);
S
Sujith 已提交
1521 1522
	}

1523 1524 1525 1526 1527 1528
	if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) {
		/*
		 * Disable SWBA interrupt only if there are no
		 * AP/IBSS interfaces.
		 */
		if ((priv->num_ap_vif <= 1) || priv->num_ibss_vif) {
1529
			ath_dbg(common, CONFIG,
1530 1531
				"Beacon disabled for BSS: %pM\n",
				bss_conf->bssid);
1532
			clear_bit(OP_ENABLE_BEACON, &priv->op_flags);
1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
			ath9k_htc_beacon_config(priv, vif);
		}
	}

	if (changed & BSS_CHANGED_BEACON_INT) {
		/*
		 * Reset the HW TSF for the first AP interface.
		 */
		if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
		    (priv->nvifs == 1) &&
		    (priv->num_ap_vif == 1) &&
		    (vif->type == NL80211_IFTYPE_AP)) {
1545
			set_bit(OP_TSF_RESET, &priv->op_flags);
1546
		}
1547
		ath_dbg(common, CONFIG,
1548 1549
			"Beacon interval changed for BSS: %pM\n",
			bss_conf->bssid);
1550
		ath9k_htc_beacon_config(priv, vif);
S
Sujith 已提交
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
	}

	if (changed & BSS_CHANGED_ERP_SLOT) {
		if (bss_conf->use_short_slot)
			ah->slottime = 9;
		else
			ah->slottime = 20;

		ath9k_hw_init_global_settings(ah);
	}

1562 1563 1564
	if (changed & BSS_CHANGED_HT)
		ath9k_htc_update_rate(priv, vif, bss_conf);

1565
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1566 1567 1568
	mutex_unlock(&priv->mutex);
}

1569 1570
static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif)
S
Sujith 已提交
1571 1572 1573 1574 1575
{
	struct ath9k_htc_priv *priv = hw->priv;
	u64 tsf;

	mutex_lock(&priv->mutex);
S
Sujith 已提交
1576
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1577
	tsf = ath9k_hw_gettsf64(priv->ah);
S
Sujith 已提交
1578
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1579 1580 1581 1582 1583
	mutex_unlock(&priv->mutex);

	return tsf;
}

1584 1585
static void ath9k_htc_set_tsf(struct ieee80211_hw *hw,
			      struct ieee80211_vif *vif, u64 tsf)
S
Sujith 已提交
1586 1587 1588 1589
{
	struct ath9k_htc_priv *priv = hw->priv;

	mutex_lock(&priv->mutex);
S
Sujith 已提交
1590
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1591
	ath9k_hw_settsf64(priv->ah, tsf);
S
Sujith 已提交
1592
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1593 1594 1595
	mutex_unlock(&priv->mutex);
}

1596 1597
static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw,
				struct ieee80211_vif *vif)
S
Sujith 已提交
1598 1599 1600 1601
{
	struct ath9k_htc_priv *priv = hw->priv;

	mutex_lock(&priv->mutex);
S
Sujith 已提交
1602
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1603
	ath9k_hw_reset_tsf(priv->ah);
1604
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1605
	mutex_unlock(&priv->mutex);
S
Sujith 已提交
1606 1607 1608 1609 1610 1611
}

static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
				  struct ieee80211_vif *vif,
				  enum ieee80211_ampdu_mlme_action action,
				  struct ieee80211_sta *sta,
1612
				  u16 tid, u16 *ssn, u8 buf_size)
S
Sujith 已提交
1613 1614 1615
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath9k_htc_sta *ista;
S
Sujith 已提交
1616
	int ret = 0;
S
Sujith 已提交
1617

1618
	mutex_lock(&priv->mutex);
1619
	ath9k_htc_ps_wakeup(priv);
1620

S
Sujith 已提交
1621 1622 1623 1624 1625 1626
	switch (action) {
	case IEEE80211_AMPDU_RX_START:
		break;
	case IEEE80211_AMPDU_RX_STOP:
		break;
	case IEEE80211_AMPDU_TX_START:
S
Sujith 已提交
1627 1628 1629 1630
		ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
		if (!ret)
			ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
		break;
1631 1632 1633
	case IEEE80211_AMPDU_TX_STOP_CONT:
	case IEEE80211_AMPDU_TX_STOP_FLUSH:
	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
S
Sujith 已提交
1634 1635
		ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
S
Sujith 已提交
1636 1637 1638
		break;
	case IEEE80211_AMPDU_TX_OPERATIONAL:
		ista = (struct ath9k_htc_sta *) sta->drv_priv;
1639
		spin_lock_bh(&priv->tx.tx_lock);
S
Sujith 已提交
1640
		ista->tid_state[tid] = AGGR_OPERATIONAL;
1641
		spin_unlock_bh(&priv->tx.tx_lock);
S
Sujith 已提交
1642 1643
		break;
	default:
1644
		ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n");
S
Sujith 已提交
1645 1646
	}

1647
	ath9k_htc_ps_restore(priv);
1648 1649
	mutex_unlock(&priv->mutex);

S
Sujith 已提交
1650
	return ret;
S
Sujith 已提交
1651 1652 1653 1654 1655 1656 1657 1658
}

static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
{
	struct ath9k_htc_priv *priv = hw->priv;

	mutex_lock(&priv->mutex);
	spin_lock_bh(&priv->beacon_lock);
1659
	set_bit(OP_SCANNING, &priv->op_flags);
S
Sujith 已提交
1660
	spin_unlock_bh(&priv->beacon_lock);
1661
	cancel_work_sync(&priv->ps_work);
1662
	ath9k_htc_stop_ani(priv);
S
Sujith 已提交
1663 1664 1665 1666 1667 1668 1669 1670 1671
	mutex_unlock(&priv->mutex);
}

static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
{
	struct ath9k_htc_priv *priv = hw->priv;

	mutex_lock(&priv->mutex);
	spin_lock_bh(&priv->beacon_lock);
1672
	clear_bit(OP_SCANNING, &priv->op_flags);
S
Sujith 已提交
1673
	spin_unlock_bh(&priv->beacon_lock);
1674 1675
	ath9k_htc_ps_wakeup(priv);
	ath9k_htc_vif_reconfig(priv);
1676
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1677
	mutex_unlock(&priv->mutex);
S
Sujith 已提交
1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690
}

static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
	return 0;
}

static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw,
					 u8 coverage_class)
{
	struct ath9k_htc_priv *priv = hw->priv;

	mutex_lock(&priv->mutex);
S
Sujith 已提交
1691
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1692 1693
	priv->ah->coverage_class = coverage_class;
	ath9k_hw_init_global_settings(priv->ah);
S
Sujith 已提交
1694
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1695 1696 1697
	mutex_unlock(&priv->mutex);
}

1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738
/*
 * Currently, this is used only for selecting the minimum rate
 * for management frames, rate selection for data frames remain
 * unaffected.
 */
static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw,
				      struct ieee80211_vif *vif,
				      const struct cfg80211_bitrate_mask *mask)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_rate_mask tmask;
	struct ath9k_htc_vif *avp = (void *)vif->drv_priv;
	int ret = 0;
	u8 cmd_rsp;

	memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask));

	tmask.vif_index = avp->index;
	tmask.band = IEEE80211_BAND_2GHZ;
	tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_2GHZ].legacy);

	WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask);
	if (ret) {
		ath_err(common,
			"Unable to set 2G rate mask for "
			"interface at idx: %d\n", avp->index);
		goto out;
	}

	tmask.band = IEEE80211_BAND_5GHZ;
	tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_5GHZ].legacy);

	WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask);
	if (ret) {
		ath_err(common,
			"Unable to set 5G rate mask for "
			"interface at idx: %d\n", avp->index);
		goto out;
	}

1739
	ath_dbg(common, CONFIG, "Set bitrate masks: 0x%x, 0x%x\n",
1740 1741 1742 1743 1744 1745
		mask->control[IEEE80211_BAND_2GHZ].legacy,
		mask->control[IEEE80211_BAND_5GHZ].legacy);
out:
	return ret;
}

1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761

static int ath9k_htc_get_stats(struct ieee80211_hw *hw,
			       struct ieee80211_low_level_stats *stats)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_hw *ah = priv->ah;
	struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;

	stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
	stats->dot11RTSFailureCount = mib_stats->rts_bad;
	stats->dot11FCSErrorCount = mib_stats->fcs_bad;
	stats->dot11RTSSuccessCount = mib_stats->rts_good;

	return 0;
}

S
Sujith 已提交
1762 1763 1764 1765 1766 1767 1768 1769
struct ieee80211_ops ath9k_htc_ops = {
	.tx                 = ath9k_htc_tx,
	.start              = ath9k_htc_start,
	.stop               = ath9k_htc_stop,
	.add_interface      = ath9k_htc_add_interface,
	.remove_interface   = ath9k_htc_remove_interface,
	.config             = ath9k_htc_config,
	.configure_filter   = ath9k_htc_configure_filter,
1770 1771
	.sta_add            = ath9k_htc_sta_add,
	.sta_remove         = ath9k_htc_sta_remove,
S
Sujith 已提交
1772
	.conf_tx            = ath9k_htc_conf_tx,
1773
	.sta_rc_update      = ath9k_htc_sta_rc_update,
S
Sujith 已提交
1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784
	.bss_info_changed   = ath9k_htc_bss_info_changed,
	.set_key            = ath9k_htc_set_key,
	.get_tsf            = ath9k_htc_get_tsf,
	.set_tsf            = ath9k_htc_set_tsf,
	.reset_tsf          = ath9k_htc_reset_tsf,
	.ampdu_action       = ath9k_htc_ampdu_action,
	.sw_scan_start      = ath9k_htc_sw_scan_start,
	.sw_scan_complete   = ath9k_htc_sw_scan_complete,
	.set_rts_threshold  = ath9k_htc_set_rts_threshold,
	.rfkill_poll        = ath9k_htc_rfkill_poll_state,
	.set_coverage_class = ath9k_htc_set_coverage_class,
1785
	.set_bitrate_mask   = ath9k_htc_set_bitrate_mask,
1786
	.get_stats	    = ath9k_htc_get_stats,
S
Sujith 已提交
1787
};