2023-08-17 12:03:40

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 0/6] wifi: rtw89: preparation of TDMA-based MCC (STA+P2P)

TDMA-based MCC (STA+P2P) is a kind of multiple interfaces concurrence.
Basically, driver is to calculate timeslot pattern and firmware follows
the pattern to switch channels. Since BT-coexistence is also a TDMA-based
mechanism, also consider BT timeslot into pattern if BT devices present.

To easier to review these 20+ patches, I summary basic purpose of these
patches below by group, and submit them by small patchset one by one.

Group 1. get BT timeslot from coex mechanism
Group 2. adjust some stuff related to driver channel context
Group 3. P2P NoA infrastructure to add the IE to beacon when playing GO
Group 4. adjust driver to support 2 channel context
Group 5. calculate timeslot patterns and trigger firmware to switch
channels followed the patterns
Group 6. disable some dynamic tracking mechanism of RF calibration when
MCC is running.
Group 7. monitor states and adjust timeslot patterns. For example, if
BT device leaves, we can reassign the slot to WiFi.
Group 8. Remain-on-channel and hardware scan are related to channel
context, so need some treatments to work with MCC properly.
Group 9. Finally, we declare 8852C to support MCC

This patchset includes groups 1-4 above, and depends on another patch
"wifi: rtw89: Introduce Time Averaged SAR (TAS) feature"
because both modify the same file, not functional dependency.

Zong-Zhe Yang (6):
wifi: rtw89: add function prototype for coex request duration
wifi: rtw89: refine rtw89_correct_cck_chan() by
rtw89_hw_to_nl80211_band()
wifi: rtw89: sar: let caller decide the center frequency to query
wifi: rtw89: call rtw89_chan_get() by vif chanctx if aware of vif
wifi: rtw89: provide functions to configure NoA for beacon update
wifi: rtw89: initialize multi-channel handling

drivers/net/wireless/realtek/rtw89/chan.c | 124 ++++++++++++++++++
drivers/net/wireless/realtek/rtw89/chan.h | 5 +
drivers/net/wireless/realtek/rtw89/coex.c | 3 +-
drivers/net/wireless/realtek/rtw89/coex.h | 9 ++
drivers/net/wireless/realtek/rtw89/core.c | 114 +++++++++++-----
drivers/net/wireless/realtek/rtw89/core.h | 78 +++++++++++
drivers/net/wireless/realtek/rtw89/debug.c | 10 +-
drivers/net/wireless/realtek/rtw89/fw.c | 16 ++-
drivers/net/wireless/realtek/rtw89/mac80211.c | 7 +-
drivers/net/wireless/realtek/rtw89/phy.c | 29 ++--
drivers/net/wireless/realtek/rtw89/ps.c | 75 ++++++++++-
drivers/net/wireless/realtek/rtw89/ps.h | 4 +
drivers/net/wireless/realtek/rtw89/sar.c | 24 ++--
drivers/net/wireless/realtek/rtw89/sar.h | 6 +-
14 files changed, 436 insertions(+), 68 deletions(-)

--
2.25.1



2023-08-17 14:14:35

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 4/6] wifi: rtw89: call rtw89_chan_get() by vif chanctx if aware of vif

From: Zong-Zhe Yang <[email protected]>

We adjust these processes which can work accodrding to vif but call
rtw89_chan_get() with static RTW89_SUB_ENTITY_0. After multi-channel
support, chanctx of vif won't always be on RTW89_SUB_ENTITY_0. So,
we make them call rtw89_chan_get() with rtwvif->sub_entity_idx.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/coex.c | 3 ++-
drivers/net/wireless/realtek/rtw89/core.c | 22 +++++++++++--------
drivers/net/wireless/realtek/rtw89/core.h | 12 ++++++++++
drivers/net/wireless/realtek/rtw89/fw.c | 6 +++--
drivers/net/wireless/realtek/rtw89/mac80211.c | 3 ++-
drivers/net/wireless/realtek/rtw89/phy.c | 21 ++++++++++--------
6 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index bda0e1e99a8c..4ba8b3df70ae 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -5666,7 +5666,8 @@ enum btc_wl_mode {
void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
struct rtw89_sta *rtwsta, enum btc_role_state state)
{
- 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);
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
struct rtw89_btc *btc = &rtwdev->btc;
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index aedabd262251..91f9a587220b 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -523,12 +523,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 +567,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 +585,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 +604,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 +616,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 ||
@@ -1899,7 +1900,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;

