htc_drv_main.c 46.8 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
 *
 * 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)
{
27 28
	if (IS_CHAN_5GHZ(ichan))
		return HTC_MODE_11NA;
S
Sujith 已提交
29

30
	return HTC_MODE_11NG;
S
Sujith 已提交
31 32
}

S
Sujith Manoharan 已提交
33 34
bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
			enum ath9k_power_mode mode)
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
{
	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)
{
58 59
	bool reset;

60 61 62 63
	mutex_lock(&priv->htc_pm_lock);
	if (--priv->ps_usecount != 0)
		goto unlock;

64 65 66
	if (priv->ps_idle) {
		ath9k_hw_setrxabort(priv->ah, true);
		ath9k_hw_stopdmarecv(priv->ah, &reset);
67
		ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
68
	} else if (priv->ps_enabled) {
69
		ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
70
	}
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
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);
}

91 92 93 94 95
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;

96 97 98
	if ((vif->type == NL80211_IFTYPE_AP ||
	     vif->type == NL80211_IFTYPE_MESH_POINT) &&
	    bss_conf->enable_beacon)
99 100
		priv->reconfig_beacon = true;

101 102 103 104 105 106 107 108 109 110 111
	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;

112 113 114
	ieee80211_iterate_active_interfaces_atomic(
		priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
		ath9k_htc_vif_iter, priv);
115
	if (priv->rearm_ani)
116
		ath9k_htc_start_ani(priv);
117 118 119 120 121 122 123 124

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

125 126 127 128 129
static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
	struct ath9k_vif_iter_data *iter_data = data;
	int i;

130 131 132 133 134 135
	if (iter_data->hw_macaddr != NULL) {
		for (i = 0; i < ETH_ALEN; i++)
			iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
	} else {
		iter_data->hw_macaddr = mac;
	}
136 137
}

138
static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv,
139 140 141 142 143 144
				     struct ieee80211_vif *vif)
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_vif_iter_data iter_data;

	/*
145 146 147
	 * Pick the MAC address of the first interface as the new hardware
	 * MAC address. The hardware will use it together with the BSSID mask
	 * when matching addresses.
148
	 */
149
	iter_data.hw_macaddr = NULL;
150 151 152 153 154 155
	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 */
156 157 158
	ieee80211_iterate_active_interfaces_atomic(
		priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
		ath9k_htc_bssid_iter, &iter_data);
159 160

	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
161 162 163 164

	if (iter_data.hw_macaddr)
		memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);

165 166 167
	ath_hw_setbssidmask(common);
}

168 169 170 171 172 173
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;
174 175
	else if (priv->num_mbss_vif)
		priv->ah->opmode = NL80211_IFTYPE_MESH_POINT;
176 177 178 179 180 181
	else
		priv->ah->opmode = NL80211_IFTYPE_STATION;

	ath9k_hw_setopmode(priv->ah);
}

182 183 184 185
void ath9k_htc_reset(struct ath9k_htc_priv *priv)
{
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
186
	struct ieee80211_channel *channel = priv->hw->conf.chandef.chan;
187
	struct ath9k_hw_cal_data *caldata = NULL;
188 189 190 191 192 193 194 195
	enum htc_phymode mode;
	__be16 htc_mode;
	u8 cmd_rsp;
	int ret;

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

196
	ath9k_htc_stop_ani(priv);
197
	ieee80211_stop_queues(priv->hw);
198

199
	del_timer_sync(&priv->tx.cleanup_timer);
200 201
	ath9k_htc_tx_drain(priv);

202 203 204 205
	WMI_CMD(WMI_DISABLE_INTR_CMDID);
	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
	WMI_CMD(WMI_STOP_RECV_CMDID);

S
Sujith Manoharan 已提交
206 207
	ath9k_wmi_event_drain(priv);

208
	caldata = &priv->caldata;
209 210 211 212 213 214 215
	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);
	}

216 217
	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
			       &priv->curtxpow);
218 219 220 221 222 223 224 225 226 227

	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);
228
	ath9k_htc_vif_reconfig(priv);
229 230
	ieee80211_wake_queues(priv->hw);

231 232 233
	mod_timer(&priv->tx.cleanup_timer,
		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));

234 235 236 237
	ath9k_htc_ps_restore(priv);
	mutex_unlock(&priv->mutex);
}

S
Sujith 已提交
238 239 240 241 242 243 244
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;
245
	bool fastcc;
246
	struct ieee80211_channel *channel = hw->conf.chandef.chan;
247
	struct ath9k_hw_cal_data *caldata = NULL;
S
Sujith 已提交
248
	enum htc_phymode mode;
S
Sujith 已提交
249
	__be16 htc_mode;
S
Sujith 已提交
250 251 252
	u8 cmd_rsp;
	int ret;

253
	if (test_bit(OP_INVALID, &priv->op_flags))
