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 } 225