diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 5f30c6d304b8..5ac6d60dfd73 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -191,6 +191,7 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev) struct rtw89_hal *hal = &rtwdev->hal; bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY); + bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES); atomic_set(&hal->roc_entity_idx, RTW89_SUB_ENTITY_IDLE); rtw89_config_default_chandef(rtwdev); } @@ -1436,15 +1437,66 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev) rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP); } +static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *mcc_role, + unsigned int ordered_idx, + void *data) +{ + struct rtw89_mcc_info *mcc = &rtwdev->mcc; + struct rtw89_mcc_role upd = { + .rtwvif = mcc_role->rtwvif, + }; + int ret; + + if (!mcc_role->is_go) + return 0; + + rtw89_mcc_fill_role_macid_bitmap(rtwdev, &upd); + if (memcmp(mcc_role->macid_bitmap, upd.macid_bitmap, + sizeof(mcc_role->macid_bitmap)) == 0) + return 0; + + ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, + upd.rtwvif->mac_id, + upd.macid_bitmap); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_CHAN, + "MCC h2c failed to update macid bitmap: %d\n", ret); + return ret; + } + + memcpy(mcc_role->macid_bitmap, upd.macid_bitmap, + sizeof(mcc_role->macid_bitmap)); + return 0; +} + +static void rtw89_mcc_update_macid_bitmap(struct rtw89_dev *rtwdev) +{ + struct rtw89_mcc_info *mcc = &rtwdev->mcc; + + if (mcc->mode != RTW89_MCC_MODE_GO_STA) + return; + + rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_map_iterator, NULL); +} + void rtw89_chanctx_work(struct work_struct *work) { struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, chanctx_work.work); + struct rtw89_hal *hal = &rtwdev->hal; enum rtw89_entity_mode mode; + u32 changed = 0; int ret; + int i; mutex_lock(&rtwdev->mutex); + for (i = 0; i < NUM_OF_RTW89_CHANCTX_CHANGES; i++) { + if (test_and_clear_bit(i, hal->changes)) + changed |= BIT(i); + } + mode = rtw89_get_entity_mode(rtwdev); switch (mode) { case RTW89_ENTITY_MODE_MCC_PREPARE: @@ -1455,6 +1507,10 @@ void rtw89_chanctx_work(struct work_struct *work) if (ret) rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret); break; + case RTW89_ENTITY_MODE_MCC: + if (changed & BIT(RTW89_CHANCTX_REMOTE_STA_CHANGE)) + rtw89_mcc_update_macid_bitmap(rtwdev); + break; default: break; } @@ -1462,8 +1518,10 @@ void rtw89_chanctx_work(struct work_struct *work) mutex_unlock(&rtwdev->mutex); } -void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev) +void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_changes change) { + struct rtw89_hal *hal = &rtwdev->hal; enum rtw89_entity_mode mode; u32 delay; @@ -1474,6 +1532,15 @@ void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev) case RTW89_ENTITY_MODE_MCC_PREPARE: delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE); break; + case RTW89_ENTITY_MODE_MCC: + delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC); + break; + } + + if (change != RTW89_CHANCTX_CHANGE_DFLT) { + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "set chanctx change %d\n", + change); + set_bit(change, hal->changes); } rtw89_debug(rtwdev, RTW89_DBG_CHAN, @@ -1483,6 +1550,11 @@ void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev) usecs_to_jiffies(delay)); } +void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev) +{ + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_CHANGE_DFLT); +} + int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx) { diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index 9bdf3d1637bb..2fca703c99f0 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -9,6 +9,7 @@ /* The dwell time in TU before doing rtw89_chanctx_work(). */ #define RTW89_CHANCTX_TIME_MCC_PREPARE 100 +#define RTW89_CHANCTX_TIME_MCC 100 /* various MCC setting time in TU */ #define RTW89_MCC_LONG_TRIGGER_TIME 300 @@ -75,6 +76,8 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev); enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev); void rtw89_chanctx_work(struct work_struct *work); void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev); +void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_changes change); int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx); void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index cb2f4e59187b..68ffd753f4a0 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -2934,6 +2934,8 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, rtw89_warn(rtwdev, "failed to send h2c role info\n"); return ret; } + + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); } return 0; @@ -3099,6 +3101,8 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, rtw89_warn(rtwdev, "failed to send h2c role info\n"); return ret; } + + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); } return 0; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 43a81acdaacf..eb185b3ffa3c 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3787,6 +3787,13 @@ struct rtw89_chanctx_cfg { enum rtw89_sub_entity_idx idx; }; +enum rtw89_chanctx_changes { + RTW89_CHANCTX_REMOTE_STA_CHANGE, + + NUM_OF_RTW89_CHANCTX_CHANGES, + RTW89_CHANCTX_CHANGE_DFLT = NUM_OF_RTW89_CHANCTX_CHANGES, +}; + enum rtw89_entity_mode { RTW89_ENTITY_MODE_SCC, RTW89_ENTITY_MODE_MCC_PREPARE, @@ -3818,6 +3825,7 @@ struct rtw89_hal { bool support_igi; atomic_t roc_entity_idx; + DECLARE_BITMAP(changes, NUM_OF_RTW89_CHANCTX_CHANGES); DECLARE_BITMAP(entity_map, NUM_OF_RTW89_SUB_ENTITY); struct rtw89_sub_entity sub[NUM_OF_RTW89_SUB_ENTITY]; struct cfg80211_chan_def roc_chandef;