S
Sujith 已提交
254 255
		return -EIO;

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

258
	ath9k_htc_ps_wakeup(priv);
259

260
	del_timer_sync(&priv->tx.cleanup_timer);
261 262
	ath9k_htc_tx_drain(priv);

S
Sujith 已提交
263 264 265 266
	WMI_CMD(WMI_DISABLE_INTR_CMDID);
	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
	WMI_CMD(WMI_STOP_RECV_CMDID);

S
Sujith Manoharan 已提交
267 268
	ath9k_wmi_event_drain(priv);

269
	ath_dbg(common, CONFIG,
J
Joe Perches 已提交
270 271 272 273
		"(%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 已提交
274

275 276
	if (!fastcc)
		caldata = &priv->caldata;
277

278
	ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
S
Sujith 已提交
279
	if (ret) {
280 281 282
		ath_err(common,
			"Unable to reset channel (%u Mhz) reset status %d\n",
			channel->center_freq, ret);
S
Sujith 已提交
283 284 285
		goto err;
	}

286 287
	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
			       &priv->curtxpow);
S
Sujith 已提交
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305

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

307
	if (!test_bit(OP_SCANNING, &priv->op_flags) &&
308 309 310
	    !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
		ath9k_htc_vif_reconfig(priv);

311 312 313
	mod_timer(&priv->tx.cleanup_timer,
		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));

S
Sujith 已提交
314
err:
315
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
316 317 318
	return ret;
}

319 320 321 322 323 324 325
/*
 * 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.
 */
326 327 328 329 330 331 332 333 334
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);
335
	hvif.index = priv->mon_vif_idx;
336
	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
337 338 339 340 341
	if (ret) {
		ath_err(common, "Unable to remove monitor interface at idx: %d\n",
			priv->mon_vif_idx);
	}

342
	priv->nvifs--;
343
	priv->vif_slot &= ~(1 << priv->mon_vif_idx);
344 345
}

346 347 348 349
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;
350
	struct ath9k_htc_target_sta tsta;
351
	int ret = 0, sta_idx;
352 353
	u8 cmd_rsp;

354 355 356 357 358
	if ((priv->nvifs >= ATH9K_HTC_MAX_VIF) ||
	    (priv->nstations >= ATH9K_HTC_MAX_STA)) {
		ret = -ENOBUFS;
		goto err_vif;
	}
359

360 361 362 363 364
	sta_idx = ffz(priv->sta_slot);
	if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) {
		ret = -ENOBUFS;
		goto err_vif;
	}
365 366 367 368

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

372
	hvif.opmode = HTC_M_MONITOR;
373
	hvif.index = ffz(priv->vif_slot);
374 375 376

	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
	if (ret)
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
		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;
392 393

	priv->nvifs++;
394 395 396 397 398 399 400 401 402

	/*
	 * 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;
403
	tsta.sta_index = sta_idx;
404
	tsta.vif_index = hvif.index;
405
	tsta.maxampdu = cpu_to_be16(0xffff);
406 407 408 409

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

413
	priv->sta_slot |= (1 << sta_idx);
414
	priv->nstations++;
415
	priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx;
416 417
	priv->ah->is_monitoring = true;

418
	ath_dbg(common, CONFIG,
419 420 421
		"Attached a monitor interface at idx: %d, sta idx: %d\n",
		priv->mon_vif_idx, sta_idx);

422
	return 0;
423

424
err_sta:
425 426 427 428
	/*
	 * Remove the interface from the target.
	 */
	__ath9k_htc_remove_monitor_interface(priv);
429
err_vif:
430
	ath_dbg(common, FATAL, "Unable to attach a monitor interface\n");
431

432
	return ret;
433 434 435 436 437 438
}

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

441
	__ath9k_htc_remove_monitor_interface(priv);
442

443
	sta_idx = priv->vif_sta_pos[priv->mon_vif_idx];
444 445 446 447 448 449 450

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

451
	priv->sta_slot &= ~(1 << sta_idx);
452
	priv->nstations--;
453
	priv->ah->is_monitoring = false;
454

455
	ath_dbg(common, CONFIG,
456 457 458
		"Removed a monitor interface at idx: %d, sta idx: %d\n",
		priv->mon_vif_idx, sta_idx);

459
	return 0;
460 461
}

S
Sujith 已提交
462 463 464 465 466 467 468 469
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;
470
	int ret, sta_idx;
S
Sujith 已提交
471
	u8 cmd_rsp;
472
	u16 maxampdu;
S
Sujith 已提交
473 474 475 476

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

477 478 479 480
	sta_idx = ffz(priv->sta_slot);
	if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA))
		return -ENOBUFS;

S
Sujith 已提交
481 482 483 484 485 486
	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);
487
		ista->index = sta_idx;
488 489 490 491
		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 已提交
