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