0001
0002
0003
0004
0005
0006
0007 #include "core.h"
0008 #include "peer.h"
0009 #include "debug.h"
0010
0011 static struct ath11k_peer *ath11k_peer_find_list_by_id(struct ath11k_base *ab,
0012 int peer_id)
0013 {
0014 struct ath11k_peer *peer;
0015
0016 lockdep_assert_held(&ab->base_lock);
0017
0018 list_for_each_entry(peer, &ab->peers, list) {
0019 if (peer->peer_id != peer_id)
0020 continue;
0021
0022 return peer;
0023 }
0024
0025 return NULL;
0026 }
0027
0028 struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id,
0029 const u8 *addr)
0030 {
0031 struct ath11k_peer *peer;
0032
0033 lockdep_assert_held(&ab->base_lock);
0034
0035 list_for_each_entry(peer, &ab->peers, list) {
0036 if (peer->vdev_id != vdev_id)
0037 continue;
0038 if (!ether_addr_equal(peer->addr, addr))
0039 continue;
0040
0041 return peer;
0042 }
0043
0044 return NULL;
0045 }
0046
0047 struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab,
0048 const u8 *addr)
0049 {
0050 struct ath11k_peer *peer;
0051
0052 lockdep_assert_held(&ab->base_lock);
0053
0054 if (!ab->rhead_peer_addr)
0055 return NULL;
0056
0057 peer = rhashtable_lookup_fast(ab->rhead_peer_addr, addr,
0058 ab->rhash_peer_addr_param);
0059
0060 return peer;
0061 }
0062
0063 struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab,
0064 int peer_id)
0065 {
0066 struct ath11k_peer *peer;
0067
0068 lockdep_assert_held(&ab->base_lock);
0069
0070 if (!ab->rhead_peer_id)
0071 return NULL;
0072
0073 peer = rhashtable_lookup_fast(ab->rhead_peer_id, &peer_id,
0074 ab->rhash_peer_id_param);
0075
0076 return peer;
0077 }
0078
0079 struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab,
0080 int vdev_id)
0081 {
0082 struct ath11k_peer *peer;
0083
0084 spin_lock_bh(&ab->base_lock);
0085
0086 list_for_each_entry(peer, &ab->peers, list) {
0087 if (vdev_id == peer->vdev_id) {
0088 spin_unlock_bh(&ab->base_lock);
0089 return peer;
0090 }
0091 }
0092 spin_unlock_bh(&ab->base_lock);
0093 return NULL;
0094 }
0095
0096 void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)
0097 {
0098 struct ath11k_peer *peer;
0099
0100 spin_lock_bh(&ab->base_lock);
0101
0102 peer = ath11k_peer_find_list_by_id(ab, peer_id);
0103 if (!peer) {
0104 ath11k_warn(ab, "peer-unmap-event: unknown peer id %d\n",
0105 peer_id);
0106 goto exit;
0107 }
0108
0109 ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
0110 peer->vdev_id, peer->addr, peer_id);
0111
0112 list_del(&peer->list);
0113 kfree(peer);
0114 wake_up(&ab->peer_mapping_wq);
0115
0116 exit:
0117 spin_unlock_bh(&ab->base_lock);
0118 }
0119
0120 void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
0121 u8 *mac_addr, u16 ast_hash, u16 hw_peer_id)
0122 {
0123 struct ath11k_peer *peer;
0124
0125 spin_lock_bh(&ab->base_lock);
0126 peer = ath11k_peer_find(ab, vdev_id, mac_addr);
0127 if (!peer) {
0128 peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
0129 if (!peer)
0130 goto exit;
0131
0132 peer->vdev_id = vdev_id;
0133 peer->peer_id = peer_id;
0134 peer->ast_hash = ast_hash;
0135 peer->hw_peer_id = hw_peer_id;
0136 ether_addr_copy(peer->addr, mac_addr);
0137 list_add(&peer->list, &ab->peers);
0138 wake_up(&ab->peer_mapping_wq);
0139 }
0140
0141 ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n",
0142 vdev_id, mac_addr, peer_id);
0143
0144 exit:
0145 spin_unlock_bh(&ab->base_lock);
0146 }
0147
0148 static int ath11k_wait_for_peer_common(struct ath11k_base *ab, int vdev_id,
0149 const u8 *addr, bool expect_mapped)
0150 {
0151 int ret;
0152
0153 ret = wait_event_timeout(ab->peer_mapping_wq, ({
0154 bool mapped;
0155
0156 spin_lock_bh(&ab->base_lock);
0157 mapped = !!ath11k_peer_find(ab, vdev_id, addr);
0158 spin_unlock_bh(&ab->base_lock);
0159
0160 (mapped == expect_mapped ||
0161 test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags));
0162 }), 3 * HZ);
0163
0164 if (ret <= 0)
0165 return -ETIMEDOUT;
0166
0167 return 0;
0168 }
0169
0170 static inline int ath11k_peer_rhash_insert(struct ath11k_base *ab,
0171 struct rhashtable *rtbl,
0172 struct rhash_head *rhead,
0173 struct rhashtable_params *params,
0174 void *key)
0175 {
0176 struct ath11k_peer *tmp;
0177
0178 lockdep_assert_held(&ab->tbl_mtx_lock);
0179
0180 tmp = rhashtable_lookup_get_insert_fast(rtbl, rhead, *params);
0181
0182 if (!tmp)
0183 return 0;
0184 else if (IS_ERR(tmp))
0185 return PTR_ERR(tmp);
0186 else
0187 return -EEXIST;
0188 }
0189
0190 static inline int ath11k_peer_rhash_remove(struct ath11k_base *ab,
0191 struct rhashtable *rtbl,
0192 struct rhash_head *rhead,
0193 struct rhashtable_params *params)
0194 {
0195 int ret;
0196
0197 lockdep_assert_held(&ab->tbl_mtx_lock);
0198
0199 ret = rhashtable_remove_fast(rtbl, rhead, *params);
0200 if (ret && ret != -ENOENT)
0201 return ret;
0202
0203 return 0;
0204 }
0205
0206 static int ath11k_peer_rhash_add(struct ath11k_base *ab, struct ath11k_peer *peer)
0207 {
0208 int ret;
0209
0210 lockdep_assert_held(&ab->base_lock);
0211 lockdep_assert_held(&ab->tbl_mtx_lock);
0212
0213 if (!ab->rhead_peer_id || !ab->rhead_peer_addr)
0214 return -EPERM;
0215
0216 ret = ath11k_peer_rhash_insert(ab, ab->rhead_peer_id, &peer->rhash_id,
0217 &ab->rhash_peer_id_param, &peer->peer_id);
0218 if (ret) {
0219 ath11k_warn(ab, "failed to add peer %pM with id %d in rhash_id ret %d\n",
0220 peer->addr, peer->peer_id, ret);
0221 return ret;
0222 }
0223
0224 ret = ath11k_peer_rhash_insert(ab, ab->rhead_peer_addr, &peer->rhash_addr,
0225 &ab->rhash_peer_addr_param, &peer->addr);
0226 if (ret) {
0227 ath11k_warn(ab, "failed to add peer %pM with id %d in rhash_addr ret %d\n",
0228 peer->addr, peer->peer_id, ret);
0229 goto err_clean;
0230 }
0231
0232 return 0;
0233
0234 err_clean:
0235 ath11k_peer_rhash_remove(ab, ab->rhead_peer_id, &peer->rhash_id,
0236 &ab->rhash_peer_id_param);
0237 return ret;
0238 }
0239
0240 void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id)
0241 {
0242 struct ath11k_peer *peer, *tmp;
0243 struct ath11k_base *ab = ar->ab;
0244
0245 lockdep_assert_held(&ar->conf_mutex);
0246
0247 mutex_lock(&ab->tbl_mtx_lock);
0248 spin_lock_bh(&ab->base_lock);
0249 list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
0250 if (peer->vdev_id != vdev_id)
0251 continue;
0252
0253 ath11k_warn(ab, "removing stale peer %pM from vdev_id %d\n",
0254 peer->addr, vdev_id);
0255
0256 ath11k_peer_rhash_delete(ab, peer);
0257 list_del(&peer->list);
0258 kfree(peer);
0259 ar->num_peers--;
0260 }
0261
0262 spin_unlock_bh(&ab->base_lock);
0263 mutex_unlock(&ab->tbl_mtx_lock);
0264 }
0265
0266 static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 *addr)
0267 {
0268 return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, false);
0269 }
0270
0271 int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
0272 const u8 *addr)
0273 {
0274 int ret;
0275 unsigned long time_left;
0276
0277 ret = ath11k_wait_for_peer_deleted(ar, vdev_id, addr);
0278 if (ret) {
0279 ath11k_warn(ar->ab, "failed wait for peer deleted");
0280 return ret;
0281 }
0282
0283 time_left = wait_for_completion_timeout(&ar->peer_delete_done,
0284 3 * HZ);
0285 if (time_left == 0) {
0286 ath11k_warn(ar->ab, "Timeout in receiving peer delete response\n");
0287 return -ETIMEDOUT;
0288 }
0289
0290 return 0;
0291 }
0292
0293 static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr)
0294 {
0295 int ret;
0296 struct ath11k_peer *peer;
0297 struct ath11k_base *ab = ar->ab;
0298
0299 lockdep_assert_held(&ar->conf_mutex);
0300
0301 mutex_lock(&ab->tbl_mtx_lock);
0302 spin_lock_bh(&ab->base_lock);
0303
0304 peer = ath11k_peer_find_by_addr(ab, addr);
0305 if (!peer) {
0306 spin_unlock_bh(&ab->base_lock);
0307 mutex_unlock(&ab->tbl_mtx_lock);
0308
0309 ath11k_warn(ab,
0310 "failed to find peer vdev_id %d addr %pM in delete\n",
0311 vdev_id, addr);
0312 return -EINVAL;
0313 }
0314
0315 ath11k_peer_rhash_delete(ab, peer);
0316
0317 spin_unlock_bh(&ab->base_lock);
0318 mutex_unlock(&ab->tbl_mtx_lock);
0319
0320 reinit_completion(&ar->peer_delete_done);
0321
0322 ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id);
0323 if (ret) {
0324 ath11k_warn(ab,
0325 "failed to delete peer vdev_id %d addr %pM ret %d\n",
0326 vdev_id, addr, ret);
0327 return ret;
0328 }
0329
0330 ret = ath11k_wait_for_peer_delete_done(ar, vdev_id, addr);
0331 if (ret)
0332 return ret;
0333
0334 return 0;
0335 }
0336
0337 int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)
0338 {
0339 int ret;
0340
0341 lockdep_assert_held(&ar->conf_mutex);
0342
0343 ret = __ath11k_peer_delete(ar, vdev_id, addr);
0344 if (ret)
0345 return ret;
0346
0347 ar->num_peers--;
0348
0349 return 0;
0350 }
0351
0352 static int ath11k_wait_for_peer_created(struct ath11k *ar, int vdev_id, const u8 *addr)
0353 {
0354 return ath11k_wait_for_peer_common(ar->ab, vdev_id, addr, true);
0355 }
0356
0357 int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
0358 struct ieee80211_sta *sta, struct peer_create_params *param)
0359 {
0360 struct ath11k_peer *peer;
0361 struct ath11k_sta *arsta;
0362 int ret, fbret;
0363
0364 lockdep_assert_held(&ar->conf_mutex);
0365
0366 if (ar->num_peers > (ar->max_num_peers - 1)) {
0367 ath11k_warn(ar->ab,
0368 "failed to create peer due to insufficient peer entry resource in firmware\n");
0369 return -ENOBUFS;
0370 }
0371
0372 spin_lock_bh(&ar->ab->base_lock);
0373 peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr);
0374 if (peer) {
0375 spin_unlock_bh(&ar->ab->base_lock);
0376 return -EINVAL;
0377 }
0378 spin_unlock_bh(&ar->ab->base_lock);
0379
0380 ret = ath11k_wmi_send_peer_create_cmd(ar, param);
0381 if (ret) {
0382 ath11k_warn(ar->ab,
0383 "failed to send peer create vdev_id %d ret %d\n",
0384 param->vdev_id, ret);
0385 return ret;
0386 }
0387
0388 ret = ath11k_wait_for_peer_created(ar, param->vdev_id,
0389 param->peer_addr);
0390 if (ret)
0391 return ret;
0392
0393 mutex_lock(&ar->ab->tbl_mtx_lock);
0394 spin_lock_bh(&ar->ab->base_lock);
0395
0396 peer = ath11k_peer_find(ar->ab, param->vdev_id, param->peer_addr);
0397 if (!peer) {
0398 spin_unlock_bh(&ar->ab->base_lock);
0399 mutex_unlock(&ar->ab->tbl_mtx_lock);
0400 ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n",
0401 param->peer_addr, param->vdev_id);
0402
0403 ret = -ENOENT;
0404 goto cleanup;
0405 }
0406
0407 ret = ath11k_peer_rhash_add(ar->ab, peer);
0408 if (ret) {
0409 spin_unlock_bh(&ar->ab->base_lock);
0410 mutex_unlock(&ar->ab->tbl_mtx_lock);
0411 goto cleanup;
0412 }
0413
0414 peer->pdev_idx = ar->pdev_idx;
0415 peer->sta = sta;
0416
0417 if (arvif->vif->type == NL80211_IFTYPE_STATION) {
0418 arvif->ast_hash = peer->ast_hash;
0419 arvif->ast_idx = peer->hw_peer_id;
0420 }
0421
0422 peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
0423 peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
0424
0425 if (sta) {
0426 arsta = (struct ath11k_sta *)sta->drv_priv;
0427 arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) |
0428 FIELD_PREP(HTT_TCL_META_DATA_PEER_ID,
0429 peer->peer_id);
0430
0431
0432 arsta->tcl_metadata &= ~HTT_TCL_META_DATA_VALID_HTT;
0433 }
0434
0435 ar->num_peers++;
0436
0437 spin_unlock_bh(&ar->ab->base_lock);
0438 mutex_unlock(&ar->ab->tbl_mtx_lock);
0439
0440 return 0;
0441
0442 cleanup:
0443 fbret = __ath11k_peer_delete(ar, param->vdev_id, param->peer_addr);
0444 if (fbret)
0445 ath11k_warn(ar->ab, "failed peer %pM delete vdev_id %d fallback ret %d\n",
0446 param->peer_addr, param->vdev_id, fbret);
0447
0448 return ret;
0449 }
0450
0451 int ath11k_peer_rhash_delete(struct ath11k_base *ab, struct ath11k_peer *peer)
0452 {
0453 int ret;
0454
0455 lockdep_assert_held(&ab->base_lock);
0456 lockdep_assert_held(&ab->tbl_mtx_lock);
0457
0458 if (!ab->rhead_peer_id || !ab->rhead_peer_addr)
0459 return -EPERM;
0460
0461 ret = ath11k_peer_rhash_remove(ab, ab->rhead_peer_addr, &peer->rhash_addr,
0462 &ab->rhash_peer_addr_param);
0463 if (ret) {
0464 ath11k_warn(ab, "failed to remove peer %pM id %d in rhash_addr ret %d\n",
0465 peer->addr, peer->peer_id, ret);
0466 return ret;
0467 }
0468
0469 ret = ath11k_peer_rhash_remove(ab, ab->rhead_peer_id, &peer->rhash_id,
0470 &ab->rhash_peer_id_param);
0471 if (ret) {
0472 ath11k_warn(ab, "failed to remove peer %pM id %d in rhash_id ret %d\n",
0473 peer->addr, peer->peer_id, ret);
0474 return ret;
0475 }
0476
0477 return 0;
0478 }
0479
0480 static int ath11k_peer_rhash_id_tbl_init(struct ath11k_base *ab)
0481 {
0482 struct rhashtable_params *param;
0483 struct rhashtable *rhash_id_tbl;
0484 int ret;
0485 size_t size;
0486
0487 lockdep_assert_held(&ab->tbl_mtx_lock);
0488
0489 if (ab->rhead_peer_id)
0490 return 0;
0491
0492 size = sizeof(*ab->rhead_peer_id);
0493 rhash_id_tbl = kzalloc(size, GFP_KERNEL);
0494 if (!rhash_id_tbl) {
0495 ath11k_warn(ab, "failed to init rhash id table due to no mem (size %zu)\n",
0496 size);
0497 return -ENOMEM;
0498 }
0499
0500 param = &ab->rhash_peer_id_param;
0501
0502 param->key_offset = offsetof(struct ath11k_peer, peer_id);
0503 param->head_offset = offsetof(struct ath11k_peer, rhash_id);
0504 param->key_len = sizeof_field(struct ath11k_peer, peer_id);
0505 param->automatic_shrinking = true;
0506 param->nelem_hint = ab->num_radios * TARGET_NUM_PEERS_PDEV(ab);
0507
0508 ret = rhashtable_init(rhash_id_tbl, param);
0509 if (ret) {
0510 ath11k_warn(ab, "failed to init peer id rhash table %d\n", ret);
0511 goto err_free;
0512 }
0513
0514 spin_lock_bh(&ab->base_lock);
0515
0516 if (!ab->rhead_peer_id) {
0517 ab->rhead_peer_id = rhash_id_tbl;
0518 } else {
0519 spin_unlock_bh(&ab->base_lock);
0520 goto cleanup_tbl;
0521 }
0522
0523 spin_unlock_bh(&ab->base_lock);
0524
0525 return 0;
0526
0527 cleanup_tbl:
0528 rhashtable_destroy(rhash_id_tbl);
0529 err_free:
0530 kfree(rhash_id_tbl);
0531
0532 return ret;
0533 }
0534
0535 static int ath11k_peer_rhash_addr_tbl_init(struct ath11k_base *ab)
0536 {
0537 struct rhashtable_params *param;
0538 struct rhashtable *rhash_addr_tbl;
0539 int ret;
0540 size_t size;
0541
0542 lockdep_assert_held(&ab->tbl_mtx_lock);
0543
0544 if (ab->rhead_peer_addr)
0545 return 0;
0546
0547 size = sizeof(*ab->rhead_peer_addr);
0548 rhash_addr_tbl = kzalloc(size, GFP_KERNEL);
0549 if (!rhash_addr_tbl) {
0550 ath11k_warn(ab, "failed to init rhash addr table due to no mem (size %zu)\n",
0551 size);
0552 return -ENOMEM;
0553 }
0554
0555 param = &ab->rhash_peer_addr_param;
0556
0557 param->key_offset = offsetof(struct ath11k_peer, addr);
0558 param->head_offset = offsetof(struct ath11k_peer, rhash_addr);
0559 param->key_len = sizeof_field(struct ath11k_peer, addr);
0560 param->automatic_shrinking = true;
0561 param->nelem_hint = ab->num_radios * TARGET_NUM_PEERS_PDEV(ab);
0562
0563 ret = rhashtable_init(rhash_addr_tbl, param);
0564 if (ret) {
0565 ath11k_warn(ab, "failed to init peer addr rhash table %d\n", ret);
0566 goto err_free;
0567 }
0568
0569 spin_lock_bh(&ab->base_lock);
0570
0571 if (!ab->rhead_peer_addr) {
0572 ab->rhead_peer_addr = rhash_addr_tbl;
0573 } else {
0574 spin_unlock_bh(&ab->base_lock);
0575 goto cleanup_tbl;
0576 }
0577
0578 spin_unlock_bh(&ab->base_lock);
0579
0580 return 0;
0581
0582 cleanup_tbl:
0583 rhashtable_destroy(rhash_addr_tbl);
0584 err_free:
0585 kfree(rhash_addr_tbl);
0586
0587 return ret;
0588 }
0589
0590 static inline void ath11k_peer_rhash_id_tbl_destroy(struct ath11k_base *ab)
0591 {
0592 lockdep_assert_held(&ab->tbl_mtx_lock);
0593
0594 if (!ab->rhead_peer_id)
0595 return;
0596
0597 rhashtable_destroy(ab->rhead_peer_id);
0598 kfree(ab->rhead_peer_id);
0599 ab->rhead_peer_id = NULL;
0600 }
0601
0602 static inline void ath11k_peer_rhash_addr_tbl_destroy(struct ath11k_base *ab)
0603 {
0604 lockdep_assert_held(&ab->tbl_mtx_lock);
0605
0606 if (!ab->rhead_peer_addr)
0607 return;
0608
0609 rhashtable_destroy(ab->rhead_peer_addr);
0610 kfree(ab->rhead_peer_addr);
0611 ab->rhead_peer_addr = NULL;
0612 }
0613
0614 int ath11k_peer_rhash_tbl_init(struct ath11k_base *ab)
0615 {
0616 int ret;
0617
0618 mutex_lock(&ab->tbl_mtx_lock);
0619
0620 ret = ath11k_peer_rhash_id_tbl_init(ab);
0621 if (ret)
0622 goto out;
0623
0624 ret = ath11k_peer_rhash_addr_tbl_init(ab);
0625 if (ret)
0626 goto cleanup_tbl;
0627
0628 mutex_unlock(&ab->tbl_mtx_lock);
0629
0630 return 0;
0631
0632 cleanup_tbl:
0633 ath11k_peer_rhash_id_tbl_destroy(ab);
0634 out:
0635 mutex_unlock(&ab->tbl_mtx_lock);
0636 return ret;
0637 }
0638
0639 void ath11k_peer_rhash_tbl_destroy(struct ath11k_base *ab)
0640 {
0641 mutex_lock(&ab->tbl_mtx_lock);
0642
0643 ath11k_peer_rhash_addr_tbl_destroy(ab);
0644 ath11k_peer_rhash_id_tbl_destroy(ab);
0645
0646 mutex_unlock(&ab->tbl_mtx_lock);
0647 }