mac80211.c 18.5 KB
Newer Older
1 2 3 4 5 6 7 8 9
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019  Realtek Corporation
 */

#include "main.h"
#include "sec.h"
#include "tx.h"
#include "fw.h"
#include "mac.h"
10
#include "coex.h"
11 12
#include "ps.h"
#include "reg.h"
13
#include "bf.h"
14 15 16 17 18 19 20 21
#include "debug.h"

static void rtw_ops_tx(struct ieee80211_hw *hw,
		       struct ieee80211_tx_control *control,
		       struct sk_buff *skb)
{
	struct rtw_dev *rtwdev = hw->priv;

22 23 24 25
	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) {
		ieee80211_free_txskb(hw, skb);
		return;
	}
26

27 28
	rtw_tx(rtwdev, control, skb);
}
29

30 31 32 33 34
static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw,
				  struct ieee80211_txq *txq)
{
	struct rtw_dev *rtwdev = hw->priv;
	struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv;
35

36 37 38 39 40 41 42 43 44
	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
		return;

	spin_lock_bh(&rtwdev->txq_lock);
	if (list_empty(&rtwtxq->list))
		list_add_tail(&rtwtxq->list, &rtwdev->txqs);
	spin_unlock_bh(&rtwdev->txq_lock);

	tasklet_schedule(&rtwdev->tx_tasklet);
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
}

static int rtw_ops_start(struct ieee80211_hw *hw)
{
	struct rtw_dev *rtwdev = hw->priv;
	int ret;

	mutex_lock(&rtwdev->mutex);
	ret = rtw_core_start(rtwdev);
	mutex_unlock(&rtwdev->mutex);

	return ret;
}

static void rtw_ops_stop(struct ieee80211_hw *hw)
{
	struct rtw_dev *rtwdev = hw->priv;

	mutex_lock(&rtwdev->mutex);
	rtw_core_stop(rtwdev);
	mutex_unlock(&rtwdev->mutex);
}

static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
{
	struct rtw_dev *rtwdev = hw->priv;
	int ret = 0;

	mutex_lock(&rtwdev->mutex);

75 76
	rtw_leave_lps_deep(rtwdev);

77 78 79 80 81 82 83 84 85 86 87 88
	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
		if (hw->conf.flags & IEEE80211_CONF_IDLE) {
			rtw_enter_ips(rtwdev);
		} else {
			ret = rtw_leave_ips(rtwdev);
			if (ret) {
				rtw_err(rtwdev, "failed to leave idle state\n");
				goto out;
			}
		}
	}

89 90 91 92 93 94 95 96 97
	if (changed & IEEE80211_CONF_CHANGE_PS) {
		if (hw->conf.flags & IEEE80211_CONF_PS) {
			rtwdev->ps_enabled = true;
		} else {
			rtwdev->ps_enabled = false;
			rtw_leave_lps(rtwdev);
		}
	}

98 99 100 101 102 103 104 105 106 107 108 109 110 111
	if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
		rtw_set_channel(rtwdev);

out:
	mutex_unlock(&rtwdev->mutex);
	return ret;
}

static const struct rtw_vif_port rtw_vif_port[] = {
	[0] = {
		.mac_addr	= {.addr = 0x0610},
		.bssid		= {.addr = 0x0618},
		.net_type	= {.addr = 0x0100, .mask = 0x30000},
		.aid		= {.addr = 0x06a8, .mask = 0x7ff},
112
		.bcn_ctrl	= {.addr = 0x0550, .mask = 0xff},
113 114 115 116 117 118
	},
	[1] = {
		.mac_addr	= {.addr = 0x0700},
		.bssid		= {.addr = 0x0708},
		.net_type	= {.addr = 0x0100, .mask = 0xc0000},
		.aid		= {.addr = 0x0710, .mask = 0x7ff},
119
		.bcn_ctrl	= {.addr = 0x0551, .mask = 0xff},
120 121 122 123 124 125
	},
	[2] = {
		.mac_addr	= {.addr = 0x1620},
		.bssid		= {.addr = 0x1628},
		.net_type	= {.addr = 0x1100, .mask = 0x3},
		.aid		= {.addr = 0x1600, .mask = 0x7ff},
126
		.bcn_ctrl	= {.addr = 0x0578, .mask = 0xff},
127 128 129 130 131 132
	},
	[3] = {
		.mac_addr	= {.addr = 0x1630},
		.bssid		= {.addr = 0x1638},
		.net_type	= {.addr = 0x1100, .mask = 0xc},
		.aid		= {.addr = 0x1604, .mask = 0x7ff},
133
		.bcn_ctrl	= {.addr = 0x0579, .mask = 0xff},
134 135 136 137 138 139
	},
	[4] = {
		.mac_addr	= {.addr = 0x1640},
		.bssid		= {.addr = 0x1648},
		.net_type	= {.addr = 0x1100, .mask = 0x30},
		.aid		= {.addr = 0x1608, .mask = 0x7ff},
140
		.bcn_ctrl	= {.addr = 0x057a, .mask = 0xff},
141 142 143 144 145 146 147 148 149 150 151
	},
};