@@ -1909,6 +1909,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;
@@ -2970,6 +2971,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 +3026,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);
@@ -3656,7 +3659,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);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 5b60bc72b4a5..257582fc39ea 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4929,6 +4929,18 @@ const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev,
return &hal->sub[idx].rcd;
}

+static inline
+const struct rtw89_chan *rtw89_scan_chan_get(struct rtw89_dev *rtwdev)
+{
+ struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
+
+ if (rtwvif)
+ return rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
+ else
+ return rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+}
+
static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 2811a94b5f69..7dd7bc4be9c7 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1758,7 +1758,8 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
- 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);
struct sk_buff *skb;
u8 pads[RTW89_PPE_BW_NUM];
u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
@@ -1915,7 +1916,8 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif)
{
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- 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);
struct sk_buff *skb;
struct sk_buff *skb_beacon;
u16 tim_offset;
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index a66503eb35b8..7c3066c0a550 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -296,7 +296,8 @@ static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif, u8 aifsn)
{
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
- 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 slot_time;
u8 sifs;

diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index fcdc61597b9b..5ff2871b230b 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -133,10 +133,10 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak)
return ra_mask;
}

-static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta)
+static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
+ const struct rtw89_chan *chan)
{
struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
enum nl80211_band band;
u64 cfg_mask;
@@ -197,9 +197,9 @@ rtw89_ra_mask_he_rates[4] = {RA_MASK_HE_1SS_RATES, RA_MASK_HE_2SS_RATES,

static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
struct rtw89_sta *rtwsta,
+ const struct rtw89_chan *chan,
bool *fix_giltf_en, u8 *fix_giltf)
{
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
u8 band = chan->band_type;
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
@@ -236,7 +236,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif = rtwsta->rtwvif;
struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern;
struct rtw89_ra_info *ra = &rtwsta->ra;
- 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);
struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif);
const u64 *high_rate_masks = rtw89_ra_mask_ht_rates;
u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi);
@@ -265,7 +266,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
ldpc_en = 1;
- rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, &fix_giltf_en, &fix_giltf);
+ rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, chan, &fix_giltf_en, &fix_giltf);
} else if (sta->deflink.vht_cap.vht_supported) {
u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);

@@ -332,7 +333,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0);

ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak);
- ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta);
+ ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan);

switch (sta->deflink.bandwidth) {
case IEEE80211_STA_RX_BW_160:
@@ -362,7 +363,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
ra->dcm_cap = 1;

if (rate_pattern->enable && !vif->p2p) {
- ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta);
+ ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan);
ra_mask &= rate_pattern->ra_mask;
mode = rate_pattern->ra_mode;
}
@@ -457,7 +458,8 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
struct ieee80211_supported_band *sband;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_phy_rate_pattern next_pattern = {0};
- 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);
static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = {
RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0),
RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0),
@@ -2889,7 +2891,8 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val,
void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- 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);
struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info;

if (!chip->support_ul_tb_ctrl)
--
2.25.1


2023-08-18 07:53:50

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 1/6] wifi: rtw89: add function prototype for coex request duration

From: Zong-Zhe Yang <[email protected]>

The request duration comes from coex mechanism, indicating the
length of time that should be reserved for BT in each time division.
It is required to handle update notification when channel concurrency
processes. Since it will involve in both coex and wifi code flow, this
commit ahead adds the prototype for required function interfaces to
split the implementation of coex and wifi in the following.