492 493 494
	} else {
		memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
		tsta.is_vif_sta = 1;
495
		tsta.maxampdu = cpu_to_be16(0xffff);
S
Sujith 已提交
496 497
	}

498
	tsta.sta_index = sta_idx;
S
Sujith 已提交
499
	tsta.vif_index = avp->index;
500

S
Sujith 已提交
501 502 503
	WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
	if (ret) {
		if (sta)
504 505 506
			ath_err(common,
				"Unable to add station entry for: %pM\n",
				sta->addr);
S
Sujith 已提交
507 508 509
		return ret;
	}

510
	if (sta) {
511
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
512 513
			"Added a station entry for: %pM (idx: %d)\n",
			sta->addr, tsta.sta_index);
514
	} else {
515
		ath_dbg(common, CONFIG,
516 517 518
			"Added a station entry for VIF %d (idx: %d)\n",
			avp->index, tsta.sta_index);
	}
S
Sujith 已提交
519

520
	priv->sta_slot |= (1 << sta_idx);
S
Sujith 已提交
521
	priv->nstations++;
522 523 524
	if (!sta)
		priv->vif_sta_pos[avp->index] = sta_idx;

S
Sujith 已提交
525 526 527 528 529 530 531 532
	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);
533
	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
S
Sujith 已提交
534 535 536 537 538 539 540 541
	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 {
542
		sta_idx = priv->vif_sta_pos[avp->index];
S
Sujith 已提交
543 544 545 546 547
	}

	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
	if (ret) {
		if (sta)
548 549 550
			ath_err(common,
				"Unable to remove station entry for: %pM\n",
				sta->addr);
S
Sujith 已提交
551 552 553
		return ret;
	}

554
	if (sta) {
555
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
556 557
			"Removed a station entry for: %pM (idx: %d)\n",
			sta->addr, sta_idx);
558
	} else {
559
		ath_dbg(common, CONFIG,
560 561 562
			"Removed a station entry for VIF %d (idx: %d)\n",
			avp->index, sta_idx);
	}
S
Sujith 已提交
563

564
	priv->sta_slot &= ~(1 << sta_idx);
S
Sujith 已提交
565
	priv->nstations--;
566

S
Sujith 已提交
567 568 569
	return 0;
}

570 571
int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv,
				u8 enable_coex)
S
Sujith 已提交
572 573 574 575 576 577 578
{
	struct ath9k_htc_cap_target tcap;
	int ret;
	u8 cmd_rsp;

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

579
	tcap.ampdu_limit = cpu_to_be32(0xffff);
580
	tcap.ampdu_subframes = 0xff;
581
	tcap.enable_coex = enable_coex;
S
Sujith 已提交
582
	tcap.tx_chainmask = priv->ah->caps.tx_chainmask;
S
Sujith 已提交
583 584 585 586 587 588

	WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap);

	return ret;
}

S
Sujith 已提交
589 590 591
static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv,
				 struct ieee80211_sta *sta,
				 struct ath9k_htc_target_rate *trate)
S
Sujith 已提交
592 593 594 595
{
	struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
	struct ieee80211_supported_band *sband;
	u32 caps = 0;
S
Sujith 已提交
596
	int i, j;
S
Sujith 已提交
597

598
	sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band];
S
Sujith 已提交
599 600 601

	for (i = 0, j = 0; i < sband->n_bitrates; i++) {
		if (sta->supp_rates[sband->band] & BIT(i)) {
S
Sujith 已提交
602
			trate->rates.legacy_rates.rs_rates[j]
S
Sujith 已提交
603 604 605 606
				= (sband->bitrates[i].bitrate * 2) / 10;
			j++;
		}
	}
S
Sujith 已提交
607
	trate->rates.legacy_rates.rs_nrates = j;
S
Sujith 已提交
608 609 610 611

	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 已提交
612
				trate->rates.ht_rates.rs_rates[j++] = i;
S
Sujith 已提交
613 614 615
			if (j == ATH_HTC_RATE_MAX)
				break;
		}
S
Sujith 已提交
616
		trate->rates.ht_rates.rs_nrates = j;
S
Sujith 已提交
617 618

		caps = WLAN_RC_HT_FLAG;
O
Oleksij Rempel 已提交
619 620
		if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
			caps |= ATH_RC_TX_STBC_FLAG;
621 622
		if (sta->ht_cap.mcs.rx_mask[1])
			caps |= WLAN_RC_DS_FLAG;
623 624
		if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
		     (conf_is_ht40(&priv->hw->conf)))
S
Sujith 已提交
625
			caps |= WLAN_RC_40_FLAG;
626 627 628 629 630
		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 已提交
631 632 633
			caps |= WLAN_RC_SGI_FLAG;
	}

S
Sujith 已提交
634 635 636 637 638 639 640 641 642 643 644
	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 已提交
645

S
Sujith 已提交
646
	WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate);