static int rtw_ops_add_interface(struct ieee80211_hw *hw,
				 struct ieee80211_vif *vif)
{
	struct rtw_dev *rtwdev = hw->priv;
	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
	enum rtw_net_type net_type;
	u32 config = 0;
	u8 port = 0;
152
	u8 bcn_ctrl = 0;
153 154 155 156 157 158 159 160

	rtwvif->port = port;
	rtwvif->vif = vif;
	rtwvif->stats.tx_unicast = 0;
	rtwvif->stats.rx_unicast = 0;
	rtwvif->stats.tx_cnt = 0;
	rtwvif->stats.rx_cnt = 0;
	rtwvif->in_lps = false;
161
	memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee));
162
	rtwvif->conf = &rtw_vif_port[port];
163
	rtw_txq_init(rtwdev, vif->txq);
164 165 166

	mutex_lock(&rtwdev->mutex);

167 168
	rtw_leave_lps_deep(rtwdev);

169 170 171 172
	switch (vif->type) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_MESH_POINT:
		net_type = RTW_NET_AP_MODE;
173
		bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
174 175 176
		break;
	case NL80211_IFTYPE_ADHOC:
		net_type = RTW_NET_AD_HOC;
177
		bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
178 179 180 181
		break;
	case NL80211_IFTYPE_STATION:
	default:
		net_type = RTW_NET_NO_LINK;
182
		bcn_ctrl = BIT_EN_BCN_FUNCTION;
183 184 185 186 187 188 189
		break;
	}

	ether_addr_copy(rtwvif->mac_addr, vif->addr);
	config |= PORT_SET_MAC_ADDR;
	rtwvif->net_type = net_type;
	config |= PORT_SET_NET_TYPE;
190 191
	rtwvif->bcn_ctrl = bcn_ctrl;
	config |= PORT_SET_BCN_CTRL;
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
	rtw_vif_port_config(rtwdev, rtwvif, config);

	mutex_unlock(&rtwdev->mutex);

	rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
	return 0;
}

static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
				     struct ieee80211_vif *vif)
{
	struct rtw_dev *rtwdev = hw->priv;
	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
	u32 config = 0;

	rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);

	mutex_lock(&rtwdev->mutex);

211 212
	rtw_leave_lps_deep(rtwdev);

213 214
	rtw_txq_cleanup(rtwdev, vif->txq);

215 216 217 218
	eth_zero_addr(rtwvif->mac_addr);
	config |= PORT_SET_MAC_ADDR;
	rtwvif->net_type = RTW_NET_NO_LINK;
	config |= PORT_SET_NET_TYPE;
219 220
	rtwvif->bcn_ctrl = 0;
	config |= PORT_SET_BCN_CTRL;
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
	rtw_vif_port_config(rtwdev, rtwvif, config);

	mutex_unlock(&rtwdev->mutex);
}