The follow-up are expected be add afterwards.
1. coex mechanism call rtw89_core_ntfy_btc_event() once bt req len changes
2. channel concurrency flow updates related stuffs when notified

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/coex.h | 9 +++++++++
drivers/net/wireless/realtek/rtw89/core.c | 21 +++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/core.h | 12 ++++++++++++
3 files changed, 42 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h
index f16421cb30ef..e76153709793 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.h
+++ b/drivers/net/wireless/realtek/rtw89/coex.h
@@ -193,4 +193,13 @@ static inline u8 rtw89_btc_path_phymap(struct rtw89_dev *rtwdev,
return rtw89_btc_phymap(rtwdev, phy_idx, BIT(path));
}

+/* return bt req len in TU */
+static inline u16 rtw89_coex_query_bt_req_len(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+
+ return btc->bt_req_len;
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 71eb9cfd4896..a338b0a97910 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -3464,6 +3464,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;
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index b5a08f90f5bd..5b60bc72b4a5 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -2656,6 +2656,17 @@ struct rtw89_btc {
bool lps;
};

+enum rtw89_btc_hmsg {
+ RTW89_BTC_HMSG_TMR_EN = 0x0,
+ RTW89_BTC_HMSG_BT_REG_READBACK = 0x1,
+ RTW89_BTC_HMSG_SET_BT_REQ_SLOT = 0x2,
+ RTW89_BTC_HMSG_FW_EV = 0x3,
+ RTW89_BTC_HMSG_BT_LINK_CHG = 0x4,
+ RTW89_BTC_HMSG_SET_BT_REQ_STBC = 0x5,
+
+ NUM_OF_RTW89_BTC_HMSG,
+};
+
enum rtw89_ra_mode {
RTW89_RA_MODE_CCK = BIT(0),
RTW89_RA_MODE_OFDM = BIT(1),
@@ -5325,5 +5336,6 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif, bool hw_scan);
void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif, bool active);
+void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event);

#endif
--
2.25.1


2023-08-18 19:43:51

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 2/6] wifi: rtw89: refine rtw89_correct_cck_chan() by rtw89_hw_to_nl80211_band()

From: Zong-Zhe Yang <[email protected]>

In rtw89_correct_cck_chan(), we turn to use rtw89_hw_to_nl80211_band().
The difference between rtw89_hw_to_nl80211_band() and the original raw
judgement is the case on 6 GHz. Since rtw89_correct_cck_chan() is common
code independent on chip, if runtime chip doesn't support 6 GHz, it is
probably safe. Otherwise, it might not.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/core.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index a338b0a97910..aedabd262251 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -1659,8 +1659,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 &&
--
2.25.1


2023-08-19 13:33:02

by Ping-Ke Shih

[permalink] [raw]
Subject: [PATCH 3/6] wifi: rtw89: sar: let caller decide the center frequency to query

From: Zong-Zhe Yang <[email protected]>

If multiple channels, SAR will be hard to determine the center frequency
to query. Therefore, we move this decision out of SAR.

Signed-off-by: Zong-Zhe Yang <[email protected]>
Signed-off-by: Ping-Ke Shih <[email protected]>
---
drivers/net/wireless/realtek/rtw89/debug.c | 10 +++++----
drivers/net/wireless/realtek/rtw89/phy.c | 8 ++++++--
drivers/net/wireless/realtek/rtw89/sar.c | 24 +++++++++++-----------
drivers/net/wireless/realtek/rtw89/sar.h | 6 +++---
4 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index f6f1e90c3934..48635458c36a 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -572,9 +572,9 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
seq_puts(m, #_regd "\n"); \
break

-static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev)
+static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan)
{
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
u8 band = chan->band_type;
u8 regd = rtw89_regd_get(rtwdev, band);

@@ -604,16 +604,18 @@ static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v)
{
struct rtw89_debugfs_priv *debugfs_priv = m->private;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
+ const struct rtw89_chan *chan;
int ret = 0;

mutex_lock(&rtwdev->mutex);
rtw89_leave_ps_mode(rtwdev);
+ chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);

seq_puts(m, "[Regulatory] ");
- __print_regd(m, rtwdev);
+ __print_regd(m, rtwdev, chan);