S
Sujith 已提交
647
	if (ret) {
648 649
		ath_err(common,
			"Unable to initialize Rate information on target\n");
S
Sujith 已提交
650 651
	}

S
Sujith 已提交
652
	return ret;
S
Sujith 已提交
653 654
}

S
Sujith 已提交
655 656
static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv,
				struct ieee80211_sta *sta)
S
Sujith 已提交
657 658
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
S
Sujith 已提交
659
	struct ath9k_htc_target_rate trate;
S
Sujith 已提交
660 661
	int ret;

S
Sujith 已提交
662 663 664 665
	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)
666
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
667 668
			"Updated target sta: %pM, rate caps: 0x%X\n",
			sta->addr, be32_to_cpu(trate.capflags));
S
Sujith 已提交
669 670
}

671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
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)
693
		ath_dbg(common, CONFIG,
J
Joe Perches 已提交
694 695
			"Updated target sta: %pM, rate caps: 0x%X\n",
			bss_conf->bssid, be32_to_cpu(trate.capflags));
696 697
}

698 699 700 701 702
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 已提交
703 704 705
{
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_htc_target_aggr aggr;
706
	struct ath9k_htc_sta *ista;
S
Sujith 已提交
707 708 709
	int ret = 0;
	u8 cmd_rsp;

710
	if (tid >= ATH9K_HTC_MAX_TID)
S
Sujith 已提交
711 712
		return -EINVAL;

713 714
	memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));
	ista = (struct ath9k_htc_sta *) sta->drv_priv;
S
Sujith 已提交
715 716

	aggr.sta_index = ista->index;
S
Sujith 已提交
717 718
	aggr.tidno = tid & 0xf;
	aggr.aggr_enable = (action == IEEE80211_AMPDU_TX_START) ? true : false;
S
Sujith 已提交
719 720 721

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

731
	spin_lock_bh(&priv->tx.tx_lock);
S
Sujith 已提交
732
	ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP;
733
	spin_unlock_bh(&priv->tx.tx_lock);
S
Sujith 已提交
734

S
Sujith 已提交
735
	return ret;
S
Sujith 已提交
736 737 738 739 740 741
}

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

742
void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
S
Sujith 已提交
743 744 745 746 747 748 749 750
{
	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;

751
	set_bit(OP_ANI_RUNNING, &priv->op_flags);
752 753

	ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
S
Sujith 已提交
754 755 756
				     msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
}

757 758 759
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv)
{
	cancel_delayed_work_sync(&priv->ani_work);
760
	clear_bit(OP_ANI_RUNNING, &priv->op_flags);
761 762 763
}

void ath9k_htc_ani_work(struct work_struct *work)
S
Sujith 已提交
764 765
{
	struct ath9k_htc_priv *priv =
766
		container_of(work, struct ath9k_htc_priv, ani_work.work);
S
Sujith 已提交
767 768 769 770 771 772 773 774
	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;

775 776
	short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
S
Sujith 已提交
777

778 779 780 781
	/* Only calibrate if awake */
	if (ah->power_mode != ATH9K_PM_AWAKE)
		goto set_timer;

S
Sujith 已提交
782 783 784
	/* Long calibration runs independently of short calibration. */
	if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
		longcal = true;
785
		ath_dbg(common, ANI, "longcal @%lu\n", jiffies);
S
Sujith 已提交
786 787 788 789 790 791 792 793
		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;
794
			ath_dbg(common, ANI, "shortcal @%lu\n", jiffies);
S
Sujith 已提交
795 796 797 798 799 800 801 802 803 804 805 806 807
			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 */
808
	if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
S
Sujith 已提交
809 810 811 812 813 814
		aniflag = true;
		common->ani.checkani_timer = timestamp;
	}

	/* Skip all processing if there's nothing to do. */
	if (longcal || shortcal || aniflag) {
815 816 817

		ath9k_htc_ps_wakeup(priv);

S
Sujith 已提交
818 819 820 821 822
		/* Call ANI routine if necessary */
		if (aniflag)
			ath9k_hw_ani_monitor(ah, ah->curchan);

		/* Perform calibration if necessary */
823
		if (longcal || shortcal)
S
Sujith 已提交
824 825
			common->ani.caldone =
				ath9k_hw_calibrate(ah, ah->curchan,
826
						   ah->rxchainmask, longcal);
S
Sujith 已提交
827

828
		ath9k_htc_ps_restore(priv);
S
Sujith 已提交
829 830
	}