static void rtw_ops_configure_filter(struct ieee80211_hw *hw,
				     unsigned int changed_flags,
				     unsigned int *new_flags,
				     u64 multicast)
{
	struct rtw_dev *rtwdev = hw->priv;

	*new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
		      FIF_BCN_PRBRESP_PROMISC;

	mutex_lock(&rtwdev->mutex);

238 239
	rtw_leave_lps_deep(rtwdev);

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
	if (changed_flags & FIF_ALLMULTI) {
		if (*new_flags & FIF_ALLMULTI)
			rtwdev->hal.rcr |= BIT_AM | BIT_AB;
		else
			rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB);
	}
	if (changed_flags & FIF_FCSFAIL) {
		if (*new_flags & FIF_FCSFAIL)
			rtwdev->hal.rcr |= BIT_ACRC32;
		else
			rtwdev->hal.rcr &= ~(BIT_ACRC32);
	}
	if (changed_flags & FIF_OTHER_BSS) {
		if (*new_flags & FIF_OTHER_BSS)
			rtwdev->hal.rcr |= BIT_AAP;
		else
			rtwdev->hal.rcr &= ~(BIT_AAP);
	}
	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
		if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
			rtwdev->hal.rcr &= ~(BIT_CBSSID_BCN | BIT_CBSSID_DATA);
		else
			rtwdev->hal.rcr |= BIT_CBSSID_BCN;
	}

	rtw_dbg(rtwdev, RTW_DBG_RX,
		"config rx filter, changed=0x%08x, new=0x%08x, rcr=0x%08x\n",
		changed_flags, *new_flags, rtwdev->hal.rcr);

	rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);

	mutex_unlock(&rtwdev->mutex);
}

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
/* Only have one group of EDCA parameters now */
static const u32 ac_to_edca_param[IEEE80211_NUM_ACS] = {
	[IEEE80211_AC_VO] = REG_EDCA_VO_PARAM,
	[IEEE80211_AC_VI] = REG_EDCA_VI_PARAM,
	[IEEE80211_AC_BE] = REG_EDCA_BE_PARAM,
	[IEEE80211_AC_BK] = REG_EDCA_BK_PARAM,
};

static u8 rtw_aifsn_to_aifs(struct rtw_dev *rtwdev,
			    struct rtw_vif *rtwvif, u8 aifsn)
{
	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
	u8 slot_time;
	u8 sifs;

	slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
	sifs = rtwdev->hal.current_band_type == RTW_BAND_5G ? 16 : 10;

	return aifsn * slot_time + sifs;
}

static void __rtw_conf_tx(struct rtw_dev *rtwdev,
			  struct rtw_vif *rtwvif, u16 ac)
{
	struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
	u32 edca_param = ac_to_edca_param[ac];
	u8 ecw_max, ecw_min;
	u8 aifs;

	/* 2^ecw - 1 = cw; ecw = log2(cw + 1) */
	ecw_max = ilog2(params->cw_max + 1);
	ecw_min = ilog2(params->cw_min + 1);
	aifs = rtw_aifsn_to_aifs(rtwdev, rtwvif, params->aifs);
	rtw_write32_mask(rtwdev, edca_param, BIT_MASK_TXOP_LMT, params->txop);
	rtw_write32_mask(rtwdev, edca_param, BIT_MASK_CWMAX, ecw_max);
	rtw_write32_mask(rtwdev, edca_param, BIT_MASK_CWMIN, ecw_min);
	rtw_write32_mask(rtwdev, edca_param, BIT_MASK_AIFS, aifs);
}

static void rtw_conf_tx(struct rtw_dev *rtwdev,
			struct rtw_vif *rtwvif)
{
	u16 ac;

	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
		__rtw_conf_tx(rtwdev, rtwvif, ac);
}

322 323 324 325 326 327 328 329 330 331 332
static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
				     struct ieee80211_vif *vif,
				     struct ieee80211_bss_conf *conf,
				     u32 changed)
{
	struct rtw_dev *rtwdev = hw->priv;
	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
	u32 config = 0;

	mutex_lock(&rtwdev->mutex);

333 334
	rtw_leave_lps_deep(rtwdev);

335 336 337 338 339
	if (changed & BSS_CHANGED_ASSOC) {
		struct rtw_chip_info *chip = rtwdev->chip;
		enum rtw_net_type net_type;

		if (conf->assoc) {
340
			rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH);
341
			net_type = RTW_NET_MGD_LINKED;
342
			chip->ops->phy_calibration(rtwdev);
343 344 345 346 347

			rtwvif->aid = conf->aid;
			rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true);
			rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true);
			rtw_add_rsvd_page(rtwdev, RSVD_NULL, true);
348 349
			rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_DPK, true);
			rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_INFO, true);
350 351
			rtw_fw_download_rsvd_page(rtwdev, vif);
			rtw_send_rsvd_page_h2c(rtwdev);
352
			rtw_coex_media_status_notify(rtwdev, conf->assoc);
353 354
			if (rtw_bf_support)
				rtw_bf_assoc(rtwdev, vif, conf);
