wifi: ath12k: implement remain on channel for P2P mode
Implement remain on channel for p2p mode in ath12k_ops: ath12k_mac_op_remain_on_channel ath12k_mac_op_cancel_remain_on_channel P2P device can trigger ROC scan. Then keep listening or sending management frames on particular channels. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Kang Yang <quic_kangyang@quicinc.com> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> Link: https://msgid.link/20240130040303.370590-7-quic_kangyang@quicinc.com
This commit is contained in:
parent
9411eecb60
commit
2830bc9e78
@ -988,6 +988,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
||||
ath12k_mac_drain_tx(ar);
|
||||
complete(&ar->scan.started);
|
||||
complete(&ar->scan.completed);
|
||||
complete(&ar->scan.on_channel);
|
||||
complete(&ar->peer_assoc_done);
|
||||
complete(&ar->peer_delete_done);
|
||||
complete(&ar->install_key_done);
|
||||
|
@ -7451,6 +7451,125 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw,
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
|
||||
}
|
||||
|
||||
static int ath12k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
|
||||
struct ath12k *ar;
|
||||
|
||||
ar = ath12k_ah_to_ar(ah);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->scan.roc_notify = false;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath12k_scan_abort(ar);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
cancel_delayed_work_sync(&ar->scan.timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel *chan,
|
||||
int duration,
|
||||
enum ieee80211_roc_type type)
|
||||
{
|
||||
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
||||
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
|
||||
struct ath12k_wmi_scan_req_arg arg;
|
||||
struct ath12k *ar;
|
||||
u32 scan_time_msec;
|
||||
int ret;
|
||||
|
||||
ar = ath12k_ah_to_ar(ah);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
switch (ar->scan.state) {
|
||||
case ATH12K_SCAN_IDLE:
|
||||
reinit_completion(&ar->scan.started);
|
||||
reinit_completion(&ar->scan.completed);
|
||||
reinit_completion(&ar->scan.on_channel);
|
||||
ar->scan.state = ATH12K_SCAN_STARTING;
|
||||
ar->scan.is_roc = true;
|
||||
ar->scan.vdev_id = arvif->vdev_id;
|
||||
ar->scan.roc_freq = chan->center_freq;
|
||||
ar->scan.roc_notify = true;
|
||||
ret = 0;
|
||||
break;
|
||||
case ATH12K_SCAN_STARTING:
|
||||
case ATH12K_SCAN_RUNNING:
|
||||
case ATH12K_SCAN_ABORTING:
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
scan_time_msec = hw->wiphy->max_remain_on_channel_duration * 2;
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
ath12k_wmi_start_scan_init(ar, &arg);
|
||||
arg.num_chan = 1;
|
||||
arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
|
||||
GFP_KERNEL);
|
||||
if (!arg.chan_list) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
arg.vdev_id = arvif->vdev_id;
|
||||
arg.scan_id = ATH12K_SCAN_ID;
|
||||
arg.chan_list[0] = chan->center_freq;
|
||||
arg.dwell_time_active = scan_time_msec;
|
||||
arg.dwell_time_passive = scan_time_msec;
|
||||
arg.max_scan_time = scan_time_msec;
|
||||
arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;
|
||||
arg.burst_duration = duration;
|
||||
|
||||
ret = ath12k_start_scan(ar, &arg);
|
||||
if (ret) {
|
||||
ath12k_warn(ar->ab, "failed to start roc scan: %d\n", ret);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->scan.state = ATH12K_SCAN_IDLE;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
goto free_chan_list;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ);
|
||||
if (ret == 0) {
|
||||
ath12k_warn(ar->ab, "failed to switch to channel for roc scan\n");
|
||||
ret = ath12k_scan_stop(ar);
|
||||
if (ret)
|
||||
ath12k_warn(ar->ab, "failed to stop scan: %d\n", ret);
|
||||
ret = -ETIMEDOUT;
|
||||
goto free_chan_list;
|
||||
}
|
||||
|
||||
ieee80211_queue_delayed_work(hw, &ar->scan.timeout,
|
||||
msecs_to_jiffies(duration));
|
||||
|
||||
ret = 0;
|
||||
|
||||
free_chan_list:
|
||||
kfree(arg.chan_list);
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops ath12k_ops = {
|
||||
.tx = ath12k_mac_op_tx,
|
||||
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
|
||||
@ -7485,6 +7604,8 @@ static const struct ieee80211_ops ath12k_ops = {
|
||||
.get_survey = ath12k_mac_op_get_survey,
|
||||
.flush = ath12k_mac_op_flush,
|
||||
.sta_statistics = ath12k_mac_op_sta_statistics,
|
||||
.remain_on_channel = ath12k_mac_op_remain_on_channel,
|
||||
.cancel_remain_on_channel = ath12k_mac_op_cancel_remain_on_channel,
|
||||
};
|
||||
|
||||
static void ath12k_mac_update_ch_list(struct ath12k *ar,
|
||||
@ -8012,6 +8133,7 @@ static void ath12k_mac_setup(struct ath12k *ar)
|
||||
init_completion(&ar->bss_survey_done);
|
||||
init_completion(&ar->scan.started);
|
||||
init_completion(&ar->scan.completed);
|
||||
init_completion(&ar->scan.on_channel);
|
||||
|
||||
INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work);
|
||||
INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work);
|
||||
|
@ -5059,6 +5059,10 @@ static void ath12k_wmi_event_scan_started(struct ath12k *ar)
|
||||
break;
|
||||
case ATH12K_SCAN_STARTING:
|
||||
ar->scan.state = ATH12K_SCAN_RUNNING;
|
||||
|
||||
if (ar->scan.is_roc)
|
||||
ieee80211_ready_on_channel(ath12k_ar_to_hw(ar));
|
||||
|
||||
complete(&ar->scan.started);
|
||||
break;
|
||||
}
|
||||
@ -5143,6 +5147,10 @@ static void ath12k_wmi_event_scan_foreign_chan(struct ath12k *ar, u32 freq)
|
||||
case ATH12K_SCAN_RUNNING:
|
||||
case ATH12K_SCAN_ABORTING:
|
||||
ar->scan_channel = ieee80211_get_channel(hw->wiphy, freq);
|
||||
|
||||
if (ar->scan.is_roc && ar->scan.roc_freq == freq)
|
||||
complete(&ar->scan.on_channel);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user