seq_puts(m, "[SAR]\n");
- rtw89_print_sar(m, rtwdev);
+ rtw89_print_sar(m, rtwdev, chan->freq);

seq_puts(m, "[TAS]\n");
rtw89_print_tas(m, rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index c40c4f8c1271..fcdc61597b9b 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -1647,6 +1647,8 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+ enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
+ u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
u8 reg6 = regulatory->reg_6ghz_power;
@@ -1682,7 +1684,7 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
}

lmt = _phy_txpwr_rf_to_mac(rtwdev, lmt);
- sar = rtw89_query_sar(rtwdev);
+ sar = rtw89_query_sar(rtwdev, freq);

return min(lmt, sar);
}
@@ -1902,6 +1904,8 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+ enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
+ u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
u8 reg6 = regulatory->reg_6ghz_power;
@@ -1937,7 +1941,7 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
}

lmt_ru = _phy_txpwr_rf_to_mac(rtwdev, lmt_ru);
- sar = rtw89_query_sar(rtwdev);
+ sar = rtw89_query_sar(rtwdev, freq);

return min(lmt_ru, sar);
}
diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c
index fafc7a0cfe97..881322f85d79 100644
--- a/drivers/net/wireless/realtek/rtw89/sar.c
+++ b/drivers/net/wireless/realtek/rtw89/sar.c
@@ -85,17 +85,15 @@ static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = {
RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8),
};

-static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
+static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev,
+ u32 center_freq, s32 *cfg)
{
struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
- enum rtw89_band band = chan->band_type;
- u32 center_freq = chan->freq;
const struct rtw89_sar_span *span = NULL;
enum rtw89_sar_subband subband_l, subband_h;
int idx;

- if (band == RTW89_BAND_6G) {
+ if (center_freq >= RTW89_SAR_6GHZ_SPAN_HEAD) {
idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq);
/* To decrease size of rtw89_sar_overlapping_6ghz[],
* RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs
@@ -115,8 +113,8 @@ static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
}

rtw89_debug(rtwdev, RTW89_DBG_SAR,
- "for {band %u, center_freq %u}, SAR subband: {%u, %u}\n",
- band, center_freq, subband_l, subband_h);
+ "center_freq %u: SAR subband {%u, %u}\n",
+ center_freq, subband_l, subband_h);

if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h])
return -ENODATA;
@@ -186,7 +184,7 @@ static s8 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl,
return cfg << (RTW89_TAS_FACTOR - fct);
}

-s8 rtw89_query_sar(struct rtw89_dev *rtwdev)
+s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq)
{
const enum rtw89_sar_sources src = rtwdev->sar.src;
/* its members are protected by rtw89_sar_set_src() */
@@ -202,7 +200,7 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev)
if (src == RTW89_SAR_SOURCE_NONE)
return RTW89_SAR_TXPWR_MAC_MAX;

- ret = sar_hdl->query_sar_config(rtwdev, &cfg);
+ ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg);
if (ret)
return RTW89_SAR_TXPWR_MAC_MAX;

@@ -224,7 +222,7 @@ s8 rtw89_query_sar(struct rtw89_dev *rtwdev)
return rtw89_txpwr_sar_to_mac(rtwdev, fct, cfg);
}

-void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev)
+void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev, u32 center_freq)
{
const enum rtw89_sar_sources src = rtwdev->sar.src;
/* its members are protected by rtw89_sar_set_src() */
@@ -243,7 +241,7 @@ void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev)

seq_printf(m, "source: %d (%s)\n", src, sar_hdl->descr_sar_source);

