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) 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 ether_addr_copy(peer->addr, mac_addr); 136 list_add(&peer->list, &ab->peers); 137 wake_up(&ab->peer_mapping_wq); 138 } 139 140 ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n", 141 vdev_id, mac_addr, peer_id); 142 143 exit: 144 spin_unlock_bh(&ab->base_lock); 145 } 146 147 static int ath11k_wait_for_peer_common(struct ath11k_base *ab, int vdev_id, 148 const u8 *addr, bool expect_mapped) 149 { 150 int ret; 151 152 ret = wait_event_timeout(ab->peer_mapping_wq, ({ 153 bool mapped; 154 155 spin_lock_bh(&ab->base_lock); 156 mapped = !!ath11k_peer_find(ab, vdev_id, addr); 157 spin_unlock_bh(&ab->base_lock); 158 159 (mapped == expect_mapped || 160 test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)); 161 }), 3 * HZ); 162 163 if (ret <= 0) 164 return -ETIMEDOUT; 165 166 return 0; 167 } 168 169 void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id) 170 { 171 struct ath11k_peer *peer, *tmp; 172 struct ath11k_base *ab = ar->ab; 173 174 lockdep_assert_held(&ar->conf_mutex); 175 176 spin_lock_bh(&ab->base_lock); 177 list_for_each_entry_safe(peer, tmp, &ab->peers, list) { 178 if (peer->vdev_id != vdev_id) 179 continue; 180 181 ath11k_warn(ab, "removing stale peer %pM from vdev_id %d\n", 182 peer->addr, vdev_id); 183 184 list_del(&peer->list); 185 kfree(peer); 186 ar->num_peers--; 187 } 188 189 spin_unlock_bh(&ab->base_lock); 190 } 191 192 static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 *addr) 193 { 194 return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, false); 195 } 196 197 int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, 198 const u8 *addr) 199 { 200 int ret; 201 unsigned long time_left; 202 203 ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr); 204 if (ret) { 205 ath11k_warn(ar->ab, "failed wait for peer deleted"); 206 return ret; 207 } 208 209 time_left = wait_for_completion_timeout(&ar->peer_delete_done, 210 3 * HZ); 211 if (time_left == 0) { 212 ath11k_warn(ar->ab, "Timeout in receiving peer delete response\n"); 213 return -ETIMEDOUT; 214 } 215 216 return 0; 217 } 218 219 int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) 220 { 221 int ret; 222 223 lockdep_assert_held(&ar->conf_mutex); 224 225 reinit_completion(&ar->peer_delete_done); 226 227 ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); 228 if (ret) { 229 ath11k_warn(ar->ab, 230 "failed to delete peer vdev_id %d addr %pM ret %d\n", 231 vdev_id, addr, ret); 232 return ret; 233 } 234 235 ret = ath11k_wait_for_peer_delete_done(ar, vdev_id, addr); 236 if (ret) 237 return ret; 238 239 ar->num_peers--; 240 241 return 0; 242 } 243 244 static int ath11k_wait_for_peer_created(struct ath11k *ar, int vdev_id, const u8 *addr) 245 { 246 return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, true); 247 } 248 249 int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, 250 struct ieee80211_sta *sta, struct peer_create_params *param) 251 { 252 struct ath11k_peer *peer; 253 int ret; 254 255 lockdep_assert_held(&ar->conf_mutex); 256 257 if (ar->num_peers > (ar->max_num_peers - 1)) { 258 ath11k_warn(ar->ab, 259 "failed to create peer due to insufficient peer entry resource in firmware\n"); 260 return -ENOBUFS; 261 } 262 263 spin_lock_bh(&ar->ab->base_lock); 264 peer = ath11k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr); 265 if (peer) { 266 spin_unlock_bh(&ar->ab->base_lock); 267 return -EINVAL; 268 } 269 spin_unlock_bh(&ar->ab->base_lock); 270 271 ret = ath11k_wmi_send_peer_create_cmd(ar, param); 272 if (ret) { 273 ath11k_warn(ar->ab, 274 "failed to send peer create vdev_id %d ret %d\n", 275 param->vdev_id, ret); 276 return ret; 277 } 278 279 ret = ath11k_wait_for_peer_created(ar, param->vdev_id, 280 param->peer_addr); 281 if (ret) 282 return ret; 283 284 spin_lock_bh(&ar->ab->base_lock); 285 286 peer = ath11k_peer_find(ar->ab, param->vdev_id, param->peer_addr); 287 if (!peer) { 288 spin_unlock_bh(&ar->ab->base_lock); 289 ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", 290 param->peer_addr, param->vdev_id); 291 292 reinit_completion(&ar->peer_delete_done); 293 294 ret = ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr, 295 param->vdev_id); 296 if (ret) { 297 ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", 298 param->vdev_id, param->peer_addr); 299 return ret; 300 } 301 302 ret = ath11k_wait_for_peer_delete_done(ar, param->vdev_id, 303 param->peer_addr); 304 if (ret) 305 return ret; 306 307 return -ENOENT; 308 } 309 310 peer->pdev_idx = ar->pdev_idx; 311 peer->sta = sta; 312 arvif->ast_hash = peer->ast_hash; 313 314 peer->sec_type = HAL_ENCRYPT_TYPE_OPEN; 315 peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN; 316 317 ar->num_peers++; 318 319 spin_unlock_bh(&ar->ab->base_lock); 320 321 return 0; 322 } 323