831
set_timer:
S
Sujith 已提交
832 833 834 835 836 837
	/*
	* 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;
838
	cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
S
Sujith 已提交
839 840 841
	if (!common->ani.caldone)
		cal_interval = min(cal_interval, (u32)short_cal_interval);

842
	ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
S
Sujith 已提交
843 844 845 846 847 848 849
				     msecs_to_jiffies(cal_interval));
}

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

850 851 852
static void ath9k_htc_tx(struct ieee80211_hw *hw,
			 struct ieee80211_tx_control *control,
			 struct sk_buff *skb)
S
Sujith 已提交
853 854 855
{
	struct ieee80211_hdr *hdr;
	struct ath9k_htc_priv *priv = hw->priv;
856
	struct ath_common *common = ath9k_hw_common(priv->ah);
S
Sujith Manoharan 已提交
857
	int padpos, padsize, ret, slot;
S
Sujith 已提交
858 859 860 861

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

	/* Add the padding after the header if this is not already done */
862
	padpos = ieee80211_hdrlen(hdr->frame_control);
S
Sujith 已提交
863 864
	padsize = padpos & 3;
	if (padsize && skb->len > padpos) {
865
		if (skb_headroom(skb) < padsize) {
866
			ath_dbg(common, XMIT, "No room for padding\n");
867
			goto fail_tx;
868
		}
S
Sujith 已提交
869 870 871 872
		skb_push(skb, padsize);
		memmove(skb->data, skb->data + padsize, padpos);
	}

S
Sujith Manoharan 已提交
873 874
	slot = ath9k_htc_tx_get_slot(priv);
	if (slot < 0) {
875
		ath_dbg(common, XMIT, "No free TX slot\n");
S
Sujith Manoharan 已提交
876 877 878
		goto fail_tx;
	}

879
	ret = ath9k_htc_tx_start(priv, control->sta, skb, slot, false);
S
Sujith 已提交
880
	if (ret != 0) {
881
		ath_dbg(common, XMIT, "Tx failed\n");
S
Sujith Manoharan 已提交
882
		goto clear_slot;
S
Sujith 已提交
883 884
	}

885 886
	ath9k_htc_check_stop_queues(priv);

887
	return;
S
Sujith 已提交
888

S
Sujith Manoharan 已提交
889 890
clear_slot:
	ath9k_htc_tx_clear_slot(priv, slot);
S
Sujith 已提交
891 892 893 894
fail_tx:
	dev_kfree_skb_any(skb);
}

S
Sujith 已提交
895
static int ath9k_htc_start(struct ieee80211_hw *hw)
S
Sujith 已提交
896 897 898 899
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
900
	struct ieee80211_channel *curchan = hw->conf.chandef.chan;
S
Sujith 已提交
901 902 903
	struct ath9k_channel *init_channel;
	int ret = 0;
	enum htc_phymode mode;
S
Sujith 已提交
904
	__be16 htc_mode;
S
Sujith 已提交
905 906
	u8 cmd_rsp;

S
Sujith 已提交
907 908
	mutex_lock(&priv->mutex);

909
	ath_dbg(common, CONFIG,
J
Joe Perches 已提交
910 911
		"Starting driver with initial channel: %d MHz\n",
		curchan->center_freq);
S
Sujith 已提交
912

S
Sujith 已提交
913 914 915 916
	/* Ensure that HW is awake before flushing RX */
	ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
	WMI_CMD(WMI_FLUSH_RECV_CMDID);

S
Sujith 已提交
917
	/* setup initial channel */
918
	init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
S
Sujith 已提交
919

920
	ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
S
Sujith 已提交
921
	if (ret) {
922 923 924
		ath_err(common,
			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
			ret, curchan->center_freq);
S
Sujith 已提交
925
		mutex_unlock(&priv->mutex);
926
		return ret;
S
Sujith 已提交
927 928
	}

929 930
	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
			       &priv->curtxpow);
S
Sujith 已提交
931 932 933 934 935 936 937 938 939

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

940
	ret = ath9k_htc_update_cap_target(priv, 0);
941
	if (ret)
942
		ath_dbg(common, CONFIG,
943 944
			"Failed to update capability in target\n");

945
	clear_bit(OP_INVALID, &priv->op_flags);
S
Sujith 已提交
946 947
	htc_start(priv->htc);

948
	spin_lock_bh(&priv->tx.tx_lock);
949
	priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
950
	spin_unlock_bh(&priv->tx.tx_lock);
S
Sujith 已提交
951 952 953

	ieee80211_wake_queues(hw);

954 955 956
	mod_timer(&priv->tx.cleanup_timer,
		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));

957 958
	ath9k_htc_start_btcoex(priv);

S
Sujith 已提交
959
	mutex_unlock(&priv->mutex);
960

S
Sujith 已提交
961 962 963
	return ret;
}

S
Sujith 已提交
964
static void ath9k_htc_stop(struct ieee80211_hw *hw)
S
Sujith 已提交
965 966 967 968
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
969
	int ret __attribute__ ((unused));
S
Sujith 已提交
970 971
	u8 cmd_rsp;

S
Sujith 已提交
972 973
	mutex_lock(&priv->mutex);

