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 struct iwl_mld_roc_iter_data { 35 enum iwl_roc_activity activity; 36 struct ieee80211_vif *vif; 37 bool found; 38 }; 39 40 static void iwl_mld_find_roc_vif_iter(void *data, u8 *mac, 41 struct ieee80211_vif *vif) 42 { 43 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 44 struct iwl_mld_roc_iter_data *roc_data = data; 45 46 if (mld_vif->roc_activity != roc_data->activity) 47 return; 48 49 /* The FW supports one ROC of each type simultaneously */ 50 if (WARN_ON(roc_data->found)) { 51 roc_data->vif = NULL; 52 return; 53 } 54 55 roc_data->found = true; 56 roc_data->vif = vif; 57 } 58 59 static struct ieee80211_vif * 60 iwl_mld_find_roc_vif(struct iwl_mld *mld, enum iwl_roc_activity activity) 61 { 62 struct iwl_mld_roc_iter_data roc_data = { 63 .activity = activity, 64 .found = false, 65 }; 66 67 ieee80211_iterate_active_interfaces_mtx(mld->hw, 68 IEEE80211_IFACE_ITER_NORMAL, 69 iwl_mld_find_roc_vif_iter, 70 &roc_data); 71 72 return roc_data.vif; 73 } 74 75 int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 76 struct ieee80211_channel *channel, int duration, 77 enum ieee80211_roc_type type) 78 { 79 struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); 80 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 81 struct iwl_mld_int_sta *aux_sta = &mld_vif->aux_sta; 82 struct iwl_roc_req cmd = { 83 .action = cpu_to_le32(FW_CTXT_ACTION_ADD), 84 }; 85 u8 ver = iwl_fw_lookup_cmd_ver(mld->fw, 86 WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0); 87 u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd); 88 enum iwl_roc_activity activity; 89 int ret = 0; 90 91 lockdep_assert_wiphy(mld->wiphy); 92 93 if (vif->type != NL80211_IFTYPE_P2P_DEVICE && 94 vif->type != NL80211_IFTYPE_STATION) { 95 IWL_ERR(mld, "NOT SUPPORTED: ROC on vif->type %d\n", 96 vif->type); 97 98 return -EOPNOTSUPP; 99 } 100 101 if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { 102 switch (type) { 103 case IEEE80211_ROC_TYPE_NORMAL: 104 activity = ROC_ACTIVITY_P2P_DISC; 105 break; 106 case IEEE80211_ROC_TYPE_MGMT_TX: 107 activity = ROC_ACTIVITY_P2P_NEG; 108 break; 109 default: 110 WARN_ONCE(1, "Got an invalid P2P ROC type\n"); 111 return -EINVAL; 112 } 113 } else { 114 activity = ROC_ACTIVITY_HOTSPOT; 115 } 116 117 /* The FW supports one ROC of each type simultaneously */ 118 if (WARN_ON(iwl_mld_find_roc_vif(mld, activity))) 119 return -EBUSY; 120 121 ieee80211_iterate_active_interfaces_mtx(mld->hw, 122 IEEE80211_IFACE_ITER_NORMAL, 123 iwl_mld_vif_iter_emlsr_block_roc, 124 &ret); 125 if (ret) 126 return ret; 127 128 ret = iwl_mld_add_aux_sta(mld, aux_sta); 129 if (ret) 130 return ret; 131 132 cmd.activity = cpu_to_le32(activity); 133 cmd.sta_id = cpu_to_le32(aux_sta->sta_id); 134 cmd.channel_info.channel = cpu_to_le32(channel->hw_value); 135 cmd.channel_info.band = iwl_mld_nl80211_band_to_fw(channel->band); 136 cmd.channel_info.width = IWL_PHY_CHANNEL_MODE20; 137 cmd.max_delay = cpu_to_le32(AUX_ROC_MAX_DELAY); 138 cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); 139 140 memcpy(cmd.node_addr, vif->addr, ETH_ALEN); 141 142 ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 143 &cmd, cmd_len); 144 if (ret) { 145 IWL_ERR(mld, "Couldn't send the ROC_CMD\n"); 146 return ret; 147 } 148 149 mld_vif->roc_activity = activity; 150 151 return 0; 152 } 153 154 static void 155 iwl_mld_vif_iter_emlsr_unblock_roc(void *data, u8 *mac, 156 struct ieee80211_vif *vif) 157 { 158 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 159 160 iwl_mld_unblock_emlsr(mld_vif->mld, vif, IWL_MLD_EMLSR_BLOCKED_ROC); 161 } 162 163 static void iwl_mld_destroy_roc(struct iwl_mld *mld, 164 struct ieee80211_vif *vif, 165 struct iwl_mld_vif *mld_vif) 166 { 167 mld_vif->roc_activity = ROC_NUM_ACTIVITIES; 168 169 ieee80211_iterate_active_interfaces_mtx(mld->hw, 170 IEEE80211_IFACE_ITER_NORMAL, 171 iwl_mld_vif_iter_emlsr_unblock_roc, 172 NULL); 173 174 /* wait until every tx has seen that roc_activity has been reset */ 175 synchronize_net(); 176 /* from here, no new tx will be added 177 * we can flush the Tx on the queues 178 */ 179 180 iwl_mld_flush_link_sta_txqs(mld, mld_vif->aux_sta.sta_id); 181 182 iwl_mld_remove_aux_sta(mld, vif); 183 } 184 185 int iwl_mld_cancel_roc(struct ieee80211_hw *hw, 186 struct ieee80211_vif *vif) 187 { 188 struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); 189 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 190 struct iwl_roc_req cmd = { 191 .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), 192 }; 193 u8 ver = iwl_fw_lookup_cmd_ver(mld->fw, 194 WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0); 195 u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd); 196 int ret; 197 198 lockdep_assert_wiphy(mld->wiphy); 199 200 if (WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE && 201 vif->type != NL80211_IFTYPE_STATION)) 202 return -EOPNOTSUPP; 203 204 /* No roc activity running it's probably already done */ 205 if (mld_vif->roc_activity == ROC_NUM_ACTIVITIES) 206 return 0; 207 208 cmd.activity = cpu_to_le32(mld_vif->roc_activity); 209 210 ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 211 &cmd, cmd_len); 212 if (ret) 213 IWL_ERR(mld, "Couldn't send the command to cancel the ROC\n"); 214 215 /* We may have raced with the firmware expiring the ROC instance at 216 * this very moment. In that case, we can have a notification in the 217 * async processing queue. However, none can arrive _after_ this as 218 * ROC_CMD was sent synchronously, i.e. we waited for a response and 219 * the firmware cannot refer to this ROC after the response. Thus, 220 * if we just cancel the notification (if there's one) we'll be at a 221 * clean state for any possible next ROC. 222 */ 223 iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_ROC, 224 mld_vif->roc_activity); 225 226 iwl_mld_destroy_roc(mld, vif, mld_vif); 227 228 return 0; 229 } 230 231 void iwl_mld_handle_roc_notif(struct iwl_mld *mld, 232 struct iwl_rx_packet *pkt) 233 { 234 const struct iwl_roc_notif *notif = (void *)pkt->data; 235 u32 activity = le32_to_cpu(notif->activity); 236 struct iwl_mld_vif *mld_vif; 237 struct ieee80211_vif *vif; 238 239 vif = iwl_mld_find_roc_vif(mld, activity); 240 if (WARN_ON(!vif)) 241 return; 242 243 mld_vif = iwl_mld_vif_from_mac80211(vif); 244 /* It is possible that the ROC was canceled 245 * but the notification was already fired. 246 */ 247 if (mld_vif->roc_activity != activity) 248 return; 249 250 if (le32_to_cpu(notif->success) && 251 le32_to_cpu(notif->started)) { 252 /* We had a successful start */ 253 ieee80211_ready_on_channel(mld->hw); 254 } else { 255 /* ROC was not successful, tell the firmware to remove it */ 256 if (le32_to_cpu(notif->started)) 257 iwl_mld_cancel_roc(mld->hw, vif); 258 else 259 iwl_mld_destroy_roc(mld, vif, mld_vif); 260 /* we need to let know mac80211 about end OR 261 * an unsuccessful start 262 */ 263 ieee80211_remain_on_channel_expired(mld->hw); 264 } 265 } 266