mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-30 05:36:10 +00:00
rtw88: update Realtek's rtw88 driver.
This version is based on
https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-testing.git
2a220a15be657a24868368892e3e2caba2115283 (tag: wt-2023-08-06)
and was committed to FreeBSD main as
90aac0d83b
.
This commit is contained in:
parent
2ed35f15d8
commit
1f3bff0d30
78
Makefile
Normal file
78
Makefile
Normal file
|
@ -0,0 +1,78 @@
|
|||
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
|
||||
obj-$(CONFIG_RTW88_CORE) += rtw88_core.o
|
||||
rtw88_core-y += main.o \
|
||||
mac80211.o \
|
||||
util.o \
|
||||
debug.o \
|
||||
tx.o \
|
||||
rx.o \
|
||||
mac.o \
|
||||
phy.o \
|
||||
coex.o \
|
||||
efuse.o \
|
||||
fw.o \
|
||||
ps.o \
|
||||
sec.o \
|
||||
bf.o \
|
||||
sar.o \
|
||||
regd.o
|
||||
|
||||
rtw88_core-$(CONFIG_PM) += wow.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822B) += rtw88_8822b.o
|
||||
rtw88_8822b-objs := rtw8822b.o rtw8822b_table.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822BE) += rtw88_8822be.o
|
||||
rtw88_8822be-objs := rtw8822be.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822BS) += rtw88_8822bs.o
|
||||
rtw88_8822bs-objs := rtw8822bs.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822BU) += rtw88_8822bu.o
|
||||
rtw88_8822bu-objs := rtw8822bu.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822C) += rtw88_8822c.o
|
||||
rtw88_8822c-objs := rtw8822c.o rtw8822c_table.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822CE) += rtw88_8822ce.o
|
||||
rtw88_8822ce-objs := rtw8822ce.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822CS) += rtw88_8822cs.o
|
||||
rtw88_8822cs-objs := rtw8822cs.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822CU) += rtw88_8822cu.o
|
||||
rtw88_8822cu-objs := rtw8822cu.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8723D) += rtw88_8723d.o
|
||||
rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o
|
||||
rtw88_8723de-objs := rtw8723de.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8723DS) += rtw88_8723ds.o
|
||||
rtw88_8723ds-objs := rtw8723ds.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o
|
||||
rtw88_8723du-objs := rtw8723du.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8821C) += rtw88_8821c.o
|
||||
rtw88_8821c-objs := rtw8821c.o rtw8821c_table.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o
|
||||
rtw88_8821ce-objs := rtw8821ce.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8821CS) += rtw88_8821cs.o
|
||||
rtw88_8821cs-objs := rtw8821cs.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8821CU) += rtw88_8821cu.o
|
||||
rtw88_8821cu-objs := rtw8821cu.o
|
||||
|
||||
obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
|
||||
rtw88_pci-objs := pci.o
|
||||
|
||||
obj-$(CONFIG_RTW88_SDIO) += rtw88_sdio.o
|
||||
rtw88_sdio-objs := sdio.o
|
||||
|
||||
obj-$(CONFIG_RTW88_USB) += rtw88_usb.o
|
||||
rtw88_usb-objs := usb.o
|
19
bf.c
19
bf.c
|
@ -30,11 +30,11 @@ void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
struct rtw_bfee *bfee = &rtwvif->bfee;
|
||||
struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_sta_vht_cap *vht_cap;
|
||||
struct ieee80211_sta_vht_cap *ic_vht_cap;
|
||||
|
@ -49,25 +49,29 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
|
||||
sta = ieee80211_find_sta(vif, bssid);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
|
||||
rtw_warn(rtwdev, "failed to find station entry for bss %pM\n",
|
||||
bssid);
|
||||
goto out_unlock;
|
||||
return;
|
||||
}
|
||||
|
||||
ic_vht_cap = &hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap;
|
||||
vht_cap = &sta->vht_cap;
|
||||
vht_cap = &sta->deflink.vht_cap;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
|
||||
(vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
|
||||
if (bfinfo->bfer_mu_cnt >= chip->bfer_mu_max_num) {
|
||||
rtw_dbg(rtwdev, RTW_DBG_BF, "mu bfer number over limit\n");
|
||||
goto out_unlock;
|
||||
return;
|
||||
}
|
||||
|
||||
ether_addr_copy(bfee->mac_addr, bssid);
|
||||
bfee->role = RTW_BFEE_MU;
|
||||
bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
|
||||
bfee->aid = bss_conf->aid;
|
||||
bfee->aid = vif->cfg.aid;
|
||||
bfinfo->bfer_mu_cnt++;
|
||||
|
||||
rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true);
|
||||
|
@ -75,7 +79,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
(vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
|
||||
if (bfinfo->bfer_su_cnt >= chip->bfer_su_max_num) {
|
||||
rtw_dbg(rtwdev, RTW_DBG_BF, "su bfer number over limit\n");
|
||||
goto out_unlock;
|
||||
return;
|
||||
}
|
||||
|
||||
sound_dim = vht_cap->cap &
|
||||
|
@ -98,9 +102,6 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
|
||||
rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev,
|
||||
|
|
385
coex.c
385
coex.c
|
@ -13,7 +13,7 @@
|
|||
static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
|
||||
u8 rssi, u8 rssi_thresh)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 tol = chip->rssi_tolerance;
|
||||
u8 next_state;
|
||||
|
||||
|
@ -36,7 +36,7 @@ static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
|
|||
static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
|
||||
bool tx_limit_en, bool ampdu_limit_en)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
u8 num_of_active_port = 1;
|
||||
|
@ -211,6 +211,10 @@ static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
|
|||
|
||||
bool is_cck_lock_rate = false;
|
||||
|
||||
if (coex_stat->wl_coex_mode != COEX_WLINK_2G1PORT &&
|
||||
coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)
|
||||
return;
|
||||
|
||||
if (coex_dm->bt_status == COEX_BTSTATUS_INQ_PAGE ||
|
||||
coex_stat->bt_setup_link) {
|
||||
coex_stat->wl_cck_lock = false;
|
||||
|
@ -361,7 +365,7 @@ static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
|
|||
|
||||
void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
u16 val = 0x2;
|
||||
|
@ -396,7 +400,7 @@ EXPORT_SYMBOL(rtw_coex_write_scbd);
|
|||
|
||||
static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (!chip->scbd_support)
|
||||
return 0;
|
||||
|
@ -406,7 +410,7 @@ static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_rfe *coex_rfe = &coex->rfe;
|
||||
|
@ -460,9 +464,32 @@ static void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode)
|
|||
rtw_coex_set_gnt_fix(rtwdev);
|
||||
}
|
||||
|
||||
static void rtw_coex_monitor_bt_ctr(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
u32 tmp;
|
||||
|
||||
tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS);
|
||||
coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, tmp);
|
||||
coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, tmp);
|
||||
|
||||
tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1);
|
||||
coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, tmp);
|
||||
coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, tmp);
|
||||
|
||||
rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL,
|
||||
BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN);
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX,
|
||||
"[BTCoex], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n",
|
||||
coex_stat->hi_pri_rx, coex_stat->hi_pri_tx,
|
||||
coex_stat->lo_pri_rx, coex_stat->lo_pri_tx);
|
||||
}
|
||||
|
||||
static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
|
@ -497,10 +524,10 @@ static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_traffic_stats *stats = &rtwdev->stats;
|
||||
bool is_5G = false;
|
||||
bool wl_busy = false;
|
||||
|
@ -606,7 +633,7 @@ static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
|
|||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct sk_buff *skb_resp = NULL;
|
||||
|
||||
mutex_lock(&coex->mutex);
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
rtw_fw_query_bt_mp_info(rtwdev, req);
|
||||
|
||||
|
@ -623,7 +650,6 @@ static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
|
|||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&coex->mutex);
|
||||
return skb_resp;
|
||||
}
|
||||
|
||||
|
@ -679,10 +705,10 @@ static const char *rtw_coex_get_bt_status_string(u8 bt_status)
|
|||
|
||||
static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 i;
|
||||
u8 rssi_state;
|
||||
u8 rssi_step;
|
||||
|
@ -779,8 +805,10 @@ static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
|
||||
struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
|
||||
u8 link = 0;
|
||||
u8 center_chan = 0;
|
||||
u8 bw;
|
||||
|
@ -791,7 +819,9 @@ static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
|
|||
if (type != COEX_MEDIA_DISCONNECT)
|
||||
center_chan = rtwdev->hal.current_channel;
|
||||
|
||||
if (center_chan == 0) {
|
||||
if (center_chan == 0 ||
|
||||
(efuse->share_ant && center_chan <= 14 &&
|
||||
coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)) {
|
||||
link = 0;
|
||||
center_chan = 0;
|
||||
bw = 0;
|
||||
|
@ -902,7 +932,7 @@ EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
|
|||
|
||||
static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_hw_reg *btg_reg = chip->btg_reg;
|
||||
|
||||
if (wifi_control) {
|
||||
|
@ -930,10 +960,27 @@ static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
|
|||
rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);
|
||||
}
|
||||
|
||||
static void rtw_coex_mimo_ps(struct rtw_dev *rtwdev, bool force, bool state)
|
||||
{
|
||||
struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
|
||||
|
||||
if (!force && state == coex_stat->wl_mimo_ps)
|
||||
return;
|
||||
|
||||
coex_stat->wl_mimo_ps = state;
|
||||
|
||||
rtw_set_txrx_1ss(rtwdev, state);
|
||||
|
||||
rtw_coex_update_wl_ch_info(rtwdev, (u8)coex_stat->wl_connected);
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX,
|
||||
"[BTCoex], %s(): state = %d\n", __func__, state);
|
||||
}
|
||||
|
||||
static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force,
|
||||
u8 table_case)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
u8 h2c_para[6] = {0};
|
||||
u32 table_wl = 0x5a5a5a5a;
|
||||
|
@ -1017,9 +1064,9 @@ static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0,
|
|||
|
||||
static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
|
||||
|
@ -1087,9 +1134,9 @@ static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
|
|||
static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
|
||||
u8 byte3, u8 byte4, u8 byte5)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
u8 ps_type = COEX_PS_WIFI_NATIVE;
|
||||
bool ap_enable = false;
|
||||
|
@ -1106,7 +1153,8 @@ static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
|
|||
|
||||
ps_type = COEX_PS_WIFI_NATIVE;
|
||||
rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
|
||||
} else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
|
||||
} else if ((byte1 & BIT(4) && !(byte1 & BIT(5))) ||
|
||||
coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX,
|
||||
"[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__,
|
||||
byte1);
|
||||
|
@ -1144,10 +1192,10 @@ static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
|
|||
|
||||
static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
u8 n, type;
|
||||
bool turn_on;
|
||||
|
@ -1477,8 +1525,8 @@ static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -1500,11 +1548,11 @@ static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 level = 0;
|
||||
bool bt_afh_loss = true;
|
||||
|
||||
|
@ -1545,8 +1593,8 @@ static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -1570,8 +1618,8 @@ static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -1595,10 +1643,10 @@ static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
u32 slot_type = 0;
|
||||
|
||||
|
@ -1635,11 +1683,11 @@ static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex_rfe *coex_rfe = &coex->rfe;
|
||||
u8 table_case = 0xff, tdma_case = 0xff;
|
||||
|
||||
|
@ -1704,10 +1752,10 @@ static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
bool wl_hi_pri = false;
|
||||
u8 table_case, tdma_case;
|
||||
u32 slot_type = 0;
|
||||
|
@ -1802,12 +1850,60 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
|
|||
rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
|
||||
}
|
||||
|
||||
static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
|
||||
static void rtw_coex_action_bt_game_hid(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
|
||||
|
||||
if (efuse->share_ant) {
|
||||
coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
|
||||
if (coex_stat->bt_whck_test)
|
||||
table_case = 2;
|
||||
else if (coex_stat->wl_linkscan_proc || coex_stat->bt_hid_exist)
|
||||
table_case = 33;
|
||||
else if (coex_stat->bt_setup_link || coex_stat->bt_inq_page)
|
||||
table_case = 0;
|
||||
else if (coex_stat->bt_a2dp_exist)
|
||||
table_case = 34;
|
||||
else
|
||||
table_case = 33;
|
||||
|
||||
tdma_case = 0;
|
||||
} else {
|
||||
if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
|
||||
tdma_case = 112;
|
||||
else
|
||||
tdma_case = 113;
|
||||
|
||||
table_case = 121;
|
||||
}
|
||||
|
||||
if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
|
||||
if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
|
||||
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]);
|
||||
else
|
||||
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]);
|
||||
} else {
|
||||
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
|
||||
}
|
||||
|
||||
rtw_coex_table(rtwdev, false, table_case);
|
||||
rtw_coex_tdma(rtwdev, false, tdma_case);
|
||||
}
|
||||
|
||||
static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -1816,13 +1912,8 @@ static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
|
|||
|
||||
if (efuse->share_ant) {
|
||||
/* Shared-Ant */
|
||||
if (coex_stat->bt_multi_link) {
|
||||
table_case = 10;
|
||||
tdma_case = 17;
|
||||
} else {
|
||||
table_case = 10;
|
||||
tdma_case = 5;
|
||||
}
|
||||
table_case = 10;
|
||||
tdma_case = 5;
|
||||
} else {
|
||||
/* Non-Shared-Ant */
|
||||
if (coex_stat->bt_multi_link) {
|
||||
|
@ -1840,10 +1931,10 @@ static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
u32 slot_type = 0;
|
||||
bool bt_multi_link_remain = false, is_toggle_table = false;
|
||||
|
@ -1923,11 +2014,11 @@ static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
u32 slot_type = 0;
|
||||
|
||||
|
@ -1965,10 +2056,10 @@ static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
bool ap_enable = false;
|
||||
|
||||
|
@ -2004,10 +2095,10 @@ static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -2041,11 +2132,11 @@ static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case, interval = 0;
|
||||
u32 slot_type = 0;
|
||||
bool is_toggle_table = false;
|
||||
|
@ -2098,10 +2189,10 @@ static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
bool wl_cpt_test = false, bt_cpt_test = false;
|
||||
|
||||
|
@ -2155,10 +2246,10 @@ static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -2190,10 +2281,10 @@ static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -2224,8 +2315,10 @@ static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -2235,6 +2328,9 @@ static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
|
|||
|
||||
rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
|
||||
|
||||
if (coex_stat->bt_game_hid_exist && coex_stat->wl_linkscan_proc)
|
||||
coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
|
||||
|
||||
if (efuse->share_ant) {
|
||||
/* Shared-Ant */
|
||||
table_case = 0;
|
||||
|
@ -2251,8 +2347,8 @@ static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -2275,9 +2371,10 @@ static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
if (coex->under_5g)
|
||||
|
@ -2286,7 +2383,6 @@ static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
|
|||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
||||
rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
|
||||
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
|
||||
|
||||
if (efuse->share_ant) {
|
||||
/* Shared-Ant */
|
||||
|
@ -2298,16 +2394,26 @@ static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
|
|||
tdma_case = 100;
|
||||
}
|
||||
|
||||
if (coex_stat->bt_game_hid_exist) {
|
||||
coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
|
||||
if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
|
||||
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]);
|
||||
else
|
||||
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]);
|
||||
} else {
|
||||
rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
|
||||
}
|
||||
|
||||
rtw_coex_table(rtwdev, false, table_case);
|
||||
rtw_coex_tdma(rtwdev, false, tdma_case);
|
||||
}
|
||||
|
||||
static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
u32 slot_type = 0;
|
||||
|
||||
|
@ -2344,8 +2450,8 @@ static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 table_case, tdma_case;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
|
||||
|
@ -2421,6 +2527,7 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
|
@ -2494,6 +2601,11 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (coex_stat->bt_game_hid_exist && coex_stat->wl_connected) {
|
||||
rtw_coex_action_bt_game_hid(rtwdev);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (coex_stat->bt_whck_test) {
|
||||
rtw_coex_action_bt_whql_test(rtwdev);
|
||||
goto exit;
|
||||
|
@ -2530,6 +2642,18 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
|
|||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (chip->wl_mimo_ps_support) {
|
||||
if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
|
||||
if (coex_dm->reason == COEX_RSN_2GMEDIA)
|
||||
rtw_coex_mimo_ps(rtwdev, true, true);
|
||||
else
|
||||
rtw_coex_mimo_ps(rtwdev, false, true);
|
||||
} else {
|
||||
rtw_coex_mimo_ps(rtwdev, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode);
|
||||
rtw_coex_limited_wl(rtwdev);
|
||||
}
|
||||
|
@ -2877,9 +3001,9 @@ void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
|
|||
|
||||
void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex_dm *coex_dm = &coex->dm;
|
||||
u32 bt_relink_time;
|
||||
u8 i, rsp_source = 0, type;
|
||||
|
@ -3139,6 +3263,135 @@ void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
|
|||
rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
|
||||
}
|
||||
|
||||
#define COEX_BT_HIDINFO_MTK 0x46
|
||||
static const u8 coex_bt_hidinfo_ps[] = {0x57, 0x69, 0x72};
|
||||
static const u8 coex_bt_hidinfo_xb[] = {0x58, 0x62, 0x6f};
|
||||
|
||||
void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_hid *hidinfo;
|
||||
struct rtw_coex_hid_info_a *hida;
|
||||
struct rtw_coex_hid_handle_list *hl, *bhl;
|
||||
u8 sub_id = buf[2], gamehid_cnt = 0, handle, i;
|
||||
bool cur_game_hid_exist, complete;
|
||||
|
||||
if (!chip->wl_mimo_ps_support &&
|
||||
(sub_id == COEX_BT_HIDINFO_LIST || sub_id == COEX_BT_HIDINFO_A))
|
||||
return;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX,
|
||||
"[BTCoex], HID info notify, sub_id = 0x%x\n", sub_id);
|
||||
|
||||
switch (sub_id) {
|
||||
case COEX_BT_HIDINFO_LIST:
|
||||
hl = &coex_stat->hid_handle_list;
|
||||
bhl = (struct rtw_coex_hid_handle_list *)buf;
|
||||
if (!memcmp(hl, bhl, sizeof(*hl)))
|
||||
return;
|
||||
coex_stat->hid_handle_list = *bhl;
|
||||
memset(&coex_stat->hid_info, 0, sizeof(coex_stat->hid_info));
|
||||
for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
|
||||
hidinfo = &coex_stat->hid_info[i];
|
||||
if (hl->handle[i] != COEX_BT_HIDINFO_NOTCON &&
|
||||
hl->handle[i] != 0)
|
||||
hidinfo->hid_handle = hl->handle[i];
|
||||
}
|
||||
break;
|
||||
case COEX_BT_HIDINFO_A:
|
||||
hida = (struct rtw_coex_hid_info_a *)buf;
|
||||
handle = hida->handle;
|
||||
for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
|
||||
hidinfo = &coex_stat->hid_info[i];
|
||||
if (hidinfo->hid_handle == handle) {
|
||||
hidinfo->hid_vendor = hida->vendor;
|
||||
memcpy(hidinfo->hid_name, hida->name,
|
||||
sizeof(hidinfo->hid_name));
|
||||
hidinfo->hid_info_completed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
|
||||
hidinfo = &coex_stat->hid_info[i];
|
||||
complete = hidinfo->hid_info_completed;
|
||||
handle = hidinfo->hid_handle;
|
||||
if (!complete || handle == COEX_BT_HIDINFO_NOTCON ||
|
||||
handle == 0 || handle >= COEX_BT_BLE_HANDLE_THRS) {
|
||||
hidinfo->is_game_hid = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hidinfo->hid_vendor == COEX_BT_HIDINFO_MTK) {
|
||||
if ((memcmp(hidinfo->hid_name,
|
||||
coex_bt_hidinfo_ps,
|
||||
COEX_BT_HIDINFO_NAME)) == 0)
|
||||
hidinfo->is_game_hid = true;
|
||||
else if ((memcmp(hidinfo->hid_name,
|
||||
coex_bt_hidinfo_xb,
|
||||
COEX_BT_HIDINFO_NAME)) == 0)
|
||||
hidinfo->is_game_hid = true;
|
||||
else
|
||||
hidinfo->is_game_hid = false;
|
||||
} else {
|
||||
hidinfo->is_game_hid = false;
|
||||
}
|
||||
if (hidinfo->is_game_hid)
|
||||
gamehid_cnt++;
|
||||
}
|
||||
|
||||
if (gamehid_cnt > 0)
|
||||
cur_game_hid_exist = true;
|
||||
else
|
||||
cur_game_hid_exist = false;
|
||||
|
||||
if (cur_game_hid_exist != coex_stat->bt_game_hid_exist) {
|
||||
coex_stat->bt_game_hid_exist = cur_game_hid_exist;
|
||||
rtw_dbg(rtwdev, RTW_DBG_COEX,
|
||||
"[BTCoex], HID info changed!bt_game_hid_exist = %d!\n",
|
||||
coex_stat->bt_game_hid_exist);
|
||||
rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
|
||||
}
|
||||
}
|
||||
|
||||
void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
struct rtw_coex_hid *hidinfo;
|
||||
u8 i, handle;
|
||||
bool complete;
|
||||
|
||||
if (!chip->wl_mimo_ps_support || coex_stat->wl_under_ips ||
|
||||
(coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl))
|
||||
return;
|
||||
|
||||
if (!coex_stat->bt_hid_exist &&
|
||||
!((coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION) &&
|
||||
(coex_stat->hi_pri_tx + coex_stat->hi_pri_rx >
|
||||
COEX_BT_GAMEHID_CNT)))
|
||||
return;
|
||||
|
||||
rtw_fw_coex_query_hid_info(rtwdev, COEX_BT_HIDINFO_LIST, 0);
|
||||
|
||||
for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
|
||||
hidinfo = &coex_stat->hid_info[i];
|
||||
complete = hidinfo->hid_info_completed;
|
||||
handle = hidinfo->hid_handle;
|
||||
if (handle == 0 || handle == COEX_BT_HIDINFO_NOTCON ||
|
||||
handle >= COEX_BT_BLE_HANDLE_THRS || complete)
|
||||
continue;
|
||||
|
||||
rtw_fw_coex_query_hid_info(rtwdev,
|
||||
COEX_BT_HIDINFO_A,
|
||||
handle);
|
||||
}
|
||||
}
|
||||
|
||||
void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
|
||||
{
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
|
@ -3175,6 +3428,17 @@ void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type)
|
|||
rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
|
||||
}
|
||||
|
||||
void rtw_coex_wl_status_check(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
|
||||
|
||||
if ((coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) ||
|
||||
coex_stat->wl_under_ips)
|
||||
return;
|
||||
|
||||
rtw_coex_monitor_bt_ctr(rtwdev);
|
||||
}
|
||||
|
||||
void rtw_coex_bt_relink_work(struct work_struct *work)
|
||||
{
|
||||
struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
|
||||
|
@ -3317,7 +3581,7 @@ static const char *rtw_coex_get_reason_string(u8 reason)
|
|||
static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
|
||||
u32 wl_reg_6c4)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
u8 ans = 0xFF;
|
||||
u8 n, i;
|
||||
|
@ -3353,8 +3617,8 @@ static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
|
|||
|
||||
static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 ans = 0xFF;
|
||||
u8 n, i, j;
|
||||
u8 load_cur_tab_val;
|
||||
|
@ -3471,7 +3735,7 @@ static int rtw_coex_val_info(struct rtw_dev *rtwdev,
|
|||
|
||||
static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_reg_domain *reg;
|
||||
char addr_info[INFO_SIZE];
|
||||
int n_addr = 0;
|
||||
|
@ -3637,6 +3901,7 @@ static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)
|
|||
switch (coex_wl_link_mode) {
|
||||
case_WLINK(2G1PORT);
|
||||
case_WLINK(5G);
|
||||
case_WLINK(2GFREE);
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
@ -3644,7 +3909,7 @@ static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)
|
|||
|
||||
void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct rtw_coex_stat *coex_stat = &coex->stat;
|
||||
|
@ -3658,7 +3923,6 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
|
|||
u16 score_board_WB, score_board_BW;
|
||||
u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
|
||||
u32 lte_coex, bt_coex;
|
||||
u32 bt_hi_pri, bt_lo_pri;
|
||||
int i;
|
||||
|
||||
score_board_BW = rtw_coex_read_scbd(rtwdev);
|
||||
|
@ -3669,17 +3933,6 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
|
|||
wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H);
|
||||
wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);
|
||||
|
||||
bt_hi_pri = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS);
|
||||
bt_lo_pri = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1);
|
||||
rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL,
|
||||
BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN);
|
||||
|
||||
coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, bt_hi_pri);
|
||||
coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, bt_hi_pri);
|
||||
|
||||
coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, bt_lo_pri);
|
||||
coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, bt_lo_pri);
|
||||
|
||||
sys_lte = rtw_read8(rtwdev, 0x73);
|
||||
lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
|
||||
bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
|
||||
|
@ -3803,7 +4056,7 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
|
|||
rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
|
||||
seq_printf(m, "%-40s = %u/ %u/ %u\n",
|
||||
"IPS/ Low Power/ PS mode",
|
||||
test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
|
||||
!test_bit(RTW_FLAG_POWERON, rtwdev->flags),
|
||||
test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
|
||||
rtwdev->lps_conf.mode);
|
||||
|
||||
|
|
19
coex.h
19
coex.h
|
@ -11,6 +11,7 @@
|
|||
|
||||
#define COEX_MIN_DELAY 10 /* delay unit in ms */
|
||||
#define COEX_RFK_TIMEOUT 600 /* RFK timeout in ms */
|
||||
#define COEX_BT_GAMEHID_CNT 800
|
||||
|
||||
#define COEX_RF_OFF 0x0
|
||||
#define COEX_RF_ON 0x1
|
||||
|
@ -172,6 +173,7 @@ enum coex_bt_profile {
|
|||
enum coex_wl_link_mode {
|
||||
COEX_WLINK_2G1PORT = 0x0,
|
||||
COEX_WLINK_5G = 0x3,
|
||||
COEX_WLINK_2GFREE = 0x7,
|
||||
COEX_WLINK_MAX
|
||||
};
|
||||
|
||||
|
@ -325,7 +327,7 @@ struct coex_rf_para {
|
|||
|
||||
static inline void rtw_coex_set_init(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->coex_set_init(rtwdev);
|
||||
}
|
||||
|
@ -333,7 +335,7 @@ static inline void rtw_coex_set_init(struct rtw_dev *rtwdev)
|
|||
static inline
|
||||
void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (!chip->ops->coex_set_ant_switch)
|
||||
return;
|
||||
|
@ -343,28 +345,28 @@ void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type)
|
|||
|
||||
static inline void rtw_coex_set_gnt_fix(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->coex_set_gnt_fix(rtwdev);
|
||||
}
|
||||
|
||||
static inline void rtw_coex_set_gnt_debug(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->coex_set_gnt_debug(rtwdev);
|
||||
}
|
||||
|
||||
static inline void rtw_coex_set_rfe_type(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->coex_set_rfe_type(rtwdev);
|
||||
}
|
||||
|
||||
static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->coex_set_wl_tx_power(rtwdev, wl_pwr);
|
||||
}
|
||||
|
@ -372,7 +374,7 @@ static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
|
|||
static inline
|
||||
void rtw_coex_set_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->coex_set_wl_rx_gain(rtwdev, low_gain);
|
||||
}
|
||||
|
@ -401,9 +403,12 @@ void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type);
|
|||
void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type);
|
||||
void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type);
|
||||
void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
|
||||
void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
|
||||
void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length);
|
||||
void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type);
|
||||
void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type);
|
||||
void rtw_coex_wl_status_check(struct rtw_dev *rtwdev);
|
||||
void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev);
|
||||
void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m);
|
||||
|
||||
static inline bool rtw_coex_disabled(struct rtw_dev *rtwdev)
|
||||
|
|
97
debug.c
97
debug.c
|
@ -144,7 +144,9 @@ static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v)
|
|||
addr = debugfs_priv->rf_addr;
|
||||
mask = debugfs_priv->rf_mask;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
val = rtw_read_rf(rtwdev, path, addr, mask);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n",
|
||||
path, addr, mask, val);
|
||||
|
@ -181,8 +183,8 @@ static int rtw_debugfs_copy_from_user(char tmp[], int size,
|
|||
|
||||
tmp_len = (count > size - 1 ? size - 1 : count);
|
||||
|
||||
if (!buffer || copy_from_user(tmp, buffer, tmp_len))
|
||||
return count;
|
||||
if (copy_from_user(tmp, buffer, tmp_len))
|
||||
return -EFAULT;
|
||||
|
||||
tmp[tmp_len] = '\0';
|
||||
|
||||
|
@ -199,13 +201,16 @@ static ssize_t rtw_debugfs_set_read_reg(struct file *filp,
|
|||
char tmp[32 + 1];
|
||||
u32 addr, len;
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
num = sscanf(tmp, "%x %x", &addr, &len);
|
||||
|
||||
if (num != 2)
|
||||
return count;
|
||||
return -EINVAL;
|
||||
|
||||
if (len != 1 && len != 2 && len != 4) {
|
||||
rtw_warn(rtwdev, "read reg setting wrong len\n");
|
||||
|
@ -269,11 +274,7 @@ static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v)
|
|||
for (i = 0 ; i < buf_size ; i += 8) {
|
||||
if (i % page_size == 0)
|
||||
seq_printf(m, "PAGE %d\n", (i + offset) / page_size);
|
||||
seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
|
||||
*(buf + i), *(buf + i + 1),
|
||||
*(buf + i + 2), *(buf + i + 3),
|
||||
*(buf + i + 4), *(buf + i + 5),
|
||||
*(buf + i + 6), *(buf + i + 7));
|
||||
seq_printf(m, "%8ph\n", buf + i);
|
||||
}
|
||||
vfree(buf);
|
||||
|
||||
|
@ -290,8 +291,11 @@ static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp,
|
|||
char tmp[32 + 1];
|
||||
u32 offset, page_num;
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
num = sscanf(tmp, "%d %d", &offset, &page_num);
|
||||
|
||||
|
@ -316,8 +320,11 @@ static ssize_t rtw_debugfs_set_single_input(struct file *filp,
|
|||
char tmp[32 + 1];
|
||||
u32 input;
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
num = kstrtoint(tmp, 0, &input);
|
||||
|
||||
|
@ -340,14 +347,17 @@ static ssize_t rtw_debugfs_set_write_reg(struct file *filp,
|
|||
char tmp[32 + 1];
|
||||
u32 addr, val, len;
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* write BB/MAC register */
|
||||
num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
|
||||
|
||||
if (num != 3)
|
||||
return count;
|
||||
return -EINVAL;
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
|
@ -383,18 +393,23 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp,
|
|||
char tmp[32 + 1];
|
||||
u8 param[8];
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
num = sscanf(tmp, "%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx",
|
||||
¶m[0], ¶m[1], ¶m[2], ¶m[3],
|
||||
¶m[4], ¶m[5], ¶m[6], ¶m[7]);
|
||||
if (num != 8) {
|
||||
rtw_info(rtwdev, "invalid H2C command format for debug\n");
|
||||
rtw_warn(rtwdev, "invalid H2C command format for debug\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_fw_h2c_cmd_dbg(rtwdev, param);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -408,17 +423,22 @@ static ssize_t rtw_debugfs_set_rf_write(struct file *filp,
|
|||
char tmp[32 + 1];
|
||||
u32 path, addr, mask, val;
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val);
|
||||
|
||||
if (num != 4) {
|
||||
rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");
|
||||
return count;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_write_rf(rtwdev, path, addr, mask, val);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,
|
||||
"write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n",
|
||||
path, addr, mask, val);
|
||||
|
@ -436,14 +456,17 @@ static ssize_t rtw_debugfs_set_rf_read(struct file *filp,
|
|||
char tmp[32 + 1];
|
||||
u32 path, addr, mask;
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
num = sscanf(tmp, "%x %x %x", &path, &addr, &mask);
|
||||
|
||||
if (num != 3) {
|
||||
rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");
|
||||
return count;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debugfs_priv->rf_path = path;
|
||||
|
@ -465,7 +488,9 @@ static ssize_t rtw_debugfs_set_fix_rate(struct file *filp,
|
|||
char tmp[32 + 1];
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = kstrtou8(tmp, 0, &fix_rate);
|
||||
if (ret) {
|
||||
|
@ -523,6 +548,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v)
|
|||
u32 addr, offset, data;
|
||||
u8 path;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
|
||||
seq_printf(m, "RF path:%d\n", path);
|
||||
for (addr = 0; addr < 0x100; addr += 4) {
|
||||
|
@ -537,6 +564,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v)
|
|||
seq_puts(m, "\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -625,11 +654,13 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
|
|||
struct rtw_debugfs_priv *debugfs_priv = m->private;
|
||||
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
u8 path, rate;
|
||||
u8 path, rate, bw, ch, regd;
|
||||
struct rtw_power_params pwr_param = {0};
|
||||
u8 bw = hal->current_band_width;
|
||||
u8 ch = hal->current_channel;
|
||||
u8 regd = rtw_regd_get(rtwdev);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
bw = hal->current_band_width;
|
||||
ch = hal->current_channel;
|
||||
regd = rtw_regd_get(rtwdev);
|
||||
|
||||
seq_printf(m, "channel: %u\n", ch);
|
||||
seq_printf(m, "bandwidth: %u\n", bw);
|
||||
|
@ -671,6 +702,7 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
|
|||
}
|
||||
|
||||
mutex_unlock(&hal->tx_power_mutex);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -715,8 +747,10 @@ static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v)
|
|||
seq_printf(m, "Current CH(fc) = %u\n", rtwdev->hal.current_channel);
|
||||
seq_printf(m, "Current BW = %u\n", rtwdev->hal.current_band_width);
|
||||
seq_printf(m, "Current IGI = 0x%x\n", dm_info->igi_history[0]);
|
||||
seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n\n",
|
||||
seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n",
|
||||
stats->tx_throughput, stats->rx_throughput);
|
||||
seq_printf(m, "1SS for TX and RX = %c\n\n", rtwdev->hal.txrx_1ss ?
|
||||
'Y' : 'N');
|
||||
|
||||
seq_puts(m, "==========[Tx Phy Info]========\n");
|
||||
seq_puts(m, "[Tx Rate] = ");
|
||||
|
@ -830,7 +864,9 @@ static int rtw_debugfs_get_coex_info(struct seq_file *m, void *v)
|
|||
struct rtw_debugfs_priv *debugfs_priv = m->private;
|
||||
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_coex_display_coex_info(rtwdev, m);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -847,7 +883,9 @@ static ssize_t rtw_debugfs_set_coex_enable(struct file *filp,
|
|||
bool enable;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = kstrtobool(tmp, &enable);
|
||||
if (ret) {
|
||||
|
@ -917,7 +955,9 @@ static ssize_t rtw_debugfs_set_fw_crash(struct file *filp,
|
|||
bool input;
|
||||
int ret;
|
||||
|
||||
rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
|
||||
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = kstrtobool(tmp, &input);
|
||||
if (ret)
|
||||
|
@ -1025,6 +1065,8 @@ static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m)
|
|||
dm_info->dm_flags & BIT(RTW_DM_CAP_TXGAPK) ? '-' : '+',
|
||||
rtw_dm_cap_strs[RTW_DM_CAP_TXGAPK]);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
|
||||
val = rtw_read_rf(rtwdev, path, RF_GAINTX, RFREG_MASK);
|
||||
seq_printf(m, "path %d:\n0x%x = 0x%x\n", path, RF_GAINTX, val);
|
||||
|
@ -1034,6 +1076,7 @@ static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m)
|
|||
txgapk->rf3f_fs[path][i], i);
|
||||
seq_puts(m, "\n");
|
||||
}
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static int rtw_debugfs_get_dm_cap(struct seq_file *m, void *v)
|
||||
|
|
2
debug.h
2
debug.h
|
@ -23,6 +23,8 @@ enum rtw_debug_mask {
|
|||
RTW_DBG_PATH_DIV = 0x00004000,
|
||||
RTW_DBG_ADAPTIVITY = 0x00008000,
|
||||
RTW_DBG_HW_SCAN = 0x00010000,
|
||||
RTW_DBG_STATE = 0x00020000,
|
||||
RTW_DBG_SDIO = 0x00040000,
|
||||
|
||||
RTW_DBG_ALL = 0xffffffff
|
||||
};
|
||||
|
|
4
efuse.c
4
efuse.c
|
@ -86,7 +86,7 @@ static int rtw_dump_logical_efuse_map(struct rtw_dev *rtwdev, u8 *phy_map,
|
|||
|
||||
static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u32 size = rtwdev->efuse.physical_size;
|
||||
u32 efuse_ctl;
|
||||
u32 addr;
|
||||
|
@ -145,7 +145,7 @@ EXPORT_SYMBOL(rtw_read8_physical_efuse);
|
|||
|
||||
int rtw_parse_efuse_map(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
u32 phy_size = efuse->physical_size;
|
||||
u32 log_size = efuse->logical_size;
|
||||
|
|
324
fw.c
324
fw.c
|
@ -14,6 +14,8 @@
|
|||
#include "util.h"
|
||||
#include "wow.h"
|
||||
#include "ps.h"
|
||||
#include "phy.h"
|
||||
#include "mac.h"
|
||||
|
||||
static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
|
||||
struct sk_buff *skb)
|
||||
|
@ -116,7 +118,7 @@ static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta)
|
|||
si->ra_report.desc_rate = rate;
|
||||
si->ra_report.bit_rate = bit_rate;
|
||||
|
||||
sta->max_rc_amsdu_len = get_max_amsdu_len(bit_rate);
|
||||
sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(bit_rate);
|
||||
}
|
||||
|
||||
static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload,
|
||||
|
@ -138,7 +140,7 @@ struct rtw_beacon_filter_iter_data {
|
|||
u8 *payload;
|
||||
};
|
||||
|
||||
static void rtw_fw_bcn_filter_notify_vif_iter(void *data, u8 *mac,
|
||||
static void rtw_fw_bcn_filter_notify_vif_iter(void *data,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtw_beacon_filter_iter_data *iter_data = data;
|
||||
|
@ -233,6 +235,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
|
|||
case C2H_BT_INFO:
|
||||
rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
|
||||
break;
|
||||
case C2H_BT_HID_INFO:
|
||||
rtw_coex_bt_hid_info_notify(rtwdev, c2h->payload, len);
|
||||
break;
|
||||
case C2H_WLAN_INFO:
|
||||
rtw_coex_wl_fwdbginfo_notify(rtwdev, c2h->payload, len);
|
||||
break;
|
||||
|
@ -303,21 +308,17 @@ void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev)
|
|||
}
|
||||
EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr);
|
||||
|
||||
static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
||||
u8 *h2c)
|
||||
static void rtw_fw_send_h2c_command_register(struct rtw_dev *rtwdev,
|
||||
struct rtw_h2c_register *h2c)
|
||||
{
|
||||
u8 box;
|
||||
u8 box_state;
|
||||
u32 box_reg, box_ex_reg;
|
||||
int idx;
|
||||
u8 box_state, box;
|
||||
int ret;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_FW,
|
||||
"send H2C content %02x%02x%02x%02x %02x%02x%02x%02x\n",
|
||||
h2c[3], h2c[2], h2c[1], h2c[0],
|
||||
h2c[7], h2c[6], h2c[5], h2c[4]);
|
||||
rtw_dbg(rtwdev, RTW_DBG_FW, "send H2C content %08x %08x\n", h2c->w0,
|
||||
h2c->w1);
|
||||
|
||||
spin_lock(&rtwdev->h2c.lock);
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
box = rtwdev->h2c.last_box_num;
|
||||
switch (box) {
|
||||
|
@ -339,7 +340,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
|||
break;
|
||||
default:
|
||||
WARN(1, "invalid h2c mail box number\n");
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = read_poll_timeout_atomic(rtw_read8, box_state,
|
||||
|
@ -348,19 +349,69 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
|||
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to send h2c command\n");
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < 4; idx++)
|
||||
rtw_write8(rtwdev, box_reg + idx, h2c[idx]);
|
||||
for (idx = 0; idx < 4; idx++)
|
||||
rtw_write8(rtwdev, box_ex_reg + idx, h2c[idx + 4]);
|
||||
rtw_write32(rtwdev, box_ex_reg, h2c->w1);
|
||||
rtw_write32(rtwdev, box_reg, h2c->w0);
|
||||
|
||||
if (++rtwdev->h2c.last_box_num >= 4)
|
||||
rtwdev->h2c.last_box_num = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock(&rtwdev->h2c.lock);
|
||||
static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
||||
u8 *h2c)
|
||||
{
|
||||
struct rtw_h2c_cmd *h2c_cmd = (struct rtw_h2c_cmd *)h2c;
|
||||
u8 box;
|
||||
u8 box_state;
|
||||
u32 box_reg, box_ex_reg;
|
||||
int ret;
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_FW,
|
||||
"send H2C content %02x%02x%02x%02x %02x%02x%02x%02x\n",
|
||||
h2c[3], h2c[2], h2c[1], h2c[0],
|
||||
h2c[7], h2c[6], h2c[5], h2c[4]);
|
||||
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
box = rtwdev->h2c.last_box_num;
|
||||
switch (box) {
|
||||
case 0:
|
||||
box_reg = REG_HMEBOX0;
|
||||
box_ex_reg = REG_HMEBOX0_EX;
|
||||
break;
|
||||
case 1:
|
||||
box_reg = REG_HMEBOX1;
|
||||
box_ex_reg = REG_HMEBOX1_EX;
|
||||
break;
|
||||
case 2:
|
||||
box_reg = REG_HMEBOX2;
|
||||
box_ex_reg = REG_HMEBOX2_EX;
|
||||
break;
|
||||
case 3:
|
||||
box_reg = REG_HMEBOX3;
|
||||
box_ex_reg = REG_HMEBOX3_EX;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "invalid h2c mail box number\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = read_poll_timeout_atomic(rtw_read8, box_state,
|
||||
!((box_state >> box) & 0x1), 100, 3000,
|
||||
false, rtwdev, REG_HMETFR);
|
||||
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to send h2c command\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rtw_write32(rtwdev, box_ex_reg, le32_to_cpu(h2c_cmd->msg_ext));
|
||||
rtw_write32(rtwdev, box_reg, le32_to_cpu(h2c_cmd->msg));
|
||||
|
||||
if (++rtwdev->h2c.last_box_num >= 4)
|
||||
rtwdev->h2c.last_box_num = 0;
|
||||
}
|
||||
|
||||
void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c)
|
||||
|
@ -372,15 +423,13 @@ static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt)
|
|||
{
|
||||
int ret;
|
||||
|
||||
spin_lock(&rtwdev->h2c.lock);
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq);
|
||||
ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE);
|
||||
if (ret)
|
||||
rtw_err(rtwdev, "failed to send h2c packet\n");
|
||||
rtwdev->h2c.seq++;
|
||||
|
||||
spin_unlock(&rtwdev->h2c.lock);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -470,6 +519,23 @@ void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
|
|||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
}
|
||||
|
||||
void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
|
||||
{
|
||||
struct rtw_h2c_register h2c = {};
|
||||
|
||||
if (rtwvif->net_type != RTW_NET_MGD_LINKED)
|
||||
return;
|
||||
|
||||
/* Leave LPS before default port H2C so FW timer is correct */
|
||||
rtw_leave_lps(rtwdev);
|
||||
|
||||
h2c.w0 = u32_encode_bits(H2C_CMD_DEFAULT_PORT, RTW_H2C_W0_CMDID) |
|
||||
u32_encode_bits(rtwvif->port, RTW_H2C_DEFAULT_PORT_W0_PORTID) |
|
||||
u32_encode_bits(rtwvif->mac_id, RTW_H2C_DEFAULT_PORT_W0_MACID);
|
||||
|
||||
rtw_fw_send_h2c_command_register(rtwdev, &h2c);
|
||||
}
|
||||
|
||||
void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw)
|
||||
{
|
||||
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
|
||||
|
@ -538,6 +604,18 @@ void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
|
|||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
}
|
||||
|
||||
void rtw_fw_coex_query_hid_info(struct rtw_dev *rtwdev, u8 sub_id, u8 data)
|
||||
{
|
||||
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
|
||||
|
||||
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_HID_INFO);
|
||||
|
||||
SET_COEX_QUERY_HID_INFO_SUBID(h2c_pkt, sub_id);
|
||||
SET_COEX_QUERY_HID_INFO_DATA1(h2c_pkt, data);
|
||||
|
||||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
}
|
||||
|
||||
void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data)
|
||||
{
|
||||
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
|
||||
|
@ -570,10 +648,10 @@ void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
|
|||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
}
|
||||
|
||||
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
|
||||
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
|
||||
bool reset_ra_mask)
|
||||
{
|
||||
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
|
||||
bool no_update = si->updated;
|
||||
bool disable_pt = true;
|
||||
|
||||
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO);
|
||||
|
@ -584,7 +662,7 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
|
|||
SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable);
|
||||
SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode);
|
||||
SET_RA_INFO_LDPC(h2c_pkt, !!si->ldpc_en);
|
||||
SET_RA_INFO_NO_UPDATE(h2c_pkt, no_update);
|
||||
SET_RA_INFO_NO_UPDATE(h2c_pkt, !reset_ra_mask);
|
||||
SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable);
|
||||
SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt);
|
||||
SET_RA_INFO_RA_MASK0(h2c_pkt, (si->ra_mask & 0xff));
|
||||
|
@ -593,7 +671,6 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
|
|||
SET_RA_INFO_RA_MASK3(h2c_pkt, (si->ra_mask & 0xff000000) >> 24);
|
||||
|
||||
si->init_ra_lv = 0;
|
||||
si->updated = true;
|
||||
|
||||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
}
|
||||
|
@ -635,7 +712,7 @@ void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
|
|||
s32 threshold = bss_conf->cqm_rssi_thold + rssi_offset;
|
||||
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
|
||||
|
||||
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER) || !si)
|
||||
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER))
|
||||
return;
|
||||
|
||||
if (!connect) {
|
||||
|
@ -645,6 +722,10 @@ void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!si)
|
||||
return;
|
||||
|
||||
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P0);
|
||||
ether_addr_copy(&h2c_pkt[1], bss_conf->bssid);
|
||||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
|
@ -804,6 +885,16 @@ void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable)
|
|||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
}
|
||||
|
||||
void rtw_fw_set_recover_bt_device(struct rtw_dev *rtwdev)
|
||||
{
|
||||
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
|
||||
|
||||
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RECOVER_BT_DEV);
|
||||
SET_RECOVER_BT_DEV_EN(h2c_pkt, 1);
|
||||
|
||||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
}
|
||||
|
||||
void rtw_fw_set_pg_info(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_lps_conf *conf = &rtwdev->lps_conf;
|
||||
|
@ -886,7 +977,7 @@ void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev)
|
|||
static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req;
|
||||
struct rtw_nlo_info_hdr *nlo_hdr;
|
||||
struct cfg80211_ssid *ssid;
|
||||
|
@ -941,7 +1032,7 @@ static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw)
|
|||
static struct sk_buff *rtw_cs_channel_info_get(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req;
|
||||
struct ieee80211_channel *channels = pno_req->channels;
|
||||
struct sk_buff *skb;
|
||||
|
@ -975,7 +1066,7 @@ static struct sk_buff *rtw_cs_channel_info_get(struct ieee80211_hw *hw)
|
|||
static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info;
|
||||
struct rtw_lps_pg_dpk_hdr *dpk_hdr;
|
||||
struct sk_buff *skb;
|
||||
|
@ -1000,7 +1091,7 @@ static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw)
|
|||
static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_lps_conf *conf = &rtwdev->lps_conf;
|
||||
struct rtw_lps_pg_info_hdr *pg_info_hdr;
|
||||
struct rtw_wow_param *rtw_wow = &rtwdev->wow;
|
||||
|
@ -1033,6 +1124,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
|
|||
struct rtw_vif *rtwvif;
|
||||
struct sk_buff *skb_new;
|
||||
struct cfg80211_ssid *ssid;
|
||||
u16 tim_offset = 0;
|
||||
|
||||
if (rsvd_pkt->type == RSVD_DUMMY) {
|
||||
skb_new = alloc_skb(1, GFP_KERNEL);
|
||||
|
@ -1051,7 +1143,8 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
|
|||
|
||||
switch (rsvd_pkt->type) {
|
||||
case RSVD_BEACON:
|
||||
skb_new = ieee80211_beacon_get(hw, vif);
|
||||
skb_new = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL, 0);
|
||||
rsvd_pkt->tim_offset = tim_offset;
|
||||
break;
|
||||
case RSVD_PS_POLL:
|
||||
skb_new = ieee80211_pspoll_get(hw, vif);
|
||||
|
@ -1060,10 +1153,10 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
|
|||
skb_new = ieee80211_proberesp_get(hw, vif);
|
||||
break;
|
||||
case RSVD_NULL:
|
||||
skb_new = ieee80211_nullfunc_get(hw, vif, false);
|
||||
skb_new = ieee80211_nullfunc_get(hw, vif, -1, false);
|
||||
break;
|
||||
case RSVD_QOS_NULL:
|
||||
skb_new = ieee80211_nullfunc_get(hw, vif, true);
|
||||
skb_new = ieee80211_nullfunc_get(hw, vif, -1, true);
|
||||
break;
|
||||
case RSVD_LPS_PG_DPK:
|
||||
skb_new = rtw_lps_pg_dpk_get(hw);
|
||||
|
@ -1102,7 +1195,7 @@ static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
|
|||
enum rtw_rsvd_packet_type type)
|
||||
{
|
||||
struct rtw_tx_pkt_info pkt_info = {0};
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 *pkt_desc;
|
||||
|
||||
rtw_tx_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb, type);
|
||||
|
@ -1368,6 +1461,10 @@ static void rtw_build_rsvd_page_iter(void *data, u8 *mac,
|
|||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
struct rtw_rsvd_page *rsvd_pkt;
|
||||
|
||||
/* AP not yet started, don't gather its rsvd pages */
|
||||
if (vif->type == NL80211_IFTYPE_AP && !rtwdev->ap_active)
|
||||
return;
|
||||
|
||||
list_for_each_entry(rsvd_pkt, &rtwvif->rsvd_page_list, vif_list) {
|
||||
if (rsvd_pkt->type == RSVD_BEACON)
|
||||
list_add(&rsvd_pkt->build_list,
|
||||
|
@ -1413,7 +1510,7 @@ static int __rtw_build_rsvd_page_from_vifs(struct rtw_dev *rtwdev)
|
|||
static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size)
|
||||
{
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct sk_buff *iter;
|
||||
struct rtw_rsvd_page *rsvd_pkt;
|
||||
u32 page = 0;
|
||||
|
@ -1582,6 +1679,17 @@ int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void rtw_fw_update_beacon_work(struct work_struct *work)
|
||||
{
|
||||
struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
|
||||
update_beacon_work);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_fw_download_rsvd_page(rtwdev);
|
||||
rtw_send_rsvd_page_h2c(rtwdev);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size,
|
||||
u32 *buf, u32 residue, u16 start_pg)
|
||||
{
|
||||
|
@ -1617,7 +1725,7 @@ static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size,
|
|||
static void rtw_fw_read_fifo(struct rtw_dev *rtwdev, enum rtw_fw_fifo_sel sel,
|
||||
u32 offset, u32 size, u32 *buf)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u32 start_pg, residue;
|
||||
|
||||
if (sel >= RTW_FW_FIFO_MAX) {
|
||||
|
@ -1676,7 +1784,7 @@ int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
|
|||
static void __rtw_fw_update_pkt(struct rtw_dev *rtwdev, u8 pkt_id, u16 size,
|
||||
u8 location)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
|
||||
u16 total_size = H2C_PKT_HDR_SIZE + H2C_PKT_UPDATE_PKT_LEN;
|
||||
|
||||
|
@ -1766,7 +1874,7 @@ void rtw_fw_adaptivity(struct rtw_dev *rtwdev)
|
|||
|
||||
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_ADAPTIVITY);
|
||||
SET_ADAPTIVITY_MODE(h2c_pkt, dm_info->edcca_mode);
|
||||
SET_ADAPTIVITY_OPTION(h2c_pkt, 2);
|
||||
SET_ADAPTIVITY_OPTION(h2c_pkt, 1);
|
||||
SET_ADAPTIVITY_IGI(h2c_pkt, dm_info->igi_history[0]);
|
||||
SET_ADAPTIVITY_L2H(h2c_pkt, dm_info->l2h_th_ini);
|
||||
SET_ADAPTIVITY_DENSITY(h2c_pkt, dm_info->scan_density);
|
||||
|
@ -1784,12 +1892,12 @@ void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
|
|||
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
|
||||
}
|
||||
|
||||
static void rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
|
||||
struct sk_buff_head *list,
|
||||
struct rtw_vif *rtwvif)
|
||||
static int rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
|
||||
struct sk_buff_head *list, u8 *bands,
|
||||
struct rtw_vif *rtwvif)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct sk_buff *new;
|
||||
u8 idx;
|
||||
|
||||
|
@ -1797,25 +1905,37 @@ static void rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
|
|||
if (!(BIT(idx) & chip->band))
|
||||
continue;
|
||||
new = skb_copy(skb, GFP_KERNEL);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
skb_put_data(new, ies->ies[idx], ies->len[idx]);
|
||||
skb_put_data(new, ies->common_ies, ies->common_ie_len);
|
||||
skb_queue_tail(list, new);
|
||||
(*bands)++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_ssids,
|
||||
static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes,
|
||||
struct sk_buff_head *probe_req_list)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct sk_buff *skb, *tmp;
|
||||
u8 page_offset = 1, *buf, page_size = chip->page_size;
|
||||
u8 pages = page_offset + num_ssids * RTW_PROBE_PG_CNT;
|
||||
u16 pg_addr = rtwdev->fifo.rsvd_h2c_info_addr, loc;
|
||||
u16 buf_offset = page_size * page_offset;
|
||||
u8 tx_desc_sz = chip->tx_pkt_desc_sz;
|
||||
u8 page_cnt, pages;
|
||||
unsigned int pkt_len;
|
||||
int ret;
|
||||
|
||||
if (rtw_fw_feature_ext_check(&rtwdev->fw, FW_FEATURE_EXT_OLD_PAGE_NUM))
|
||||
page_cnt = RTW_OLD_PROBE_PG_CNT;
|
||||
else
|
||||
page_cnt = RTW_PROBE_PG_CNT;
|
||||
|
||||
pages = page_offset + num_probes * page_cnt;
|
||||
|
||||
buf = kzalloc(page_size * pages, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
@ -1824,7 +1944,7 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_ssids,
|
|||
skb_queue_walk_safe(probe_req_list, skb, tmp) {
|
||||
skb_unlink(skb, probe_req_list);
|
||||
rtw_fill_rsvd_page_desc(rtwdev, skb, RSVD_PROBE_REQ);
|
||||
if (skb->len > page_size * RTW_PROBE_PG_CNT) {
|
||||
if (skb->len > page_size * page_cnt) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -1834,8 +1954,8 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_ssids,
|
|||
loc = pg_addr - rtwdev->fifo.rsvd_boundary + page_offset;
|
||||
__rtw_fw_update_pkt(rtwdev, RTW_PACKET_PROBE_REQ, pkt_len, loc);
|
||||
|
||||
buf_offset += RTW_PROBE_PG_CNT * page_size;
|
||||
page_offset += RTW_PROBE_PG_CNT;
|
||||
buf_offset += page_cnt * page_size;
|
||||
page_offset += page_cnt;
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
|
@ -1848,6 +1968,8 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_ssids,
|
|||
rtwdev->scan_info.probe_pg_size = page_offset;
|
||||
out:
|
||||
kfree(buf);
|
||||
skb_queue_walk_safe(probe_req_list, skb, tmp)
|
||||
kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1857,8 +1979,9 @@ static int rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev,
|
|||
{
|
||||
struct cfg80211_scan_request *req = rtwvif->scan_req;
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *skb;
|
||||
u8 num = req->n_ssids, i;
|
||||
struct sk_buff *skb, *tmp;
|
||||
u8 num = req->n_ssids, i, bands = 0;
|
||||
int ret;
|
||||
|
||||
skb_queue_head_init(&list);
|
||||
for (i = 0; i < num; i++) {
|
||||
|
@ -1866,11 +1989,25 @@ static int rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev,
|
|||
req->ssids[i].ssid,
|
||||
req->ssids[i].ssid_len,
|
||||
req->ie_len);
|
||||
rtw_append_probe_req_ie(rtwdev, skb, &list, rtwvif);
|
||||
if (!skb) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
ret = rtw_append_probe_req_ie(rtwdev, skb, &list, &bands,
|
||||
rtwvif);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
return _rtw_hw_scan_update_probe_req(rtwdev, num, &list);
|
||||
return _rtw_hw_scan_update_probe_req(rtwdev, num * bands, &list);
|
||||
|
||||
out:
|
||||
skb_queue_walk_safe(&list, skb, tmp)
|
||||
kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtw_add_chan_info(struct rtw_dev *rtwdev, struct rtw_chan_info *info,
|
||||
|
@ -1996,6 +2133,9 @@ void rtw_hw_scan_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
rtwvif->scan_req = req;
|
||||
|
||||
ieee80211_stop_queues(rtwdev->hw);
|
||||
rtw_leave_lps_deep(rtwdev);
|
||||
rtw_hci_flush_all_queues(rtwdev, false);
|
||||
rtw_mac_flush_all_queues(rtwdev, false);
|
||||
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
|
||||
get_random_mask_addr(mac_addr, req->mac_addr,
|
||||
req->mac_addr_mask);
|
||||
|
@ -2014,7 +2154,10 @@ void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
};
|
||||
struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
struct rtw_vif *rtwvif;
|
||||
u8 chan = scan_info->op_chan;
|
||||
|
||||
if (!vif)
|
||||
return;
|
||||
|
@ -2022,12 +2165,15 @@ void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
rtwdev->hal.rcr |= BIT_CBSSID_BCN;
|
||||
rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);
|
||||
|
||||
rtw_core_scan_complete(rtwdev, vif);
|
||||
rtw_core_scan_complete(rtwdev, vif, true);
|
||||
|
||||
rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
if (chan)
|
||||
rtw_store_op_chan(rtwdev, false);
|
||||
rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
|
||||
ieee80211_wake_queues(rtwdev->hw);
|
||||
ieee80211_scan_completed(rtwdev->hw, &info);
|
||||
|
||||
rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
rtwvif->scan_req = NULL;
|
||||
rtwvif->scan_ies = NULL;
|
||||
rtwdev->scan_info.scanning_vif = NULL;
|
||||
|
@ -2065,6 +2211,7 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
bool enable)
|
||||
{
|
||||
struct rtw_vif *rtwvif = vif ? (struct rtw_vif *)vif->drv_priv : NULL;
|
||||
struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw_ch_switch_option cs_option = {0};
|
||||
struct rtw_chan_list chan_list = {0};
|
||||
int ret = 0;
|
||||
|
@ -2073,7 +2220,7 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
return -EINVAL;
|
||||
|
||||
cs_option.switch_en = enable;
|
||||
cs_option.back_op_en = rtwvif->net_type == RTW_NET_MGD_LINKED;
|
||||
cs_option.back_op_en = scan_info->op_chan != 0;
|
||||
if (enable) {
|
||||
ret = rtw_hw_scan_prehandle(rtwdev, rtwvif, &chan_list);
|
||||
if (ret)
|
||||
|
@ -2081,11 +2228,19 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
}
|
||||
rtw_fw_set_scan_offload(rtwdev, &cs_option, rtwvif, &chan_list);
|
||||
out:
|
||||
if (rtwdev->ap_active) {
|
||||
ret = rtw_download_beacon(rtwdev);
|
||||
if (ret)
|
||||
rtw_err(rtwdev, "HW scan download beacon failed\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rtw_hw_scan_abort(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
|
||||
void rtw_hw_scan_abort(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
|
||||
|
||||
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
|
||||
return;
|
||||
|
||||
|
@ -2109,17 +2264,36 @@ void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb)
|
|||
rtw_hw_scan_complete(rtwdev, vif, aborted);
|
||||
|
||||
if (aborted)
|
||||
rtw_info(rtwdev, "HW scan aborted with code: %d\n", rc);
|
||||
rtw_dbg(rtwdev, RTW_DBG_HW_SCAN, "HW scan aborted with code: %d\n", rc);
|
||||
}
|
||||
|
||||
void rtw_store_op_chan(struct rtw_dev *rtwdev)
|
||||
void rtw_store_op_chan(struct rtw_dev *rtwdev, bool backup)
|
||||
{
|
||||
struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
u8 band;
|
||||
|
||||
scan_info->op_chan = hal->current_channel;
|
||||
scan_info->op_bw = hal->current_band_width;
|
||||
scan_info->op_pri_ch_idx = hal->current_primary_channel_index;
|
||||
if (backup) {
|
||||
scan_info->op_chan = hal->current_channel;
|
||||
scan_info->op_bw = hal->current_band_width;
|
||||
scan_info->op_pri_ch_idx = hal->current_primary_channel_index;
|
||||
scan_info->op_pri_ch = hal->primary_channel;
|
||||
} else {
|
||||
band = scan_info->op_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
|
||||
rtw_update_channel(rtwdev, scan_info->op_chan,
|
||||
scan_info->op_pri_ch,
|
||||
band, scan_info->op_bw);
|
||||
}
|
||||
}
|
||||
|
||||
void rtw_clear_op_chan(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info;
|
||||
|
||||
scan_info->op_chan = 0;
|
||||
scan_info->op_bw = 0;
|
||||
scan_info->op_pri_ch_idx = 0;
|
||||
scan_info->op_pri_ch = 0;
|
||||
}
|
||||
|
||||
static bool rtw_is_op_chan(struct rtw_dev *rtwdev, u8 channel)
|
||||
|
@ -2134,7 +2308,10 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
|
|||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
struct rtw_c2h_cmd *c2h;
|
||||
enum rtw_scan_notify_id id;
|
||||
u8 chan, status;
|
||||
u8 chan, band, status;
|
||||
|
||||
if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
|
||||
return;
|
||||
|
||||
c2h = get_c2h_from_skb(skb);
|
||||
chan = GET_CHAN_SWITCH_CENTRAL_CH(c2h->payload);
|
||||
|
@ -2142,10 +2319,14 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
|
|||
status = GET_CHAN_SWITCH_STATUS(c2h->payload);
|
||||
|
||||
if (id == RTW_SCAN_NOTIFY_ID_POSTSWITCH) {
|
||||
if (rtw_is_op_chan(rtwdev, chan))
|
||||
band = chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
|
||||
rtw_update_channel(rtwdev, chan, chan, band,
|
||||
RTW_CHANNEL_WIDTH_20);
|
||||
if (rtw_is_op_chan(rtwdev, chan)) {
|
||||
rtw_store_op_chan(rtwdev, false);
|
||||
ieee80211_wake_queues(rtwdev->hw);
|
||||
hal->current_channel = chan;
|
||||
hal->current_band_type = chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
|
||||
rtw_core_enable_beacon(rtwdev, true);
|
||||
}
|
||||
} else if (id == RTW_SCAN_NOTIFY_ID_PRESWITCH) {
|
||||
if (IS_CH_5G_BAND(chan)) {
|
||||
rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G);
|
||||
|
@ -2158,8 +2339,15 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
|
|||
chan_type = COEX_SWITCH_TO_24G_NOFORSCAN;
|
||||
rtw_coex_switchband_notify(rtwdev, chan_type);
|
||||
}
|
||||
if (rtw_is_op_chan(rtwdev, chan))
|
||||
/* The channel of C2H RTW_SCAN_NOTIFY_ID_PRESWITCH is next
|
||||
* channel that hardware will switch. We need to stop queue
|
||||
* if next channel is non-op channel.
|
||||
*/
|
||||
if (!rtw_is_op_chan(rtwdev, chan) &&
|
||||
rtw_is_op_chan(rtwdev, hal->current_channel)) {
|
||||
rtw_core_enable_beacon(rtwdev, false);
|
||||
ieee80211_stop_queues(rtwdev->hw);
|
||||
}
|
||||
}
|
||||
|
||||
rtw_dbg(rtwdev, RTW_DBG_HW_SCAN,
|
||||
|
|
61
fw.h
61
fw.h
|
@ -41,12 +41,14 @@
|
|||
#define RTW_EX_CH_INFO_HDR_SIZE 2
|
||||
#define RTW_SCAN_WIDTH 0
|
||||
#define RTW_PRI_CH_IDX 1
|
||||
#define RTW_PROBE_PG_CNT 2
|
||||
#define RTW_OLD_PROBE_PG_CNT 2
|
||||
#define RTW_PROBE_PG_CNT 4
|
||||
|
||||
enum rtw_c2h_cmd_id {
|
||||
C2H_CCX_TX_RPT = 0x03,
|
||||
C2H_BT_INFO = 0x09,
|
||||
C2H_BT_MP_INFO = 0x0b,
|
||||
C2H_BT_HID_INFO = 0x45,
|
||||
C2H_RA_RPT = 0x0c,
|
||||
C2H_HW_FEATURE_REPORT = 0x19,
|
||||
C2H_WLAN_INFO = 0x27,
|
||||
|
@ -79,6 +81,22 @@ struct rtw_c2h_adaptivity {
|
|||
u8 option;
|
||||
} __packed;
|
||||
|
||||
struct rtw_h2c_register {
|
||||
u32 w0;
|
||||
u32 w1;
|
||||
} __packed;
|
||||
|
||||
#define RTW_H2C_W0_CMDID GENMASK(7, 0)
|
||||
|
||||
/* H2C_CMD_DEFAULT_PORT command */
|
||||
#define RTW_H2C_DEFAULT_PORT_W0_PORTID GENMASK(15, 8)
|
||||
#define RTW_H2C_DEFAULT_PORT_W0_MACID GENMASK(23, 16)
|
||||
|
||||
struct rtw_h2c_cmd {
|
||||
__le32 msg;
|
||||
__le32 msg_ext;
|
||||
} __packed;
|
||||
|
||||
enum rtw_rsvd_packet_type {
|
||||
RSVD_BEACON,
|
||||
RSVD_DUMMY,
|
||||
|
@ -119,6 +137,10 @@ enum rtw_fw_feature {
|
|||
FW_FEATURE_MAX = BIT(31),
|
||||
};
|
||||
|
||||
enum rtw_fw_feature_ext {
|
||||
FW_FEATURE_EXT_OLD_PAGE_NUM = BIT(0),
|
||||
};
|
||||
|
||||
enum rtw_beacon_filter_offload_mode {
|
||||
BCN_FILTER_OFFLOAD_MODE_0 = 0,
|
||||
BCN_FILTER_OFFLOAD_MODE_1,
|
||||
|
@ -171,6 +193,7 @@ struct rtw_rsvd_page {
|
|||
struct sk_buff *skb;
|
||||
enum rtw_rsvd_packet_type type;
|
||||
u8 page;
|
||||
u16 tim_offset;
|
||||
bool add_txdesc;
|
||||
struct cfg80211_ssid *ssid;
|
||||
u16 probe_req_size;
|
||||
|
@ -321,6 +344,11 @@ struct rtw_fw_hdr_legacy {
|
|||
__le32 rsvd5;
|
||||
} __packed;
|
||||
|
||||
#define RTW_FW_VER_CODE(ver, sub_ver, idx) \
|
||||
(((ver) << 16) | ((sub_ver) << 8) | (idx))
|
||||
#define RTW_FW_SUIT_VER_CODE(s) \
|
||||
RTW_FW_VER_CODE((s).version, (s).sub_version, (s).sub_index)
|
||||
|
||||
/* C2H */
|
||||
#define GET_CCX_REPORT_SEQNUM_V0(c2h_payload) (c2h_payload[6] & 0xfc)
|
||||
#define GET_CCX_REPORT_STATUS_V0(c2h_payload) (c2h_payload[0] & 0xc0)
|
||||
|
@ -513,6 +541,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
|
|||
#define H2C_CMD_MEDIA_STATUS_RPT 0x01
|
||||
#define H2C_CMD_SET_PWR_MODE 0x20
|
||||
#define H2C_CMD_LPS_PG_INFO 0x2b
|
||||
#define H2C_CMD_DEFAULT_PORT 0x2c
|
||||
#define H2C_CMD_RA_INFO 0x40
|
||||
#define H2C_CMD_RSSI_MONITOR 0x42
|
||||
#define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56
|
||||
|
@ -529,6 +558,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
|
|||
#define H2C_CMD_QUERY_BT_MP_INFO 0x67
|
||||
#define H2C_CMD_BT_WIFI_CONTROL 0x69
|
||||
#define H2C_CMD_WIFI_CALIBRATION 0x6d
|
||||
#define H2C_CMD_QUERY_BT_HID_INFO 0x73
|
||||
|
||||
#define H2C_CMD_KEEP_ALIVE 0x03
|
||||
#define H2C_CMD_DISCONNECT_DECISION 0x04
|
||||
|
@ -537,6 +567,8 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
|
|||
#define H2C_CMD_AOAC_GLOBAL_INFO 0x82
|
||||
#define H2C_CMD_NLO_INFO 0x8C
|
||||
|
||||
#define H2C_CMD_RECOVER_BT_DEV 0xD1
|
||||
|
||||
#define SET_H2C_CMD_ID_CLASS(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0))
|
||||
|
||||
|
@ -681,6 +713,11 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
|
|||
#define SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))
|
||||
|
||||
#define SET_COEX_QUERY_HID_INFO_SUBID(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
|
||||
#define SET_COEX_QUERY_HID_INFO_DATA1(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
|
||||
|
||||
#define SET_KEEP_ALIVE_ENABLE(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
|
||||
#define SET_KEEP_ALIVE_ADOPT(h2c_pkt, value) \
|
||||
|
@ -731,6 +768,9 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
|
|||
#define SET_NLO_LOC_NLO_INFO(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
|
||||
|
||||
#define SET_RECOVER_BT_DEV_EN(h2c_pkt, value) \
|
||||
le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
|
||||
|
||||
#define GET_FW_DUMP_LEN(_header) \
|
||||
le32_get_bits(*((__le32 *)(_header) + 0x00), GENMASK(15, 0))
|
||||
#define GET_FW_DUMP_SEQ(_header) \
|
||||
|
@ -762,11 +802,18 @@ static inline bool rtw_fw_feature_check(struct rtw_fw_state *fw,
|
|||
return !!(fw->feature & feature);
|
||||
}
|
||||
|
||||
static inline bool rtw_fw_feature_ext_check(struct rtw_fw_state *fw,
|
||||
enum rtw_fw_feature_ext feature)
|
||||
{
|
||||
return !!(fw->feature_ext & feature);
|
||||
}
|
||||
|
||||
void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
|
||||
struct sk_buff *skb);
|
||||
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
|
||||
void rtw_fw_send_general_info(struct rtw_dev *rtwdev);
|
||||
void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
|
||||
void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif);
|
||||
|
||||
void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
|
||||
void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start);
|
||||
|
@ -780,9 +827,12 @@ void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl);
|
|||
void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable);
|
||||
void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
|
||||
u8 para1, u8 para2, u8 para3, u8 para4, u8 para5);
|
||||
void rtw_fw_coex_query_hid_info(struct rtw_dev *rtwdev, u8 sub_id, u8 data);
|
||||
|
||||
void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data);
|
||||
void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
|
||||
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
|
||||
void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
|
||||
bool reset_ra_mask);
|
||||
void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn);
|
||||
void rtw_fw_update_wl_phy_info(struct rtw_dev *rtwdev);
|
||||
void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
|
||||
|
@ -798,6 +848,7 @@ void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev,
|
|||
void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev,
|
||||
struct rtw_vif *rtwvif);
|
||||
int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev);
|
||||
void rtw_fw_update_beacon_work(struct work_struct *work);
|
||||
void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev);
|
||||
int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
|
||||
u32 offset, u32 size, u32 *buf);
|
||||
|
@ -810,6 +861,7 @@ void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev,
|
|||
u8 group_key_enc);
|
||||
|
||||
void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable);
|
||||
void rtw_fw_set_recover_bt_device(struct rtw_dev *rtwdev);
|
||||
void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev,
|
||||
struct cfg80211_ssid *ssid);
|
||||
void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable);
|
||||
|
@ -819,7 +871,8 @@ int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
|
|||
u32 *buffer);
|
||||
void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
|
||||
void rtw_fw_adaptivity(struct rtw_dev *rtwdev);
|
||||
void rtw_store_op_chan(struct rtw_dev *rtwdev);
|
||||
void rtw_store_op_chan(struct rtw_dev *rtwdev, bool backup);
|
||||
void rtw_clear_op_chan(struct rtw_dev *rtwdev);
|
||||
void rtw_hw_scan_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *req);
|
||||
void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
|
@ -828,5 +881,5 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
bool enable);
|
||||
void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb);
|
||||
void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb);
|
||||
void rtw_hw_scan_abort(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
|
||||
void rtw_hw_scan_abort(struct rtw_dev *rtwdev);
|
||||
#endif
|
||||
|
|
9
hci.h
9
hci.h
|
@ -166,12 +166,11 @@ static inline u32
|
|||
rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
||||
u32 addr, u32 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&rtwdev->rf_lock, flags);
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
|
||||
spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -180,11 +179,9 @@ static inline void
|
|||
rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data)
|
||||
{
|
||||
unsigned long flags;
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
spin_lock_irqsave(&rtwdev->rf_lock, flags);
|
||||
rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data);
|
||||
spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
|
|
123
mac.c
123
mac.c
|
@ -7,6 +7,7 @@
|
|||
#include "reg.h"
|
||||
#include "fw.h"
|
||||
#include "debug.h"
|
||||
#include "sdio.h"
|
||||
|
||||
void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
|
||||
u8 primary_ch_idx)
|
||||
|
@ -60,6 +61,7 @@ EXPORT_SYMBOL(rtw_set_channel_mac);
|
|||
|
||||
static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev)
|
||||
{
|
||||
unsigned int retry;
|
||||
u32 value32;
|
||||
u8 value8;
|
||||
|
||||
|
@ -75,7 +77,29 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev)
|
|||
|
||||
switch (rtw_hci_type(rtwdev)) {
|
||||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_BT_DIG_CLK_EN);
|
||||
rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS);
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rtw_write8_clr(rtwdev, REG_SDIO_HSUS_CTRL, BIT_HCI_SUS_REQ);
|
||||
|
||||
for (retry = 0; retry < RTW_PWR_POLLING_CNT; retry++) {
|
||||
if (rtw_read8(rtwdev, REG_SDIO_HSUS_CTRL) & BIT_HCI_RESUME_RDY)
|
||||
break;
|
||||
|
||||
usleep_range(10, 50);
|
||||
}
|
||||
|
||||
if (retry == RTW_PWR_POLLING_CNT) {
|
||||
rtw_err(rtwdev, "failed to poll REG_SDIO_HSUS_CTRL[1]");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (rtw_sdio_is_sdio30_supported(rtwdev))
|
||||
rtw_write8_set(rtwdev, REG_HCI_OPT_CTRL + 2,
|
||||
BIT_SDIO_PAD_E5 >> 16);
|
||||
else
|
||||
rtw_write8_clr(rtwdev, REG_HCI_OPT_CTRL + 2,
|
||||
BIT_SDIO_PAD_E5 >> 16);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
break;
|
||||
|
@ -217,10 +241,13 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
|
|||
cut_mask = cut_version_to_mask(cut);
|
||||
switch (rtw_hci_type(rtwdev)) {
|
||||
case RTW_HCI_TYPE_PCIE:
|
||||
intf_mask = BIT(2);
|
||||
intf_mask = RTW_PWR_INTF_PCI_MSK;
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
intf_mask = BIT(1);
|
||||
intf_mask = RTW_PWR_INTF_USB_MSK;
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
intf_mask = RTW_PWR_INTF_SDIO_MSK;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -233,7 +260,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
|
|||
|
||||
ret = rtw_sub_pwr_seq_parser(rtwdev, intf_mask, cut_mask, cmd);
|
||||
if (ret)
|
||||
return -EBUSY;
|
||||
return ret;
|
||||
|
||||
idx++;
|
||||
} while (1);
|
||||
|
@ -243,10 +270,12 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
|
|||
|
||||
static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_pwr_seq_cmd **pwr_seq;
|
||||
u32 imr = 0;
|
||||
u8 rpwm;
|
||||
bool cur_pwr;
|
||||
int ret;
|
||||
|
||||
if (rtw_chip_wcpu_11ac(rtwdev)) {
|
||||
rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
|
||||
|
@ -269,11 +298,24 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
|
|||
if (pwr_on == cur_pwr)
|
||||
return -EALREADY;
|
||||
|
||||
pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
|
||||
if (rtw_pwr_seq_parser(rtwdev, pwr_seq))
|
||||
return -EINVAL;
|
||||
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) {
|
||||
imr = rtw_read32(rtwdev, REG_SDIO_HIMR);
|
||||
rtw_write32(rtwdev, REG_SDIO_HIMR, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (!pwr_on)
|
||||
clear_bit(RTW_FLAG_POWERON, rtwdev->flags);
|
||||
|
||||
pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
|
||||
ret = rtw_pwr_seq_parser(rtwdev, pwr_seq);
|
||||
|
||||
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO)
|
||||
rtw_write32(rtwdev, REG_SDIO_HIMR, imr);
|
||||
|
||||
if (!ret && pwr_on)
|
||||
set_bit(RTW_FLAG_POWERON, rtwdev->flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __rtw_mac_init_system_cfg(struct rtw_dev *rtwdev)
|
||||
|
@ -335,6 +377,11 @@ int rtw_mac_power_on(struct rtw_dev *rtwdev)
|
|||
ret = rtw_mac_power_switch(rtwdev, true);
|
||||
if (ret == -EALREADY) {
|
||||
rtw_mac_power_switch(rtwdev, false);
|
||||
|
||||
ret = rtw_mac_pre_system_cfg(rtwdev);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = rtw_mac_power_switch(rtwdev, true);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -439,6 +486,9 @@ static void download_firmware_reg_backup(struct rtw_dev *rtwdev,
|
|||
rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, 0x200);
|
||||
rtw_write32(rtwdev, REG_RQPN_CTRL_2, bckp[bckp_idx - 1].val);
|
||||
|
||||
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO)
|
||||
rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);
|
||||
|
||||
/* Disable beacon related functions */
|
||||
tmp = rtw_read8(rtwdev, REG_BCN_CTRL);
|
||||
bckp[bckp_idx].len = 1;
|
||||
|
@ -587,7 +637,7 @@ static int
|
|||
download_firmware_to_mem(struct rtw_dev *rtwdev, const u8 *data,
|
||||
u32 src, u32 dst, u32 size)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u32 desc_size = chip->tx_pkt_desc_sz;
|
||||
u8 first_part;
|
||||
u32 mem_offset;
|
||||
|
@ -744,8 +794,10 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev,
|
|||
|
||||
wlan_cpu_enable(rtwdev, true);
|
||||
|
||||
if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp))
|
||||
return -EBUSY;
|
||||
if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) {
|
||||
ret = -EBUSY;
|
||||
goto dlfw_fail;
|
||||
}
|
||||
|
||||
ret = download_firmware_validate(rtwdev);
|
||||
if (ret)
|
||||
|
@ -906,7 +958,8 @@ static int __rtw_download_firmware_legacy(struct rtw_dev *rtwdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
|
||||
static
|
||||
int _rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
|
||||
{
|
||||
if (rtw_chip_wcpu_11n(rtwdev))
|
||||
return __rtw_download_firmware_legacy(rtwdev, fw);
|
||||
|
@ -914,6 +967,21 @@ int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
|
|||
return __rtw_download_firmware(rtwdev, fw);
|
||||
}
|
||||
|
||||
int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = _rtw_download_firmware(rtwdev, fw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE &&
|
||||
rtwdev->chip->id == RTW_CHIP_TYPE_8821C)
|
||||
rtw_fw_set_recover_bt_device(rtwdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues)
|
||||
{
|
||||
const struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn;
|
||||
|
@ -934,7 +1002,7 @@ static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues)
|
|||
static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev,
|
||||
u32 prio_queue, bool drop)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_prioq_addr *addr;
|
||||
bool wsize;
|
||||
u16 avail_page, rsvd_page;
|
||||
|
@ -996,7 +1064,7 @@ void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop)
|
|||
|
||||
static int txdma_queue_mapping(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_rqpn *rqpn = NULL;
|
||||
u16 txdma_pq_map = 0;
|
||||
|
||||
|
@ -1014,6 +1082,9 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev)
|
|||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rqpn = &chip->rqpn_table[0];
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1032,18 +1103,25 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev)
|
|||
if (rtw_chip_wcpu_11ac(rtwdev))
|
||||
rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
|
||||
|
||||
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) {
|
||||
rtw_read32(rtwdev, REG_SDIO_FREE_TXPG);
|
||||
rtw_write32(rtwdev, REG_SDIO_TX_CTRL, 0);
|
||||
} else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) {
|
||||
rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_ARBBW_EN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_trx_fifo_info(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_fifo_conf *fifo = &rtwdev->fifo;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u16 cur_pg_addr;
|
||||
u8 csi_buf_pg_num = chip->csi_buf_pg_num;
|
||||
|
||||
/* config rsvd page num */
|
||||
fifo->rsvd_drv_pg_num = 8;
|
||||
fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num;
|
||||
fifo->txff_pg_num = chip->txff_size >> 7;
|
||||
if (rtw_chip_wcpu_11n(rtwdev))
|
||||
fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num;
|
||||
|
@ -1092,8 +1170,8 @@ static int __priority_queue_cfg(struct rtw_dev *rtwdev,
|
|||
const struct rtw_page_table *pg_tbl,
|
||||
u16 pubq_num)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_fifo_conf *fifo = &rtwdev->fifo;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num);
|
||||
rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num);
|
||||
|
@ -1123,8 +1201,8 @@ static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev,
|
|||
const struct rtw_page_table *pg_tbl,
|
||||
u16 pubq_num)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_fifo_conf *fifo = &rtwdev->fifo;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u32 val32;
|
||||
|
||||
val32 = BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num);
|
||||
|
@ -1149,8 +1227,8 @@ static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev,
|
|||
|
||||
static int priority_queue_cfg(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_fifo_conf *fifo = &rtwdev->fifo;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_page_table *pg_tbl = NULL;
|
||||
u16 pubq_num;
|
||||
int ret;
|
||||
|
@ -1173,6 +1251,9 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev)
|
|||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
pg_tbl = &chip->page_table[0];
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1277,7 +1358,7 @@ static int rtw_drv_info_cfg(struct rtw_dev *rtwdev)
|
|||
|
||||
int rtw_mac_init(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
int ret;
|
||||
|
||||
ret = rtw_init_trx_cfg(rtwdev);
|
||||
|
|
1
mac.h
1
mac.h
|
@ -7,7 +7,6 @@
|
|||
|
||||
#define RTW_HW_PORT_NUM 5
|
||||
#define cut_version_to_mask(cut) (0x1 << ((cut) + 1))
|
||||
#define SDIO_LOCAL_OFFSET 0x10250000
|
||||
#define DDMA_POLLING_COUNT 1000
|
||||
#define C2H_PKT_BUF 256
|
||||
#define REPORT_BUF 128
|
||||
|
|
147
mac80211.c
147
mac80211.c
|
@ -43,7 +43,11 @@ static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw,
|
|||
list_add_tail(&rtwtxq->list, &rtwdev->txqs);
|
||||
spin_unlock_bh(&rtwdev->txq_lock);
|
||||
|
||||
queue_work(rtwdev->tx_wq, &rtwdev->tx_work);
|
||||
/* ensure to dequeue EAPOL (4/4) at the right time */
|
||||
if (txq->ac == IEEE80211_AC_VO)
|
||||
__rtw_tx_work(rtwdev);
|
||||
else
|
||||
queue_work(rtwdev->tx_wq, &rtwdev->tx_work);
|
||||
}
|
||||
|
||||
static int rtw_ops_start(struct ieee80211_hw *hw)
|
||||
|
@ -72,6 +76,9 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
|
|||
struct rtw_dev *rtwdev = hw->priv;
|
||||
int ret = 0;
|
||||
|
||||
/* let previous ips work finish to ensure we don't leave ips twice */
|
||||
cancel_work_sync(&rtwdev->ips_work);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
rtw_leave_lps_deep(rtwdev);
|
||||
|
@ -85,20 +92,12 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
|
||||
rtw_set_channel(rtwdev);
|
||||
|
||||
if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
|
||||
(hw->conf.flags & IEEE80211_CONF_IDLE))
|
||||
(hw->conf.flags & IEEE80211_CONF_IDLE) &&
|
||||
!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
|
||||
rtw_enter_ips(rtwdev);
|
||||
|
||||
out:
|
||||
|
@ -151,25 +150,32 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
|
|||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
enum rtw_net_type net_type;
|
||||
u32 config = 0;
|
||||
u8 port = 0;
|
||||
u8 port;
|
||||
u8 bcn_ctrl = 0;
|
||||
|
||||
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER))
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
rtwvif->port = port;
|
||||
rtwvif->stats.tx_unicast = 0;
|
||||
rtwvif->stats.rx_unicast = 0;
|
||||
rtwvif->stats.tx_cnt = 0;
|
||||
rtwvif->stats.rx_cnt = 0;
|
||||
rtwvif->scan_req = NULL;
|
||||
memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee));
|
||||
rtwvif->conf = &rtw_vif_port[port];
|
||||
rtw_txq_init(rtwdev, vif->txq);
|
||||
INIT_LIST_HEAD(&rtwvif->rsvd_page_list);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
port = find_first_zero_bit(rtwdev->hw_port, RTW_PORT_NUM);
|
||||
if (port >= RTW_PORT_NUM) {
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
set_bit(port, rtwdev->hw_port);
|
||||
|
||||
rtwvif->port = port;
|
||||
rtwvif->conf = &rtw_vif_port[port];
|
||||
rtw_leave_lps_deep(rtwdev);
|
||||
|
||||
switch (vif->type) {
|
||||
|
@ -191,6 +197,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
|
|||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
clear_bit(rtwvif->port, rtwdev->hw_port);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -202,10 +209,12 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
|
|||
rtwvif->bcn_ctrl = bcn_ctrl;
|
||||
config |= PORT_SET_BCN_CTRL;
|
||||
rtw_vif_port_config(rtwdev, rtwvif, config);
|
||||
rtw_core_port_switch(rtwdev, vif);
|
||||
rtw_recalc_lps(rtwdev, vif);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
|
||||
rtw_dbg(rtwdev, RTW_DBG_STATE, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -216,7 +225,7 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
|
|||
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);
|
||||
rtw_dbg(rtwdev, RTW_DBG_STATE, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
|
@ -232,6 +241,8 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw,
|
|||
rtwvif->bcn_ctrl = 0;
|
||||
config |= PORT_SET_BCN_CTRL;
|
||||
rtw_vif_port_config(rtwdev, rtwvif, config);
|
||||
clear_bit(rtwvif->port, rtwdev->hw_port);
|
||||
rtw_recalc_lps(rtwdev, NULL);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
@ -242,8 +253,8 @@ static int rtw_ops_change_interface(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
rtw_info(rtwdev, "change vif %pM (%d)->(%d), p2p (%d)->(%d)\n",
|
||||
vif->addr, vif->type, type, vif->p2p, p2p);
|
||||
rtw_dbg(rtwdev, RTW_DBG_STATE, "change vif %pM (%d)->(%d), p2p (%d)->(%d)\n",
|
||||
vif->addr, vif->type, type, vif->p2p, p2p);
|
||||
|
||||
rtw_ops_remove_interface(hw, vif);
|
||||
|
||||
|
@ -352,7 +363,7 @@ static void rtw_conf_tx(struct rtw_dev *rtwdev,
|
|||
static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *conf,
|
||||
u32 changed)
|
||||
u64 changed)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
|
@ -366,15 +377,15 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
rtw_vif_assoc_changed(rtwvif, conf);
|
||||
if (conf->assoc) {
|
||||
if (vif->cfg.assoc) {
|
||||
rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH);
|
||||
|
||||
rtw_fw_download_rsvd_page(rtwdev);
|
||||
rtw_send_rsvd_page_h2c(rtwdev);
|
||||
rtw_coex_media_status_notify(rtwdev, conf->assoc);
|
||||
rtw_fw_default_port(rtwdev, rtwvif);
|
||||
rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc);
|
||||
if (rtw_bf_support)
|
||||
rtw_bf_assoc(rtwdev, vif, conf);
|
||||
rtw_store_op_chan(rtwdev);
|
||||
} else {
|
||||
rtw_leave_lps(rtwdev);
|
||||
rtw_bf_disassoc(rtwdev, vif, conf);
|
||||
|
@ -382,7 +393,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
* when disconnected by peer
|
||||
*/
|
||||
if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
|
||||
rtw_hw_scan_abort(rtwdev, vif);
|
||||
rtw_hw_scan_abort(rtwdev);
|
||||
|
||||
}
|
||||
|
||||
config |= PORT_SET_NET_TYPE;
|
||||
|
@ -392,6 +404,10 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
if (changed & BSS_CHANGED_BSSID) {
|
||||
ether_addr_copy(rtwvif->bssid, conf->bssid);
|
||||
config |= PORT_SET_BSSID;
|
||||
if (!rtw_core_check_sta_active(rtwdev))
|
||||
rtw_clear_op_chan(rtwdev);
|
||||
else
|
||||
rtw_store_op_chan(rtwdev, true);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_INT) {
|
||||
|
@ -399,8 +415,11 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
coex_stat->wl_beacon_interval = conf->beacon_int;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON)
|
||||
if (changed & BSS_CHANGED_BEACON) {
|
||||
rtw_set_dtim_period(rtwdev, conf->dtim_period);
|
||||
rtw_fw_download_rsvd_page(rtwdev);
|
||||
rtw_send_rsvd_page_h2c(rtwdev);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (conf->enable_beacon)
|
||||
|
@ -419,13 +438,48 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
|
|||
if (changed & BSS_CHANGED_ERP_SLOT)
|
||||
rtw_conf_tx(rtwdev, rtwvif);
|
||||
|
||||
if (changed & BSS_CHANGED_PS)
|
||||
rtw_recalc_lps(rtwdev, NULL);
|
||||
|
||||
rtw_vif_port_config(rtwdev, rtwvif, config);
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static int rtw_ops_start_ap(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD);
|
||||
rtwdev->ap_active = true;
|
||||
rtw_store_op_chan(rtwdev, true);
|
||||
chip->ops->phy_calibration(rtwdev);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_ops_stop_ap(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_write32_clr(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD);
|
||||
rtwdev->ap_active = false;
|
||||
if (!rtw_core_check_sta_active(rtwdev))
|
||||
rtw_clear_op_chan(rtwdev);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static int rtw_ops_conf_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u16 ac,
|
||||
struct ieee80211_vif *vif,
|
||||
unsigned int link_id, u16 ac,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
@ -463,14 +517,24 @@ static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
rtw_fw_beacon_filter_config(rtwdev, false, vif);
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_fw_beacon_filter_config(rtwdev, false, vif);
|
||||
rtw_sta_remove(rtwdev, sta, true);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtw_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||
bool set)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
ieee80211_queue_work(hw, &rtwdev->update_beacon_work);
|
||||
|
||||
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)
|
||||
|
@ -614,7 +678,7 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
|
|||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_core_scan_complete(rtwdev, vif);
|
||||
rtw_core_scan_complete(rtwdev, vif, false);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
|
@ -691,7 +755,7 @@ static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
|
|||
}
|
||||
|
||||
si->use_cfg_mask = true;
|
||||
rtw_update_sta_info(br_data->rtwdev, si);
|
||||
rtw_update_sta_info(br_data->rtwdev, si, true);
|
||||
}
|
||||
|
||||
static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev,
|
||||
|
@ -703,7 +767,7 @@ static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev,
|
|||
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);
|
||||
rtw_iterate_stas(rtwdev, rtw_ra_mask_info_update_iter, &br_data);
|
||||
}
|
||||
|
||||
static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw,
|
||||
|
@ -712,7 +776,9 @@ static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_ra_mask_info_update(rtwdev, vif, mask);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -722,7 +788,7 @@ static int rtw_ops_set_antenna(struct ieee80211_hw *hw,
|
|||
u32 rx_antenna)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
int ret;
|
||||
|
||||
if (!chip->ops->set_antenna)
|
||||
|
@ -813,7 +879,7 @@ static int rtw_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
rtw_hw_scan_start(rtwdev, vif, req);
|
||||
ret = rtw_hw_scan_offload(rtwdev, vif, true);
|
||||
if (ret) {
|
||||
rtw_hw_scan_abort(rtwdev, vif);
|
||||
rtw_hw_scan_abort(rtwdev);
|
||||
rtw_err(rtwdev, "HW scan failed with status: %d\n", ret);
|
||||
}
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
@ -833,7 +899,7 @@ static void rtw_ops_cancel_hw_scan(struct ieee80211_hw *hw,
|
|||
return;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_hw_scan_abort(rtwdev, vif);
|
||||
rtw_hw_scan_abort(rtwdev);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
|
@ -842,11 +908,24 @@ static int rtw_ops_set_sar_specs(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_set_sar_specs(rtwdev, sar);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_ops_sta_rc_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u32 changed)
|
||||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
|
||||
|
||||
if (changed & IEEE80211_RC_BW_CHANGED)
|
||||
ieee80211_queue_work(rtwdev->hw, &si->rc_work);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops rtw_ops = {
|
||||
.tx = rtw_ops_tx,
|
||||
.wake_tx_queue = rtw_ops_wake_tx_queue,
|
||||
|
@ -858,9 +937,12 @@ const struct ieee80211_ops rtw_ops = {
|
|||
.change_interface = rtw_ops_change_interface,
|
||||
.configure_filter = rtw_ops_configure_filter,
|
||||
.bss_info_changed = rtw_ops_bss_info_changed,
|
||||
.start_ap = rtw_ops_start_ap,
|
||||
.stop_ap = rtw_ops_stop_ap,
|
||||
.conf_tx = rtw_ops_conf_tx,
|
||||
.sta_add = rtw_ops_sta_add,
|
||||
.sta_remove = rtw_ops_sta_remove,
|
||||
.set_tim = rtw_ops_set_tim,
|
||||
.set_key = rtw_ops_set_key,
|
||||
.ampdu_action = rtw_ops_ampdu_action,
|
||||
.can_aggregate_in_amsdu = rtw_ops_can_aggregate_in_amsdu,
|
||||
|
@ -876,6 +958,7 @@ const struct ieee80211_ops rtw_ops = {
|
|||
.reconfig_complete = rtw_reconfig_complete,
|
||||
.hw_scan = rtw_ops_hw_scan,
|
||||
.cancel_hw_scan = rtw_ops_cancel_hw_scan,
|
||||
.sta_rc_update = rtw_ops_sta_rc_update,
|
||||
.set_sar_specs = rtw_ops_set_sar_specs,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = rtw_ops_suspend,
|
||||
|
|
148
main.h
148
main.h
|
@ -17,13 +17,11 @@
|
|||
|
||||
#include "util.h"
|
||||
|
||||
#define RTW_NAPI_WEIGHT_NUM 64
|
||||
#define RTW_MAX_MAC_ID_NUM 32
|
||||
#define RTW_MAX_SEC_CAM_NUM 32
|
||||
#define MAX_PG_CAM_BACKUP_NUM 8
|
||||
|
||||
#define RTW_SCAN_MAX_SSIDS 4
|
||||
#define RTW_SCAN_MAX_IE_LEN 128
|
||||
|
||||
#define RTW_MAX_PATTERN_NUM 12
|
||||
#define RTW_MAX_PATTERN_MASK_SIZE 16
|
||||
|
@ -34,6 +32,7 @@
|
|||
#define RFREG_MASK 0xfffff
|
||||
#define INV_RF_DATA 0xffffffff
|
||||
#define TX_PAGE_SIZE_SHIFT 7
|
||||
#define TX_PAGE_SIZE (1 << TX_PAGE_SIZE_SHIFT)
|
||||
|
||||
#define RTW_CHANNEL_WIDTH_MAX 3
|
||||
#define RTW_RF_PATH_MAX 4
|
||||
|
@ -89,7 +88,7 @@ enum rtw_supported_band {
|
|||
RTW_BAND_60G = BIT(NL80211_BAND_60GHZ),
|
||||
};
|
||||
|
||||
/* now, support upto 80M bw */
|
||||
/* now, support up to 80M bw */
|
||||
#define RTW_MAX_CHANNEL_WIDTH RTW_CHANNEL_WIDTH_80
|
||||
|
||||
enum rtw_bandwidth {
|
||||
|
@ -357,7 +356,7 @@ enum rtw_flags {
|
|||
RTW_FLAG_RUNNING,
|
||||
RTW_FLAG_FW_RUNNING,
|
||||
RTW_FLAG_SCANNING,
|
||||
RTW_FLAG_INACTIVE_PS,
|
||||
RTW_FLAG_POWERON,
|
||||
RTW_FLAG_LEISURE_PS,
|
||||
RTW_FLAG_LEISURE_PS_DEEP,
|
||||
RTW_FLAG_DIG_DISABLE,
|
||||
|
@ -396,6 +395,15 @@ enum rtw_snr {
|
|||
RTW_SNR_NUM
|
||||
};
|
||||
|
||||
enum rtw_port {
|
||||
RTW_PORT_0 = 0,
|
||||
RTW_PORT_1 = 1,
|
||||
RTW_PORT_2 = 2,
|
||||
RTW_PORT_3 = 3,
|
||||
RTW_PORT_4 = 4,
|
||||
RTW_PORT_NUM
|
||||
};
|
||||
|
||||
enum rtw_wow_flags {
|
||||
RTW_WOW_FLAG_EN_MAGIC_PKT,
|
||||
RTW_WOW_FLAG_EN_REKEY_PKT,
|
||||
|
@ -503,20 +511,10 @@ struct rtw_txpwr_idx {
|
|||
struct rtw_5g_txpwr_idx pwr_idx_5g;
|
||||
};
|
||||
|
||||
struct rtw_timer_list {
|
||||
struct timer_list timer;
|
||||
void (*function)(void *data);
|
||||
void *args;
|
||||
};
|
||||
|
||||
struct rtw_channel_params {
|
||||
u8 center_chan;
|
||||
u8 primary_chan;
|
||||
u8 bandwidth;
|
||||
u8 primary_chan_idx;
|
||||
/* center channel by different available bandwidth,
|
||||
* val of (bw > current bandwidth) is invalid
|
||||
*/
|
||||
u8 cch_by_bw[RTW_MAX_CHANNEL_WIDTH + 1];
|
||||
};
|
||||
|
||||
struct rtw_hw_reg {
|
||||
|
@ -580,6 +578,7 @@ struct rtw_tx_pkt_info {
|
|||
u32 tx_pkt_size;
|
||||
u8 offset;
|
||||
u8 pkt_offset;
|
||||
u8 tim_offset;
|
||||
u8 mac_id;
|
||||
u8 rate_id;
|
||||
u8 rate;
|
||||
|
@ -729,15 +728,14 @@ struct rtw_ra_report {
|
|||
|
||||
struct rtw_txq {
|
||||
struct list_head list;
|
||||
|
||||
unsigned long flags;
|
||||
unsigned long last_push;
|
||||
};
|
||||
|
||||
#define RTW_BC_MC_MACID 1
|
||||
DECLARE_EWMA(rssi, 10, 16);
|
||||
|
||||
struct rtw_sta_info {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
|
@ -748,12 +746,10 @@ struct rtw_sta_info {
|
|||
u8 rate_id;
|
||||
enum rtw_bandwidth bw_mode;
|
||||
enum rtw_rf_type rf_type;
|
||||
enum rtw_wireless_set wireless_set;
|
||||
u8 stbc_en:2;
|
||||
u8 ldpc_en:2;
|
||||
bool sgi_enable;
|
||||
bool vht_enable;
|
||||
bool updated;
|
||||
u8 init_ra_lv;
|
||||
u64 ra_mask;
|
||||
|
||||
|
@ -763,6 +759,8 @@ struct rtw_sta_info {
|
|||
|
||||
bool use_cfg_mask;
|
||||
struct cfg80211_bitrate_mask *mask;
|
||||
|
||||
struct work_struct rc_work;
|
||||
};
|
||||
|
||||
enum rtw_bfee_role {
|
||||
|
@ -796,6 +794,7 @@ struct rtw_bf_info {
|
|||
struct rtw_vif {
|
||||
enum rtw_net_type net_type;
|
||||
u16 aid;
|
||||
u8 mac_id; /* for STA mode only */
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 port;
|
||||
|
@ -874,6 +873,12 @@ struct rtw_chip_ops {
|
|||
enum rtw_bb_path tx_path_1ss,
|
||||
enum rtw_bb_path tx_path_cck,
|
||||
bool is_tx2_path);
|
||||
void (*config_txrx_mode)(struct rtw_dev *rtwdev, u8 tx_path,
|
||||
u8 rx_path, bool is_tx2_path);
|
||||
/* for USB/SDIO only */
|
||||
void (*fill_txdesc_checksum)(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc);
|
||||
|
||||
/* for coex */
|
||||
void (*coex_set_init)(struct rtw_dev *rtwdev);
|
||||
|
@ -1167,6 +1172,7 @@ struct rtw_chip_info {
|
|||
u32 txff_size;
|
||||
u32 rxff_size;
|
||||
u32 fw_rxff_size;
|
||||
u16 rsvd_drv_pg_num;
|
||||
u8 band;
|
||||
u8 page_size;
|
||||
u8 csi_buf_pg_num;
|
||||
|
@ -1177,6 +1183,7 @@ struct rtw_chip_info {
|
|||
bool rx_ldpc;
|
||||
bool tx_stbc;
|
||||
u8 max_power_index;
|
||||
u8 ampdu_density;
|
||||
|
||||
u16 fw_fifo_addr[RTW_FW_FIFO_MAX];
|
||||
const struct rtw_fwcd_segs *fwcd_segs;
|
||||
|
@ -1230,9 +1237,7 @@ struct rtw_chip_info {
|
|||
const char *wow_fw_name;
|
||||
const struct wiphy_wowlan_support *wowlan_stub;
|
||||
const u8 max_sched_scan_ssids;
|
||||
|
||||
/* for 8821c set channel */
|
||||
u32 ch_param[3];
|
||||
const u16 max_scan_ie_len;
|
||||
|
||||
/* coex paras */
|
||||
u32 coex_para_ver;
|
||||
|
@ -1240,6 +1245,7 @@ struct rtw_chip_info {
|
|||
bool scbd_support;
|
||||
bool new_scbd10_def; /* true: fix 2M(8822c) */
|
||||
bool ble_hid_profile_support;
|
||||
bool wl_mimo_ps_support;
|
||||
u8 pstdma_type; /* 0: LPSoff, 1:LPSon */
|
||||
u8 bt_rssi_type;
|
||||
u8 ant_isolation;
|
||||
|
@ -1352,6 +1358,42 @@ struct rtw_coex_dm {
|
|||
#define COEX_BTINFO_LENGTH_MAX 10
|
||||
#define COEX_BTINFO_LENGTH 7
|
||||
|
||||
#define COEX_BT_HIDINFO_LIST 0x0
|
||||
#define COEX_BT_HIDINFO_A 0x1
|
||||
#define COEX_BT_HIDINFO_NAME 3
|
||||
|
||||
#define COEX_BT_HIDINFO_LENGTH 6
|
||||
#define COEX_BT_HIDINFO_HANDLE_NUM 4
|
||||
#define COEX_BT_HIDINFO_C2H_HANDLE 0
|
||||
#define COEX_BT_HIDINFO_C2H_VENDOR 1
|
||||
#define COEX_BT_BLE_HANDLE_THRS 0x10
|
||||
#define COEX_BT_HIDINFO_NOTCON 0xff
|
||||
|
||||
struct rtw_coex_hid {
|
||||
u8 hid_handle;
|
||||
u8 hid_vendor;
|
||||
u8 hid_name[COEX_BT_HIDINFO_NAME];
|
||||
bool hid_info_completed;
|
||||
bool is_game_hid;
|
||||
};
|
||||
|
||||
struct rtw_coex_hid_handle_list {
|
||||
u8 cmd_id;
|
||||
u8 len;
|
||||
u8 subid;
|
||||
u8 handle_cnt;
|
||||
u8 handle[COEX_BT_HIDINFO_HANDLE_NUM];
|
||||
} __packed;
|
||||
|
||||
struct rtw_coex_hid_info_a {
|
||||
u8 cmd_id;
|
||||
u8 len;
|
||||
u8 subid;
|
||||
u8 handle;
|
||||
u8 vendor;
|
||||
u8 name[COEX_BT_HIDINFO_NAME];
|
||||
} __packed;
|
||||
|
||||
struct rtw_coex_stat {
|
||||
bool bt_disabled;
|
||||
bool bt_disabled_pre;
|
||||
|
@ -1382,6 +1424,8 @@ struct rtw_coex_stat {
|
|||
bool bt_slave;
|
||||
bool bt_418_hid_exist;
|
||||
bool bt_ble_hid_exist;
|
||||
bool bt_game_hid_exist;
|
||||
bool bt_hid_handle_cnt;
|
||||
bool bt_mailbox_reply;
|
||||
|
||||
bool wl_under_lps;
|
||||
|
@ -1402,6 +1446,7 @@ struct rtw_coex_stat {
|
|||
bool wl_connecting;
|
||||
bool wl_slot_toggle;
|
||||
bool wl_slot_toggle_change; /* if toggle to no-toggle */
|
||||
bool wl_mimo_ps;
|
||||
|
||||
u32 bt_supported_version;
|
||||
u32 bt_supported_feature;
|
||||
|
@ -1459,11 +1504,12 @@ struct rtw_coex_stat {
|
|||
|
||||
u32 darfrc;
|
||||
u32 darfrch;
|
||||
|
||||
struct rtw_coex_hid hid_info[COEX_BT_HIDINFO_HANDLE_NUM];
|
||||
struct rtw_coex_hid_handle_list hid_handle_list;
|
||||
};
|
||||
|
||||
struct rtw_coex {
|
||||
/* protects coex info request section */
|
||||
struct mutex mutex;
|
||||
struct sk_buff_head queue;
|
||||
wait_queue_head_t wait;
|
||||
|
||||
|
@ -1811,6 +1857,8 @@ struct rtw_fw_state {
|
|||
u8 sub_index;
|
||||
u16 h2c_version;
|
||||
u32 feature;
|
||||
u32 feature_ext;
|
||||
enum rtw_fw_type type;
|
||||
};
|
||||
|
||||
enum rtw_sar_sources {
|
||||
|
@ -1828,7 +1876,7 @@ enum rtw_sar_bands {
|
|||
RTW_SAR_BAND_NR,
|
||||
};
|
||||
|
||||
/* the union is reserved for other knids of SAR sources
|
||||
/* the union is reserved for other kinds of SAR sources
|
||||
* which might not re-use same format with array common.
|
||||
*/
|
||||
union rtw_sar_cfg {
|
||||
|
@ -1847,13 +1895,16 @@ struct rtw_hal {
|
|||
u8 cut_version;
|
||||
u8 mp_chip;
|
||||
u8 oem_id;
|
||||
u8 pkg_type;
|
||||
struct rtw_phy_cond phy_cond;
|
||||
bool rfe_btg;
|
||||
|
||||
u8 ps_mode;
|
||||
u8 current_channel;
|
||||
u8 current_primary_channel_index;
|
||||
u8 current_band_width;
|
||||
u8 current_band_type;
|
||||
u8 primary_channel;
|
||||
|
||||
/* center channel for different available bandwidth,
|
||||
* val of (bw > current_band_width) is invalid
|
||||
|
@ -1867,6 +1918,7 @@ struct rtw_hal {
|
|||
u32 antenna_tx;
|
||||
u32 antenna_rx;
|
||||
u8 bfee_sts_cap;
|
||||
bool txrx_1ss;
|
||||
|
||||
/* protect tx power section */
|
||||
struct mutex tx_power_mutex;
|
||||
|
@ -1891,6 +1943,9 @@ struct rtw_hal {
|
|||
|
||||
enum rtw_sar_bands sar_band;
|
||||
struct rtw_sar sar;
|
||||
|
||||
/* for 8821c set channel */
|
||||
u32 ch_param[3];
|
||||
};
|
||||
|
||||
struct rtw_path_div {
|
||||
|
@ -1921,6 +1976,7 @@ struct rtw_hw_scan_info {
|
|||
struct ieee80211_vif *scanning_vif;
|
||||
u8 probe_pg_size;
|
||||
u8 op_pri_ch_idx;
|
||||
u8 op_pri_ch;
|
||||
u8 op_chan;
|
||||
u8 op_bw;
|
||||
};
|
||||
|
@ -1932,7 +1988,7 @@ struct rtw_dev {
|
|||
struct rtw_hci hci;
|
||||
|
||||
struct rtw_hw_scan_info scan_info;
|
||||
struct rtw_chip_info *chip;
|
||||
const struct rtw_chip_info *chip;
|
||||
struct rtw_hal hal;
|
||||
struct rtw_fifo_conf fifo;
|
||||
struct rtw_fw_state fw;
|
||||
|
@ -1948,9 +2004,6 @@ struct rtw_dev {
|
|||
/* ensures exclusive access from mac80211 callbacks */
|
||||
struct mutex mutex;
|
||||
|
||||
/* read/write rf register */
|
||||
spinlock_t rf_lock;
|
||||
|
||||
/* watch dog every 2 sec */
|
||||
struct delayed_work watch_dog_work;
|
||||
u32 watch_dog_cnt;
|
||||
|
@ -1960,7 +2013,9 @@ struct rtw_dev {
|
|||
/* c2h cmd queue & handler work */
|
||||
struct sk_buff_head c2h_queue;
|
||||
struct work_struct c2h_work;
|
||||
struct work_struct ips_work;
|
||||
struct work_struct fw_recovery_work;
|
||||
struct work_struct update_beacon_work;
|
||||
|
||||
/* used to protect txqs list */
|
||||
spinlock_t txq_lock;
|
||||
|
@ -1972,10 +2027,8 @@ struct rtw_dev {
|
|||
struct rtw_tx_report tx_report;
|
||||
|
||||
struct {
|
||||
/* incicate the mail box to use with fw */
|
||||
/* indicate the mail box to use with fw */
|
||||
u8 last_box_num;
|
||||
/* protect to send h2c to fw */
|
||||
spinlock_t lock;
|
||||
u32 seq;
|
||||
} h2c;
|
||||
|
||||
|
@ -1990,6 +2043,7 @@ struct rtw_dev {
|
|||
u8 sta_cnt;
|
||||
u32 rts_threshold;
|
||||
|
||||
DECLARE_BITMAP(hw_port, RTW_PORT_NUM);
|
||||
DECLARE_BITMAP(mac_id_map, RTW_MAX_MAC_ID_NUM);
|
||||
DECLARE_BITMAP(flags, NUM_OF_RTW_FLAGS);
|
||||
|
||||
|
@ -2001,6 +2055,7 @@ struct rtw_dev {
|
|||
|
||||
bool need_rfk;
|
||||
struct completion fw_scan_density;
|
||||
bool ap_active;
|
||||
|
||||
/* hci related data, must be last */
|
||||
u8 priv[] __aligned(sizeof(void *));
|
||||
|
@ -2084,7 +2139,22 @@ static inline int rtw_chip_dump_fw_crash(struct rtw_dev *rtwdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
enum nl80211_band rtw_hw_to_nl80211_band(enum rtw_supported_band hw_band)
|
||||
{
|
||||
switch (hw_band) {
|
||||
default:
|
||||
case RTW_BAND_2G:
|
||||
return NL80211_BAND_2GHZ;
|
||||
case RTW_BAND_5G:
|
||||
return NL80211_BAND_5GHZ;
|
||||
case RTW_BAND_60G:
|
||||
return NL80211_BAND_60GHZ;
|
||||
}
|
||||
}
|
||||
|
||||
void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel);
|
||||
void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period);
|
||||
void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
|
||||
struct rtw_channel_params *ch_param);
|
||||
bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target);
|
||||
|
@ -2098,10 +2168,12 @@ void rtw_chip_prepare_tx(struct rtw_dev *rtwdev);
|
|||
void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
|
||||
u32 config);
|
||||
void rtw_tx_report_purge_timer(struct timer_list *t);
|
||||
void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
|
||||
void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
|
||||
bool reset_ra_mask);
|
||||
void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
|
||||
const u8 *mac_addr, bool hw_scan);
|
||||
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
|
||||
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
||||
bool hw_scan);
|
||||
int rtw_core_start(struct rtw_dev *rtwdev);
|
||||
void rtw_core_stop(struct rtw_dev *rtwdev);
|
||||
int rtw_chip_info_setup(struct rtw_dev *rtwdev);
|
||||
|
@ -2121,5 +2193,11 @@ void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
|
|||
int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size,
|
||||
u32 fwcd_item);
|
||||
int rtw_dump_reg(struct rtw_dev *rtwdev, const u32 addr, const u32 size);
|
||||
|
||||
void rtw_set_txrx_1ss(struct rtw_dev *rtwdev, bool config_1ss);
|
||||
void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel,
|
||||
u8 primary_channel, enum rtw_supported_band band,
|
||||
enum rtw_bandwidth bandwidth);
|
||||
void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif);
|
||||
bool rtw_core_check_sta_active(struct rtw_dev *rtwdev);
|
||||
void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable);
|
||||
#endif
|
||||
|
|
97
pci.c
97
pci.c
|
@ -30,7 +30,8 @@ static u32 rtw_pci_tx_queue_idx_addr[] = {
|
|||
[RTW_TX_QUEUE_H2C] = RTK_PCI_TXBD_IDX_H2CQ,
|
||||
};
|
||||
|
||||
static u8 rtw_pci_get_tx_qsel(struct sk_buff *skb, u8 queue)
|
||||
static u8 rtw_pci_get_tx_qsel(struct sk_buff *skb,
|
||||
enum rtw_tx_queue_type queue)
|
||||
{
|
||||
switch (queue) {
|
||||
case RTW_TX_QUEUE_BCN:
|
||||
|
@ -88,13 +89,6 @@ static void rtw_pci_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
|
|||
writel(val, rtwpci->mmap + addr);
|
||||
}
|
||||
|
||||
static inline void *rtw_pci_get_tx_desc(struct rtw_pci_tx_ring *tx_ring, u8 idx)
|
||||
{
|
||||
int offset = tx_ring->r.desc_size * idx;
|
||||
|
||||
return tx_ring->r.head + offset;
|
||||
}
|
||||
|
||||
static void rtw_pci_free_tx_ring_skbs(struct rtw_dev *rtwdev,
|
||||
struct rtw_pci_tx_ring *tx_ring)
|
||||
{
|
||||
|
@ -322,7 +316,7 @@ static int rtw_pci_init_trx_ring(struct rtw_dev *rtwdev)
|
|||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
struct rtw_pci_tx_ring *tx_ring;
|
||||
struct rtw_pci_rx_ring *rx_ring;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
int i = 0, j = 0, tx_alloced = 0, rx_alloced = 0;
|
||||
int tx_desc_size, rx_desc_size;
|
||||
u32 len;
|
||||
|
@ -542,7 +536,7 @@ static int rtw_pci_setup(struct rtw_dev *rtwdev)
|
|||
static void rtw_pci_dma_release(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci)
|
||||
{
|
||||
struct rtw_pci_tx_ring *tx_ring;
|
||||
u8 queue;
|
||||
enum rtw_tx_queue_type queue;
|
||||
|
||||
rtw_pci_reset_trx_ring(rtwdev);
|
||||
for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) {
|
||||
|
@ -608,8 +602,8 @@ static void rtw_pci_deep_ps_enter(struct rtw_dev *rtwdev)
|
|||
{
|
||||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
struct rtw_pci_tx_ring *tx_ring;
|
||||
enum rtw_tx_queue_type queue;
|
||||
bool tx_empty = true;
|
||||
u8 queue;
|
||||
|
||||
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_TX_WAKE))
|
||||
goto enter_deep_ps;
|
||||
|
@ -669,34 +663,6 @@ static void rtw_pci_deep_ps(struct rtw_dev *rtwdev, bool enter)
|
|||
spin_unlock_bh(&rtwpci->irq_lock);
|
||||
}
|
||||
|
||||
static u8 ac_to_hwq[] = {
|
||||
[IEEE80211_AC_VO] = RTW_TX_QUEUE_VO,
|
||||
[IEEE80211_AC_VI] = RTW_TX_QUEUE_VI,
|
||||
[IEEE80211_AC_BE] = RTW_TX_QUEUE_BE,
|
||||
[IEEE80211_AC_BK] = RTW_TX_QUEUE_BK,
|
||||
};
|
||||
|
||||
static_assert(ARRAY_SIZE(ac_to_hwq) == IEEE80211_NUM_ACS);
|
||||
|
||||
static u8 rtw_hw_queue_mapping(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 q_mapping = skb_get_queue_mapping(skb);
|
||||
u8 queue;
|
||||
|
||||
if (unlikely(ieee80211_is_beacon(fc)))
|
||||
queue = RTW_TX_QUEUE_BCN;
|
||||
else if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
|
||||
queue = RTW_TX_QUEUE_MGMT;
|
||||
else if (WARN_ON_ONCE(q_mapping >= ARRAY_SIZE(ac_to_hwq)))
|
||||
queue = ac_to_hwq[IEEE80211_AC_BE];
|
||||
else
|
||||
queue = ac_to_hwq[q_mapping];
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
static void rtw_pci_release_rsvd_page(struct rtw_pci *rtwpci,
|
||||
struct rtw_pci_tx_ring *ring)
|
||||
{
|
||||
|
@ -718,7 +684,7 @@ static void rtw_pci_dma_check(struct rtw_dev *rtwdev,
|
|||
u32 idx)
|
||||
{
|
||||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_pci_rx_buffer_desc *buf_desc;
|
||||
u32 desc_sz = chip->rx_buf_desc_sz;
|
||||
u16 total_pkt_size;
|
||||
|
@ -772,8 +738,9 @@ static void __rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 pci_queues,
|
|||
u8 q;
|
||||
|
||||
for (q = 0; q < RTK_MAX_TX_QUEUE_NUM; q++) {
|
||||
/* It may be not necessary to flush BCN and H2C tx queues. */
|
||||
if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C)
|
||||
/* Unnecessary to flush BCN, H2C and HI tx queues. */
|
||||
if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C ||
|
||||
q == RTW_TX_QUEUE_HI0)
|
||||
continue;
|
||||
|
||||
if (pci_queues & BIT(q))
|
||||
|
@ -794,13 +761,14 @@ static void rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop)
|
|||
} else {
|
||||
for (i = 0; i < rtwdev->hw->queues; i++)
|
||||
if (queues & BIT(i))
|
||||
pci_queues |= BIT(ac_to_hwq[i]);
|
||||
pci_queues |= BIT(rtw_tx_ac_to_hwq(i));
|
||||
}
|
||||
|
||||
__rtw_pci_flush_queues(rtwdev, pci_queues, drop);
|
||||
}
|
||||
|
||||
static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, u8 queue)
|
||||
static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev,
|
||||
enum rtw_tx_queue_type queue)
|
||||
{
|
||||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
struct rtw_pci_tx_ring *ring;
|
||||
|
@ -819,7 +787,7 @@ static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, u8 queue)
|
|||
static void rtw_pci_tx_kick_off(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
u8 queue;
|
||||
enum rtw_tx_queue_type queue;
|
||||
|
||||
for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++)
|
||||
if (test_and_clear_bit(queue, rtwpci->tx_queued))
|
||||
|
@ -828,10 +796,11 @@ static void rtw_pci_tx_kick_off(struct rtw_dev *rtwdev)
|
|||
|
||||
static int rtw_pci_tx_write_data(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
struct sk_buff *skb, u8 queue)
|
||||
struct sk_buff *skb,
|
||||
enum rtw_tx_queue_type queue)
|
||||
{
|
||||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_pci_tx_ring *ring;
|
||||
struct rtw_pci_tx_data *tx_data;
|
||||
dma_addr_t dma;
|
||||
|
@ -946,9 +915,9 @@ static int rtw_pci_tx_write(struct rtw_dev *rtwdev,
|
|||
struct rtw_tx_pkt_info *pkt_info,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
enum rtw_tx_queue_type queue = rtw_tx_queue_mapping(skb);
|
||||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
struct rtw_pci_tx_ring *ring;
|
||||
u8 queue = rtw_hw_queue_mapping(skb);
|
||||
int ret;
|
||||
|
||||
ret = rtw_pci_tx_write_data(rtwdev, pkt_info, skb, queue);
|
||||
|
@ -1070,7 +1039,7 @@ static int rtw_pci_get_hw_rx_ring_nr(struct rtw_dev *rtwdev,
|
|||
static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
|
||||
u8 hw_queue, u32 limit)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct napi_struct *napi = &rtwpci->napi;
|
||||
struct rtw_pci_rx_ring *ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU];
|
||||
struct rtw_rx_pkt_stat pkt_stat;
|
||||
|
@ -1422,7 +1391,7 @@ static void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter)
|
|||
|
||||
static void rtw_pci_link_cfg(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
struct pci_dev *pdev = rtwpci->pdev;
|
||||
u16 link_ctrl;
|
||||
|
@ -1464,7 +1433,7 @@ static void rtw_pci_link_cfg(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
switch (chip->id) {
|
||||
case RTW_CHIP_TYPE_8822C:
|
||||
|
@ -1479,12 +1448,15 @@ static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct pci_dev *pdev = rtwpci->pdev;
|
||||
const struct rtw_intf_phy_para *para;
|
||||
u16 cut;
|
||||
u16 value;
|
||||
u16 offset;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
cut = BIT(0) << rtwdev->hal.cut_version;
|
||||
|
||||
|
@ -1517,13 +1489,22 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev)
|
|||
}
|
||||
|
||||
rtw_pci_link_cfg(rtwdev);
|
||||
|
||||
/* Disable 8821ce completion timeout by default */
|
||||
if (chip->id == RTW_CHIP_TYPE_8821C) {
|
||||
ret = pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2,
|
||||
PCI_EXP_DEVCTL2_COMP_TMOUT_DIS);
|
||||
if (ret)
|
||||
rtw_err(rtwdev, "failed to set PCI cap, ret = %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
static int __maybe_unused rtw_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = dev_get_drvdata(dev);
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
||||
if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6)
|
||||
|
@ -1535,7 +1516,7 @@ static int __maybe_unused rtw_pci_resume(struct device *dev)
|
|||
{
|
||||
struct ieee80211_hw *hw = dev_get_drvdata(dev);
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
||||
if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6)
|
||||
|
@ -1565,7 +1546,6 @@ static int rtw_pci_claim(struct rtw_dev *rtwdev, struct pci_dev *pdev)
|
|||
|
||||
static void rtw_pci_declaim(struct rtw_dev *rtwdev, struct pci_dev *pdev)
|
||||
{
|
||||
pci_clear_master(pdev);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
|
@ -1702,8 +1682,7 @@ static void rtw_pci_napi_init(struct rtw_dev *rtwdev)
|
|||
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
|
||||
|
||||
init_dummy_netdev(&rtwpci->netdev);
|
||||
netif_napi_add(&rtwpci->netdev, &rtwpci->napi, rtw_pci_napi_poll,
|
||||
RTW_NAPI_WEIGHT_NUM);
|
||||
netif_napi_add(&rtwpci->netdev, &rtwpci->napi, rtw_pci_napi_poll);
|
||||
}
|
||||
|
||||
static void rtw_pci_napi_deinit(struct rtw_dev *rtwdev)
|
||||
|
@ -1770,7 +1749,7 @@ int rtw_pci_probe(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
/* Disable PCIe ASPM L1 while doing NAPI poll for 8821CE */
|
||||
if (pdev->device == 0xc821 && bridge->vendor == PCI_VENDOR_ID_INTEL)
|
||||
if (rtwdev->chip->id == RTW_CHIP_TYPE_8821C && bridge->vendor == PCI_VENDOR_ID_INTEL)
|
||||
rtwpci->rx_no_aspm = true;
|
||||
|
||||
rtw_pci_phy_cfg(rtwdev);
|
||||
|
@ -1833,7 +1812,7 @@ void rtw_pci_shutdown(struct pci_dev *pdev)
|
|||
{
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct rtw_dev *rtwdev;
|
||||
struct rtw_chip_info *chip;
|
||||
const struct rtw_chip_info *chip;
|
||||
|
||||
if (!hw)
|
||||
return;
|
||||
|
|
73
phy.c
73
phy.c
|
@ -138,7 +138,7 @@ EXPORT_SYMBOL(rtw_phy_set_edcca_th);
|
|||
|
||||
void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
|
||||
/* turn off in debugfs for debug usage */
|
||||
|
@ -165,7 +165,7 @@ void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_phy_adaptivity_init(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
rtw_phy_adaptivity_set_mode(rtwdev);
|
||||
if (chip->ops->adaptivity_init)
|
||||
|
@ -180,7 +180,7 @@ static void rtw_phy_adaptivity(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_phy_cfo_init(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->ops->cfo_init)
|
||||
chip->ops->cfo_init(rtwdev);
|
||||
|
@ -199,7 +199,7 @@ static void rtw_phy_tx_path_div_init(struct rtw_dev *rtwdev)
|
|||
|
||||
void rtw_phy_init(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
u32 addr, mask;
|
||||
|
||||
|
@ -226,7 +226,7 @@ EXPORT_SYMBOL(rtw_phy_init);
|
|||
|
||||
void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
u32 addr, mask;
|
||||
u8 path;
|
||||
|
@ -245,7 +245,7 @@ void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi)
|
|||
|
||||
static void rtw_phy_stat_false_alarm(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->false_alarm_statistics(rtwdev);
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ static void rtw_phy_stat_rssi(struct rtw_dev *rtwdev)
|
|||
|
||||
data.rtwdev = rtwdev;
|
||||
data.min_rssi = U8_MAX;
|
||||
rtw_iterate_stas_atomic(rtwdev, rtw_phy_stat_rssi_iter, &data);
|
||||
rtw_iterate_stas(rtwdev, rtw_phy_stat_rssi_iter, &data);
|
||||
|
||||
dm_info->pre_min_rssi = dm_info->min_rssi;
|
||||
dm_info->min_rssi = data.min_rssi;
|
||||
|
@ -536,7 +536,7 @@ static void rtw_phy_ra_info_update_iter(void *data, struct ieee80211_sta *sta)
|
|||
struct rtw_dev *rtwdev = data;
|
||||
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
|
||||
|
||||
rtw_update_sta_info(rtwdev, si);
|
||||
rtw_update_sta_info(rtwdev, si, false);
|
||||
}
|
||||
|
||||
static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev)
|
||||
|
@ -544,7 +544,7 @@ static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev)
|
|||
if (rtwdev->watch_dog_cnt & 0x3)
|
||||
return;
|
||||
|
||||
rtw_iterate_stas_atomic(rtwdev, rtw_phy_ra_info_update_iter, rtwdev);
|
||||
rtw_iterate_stas(rtwdev, rtw_phy_ra_info_update_iter, rtwdev);
|
||||
}
|
||||
|
||||
static u32 rtw_phy_get_rrsr_mask(struct rtw_dev *rtwdev, u8 rate_idx)
|
||||
|
@ -597,13 +597,13 @@ static void rtw_phy_rrsr_update(struct rtw_dev *rtwdev)
|
|||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
|
||||
dm_info->rrsr_mask_min = RRSR_RATE_ORDER_MAX;
|
||||
rtw_iterate_stas_atomic(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev);
|
||||
rtw_iterate_stas(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev);
|
||||
rtw_write32(rtwdev, REG_RRSR, dm_info->rrsr_val_init & dm_info->rrsr_mask_min);
|
||||
}
|
||||
|
||||
static void rtw_phy_dpk_track(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->ops->dpk_track)
|
||||
chip->ops->dpk_track(rtwdev);
|
||||
|
@ -659,7 +659,7 @@ EXPORT_SYMBOL(rtw_phy_parsing_cfo);
|
|||
|
||||
static void rtw_phy_cfo_track(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (chip->ops->cfo_track)
|
||||
chip->ops->cfo_track(rtwdev);
|
||||
|
@ -720,8 +720,8 @@ static u8 rtw_phy_cck_pd_lv(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw_phy_cck_pd(struct rtw_dev *rtwdev)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u32 cck_fa = dm_info->cck_fa_cnt;
|
||||
u8 level;
|
||||
|
||||
|
@ -816,23 +816,18 @@ static u8 rtw_phy_linear_2_db(u64 linear)
|
|||
u8 j;
|
||||
u32 dB;
|
||||
|
||||
if (linear >= db_invert_table[11][7])
|
||||
return 96; /* maximum 96 dB */
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][7])
|
||||
break;
|
||||
else if (i > 2 && linear <= db_invert_table[i][7])
|
||||
break;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j])
|
||||
goto cnt;
|
||||
else if (i > 2 && linear <= db_invert_table[i][j])
|
||||
goto cnt;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j])
|
||||
break;
|
||||
else if (i > 2 && linear <= db_invert_table[i][j])
|
||||
break;
|
||||
}
|
||||
return 96; /* maximum 96 dB */
|
||||
|
||||
cnt:
|
||||
if (j == 0 && i == 0)
|
||||
goto end;
|
||||
|
||||
|
@ -900,7 +895,7 @@ u32 rtw_phy_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
|||
u32 addr, u32 mask)
|
||||
{
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const u32 *base_addr = chip->rf_base_addr;
|
||||
u32 val, direct_addr;
|
||||
|
||||
|
@ -923,7 +918,7 @@ u32 rtw_phy_read_rf_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
|||
u32 addr, u32 mask)
|
||||
{
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_rf_sipi_addr *rf_sipi_addr;
|
||||
const struct rtw_rf_sipi_addr *rf_sipi_addr_a;
|
||||
u32 val32;
|
||||
|
@ -972,8 +967,8 @@ bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
|||
u32 addr, u32 mask, u32 data)
|
||||
{
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u32 *sipi_addr = chip->rf_sipi_addr;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const u32 *sipi_addr = chip->rf_sipi_addr;
|
||||
u32 data_and_addr;
|
||||
u32 old_data = 0;
|
||||
u32 shift;
|
||||
|
@ -1012,7 +1007,7 @@ bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
|||
u32 addr, u32 mask, u32 data)
|
||||
{
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const u32 *base_addr = chip->rf_base_addr;
|
||||
u32 direct_addr;
|
||||
|
||||
|
@ -1747,7 +1742,7 @@ EXPORT_SYMBOL(rtw_phy_cfg_rf);
|
|||
|
||||
static void rtw_load_rfk_table(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info;
|
||||
|
||||
if (!chip->rfk_init_tbl)
|
||||
|
@ -1766,7 +1761,7 @@ static void rtw_load_rfk_table(struct rtw_dev *rtwdev)
|
|||
|
||||
void rtw_phy_load_tables(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 rf_path;
|
||||
|
||||
rtw_load_table(rtwdev, chip->mac_tbl);
|
||||
|
@ -1875,7 +1870,7 @@ static u8 rtw_get_channel_group(u8 channel, u8 rate)
|
|||
|
||||
static s8 rtw_phy_get_dis_dpd_by_rate_diff(struct rtw_dev *rtwdev, u16 rate)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
s8 dpd_diff = 0;
|
||||
|
||||
if (!chip->en_dis_dpd)
|
||||
|
@ -1909,7 +1904,7 @@ static u8 rtw_phy_get_2g_tx_power_index(struct rtw_dev *rtwdev,
|
|||
enum rtw_bandwidth bandwidth,
|
||||
u8 rate, u8 group)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 tx_power;
|
||||
bool mcs_rate;
|
||||
bool above_2ss;
|
||||
|
@ -1956,7 +1951,7 @@ static u8 rtw_phy_get_5g_tx_power_index(struct rtw_dev *rtwdev,
|
|||
enum rtw_bandwidth bandwidth,
|
||||
u8 rate, u8 group)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
u8 tx_power;
|
||||
u8 upper, lower;
|
||||
bool mcs_rate;
|
||||
|
@ -2209,7 +2204,7 @@ static void rtw_phy_set_tx_power_level_by_path(struct rtw_dev *rtwdev,
|
|||
|
||||
void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
u8 path;
|
||||
|
||||
|
@ -2484,7 +2479,7 @@ static void rtw_phy_set_tx_path_by_reg(struct rtw_dev *rtwdev,
|
|||
{
|
||||
struct rtw_path_div *path_div = &rtwdev->dm_path_div;
|
||||
enum rtw_bb_path tx_path_sel_cck = tx_path_sel_1ss;
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (tx_path_sel_1ss == path_div->current_tx_path)
|
||||
return;
|
||||
|
@ -2539,7 +2534,7 @@ static void rtw_phy_tx_path_diversity_2ss(struct rtw_dev *rtwdev)
|
|||
|
||||
void rtw_phy_tx_path_diversity(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
if (!chip->path_div_supported)
|
||||
return;
|
||||
|
|
2
phy.h
2
phy.h
|
@ -114,7 +114,7 @@ const struct rtw_table name ## _tbl = { \
|
|||
|
||||
static inline const struct rtw_rfe_def *rtw_get_rfe_def(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
const struct rtw_rfe_def *rfe_def = NULL;
|
||||
|
||||
|
|
57
ps.c
57
ps.c
|
@ -18,15 +18,16 @@ static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
|
|||
if (ret)
|
||||
rtw_err(rtwdev, "leave idle state failed\n");
|
||||
|
||||
rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
|
||||
rtw_set_channel(rtwdev);
|
||||
clear_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtw_enter_ips(struct rtw_dev *rtwdev)
|
||||
{
|
||||
set_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
|
||||
if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags))
|
||||
return 0;
|
||||
|
||||
rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
|
||||
|
||||
|
@ -36,8 +37,7 @@ int rtw_enter_ips(struct rtw_dev *rtwdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_restore_port_cfg_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
static void rtw_restore_port_cfg_iter(void *data, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtw_dev *rtwdev = data;
|
||||
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
|
||||
|
@ -50,6 +50,9 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (test_bit(RTW_FLAG_POWERON, rtwdev->flags))
|
||||
return 0;
|
||||
|
||||
rtw_hci_link_ps(rtwdev, false);
|
||||
|
||||
ret = rtw_ips_pwr_up(rtwdev);
|
||||
|
@ -58,9 +61,7 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
|
||||
|
||||
rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
|
||||
rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -296,3 +297,45 @@ void rtw_leave_lps_deep(struct rtw_dev *rtwdev)
|
|||
|
||||
__rtw_leave_lps_deep(rtwdev);
|
||||
}
|
||||
|
||||
struct rtw_vif_recalc_lps_iter_data {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct ieee80211_vif *found_vif;
|
||||
int count;
|
||||
};
|
||||
|
||||
static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
if (data->count < 0)
|
||||
return;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION) {
|
||||
data->count = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
data->count++;
|
||||
data->found_vif = vif;
|
||||
}
|
||||
|
||||
static void rtw_vif_recalc_lps_iter(void *data, struct ieee80211_vif *vif)
|
||||
{
|
||||
__rtw_vif_recalc_lps(data, vif);
|
||||
}
|
||||
|
||||
void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif)
|
||||
{
|
||||
struct rtw_vif_recalc_lps_iter_data data = { .rtwdev = rtwdev };
|
||||
|
||||
if (new_vif)
|
||||
__rtw_vif_recalc_lps(&data, new_vif);
|
||||
rtw_iterate_vifs(rtwdev, rtw_vif_recalc_lps_iter, &data);
|
||||
|
||||
if (data.count == 1 && data.found_vif->cfg.ps) {
|
||||
rtwdev->ps_enabled = true;
|
||||
} else {
|
||||
rtwdev->ps_enabled = false;
|
||||
rtw_leave_lps(rtwdev);
|
||||
}
|
||||
}
|
||||
|
|
2
ps.h
2
ps.h
|
@ -23,4 +23,6 @@ void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id);
|
|||
void rtw_leave_lps(struct rtw_dev *rtwdev);
|
||||
void rtw_leave_lps_deep(struct rtw_dev *rtwdev);
|
||||
enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev);
|
||||
void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif);
|
||||
|
||||
#endif
|
||||
|
|
17
reg.h
17
reg.h
|
@ -87,6 +87,7 @@
|
|||
#define BIT_LTE_MUX_CTRL_PATH BIT(26)
|
||||
#define REG_HCI_OPT_CTRL 0x0074
|
||||
#define BIT_USB_SUS_DIS BIT(8)
|
||||
#define BIT_SDIO_PAD_E5 BIT(18)
|
||||
|
||||
#define REG_AFE_CTRL_4 0x0078
|
||||
#define BIT_CK320M_AFE_EN BIT(4)
|
||||
|
@ -184,6 +185,10 @@
|
|||
#define BIT_TXDMA_VIQ_MAP(x) \
|
||||
(((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP)
|
||||
#define REG_TXDMA_PQ_MAP 0x010C
|
||||
#define BIT_RXDMA_ARBBW_EN BIT(0)
|
||||
#define BIT_RXSHFT_EN BIT(1)
|
||||
#define BIT_RXDMA_AGG_EN BIT(2)
|
||||
#define BIT_TXDMA_BW_EN BIT(3)
|
||||
#define BIT_SHIFT_TXDMA_BEQ_MAP 8
|
||||
#define BIT_MASK_TXDMA_BEQ_MAP 0x3
|
||||
#define BIT_TXDMA_BEQ_MAP(x) \
|
||||
|
@ -282,10 +287,18 @@
|
|||
#define REG_H2C_TAIL 0x0248
|
||||
#define REG_H2C_READ_ADDR 0x024C
|
||||
#define REG_H2C_INFO 0x0254
|
||||
#define REG_RXDMA_AGG_PG_TH 0x0280
|
||||
#define BIT_RXDMA_AGG_PG_TH GENMASK(7, 0)
|
||||
#define BIT_DMA_AGG_TO_V1 GENMASK(15, 8)
|
||||
#define BIT_EN_PRE_CALC BIT(29)
|
||||
#define REG_RXPKT_NUM 0x0284
|
||||
#define BIT_RXDMA_REQ BIT(19)
|
||||
#define BIT_RW_RELEASE BIT(18)
|
||||
#define BIT_RXDMA_IDLE BIT(17)
|
||||
#define REG_RXDMA_STATUS 0x0288
|
||||
#define REG_RXDMA_DPR 0x028C
|
||||
#define REG_RXDMA_MODE 0x0290
|
||||
#define BIT_DMA_MODE BIT(1)
|
||||
#define REG_RXPKTNUM 0x02B0
|
||||
|
||||
#define REG_INT_MIG 0x0304
|
||||
|
@ -365,6 +378,7 @@
|
|||
#define BIT_SIFS_BK_EN BIT(12)
|
||||
#define REG_TXPAUSE 0x0522
|
||||
#define BIT_AC_QUEUE GENMASK(7, 0)
|
||||
#define BIT_HIGH_QUEUE BIT(5)
|
||||
#define REG_RD_CTRL 0x0524
|
||||
#define BIT_EDCCA_MSK_CNTDOWN_EN BIT(11)
|
||||
#define BIT_DIS_TXOP_CFE BIT(10)
|
||||
|
@ -389,12 +403,15 @@
|
|||
#define BIT_EN_FREE_CNT BIT(3)
|
||||
#define BIT_DIS_SECOND_CCA (BIT(0) | BIT(1))
|
||||
#define REG_HIQ_NO_LMT_EN 0x5A7
|
||||
#define REG_DTIM_COUNTER_ROOT 0x5A8
|
||||
#define BIT_HIQ_NO_LMT_EN_ROOT BIT(0)
|
||||
#define REG_TIMER0_SRC_SEL 0x05B4
|
||||
#define BIT_TSFT_SEL_TIMER0 (BIT(4) | BIT(5) | BIT(6))
|
||||
|
||||
#define REG_TCR 0x0604
|
||||
#define BIT_PWRMGT_HWDATA_EN BIT(7)
|
||||
#define BIT_TCR_UPDATE_TIMIE BIT(5)
|
||||
#define BIT_TCR_UPDATE_HGQMD BIT(4)
|
||||
#define REG_RCR 0x0608
|
||||
#define BIT_APP_FCS BIT(31)
|
||||
#define BIT_APP_MIC BIT(30)
|
||||
|
|
2
regd.c
2
regd.c
|
@ -479,6 +479,7 @@ void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|||
rtw_dbg(rtwdev, RTW_DBG_REGD, "regd state: %d -> %d\n",
|
||||
rtwdev->regd.state, next_regd.state);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtwdev->regd = next_regd;
|
||||
rtw_dbg_regd_dump(rtwdev, "get alpha2 %c%c from initiator %d: ",
|
||||
request->alpha2[0],
|
||||
|
@ -487,6 +488,7 @@ void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|||
|
||||
rtw_phy_adaptivity_set_mode(rtwdev);
|
||||
rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
u8 rtw_regd_get(struct rtw_dev *rtwdev)
|
||||
|
|
47
rtw8723d.c
47
rtw8723d.c
|
@ -210,6 +210,18 @@ static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->e.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8723d_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8723ds_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8723d_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->s.mac_addr);
|
||||
}
|
||||
|
||||
static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
@ -239,6 +251,12 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw8723de_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtw8723du_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rtw8723ds_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
@ -1945,6 +1963,26 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev)
|
|||
dm_info->pwr_trk_triggered = false;
|
||||
}
|
||||
|
||||
static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
|
||||
__le16 chksum = 0;
|
||||
__le16 *data = (__le16 *)(txdesc);
|
||||
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
|
||||
|
||||
le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
|
||||
|
||||
while (words--)
|
||||
chksum ^= *data++;
|
||||
|
||||
chksum = ~chksum;
|
||||
|
||||
le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
|
||||
RTW_TX_DESC_W7_TXDESC_CHECKSUM);
|
||||
}
|
||||
|
||||
static struct rtw_chip_ops rtw8723d_ops = {
|
||||
.phy_set_param = rtw8723d_phy_set_param,
|
||||
.read_efuse = rtw8723d_read_efuse,
|
||||
|
@ -1965,6 +2003,7 @@ static struct rtw_chip_ops rtw8723d_ops = {
|
|||
.config_bfee = NULL,
|
||||
.set_gid_table = NULL,
|
||||
.cfg_csi_rate = NULL,
|
||||
.fill_txdesc_checksum = rtw8723d_fill_txdesc_checksum,
|
||||
|
||||
.coex_set_init = rtw8723d_coex_cfg_init,
|
||||
.coex_set_ant_switch = NULL,
|
||||
|
@ -2701,7 +2740,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = {
|
|||
{0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
|
||||
};
|
||||
|
||||
struct rtw_chip_info rtw8723d_hw_spec = {
|
||||
const struct rtw_chip_info rtw8723d_hw_spec = {
|
||||
.ops = &rtw8723d_ops,
|
||||
.id = RTW_CHIP_TYPE_8723D,
|
||||
.fw_name = "rtw88/rtw8723d_fw.bin",
|
||||
|
@ -2715,12 +2754,13 @@ struct rtw_chip_info rtw8723d_hw_spec = {
|
|||
.ptct_efuse_size = 96 + 1,
|
||||
.txff_size = 32768,
|
||||
.rxff_size = 16384,
|
||||
.rsvd_drv_pg_num = 8,
|
||||
.txgi_factor = 1,
|
||||
.is_pwr_by_rate_dec = true,
|
||||
.max_power_index = 0x3f,
|
||||
.csi_buf_pg_num = 0,
|
||||
.band = RTW_BAND_2G,
|
||||
.page_size = 128,
|
||||
.page_size = TX_PAGE_SIZE,
|
||||
.dig_min = 0x20,
|
||||
.ht_supported = true,
|
||||
.vht_supported = false,
|
||||
|
@ -2747,12 +2787,15 @@ struct rtw_chip_info rtw8723d_hw_spec = {
|
|||
.rx_ldpc = false,
|
||||
.pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl,
|
||||
.iqk_threshold = 8,
|
||||
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
|
||||
.max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
|
||||
|
||||
.coex_para_ver = 0x2007022f,
|
||||
.bt_desired_ver = 0x2f,
|
||||
.scbd_support = true,
|
||||
.new_scbd10_def = true,
|
||||
.ble_hid_profile_support = false,
|
||||
.wl_mimo_ps_support = false,
|
||||
.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
|
||||
.bt_rssi_type = COEX_BTRSSI_RATIO,
|
||||
.ant_isolation = 15,
|
||||
|
|
21
rtw8723d.h
21
rtw8723d.h
|
@ -41,6 +41,19 @@ struct rtw8723de_efuse {
|
|||
u8 sub_device_id[2];
|
||||
};
|
||||
|
||||
struct rtw8723du_efuse {
|
||||
u8 res4[48]; /* 0xd0 */
|
||||
u8 vender_id[2]; /* 0x100 */
|
||||
u8 product_id[2]; /* 0x102 */
|
||||
u8 usb_option; /* 0x104 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x107 */
|
||||
};
|
||||
|
||||
struct rtw8723ds_efuse {
|
||||
u8 res4[0x4a]; /* 0xd0 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x11a */
|
||||
};
|
||||
|
||||
struct rtw8723d_efuse {
|
||||
__le16 rtl_id;
|
||||
u8 rsvd[2];
|
||||
|
@ -69,9 +82,15 @@ struct rtw8723d_efuse {
|
|||
u8 rfe_option;
|
||||
u8 country_code[2];
|
||||
u8 res[3];
|
||||
struct rtw8723de_efuse e;
|
||||
union {
|
||||
struct rtw8723de_efuse e;
|
||||
struct rtw8723du_efuse u;
|
||||
struct rtw8723ds_efuse s;
|
||||
};
|
||||
};
|
||||
|
||||
extern const struct rtw_chip_info rtw8723d_hw_spec;
|
||||
|
||||
/* phy status page0 */
|
||||
#define GET_PHY_STAT_P0_PWDB(phy_stat) \
|
||||
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "pci.h"
|
||||
#include "rtw8723de.h"
|
||||
#include "rtw8723d.h"
|
||||
|
||||
static const struct pci_device_id rtw_8723de_id_table[] = {
|
||||
{
|
||||
|
|
10
rtw8723de.h
10
rtw8723de.h
|
@ -1,10 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_8723DE_H_
|
||||
#define __RTW_8723DE_H_
|
||||
|
||||
extern struct rtw_chip_info rtw8723d_hw_spec;
|
||||
|
||||
#endif
|
41
rtw8723ds.c
Normal file
41
rtw8723ds.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
*/
|
||||
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/module.h>
|
||||
#include "main.h"
|
||||
#include "rtw8723d.h"
|
||||
#include "sdio.h"
|
||||
|
||||
static const struct sdio_device_id rtw_8723ds_id_table[] = {
|
||||
{
|
||||
SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
|
||||
SDIO_DEVICE_ID_REALTEK_RTW8723DS_1ANT),
|
||||
.driver_data = (kernel_ulong_t)&rtw8723d_hw_spec,
|
||||
},
|
||||
{
|
||||
SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
|
||||
SDIO_DEVICE_ID_REALTEK_RTW8723DS_2ANT),
|
||||
.driver_data = (kernel_ulong_t)&rtw8723d_hw_spec,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8723ds_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8723ds_driver = {
|
||||
.name = "rtw_8723ds",
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
.id_table = rtw_8723ds_id_table,
|
||||
.drv = {
|
||||
.pm = &rtw_sdio_pm_ops,
|
||||
.shutdown = rtw_sdio_shutdown,
|
||||
}
|
||||
};
|
||||
module_sdio_driver(rtw_8723ds_driver);
|
||||
|
||||
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
|
||||
MODULE_DESCRIPTION("Realtek 802.11n wireless 8723ds driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
36
rtw8723du.c
Normal file
36
rtw8723du.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "main.h"
|
||||
#include "rtw8723d.h"
|
||||
#include "usb.h"
|
||||
|
||||
static const struct usb_device_id rtw_8723du_id_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd723, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* 8723DU 1*1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd611, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* Edimax EW-7611ULB V2 */
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8723du_id_table);
|
||||
|
||||
static int rtw8723du_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtw_usb_probe(intf, id);
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8723du_driver = {
|
||||
.name = "rtw_8723du",
|
||||
.id_table = rtw_8723du_id_table,
|
||||
.probe = rtw8723du_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
};
|
||||
module_usb_driver(rtw_8723du_driver);
|
||||
|
||||
MODULE_AUTHOR("Hans Ulli Kroll <linux@ulli-kroll.de>");
|
||||
MODULE_DESCRIPTION("Realtek 802.11n wireless 8723du driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
79
rtw8821c.c
79
rtw8821c.c
|
@ -26,6 +26,18 @@ static void rtw8821ce_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->e.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8821cu_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8821c_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8821cs_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8821c_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->s.mac_addr);
|
||||
}
|
||||
|
||||
enum rtw8821ce_rf_set {
|
||||
SWITCH_TO_BTG,
|
||||
SWITCH_TO_WLG,
|
||||
|
@ -35,13 +47,14 @@ enum rtw8821ce_rf_set {
|
|||
|
||||
static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
struct rtw8821c_efuse *map;
|
||||
int i;
|
||||
|
||||
map = (struct rtw8821c_efuse *)log_map;
|
||||
|
||||
efuse->rfe_option = map->rfe_option;
|
||||
efuse->rfe_option = map->rfe_option & 0x1f;
|
||||
efuse->rf_board_option = map->rf_board_option;
|
||||
efuse->crystal_cap = map->xtal_k;
|
||||
efuse->pa_type_2g = map->pa_type;
|
||||
|
@ -58,6 +71,19 @@ static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
efuse->tx_bb_swing_setting_2g = map->tx_bb_swing_setting_2g;
|
||||
efuse->tx_bb_swing_setting_5g = map->tx_bb_swing_setting_5g;
|
||||
|
||||
hal->pkg_type = map->rfe_option & BIT(5) ? 1 : 0;
|
||||
|
||||
switch (efuse->rfe_option) {
|
||||
case 0x2:
|
||||
case 0x4:
|
||||
case 0x7:
|
||||
case 0xa:
|
||||
case 0xc:
|
||||
case 0xf:
|
||||
hal->rfe_btg = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
|
||||
|
||||
|
@ -68,6 +94,12 @@ static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw8821ce_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtw8821cu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rtw8821cs_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
@ -125,6 +157,7 @@ static void rtw8821c_phy_bf_init(struct rtw_dev *rtwdev)
|
|||
|
||||
static void rtw8821c_phy_set_param(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
u8 crystal_cap, val;
|
||||
|
||||
/* power on BB/RF domain */
|
||||
|
@ -159,9 +192,9 @@ static void rtw8821c_phy_set_param(struct rtw_dev *rtwdev)
|
|||
|
||||
/* post init after header files config */
|
||||
rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST);
|
||||
rtwdev->chip->ch_param[0] = rtw_read32_mask(rtwdev, REG_TXSF2, MASKDWORD);
|
||||
rtwdev->chip->ch_param[1] = rtw_read32_mask(rtwdev, REG_TXSF6, MASKDWORD);
|
||||
rtwdev->chip->ch_param[2] = rtw_read32_mask(rtwdev, REG_TXFILTER, MASKDWORD);
|
||||
hal->ch_param[0] = rtw_read32_mask(rtwdev, REG_TXSF2, MASKDWORD);
|
||||
hal->ch_param[1] = rtw_read32_mask(rtwdev, REG_TXSF6, MASKDWORD);
|
||||
hal->ch_param[2] = rtw_read32_mask(rtwdev, REG_TXFILTER, MASKDWORD);
|
||||
|
||||
rtw_phy_init(rtwdev);
|
||||
rtwdev->dm_info.cck_pd_default = rtw_read8(rtwdev, REG_CSRATIO) & 0x1f;
|
||||
|
@ -276,6 +309,7 @@ static void rtw8821c_switch_rf_set(struct rtw_dev *rtwdev, u8 rf_set)
|
|||
|
||||
static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
|
||||
{
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
u32 rf_reg18;
|
||||
|
||||
rf_reg18 = rtw_read_rf(rtwdev, RF_PATH_A, 0x18, RFREG_MASK);
|
||||
|
@ -307,11 +341,10 @@ static void rtw8821c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
|
|||
}
|
||||
|
||||
if (channel <= 14) {
|
||||
if (rtwdev->efuse.rfe_option == 0)
|
||||
rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_WLG);
|
||||
else if (rtwdev->efuse.rfe_option == 2 ||
|
||||
rtwdev->efuse.rfe_option == 4)
|
||||
if (hal->rfe_btg)
|
||||
rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_BTG);
|
||||
else
|
||||
rtw8821c_switch_rf_set(rtwdev, SWITCH_TO_WLG);
|
||||
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTDBG, BIT(6), 0x1);
|
||||
rtw_write_rf(rtwdev, RF_PATH_A, 0x64, 0xf, 0xf);
|
||||
} else {
|
||||
|
@ -351,6 +384,7 @@ static void rtw8821c_set_channel_rxdfir(struct rtw_dev *rtwdev, u8 bw)
|
|||
static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
|
||||
u8 primary_ch_idx)
|
||||
{
|
||||
struct rtw_hal *hal = &rtwdev->hal;
|
||||
u32 val32;
|
||||
|
||||
if (channel <= 14) {
|
||||
|
@ -367,11 +401,11 @@ static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
|
|||
rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD, 0x00003667);
|
||||
} else {
|
||||
rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD,
|
||||
rtwdev->chip->ch_param[0]);
|
||||
hal->ch_param[0]);
|
||||
rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD,
|
||||
rtwdev->chip->ch_param[1] & MASKLWORD);
|
||||
hal->ch_param[1] & MASKLWORD);
|
||||
rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD,
|
||||
rtwdev->chip->ch_param[2]);
|
||||
hal->ch_param[2]);
|
||||
}
|
||||
} else if (channel > 35) {
|
||||
rtw_write32_mask(rtwdev, REG_ENTXCCK, BIT(18), 0x1);
|
||||
|
@ -499,7 +533,7 @@ static s8 get_cck_rx_pwr(struct rtw_dev *rtwdev, u8 lna_idx, u8 vga_idx)
|
|||
}
|
||||
|
||||
if (lna_idx >= lna_gain_table_size) {
|
||||
rtw_info(rtwdev, "incorrect lna index (%d)\n", lna_idx);
|
||||
rtw_warn(rtwdev, "incorrect lna index (%d)\n", lna_idx);
|
||||
return -120;
|
||||
}
|
||||
|
||||
|
@ -512,6 +546,7 @@ static s8 get_cck_rx_pwr(struct rtw_dev *rtwdev, u8 lna_idx, u8 vga_idx)
|
|||
static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
|
||||
struct rtw_rx_pkt_stat *pkt_stat)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
s8 rx_power;
|
||||
u8 lna_idx = 0;
|
||||
u8 vga_idx = 0;
|
||||
|
@ -523,6 +558,7 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
|
|||
|
||||
pkt_stat->rx_power[RF_PATH_A] = rx_power;
|
||||
pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
|
||||
dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
|
||||
pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
|
||||
pkt_stat->signal_power = rx_power;
|
||||
}
|
||||
|
@ -530,6 +566,7 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
|
|||
static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
|
||||
struct rtw_rx_pkt_stat *pkt_stat)
|
||||
{
|
||||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
u8 rxsc, bw;
|
||||
s8 min_rx_power = -120;
|
||||
|
||||
|
@ -549,6 +586,7 @@ static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
|
|||
|
||||
pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110;
|
||||
pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
|
||||
dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
|
||||
pkt_stat->bw = bw;
|
||||
pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
|
||||
min_rx_power);
|
||||
|
@ -1142,6 +1180,13 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
|
|||
dm_info->cck_pd_default + new_lvl * 2);
|
||||
}
|
||||
|
||||
static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
fill_txdesc_checksum_common(txdesc, 16);
|
||||
}
|
||||
|
||||
static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = {
|
||||
{0x0086,
|
||||
RTW_PWR_CUT_ALL_MSK,
|
||||
|
@ -1514,6 +1559,7 @@ static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
|
|||
[0] = RTW_DEF_RFE(8821c, 0, 0),
|
||||
[2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
|
||||
[4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
|
||||
[6] = RTW_DEF_RFE(8821c, 0, 0),
|
||||
};
|
||||
|
||||
static struct rtw_hw_reg rtw8821c_dig[] = {
|
||||
|
@ -1588,6 +1634,7 @@ static struct rtw_chip_ops rtw8821c_ops = {
|
|||
.config_bfee = rtw8821c_bf_config_bfee,
|
||||
.set_gid_table = rtw_bf_set_gid_table,
|
||||
.cfg_csi_rate = rtw_bf_cfg_csi_rate,
|
||||
.fill_txdesc_checksum = rtw8821c_fill_txdesc_checksum,
|
||||
|
||||
.coex_set_init = rtw8821c_coex_cfg_init,
|
||||
.coex_set_ant_switch = rtw8821c_coex_cfg_ant_switch,
|
||||
|
@ -1872,7 +1919,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = {
|
|||
{0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
|
||||
};
|
||||
|
||||
struct rtw_chip_info rtw8821c_hw_spec = {
|
||||
const struct rtw_chip_info rtw8821c_hw_spec = {
|
||||
.ops = &rtw8821c_ops,
|
||||
.id = RTW_CHIP_TYPE_8821C,
|
||||
.fw_name = "rtw88/rtw8821c_fw.bin",
|
||||
|
@ -1886,12 +1933,13 @@ struct rtw_chip_info rtw8821c_hw_spec = {
|
|||
.ptct_efuse_size = 96,
|
||||
.txff_size = 65536,
|
||||
.rxff_size = 16384,
|
||||
.rsvd_drv_pg_num = 8,
|
||||
.txgi_factor = 1,
|
||||
.is_pwr_by_rate_dec = true,
|
||||
.max_power_index = 0x3f,
|
||||
.csi_buf_pg_num = 0,
|
||||
.band = RTW_BAND_2G | RTW_BAND_5G,
|
||||
.page_size = 128,
|
||||
.page_size = TX_PAGE_SIZE,
|
||||
.dig_min = 0x1c,
|
||||
.ht_supported = true,
|
||||
.vht_supported = true,
|
||||
|
@ -1918,12 +1966,15 @@ struct rtw_chip_info rtw8821c_hw_spec = {
|
|||
.iqk_threshold = 8,
|
||||
.bfer_su_max_num = 2,
|
||||
.bfer_mu_max_num = 1,
|
||||
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_2,
|
||||
.max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
|
||||
|
||||
.coex_para_ver = 0x19092746,
|
||||
.bt_desired_ver = 0x46,
|
||||
.scbd_support = true,
|
||||
.new_scbd10_def = false,
|
||||
.ble_hid_profile_support = false,
|
||||
.wl_mimo_ps_support = false,
|
||||
.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
|
||||
.bt_rssi_type = COEX_BTRSSI_RATIO,
|
||||
.ant_isolation = 15,
|
||||
|
|
29
rtw8821c.h
29
rtw8821c.h
|
@ -9,6 +9,26 @@
|
|||
|
||||
#define RCR_VHT_ACK BIT(26)
|
||||
|
||||
struct rtw8821cu_efuse {
|
||||
u8 res4[4]; /* 0xd0 */
|
||||
u8 usb_optional_function;
|
||||
u8 res5[0x1e];
|
||||
u8 res6[2];
|
||||
u8 serial[0x0b]; /* 0xf5 */
|
||||
u8 vid; /* 0x100 */
|
||||
u8 res7;
|
||||
u8 pid;
|
||||
u8 res8[4];
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x107 */
|
||||
u8 res9[2];
|
||||
u8 vendor_name[0x07];
|
||||
u8 res10[2];
|
||||
u8 device_name[0x14];
|
||||
u8 res11[0xcf];
|
||||
u8 package_type; /* 0x1fb */
|
||||
u8 res12[0x4];
|
||||
};
|
||||
|
||||
struct rtw8821ce_efuse {
|
||||
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
|
||||
u8 vender_id[2];
|
||||
|
@ -45,6 +65,11 @@ struct rtw8821ce_efuse {
|
|||
u8 res7;
|
||||
};
|
||||
|
||||
struct rtw8821cs_efuse {
|
||||
u8 res4[0x4a]; /* 0xd0 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x11a */
|
||||
} __packed;
|
||||
|
||||
struct rtw8821c_efuse {
|
||||
__le16 rtl_id;
|
||||
u8 res0[0x0e];
|
||||
|
@ -73,6 +98,8 @@ struct rtw8821c_efuse {
|
|||
u8 res[3];
|
||||
union {
|
||||
struct rtw8821ce_efuse e;
|
||||
struct rtw8821cu_efuse u;
|
||||
struct rtw8821cs_efuse s;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -84,6 +111,8 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
|
|||
rtw_write32_mask(rtwdev, addr + 0x200, mask, data);
|
||||
}
|
||||
|
||||
extern const struct rtw_chip_info rtw8821c_hw_spec;
|
||||
|
||||
#define rtw_write32s_mask(rtwdev, addr, mask, data) \
|
||||
do { \
|
||||
BUILD_BUG_ON((addr) < 0xC00 || (addr) >= 0xD00); \
|
||||
|
|
|
@ -13,7 +13,7 @@ static const u32 rtw8821c_mac[] = {
|
|||
0x04F, 0x00000001,
|
||||
0x029, 0x000000F9,
|
||||
0x420, 0x00000080,
|
||||
0x421, 0x0000000F,
|
||||
0x421, 0x0000001F,
|
||||
0x428, 0x0000000A,
|
||||
0x429, 0x00000010,
|
||||
0x430, 0x00000000,
|
||||
|
|
|
@ -5,9 +5,13 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "pci.h"
|
||||
#include "rtw8821ce.h"
|
||||
#include "rtw8821c.h"
|
||||
|
||||
static const struct pci_device_id rtw_8821ce_id_table[] = {
|
||||
{
|
||||
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB821),
|
||||
.driver_data = (kernel_ulong_t)&rtw8821c_hw_spec
|
||||
},
|
||||
{
|
||||
PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC821),
|
||||
.driver_data = (kernel_ulong_t)&rtw8821c_hw_spec
|
||||
|
|
10
rtw8821ce.h
10
rtw8821ce.h
|
@ -1,10 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_8821CE_H_
|
||||
#define __RTW_8821CE_H_
|
||||
|
||||
extern struct rtw_chip_info rtw8821c_hw_spec;
|
||||
|
||||
#endif
|
36
rtw8821cs.c
Normal file
36
rtw8821cs.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
*/
|
||||
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/module.h>
|
||||
#include "main.h"
|
||||
#include "rtw8821c.h"
|
||||
#include "sdio.h"
|
||||
|
||||
static const struct sdio_device_id rtw_8821cs_id_table[] = {
|
||||
{
|
||||
SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
|
||||
SDIO_DEVICE_ID_REALTEK_RTW8821CS),
|
||||
.driver_data = (kernel_ulong_t)&rtw8821c_hw_spec,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8821cs_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8821cs_driver = {
|
||||
.name = "rtw_8821cs",
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
.id_table = rtw_8821cs_id_table,
|
||||
.drv = {
|
||||
.pm = &rtw_sdio_pm_ops,
|
||||
.shutdown = rtw_sdio_shutdown,
|
||||
}
|
||||
};
|
||||
module_sdio_driver(rtw_8821cs_driver);
|
||||
|
||||
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cs driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
50
rtw8821cu.c
Normal file
50
rtw8821cu.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "main.h"
|
||||
#include "rtw8821c.h"
|
||||
#include "usb.h"
|
||||
|
||||
static const struct usb_device_id rtw_8821cu_id_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* TOTOLINK A650UA v3 */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table);
|
||||
|
||||
static int rtw_8821cu_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtw_usb_probe(intf, id);
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8821cu_driver = {
|
||||
.name = "rtw_8821cu",
|
||||
.id_table = rtw_8821cu_id_table,
|
||||
.probe = rtw_8821cu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
};
|
||||
module_usb_driver(rtw_8821cu_driver);
|
||||
|
||||
MODULE_AUTHOR("Hans Ulli Kroll <linux@ulli-kroll.de>");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cu driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
40
rtw8822b.c
40
rtw8822b.c
|
@ -26,6 +26,18 @@ static void rtw8822be_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->e.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8822bu_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8822b_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8822bs_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8822b_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->s.mac_addr);
|
||||
}
|
||||
|
||||
static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
@ -56,6 +68,12 @@ static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw8822be_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtw8822bu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rtw8822bs_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
@ -1012,12 +1030,12 @@ static int rtw8822b_set_antenna(struct rtw_dev *rtwdev,
|
|||
antenna_tx, antenna_rx);
|
||||
|
||||
if (!rtw8822b_check_rf_path(antenna_tx)) {
|
||||
rtw_info(rtwdev, "unsupported tx path 0x%x\n", antenna_tx);
|
||||
rtw_warn(rtwdev, "unsupported tx path 0x%x\n", antenna_tx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!rtw8822b_check_rf_path(antenna_rx)) {
|
||||
rtw_info(rtwdev, "unsupported rx path 0x%x\n", antenna_rx);
|
||||
rtw_warn(rtwdev, "unsupported rx path 0x%x\n", antenna_rx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1588,6 +1606,15 @@ static void rtw8822b_adaptivity(struct rtw_dev *rtwdev)
|
|||
rtw_phy_set_edcca_th(rtwdev, l2h, h2l);
|
||||
}
|
||||
|
||||
static void rtw8822b_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
|
||||
|
||||
fill_txdesc_checksum_common(txdesc, words);
|
||||
}
|
||||
|
||||
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = {
|
||||
{0x0086,
|
||||
RTW_PWR_CUT_ALL_MSK,
|
||||
|
@ -2163,6 +2190,7 @@ static struct rtw_chip_ops rtw8822b_ops = {
|
|||
.cfg_csi_rate = rtw_bf_cfg_csi_rate,
|
||||
.adaptivity_init = rtw8822b_adaptivity_init,
|
||||
.adaptivity = rtw8822b_adaptivity,
|
||||
.fill_txdesc_checksum = rtw8822b_fill_txdesc_checksum,
|
||||
|
||||
.coex_set_init = rtw8822b_coex_cfg_init,
|
||||
.coex_set_ant_switch = rtw8822b_coex_cfg_ant_switch,
|
||||
|
@ -2497,7 +2525,7 @@ static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = {
|
|||
[EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0},
|
||||
};
|
||||
|
||||
struct rtw_chip_info rtw8822b_hw_spec = {
|
||||
const struct rtw_chip_info rtw8822b_hw_spec = {
|
||||
.ops = &rtw8822b_ops,
|
||||
.id = RTW_CHIP_TYPE_8822B,
|
||||
.fw_name = "rtw88/rtw8822b_fw.bin",
|
||||
|
@ -2512,12 +2540,13 @@ struct rtw_chip_info rtw8822b_hw_spec = {
|
|||
.txff_size = 262144,
|
||||
.rxff_size = 24576,
|
||||
.fw_rxff_size = 12288,
|
||||
.rsvd_drv_pg_num = 8,
|
||||
.txgi_factor = 1,
|
||||
.is_pwr_by_rate_dec = true,
|
||||
.max_power_index = 0x3f,
|
||||
.csi_buf_pg_num = 0,
|
||||
.band = RTW_BAND_2G | RTW_BAND_5G,
|
||||
.page_size = 128,
|
||||
.page_size = TX_PAGE_SIZE,
|
||||
.dig_min = 0x1c,
|
||||
.ht_supported = true,
|
||||
.vht_supported = true,
|
||||
|
@ -2548,12 +2577,15 @@ struct rtw_chip_info rtw8822b_hw_spec = {
|
|||
.edcca_th = rtw8822b_edcca_th,
|
||||
.l2h_th_ini_cs = 10 + EDCCA_IGI_BASE,
|
||||
.l2h_th_ini_ad = -14 + EDCCA_IGI_BASE,
|
||||
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_2,
|
||||
.max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
|
||||
|
||||
.coex_para_ver = 0x20070206,
|
||||
.bt_desired_ver = 0x6,
|
||||
.scbd_support = true,
|
||||
.new_scbd10_def = false,
|
||||
.ble_hid_profile_support = false,
|
||||
.wl_mimo_ps_support = false,
|
||||
.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
|
||||
.bt_rssi_type = COEX_BTRSSI_RATIO,
|
||||
.ant_isolation = 15,
|
||||
|
|
10
rtw8822b.h
10
rtw8822b.h
|
@ -65,6 +65,11 @@ struct rtw8822be_efuse {
|
|||
u8 res7;
|
||||
};
|
||||
|
||||
struct rtw8822bs_efuse {
|
||||
u8 res4[0x4a]; /* 0xd0 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x11a */
|
||||
} __packed;
|
||||
|
||||
struct rtw8822b_efuse {
|
||||
__le16 rtl_id;
|
||||
u8 res0[0x0e];
|
||||
|
@ -92,8 +97,9 @@ struct rtw8822b_efuse {
|
|||
u8 country_code[2];
|
||||
u8 res[3];
|
||||
union {
|
||||
struct rtw8822bu_efuse u;
|
||||
struct rtw8822be_efuse e;
|
||||
struct rtw8822bu_efuse u;
|
||||
struct rtw8822bs_efuse s;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -187,4 +193,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data)
|
|||
#define REG_ANTWT 0x1904
|
||||
#define REG_IQKFAILMSK 0x1bf0
|
||||
|
||||
extern const struct rtw_chip_info rtw8822b_hw_spec;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "pci.h"
|
||||
#include "rtw8822be.h"
|
||||
#include "rtw8822b.h"
|
||||
|
||||
static const struct pci_device_id rtw_8822be_id_table[] = {
|
||||
{
|
||||
|
|
10
rtw8822be.h
10
rtw8822be.h
|
@ -1,10 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_8822BE_H_
|
||||
#define __RTW_8822BE_H_
|
||||
|
||||
extern struct rtw_chip_info rtw8822b_hw_spec;
|
||||
|
||||
#endif
|
36
rtw8822bs.c
Normal file
36
rtw8822bs.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/module.h>
|
||||
#include "main.h"
|
||||
#include "rtw8822b.h"
|
||||
#include "sdio.h"
|
||||
|
||||
static const struct sdio_device_id rtw_8822bs_id_table[] = {
|
||||
{
|
||||
SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
|
||||
SDIO_DEVICE_ID_REALTEK_RTW8822BS),
|
||||
.driver_data = (kernel_ulong_t)&rtw8822b_hw_spec,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8822bs_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8822bs_driver = {
|
||||
.name = "rtw_8822bs",
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
.id_table = rtw_8822bs_id_table,
|
||||
.drv = {
|
||||
.pm = &rtw_sdio_pm_ops,
|
||||
.shutdown = rtw_sdio_shutdown,
|
||||
}
|
||||
};
|
||||
module_sdio_driver(rtw_8822bs_driver);
|
||||
|
||||
MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@gmail.com>");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822bs driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
90
rtw8822bu.c
Normal file
90
rtw8822bu.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "main.h"
|
||||
#include "rtw8822b.h"
|
||||
#include "usb.h"
|
||||
|
||||
static const struct usb_device_id rtw_8822bu_id_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb812, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82c, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2102, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* CCNC */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822ULC */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UTC */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xe822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xf822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UAD */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb81a, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Default ID */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1841, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS AC1300 USB-AC55 B1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x184c, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS U2 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x19aa, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS - USB-AC58 rev A1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1870, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1874, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331e, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-181 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331c, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-182 - D1 */
|
||||
{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331f, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec)}, /* Dlink - DWA-183 D Ver */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB6400M */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0045, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB3600 v2 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012d, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U v1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0138, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U Plus v1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0115, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T4U V3 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012e, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0116, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0117, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9055, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Netgear A6150 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0025, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Hawking HW12ACU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x04ca, 0x8602, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* LiteOn */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x808a, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-808UBM */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table);
|
||||
|
||||
static int rtw8822bu_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtw_usb_probe(intf, id);
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8822bu_driver = {
|
||||
.name = "rtw_8822bu",
|
||||
.id_table = rtw_8822bu_id_table,
|
||||
.probe = rtw8822bu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
};
|
||||
module_usb_driver(rtw_8822bu_driver);
|
||||
|
||||
MODULE_AUTHOR("Realtek Corporation");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822bu driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
87
rtw8822c.c
87
rtw8822c.c
|
@ -29,6 +29,18 @@ static void rtw8822ce_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->e.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8822cu_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8822c_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8822cs_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8822c_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->s.mac_addr);
|
||||
}
|
||||
|
||||
static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
@ -58,6 +70,12 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw8822ce_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtw8822cu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_SDIO:
|
||||
rtw8822cs_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
@ -2798,7 +2816,7 @@ static int rtw8822c_set_antenna(struct rtw_dev *rtwdev,
|
|||
case BB_PATH_AB:
|
||||
break;
|
||||
default:
|
||||
rtw_info(rtwdev, "unsupported tx path 0x%x\n", antenna_tx);
|
||||
rtw_warn(rtwdev, "unsupported tx path 0x%x\n", antenna_tx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2808,7 +2826,7 @@ static int rtw8822c_set_antenna(struct rtw_dev *rtwdev,
|
|||
case BB_PATH_AB:
|
||||
break;
|
||||
default:
|
||||
rtw_info(rtwdev, "unsupported rx path 0x%x\n", antenna_rx);
|
||||
rtw_warn(rtwdev, "unsupported rx path 0x%x\n", antenna_rx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2996,19 +3014,34 @@ static void rtw8822c_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
|
|||
* enable "DAC off if GNT_WL = 0" for non-shared-antenna
|
||||
* disable 0x1c30[22] = 0,
|
||||
* enable: 0x1c30[22] = 1, 0x1c38[12] = 0, 0x1c38[28] = 1
|
||||
*
|
||||
* disable WL-S1 BB chage RF mode if GNT_BT
|
||||
*/
|
||||
if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
|
||||
rtw_write8_mask(rtwdev, REG_ANAPAR + 2,
|
||||
BIT_ANAPAR_BTPS >> 16, 0);
|
||||
} else {
|
||||
rtw_write8_mask(rtwdev, REG_ANAPAR + 2,
|
||||
BIT_ANAPAR_BTPS >> 16, 1);
|
||||
rtw_write8_mask(rtwdev, REG_RSTB_SEL + 1,
|
||||
BIT_DAC_OFF_ENABLE, 0);
|
||||
rtw_write8_mask(rtwdev, REG_RSTB_SEL + 3,
|
||||
BIT_DAC_OFF_ENABLE, 1);
|
||||
}
|
||||
|
||||
/* disable WL-S1 BB chage RF mode if GNT_BT
|
||||
* since RF TRx mask can do it
|
||||
*/
|
||||
rtw_write8_mask(rtwdev, REG_ANAPAR + 2, BIT_ANAPAR_BTPS >> 16, 1);
|
||||
rtw_write8_mask(rtwdev, REG_RSTB_SEL + 1, BIT_DAC_OFF_ENABLE, 0);
|
||||
rtw_write8_mask(rtwdev, REG_RSTB_SEL + 3, BIT_DAC_OFF_ENABLE, 1);
|
||||
rtw_write8_mask(rtwdev, REG_IGN_GNTBT4, BIT_PI_IGNORE_GNT_BT, 1);
|
||||
rtw_write8_mask(rtwdev, REG_IGN_GNTBT4,
|
||||
BIT_PI_IGNORE_GNT_BT, 1);
|
||||
|
||||
/* disable WL-S0 BB chage RF mode if wifi is at 5G,
|
||||
* or antenna path is separated
|
||||
*/
|
||||
if (coex_stat->wl_coex_mode == COEX_WLINK_5G ||
|
||||
if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
|
||||
rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1,
|
||||
BIT_PI_IGNORE_GNT_BT, 1);
|
||||
rtw_write8_mask(rtwdev, REG_NOMASK_TXBT,
|
||||
BIT_NOMASK_TXBT_ENABLE, 1);
|
||||
} else if (coex_stat->wl_coex_mode == COEX_WLINK_5G ||
|
||||
coex->under_5g || !efuse->share_ant) {
|
||||
if (coex_stat->kt_ver >= 3) {
|
||||
rtw_write8_mask(rtwdev, REG_IGN_GNT_BT1,
|
||||
|
@ -4542,6 +4575,18 @@ static void rtw8822c_adaptivity(struct rtw_dev *rtwdev)
|
|||
rtw_phy_set_edcca_th(rtwdev, l2h, h2l);
|
||||
}
|
||||
|
||||
static void rtw8822c_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
size_t words;
|
||||
|
||||
words = (pkt_info->pkt_offset * 8 + chip->tx_pkt_desc_sz) / 2;
|
||||
|
||||
fill_txdesc_checksum_common(txdesc, words);
|
||||
}
|
||||
|
||||
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = {
|
||||
{0x0086,
|
||||
RTW_PWR_CUT_ALL_MSK,
|
||||
|
@ -4880,6 +4925,8 @@ static const struct rtw_rfe_def rtw8822c_rfe_defs[] = {
|
|||
[0] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[1] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[2] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[3] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[4] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[5] = RTW_DEF_RFE(8822c, 0, 5),
|
||||
[6] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
};
|
||||
|
@ -4962,6 +5009,8 @@ static struct rtw_chip_ops rtw8822c_ops = {
|
|||
.cfo_init = rtw8822c_cfo_init,
|
||||
.cfo_track = rtw8822c_cfo_track,
|
||||
.config_tx_path = rtw8822c_config_tx_path,
|
||||
.config_txrx_mode = rtw8822c_config_trx_mode,
|
||||
.fill_txdesc_checksum = rtw8822c_fill_txdesc_checksum,
|
||||
|
||||
.coex_set_init = rtw8822c_coex_cfg_init,
|
||||
.coex_set_ant_switch = NULL,
|
||||
|
@ -5007,6 +5056,8 @@ static const struct coex_table_para table_sant_8822c[] = {
|
|||
{0x66556aaa, 0x6a5a6aaa}, /*case-30*/
|
||||
{0xffffffff, 0x5aaa5aaa},
|
||||
{0x56555555, 0x5a5a5aaa},
|
||||
{0xdaffdaff, 0xdaffdaff},
|
||||
{0xddffddff, 0xddffddff},
|
||||
};
|
||||
|
||||
/* Non-Shared-Antenna Coex Table */
|
||||
|
@ -5107,7 +5158,8 @@ static const struct coex_rf_para rf_para_tx_8822c[] = {
|
|||
{8, 17, true, 4},
|
||||
{7, 18, true, 4},
|
||||
{6, 19, true, 4},
|
||||
{5, 20, true, 4}
|
||||
{5, 20, true, 4},
|
||||
{0, 21, true, 4} /* for gamg hid */
|
||||
};
|
||||
|
||||
static const struct coex_rf_para rf_para_rx_8822c[] = {
|
||||
|
@ -5116,7 +5168,8 @@ static const struct coex_rf_para rf_para_rx_8822c[] = {
|
|||
{3, 24, true, 5},
|
||||
{2, 26, true, 5},
|
||||
{1, 27, true, 5},
|
||||
{0, 28, true, 5}
|
||||
{0, 28, true, 5},
|
||||
{0, 28, true, 5} /* for gamg hid */
|
||||
};
|
||||
|
||||
static_assert(ARRAY_SIZE(rf_para_tx_8822c) == ARRAY_SIZE(rf_para_rx_8822c));
|
||||
|
@ -5290,7 +5343,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822c[] = {
|
|||
{0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
|
||||
};
|
||||
|
||||
struct rtw_chip_info rtw8822c_hw_spec = {
|
||||
const struct rtw_chip_info rtw8822c_hw_spec = {
|
||||
.ops = &rtw8822c_ops,
|
||||
.id = RTW_CHIP_TYPE_8822C,
|
||||
.fw_name = "rtw88/rtw8822c_fw.bin",
|
||||
|
@ -5305,12 +5358,13 @@ struct rtw_chip_info rtw8822c_hw_spec = {
|
|||
.txff_size = 262144,
|
||||
.rxff_size = 24576,
|
||||
.fw_rxff_size = 12288,
|
||||
.rsvd_drv_pg_num = 16,
|
||||
.txgi_factor = 2,
|
||||
.is_pwr_by_rate_dec = false,
|
||||
.max_power_index = 0x7f,
|
||||
.csi_buf_pg_num = 50,
|
||||
.band = RTW_BAND_2G | RTW_BAND_5G,
|
||||
.page_size = 128,
|
||||
.page_size = TX_PAGE_SIZE,
|
||||
.dig_min = 0x20,
|
||||
.default_1ss_tx_path = BB_PATH_A,
|
||||
.path_div_supported = true,
|
||||
|
@ -5348,17 +5402,20 @@ struct rtw_chip_info rtw8822c_hw_spec = {
|
|||
.edcca_th = rtw8822c_edcca_th,
|
||||
.l2h_th_ini_cs = 60,
|
||||
.l2h_th_ini_ad = 45,
|
||||
.ampdu_density = IEEE80211_HT_MPDU_DENSITY_2,
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
.wow_fw_name = "rtw88/rtw8822c_wow_fw.bin",
|
||||
.wowlan_stub = &rtw_wowlan_stub_8822c,
|
||||
.max_sched_scan_ssids = 4,
|
||||
#endif
|
||||
.coex_para_ver = 0x2103181c,
|
||||
.bt_desired_ver = 0x1c,
|
||||
.max_scan_ie_len = (RTW_PROBE_PG_CNT - 1) * TX_PAGE_SIZE,
|
||||
.coex_para_ver = 0x22020720,
|
||||
.bt_desired_ver = 0x20,
|
||||
.scbd_support = true,
|
||||
.new_scbd10_def = true,
|
||||
.ble_hid_profile_support = true,
|
||||
.wl_mimo_ps_support = true,
|
||||
.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
|
||||
.bt_rssi_type = COEX_BTRSSI_DBM,
|
||||
.ant_isolation = 15,
|
||||
|
|
10
rtw8822c.h
10
rtw8822c.h
|
@ -16,6 +16,11 @@ struct rtw8822cu_efuse {
|
|||
u8 res2[0x3d];
|
||||
};
|
||||
|
||||
struct rtw8822cs_efuse {
|
||||
u8 res0[0x4a]; /* 0x120 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x16a */
|
||||
} __packed;
|
||||
|
||||
struct rtw8822ce_efuse {
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x120 */
|
||||
u8 vender_id[2];
|
||||
|
@ -91,8 +96,9 @@ struct rtw8822c_efuse {
|
|||
u8 res9;
|
||||
u8 res10[0x42];
|
||||
union {
|
||||
struct rtw8822cu_efuse u;
|
||||
struct rtw8822ce_efuse e;
|
||||
struct rtw8822cu_efuse u;
|
||||
struct rtw8822cs_efuse s;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -118,6 +124,8 @@ enum rtw8822c_dpk_one_shot_action {
|
|||
void rtw8822c_parse_tbl_dpk(struct rtw_dev *rtwdev,
|
||||
const struct rtw_table *tbl);
|
||||
|
||||
extern const struct rtw_chip_info rtw8822c_hw_spec;
|
||||
|
||||
#define RTW_DECL_TABLE_DPK(name) \
|
||||
const struct rtw_table name ## _tbl = { \
|
||||
.data = name, \
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include "pci.h"
|
||||
#include "rtw8822ce.h"
|
||||
#include "rtw8822c.h"
|
||||
|
||||
static const struct pci_device_id rtw_8822ce_id_table[] = {
|
||||
{
|
||||
|
|
10
rtw8822ce.h
10
rtw8822ce.h
|
@ -1,10 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_8822CE_H_
|
||||
#define __RTW_8822CE_H_
|
||||
|
||||
extern struct rtw_chip_info rtw8822c_hw_spec;
|
||||
|
||||
#endif
|
36
rtw8822cs.c
Normal file
36
rtw8822cs.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
*/
|
||||
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/module.h>
|
||||
#include "main.h"
|
||||
#include "rtw8822c.h"
|
||||
#include "sdio.h"
|
||||
|
||||
static const struct sdio_device_id rtw_8822cs_id_table[] = {
|
||||
{
|
||||
SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
|
||||
SDIO_DEVICE_ID_REALTEK_RTW8822CS),
|
||||
.driver_data = (kernel_ulong_t)&rtw8822c_hw_spec,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, rtw_8822cs_id_table);
|
||||
|
||||
static struct sdio_driver rtw_8822cs_driver = {
|
||||
.name = "rtw_8822cs",
|
||||
.probe = rtw_sdio_probe,
|
||||
.remove = rtw_sdio_remove,
|
||||
.id_table = rtw_8822cs_id_table,
|
||||
.drv = {
|
||||
.pm = &rtw_sdio_pm_ops,
|
||||
.shutdown = rtw_sdio_shutdown,
|
||||
}
|
||||
};
|
||||
module_sdio_driver(rtw_8822cs_driver);
|
||||
|
||||
MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822cs driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
44
rtw8822cu.c
Normal file
44
rtw8822cu.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "main.h"
|
||||
#include "rtw8822c.h"
|
||||
#include "usb.h"
|
||||
|
||||
static const struct usb_device_id rtw_8822cu_id_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc812, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82e, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd820, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd82b, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* Alpha - Alpha */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8822cu_id_table);
|
||||
|
||||
static int rtw8822bu_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtw_usb_probe(intf, id);
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8822cu_driver = {
|
||||
.name = "rtw_8822cu",
|
||||
.id_table = rtw_8822cu_id_table,
|
||||
.probe = rtw8822bu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
};
|
||||
module_usb_driver(rtw_8822cu_driver);
|
||||
|
||||
MODULE_AUTHOR("Realtek Corporation");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822cu driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
3
rx.c
3
rx.c
|
@ -158,7 +158,8 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
|
|||
memset(rx_status, 0, sizeof(*rx_status));
|
||||
rx_status->freq = hw->conf.chandef.chan->center_freq;
|
||||
rx_status->band = hw->conf.chandef.chan->band;
|
||||
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD))
|
||||
if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD) &&
|
||||
test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
|
||||
rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status);
|
||||
if (pkt_stat->crc_err)
|
||||
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
|
|
8
sar.c
8
sar.c
|
@ -91,10 +91,10 @@ int rtw_set_sar_specs(struct rtw_dev *rtwdev,
|
|||
return -EINVAL;
|
||||
|
||||
power = sar->sub_specs[i].power;
|
||||
rtw_info(rtwdev, "On freq %u to %u, set SAR %d in 1/%lu dBm\n",
|
||||
rtw_common_sar_freq_ranges[idx].start_freq,
|
||||
rtw_common_sar_freq_ranges[idx].end_freq,
|
||||
power, BIT(RTW_COMMON_SAR_FCT));
|
||||
rtw_dbg(rtwdev, RTW_DBG_REGD, "On freq %u to %u, set SAR %d in 1/%lu dBm\n",
|
||||
rtw_common_sar_freq_ranges[idx].start_freq,
|
||||
rtw_common_sar_freq_ranges[idx].end_freq,
|
||||
power, BIT(RTW_COMMON_SAR_FCT));
|
||||
|
||||
for (j = 0; j < RTW_RF_PATH_MAX; j++) {
|
||||
for (k = 0; k < RTW_RATE_SECTION_MAX; k++) {
|
||||
|
|
178
sdio.h
Normal file
178
sdio.h
Normal file
|
@ -0,0 +1,178 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright (C) 2021 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||
* Copyright (C) 2021 Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __REG_SDIO_H_
|
||||
#define __REG_SDIO_H_
|
||||
|
||||
/* I/O bus domain address mapping */
|
||||
#define SDIO_LOCAL_OFFSET 0x10250000
|
||||
#define WLAN_IOREG_OFFSET 0x10260000
|
||||
#define FIRMWARE_FIFO_OFFSET 0x10270000
|
||||
#define TX_HIQ_OFFSET 0x10310000
|
||||
#define TX_MIQ_OFFSET 0x10320000
|
||||
#define TX_LOQ_OFFSET 0x10330000
|
||||
#define TX_EPQ_OFFSET 0x10350000
|
||||
#define RX_RX0FF_OFFSET 0x10340000
|
||||
|
||||
#define RTW_SDIO_BUS_MSK 0xffff0000
|
||||
#define SDIO_LOCAL_REG_MSK 0x00000fff
|
||||
#define WLAN_IOREG_REG_MSK 0x0000ffff
|
||||
|
||||
/* SDIO Tx Control */
|
||||
#define REG_SDIO_TX_CTRL (SDIO_LOCAL_OFFSET + 0x0000)
|
||||
|
||||
/*SDIO status timeout*/
|
||||
#define REG_SDIO_TIMEOUT (SDIO_LOCAL_OFFSET + 0x0002)
|
||||
|
||||
/* SDIO Host Interrupt Mask */
|
||||
#define REG_SDIO_HIMR (SDIO_LOCAL_OFFSET + 0x0014)
|
||||
#define REG_SDIO_HIMR_RX_REQUEST BIT(0)
|
||||
#define REG_SDIO_HIMR_AVAL BIT(1)
|
||||
#define REG_SDIO_HIMR_TXERR BIT(2)
|
||||
#define REG_SDIO_HIMR_RXERR BIT(3)
|
||||
#define REG_SDIO_HIMR_TXFOVW BIT(4)
|
||||
#define REG_SDIO_HIMR_RXFOVW BIT(5)
|
||||
#define REG_SDIO_HIMR_TXBCNOK BIT(6)
|
||||
#define REG_SDIO_HIMR_TXBCNERR BIT(7)
|
||||
#define REG_SDIO_HIMR_BCNERLY_INT BIT(16)
|
||||
#define REG_SDIO_HIMR_C2HCMD BIT(17)
|
||||
#define REG_SDIO_HIMR_CPWM1 BIT(18)
|
||||
#define REG_SDIO_HIMR_CPWM2 BIT(19)
|
||||
#define REG_SDIO_HIMR_HSISR_IND BIT(20)
|
||||
#define REG_SDIO_HIMR_GTINT3_IND BIT(21)
|
||||
#define REG_SDIO_HIMR_GTINT4_IND BIT(22)
|
||||
#define REG_SDIO_HIMR_PSTIMEOUT BIT(23)
|
||||
#define REG_SDIO_HIMR_OCPINT BIT(24)
|
||||
#define REG_SDIO_HIMR_ATIMEND BIT(25)
|
||||
#define REG_SDIO_HIMR_ATIMEND_E BIT(26)
|
||||
#define REG_SDIO_HIMR_CTWEND BIT(27)
|
||||
/* the following two are RTL8188 SDIO Specific */
|
||||
#define REG_SDIO_HIMR_MCU_ERR BIT(28)
|
||||
#define REG_SDIO_HIMR_TSF_BIT32_TOGGLE BIT(29)
|
||||
|
||||
/* SDIO Host Interrupt Service Routine */
|
||||
#define REG_SDIO_HISR (SDIO_LOCAL_OFFSET + 0x0018)
|
||||
#define REG_SDIO_HISR_RX_REQUEST BIT(0)
|
||||
#define REG_SDIO_HISR_AVAL BIT(1)
|
||||
#define REG_SDIO_HISR_TXERR BIT(2)
|
||||
#define REG_SDIO_HISR_RXERR BIT(3)
|
||||
#define REG_SDIO_HISR_TXFOVW BIT(4)
|
||||
#define REG_SDIO_HISR_RXFOVW BIT(5)
|
||||
#define REG_SDIO_HISR_TXBCNOK BIT(6)
|
||||
#define REG_SDIO_HISR_TXBCNERR BIT(7)
|
||||
#define REG_SDIO_HISR_BCNERLY_INT BIT(16)
|
||||
#define REG_SDIO_HISR_C2HCMD BIT(17)
|
||||
#define REG_SDIO_HISR_CPWM1 BIT(18)
|
||||
#define REG_SDIO_HISR_CPWM2 BIT(19)
|
||||
#define REG_SDIO_HISR_HSISR_IND BIT(20)
|
||||
#define REG_SDIO_HISR_GTINT3_IND BIT(21)
|
||||
#define REG_SDIO_HISR_GTINT4_IND BIT(22)
|
||||
#define REG_SDIO_HISR_PSTIMEOUT BIT(23)
|
||||
#define REG_SDIO_HISR_OCPINT BIT(24)
|
||||
#define REG_SDIO_HISR_ATIMEND BIT(25)
|
||||
#define REG_SDIO_HISR_ATIMEND_E BIT(26)
|
||||
#define REG_SDIO_HISR_CTWEND BIT(27)
|
||||
/* the following two are RTL8188 SDIO Specific */
|
||||
#define REG_SDIO_HISR_MCU_ERR BIT(28)
|
||||
#define REG_SDIO_HISR_TSF_BIT32_TOGGLE BIT(29)
|
||||
|
||||
/* HCI Current Power Mode */
|
||||
#define REG_SDIO_HCPWM (SDIO_LOCAL_OFFSET + 0x0019)
|
||||
/* RXDMA Request Length */
|
||||
#define REG_SDIO_RX0_REQ_LEN (SDIO_LOCAL_OFFSET + 0x001C)
|
||||
/* OQT Free Page */
|
||||
#define REG_SDIO_OQT_FREE_PG (SDIO_LOCAL_OFFSET + 0x001E)
|
||||
/* Free Tx Buffer Page */
|
||||
#define REG_SDIO_FREE_TXPG (SDIO_LOCAL_OFFSET + 0x0020)
|
||||
/* HCI Current Power Mode 1 */
|
||||
#define REG_SDIO_HCPWM1 (SDIO_LOCAL_OFFSET + 0x0024)
|
||||
/* HCI Current Power Mode 2 */
|
||||
#define REG_SDIO_HCPWM2 (SDIO_LOCAL_OFFSET + 0x0026)
|
||||
/* Free Tx Page Sequence */
|
||||
#define REG_SDIO_FREE_TXPG_SEQ (SDIO_LOCAL_OFFSET + 0x0028)
|
||||
/* HTSF Information */
|
||||
#define REG_SDIO_HTSFR_INFO (SDIO_LOCAL_OFFSET + 0x0030)
|
||||
#define REG_SDIO_HCPWM1_V2 (SDIO_LOCAL_OFFSET + 0x0038)
|
||||
/* H2C */
|
||||
#define REG_SDIO_H2C (SDIO_LOCAL_OFFSET + 0x0060)
|
||||
/* HCI Request Power Mode 1 */
|
||||
#define REG_SDIO_HRPWM1 (SDIO_LOCAL_OFFSET + 0x0080)
|
||||
/* HCI Request Power Mode 2 */
|
||||
#define REG_SDIO_HRPWM2 (SDIO_LOCAL_OFFSET + 0x0082)
|
||||
/* HCI Power Save Clock */
|
||||
#define REG_SDIO_HPS_CLKR (SDIO_LOCAL_OFFSET + 0x0084)
|
||||
/* SDIO HCI Suspend Control */
|
||||
#define REG_SDIO_HSUS_CTRL (SDIO_LOCAL_OFFSET + 0x0086)
|
||||
#define BIT_HCI_SUS_REQ BIT(0)
|
||||
#define BIT_HCI_RESUME_RDY BIT(1)
|
||||
/* SDIO Host Extension Interrupt Mask Always */
|
||||
#define REG_SDIO_HIMR_ON (SDIO_LOCAL_OFFSET + 0x0090)
|
||||
/* SDIO Host Extension Interrupt Status Always */
|
||||
#define REG_SDIO_HISR_ON (SDIO_LOCAL_OFFSET + 0x0091)
|
||||
|
||||
#define REG_SDIO_INDIRECT_REG_CFG (SDIO_LOCAL_OFFSET + 0x0040)
|
||||
#define BIT_SDIO_INDIRECT_REG_CFG_WORD BIT(16)
|
||||
#define BIT_SDIO_INDIRECT_REG_CFG_DWORD BIT(17)
|
||||
#define BIT_SDIO_INDIRECT_REG_CFG_WRITE BIT(18)
|
||||
#define BIT_SDIO_INDIRECT_REG_CFG_READ BIT(19)
|
||||
#define BIT_SDIO_INDIRECT_REG_CFG_UNK20 BIT(20)
|
||||
#define REG_SDIO_INDIRECT_REG_DATA (SDIO_LOCAL_OFFSET + 0x0044)
|
||||
|
||||
/* Sdio Address for SDIO Local Reg, TRX FIFO, MAC Reg */
|
||||
#define REG_SDIO_CMD_ADDR_MSK GENMASK(16, 13)
|
||||
#define REG_SDIO_CMD_ADDR_SDIO_REG 0
|
||||
#define REG_SDIO_CMD_ADDR_MAC_REG 8
|
||||
#define REG_SDIO_CMD_ADDR_TXFF_HIGH 4
|
||||
#define REG_SDIO_CMD_ADDR_TXFF_LOW 6
|
||||
#define REG_SDIO_CMD_ADDR_TXFF_NORMAL 5
|
||||
#define REG_SDIO_CMD_ADDR_TXFF_EXTRA 7
|
||||
#define REG_SDIO_CMD_ADDR_RXFF 7
|
||||
|
||||
#define RTW_SDIO_BLOCK_SIZE 512
|
||||
#define RTW_SDIO_ADDR_RX_RX0FF_GEN(_id) (0x0e000 | ((_id) & 0x3))
|
||||
|
||||
#define RTW_SDIO_DATA_PTR_ALIGN 8
|
||||
|
||||
struct sdio_func;
|
||||
struct sdio_device_id;
|
||||
|
||||
struct rtw_sdio_tx_data {
|
||||
u8 sn;
|
||||
};
|
||||
|
||||
struct rtw_sdio_work_data {
|
||||
struct work_struct work;
|
||||
struct rtw_dev *rtwdev;
|
||||
};
|
||||
|
||||
struct rtw_sdio {
|
||||
struct sdio_func *sdio_func;
|
||||
|
||||
u32 irq_mask;
|
||||
u8 rx_addr;
|
||||
bool sdio3_bus_mode;
|
||||
|
||||
void *irq_thread;
|
||||
|
||||
struct workqueue_struct *txwq;
|
||||
struct rtw_sdio_work_data *tx_handler_data;
|
||||
struct sk_buff_head tx_queue[RTK_MAX_TX_QUEUE_NUM];
|
||||
};
|
||||
|
||||
extern const struct dev_pm_ops rtw_sdio_pm_ops;
|
||||
|
||||
int rtw_sdio_probe(struct sdio_func *sdio_func,
|
||||
const struct sdio_device_id *id);
|
||||
void rtw_sdio_remove(struct sdio_func *sdio_func);
|
||||
void rtw_sdio_shutdown(struct device *dev);
|
||||
|
||||
static inline bool rtw_sdio_is_sdio30_supported(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
|
||||
|
||||
return rtwsdio->sdio3_bus_mode;
|
||||
}
|
||||
|
||||
#endif
|
168
tx.c
168
tx.c
|
@ -34,45 +34,63 @@ void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
|
||||
void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
|
||||
{
|
||||
__le32 *txdesc = (__le32 *)skb->data;
|
||||
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
|
||||
bool more_data = false;
|
||||
|
||||
if (pkt_info->qsel == TX_DESC_QSEL_HIGH)
|
||||
more_data = true;
|
||||
|
||||
tx_desc->w0 = le32_encode_bits(pkt_info->tx_pkt_size, RTW_TX_DESC_W0_TXPKTSIZE) |
|
||||
le32_encode_bits(pkt_info->offset, RTW_TX_DESC_W0_OFFSET) |
|
||||
le32_encode_bits(pkt_info->bmc, RTW_TX_DESC_W0_BMC) |
|
||||
le32_encode_bits(pkt_info->ls, RTW_TX_DESC_W0_LS) |
|
||||
le32_encode_bits(pkt_info->dis_qselseq, RTW_TX_DESC_W0_DISQSELSEQ);
|
||||
|
||||
tx_desc->w1 = le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) |
|
||||
le32_encode_bits(pkt_info->rate_id, RTW_TX_DESC_W1_RATE_ID) |
|
||||
le32_encode_bits(pkt_info->sec_type, RTW_TX_DESC_W1_SEC_TYPE) |
|
||||
le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET) |
|
||||
le32_encode_bits(more_data, RTW_TX_DESC_W1_MORE_DATA);
|
||||
|
||||
tx_desc->w2 = le32_encode_bits(pkt_info->ampdu_en, RTW_TX_DESC_W2_AGG_EN) |
|
||||
le32_encode_bits(pkt_info->report, RTW_TX_DESC_W2_SPE_RPT) |
|
||||
le32_encode_bits(pkt_info->ampdu_density, RTW_TX_DESC_W2_AMPDU_DEN) |
|
||||
le32_encode_bits(pkt_info->bt_null, RTW_TX_DESC_W2_BT_NULL);
|
||||
|
||||
tx_desc->w3 = le32_encode_bits(pkt_info->hw_ssn_sel, RTW_TX_DESC_W3_HW_SSN_SEL) |
|
||||
le32_encode_bits(pkt_info->use_rate, RTW_TX_DESC_W3_USE_RATE) |
|
||||
le32_encode_bits(pkt_info->dis_rate_fallback, RTW_TX_DESC_W3_DISDATAFB) |
|
||||
le32_encode_bits(pkt_info->rts, RTW_TX_DESC_W3_USE_RTS) |
|
||||
le32_encode_bits(pkt_info->nav_use_hdr, RTW_TX_DESC_W3_NAVUSEHDR) |
|
||||
le32_encode_bits(pkt_info->ampdu_factor, RTW_TX_DESC_W3_MAX_AGG_NUM);
|
||||
|
||||
tx_desc->w4 = le32_encode_bits(pkt_info->rate, RTW_TX_DESC_W4_DATARATE);
|
||||
|
||||
tx_desc->w5 = le32_encode_bits(pkt_info->short_gi, RTW_TX_DESC_W5_DATA_SHORT) |
|
||||
le32_encode_bits(pkt_info->bw, RTW_TX_DESC_W5_DATA_BW) |
|
||||
le32_encode_bits(pkt_info->ldpc, RTW_TX_DESC_W5_DATA_LDPC) |
|
||||
le32_encode_bits(pkt_info->stbc, RTW_TX_DESC_W5_DATA_STBC);
|
||||
|
||||
tx_desc->w6 = le32_encode_bits(pkt_info->sn, RTW_TX_DESC_W6_SW_DEFINE);
|
||||
|
||||
tx_desc->w8 = le32_encode_bits(pkt_info->en_hwseq, RTW_TX_DESC_W8_EN_HWSEQ);
|
||||
|
||||
tx_desc->w9 = le32_encode_bits(pkt_info->seq, RTW_TX_DESC_W9_SW_SEQ);
|
||||
|
||||
SET_TX_DESC_TXPKTSIZE(txdesc, pkt_info->tx_pkt_size);
|
||||
SET_TX_DESC_OFFSET(txdesc, pkt_info->offset);
|
||||
SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset);
|
||||
SET_TX_DESC_QSEL(txdesc, pkt_info->qsel);
|
||||
SET_TX_DESC_BMC(txdesc, pkt_info->bmc);
|
||||
SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id);
|
||||
SET_TX_DESC_DATARATE(txdesc, pkt_info->rate);
|
||||
SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback);
|
||||
SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate);
|
||||
SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type);
|
||||
SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw);
|
||||
SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq);
|
||||
SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor);
|
||||
SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density);
|
||||
SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc);
|
||||
SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc);
|
||||
SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en);
|
||||
SET_TX_DESC_LS(txdesc, pkt_info->ls);
|
||||
SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi);
|
||||
SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report);
|
||||
SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn);
|
||||
SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts);
|
||||
if (pkt_info->rts) {
|
||||
SET_TX_DESC_RTSRATE(txdesc, DESC_RATE24M);
|
||||
SET_TX_DESC_DATA_RTS_SHORT(txdesc, 1);
|
||||
tx_desc->w4 |= le32_encode_bits(DESC_RATE24M, RTW_TX_DESC_W4_RTSRATE);
|
||||
tx_desc->w5 |= le32_encode_bits(1, RTW_TX_DESC_W5_DATA_RTS_SHORT);
|
||||
}
|
||||
SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq);
|
||||
SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq);
|
||||
SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel);
|
||||
SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr);
|
||||
SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null);
|
||||
|
||||
if (pkt_info->tim_offset)
|
||||
tx_desc->w9 |= le32_encode_bits(1, RTW_TX_DESC_W9_TIM_EN) |
|
||||
le32_encode_bits(pkt_info->tim_offset, RTW_TX_DESC_W9_TIM_OFFSET);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
|
||||
|
||||
static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta)
|
||||
{
|
||||
u8 exp = sta->ht_cap.ampdu_factor;
|
||||
u8 exp = sta->deflink.ht_cap.ampdu_factor;
|
||||
|
||||
/* the least ampdu factor is 8K, and the value in the tx desc is the
|
||||
* max aggregation num, which represents val * 2 packets can be
|
||||
|
@ -83,7 +101,7 @@ static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta)
|
|||
|
||||
static u8 get_tx_ampdu_density(struct ieee80211_sta *sta)
|
||||
{
|
||||
return sta->ht_cap.ampdu_density;
|
||||
return sta->deflink.ht_cap.ampdu_density;
|
||||
}
|
||||
|
||||
static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev,
|
||||
|
@ -91,7 +109,7 @@ static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev,
|
|||
{
|
||||
u8 rate;
|
||||
|
||||
if (rtwdev->hal.rf_type == RF_2T2R && sta->ht_cap.mcs.rx_mask[1] != 0)
|
||||
if (rtwdev->hal.rf_type == RF_2T2R && sta->deflink.ht_cap.mcs.rx_mask[1] != 0)
|
||||
rate = DESC_RATEMCS15;
|
||||
else
|
||||
rate = DESC_RATEMCS7;
|
||||
|
@ -106,7 +124,7 @@ static u8 get_highest_vht_tx_rate(struct rtw_dev *rtwdev,
|
|||
u8 rate;
|
||||
u16 tx_mcs_map;
|
||||
|
||||
tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map);
|
||||
tx_mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.tx_mcs_map);
|
||||
if (efuse->hw_cap.nss == 1) {
|
||||
switch (tx_mcs_map & 0x3) {
|
||||
case IEEE80211_VHT_MCS_SUPPORT_0_7:
|
||||
|
@ -340,11 +358,11 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
|
|||
if (info->control.use_rts || skb->len > hw->wiphy->rts_threshold)
|
||||
pkt_info->rts = true;
|
||||
|
||||
if (sta->vht_cap.vht_supported)
|
||||
if (sta->deflink.vht_cap.vht_supported)
|
||||
rate = get_highest_vht_tx_rate(rtwdev, sta);
|
||||
else if (sta->ht_cap.ht_supported)
|
||||
else if (sta->deflink.ht_cap.ht_supported)
|
||||
rate = get_highest_ht_tx_rate(rtwdev, sta);
|
||||
else if (sta->supp_rates[0] <= 0xf)
|
||||
else if (sta->deflink.supp_rates[0] <= 0xf)
|
||||
rate = DESC_RATE11M;
|
||||
else
|
||||
rate = DESC_RATE54M;
|
||||
|
@ -353,7 +371,7 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
|
|||
|
||||
bw = si->bw_mode;
|
||||
rate_id = si->rate_id;
|
||||
stbc = si->stbc_en;
|
||||
stbc = rtwdev->hal.txrx_1ss ? false : si->stbc_en;
|
||||
ldpc = si->ldpc_en;
|
||||
|
||||
out:
|
||||
|
@ -380,7 +398,7 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
|
|||
struct ieee80211_sta *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct rtw_sta_info *si;
|
||||
|
@ -420,7 +438,7 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
|
|||
struct sk_buff *skb,
|
||||
enum rtw_rsvd_packet_type type)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
bool bmc;
|
||||
|
||||
|
@ -448,6 +466,19 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
|
|||
if (type == RSVD_QOS_NULL)
|
||||
pkt_info->bt_null = true;
|
||||
|
||||
if (type == RSVD_BEACON) {
|
||||
struct rtw_rsvd_page *rsvd_pkt;
|
||||
int hdr_len;
|
||||
|
||||
rsvd_pkt = list_first_entry_or_null(&rtwdev->rsvd_page_list,
|
||||
struct rtw_rsvd_page,
|
||||
build_list);
|
||||
if (rsvd_pkt && rsvd_pkt->tim_offset != 0) {
|
||||
hdr_len = sizeof(struct ieee80211_hdr_3addr);
|
||||
pkt_info->tim_offset = rsvd_pkt->tim_offset - hdr_len;
|
||||
}
|
||||
}
|
||||
|
||||
rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
|
||||
|
||||
/* TODO: need to change hw port and hw ssn sel for multiple vifs */
|
||||
|
@ -458,7 +489,7 @@ rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
|
|||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *buf, u32 size)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct sk_buff *skb;
|
||||
u32 tx_pkt_desc_sz;
|
||||
u32 length;
|
||||
|
@ -484,7 +515,7 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
|
|||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *buf, u32 size)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct sk_buff *skb;
|
||||
u32 tx_pkt_desc_sz;
|
||||
u32 length;
|
||||
|
@ -575,8 +606,6 @@ static int rtw_txq_push_skb(struct rtw_dev *rtwdev,
|
|||
rtw_err(rtwdev, "failed to write TX skb to HCI\n");
|
||||
return ret;
|
||||
}
|
||||
rtwtxq->last_push = jiffies;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -618,9 +647,8 @@ static void rtw_txq_push(struct rtw_dev *rtwdev,
|
|||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void rtw_tx_work(struct work_struct *w)
|
||||
void __rtw_tx_work(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work);
|
||||
struct rtw_txq *rtwtxq, *tmp;
|
||||
|
||||
spin_lock_bh(&rtwdev->txq_lock);
|
||||
|
@ -641,6 +669,13 @@ void rtw_tx_work(struct work_struct *w)
|
|||
spin_unlock_bh(&rtwdev->txq_lock);
|
||||
}
|
||||
|
||||
void rtw_tx_work(struct work_struct *w)
|
||||
{
|
||||
struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work);
|
||||
|
||||
__rtw_tx_work(rtwdev);
|
||||
}
|
||||
|
||||
void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
|
||||
{
|
||||
struct rtw_txq *rtwtxq;
|
||||
|
@ -665,3 +700,44 @@ void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
|
|||
list_del_init(&rtwtxq->list);
|
||||
spin_unlock_bh(&rtwdev->txq_lock);
|
||||
}
|
||||
|
||||
static const enum rtw_tx_queue_type ac_to_hwq[] = {
|
||||
[IEEE80211_AC_VO] = RTW_TX_QUEUE_VO,
|
||||
[IEEE80211_AC_VI] = RTW_TX_QUEUE_VI,
|
||||
[IEEE80211_AC_BE] = RTW_TX_QUEUE_BE,
|
||||
[IEEE80211_AC_BK] = RTW_TX_QUEUE_BK,
|
||||
};
|
||||
|
||||
static_assert(ARRAY_SIZE(ac_to_hwq) == IEEE80211_NUM_ACS);
|
||||
|
||||
enum rtw_tx_queue_type rtw_tx_ac_to_hwq(enum ieee80211_ac_numbers ac)
|
||||
{
|
||||
if (WARN_ON(unlikely(ac >= IEEE80211_NUM_ACS)))
|
||||
return RTW_TX_QUEUE_BE;
|
||||
|
||||
return ac_to_hwq[ac];
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_tx_ac_to_hwq);
|
||||
|
||||
enum rtw_tx_queue_type rtw_tx_queue_mapping(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 q_mapping = skb_get_queue_mapping(skb);
|
||||
enum rtw_tx_queue_type queue;
|
||||
|
||||
if (unlikely(ieee80211_is_beacon(fc)))
|
||||
queue = RTW_TX_QUEUE_BCN;
|
||||
else if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
|
||||
queue = RTW_TX_QUEUE_MGMT;
|
||||
else if (is_broadcast_ether_addr(hdr->addr1) ||
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
queue = RTW_TX_QUEUE_HI0;
|
||||
else if (WARN_ON_ONCE(q_mapping >= ARRAY_SIZE(ac_to_hwq)))
|
||||
queue = ac_to_hwq[IEEE80211_AC_BE];
|
||||
else
|
||||
queue = ac_to_hwq[q_mapping];
|
||||
|
||||
return queue;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_tx_queue_mapping);
|
||||
|
|
134
tx.h
134
tx.h
|
@ -9,64 +9,53 @@
|
|||
|
||||
#define RTW_TX_PROBE_TIMEOUT msecs_to_jiffies(500)
|
||||
|
||||
#define SET_TX_DESC_TXPKTSIZE(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(15, 0))
|
||||
#define SET_TX_DESC_OFFSET(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(23, 16))
|
||||
#define SET_TX_DESC_PKT_OFFSET(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(28, 24))
|
||||
#define SET_TX_DESC_QSEL(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(12, 8))
|
||||
#define SET_TX_DESC_BMC(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(24))
|
||||
#define SET_TX_DESC_RATE_ID(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(20, 16))
|
||||
#define SET_TX_DESC_DATARATE(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(6, 0))
|
||||
#define SET_TX_DESC_DISDATAFB(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(10))
|
||||
#define SET_TX_DESC_USE_RATE(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(8))
|
||||
#define SET_TX_DESC_SEC_TYPE(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(23, 22))
|
||||
#define SET_TX_DESC_DATA_BW(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(6, 5))
|
||||
#define SET_TX_DESC_SW_SEQ(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(23, 12))
|
||||
#define SET_TX_DESC_MAX_AGG_NUM(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(21, 17))
|
||||
#define SET_TX_DESC_USE_RTS(tx_desc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(12))
|
||||
#define SET_TX_DESC_RTSRATE(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(28, 24))
|
||||
#define SET_TX_DESC_DATA_RTS_SHORT(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(12))
|
||||
#define SET_TX_DESC_AMPDU_DENSITY(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, GENMASK(22, 20))
|
||||
#define SET_TX_DESC_DATA_STBC(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(9, 8))
|
||||
#define SET_TX_DESC_DATA_LDPC(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(7))
|
||||
#define SET_TX_DESC_AGG_EN(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(12))
|
||||
#define SET_TX_DESC_LS(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(26))
|
||||
#define SET_TX_DESC_DATA_SHORT(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(4))
|
||||
#define SET_TX_DESC_SPE_RPT(tx_desc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(19))
|
||||
#define SET_TX_DESC_SW_DEFINE(tx_desc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x06, value, GENMASK(11, 0))
|
||||
#define SET_TX_DESC_DISQSELSEQ(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(31))
|
||||
#define SET_TX_DESC_EN_HWSEQ(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(15))
|
||||
#define SET_TX_DESC_HW_SSN_SEL(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(7, 6))
|
||||
#define SET_TX_DESC_NAVUSEHDR(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15))
|
||||
#define SET_TX_DESC_BT_NULL(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23))
|
||||
struct rtw_tx_desc {
|
||||
__le32 w0;
|
||||
__le32 w1;
|
||||
__le32 w2;
|
||||
__le32 w3;
|
||||
__le32 w4;
|
||||
__le32 w5;
|
||||
__le32 w6;
|
||||
__le32 w7;
|
||||
__le32 w8;
|
||||
__le32 w9;
|
||||
} __packed;
|
||||
|
||||
#define RTW_TX_DESC_W0_TXPKTSIZE GENMASK(15, 0)
|
||||
#define RTW_TX_DESC_W0_OFFSET GENMASK(23, 16)
|
||||
#define RTW_TX_DESC_W0_BMC BIT(24)
|
||||
#define RTW_TX_DESC_W0_LS BIT(26)
|
||||
#define RTW_TX_DESC_W0_DISQSELSEQ BIT(31)
|
||||
#define RTW_TX_DESC_W1_QSEL GENMASK(12, 8)
|
||||
#define RTW_TX_DESC_W1_RATE_ID GENMASK(20, 16)
|
||||
#define RTW_TX_DESC_W1_SEC_TYPE GENMASK(23, 22)
|
||||
#define RTW_TX_DESC_W1_PKT_OFFSET GENMASK(28, 24)
|
||||
#define RTW_TX_DESC_W1_MORE_DATA BIT(29)
|
||||
#define RTW_TX_DESC_W2_AGG_EN BIT(12)
|
||||
#define RTW_TX_DESC_W2_SPE_RPT BIT(19)
|
||||
#define RTW_TX_DESC_W2_AMPDU_DEN GENMASK(22, 20)
|
||||
#define RTW_TX_DESC_W2_BT_NULL BIT(23)
|
||||
#define RTW_TX_DESC_W3_HW_SSN_SEL GENMASK(7, 6)
|
||||
#define RTW_TX_DESC_W3_USE_RATE BIT(8)
|
||||
#define RTW_TX_DESC_W3_DISDATAFB BIT(10)
|
||||
#define RTW_TX_DESC_W3_USE_RTS BIT(12)
|
||||
#define RTW_TX_DESC_W3_NAVUSEHDR BIT(15)
|
||||
#define RTW_TX_DESC_W3_MAX_AGG_NUM GENMASK(21, 17)
|
||||
#define RTW_TX_DESC_W4_DATARATE GENMASK(6, 0)
|
||||
#define RTW_TX_DESC_W4_RTSRATE GENMASK(28, 24)
|
||||
#define RTW_TX_DESC_W5_DATA_SHORT BIT(4)
|
||||
#define RTW_TX_DESC_W5_DATA_BW GENMASK(6, 5)
|
||||
#define RTW_TX_DESC_W5_DATA_LDPC BIT(7)
|
||||
#define RTW_TX_DESC_W5_DATA_STBC GENMASK(9, 8)
|
||||
#define RTW_TX_DESC_W5_DATA_RTS_SHORT BIT(12)
|
||||
#define RTW_TX_DESC_W6_SW_DEFINE GENMASK(11, 0)
|
||||
#define RTW_TX_DESC_W7_TXDESC_CHECKSUM GENMASK(15, 0)
|
||||
#define RTW_TX_DESC_W7_DMA_TXAGG_NUM GENMASK(31, 24)
|
||||
#define RTW_TX_DESC_W8_EN_HWSEQ BIT(15)
|
||||
#define RTW_TX_DESC_W9_SW_SEQ GENMASK(23, 12)
|
||||
#define RTW_TX_DESC_W9_TIM_EN BIT(7)
|
||||
#define RTW_TX_DESC_W9_TIM_OFFSET GENMASK(6, 0)
|
||||
|
||||
enum rtw_tx_desc_queue_select {
|
||||
TX_DESC_QSEL_TID0 = 0,
|
||||
|
@ -99,6 +88,7 @@ void rtw_tx(struct rtw_dev *rtwdev,
|
|||
void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
|
||||
void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
|
||||
void rtw_tx_work(struct work_struct *w);
|
||||
void __rtw_tx_work(struct rtw_dev *rtwdev);
|
||||
void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -119,4 +109,32 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
|
|||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *buf, u32 size);
|
||||
|
||||
enum rtw_tx_queue_type rtw_tx_ac_to_hwq(enum ieee80211_ac_numbers ac);
|
||||
enum rtw_tx_queue_type rtw_tx_queue_mapping(struct sk_buff *skb);
|
||||
|
||||
static inline
|
||||
void fill_txdesc_checksum_common(u8 *txdesc, size_t words)
|
||||
{
|
||||
__le16 chksum = 0;
|
||||
__le16 *data = (__le16 *)(txdesc);
|
||||
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
|
||||
|
||||
le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
|
||||
|
||||
while (words--)
|
||||
chksum ^= *data++;
|
||||
|
||||
le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
|
||||
RTW_TX_DESC_W7_TXDESC_CHECKSUM);
|
||||
}
|
||||
|
||||
static inline void rtw_tx_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->fill_txdesc_checksum(rtwdev, pkt_info, txdesc);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
913
usb.c
Normal file
913
usb.c
Normal file
|
@ -0,0 +1,913 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "main.h"
|
||||
#include "debug.h"
|
||||
#include "reg.h"
|
||||
#include "tx.h"
|
||||
#include "rx.h"
|
||||
#include "fw.h"
|
||||
#include "ps.h"
|
||||
#include "usb.h"
|
||||
|
||||
#define RTW_USB_MAX_RXQ_LEN 512
|
||||
|
||||
struct rtw_usb_txcb {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct sk_buff_head tx_ack_queue;
|
||||
};
|
||||
|
||||
static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
|
||||
struct sk_buff *skb, int agg_num)
|
||||
{
|
||||
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
|
||||
struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
||||
struct rtw_tx_pkt_info pkt_info;
|
||||
|
||||
le32p_replace_bits(&tx_desc->w7, agg_num, RTW_TX_DESC_W7_DMA_TXAGG_NUM);
|
||||
pkt_info.pkt_offset = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_PKT_OFFSET);
|
||||
rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
|
||||
}
|
||||
|
||||
static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_device *udev = rtwusb->udev;
|
||||
__le32 *data;
|
||||
unsigned long flags;
|
||||
int idx, ret;
|
||||
static int count;
|
||||
|
||||
spin_lock_irqsave(&rtwusb->usb_lock, flags);
|
||||
|
||||
idx = rtwusb->usb_data_index;
|
||||
rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1);
|
||||
|
||||
spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
|
||||
|
||||
data = &rtwusb->usb_data[idx];
|
||||
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
RTW_USB_CMD_REQ, RTW_USB_CMD_READ, addr,
|
||||
RTW_USB_VENQT_CMD_IDX, data, len, 1000);
|
||||
if (ret < 0 && ret != -ENODEV && count++ < 4)
|
||||
rtw_err(rtwdev, "read register 0x%x failed with %d\n",
|
||||
addr, ret);
|
||||
|
||||
return le32_to_cpu(*data);
|
||||
}
|
||||
|
||||
static u8 rtw_usb_read8(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return (u8)rtw_usb_read(rtwdev, addr, 1);
|
||||
}
|
||||
|
||||
static u16 rtw_usb_read16(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return (u16)rtw_usb_read(rtwdev, addr, 2);
|
||||
}
|
||||
|
||||
static u32 rtw_usb_read32(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return (u32)rtw_usb_read(rtwdev, addr, 4);
|
||||
}
|
||||
|
||||
static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)
|
||||
{
|
||||
struct rtw_usb *rtwusb = (struct rtw_usb *)rtwdev->priv;
|
||||
struct usb_device *udev = rtwusb->udev;
|
||||
unsigned long flags;
|
||||
__le32 *data;
|
||||
int idx, ret;
|
||||
static int count;
|
||||
|
||||
spin_lock_irqsave(&rtwusb->usb_lock, flags);
|
||||
|
||||
idx = rtwusb->usb_data_index;
|
||||
rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1);
|
||||
|
||||
spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
|
||||
|
||||
data = &rtwusb->usb_data[idx];
|
||||
|
||||
*data = cpu_to_le32(val);
|
||||
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
|
||||
addr, 0, data, len, 30000);
|
||||
if (ret < 0 && ret != -ENODEV && count++ < 4)
|
||||
rtw_err(rtwdev, "write register 0x%x failed with %d\n",
|
||||
addr, ret);
|
||||
}
|
||||
|
||||
static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
|
||||
{
|
||||
rtw_usb_write(rtwdev, addr, val, 1);
|
||||
}
|
||||
|
||||
static void rtw_usb_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
|
||||
{
|
||||
rtw_usb_write(rtwdev, addr, val, 2);
|
||||
}
|
||||
|
||||
static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
|
||||
{
|
||||
rtw_usb_write(rtwdev, addr, val, 4);
|
||||
}
|
||||
|
||||
static int dma_mapping_to_ep(enum rtw_dma_mapping dma_mapping)
|
||||
{
|
||||
switch (dma_mapping) {
|
||||
case RTW_DMA_MAPPING_HIGH:
|
||||
return 0;
|
||||
case RTW_DMA_MAPPING_NORMAL:
|
||||
return 1;
|
||||
case RTW_DMA_MAPPING_LOW:
|
||||
return 2;
|
||||
case RTW_DMA_MAPPING_EXTRA:
|
||||
return 3;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int rtw_usb_parse(struct rtw_dev *rtwdev,
|
||||
struct usb_interface *interface)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_host_interface *host_interface = &interface->altsetting[0];
|
||||
struct usb_interface_descriptor *interface_desc = &host_interface->desc;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
int num_out_pipes = 0;
|
||||
int i;
|
||||
u8 num;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_rqpn *rqpn;
|
||||
|
||||
for (i = 0; i < interface_desc->bNumEndpoints; i++) {
|
||||
endpoint = &host_interface->endpoint[i].desc;
|
||||
num = usb_endpoint_num(endpoint);
|
||||
|
||||
if (usb_endpoint_dir_in(endpoint) &&
|
||||
usb_endpoint_xfer_bulk(endpoint)) {
|
||||
if (rtwusb->pipe_in) {
|
||||
rtw_err(rtwdev, "IN pipes overflow\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtwusb->pipe_in = num;
|
||||
}
|
||||
|
||||
if (usb_endpoint_dir_in(endpoint) &&
|
||||
usb_endpoint_xfer_int(endpoint)) {
|
||||
if (rtwusb->pipe_interrupt) {
|
||||
rtw_err(rtwdev, "INT pipes overflow\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtwusb->pipe_interrupt = num;
|
||||
}
|
||||
|
||||
if (usb_endpoint_dir_out(endpoint) &&
|
||||
usb_endpoint_xfer_bulk(endpoint)) {
|
||||
if (num_out_pipes >= ARRAY_SIZE(rtwusb->out_ep)) {
|
||||
rtw_err(rtwdev, "OUT pipes overflow\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtwusb->out_ep[num_out_pipes++] = num;
|
||||
}
|
||||
}
|
||||
|
||||
rtwdev->hci.bulkout_num = num_out_pipes;
|
||||
|
||||
if (num_out_pipes < 1 || num_out_pipes > 4) {
|
||||
rtw_err(rtwdev, "invalid number of endpoints %d\n", num_out_pipes);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rqpn = &chip->rqpn_table[num_out_pipes];
|
||||
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = dma_mapping_to_ep(rqpn->dma_map_be);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = dma_mapping_to_ep(rqpn->dma_map_bk);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = dma_mapping_to_ep(rqpn->dma_map_bk);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = dma_mapping_to_ep(rqpn->dma_map_be);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = dma_mapping_to_ep(rqpn->dma_map_vi);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = dma_mapping_to_ep(rqpn->dma_map_vi);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = dma_mapping_to_ep(rqpn->dma_map_vo);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = dma_mapping_to_ep(rqpn->dma_map_vo);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID8] = -EINVAL;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID9] = -EINVAL;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID10] = -EINVAL;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID11] = -EINVAL;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID12] = -EINVAL;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID13] = -EINVAL;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID14] = -EINVAL;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID15] = -EINVAL;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_BEACON] = dma_mapping_to_ep(rqpn->dma_map_hi);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_HIGH] = dma_mapping_to_ep(rqpn->dma_map_hi);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_MGMT] = dma_mapping_to_ep(rqpn->dma_map_mg);
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_H2C] = dma_mapping_to_ep(rqpn->dma_map_hi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_write_port_tx_complete(struct urb *urb)
|
||||
{
|
||||
struct rtw_usb_txcb *txcb = urb->context;
|
||||
struct rtw_dev *rtwdev = txcb->rtwdev;
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
|
||||
while (true) {
|
||||
struct sk_buff *skb = skb_dequeue(&txcb->tx_ack_queue);
|
||||
struct ieee80211_tx_info *info;
|
||||
struct rtw_usb_tx_data *tx_data;
|
||||
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
tx_data = rtw_usb_get_tx_data(skb);
|
||||
|
||||
/* enqueue to wait for tx report */
|
||||
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
|
||||
rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* always ACK for others, then they won't be marked as drop */
|
||||
ieee80211_tx_info_clear_status(info);
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
|
||||
else
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
}
|
||||
|
||||
kfree(txcb);
|
||||
}
|
||||
|
||||
static int qsel_to_ep(struct rtw_usb *rtwusb, unsigned int qsel)
|
||||
{
|
||||
if (qsel >= ARRAY_SIZE(rtwusb->qsel_to_ep))
|
||||
return -EINVAL;
|
||||
|
||||
return rtwusb->qsel_to_ep[qsel];
|
||||
}
|
||||
|
||||
static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *skb,
|
||||
usb_complete_t cb, void *context)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_device *usbd = rtwusb->udev;
|
||||
struct urb *urb;
|
||||
unsigned int pipe;
|
||||
int ret;
|
||||
int ep = qsel_to_ep(rtwusb, qsel);
|
||||
|
||||
if (ep < 0)
|
||||
return ep;
|
||||
|
||||
pipe = usb_sndbulkpipe(usbd, rtwusb->out_ep[ep]);
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
usb_fill_bulk_urb(urb, usbd, pipe, skb->data, skb->len, cb, context);
|
||||
urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list)
|
||||
{
|
||||
struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
||||
struct rtw_tx_desc *tx_desc;
|
||||
struct rtw_usb_txcb *txcb;
|
||||
struct sk_buff *skb_head;
|
||||
struct sk_buff *skb_iter;
|
||||
int agg_num = 0;
|
||||
unsigned int align_next = 0;
|
||||
u8 qsel;
|
||||
|
||||
if (skb_queue_empty(list))
|
||||
return false;
|
||||
|
||||
txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC);
|
||||
if (!txcb)
|
||||
return false;
|
||||
|
||||
txcb->rtwdev = rtwdev;
|
||||
skb_queue_head_init(&txcb->tx_ack_queue);
|
||||
|
||||
skb_iter = skb_dequeue(list);
|
||||
|
||||
if (skb_queue_empty(list)) {
|
||||
skb_head = skb_iter;
|
||||
goto queue;
|
||||
}
|
||||
|
||||
skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ);
|
||||
if (!skb_head) {
|
||||
skb_head = skb_iter;
|
||||
goto queue;
|
||||
}
|
||||
|
||||
while (skb_iter) {
|
||||
unsigned long flags;
|
||||
|
||||
skb_put(skb_head, align_next);
|
||||
skb_put_data(skb_head, skb_iter->data, skb_iter->len);
|
||||
|
||||
align_next = ALIGN(skb_iter->len, 8) - skb_iter->len;
|
||||
|
||||
agg_num++;
|
||||
|
||||
skb_queue_tail(&txcb->tx_ack_queue, skb_iter);
|
||||
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
|
||||
skb_iter = skb_peek(list);
|
||||
|
||||
if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ)
|
||||
__skb_unlink(skb_iter, list);
|
||||
else
|
||||
skb_iter = NULL;
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
}
|
||||
|
||||
if (agg_num > 1)
|
||||
rtw_usb_fill_tx_checksum(rtwusb, skb_head, agg_num);
|
||||
|
||||
queue:
|
||||
skb_queue_tail(&txcb->tx_ack_queue, skb_head);
|
||||
tx_desc = (struct rtw_tx_desc *)skb_head->data;
|
||||
qsel = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_QSEL);
|
||||
|
||||
rtw_usb_write_port(rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rtw_usb_tx_handler(struct work_struct *work)
|
||||
{
|
||||
struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, tx_work);
|
||||
int i, limit;
|
||||
|
||||
for (i = ARRAY_SIZE(rtwusb->tx_queue) - 1; i >= 0; i--) {
|
||||
for (limit = 0; limit < 200; limit++) {
|
||||
struct sk_buff_head *list = &rtwusb->tx_queue[i];
|
||||
|
||||
if (!rtw_usb_tx_agg_skb(rtwusb, list))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
|
||||
skb_queue_purge(&rtwusb->tx_queue[i]);
|
||||
}
|
||||
|
||||
static void rtw_usb_write_port_complete(struct urb *urb)
|
||||
{
|
||||
struct sk_buff *skb = urb->context;
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
static int rtw_usb_write_data(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *buf)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct sk_buff *skb;
|
||||
unsigned int desclen, headsize, size;
|
||||
u8 qsel;
|
||||
int ret = 0;
|
||||
|
||||
size = pkt_info->tx_pkt_size;
|
||||
qsel = pkt_info->qsel;
|
||||
desclen = chip->tx_pkt_desc_sz;
|
||||
headsize = pkt_info->offset ? pkt_info->offset : desclen;
|
||||
|
||||
skb = dev_alloc_skb(headsize + size);
|
||||
if (unlikely(!skb))
|
||||
return -ENOMEM;
|
||||
|
||||
skb_reserve(skb, headsize);
|
||||
skb_put_data(skb, buf, size);
|
||||
skb_push(skb, headsize);
|
||||
memset(skb->data, 0, headsize);
|
||||
rtw_tx_fill_tx_desc(pkt_info, skb);
|
||||
rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
|
||||
|
||||
ret = rtw_usb_write_port(rtwdev, qsel, skb,
|
||||
rtw_usb_write_port_complete, skb);
|
||||
if (unlikely(ret))
|
||||
rtw_err(rtwdev, "failed to do USB write, ret=%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtw_usb_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf,
|
||||
u32 size)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_tx_pkt_info pkt_info = {0};
|
||||
|
||||
pkt_info.tx_pkt_size = size;
|
||||
pkt_info.qsel = TX_DESC_QSEL_BEACON;
|
||||
pkt_info.offset = chip->tx_pkt_desc_sz;
|
||||
|
||||
return rtw_usb_write_data(rtwdev, &pkt_info, buf);
|
||||
}
|
||||
|
||||
static int rtw_usb_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
|
||||
{
|
||||
struct rtw_tx_pkt_info pkt_info = {0};
|
||||
|
||||
pkt_info.tx_pkt_size = size;
|
||||
pkt_info.qsel = TX_DESC_QSEL_H2C;
|
||||
|
||||
return rtw_usb_write_data(rtwdev, &pkt_info, buf);
|
||||
}
|
||||
|
||||
static u8 rtw_usb_tx_queue_mapping_to_qsel(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 qsel;
|
||||
|
||||
if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
|
||||
qsel = TX_DESC_QSEL_MGMT;
|
||||
else if (is_broadcast_ether_addr(hdr->addr1) ||
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
qsel = TX_DESC_QSEL_HIGH;
|
||||
else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK)
|
||||
qsel = skb->priority;
|
||||
else
|
||||
qsel = TX_DESC_QSEL_BEACON;
|
||||
|
||||
return qsel;
|
||||
}
|
||||
|
||||
static int rtw_usb_tx_write(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_usb_tx_data *tx_data;
|
||||
u8 *pkt_desc;
|
||||
int ep;
|
||||
|
||||
pkt_info->qsel = rtw_usb_tx_queue_mapping_to_qsel(skb);
|
||||
pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
|
||||
memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
|
||||
ep = qsel_to_ep(rtwusb, pkt_info->qsel);
|
||||
rtw_tx_fill_tx_desc(pkt_info, skb);
|
||||
rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
|
||||
tx_data = rtw_usb_get_tx_data(skb);
|
||||
tx_data->sn = pkt_info->sn;
|
||||
|
||||
skb_queue_tail(&rtwusb->tx_queue[ep], skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_tx_kick_off(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
queue_work(rtwusb->txwq, &rtwusb->tx_work);
|
||||
}
|
||||
|
||||
static void rtw_usb_rx_handler(struct work_struct *work)
|
||||
{
|
||||
struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_work);
|
||||
struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_rx_pkt_stat pkt_stat;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct sk_buff *skb;
|
||||
u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
|
||||
u32 pkt_offset;
|
||||
u8 *rx_desc;
|
||||
int limit;
|
||||
|
||||
for (limit = 0; limit < 200; limit++) {
|
||||
skb = skb_dequeue(&rtwusb->rx_queue);
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
rx_desc = skb->data;
|
||||
chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
|
||||
&rx_status);
|
||||
pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
|
||||
pkt_stat.shift;
|
||||
|
||||
if (pkt_stat.is_c2h) {
|
||||
skb_put(skb, pkt_stat.pkt_len + pkt_offset);
|
||||
rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) {
|
||||
dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_put(skb, pkt_stat.pkt_len);
|
||||
skb_reserve(skb, pkt_offset);
|
||||
memcpy(skb->cb, &rx_status, sizeof(rx_status));
|
||||
ieee80211_rx_irqsafe(rtwdev->hw, skb);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_read_port_complete(struct urb *urb);
|
||||
|
||||
static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb)
|
||||
{
|
||||
struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
||||
int error;
|
||||
|
||||
rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC);
|
||||
if (!rxcb->rx_skb)
|
||||
return;
|
||||
|
||||
usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev,
|
||||
usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in),
|
||||
rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ,
|
||||
rtw_usb_read_port_complete, rxcb);
|
||||
|
||||
error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC);
|
||||
if (error) {
|
||||
kfree_skb(rxcb->rx_skb);
|
||||
if (error != -ENODEV)
|
||||
rtw_err(rtwdev, "Err sending rx data urb %d\n",
|
||||
error);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_read_port_complete(struct urb *urb)
|
||||
{
|
||||
struct rx_usb_ctrl_block *rxcb = urb->context;
|
||||
struct rtw_dev *rtwdev = rxcb->rtwdev;
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct sk_buff *skb = rxcb->rx_skb;
|
||||
|
||||
if (urb->status == 0) {
|
||||
if (urb->actual_length >= RTW_USB_MAX_RECVBUF_SZ ||
|
||||
urb->actual_length < 24) {
|
||||
rtw_err(rtwdev, "failed to get urb length:%d\n",
|
||||
urb->actual_length);
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
skb_queue_tail(&rtwusb->rx_queue, skb);
|
||||
queue_work(rtwusb->rxwq, &rtwusb->rx_work);
|
||||
}
|
||||
rtw_usb_rx_resubmit(rtwusb, rxcb);
|
||||
} else {
|
||||
switch (urb->status) {
|
||||
case -EINVAL:
|
||||
case -EPIPE:
|
||||
case -ENODEV:
|
||||
case -ESHUTDOWN:
|
||||
case -ENOENT:
|
||||
case -EPROTO:
|
||||
case -EILSEQ:
|
||||
case -ETIME:
|
||||
case -ECOMM:
|
||||
case -EOVERFLOW:
|
||||
case -EINPROGRESS:
|
||||
break;
|
||||
default:
|
||||
rtw_err(rtwdev, "status %d\n", urb->status);
|
||||
break;
|
||||
}
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_cancel_rx_bufs(struct rtw_usb *rtwusb)
|
||||
{
|
||||
struct rx_usb_ctrl_block *rxcb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
|
||||
rxcb = &rtwusb->rx_cb[i];
|
||||
if (rxcb->rx_urb)
|
||||
usb_kill_urb(rxcb->rx_urb);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_free_rx_bufs(struct rtw_usb *rtwusb)
|
||||
{
|
||||
struct rx_usb_ctrl_block *rxcb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
|
||||
rxcb = &rtwusb->rx_cb[i];
|
||||
if (rxcb->rx_urb) {
|
||||
usb_kill_urb(rxcb->rx_urb);
|
||||
usb_free_urb(rxcb->rx_urb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rtw_usb_alloc_rx_bufs(struct rtw_usb *rtwusb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
|
||||
struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
|
||||
|
||||
rxcb->rtwdev = rtwusb->rtwdev;
|
||||
rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!rxcb->rx_urb)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
rtw_usb_free_rx_bufs(rtwusb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int rtw_usb_setup(struct rtw_dev *rtwdev)
|
||||
{
|
||||
/* empty function for rtw_hci_ops */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtw_usb_start(struct rtw_dev *rtwdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_stop(struct rtw_dev *rtwdev)
|
||||
{
|
||||
}
|
||||
|
||||
static void rtw_usb_deep_ps(struct rtw_dev *rtwdev, bool enter)
|
||||
{
|
||||
/* empty function for rtw_hci_ops */
|
||||
}
|
||||
|
||||
static void rtw_usb_link_ps(struct rtw_dev *rtwdev, bool enter)
|
||||
{
|
||||
/* empty function for rtw_hci_ops */
|
||||
}
|
||||
|
||||
static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev)
|
||||
{
|
||||
/* empty function for rtw_hci_ops */
|
||||
}
|
||||
|
||||
static struct rtw_hci_ops rtw_usb_ops = {
|
||||
.tx_write = rtw_usb_tx_write,
|
||||
.tx_kick_off = rtw_usb_tx_kick_off,
|
||||
.setup = rtw_usb_setup,
|
||||
.start = rtw_usb_start,
|
||||
.stop = rtw_usb_stop,
|
||||
.deep_ps = rtw_usb_deep_ps,
|
||||
.link_ps = rtw_usb_link_ps,
|
||||
.interface_cfg = rtw_usb_interface_cfg,
|
||||
|
||||
.write8 = rtw_usb_write8,
|
||||
.write16 = rtw_usb_write16,
|
||||
.write32 = rtw_usb_write32,
|
||||
.read8 = rtw_usb_read8,
|
||||
.read16 = rtw_usb_read16,
|
||||
.read32 = rtw_usb_read32,
|
||||
|
||||
.write_data_rsvd_page = rtw_usb_write_data_rsvd_page,
|
||||
.write_data_h2c = rtw_usb_write_data_h2c,
|
||||
};
|
||||
|
||||
static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
int i;
|
||||
|
||||
rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq");
|
||||
if (!rtwusb->rxwq) {
|
||||
rtw_err(rtwdev, "failed to create RX work queue\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skb_queue_head_init(&rtwusb->rx_queue);
|
||||
|
||||
INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler);
|
||||
|
||||
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
|
||||
struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
|
||||
|
||||
rtw_usb_rx_resubmit(rtwusb, rxcb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
skb_queue_purge(&rtwusb->rx_queue);
|
||||
|
||||
flush_workqueue(rtwusb->rxwq);
|
||||
destroy_workqueue(rtwusb->rxwq);
|
||||
}
|
||||
|
||||
static int rtw_usb_init_tx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
int i;
|
||||
|
||||
rtwusb->txwq = create_singlethread_workqueue("rtw88_usb: tx wq");
|
||||
if (!rtwusb->txwq) {
|
||||
rtw_err(rtwdev, "failed to create TX work queue\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
|
||||
skb_queue_head_init(&rtwusb->tx_queue[i]);
|
||||
|
||||
INIT_WORK(&rtwusb->tx_work, rtw_usb_tx_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
rtw_usb_tx_queue_purge(rtwusb);
|
||||
flush_workqueue(rtwusb->txwq);
|
||||
destroy_workqueue(rtwusb->txwq);
|
||||
}
|
||||
|
||||
static int rtw_usb_intf_init(struct rtw_dev *rtwdev,
|
||||
struct usb_interface *intf)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf));
|
||||
int ret;
|
||||
|
||||
rtwusb->udev = udev;
|
||||
ret = rtw_usb_parse(rtwdev, intf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rtwusb->usb_data = kcalloc(RTW_USB_MAX_RXTX_COUNT, sizeof(u32),
|
||||
GFP_KERNEL);
|
||||
if (!rtwusb->usb_data)
|
||||
return -ENOMEM;
|
||||
|
||||
usb_set_intfdata(intf, rtwdev->hw);
|
||||
|
||||
SET_IEEE80211_DEV(rtwdev->hw, &intf->dev);
|
||||
spin_lock_init(&rtwusb->usb_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev,
|
||||
struct usb_interface *intf)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
usb_put_dev(rtwusb->udev);
|
||||
kfree(rtwusb->usb_data);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
}
|
||||
|
||||
int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct rtw_dev *rtwdev;
|
||||
struct ieee80211_hw *hw;
|
||||
struct rtw_usb *rtwusb;
|
||||
int drv_data_size;
|
||||
int ret;
|
||||
|
||||
drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_usb);
|
||||
hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops);
|
||||
if (!hw)
|
||||
return -ENOMEM;
|
||||
|
||||
rtwdev = hw->priv;
|
||||
rtwdev->hw = hw;
|
||||
rtwdev->dev = &intf->dev;
|
||||
rtwdev->chip = (struct rtw_chip_info *)id->driver_info;
|
||||
rtwdev->hci.ops = &rtw_usb_ops;
|
||||
rtwdev->hci.type = RTW_HCI_TYPE_USB;
|
||||
|
||||
rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
rtwusb->rtwdev = rtwdev;
|
||||
|
||||
ret = rtw_usb_alloc_rx_bufs(rtwusb);
|
||||
if (ret)
|
||||
goto err_release_hw;
|
||||
|
||||
ret = rtw_core_init(rtwdev);
|
||||
if (ret)
|
||||
goto err_release_hw;
|
||||
|
||||
ret = rtw_usb_intf_init(rtwdev, intf);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to init USB interface\n");
|
||||
goto err_deinit_core;
|
||||
}
|
||||
|
||||
ret = rtw_usb_init_tx(rtwdev);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to init USB TX\n");
|
||||
goto err_destroy_usb;
|
||||
}
|
||||
|
||||
ret = rtw_usb_init_rx(rtwdev);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to init USB RX\n");
|
||||
goto err_destroy_txwq;
|
||||
}
|
||||
|
||||
ret = rtw_chip_info_setup(rtwdev);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to setup chip information\n");
|
||||
goto err_destroy_rxwq;
|
||||
}
|
||||
|
||||
ret = rtw_register_hw(rtwdev, rtwdev->hw);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to register hw\n");
|
||||
goto err_destroy_rxwq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_rxwq:
|
||||
rtw_usb_deinit_rx(rtwdev);
|
||||
|
||||
err_destroy_txwq:
|
||||
rtw_usb_deinit_tx(rtwdev);
|
||||
|
||||
err_destroy_usb:
|
||||
rtw_usb_intf_deinit(rtwdev, intf);
|
||||
|
||||
err_deinit_core:
|
||||
rtw_core_deinit(rtwdev);
|
||||
|
||||
err_release_hw:
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_usb_probe);
|
||||
|
||||
void rtw_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct ieee80211_hw *hw = usb_get_intfdata(intf);
|
||||
struct rtw_dev *rtwdev;
|
||||
struct rtw_usb *rtwusb;
|
||||
|
||||
if (!hw)
|
||||
return;
|
||||
|
||||
rtwdev = hw->priv;
|
||||
rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
rtw_usb_cancel_rx_bufs(rtwusb);
|
||||
|
||||
rtw_unregister_hw(rtwdev, hw);
|
||||
rtw_usb_deinit_tx(rtwdev);
|
||||
rtw_usb_deinit_rx(rtwdev);
|
||||
|
||||
if (rtwusb->udev->state != USB_STATE_NOTATTACHED)
|
||||
usb_reset_device(rtwusb->udev);
|
||||
|
||||
rtw_usb_free_rx_bufs(rtwusb);
|
||||
|
||||
rtw_usb_intf_deinit(rtwdev, intf);
|
||||
rtw_core_deinit(rtwdev);
|
||||
ieee80211_free_hw(hw);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_usb_disconnect);
|
||||
|
||||
MODULE_AUTHOR("Realtek Corporation");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
100
usb.h
Normal file
100
usb.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_USB_H_
|
||||
#define __RTW_USB_H_
|
||||
|
||||
#define FW_8192C_START_ADDRESS 0x1000
|
||||
#define FW_8192C_END_ADDRESS 0x5fff
|
||||
|
||||
#define RTW_USB_MAX_RXTX_COUNT 128
|
||||
#define RTW_USB_VENQT_MAX_BUF_SIZE 254
|
||||
#define MAX_USBCTRL_VENDORREQ_TIMES 10
|
||||
|
||||
#define RTW_USB_CMD_READ 0xc0
|
||||
#define RTW_USB_CMD_WRITE 0x40
|
||||
#define RTW_USB_CMD_REQ 0x05
|
||||
|
||||
#define RTW_USB_VENQT_CMD_IDX 0x00
|
||||
|
||||
#define RTW_USB_TX_SEL_HQ BIT(0)
|
||||
#define RTW_USB_TX_SEL_LQ BIT(1)
|
||||
#define RTW_USB_TX_SEL_NQ BIT(2)
|
||||
#define RTW_USB_TX_SEL_EQ BIT(3)
|
||||
|
||||
#define RTW_USB_BULK_IN_ADDR 0x80
|
||||
#define RTW_USB_INT_IN_ADDR 0x81
|
||||
|
||||
#define RTW_USB_HW_QUEUE_ENTRY 8
|
||||
|
||||
#define RTW_USB_PACKET_OFFSET_SZ 8
|
||||
#define RTW_USB_MAX_XMITBUF_SZ (1024 * 20)
|
||||
#define RTW_USB_MAX_RECVBUF_SZ 32768
|
||||
|
||||
#define RTW_USB_RECVBUFF_ALIGN_SZ 8
|
||||
|
||||
#define RTW_USB_RXAGG_SIZE 6
|
||||
#define RTW_USB_RXAGG_TIMEOUT 10
|
||||
|
||||
#define RTW_USB_RXCB_NUM 4
|
||||
|
||||
#define RTW_USB_EP_MAX 4
|
||||
|
||||
#define TX_DESC_QSEL_MAX 20
|
||||
|
||||
#define RTW_USB_VENDOR_ID_REALTEK 0x0bda
|
||||
|
||||
static inline struct rtw_usb *rtw_get_usb_priv(struct rtw_dev *rtwdev)
|
||||
{
|
||||
return (struct rtw_usb *)rtwdev->priv;
|
||||
}
|
||||
|
||||
struct rx_usb_ctrl_block {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct urb *rx_urb;
|
||||
struct sk_buff *rx_skb;
|
||||
};
|
||||
|
||||
struct rtw_usb_tx_data {
|
||||
u8 sn;
|
||||
};
|
||||
|
||||
struct rtw_usb {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct usb_device *udev;
|
||||
|
||||
/* protects usb_data_index */
|
||||
spinlock_t usb_lock;
|
||||
__le32 *usb_data;
|
||||
unsigned int usb_data_index;
|
||||
|
||||
u8 pipe_interrupt;
|
||||
u8 pipe_in;
|
||||
u8 out_ep[RTW_USB_EP_MAX];
|
||||
int qsel_to_ep[TX_DESC_QSEL_MAX];
|
||||
|
||||
struct workqueue_struct *txwq, *rxwq;
|
||||
|
||||
struct sk_buff_head tx_queue[RTW_USB_EP_MAX];
|
||||
struct work_struct tx_work;
|
||||
|
||||
struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM];
|
||||
struct sk_buff_head rx_queue;
|
||||
struct work_struct rx_work;
|
||||
};
|
||||
|
||||
static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) >
|
||||
sizeof(info->status.status_driver_data));
|
||||
|
||||
return (struct rtw_usb_tx_data *)info->status.status_driver_data;
|
||||
}
|
||||
|
||||
int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id);
|
||||
void rtw_usb_disconnect(struct usb_interface *intf);
|
||||
|
||||
#endif
|
104
util.c
104
util.c
|
@ -23,7 +23,7 @@ EXPORT_SYMBOL(check_hw_ready);
|
|||
|
||||
bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr;
|
||||
|
||||
if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1))
|
||||
|
@ -37,7 +37,7 @@ bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val)
|
|||
|
||||
bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value)
|
||||
{
|
||||
struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr;
|
||||
|
||||
if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1))
|
||||
|
@ -105,3 +105,103 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss)
|
|||
*mcs = rate - DESC_RATEMCS0;
|
||||
}
|
||||
}
|
||||
|
||||
struct rtw_stas_entry {
|
||||
struct list_head list;
|
||||
struct ieee80211_sta *sta;
|
||||
};
|
||||
|
||||
struct rtw_iter_stas_data {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static void rtw_collect_sta_iter(void *data, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct rtw_iter_stas_data *iter_stas = data;
|
||||
struct rtw_stas_entry *stas_entry;
|
||||
|
||||
stas_entry = kmalloc(sizeof(*stas_entry), GFP_ATOMIC);
|
||||
if (!stas_entry)
|
||||
return;
|
||||
|
||||
stas_entry->sta = sta;
|
||||
list_add_tail(&stas_entry->list, &iter_stas->list);
|
||||
}
|
||||
|
||||
void rtw_iterate_stas(struct rtw_dev *rtwdev,
|
||||
void (*iterator)(void *data,
|
||||
struct ieee80211_sta *sta),
|
||||
void *data)
|
||||
{
|
||||
struct rtw_iter_stas_data iter_data;
|
||||
struct rtw_stas_entry *sta_entry, *tmp;
|
||||
|
||||
/* &rtwdev->mutex makes sure no stations can be removed between
|
||||
* collecting the stations and iterating over them.
|
||||
*/
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
iter_data.rtwdev = rtwdev;
|
||||
INIT_LIST_HEAD(&iter_data.list);
|
||||
|
||||
ieee80211_iterate_stations_atomic(rtwdev->hw, rtw_collect_sta_iter,
|
||||
&iter_data);
|
||||
|
||||
list_for_each_entry_safe(sta_entry, tmp, &iter_data.list,
|
||||
list) {
|
||||
list_del_init(&sta_entry->list);
|
||||
iterator(data, sta_entry->sta);
|
||||
kfree(sta_entry);
|
||||
}
|
||||
}
|
||||
|
||||
struct rtw_vifs_entry {
|
||||
struct list_head list;
|
||||
struct ieee80211_vif *vif;
|
||||
};
|
||||
|
||||
struct rtw_iter_vifs_data {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtw_iter_vifs_data *iter_stas = data;
|
||||
struct rtw_vifs_entry *vifs_entry;
|
||||
|
||||
vifs_entry = kmalloc(sizeof(*vifs_entry), GFP_ATOMIC);
|
||||
if (!vifs_entry)
|
||||
return;
|
||||
|
||||
vifs_entry->vif = vif;
|
||||
list_add_tail(&vifs_entry->list, &iter_stas->list);
|
||||
}
|
||||
|
||||
void rtw_iterate_vifs(struct rtw_dev *rtwdev,
|
||||
void (*iterator)(void *data, struct ieee80211_vif *vif),
|
||||
void *data)
|
||||
{
|
||||
struct rtw_iter_vifs_data iter_data;
|
||||
struct rtw_vifs_entry *vif_entry, *tmp;
|
||||
|
||||
/* &rtwdev->mutex makes sure no interfaces can be removed between
|
||||
* collecting the interfaces and iterating over them.
|
||||
*/
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
iter_data.rtwdev = rtwdev;
|
||||
INIT_LIST_HEAD(&iter_data.list);
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(rtwdev->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
rtw_collect_vif_iter, &iter_data);
|
||||
|
||||
list_for_each_entry_safe(vif_entry, tmp, &iter_data.list,
|
||||
list) {
|
||||
list_del_init(&vif_entry->list);
|
||||
iterator(data, vif_entry->vif);
|
||||
kfree(vif_entry);
|
||||
}
|
||||
}
|
||||
|
|
11
util.h
11
util.h
|
@ -7,9 +7,6 @@
|
|||
|
||||
struct rtw_dev;
|
||||
|
||||
#define rtw_iterate_vifs(rtwdev, iterator, data) \
|
||||
ieee80211_iterate_active_interfaces(rtwdev->hw, \
|
||||
IEEE80211_IFACE_ITER_NORMAL, iterator, data)
|
||||
#define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \
|
||||
ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \
|
||||
IEEE80211_IFACE_ITER_NORMAL, iterator, data)
|
||||
|
@ -20,6 +17,14 @@ struct rtw_dev;
|
|||
#define rtw_iterate_keys_rcu(rtwdev, vif, iterator, data) \
|
||||
ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data)
|
||||
|
||||
void rtw_iterate_vifs(struct rtw_dev *rtwdev,
|
||||
void (*iterator)(void *data, struct ieee80211_vif *vif),
|
||||
void *data);
|
||||
void rtw_iterate_stas(struct rtw_dev *rtwdev,
|
||||
void (*iterator)(void *data,
|
||||
struct ieee80211_sta *sta),
|
||||
void *data);
|
||||
|
||||
static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
|
||||
{
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
|
2
wow.c
2
wow.c
|
@ -592,7 +592,7 @@ static int rtw_wow_leave_no_link_ps(struct rtw_dev *rtwdev)
|
|||
if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
|
||||
rtw_leave_lps_deep(rtwdev);
|
||||
} else {
|
||||
if (test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags)) {
|
||||
if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags)) {
|
||||
rtw_wow->ips_enabled = true;
|
||||
ret = rtw_leave_ips(rtwdev);
|
||||
if (ret)
|
||||
|
|
Loading…
Reference in a new issue