Skip to content

Commit af3be90

Browse files
striebitjmberg-intel
authored andcommitted
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 <[email protected]> Signed-off-by: Miri Korenblit <[email protected]> Link: https://patch.msgid.link/20250205145347.956c33729d48.I609835c08f0003c084a13a1e1e505cb7bc8ecbc6@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent 9e8c760 commit af3be90

File tree

3 files changed

+265
-7
lines changed

3 files changed

+265
-7
lines changed

drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
22
/*
3-
* Copyright (C) 2012-2014, 2018-2020, 2022-2024 Intel Corporation
3+
* Copyright (C) 2012-2014, 2018-2020, 2022-2025 Intel Corporation
44
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
55
* Copyright (C) 2016-2017 Intel Deutschland GmbH
66
*/
@@ -351,7 +351,7 @@ enum iwl_roc_activity {
351351
}; /* ROC_ACTIVITY_API_E_VER_1 */
352352

353353
/*
354-
* ROC command
354+
* ROC command v5
355355
*
356356
* Command requests the firmware to remain on a channel for a certain duration.
357357
*
@@ -366,7 +366,7 @@ enum iwl_roc_activity {
366366
* @max_delay: max delay the ROC can start in TU
367367
* @duration: remain on channel duration in TU
368368
*/
369-
struct iwl_roc_req {
369+
struct iwl_roc_req_v5 {
370370
__le32 action;
371371
__le32 activity;
372372
__le32 sta_id;
@@ -375,7 +375,41 @@ struct iwl_roc_req {
375375
__le16 reserved;
376376
__le32 max_delay;
377377
__le32 duration;
378-
} __packed; /* ROC_CMD_API_S_VER_3 */
378+
} __packed; /* ROC_CMD_API_S_VER_5 */
379+
380+
/*
381+
* ROC command
382+
*
383+
* Command requests the firmware to remain on a channel for a certain duration.
384+
*
385+
* ( MAC_CONF_GROUP 0x3, ROC_CMD 0xE )
386+
*
387+
* @action: action to perform, see &enum iwl_ctxt_action
388+
* @activity: type of activity, see &enum iwl_roc_activity
389+
* @sta_id: station id, resumed during "Remain On Channel" activity.
390+
* @channel_info: &struct iwl_fw_channel_info
391+
* @node_addr: node MAC address for Rx filtering
392+
* @reserved1: align to a dword
393+
* @max_delay: max delay the ROC can start in TU
394+
* @duration: remain on channel duration in TU
395+
* @interval: interval between repetitions (when repetitions > 1).
396+
* @repetitions: number of repetitions
397+
* 0xFF: infinite repetitions. 0 or 1: single repetition.
398+
* @reserved2: align to a dword
399+
*/
400+
struct iwl_roc_req {
401+
__le32 action;
402+
__le32 activity;
403+
__le32 sta_id;
404+
struct iwl_fw_channel_info channel_info;
405+
u8 node_addr[ETH_ALEN];
406+
__le16 reserved1;
407+
__le32 max_delay;
408+
__le32 duration;
409+
__le32 interval;
410+
u8 repetitions;
411+
u8 reserved2[3];
412+
} __packed; /* ROC_CMD_API_S_VER_6 */
379413

380414
/*
381415
* ROC notification
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2+
/*
3+
* Copyright (C) 2024 - 2025 Intel Corporation
4+
*/
5+
#include <net/cfg80211.h>
6+
#include <net/mac80211.h>
7+
8+
#include "mld.h"
9+
#include "roc.h"
10+
#include "hcmd.h"
11+
#include "iface.h"
12+
#include "sta.h"
13+
#include "mlo.h"
14+
15+
#include "fw/api/context.h"
16+
#include "fw/api/time-event.h"
17+
18+
#define AUX_ROC_MAX_DELAY MSEC_TO_TU(200)
19+
20+
static void
21+
iwl_mld_vif_iter_emlsr_block_roc(void *data, u8 *mac, struct ieee80211_vif *vif)
22+
{
23+
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
24+
int *result = data;
25+
int ret;
26+
27+
ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif,
28+
IWL_MLD_EMLSR_BLOCKED_ROC,
29+
iwl_mld_get_primary_link(vif));
30+
if (ret)
31+
*result = ret;
32+
}
33+
34+
int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
35+
struct ieee80211_channel *channel, int duration,
36+
enum ieee80211_roc_type type)
37+
{
38+
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
39+
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
40+
struct iwl_mld_int_sta *aux_sta;
41+
struct iwl_roc_req cmd = {
42+
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
43+
};
44+
u8 ver = iwl_fw_lookup_cmd_ver(mld->fw,
45+
WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
46+
u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd);
47+
enum iwl_roc_activity activity;
48+
int ret = 0;
49+
50+
lockdep_assert_wiphy(mld->wiphy);
51+
52+
ieee80211_iterate_active_interfaces_mtx(mld->hw,
53+
IEEE80211_IFACE_ITER_NORMAL,
54+
iwl_mld_vif_iter_emlsr_block_roc,
55+
&ret);
56+
if (ret)
57+
return ret;
58+
59+
/* TODO: task=Hotspot 2.0 */
60+
if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
61+
IWL_ERR(mld, "NOT SUPPORTED: ROC on vif->type %d\n",
62+
vif->type);
63+
64+
return -EOPNOTSUPP;
65+
}
66+
67+
switch (type) {
68+
case IEEE80211_ROC_TYPE_NORMAL:
69+
activity = ROC_ACTIVITY_P2P_DISC;
70+
break;
71+
case IEEE80211_ROC_TYPE_MGMT_TX:
72+
activity = ROC_ACTIVITY_P2P_NEG;
73+
break;
74+
default:
75+
WARN_ONCE(1, "Got an invalid P2P ROC type\n");
76+
return -EINVAL;
77+
}
78+
79+
if (WARN_ON(mld_vif->roc_activity != ROC_NUM_ACTIVITIES))
80+
return -EBUSY;
81+
82+
/* No MLO on P2P device */
83+
aux_sta = &mld_vif->deflink.aux_sta;
84+
85+
ret = iwl_mld_add_aux_sta(mld, aux_sta);
86+
if (ret)
87+
return ret;
88+
89+
cmd.activity = cpu_to_le32(activity);
90+
cmd.sta_id = cpu_to_le32(aux_sta->sta_id);
91+
cmd.channel_info.channel = cpu_to_le32(channel->hw_value);
92+
cmd.channel_info.band = iwl_mld_nl80211_band_to_fw(channel->band);
93+
cmd.channel_info.width = IWL_PHY_CHANNEL_MODE20;
94+
/* TODO: task=Hotspot 2.0, revisit those parameters when we add an ROC
95+
* on the BSS vif
96+
*/
97+
cmd.max_delay = cpu_to_le32(AUX_ROC_MAX_DELAY);
98+
cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
99+
100+
memcpy(cmd.node_addr, vif->addr, ETH_ALEN);
101+
102+
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD),
103+
&cmd, cmd_len);
104+
if (ret) {
105+
IWL_ERR(mld, "Couldn't send the ROC_CMD\n");
106+
return ret;
107+
}
108+
mld_vif->roc_activity = activity;
109+
110+
return 0;
111+
}
112+
113+
static void
114+
iwl_mld_vif_iter_emlsr_unblock_roc(void *data, u8 *mac,
115+
struct ieee80211_vif *vif)
116+
{
117+
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
118+
119+
iwl_mld_unblock_emlsr(mld_vif->mld, vif, IWL_MLD_EMLSR_BLOCKED_ROC);
120+
}
121+
122+
static void iwl_mld_destroy_roc(struct iwl_mld *mld,
123+
struct ieee80211_vif *vif,
124+
struct iwl_mld_vif *mld_vif)
125+
{
126+
mld_vif->roc_activity = ROC_NUM_ACTIVITIES;
127+
128+
ieee80211_iterate_active_interfaces_mtx(mld->hw,
129+
IEEE80211_IFACE_ITER_NORMAL,
130+
iwl_mld_vif_iter_emlsr_unblock_roc,
131+
NULL);
132+
133+
/* wait until every tx has seen that roc_activity has been reset */
134+
synchronize_net();
135+
/* from here, no new tx will be added
136+
* we can flush the Tx on the queues
137+
*/
138+
139+
iwl_mld_flush_link_sta_txqs(mld, mld_vif->deflink.aux_sta.sta_id);
140+
141+
iwl_mld_remove_aux_sta(mld, vif, &vif->bss_conf);
142+
}
143+
144+
int iwl_mld_cancel_roc(struct ieee80211_hw *hw,
145+
struct ieee80211_vif *vif)
146+
{
147+
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
148+
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
149+
struct iwl_roc_req cmd = {
150+
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
151+
};
152+
u8 ver = iwl_fw_lookup_cmd_ver(mld->fw,
153+
WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
154+
u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd);
155+
int ret;
156+
157+
lockdep_assert_wiphy(mld->wiphy);
158+
159+
/* TODO: task=Hotspot 2.0 */
160+
if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE))
161+
return -EOPNOTSUPP;
162+
163+
/* No roc activity running it's probably already done */
164+
if (mld_vif->roc_activity == ROC_NUM_ACTIVITIES)
165+
return 0;
166+
167+
cmd.activity = cpu_to_le32(mld_vif->roc_activity);
168+
169+
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD),
170+
&cmd, cmd_len);
171+
if (ret)
172+
IWL_ERR(mld, "Couldn't send the command to cancel the ROC\n");
173+
174+
/* We may have raced with the firmware expiring the ROC instance at
175+
* this very moment. In that case, we can have a notification in the
176+
* async processing queue. However, none can arrive _after_ this as
177+
* ROC_CMD was sent synchronously, i.e. we waited for a response and
178+
* the firmware cannot refer to this ROC after the response. Thus,
179+
* if we just cancel the notification (if there's one) we'll be at a
180+
* clean state for any possible next ROC.
181+
*/
182+
iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_ROC,
183+
mld_vif->roc_activity);
184+
185+
iwl_mld_destroy_roc(mld, vif, mld_vif);
186+
187+
return 0;
188+
}
189+
190+
void iwl_mld_handle_roc_notif(struct iwl_mld *mld,
191+
struct iwl_rx_packet *pkt)
192+
{
193+
const struct iwl_roc_notif *notif = (void *)pkt->data;
194+
u32 activity = le32_to_cpu(notif->activity);
195+
/* TODO: task=Hotspot 2.0 - roc can run on BSS */
196+
struct ieee80211_vif *vif = mld->p2p_device_vif;
197+
struct iwl_mld_vif *mld_vif;
198+
199+
if (WARN_ON(!vif))
200+
return;
201+
202+
mld_vif = iwl_mld_vif_from_mac80211(vif);
203+
/* It is possible that the ROC was canceled
204+
* but the notification was already fired.
205+
*/
206+
if (mld_vif->roc_activity != activity)
207+
return;
208+
209+
if (le32_to_cpu(notif->success) &&
210+
le32_to_cpu(notif->started)) {
211+
/* We had a successful start */
212+
ieee80211_ready_on_channel(mld->hw);
213+
} else {
214+
/* ROC was not successful, tell the firmware to remove it */
215+
if (le32_to_cpu(notif->started))
216+
iwl_mld_cancel_roc(mld->hw, vif);
217+
else
218+
iwl_mld_destroy_roc(mld, vif, mld_vif);
219+
/* we need to let know mac80211 about end OR
220+
* an unsuccessful start
221+
*/
222+
ieee80211_remain_on_channel_expired(mld->hw);
223+
}
224+
}

drivers/net/wireless/intel/iwlwifi/mvm/time-event.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22
/*
3-
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
3+
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
44
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
55
* Copyright (C) 2017 Intel Deutschland GmbH
66
*/
@@ -771,7 +771,7 @@ static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
771771

772772
static void iwl_mvm_roc_rm_cmd(struct iwl_mvm *mvm, u32 activity)
773773
{
774-
struct iwl_roc_req roc_cmd = {
774+
struct iwl_roc_req_v5 roc_cmd = {
775775
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
776776
.activity = cpu_to_le32(activity),
777777
};
@@ -1100,7 +1100,7 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
11001100
{
11011101
int res;
11021102
u32 duration_tu, delay;
1103-
struct iwl_roc_req roc_req = {
1103+
struct iwl_roc_req_v5 roc_req = {
11041104
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
11051105
.activity = cpu_to_le32(activity),
11061106
.sta_id = cpu_to_le32(mvm->aux_sta.sta_id),

0 commit comments

Comments
 (0)