974
	if (test_bit(OP_INVALID, &priv->op_flags)) {
975
		ath_dbg(common, ANY, "Device not present\n");
S
Sujith 已提交
976
		mutex_unlock(&priv->mutex);
S
Sujith 已提交
977 978 979
		return;
	}

980
	ath9k_htc_ps_wakeup(priv);
981

S
Sujith 已提交
982 983 984
	WMI_CMD(WMI_DISABLE_INTR_CMDID);
	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
	WMI_CMD(WMI_STOP_RECV_CMDID);
985 986

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

988
	del_timer_sync(&priv->tx.cleanup_timer);
989
	ath9k_htc_tx_drain(priv);
S
Sujith Manoharan 已提交
990 991
	ath9k_wmi_event_drain(priv);

992 993 994 995 996
	mutex_unlock(&priv->mutex);

	/* Cancel all the running timers/work .. */
	cancel_work_sync(&priv->fatal_work);
	cancel_work_sync(&priv->ps_work);
997 998 999 1000

#ifdef CONFIG_MAC80211_LEDS
	cancel_work_sync(&priv->led_work);
#endif
1001
	ath9k_htc_stop_ani(priv);
1002 1003 1004

	mutex_lock(&priv->mutex);

1005
	ath9k_htc_stop_btcoex(priv);
1006

1007 1008 1009 1010
	/* Remove a monitor interface if it's present. */
	if (priv->ah->is_monitoring)
		ath9k_htc_remove_monitor_interface(priv);

1011 1012 1013 1014 1015
	ath9k_hw_phy_disable(ah);
	ath9k_hw_disable(ah);
	ath9k_htc_ps_restore(priv);
	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);

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

1018
	ath_dbg(common, CONFIG, "Driver halt\n");
1019 1020 1021
	mutex_unlock(&priv->mutex);
}

S
Sujith 已提交
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
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);

1034
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1035 1036 1037 1038 1039
	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
	memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);

	switch (vif->type) {
	case NL80211_IFTYPE_STATION:
1040
		hvif.opmode = HTC_M_STA;
S
Sujith 已提交
1041 1042
		break;
	case NL80211_IFTYPE_ADHOC:
1043
		hvif.opmode = HTC_M_IBSS;
S
Sujith 已提交
1044
		break;
1045
	case NL80211_IFTYPE_AP:
1046
		hvif.opmode = HTC_M_HOSTAP;
1047
		break;
1048 1049 1050
	case NL80211_IFTYPE_MESH_POINT:
		hvif.opmode = HTC_M_WDS;	/* close enough */
		break;
S
Sujith 已提交
1051
	default:
1052
		ath_err(common,
S
Sujith 已提交
1053 1054 1055 1056 1057 1058
			"Interface type %d not yet supported\n", vif->type);
		ret = -EOPNOTSUPP;
		goto out;
	}

	/* Index starts from zero on the target */
1059
	avp->index = hvif.index = ffz(priv->vif_slot);
S
Sujith 已提交
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
	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);
1070 1071
	if (ret) {
		WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
S
Sujith 已提交
1072
		goto out;
1073
	}
S
Sujith 已提交
1074

1075
	ath9k_htc_set_mac_bssid_mask(priv, vif);
1076

1077
	priv->vif_slot |= (1 << avp->index);
1078
	priv->nvifs++;
1079

1080
	INC_VIF(priv, vif->type);
S
Sujith Manoharan 已提交
1081 1082

	if ((vif->type == NL80211_IFTYPE_AP) ||
1083
	    (vif->type == NL80211_IFTYPE_MESH_POINT) ||
S
Sujith Manoharan 已提交
1084 1085 1086
	    (vif->type == NL80211_IFTYPE_ADHOC))
		ath9k_htc_assign_bslot(priv, vif);

1087
	ath9k_htc_set_opmode(priv);
1088

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

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

S
Sujith 已提交
1098
out:
1099
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1100
	mutex_unlock(&priv->mutex);
S
Sujith 已提交
1101

S
Sujith 已提交
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
	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 已提交
1116
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1117 1118 1119 1120 1121

	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);
1122 1123 1124 1125
	if (ret) {
		ath_err(common, "Unable to remove interface at idx: %d\n",
			avp->index);
	}
S
Sujith 已提交
1126
	priv->nvifs--;
1127
	priv->vif_slot &= ~(1 << avp->index);
S
Sujith 已提交
1128 1129 1130

	ath9k_htc_remove_station(priv, vif, NULL);

1131
	DEC_VIF(priv, vif->type);
S
Sujith Manoharan 已提交
1132 1133

	if ((vif->type == NL80211_IFTYPE_AP) ||
1134
	     vif->type == NL80211_IFTYPE_MESH_POINT ||
S
Sujith Manoharan 已提交
1135 1136 1137
	    (vif->type == NL80211_IFTYPE_ADHOC))
		ath9k_htc_remove_bslot(priv, vif);

