{
struct rtw89_hal *hal = &rtwdev->hal;
+ hal->entity_pause = false;
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);
u8 last;
u8 idx;
+ lockdep_assert_held(&rtwdev->mutex);
+
weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
switch (weight) {
default:
rtw89_assign_entity_chan(rtwdev, idx, &chan);
}
+ if (hal->entity_pause)
+ return rtw89_get_entity_mode(rtwdev);
+
rtw89_set_entity_mode(rtwdev, mode);
return mode;
}
mutex_lock(&rtwdev->mutex);
+ if (hal->entity_pause) {
+ mutex_unlock(&rtwdev->mutex);
+ return;
+ }
+
for (i = 0; i < NUM_OF_RTW89_CHANCTX_CHANGES; i++) {
if (test_and_clear_bit(i, hal->changes))
changed |= BIT(i);
void rtw89_chanctx_track(struct rtw89_dev *rtwdev)
{
+ struct rtw89_hal *hal = &rtwdev->hal;
enum rtw89_entity_mode mode;
lockdep_assert_held(&rtwdev->mutex);
+ if (hal->entity_pause)
+ return;
+
mode = rtw89_get_entity_mode(rtwdev);
switch (mode) {
case RTW89_ENTITY_MODE_MCC:
}
}
+void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
+ enum rtw89_chanctx_pause_reasons rsn)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ enum rtw89_entity_mode mode;
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ if (hal->entity_pause)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx pause (rsn: %d)\n", rsn);
+
+ mode = rtw89_get_entity_mode(rtwdev);
+ switch (mode) {
+ case RTW89_ENTITY_MODE_MCC:
+ rtw89_mcc_stop(rtwdev);
+ break;
+ default:
+ break;
+ }
+
+ hal->entity_pause = true;
+}
+
+void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ enum rtw89_entity_mode mode;
+ int ret;
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ if (!hal->entity_pause)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx proceed\n");
+
+ hal->entity_pause = false;
+ rtw89_set_channel(rtwdev);
+
+ mode = rtw89_get_entity_mode(rtwdev);
+ switch (mode) {
+ case RTW89_ENTITY_MODE_MCC:
+ ret = rtw89_mcc_start(rtwdev);
+ if (ret)
+ rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
+ break;
+ default:
+ break;
+ }
+
+ rtw89_queue_chanctx_work(rtwdev);
+}
+
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx)
{
#define NUM_OF_RTW89_MCC_ROLES 2
+enum rtw89_chanctx_pause_reasons {
+ RTW89_CHANCTX_PAUSE_REASON_HW_SCAN,
+ RTW89_CHANCTX_PAUSE_REASON_ROC,
+};
+
static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev)
{
struct rtw89_hal *hal = &rtwdev->hal;
void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_changes change);
void rtw89_chanctx_track(struct rtw89_dev *rtwdev);
+void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
+ enum rtw89_chanctx_pause_reasons rsn);
+void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev);
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx);
void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
rtw89_leave_ips_by_hwflags(rtwdev);
rtw89_leave_lps(rtwdev);
+ rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_ROC);
ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, true);
if (ret)
roc->state = RTW89_ROC_IDLE;
rtw89_config_roc_chandef(rtwdev, rtwvif->sub_entity_idx, NULL);
- rtw89_set_channel(rtwdev);
+ rtw89_chanctx_proceed(rtwdev);
ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, false);
if (ret)
rtw89_debug(rtwdev, RTW89_DBG_TXRX,
rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0),
B_AX_RX_FLTR_CFG_MASK,
rx_fltr);
+
+ rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN);
}
void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
scan_info->last_chan_idx = 0;
scan_info->scanning_vif = NULL;
- rtw89_set_channel(rtwdev);
+ rtw89_chanctx_proceed(rtwdev);
}
void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)