- ret = sar_hdl->query_sar_config(rtwdev, &cfg);
+ ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg);
if (ret) {
seq_printf(m, "config: return code: %d\n", ret);
seq_printf(m, "assign: max setting: %d (unit: 1/%lu dBm)\n",
@@ -359,6 +357,7 @@ static void rtw89_tas_state_update(struct rtw89_dev *rtwdev)
s32 txpwr_avg = tas->total_txpwr / RTW89_TAS_MAX_WINDOW / PERCENT;
s32 dpr_on_threshold, dpr_off_threshold, cfg;
enum rtw89_tas_state state = tas->state;
+ const struct rtw89_chan *chan;
int ret;

lockdep_assert_held(&rtwdev->mutex);
@@ -366,7 +365,8 @@ static void rtw89_tas_state_update(struct rtw89_dev *rtwdev)
if (src == RTW89_SAR_SOURCE_NONE)
return;

- ret = sar_hdl->query_sar_config(rtwdev, &cfg);
+ chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ ret = sar_hdl->query_sar_config(rtwdev, chan->freq, &cfg);
if (ret)
return;

diff --git a/drivers/net/wireless/realtek/rtw89/sar.h b/drivers/net/wireless/realtek/rtw89/sar.h
index 40ce5990ceaf..bd7a657188d9 100644
--- a/drivers/net/wireless/realtek/rtw89/sar.h
+++ b/drivers/net/wireless/realtek/rtw89/sar.h
@@ -13,13 +13,13 @@
struct rtw89_sar_handler {
const char *descr_sar_source;
u8 txpwr_factor_sar;
- int (*query_sar_config)(struct rtw89_dev *rtwdev, s32 *cfg);
+ int (*query_sar_config)(struct rtw89_dev *rtwdev, u32 center_freq, s32 *cfg);
};

extern const struct cfg80211_sar_capa rtw89_sar_capa;

-s8 rtw89_query_sar(struct rtw89_dev *rtwdev);
-void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev);
+s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq);
+void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev, u32 center_freq);
void rtw89_print_tas(struct seq_file *m, struct rtw89_dev *rtwdev);
int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
--
2.25.1


2023-08-23 15:14:38

by Ping-Ke Shih

[permalink] [raw]
Subject: Re: [PATCH 0/6] wifi: rtw89: preparation of TDMA-based MCC (STA+P2P)

On Wed, 2023-08-23 at 16:56 +0300, Kalle Valo wrote:
>
> Ping-Ke Shih <[email protected]> writes:
>
> > TDMA-based MCC (STA+P2P) is a kind of multiple interfaces concurrence.
> > Basically, driver is to calculate timeslot pattern and firmware follows
> > the pattern to switch channels. Since BT-coexistence is also a TDMA-based
> > mechanism, also consider BT timeslot into pattern if BT devices present.
>
> What do you mean with TDMA here? It something like that in STA mode the
> driver enables 802.11 PS mode before going to another channel? Or
> something else?
>

Yes, when it is working as STA mode or GC, using 802.11 PS mode before
switching channel. When it plays as GO, NoA is used to inform GC absent
timing.

For example, STA on channel 1 + GO on channel 11, and preserve some
time slot for BT


(1)
channel 1 (STA) +++++++++

(2)
channel 11 (GO) +++++++++

BT ++++++++

|<----------------------->|
Period (or cycle time)

(1) issue null with power bit
(2) issue beacon with NoA


Though STA and GO are in different channels, they don't operate at
the same time. This is the reason I point "TDMA" to prevent
misunderstanding two virtual interfaces can operate two channels
at the same time, which may be called DBS or DBCC. But, I'm trying
to explain hardware capability correctly.

Ping-Ke


2023-08-25 08:41:47

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 0/6] wifi: rtw89: preparation of TDMA-based MCC (STA+P2P)

Ping-Ke Shih <[email protected]> writes:

> On Wed, 2023-08-23 at 21:24 +0300, Kalle Valo wrote:
>>
>>
>> Just out of curiosity, how do you create your ascii diagrams? Is there
>> some nifty tool to help with those? :)
>>
>
> I draw these diagrams manually, not pretty but useful (I think so :) ).
>
> Recently, I draw a diagram in cover letter, because purpose of
> patchset is simple, but too much detail things cause patches
> complicated. So, I hope a diagram can help reviewers to have a
> concept quickly before reviewing my patches.

At least I have found the diagrams very helpful :)

--
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches