-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wifi: iwlwifi: support ROC version 6
Version 6 added ROC with multi repetitions. We don't use it, but need to update the command length. Signed-off-by: Shaul Triebitz <shaul.triebitz@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20250205145347.956c33729d48.I609835c08f0003c084a13a1e1e505cb7bc8ecbc6@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
- Loading branch information
Shaul Triebitz
authored and
Johannes Berg
committed
Feb 11, 2025
1 parent
9e8c760
commit af3be90
Showing
3 changed files
with
265 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause | ||
/* | ||
* Copyright (C) 2024 - 2025 Intel Corporation | ||
*/ | ||
#include <net/cfg80211.h> | ||
#include <net/mac80211.h> | ||
|
||
#include "mld.h" | ||
#include "roc.h" | ||
#include "hcmd.h" | ||
#include "iface.h" | ||
#include "sta.h" | ||
#include "mlo.h" | ||
|
||
#include "fw/api/context.h" | ||
#include "fw/api/time-event.h" | ||
|
||
#define AUX_ROC_MAX_DELAY MSEC_TO_TU(200) | ||
|
||
static void | ||
iwl_mld_vif_iter_emlsr_block_roc(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
{ | ||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); | ||
int *result = data; | ||
int ret; | ||
|
||
ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif, | ||
IWL_MLD_EMLSR_BLOCKED_ROC, | ||
iwl_mld_get_primary_link(vif)); | ||
if (ret) | ||
*result = ret; | ||
} | ||
|
||
int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
struct ieee80211_channel *channel, int duration, | ||
enum ieee80211_roc_type type) | ||
{ | ||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); | ||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); | ||
struct iwl_mld_int_sta *aux_sta; | ||
struct iwl_roc_req cmd = { | ||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD), | ||
}; | ||
u8 ver = iwl_fw_lookup_cmd_ver(mld->fw, | ||
WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0); | ||
u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd); | ||
enum iwl_roc_activity activity; | ||
int ret = 0; | ||
|
||
lockdep_assert_wiphy(mld->wiphy); | ||
|
||
ieee80211_iterate_active_interfaces_mtx(mld->hw, | ||
IEEE80211_IFACE_ITER_NORMAL, | ||
iwl_mld_vif_iter_emlsr_block_roc, | ||
&ret); | ||
if (ret) | ||
return ret; | ||
|
||
/* TODO: task=Hotspot 2.0 */ | ||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { | ||
IWL_ERR(mld, "NOT SUPPORTED: ROC on vif->type %d\n", | ||
vif->type); | ||
|
||
return -EOPNOTSUPP; | ||
} | ||
|
||
switch (type) { | ||
case IEEE80211_ROC_TYPE_NORMAL: | ||
activity = ROC_ACTIVITY_P2P_DISC; | ||
break; | ||
case IEEE80211_ROC_TYPE_MGMT_TX: | ||
activity = ROC_ACTIVITY_P2P_NEG; | ||
break; | ||
default: | ||
WARN_ONCE(1, "Got an invalid P2P ROC type\n"); | ||
return -EINVAL; | ||
} | ||
|
||
if (WARN_ON(mld_vif->roc_activity != ROC_NUM_ACTIVITIES)) | ||
return -EBUSY; | ||
|
||
/* No MLO on P2P device */ | ||
aux_sta = &mld_vif->deflink.aux_sta; | ||
|
||
ret = iwl_mld_add_aux_sta(mld, aux_sta); | ||
if (ret) | ||
return ret; | ||
|
||
cmd.activity = cpu_to_le32(activity); | ||
cmd.sta_id = cpu_to_le32(aux_sta->sta_id); | ||
cmd.channel_info.channel = cpu_to_le32(channel->hw_value); | ||
cmd.channel_info.band = iwl_mld_nl80211_band_to_fw(channel->band); | ||
cmd.channel_info.width = IWL_PHY_CHANNEL_MODE20; | ||
/* TODO: task=Hotspot 2.0, revisit those parameters when we add an ROC | ||
* on the BSS vif | ||
*/ | ||
cmd.max_delay = cpu_to_le32(AUX_ROC_MAX_DELAY); | ||
cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); | ||
|
||
memcpy(cmd.node_addr, vif->addr, ETH_ALEN); | ||
|
||
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), | ||
&cmd, cmd_len); | ||
if (ret) { | ||
IWL_ERR(mld, "Couldn't send the ROC_CMD\n"); | ||
return ret; | ||
} | ||
mld_vif->roc_activity = activity; | ||
|
||
return 0; | ||
} | ||
|
||
static void | ||
iwl_mld_vif_iter_emlsr_unblock_roc(void *data, u8 *mac, | ||
struct ieee80211_vif *vif) | ||
{ | ||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); | ||
|
||
iwl_mld_unblock_emlsr(mld_vif->mld, vif, IWL_MLD_EMLSR_BLOCKED_ROC); | ||
} | ||
|
||
static void iwl_mld_destroy_roc(struct iwl_mld *mld, | ||
struct ieee80211_vif *vif, | ||
struct iwl_mld_vif *mld_vif) | ||
{ | ||
mld_vif->roc_activity = ROC_NUM_ACTIVITIES; | ||
|
||
ieee80211_iterate_active_interfaces_mtx(mld->hw, | ||
IEEE80211_IFACE_ITER_NORMAL, | ||
iwl_mld_vif_iter_emlsr_unblock_roc, | ||
NULL); | ||
|
||
/* wait until every tx has seen that roc_activity has been reset */ | ||
synchronize_net(); | ||
/* from here, no new tx will be added | ||
* we can flush the Tx on the queues | ||
*/ | ||
|
||
iwl_mld_flush_link_sta_txqs(mld, mld_vif->deflink.aux_sta.sta_id); | ||
|
||
iwl_mld_remove_aux_sta(mld, vif, &vif->bss_conf); | ||
} | ||
|
||
int iwl_mld_cancel_roc(struct ieee80211_hw *hw, | ||
struct ieee80211_vif *vif) | ||
{ | ||
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); | ||
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); | ||
struct iwl_roc_req cmd = { | ||
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), | ||
}; | ||
u8 ver = iwl_fw_lookup_cmd_ver(mld->fw, | ||
WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0); | ||
u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd); | ||
int ret; | ||
|
||
lockdep_assert_wiphy(mld->wiphy); | ||
|
||
/* TODO: task=Hotspot 2.0 */ | ||
if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE)) | ||
return -EOPNOTSUPP; | ||
|
||
/* No roc activity running it's probably already done */ | ||
if (mld_vif->roc_activity == ROC_NUM_ACTIVITIES) | ||
return 0; | ||
|
||
cmd.activity = cpu_to_le32(mld_vif->roc_activity); | ||
|
||
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), | ||
&cmd, cmd_len); | ||
if (ret) | ||
IWL_ERR(mld, "Couldn't send the command to cancel the ROC\n"); | ||
|
||
/* We may have raced with the firmware expiring the ROC instance at | ||
* this very moment. In that case, we can have a notification in the | ||
* async processing queue. However, none can arrive _after_ this as | ||
* ROC_CMD was sent synchronously, i.e. we waited for a response and | ||
* the firmware cannot refer to this ROC after the response. Thus, | ||
* if we just cancel the notification (if there's one) we'll be at a | ||
* clean state for any possible next ROC. | ||
*/ | ||
iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_ROC, | ||
mld_vif->roc_activity); | ||
|
||
iwl_mld_destroy_roc(mld, vif, mld_vif); | ||
|
||
return 0; | ||
} | ||
|
||
void iwl_mld_handle_roc_notif(struct iwl_mld *mld, | ||
struct iwl_rx_packet *pkt) | ||
{ | ||
const struct iwl_roc_notif *notif = (void *)pkt->data; | ||
u32 activity = le32_to_cpu(notif->activity); | ||
/* TODO: task=Hotspot 2.0 - roc can run on BSS */ | ||
struct ieee80211_vif *vif = mld->p2p_device_vif; | ||
struct iwl_mld_vif *mld_vif; | ||
|
||
if (WARN_ON(!vif)) | ||
return; | ||
|
||
mld_vif = iwl_mld_vif_from_mac80211(vif); | ||
/* It is possible that the ROC was canceled | ||
* but the notification was already fired. | ||
*/ | ||
if (mld_vif->roc_activity != activity) | ||
return; | ||
|
||
if (le32_to_cpu(notif->success) && | ||
le32_to_cpu(notif->started)) { | ||
/* We had a successful start */ | ||
ieee80211_ready_on_channel(mld->hw); | ||
} else { | ||
/* ROC was not successful, tell the firmware to remove it */ | ||
if (le32_to_cpu(notif->started)) | ||
iwl_mld_cancel_roc(mld->hw, vif); | ||
else | ||
iwl_mld_destroy_roc(mld, vif, mld_vif); | ||
/* we need to let know mac80211 about end OR | ||
* an unsuccessful start | ||
*/ | ||
ieee80211_remain_on_channel_expired(mld->hw); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters