htc_drv_main.c 45.3 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
void ath9k_htc_reset(struct ath9k_htc_priv *priv)
{
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
193
	struct ieee80211_channel *channel = priv->hw->conf.chandef.chan;
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;
253
	struct ieee80211_channel *channel = hw->conf.chandef.chan;
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

605
	sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->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
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
907
	struct ieee80211_channel *curchan = hw->conf.chandef.chan;
S
Sujith 已提交
908 909 910
	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) {
1196 1197 1198
		struct ieee80211_channel *curchan = hw->conf.chandef.chan;
		enum nl80211_channel_type channel_type =
			cfg80211_get_chandef_type(&hw->conf.chandef);
S
Sujith 已提交
1199 1200
		int pos = curchan->hw_value;

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

1204
		ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
1205 1206
					  hw->conf.chandef.chan,
					  channel_type);
S
Sujith 已提交
1207 1208

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

	}
1215

1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
	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 已提交
1226

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

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

#define SUPPORTED_FILTERS			\
	(FIF_PROMISC_IN_BSS |			\
	FIF_ALLMULTI |				\
	FIF_CONTROL |				\
	FIF_PSPOLL |				\
	FIF_OTHER_BSS |				\
	FIF_BCN_PRBRESP_PROMISC |		\
1246
	FIF_PROBE_REQ |				\
S
Sujith 已提交
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
	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;

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

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

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

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

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

1287
	mutex_lock(&priv->mutex);
S
Sujith 已提交
1288
	ath9k_htc_ps_wakeup(priv);
1289 1290 1291 1292 1293
	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);
1294

1295 1296 1297 1298 1299 1300 1301 1302
	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;
1303
	struct ath9k_htc_sta *ista;
1304
	int ret;
1305

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

	return ret;
S
Sujith 已提交
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 1343 1344
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);
}

1345 1346
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif, u16 queue,
S
Sujith 已提交
1347 1348 1349 1350 1351 1352 1353
			     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;

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

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

	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;
1365
	qi.tqi_burstTime = params->txop * 32;
S
Sujith 已提交
1366 1367 1368

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

1369
	ath_dbg(common, CONFIG,
J
Joe Perches 已提交
1370 1371 1372
		"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 已提交
1373

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

S
Sujith 已提交
1380
	if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
1381
	    (qnum == priv->hwq_map[IEEE80211_AC_BE]))
S
Sujith 已提交
1382 1383
		    ath9k_htc_beaconq_config(priv);
out:
S
Sujith 已提交
1384
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
	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;

1400
	if (htc_modparam_nohwcrypt)
S
Sujith 已提交
1401 1402
		return -ENOSPC;

1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
	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 已提交
1418
	mutex_lock(&priv->mutex);
1419
	ath_dbg(common, CONFIG, "Set HW Key\n");
1420
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1421 1422 1423

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

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

	return ret;
}

1450 1451 1452 1453 1454
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);
1455
	ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
		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) {
1474 1475 1476
		ieee80211_iterate_active_interfaces_atomic(
			priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
			ath9k_htc_bss_iter, priv);
1477 1478 1479 1480
		ath9k_htc_set_bssid(priv);
	}
}

S
Sujith 已提交
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
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);
1491
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1492 1493

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

1497 1498
		bss_conf->assoc ?
			priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--;
1499

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

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

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

1525 1526 1527 1528 1529 1530
	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) {
1531
			ath_dbg(common, CONFIG,
1532 1533
				"Beacon disabled for BSS: %pM\n",
				bss_conf->bssid);
1534
			clear_bit(OP_ENABLE_BEACON, &priv->op_flags);
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
			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)) {
1547
			set_bit(OP_TSF_RESET, &priv->op_flags);
1548
		}
1549
		ath_dbg(common, CONFIG,
1550 1551
			"Beacon interval changed for BSS: %pM\n",
			bss_conf->bssid);
1552
		ath9k_htc_beacon_config(priv, vif);
S
Sujith 已提交
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563
	}

	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);
	}

1564 1565 1566
	if (changed & BSS_CHANGED_HT)
		ath9k_htc_update_rate(priv, vif, bss_conf);

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

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

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

	return tsf;
}

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

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

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

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

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

1620
	mutex_lock(&priv->mutex);
1621
	ath9k_htc_ps_wakeup(priv);
1622

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

1649
	ath9k_htc_ps_restore(priv);
1650 1651
	mutex_unlock(&priv->mutex);

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

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);
1661
	set_bit(OP_SCANNING, &priv->op_flags);
S
Sujith 已提交
1662
	spin_unlock_bh(&priv->beacon_lock);
1663
	cancel_work_sync(&priv->ps_work);
1664
	ath9k_htc_stop_ani(priv);
S
Sujith 已提交
1665 1666 1667 1668 1669 1670 1671 1672 1673
	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);
1674
	clear_bit(OP_SCANNING, &priv->op_flags);
S
Sujith 已提交
1675
	spin_unlock_bh(&priv->beacon_lock);
1676 1677
	ath9k_htc_ps_wakeup(priv);
	ath9k_htc_vif_reconfig(priv);
1678
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1679
	mutex_unlock(&priv->mutex);
S
Sujith 已提交
1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692
}

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 已提交
1693
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1694 1695
	priv->ah->coverage_class = coverage_class;
	ath9k_hw_init_global_settings(priv->ah);
S
Sujith 已提交
1696
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1697 1698 1699
	mutex_unlock(&priv->mutex);
}

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 1739 1740
/*
 * 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;
	}

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

1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763

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 已提交
1764 1765 1766 1767 1768 1769 1770 1771
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,
1772 1773
	.sta_add            = ath9k_htc_sta_add,
	.sta_remove         = ath9k_htc_sta_remove,
S
Sujith 已提交
1774
	.conf_tx            = ath9k_htc_conf_tx,
1775
	.sta_rc_update      = ath9k_htc_sta_rc_update,
S
Sujith 已提交
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786
	.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,
1787
	.set_bitrate_mask   = ath9k_htc_set_bitrate_mask,
1788
	.get_stats	    = ath9k_htc_get_stats,
S
Sujith 已提交
1789
};