355
		} else {
356
			rtw_leave_lps(rtwdev);
357 358 359
			net_type = RTW_NET_NO_LINK;
			rtwvif->aid = 0;
			rtw_reset_rsvd_page(rtwdev);
360
			rtw_bf_disassoc(rtwdev, vif, conf);
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
		}

		rtwvif->net_type = net_type;
		config |= PORT_SET_NET_TYPE;
		config |= PORT_SET_AID;
	}

	if (changed & BSS_CHANGED_BSSID) {
		ether_addr_copy(rtwvif->bssid, conf->bssid);
		config |= PORT_SET_BSSID;
	}

	if (changed & BSS_CHANGED_BEACON)
		rtw_fw_download_rsvd_page(rtwdev, vif);

376 377 378 379 380 381
	if (changed & BSS_CHANGED_MU_GROUPS) {
		struct rtw_chip_info *chip = rtwdev->chip;

		chip->ops->set_gid_table(rtwdev, vif, conf);
	}

382 383 384
	if (changed & BSS_CHANGED_ERP_SLOT)
		rtw_conf_tx(rtwdev, rtwvif);

385 386 387 388 389
	rtw_vif_port_config(rtwdev, rtwvif, config);

	mutex_unlock(&rtwdev->mutex);
}

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
static int rtw_ops_conf_tx(struct ieee80211_hw *hw,
			   struct ieee80211_vif *vif, u16 ac,
			   const struct ieee80211_tx_queue_params *params)
{
	struct rtw_dev *rtwdev = hw->priv;
	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;

	mutex_lock(&rtwdev->mutex);

	rtw_leave_lps_deep(rtwdev);

	rtwvif->tx_params[ac] = *params;
	__rtw_conf_tx(rtwdev, rtwvif, ac);

	mutex_unlock(&rtwdev->mutex);

	return 0;
}

409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
{
	unsigned long mac_id;

	mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
	if (mac_id < RTW_MAX_MAC_ID_NUM)
		set_bit(mac_id, rtwdev->mac_id_map);

	return mac_id;
}

static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id)
{
	clear_bit(mac_id, rtwdev->mac_id_map);
}

static int rtw_ops_sta_add(struct ieee80211_hw *hw,
			   struct ieee80211_vif *vif,
			   struct ieee80211_sta *sta)
{
	struct rtw_dev *rtwdev = hw->priv;
	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
431
	int i;
432 433 434 435 436 437 438 439 440 441 442 443 444 445
	int ret = 0;

	mutex_lock(&rtwdev->mutex);

	si->mac_id = rtw_acquire_macid(rtwdev);
	if (si->mac_id >= RTW_MAX_MAC_ID_NUM) {
		ret = -ENOSPC;
		goto out;
	}

	si->sta = sta;
	si->vif = vif;
	si->init_ra_lv = 1;
	ewma_rssi_init(&si->avg_rssi);
446 447
	for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
		rtw_txq_init(rtwdev, sta->txq[i]);
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467

	rtw_update_sta_info(rtwdev, si);
	rtw_fw_media_status_report(rtwdev, si->mac_id, true);

	rtwdev->sta_cnt++;

	rtw_info(rtwdev, "sta %pM joined with macid %d\n",
		 sta->addr, si->mac_id);

out:
	mutex_unlock(&rtwdev->mutex);
	return ret;
}

static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
			      struct ieee80211_vif *vif,
			      struct ieee80211_sta *sta)
{
	struct rtw_dev *rtwdev = hw->priv;
	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
468
	int i;
469 470 471 472 473 474

	mutex_lock(&rtwdev->mutex);

	rtw_release_macid(rtwdev, si->mac_id);
	rtw_fw_media_status_report(rtwdev, si->mac_id, false);

475 476 477
	for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
		rtw_txq_cleanup(rtwdev, sta->txq[i]);

T
Tzu-En Huang 已提交
478 479
	kfree(si->mask);

480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
	rtwdev->sta_cnt--;

	rtw_info(rtwdev, "sta %pM with macid %d left\n",
		 sta->addr, si->mac_id);

	mutex_unlock(&rtwdev->mutex);
	return 0;
}

