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