1138
	ath9k_htc_set_opmode(priv);
1139

1140
	ath9k_htc_set_mac_bssid_mask(priv, vif);
1141

1142 1143 1144 1145 1146
	/*
	 * 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;
1147 1148 1149
		ieee80211_iterate_active_interfaces_atomic(
			priv->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
			ath9k_htc_vif_iter, priv);
1150 1151 1152 1153
		if (!priv->rearm_ani)
			ath9k_htc_stop_ani(priv);
	}

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

S
Sujith 已提交
1156
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1157 1158 1159 1160 1161 1162 1163 1164
	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;
1165 1166
	bool chip_reset = false;
	int ret = 0;
S
Sujith 已提交
1167 1168

	mutex_lock(&priv->mutex);
1169
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1170

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

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

		mutex_unlock(&priv->htc_pm_lock);
1179 1180
	}

1181 1182 1183 1184 1185
	/*
	 * Monitor interface should be added before
	 * IEEE80211_CONF_CHANGE_CHANNEL is handled.
	 */
	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1186 1187 1188 1189 1190
		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);
1191 1192
	}

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

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

1200
		ath9k_cmn_get_channel(hw, priv->ah, &hw->conf.chandef);
S
Sujith 已提交
1201
		if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
1202
			ath_err(common, "Unable to set channel\n");
1203 1204
			ret = -EINVAL;
			goto out;
S
Sujith 已提交
1205 1206 1207
		}

	}
1208

1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
	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 已提交
1219

1220 1221
	if (changed & IEEE80211_CONF_CHANGE_POWER) {
		priv->txpowlimit = 2 * conf->power_level;
1222 1223
		ath9k_cmn_update_txpow(priv->ah, priv->curtxpow,
				       priv->txpowlimit, &priv->curtxpow);
1224 1225
	}

S
Sujith 已提交
1226
out:
1227
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1228
	mutex_unlock(&priv->mutex);
1229
	return ret;
S
Sujith 已提交
1230 1231 1232 1233 1234 1235 1236 1237 1238
}

#define SUPPORTED_FILTERS			\
	(FIF_PROMISC_IN_BSS |			\
	FIF_ALLMULTI |				\
	FIF_CONTROL |				\
	FIF_PSPOLL |				\
	FIF_OTHER_BSS |				\
	FIF_BCN_PRBRESP_PROMISC |		\
1239
	FIF_PROBE_REQ |				\
S
Sujith 已提交
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
	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;

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

S
Sujith 已提交
1262
	priv->rxfilter = *total_flags;
1263
	rfilt = ath9k_htc_calcrxfilter(priv);
S
Sujith 已提交
1264 1265
	ath9k_hw_setrxfilter(priv->ah, rfilt);

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

1269
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1270 1271 1272
	mutex_unlock(&priv->mutex);
}

1273 1274 1275
static int ath9k_htc_sta_add(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif,
			     struct ieee80211_sta *sta)
S
Sujith 已提交
1276 1277 1278 1279
{
	struct ath9k_htc_priv *priv = hw->priv;
	int ret;

1280
	mutex_lock(&priv->mutex);
S
Sujith 已提交
1281
	ath9k_htc_ps_wakeup(priv);
1282 1283 1284 1285 1286
	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);
1287

1288 1289 1290 1291 1292 1293 1294 1295
	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;
1296
	struct ath9k_htc_sta *ista;
1297
	int ret;
1298

1299 1300
	mutex_lock(&priv->mutex);
	ath9k_htc_ps_wakeup(priv);
1301 1302
	ista = (struct ath9k_htc_sta *) sta->drv_priv;
	htc_sta_drain(priv->htc, ista->index);
1303
	ret = ath9k_htc_remove_station(priv, vif, sta);
S
Sujith 已提交
1304
	ath9k_htc_ps_restore(priv);
1305
	mutex_unlock(&priv->mutex);
1306 1307

	return ret;
S
Sujith 已提交
1308 1309
}

1310 1311 1312 1313 1314 1315 1316 1317
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;

1318 1319 1320
	if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED))
		return;

1321 1322 1323
	mutex_lock(&priv->mutex);
	ath9k_htc_ps_wakeup(priv);

1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
	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);
1334 1335 1336 1337 1338

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

1339 1340
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif, u16 queue,
S
Sujith 已提交
1341 1342 1343 1344 1345 1346 1347
			     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;

1348
	if (queue >= IEEE80211_NUM_ACS)
S
Sujith 已提交
1349 1350 1351
		return 0;

	mutex_lock(&priv->mutex);
S
Sujith 已提交
1352
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1353 1354 1355 1356 1357 1358

	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;
1359
	qi.tqi_burstTime = params->txop * 32;
S
Sujith 已提交
1360 1361 1362

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