static int rtw_ops_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 rtw_dev *rtwdev = hw->priv;
	struct rtw_sec_desc *sec = &rtwdev->sec;
	u8 hw_key_type;
	u8 hw_key_idx;
	int ret = 0;

	switch (key->cipher) {
	case WLAN_CIPHER_SUITE_WEP40:
		hw_key_type = RTW_CAM_WEP40;
		break;
	case WLAN_CIPHER_SUITE_WEP104:
		hw_key_type = RTW_CAM_WEP104;
		break;
	case WLAN_CIPHER_SUITE_TKIP:
		hw_key_type = RTW_CAM_TKIP;
		key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
		break;
	case WLAN_CIPHER_SUITE_CCMP:
		hw_key_type = RTW_CAM_AES;
		key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
		/* suppress error messages */
		return -EOPNOTSUPP;
	default:
		return -ENOTSUPP;
	}

	mutex_lock(&rtwdev->mutex);

526 527
	rtw_leave_lps_deep(rtwdev);

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
		hw_key_idx = rtw_sec_get_free_cam(sec);
	} else {
		/* multiple interfaces? */
		hw_key_idx = key->keyidx;
	}

	if (hw_key_idx > sec->total_cam_num) {
		ret = -ENOSPC;
		goto out;
	}

	switch (cmd) {
	case SET_KEY:
		/* need sw generated IV */
		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
		key->hw_key_idx = hw_key_idx;
		rtw_sec_write_cam(rtwdev, sec, sta, key,
				  hw_key_type, hw_key_idx);
		break;
	case DISABLE_KEY:
549
		rtw_mac_flush_all_queues(rtwdev, false);
550 551 552 553
		rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx);
		break;
	}

554 555 556 557
	/* download new cam settings for PG to backup */
	if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
		rtw_fw_download_rsvd_page(rtwdev, vif);

558 559 560 561 562 563 564 565 566 567 568 569
out:
	mutex_unlock(&rtwdev->mutex);

	return ret;
}

static int rtw_ops_ampdu_action(struct ieee80211_hw *hw,
				struct ieee80211_vif *vif,
				struct ieee80211_ampdu_params *params)
{
	struct ieee80211_sta *sta = params->sta;
	u16 tid = params->tid;
570 571
	struct ieee80211_txq *txq = sta->txq[tid];
	struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv;
572 573 574

	switch (params->action) {
	case IEEE80211_AMPDU_TX_START:
575
		return IEEE80211_AMPDU_TX_START_IMMEDIATE;
576 577 578
	case IEEE80211_AMPDU_TX_STOP_CONT:
	case IEEE80211_AMPDU_TX_STOP_FLUSH:
	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
579
		clear_bit(RTW_TXQ_AMPDU, &rtwtxq->flags);
580 581 582
		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
		break;
	case IEEE80211_AMPDU_TX_OPERATIONAL:
583 584
		set_bit(RTW_TXQ_AMPDU, &rtwtxq->flags);
		break;
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
	case IEEE80211_AMPDU_RX_START:
	case IEEE80211_AMPDU_RX_STOP:
		break;
	default:
		WARN_ON(1);
		return -ENOTSUPP;
	}

	return 0;
}

static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
				  struct ieee80211_vif *vif,
				  const u8 *mac_addr)
{
	struct rtw_dev *rtwdev = hw->priv;
	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
602
	u32 config = 0;
603

604 605
	mutex_lock(&rtwdev->mutex);

606 607
	rtw_leave_lps(rtwdev);

608 609 610 611
	ether_addr_copy(rtwvif->mac_addr, mac_addr);
	config |= PORT_SET_MAC_ADDR;
	rtw_vif_port_config(rtwdev, rtwvif, config);

612 613
	rtw_coex_scan_notify(rtwdev, COEX_SCAN_START);

614 615
	set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
	set_bit(RTW_FLAG_SCANNING, rtwdev->flags);
616 617

	mutex_unlock(&rtwdev->mutex);
618 619 620 621 622 623
}

static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
				     struct ieee80211_vif *vif)
{
	struct rtw_dev *rtwdev = hw->priv;
624 625 626 627
	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
	u32 config = 0;

	mutex_lock(&rtwdev->mutex);
628

629 630
	clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
	clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
631 632 633 634 635

	ether_addr_copy(rtwvif->mac_addr, vif->addr);
	config |= PORT_SET_MAC_ADDR;
	rtw_vif_port_config(rtwdev, rtwvif, config);

636 637 638 639 640 641 642 643 644 645 646 647
	rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH);

	mutex_unlock(&rtwdev->mutex);
}

