summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtw89/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/core.c')
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c156
1 files changed, 110 insertions, 46 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 69b181fa2966..133bf289bacb 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -256,8 +256,8 @@ void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef)
NL80211_CHAN_NO_HT);
}
-static void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
- struct rtw89_chan *chan)
+void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
+ struct rtw89_chan *chan)
{
struct ieee80211_channel *channel = chandef->chan;
enum nl80211_chan_width width = chandef->width;
@@ -318,9 +318,11 @@ static void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
{
+ struct rtw89_hal *hal = &rtwdev->hal;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_chan *chan;
enum rtw89_sub_entity_idx sub_entity_idx;
+ enum rtw89_sub_entity_idx roc_idx;
enum rtw89_phy_idx phy_idx;
enum rtw89_entity_mode mode;
bool entity_active;
@@ -330,10 +332,23 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
return;
mode = rtw89_get_entity_mode(rtwdev);
- if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode))
+ switch (mode) {
+ case RTW89_ENTITY_MODE_SCC:
+ case RTW89_ENTITY_MODE_MCC:
+ sub_entity_idx = RTW89_SUB_ENTITY_0;
+ break;
+ case RTW89_ENTITY_MODE_MCC_PREPARE:
+ sub_entity_idx = RTW89_SUB_ENTITY_1;
+ break;
+ default:
+ WARN(1, "Invalid ent mode: %d\n", mode);
return;
+ }
+
+ roc_idx = atomic_read(&hal->roc_entity_idx);
+ if (roc_idx != RTW89_SUB_ENTITY_IDLE)
+ sub_entity_idx = roc_idx;
- sub_entity_idx = RTW89_SUB_ENTITY_0;
phy_idx = RTW89_PHY_0;
chan = rtw89_chan_get(rtwdev, sub_entity_idx);
chip->ops->set_txpwr(rtwdev, chan, phy_idx);
@@ -341,43 +356,54 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
void rtw89_set_channel(struct rtw89_dev *rtwdev)
{
+ struct rtw89_hal *hal = &rtwdev->hal;
const struct rtw89_chip_info *chip = rtwdev->chip;
- const struct cfg80211_chan_def *chandef;
+ const struct rtw89_chan_rcd *chan_rcd;
+ const struct rtw89_chan *chan;
enum rtw89_sub_entity_idx sub_entity_idx;
+ enum rtw89_sub_entity_idx roc_idx;
enum rtw89_mac_idx mac_idx;
enum rtw89_phy_idx phy_idx;
- struct rtw89_chan chan;
struct rtw89_channel_help_params bak;
enum rtw89_entity_mode mode;
- bool band_changed;
bool entity_active;
entity_active = rtw89_get_entity_state(rtwdev);
mode = rtw89_entity_recalc(rtwdev);
- if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode))
+ switch (mode) {
+ case RTW89_ENTITY_MODE_SCC:
+ case RTW89_ENTITY_MODE_MCC:
+ sub_entity_idx = RTW89_SUB_ENTITY_0;
+ break;
+ case RTW89_ENTITY_MODE_MCC_PREPARE:
+ sub_entity_idx = RTW89_SUB_ENTITY_1;
+ break;
+ default:
+ WARN(1, "Invalid ent mode: %d\n", mode);
return;
+ }
+
+ roc_idx = atomic_read(&hal->roc_entity_idx);
+ if (roc_idx != RTW89_SUB_ENTITY_IDLE)
+ sub_entity_idx = roc_idx;
- sub_entity_idx = RTW89_SUB_ENTITY_0;
mac_idx = RTW89_MAC_0;
phy_idx = RTW89_PHY_0;
- chandef = rtw89_chandef_get(rtwdev, sub_entity_idx);
- rtw89_get_channel_params(chandef, &chan);
- if (WARN(chan.channel == 0, "Invalid channel\n"))
- return;
- band_changed = rtw89_assign_entity_chan(rtwdev, sub_entity_idx, &chan);
+ chan = rtw89_chan_get(rtwdev, sub_entity_idx);
+ chan_rcd = rtw89_chan_rcd_get(rtwdev, sub_entity_idx);
- rtw89_chip_set_channel_prepare(rtwdev, &bak, &chan, mac_idx, phy_idx);
+ rtw89_chip_set_channel_prepare(rtwdev, &bak, chan, mac_idx, phy_idx);
- chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx);
+ chip->ops->set_channel(rtwdev, chan, mac_idx, phy_idx);
- chip->ops->set_txpwr(rtwdev, &chan, phy_idx);
+ chip->ops->set_txpwr(rtwdev, chan, phy_idx);
- rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx);
+ rtw89_chip_set_channel_done(rtwdev, &bak, chan, mac_idx, phy_idx);
- if (!entity_active || band_changed) {
- rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan.band_type);
+ if (!entity_active || chan_rcd->band_changed) {
+ rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan->band_type);
rtw89_chip_rfk_band_changed(rtwdev, phy_idx);
}
@@ -523,12 +549,12 @@ rtw89_core_tx_update_sec_key(struct rtw89_dev *rtwdev,
}
static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
- struct rtw89_core_tx_request *tx_req)
+ struct rtw89_core_tx_request *tx_req,
+ const struct rtw89_chan *chan)
{
struct sk_buff *skb = tx_req->skb;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = tx_info->control.vif;
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
u16 lowest_rate;
if (tx_info->flags & IEEE80211_TX_CTL_NO_CCK_RATE ||
@@ -567,7 +593,8 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif = tx_req->vif;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
+ rtwvif->sub_entity_idx);
u8 qsel, ch_dma;
qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : RTW89_TX_QSEL_B0_MGMT;
@@ -584,7 +611,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
desc_info->en_wd_info = true;
desc_info->use_rate = true;
desc_info->dis_data_fb = true;
- desc_info->data_rate = rtw89_core_get_mgmt_rate(rtwdev, tx_req);
+ desc_info->data_rate = rtw89_core_get_mgmt_rate(rtwdev, tx_req, chan);
rtw89_debug(rtwdev, RTW89_DBG_TXRX,
"tx mgmt frame with rate 0x%x on channel %d (band %d, bw %d)\n",
@@ -603,7 +630,8 @@ rtw89_core_tx_update_h2c_info(struct rtw89_dev *rtwdev,
desc_info->ch_dma = RTW89_DMA_H2C;
}
-static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc)
+static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc,
+ const struct rtw89_chan *chan)
{
static const u8 rtw89_bandwidth_to_om[] = {
[RTW89_CHANNEL_WIDTH_20] = HTC_OM_CHANNEL_WIDTH_20,
@@ -614,7 +642,6 @@ static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc
};
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_hal *hal = &rtwdev->hal;
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
u8 om_bandwidth;
if (!chip->dis_2g_40m_ul_ofdma ||
@@ -1456,16 +1483,16 @@ static bool rtw89_core_rx_ppdu_match(struct rtw89_dev *rtwdev,
bool ret;
data_rate = desc_info->data_rate;
- data_rate_mode = GET_DATA_RATE_MODE(data_rate);
+ data_rate_mode = rtw89_get_data_rate_mode(rtwdev, data_rate);
if (data_rate_mode == DATA_RATE_MODE_NON_HT) {
- rate_idx = GET_DATA_RATE_NOT_HT_IDX(data_rate);
+ rate_idx = rtw89_get_data_not_ht_idx(rtwdev, data_rate);
/* rate_idx is still hardware value here */
} else if (data_rate_mode == DATA_RATE_MODE_HT) {
- rate_idx = GET_DATA_RATE_HT_IDX(data_rate);
+ rate_idx = rtw89_get_data_ht_mcs(rtwdev, data_rate);
} else if (data_rate_mode == DATA_RATE_MODE_VHT) {
- rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate);
+ rate_idx = rtw89_get_data_mcs(rtwdev, data_rate);
} else if (data_rate_mode == DATA_RATE_MODE_HE) {
- rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate);
+ rate_idx = rtw89_get_data_mcs(rtwdev, data_rate);
} else {
rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode);
}
@@ -1659,8 +1686,7 @@ static void rtw89_correct_cck_chan(struct rtw89_dev *rtwdev,
const struct rtw89_chan_rcd *rcd =
rtw89_chan_rcd_get(rtwdev, RTW89_SUB_ENTITY_0);
u16 chan = rcd->prev_primary_channel;
- u8 band = rcd->prev_band_type == RTW89_BAND_2G ?
- NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
+ u8 band = rtw89_hw_to_nl80211_band(rcd->prev_band_type);
if (status->band != NL80211_BAND_2GHZ &&
status->encoding == RX_ENC_LEGACY &&
@@ -1900,7 +1926,6 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
{
const struct cfg80211_chan_def *chandef =
rtw89_chandef_get(rtwdev, RTW89_SUB_ENTITY_0);
- const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
u16 data_rate;
u8 data_rate_mode;
@@ -1910,6 +1935,7 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
if (rtwdev->scanning &&
RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
+ const struct rtw89_chan *cur = rtw89_scan_chan_get(rtwdev);
u8 chan = cur->primary_channel;
u8 band = cur->band_type;
enum nl80211_band nl_band;
@@ -1929,26 +1955,26 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
rx_status->bw = rtw89_hw_to_rate_info_bw(desc_info->bw);
data_rate = desc_info->data_rate;
- data_rate_mode = GET_DATA_RATE_MODE(data_rate);
+ data_rate_mode = rtw89_get_data_rate_mode(rtwdev, data_rate);
if (data_rate_mode == DATA_RATE_MODE_NON_HT) {
rx_status->encoding = RX_ENC_LEGACY;
- rx_status->rate_idx = GET_DATA_RATE_NOT_HT_IDX(data_rate);
+ rx_status->rate_idx = rtw89_get_data_not_ht_idx(rtwdev, data_rate);
/* convert rate_idx after we get the correct band */
} else if (data_rate_mode == DATA_RATE_MODE_HT) {
rx_status->encoding = RX_ENC_HT;
- rx_status->rate_idx = GET_DATA_RATE_HT_IDX(data_rate);
+ rx_status->rate_idx = rtw89_get_data_ht_mcs(rtwdev, data_rate);
if (desc_info->gi_ltf)
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
} else if (data_rate_mode == DATA_RATE_MODE_VHT) {
rx_status->encoding = RX_ENC_VHT;
- rx_status->rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate);
- rx_status->nss = GET_DATA_RATE_NSS(data_rate) + 1;
+ rx_status->rate_idx = rtw89_get_data_mcs(rtwdev, data_rate);
+ rx_status->nss = rtw89_get_data_nss(rtwdev, data_rate) + 1;
if (desc_info->gi_ltf)
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
} else if (data_rate_mode == DATA_RATE_MODE_HE) {
rx_status->encoding = RX_ENC_HE;
- rx_status->rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate);
- rx_status->nss = GET_DATA_RATE_NSS(data_rate) + 1;
+ rx_status->rate_idx = rtw89_get_data_mcs(rtwdev, data_rate);
+ rx_status->nss = rtw89_get_data_nss(rtwdev, data_rate) + 1;
} else {
rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode);
}
@@ -2451,6 +2477,7 @@ out:
void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw89_roc *roc = &rtwvif->roc;
struct cfg80211_chan_def roc_chan;
@@ -2478,7 +2505,7 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
rtw89_config_roc_chandef(rtwdev, rtwvif->sub_entity_idx, &roc_chan);
rtw89_set_channel(rtwdev);
rtw89_write32_clr(rtwdev,
- rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
+ rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH);
ieee80211_ready_on_channel(hw);
@@ -2486,6 +2513,7 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw89_roc *roc = &rtwvif->roc;
struct rtw89_vif *tmp;
@@ -2499,7 +2527,7 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
rtw89_leave_lps(rtwdev);
rtw89_write32_mask(rtwdev,
- rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
+ rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
B_AX_RX_FLTR_CFG_MASK,
rtwdev->hal.rx_fltr);
@@ -2682,6 +2710,7 @@ static void rtw89_track_work(struct work_struct *work)
rtw89_phy_tx_path_div_track(rtwdev);
rtw89_phy_antdiv_track(rtwdev);
rtw89_phy_ul_tb_ctrl_track(rtwdev);
+ rtw89_tas_track(rtwdev);
if (rtwdev->lps_enabled && !rtwdev->btc.lps)
rtw89_enter_lps_track(rtwdev);
@@ -2970,6 +2999,8 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta);
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
+ rtwvif->sub_entity_idx);
int ret;
if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
@@ -3023,7 +3054,7 @@ int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev,
rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
BTC_ROLE_MSTS_STA_CONN_END);
- rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template);
+ rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template, chan);
rtw89_phy_ul_tb_assoc(rtwdev, rtwvif);
ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id);
@@ -3463,6 +3494,27 @@ void rtw89_complete_cond(struct rtw89_wait_info *wait, unsigned int cond,
complete(&wait->completion);
}
+void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event)
+{
+ u16 bt_req_len;
+
+ switch (event) {
+ case RTW89_BTC_HMSG_SET_BT_REQ_SLOT:
+ bt_req_len = rtw89_coex_query_bt_req_len(rtwdev, RTW89_PHY_0);
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "coex updates BT req len to %d TU\n", bt_req_len);
+ break;
+ default:
+ if (event < NUM_OF_RTW89_BTC_HMSG)
+ rtw89_debug(rtwdev, RTW89_DBG_BTC,
+ "unhandled BTC HMSG event: %d\n", event);
+ else
+ rtw89_warn(rtwdev,
+ "unrecognized BTC HMSG event: %d\n", event);
+ break;
+ }
+}
+
int rtw89_core_start(struct rtw89_dev *rtwdev)
{
int ret;
@@ -3496,6 +3548,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0);
+ rtw89_tas_reset(rtwdev);
+
ret = rtw89_hci_start(rtwdev);
if (ret) {
rtw89_err(rtwdev, "failed to start hci\n");
@@ -3508,7 +3562,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
set_bit(RTW89_FLAG_RUNNING, rtwdev->flags);
rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
- rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.fw_log_enable);
+ rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.log.enable);
rtw89_fw_h2c_init_ba_cam(rtwdev);
return 0;
@@ -3536,6 +3590,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev)
cancel_work_sync(&btc->icmp_notify_work);
cancel_delayed_work_sync(&rtwdev->txq_reinvoke_work);
cancel_delayed_work_sync(&rtwdev->track_work);
+ cancel_delayed_work_sync(&rtwdev->chanctx_work);
cancel_delayed_work_sync(&rtwdev->coex_act1_work);
cancel_delayed_work_sync(&rtwdev->coex_bt_devinfo_work);
cancel_delayed_work_sync(&rtwdev->coex_rfk_chk_work);
@@ -3572,6 +3627,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work);
INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work);
INIT_DELAYED_WORK(&rtwdev->track_work, rtw89_track_work);
+ INIT_DELAYED_WORK(&rtwdev->chanctx_work, rtw89_chanctx_work);
INIT_DELAYED_WORK(&rtwdev->coex_act1_work, rtw89_coex_act1_work);
INIT_DELAYED_WORK(&rtwdev->coex_bt_devinfo_work, rtw89_coex_bt_devinfo_work);
INIT_DELAYED_WORK(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work);
@@ -3612,6 +3668,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
rtw89_ser_init(rtwdev);
rtw89_entity_init(rtwdev);
+ rtw89_tas_init(rtwdev);
return 0;
}
@@ -3632,7 +3689,8 @@ EXPORT_SYMBOL(rtw89_core_deinit);
void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
const u8 *mac_addr, bool hw_scan)
{
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
+ rtwvif->sub_entity_idx);
rtwdev->scanning = true;
rtw89_leave_lps(rtwdev);
@@ -3779,6 +3837,12 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
return ret;
}
+ ret = rtw89_fw_recognize_elements(rtwdev);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to recognize firmware elements\n");
+ return ret;
+ }
+
ret = rtw89_chip_efuse_info_setup(rtwdev);
if (ret)
return ret;