1363
	ath_dbg(common, CONFIG,
J
Joe Perches 已提交
1364 1365 1366
		"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 已提交
1367

1368
	ret = ath_htc_txq_update(priv, qnum, &qi);
S
Sujith 已提交
1369
	if (ret) {
1370
		ath_err(common, "TXQ Update failed\n");
S
Sujith 已提交
1371 1372
		goto out;
	}
S
Sujith 已提交
1373

S
Sujith 已提交
1374
	if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
1375
	    (qnum == priv->hwq_map[IEEE80211_AC_BE]))
S
Sujith 已提交
1376 1377
		    ath9k_htc_beaconq_config(priv);
out:
S
Sujith 已提交
1378
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
	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;

1394
	if (htc_modparam_nohwcrypt)
S
Sujith 已提交
1395 1396
		return -ENOSPC;

1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
	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 已提交
1412
	mutex_lock(&priv->mutex);
1413
	ath_dbg(common, CONFIG, "Set HW Key\n");
1414
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1415 1416 1417

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

1438
	ath9k_htc_ps_restore(priv);
S
Sujith 已提交
1439 1440 1441 1442 1443
	mutex_unlock(&priv->mutex);

	return ret;
}

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

S
Sujith 已提交
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484
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);
1485
	ath9k_htc_ps_wakeup(priv);
S
Sujith 已提交
1486 1487

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

1491 1492
		bss_conf->assoc ?
			priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--;
1493

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

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

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

1519 1520 1521
	if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) {
		/*
		 * Disable SWBA interrupt only if there are no
1522
		 * concurrent AP/mesh or IBSS interfaces.
1523
		 */
1524 1525
		if ((priv->num_ap_vif + priv->num_mbss_vif <= 1) ||
		     priv->num_ibss_vif) {
1526
			ath_dbg(common, CONFIG,
1527 1528
				"Beacon disabled for BSS: %pM\n",
				bss_conf->bssid);
1529
			clear_bit(OP_ENABLE_BEACON, &priv->op_flags);
1530 1531 1532 1533 1534 1535
			ath9k_htc_beacon_config(priv, vif);
		}
	}

	if (changed & BSS_CHANGED_BEACON_INT) {
		/*
1536
		 * Reset the HW TSF for the first AP or mesh interface.
1537
		 */
1538 1539 1540 1541 1542 1543 1544
		if (priv->nvifs == 1 &&
		    ((priv->ah->opmode == NL80211_IFTYPE_AP &&
		      vif->type == NL80211_IFTYPE_AP &&
		      priv->num_ap_vif == 1) ||
		    (priv->ah->opmode == NL80211_IFTYPE_MESH_POINT &&
		      vif->type == NL80211_IFTYPE_MESH_POINT &&
		      priv->num_mbss_vif == 1))) {
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;
}

1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798
struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv)
{
	struct base_eep_header *pBase = NULL;
	/*
	 * This can be done since all the 3 EEPROM families have the
	 * same base header upto a certain point, and we are interested in
	 * the data only upto that point.
	 */

	if (AR_SREV_9271(priv->ah))
		pBase = (struct base_eep_header *)
			&priv->ah->eeprom.map4k.baseEepHeader;
	else if (priv->ah->hw_version.usbdev == AR9280_USB)
		pBase = (struct base_eep_header *)
			&priv->ah->eeprom.def.baseEepHeader;
	else if (priv->ah->hw_version.usbdev == AR9287_USB)
		pBase = (struct base_eep_header *)
			&priv->ah->eeprom.map9287.baseEepHeader;
	return pBase;
}


static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
				 u32 *rx_ant)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct base_eep_header *pBase = ath9k_htc_get_eeprom_base(priv);
	if (pBase) {
		*tx_ant = pBase->txMask;
		*rx_ant = pBase->rxMask;
	} else {
		*tx_ant = 0;
		*rx_ant = 0;
	}
	return 0;
}

S
Sujith 已提交
1799 1800 1801 1802 1803 1804 1805 1806
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,
1807 1808
	.sta_add            = ath9k_htc_sta_add,
	.sta_remove         = ath9k_htc_sta_remove,
S
Sujith 已提交
1809
	.conf_tx            = ath9k_htc_conf_tx,
1810
	.sta_rc_update      = ath9k_htc_sta_rc_update,
S
Sujith 已提交
1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
	.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,
1822
	.set_bitrate_mask   = ath9k_htc_set_bitrate_mask,
1823
	.get_stats	    = ath9k_htc_get_stats,
1824
	.get_antenna	    = ath9k_htc_get_antenna,
1825 1826 1827 1828 1829 1830

#ifdef CONFIG_ATH9K_HTC_DEBUGFS
	.get_et_sset_count  = ath9k_htc_get_et_sset_count,
	.get_et_stats       = ath9k_htc_get_et_stats,
	.get_et_strings     = ath9k_htc_get_et_strings,
#endif
S
Sujith 已提交
1831
};