1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 4 */ 5 6 #include "core.h" 7 #include "peer.h" 8 #include "debug.h" 9 10 struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, 11 const u8 *addr) 12 { 13 struct ath11k_peer *peer; 14 15 lockdep_assert_held(&ab->base_lock); 16 17 list_for_each_entry(peer, &ab->peers, list) { 18 if (peer->vdev_id != vdev_id) 19 continue; 20 if (!ether_addr_equal(peer->addr, addr)) 21 continue; 22 23 return peer; 24 } 25 26 return NULL; 27 } 28 29 static struct ath11k_peer *ath11k_peer_find_by_pdev_idx(struct ath11k_base *ab, 30 u8 pdev_idx, const u8 *addr) 31 { 32 struct ath11k_peer *peer; 33 34 lockdep_assert_held(&ab->base_lock); 35 36 list_for_each_entry(peer, &ab->peers, list) { 37 if (peer->pdev_idx != pdev_idx) 38 continue; 39 if (!ether_addr_equal(peer->addr, addr)) 40 continue; 41 42 return peer; 43 } 44 45 return NULL; 46 } 47 48 struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, 49 const u8 *addr) 50 { 51 struct ath11k_peer *peer; 52 53 lockdep_assert_held(&ab->base_lock); 54 55 list_for_each_entry(peer, &ab->peers, list) { 56 if (!ether_addr_equal(peer->addr, addr)) 57 continue; 58 59 return peer; 60 } 61 62 return NULL; 63 } 64 65 struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, 66 int peer_id) 67 { 68 struct ath11k_peer *peer; 69 70 lockdep_assert_held(&ab->base_lock); 71 72 list_for_each_entry(peer, &ab->peers, list) 73 if (peer_id == peer->peer_id) 74 return peer; 75 76 return NULL; 77 } 78 79 struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, 80 int vdev_id) 81 { 82 struct ath11k_peer *peer; 83 84 spin_lock_bh(&ab->base_lock); 85 86 list_for_each_entry(peer, &ab->peers, list) { 87 if (vdev_id == peer->vdev_id) { 88 spin_unlock_bh(&ab->base_lock); 89 return peer; 90 } 91 } 92 spin_unlock_bh(&ab->base_lock); 93 return NULL; 94 } 95 96 void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id) 97 { 98 struct ath11k_peer *peer; 99 100 spin_lock_bh(&ab->base_lock); 101 102 peer = ath11k_peer_find_by_id(ab, peer_id); 103 if (!peer) { 104 ath11k_warn(ab, "peer-unmap-event: unknown peer id %d\n", 105 peer_id); 106 goto exit; 107 } 108 109 ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n", 110 peer->vdev_id, peer->addr, peer_id); 111 112 list_del(&peer->list); 113 kfree(peer); 114 wake_up(&ab->peer_mapping_wq); 115 116 exit: 117 spin_unlock_bh(&ab->base_lock); 118 } 119 120 void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id, 121 u8 *mac_addr, u16 ast_hash, u16 hw_peer_id) 122 { 123 struct ath11k_peer *peer; 124 125 spin_lock_bh(&ab->base_lock); 126 peer = ath11k_peer_find(ab, vdev_id, mac_addr); 127 if (!peer) { 128 peer = kzalloc(sizeof(*peer), GFP_ATOMIC); 129 if (!peer) 130 goto exit; 131 132 peer->vdev_id = vdev_id; 133 peer->peer_id = peer_id; 134 peer->ast_hash = ast_hash; 135 peer->hw_peer_id = hw_peer_id; 136 ether_addr_copy(peer->addr, mac_addr); 137 list_add(&peer->list, &ab->peers); 138 wake_up(&ab->peer_mapping_wq); 139 } 140 141 ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n", 142 vdev_id, mac_addr, peer_id); 143 144 exit: 145 spin_unlock_bh(&ab->base_lock); 146 } 147 148 static int ath11k_wait_for_peer_common(struct ath11k_base *ab, int vdev_id, 149 const u8 *addr, bool expect_mapped) 150 { 151 int ret; 152 153 ret = wait_event_timeout(ab->peer_mapping_wq, ({ 154 bool mapped; 155 156 spin_lock_bh(&ab->base_lock); 157 mapped = !!ath11k_peer_find(ab, vdev_id, addr); 158 spin_unlock_bh(&ab->base_lock); 159 160 (mapped == expect_mapped || 161 test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)); 162 }), 3 * HZ); 163 164 if (ret <= 0) 165 return -ETIMEDOUT; 166 167 return 0; 168 } 169 170 void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id) 171 { 172 struct ath11k_peer *peer, *tmp; 173 struct ath11k_base *ab = ar->ab; 174 175 lockdep_assert_held(&ar->conf_mutex); 176 177 spin_lock_bh(&ab->base_lock); 178 list_for_each_entry_safe(peer, tmp, &ab->peers, list) { 179 if (peer->vdev_id != vdev_id) 180 continue; 181 182 ath11k_warn(ab, "removing stale peer %pM from vdev_id %d\n", 183 peer->addr, vdev_id); 184 185 list_del(&peer->list); 186 kfree(peer); 187 ar->num_peers--; 188 } 189 190 spin_unlock_bh(&ab->base_lock); 191 } 192 193 static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 *addr) 194 { 195 return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, false); 196 } 197 198 int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, 199 const u8 *addr) 200 { 201 int ret; 202 unsigned long time_left; 203 204 ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr); 205 if (ret) { 206 ath11k_warn(ar->ab, "failed wait for peer deleted"); 207 return ret; 208 } 209 210 time_left = wait_for_completion_timeout(&ar->peer_delete_done, 211 3 * HZ); 212 if (time_left == 0) { 213 ath11k_warn(ar->ab, "Timeout in receiving peer delete response\n"); 214 return -ETIMEDOUT; 215 } 216 217 return 0; 218 } 219 220 int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) 221 { 222 int ret; 223 224 lockdep_assert_held(&ar->conf_mutex); 225 226 reinit_completion(&ar->peer_delete_done); 227 228 ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); 229 if (ret) { 230 ath11k_warn(ar->ab, 231 "failed to delete peer vdev_id %d addr %pM ret %d\n", 232 vdev_id, addr, ret); 233 return ret; 234 } 235 236 ret = ath11k_wait_for_peer_delete_done(ar, vdev_id, addr); 237 if (ret) 238 return ret; 239 240 ar->num_peers--; 241 242 return 0; 243 } 244 245 static int ath11k_wait_for_peer_created(struct ath11k *ar, int vdev_id, const u8 *addr) 246 { 247 return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, true); 248 } 249 250 int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, 251 struct ieee80211_sta *sta, struct peer_create_params *param) 252 { 253 struct ath11k_peer *peer; 254 struct ath11k_sta *arsta; 255 int ret, fbret; 256 257 lockdep_assert_held(&ar->conf_mutex); 258 259 if (ar->num_peers > (ar->max_num_peers - 1)) { 260 ath11k_warn(ar->ab, 261 "failed to create peer due to insufficient peer entry resource in firmware\n"); 262 return -ENOBUFS; 263 } 264 265 spin_lock_bh(&ar->ab->base_lock); 266 peer = ath11k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr); 267 if (peer) { 268 spin_unlock_bh(&ar->ab->base_lock); 269 return -EINVAL; 270 } 271 spin_unlock_bh(&ar->ab->base_lock); 272 273 ret = ath11k_wmi_send_peer_create_cmd(ar, param); 274 if (ret) { 275 ath11k_warn(ar->ab, 276 "failed to send peer create vdev_id %d ret %d\n", 277 param->vdev_id, ret); 278 return ret; 279 } 280 281 ret = ath11k_wait_for_peer_created(ar, param->vdev_id, 282 param->peer_addr); 283 if (ret) 284 return ret; 285 286 spin_lock_bh(&ar->ab->base_lock); 287 288 peer = ath11k_peer_find(ar->ab, param->vdev_id, param->peer_addr); 289 if (!peer) { 290 spin_unlock_bh(&ar->ab->base_lock); 291 ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", 292 param->peer_addr, param->vdev_id); 293 294 ret = -ENOENT; 295 goto cleanup; 296 } 297 298 peer->pdev_idx = ar->pdev_idx; 299 peer->sta = sta; 300 301 if (arvif->vif->type == NL80211_IFTYPE_STATION) { 302 arvif->ast_hash = peer->ast_hash; 303 arvif->ast_idx = peer->hw_peer_id; 304 } 305 306 peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; 307 peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; 308 309 if (sta) { 310 arsta = (struct ath11k_sta *)sta->drv_priv; 311 arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) | 312 FIELD_PREP(HTT_TCL_META_DATA_PEER_ID, 313 peer->peer_id); 314 315 /* set HTT extension valid bit to 0 by default */ 316 arsta->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT; 317 } 318 319 ar->num_peers++; 320 321 spin_unlock_bh(&ar->ab->base_lock); 322 323 return 0; 324 325 cleanup: 326 reinit_completion(&ar->peer_delete_done); 327 328 fbret = ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr, 329 param->vdev_id); 330 if (fbret) { 331 ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", 332 param->vdev_id, param->peer_addr); 333 goto exit; 334 } 335 336 fbret = ath11k_wait_for_peer_delete_done(ar, param->vdev_id, 337 param->peer_addr); 338 if (fbret) 339 ath11k_warn(ar->ab, "failed wait for peer %pM delete done id %d fallback ret %d\n", 340 param->peer_addr, param->vdev_id, fbret); 341 342 exit: 343 return ret; 344 } 345