static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif,
				   u16 duration)
{
	struct rtw_dev *rtwdev = hw->priv;

	mutex_lock(&rtwdev->mutex);
648
	rtw_leave_lps_deep(rtwdev);
649
	rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START);
650
	mutex_unlock(&rtwdev->mutex);
651 652
}

653 654 655 656 657 658 659 660 661 662 663
static int rtw_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
	struct rtw_dev *rtwdev = hw->priv;

	mutex_lock(&rtwdev->mutex);
	rtwdev->rts_threshold = value;
	mutex_unlock(&rtwdev->mutex);

	return 0;
}

664 665 666 667 668 669 670 671 672 673 674
static void rtw_ops_sta_statistics(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif,
				   struct ieee80211_sta *sta,
				   struct station_info *sinfo)
{
	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;

	sinfo->txrate = si->ra_report.txrate;
	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}

Y
Yan-Hsuan Chuang 已提交
675 676 677 678 679 680 681 682 683 684 685 686 687
static void rtw_ops_flush(struct ieee80211_hw *hw,
			  struct ieee80211_vif *vif,
			  u32 queues, bool drop)
{
	struct rtw_dev *rtwdev = hw->priv;

	mutex_lock(&rtwdev->mutex);
	rtw_leave_lps_deep(rtwdev);

	rtw_mac_flush_queues(rtwdev, queues, drop);
	mutex_unlock(&rtwdev->mutex);
}

T
Tzu-En Huang 已提交
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
struct rtw_iter_bitrate_mask_data {
	struct rtw_dev *rtwdev;
	struct ieee80211_vif *vif;
	const struct cfg80211_bitrate_mask *mask;
};

static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
{
	struct rtw_iter_bitrate_mask_data *br_data = data;
	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;

	if (si->vif != br_data->vif)
		return;

	/* free previous mask setting */
	kfree(si->mask);
	si->mask = kmemdup(br_data->mask, sizeof(struct cfg80211_bitrate_mask),
			   GFP_ATOMIC);
	if (!si->mask) {
		si->use_cfg_mask = false;
		return;
	}

	si->use_cfg_mask = true;
	rtw_update_sta_info(br_data->rtwdev, si);
}

static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev,
				    struct ieee80211_vif *vif,
				    const struct cfg80211_bitrate_mask *mask)
{
	struct rtw_iter_bitrate_mask_data br_data;

	br_data.rtwdev = rtwdev;
	br_data.vif = vif;
	br_data.mask = mask;
	rtw_iterate_stas_atomic(rtwdev, rtw_ra_mask_info_update_iter, &br_data);
}

static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw,
				    struct ieee80211_vif *vif,
				    const struct cfg80211_bitrate_mask *mask)
{
	struct rtw_dev *rtwdev = hw->priv;

	rtw_ra_mask_info_update(rtwdev, vif, mask);

	return 0;
}

738 739
const struct ieee80211_ops rtw_ops = {
	.tx			= rtw_ops_tx,
740
	.wake_tx_queue		= rtw_ops_wake_tx_queue,
741 742 743 744 745 746 747
	.start			= rtw_ops_start,
	.stop			= rtw_ops_stop,
	.config			= rtw_ops_config,
	.add_interface		= rtw_ops_add_interface,
	.remove_interface	= rtw_ops_remove_interface,
	.configure_filter	= rtw_ops_configure_filter,
	.bss_info_changed	= rtw_ops_bss_info_changed,
748
	.conf_tx		= rtw_ops_conf_tx,
749 750 751 752 753 754
	.sta_add		= rtw_ops_sta_add,
	.sta_remove		= rtw_ops_sta_remove,
	.set_key		= rtw_ops_set_key,
	.ampdu_action		= rtw_ops_ampdu_action,
	.sw_scan_start		= rtw_ops_sw_scan_start,
	.sw_scan_complete	= rtw_ops_sw_scan_complete,
755
	.mgd_prepare_tx		= rtw_ops_mgd_prepare_tx,
756
	.set_rts_threshold	= rtw_ops_set_rts_threshold,
757
	.sta_statistics		= rtw_ops_sta_statistics,
Y
Yan-Hsuan Chuang 已提交
758
	.flush			= rtw_ops_flush,
T
Tzu-En Huang 已提交
759
	.set_bitrate_mask	= rtw_ops_set_bitrate_mask,
760 761
};
EXPORT_SYMBOL(rtw_ops);