sta_info.c (246b39e4a1ba5ad77edfb2f28d147abc5e2bb0a7) sta_info.c (cb71f1d136a635decf43c3b502ee34fb05640fcd)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2002-2005, Instant802 Networks, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
7 * Copyright (C) 2018-2021 Intel Corporation
8 */

--- 50 unchanged lines hidden (view full) ---

59 * calls are available.
60 *
61 * There is no concept of ownership on a STA entry, each structure is
62 * owned by the global hash table/list until it is removed. All users of
63 * the structure need to be RCU protected so that the structure won't be
64 * freed before they are done using it.
65 */
66
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2002-2005, Instant802 Networks, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
7 * Copyright (C) 2018-2021 Intel Corporation
8 */

--- 50 unchanged lines hidden (view full) ---

59 * calls are available.
60 *
61 * There is no concept of ownership on a STA entry, each structure is
62 * owned by the global hash table/list until it is removed. All users of
63 * the structure need to be RCU protected so that the structure won't be
64 * freed before they are done using it.
65 */
66
67struct sta_link_alloc {
68 struct link_sta_info info;
69 struct ieee80211_link_sta sta;
70};
71
67static const struct rhashtable_params sta_rht_params = {
68 .nelem_hint = 3, /* start small */
69 .automatic_shrinking = true,
70 .head_offset = offsetof(struct sta_info, hash_node),
71 .key_offset = offsetof(struct sta_info, addr),
72 .key_len = ETH_ALEN,
73 .max_size = CONFIG_MAC80211_STA_HASH_MAX_SIZE,
74};

--- 165 unchanged lines hidden (view full) ---

240 continue;
241 }
242 return sta;
243 }
244
245 return NULL;
246}
247
72static const struct rhashtable_params sta_rht_params = {
73 .nelem_hint = 3, /* start small */
74 .automatic_shrinking = true,
75 .head_offset = offsetof(struct sta_info, hash_node),
76 .key_offset = offsetof(struct sta_info, addr),
77 .key_len = ETH_ALEN,
78 .max_size = CONFIG_MAC80211_STA_HASH_MAX_SIZE,
79};

--- 165 unchanged lines hidden (view full) ---

245 continue;
246 }
247 return sta;
248 }
249
250 return NULL;
251}
252
248static void sta_info_free_links(struct sta_info *sta)
253static void sta_info_free_link(struct link_sta_info *link_sta)
249{
254{
250 unsigned int link_id;
255 free_percpu(link_sta->pcpu_rx_stats);
256}
251
257
252 for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
253 if (!sta->link[link_id])
254 continue;
255 free_percpu(sta->link[link_id]->pcpu_rx_stats);
258static void sta_remove_link(struct sta_info *sta, unsigned int link_id)
259{
260 struct sta_link_alloc *alloc = NULL;
256
261
257 if (sta->link[link_id] != &sta->deflink)
258 kfree(sta->link[link_id]);
262 if (WARN_ON(!sta->link[link_id]))
263 return;
264
265 if (sta->link[link_id] != &sta->deflink)
266 alloc = container_of(sta->link[link_id], typeof(*alloc), info);
267
268 sta->sta.valid_links &= ~BIT(link_id);
269 sta->link[link_id] = NULL;
270 sta->sta.link[link_id] = NULL;
271 if (alloc) {
272 sta_info_free_link(&alloc->info);
273 kfree(alloc);
259 }
260}
261
262/**
263 * sta_info_free - free STA
264 *
265 * @local: pointer to the global information
266 * @sta: STA info to free
267 *
268 * This function must undo everything done by sta_info_alloc()
269 * that may happen before sta_info_insert(). It may only be
270 * called when sta_info_insert() has not been attempted (and
271 * if that fails, the station is freed anyway.)
272 */
273void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
274{
274 }
275}
276
277/**
278 * sta_info_free - free STA
279 *
280 * @local: pointer to the global information
281 * @sta: STA info to free
282 *
283 * This function must undo everything done by sta_info_alloc()
284 * that may happen before sta_info_insert(). It may only be
285 * called when sta_info_insert() has not been attempted (and
286 * if that fails, the station is freed anyway.)
287 */
288void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
289{
290 int i;
291
292 for (i = 0; i < ARRAY_SIZE(sta->link); i++) {
293 if (!(sta->sta.valid_links & BIT(i)))
294 continue;
295
296 sta_remove_link(sta, i);
297 }
298
275 /*
276 * If we had used sta_info_pre_move_state() then we might not
277 * have gone through the state transitions down again, so do
278 * it here now (and warn if it's inserted).
279 *
280 * This will clear state such as fast TX/RX that may have been
281 * allocated during state transitions.
282 */

--- 14 unchanged lines hidden (view full) ---

297
298 if (sta->sta.txq[0])
299 kfree(to_txq_info(sta->sta.txq[0]));
300 kfree(rcu_dereference_raw(sta->sta.rates));
301#ifdef CONFIG_MAC80211_MESH
302 kfree(sta->mesh);
303#endif
304
299 /*
300 * If we had used sta_info_pre_move_state() then we might not
301 * have gone through the state transitions down again, so do
302 * it here now (and warn if it's inserted).
303 *
304 * This will clear state such as fast TX/RX that may have been
305 * allocated during state transitions.
306 */

--- 14 unchanged lines hidden (view full) ---

321
322 if (sta->sta.txq[0])
323 kfree(to_txq_info(sta->sta.txq[0]));
324 kfree(rcu_dereference_raw(sta->sta.rates));
325#ifdef CONFIG_MAC80211_MESH
326 kfree(sta->mesh);
327#endif
328
305 sta_info_free_links(sta);
329 sta_info_free_link(&sta->deflink);
306 kfree(sta);
307}
308
309/* Caller must hold local->sta_mtx */
310static int sta_info_hash_add(struct ieee80211_local *local,
311 struct sta_info *sta)
312{
313 return rhltable_insert(&local->sta_hash, &sta->hash_node,

--- 29 unchanged lines hidden (view full) ---

343 sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
344 sta, gfp);
345 if (!sta->rate_ctrl_priv)
346 return -ENOMEM;
347
348 return 0;
349}
350
330 kfree(sta);
331}
332
333/* Caller must hold local->sta_mtx */
334static int sta_info_hash_add(struct ieee80211_local *local,
335 struct sta_info *sta)
336{
337 return rhltable_insert(&local->sta_hash, &sta->hash_node,

--- 29 unchanged lines hidden (view full) ---

367 sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
368 sta, gfp);
369 if (!sta->rate_ctrl_priv)
370 return -ENOMEM;
371
372 return 0;
373}
374
351static int sta_info_init_link(struct sta_info *sta,
352 unsigned int link_id,
353 struct link_sta_info *link_info,
354 struct ieee80211_link_sta *link_sta,
355 gfp_t gfp)
375static int sta_info_alloc_link(struct ieee80211_local *local,
376 struct link_sta_info *link_info,
377 gfp_t gfp)
356{
378{
357 struct ieee80211_local *local = sta->local;
358 struct ieee80211_hw *hw = &local->hw;
359 int i;
360
379 struct ieee80211_hw *hw = &local->hw;
380 int i;
381
361 link_info->sta = sta;
362 link_info->link_id = link_id;
363
364 if (ieee80211_hw_check(hw, USES_RSS)) {
365 link_info->pcpu_rx_stats =
366 alloc_percpu_gfp(struct ieee80211_sta_rx_stats, gfp);
367 if (!link_info->pcpu_rx_stats)
368 return -ENOMEM;
369 }
370
382 if (ieee80211_hw_check(hw, USES_RSS)) {
383 link_info->pcpu_rx_stats =
384 alloc_percpu_gfp(struct ieee80211_sta_rx_stats, gfp);
385 if (!link_info->pcpu_rx_stats)
386 return -ENOMEM;
387 }
388
371 sta->link[link_id] = link_info;
372 sta->sta.link[link_id] = link_sta;
373
374 link_info->rx_stats.last_rx = jiffies;
375 u64_stats_init(&link_info->rx_stats.syncp);
376
377 ewma_signal_init(&link_info->rx_stats_avg.signal);
378 ewma_avg_signal_init(&link_info->status_stats.avg_ack_signal);
379 for (i = 0; i < ARRAY_SIZE(link_info->rx_stats_avg.chain_signal); i++)
380 ewma_signal_init(&link_info->rx_stats_avg.chain_signal[i]);
381
382 return 0;
383}
384
389 link_info->rx_stats.last_rx = jiffies;
390 u64_stats_init(&link_info->rx_stats.syncp);
391
392 ewma_signal_init(&link_info->rx_stats_avg.signal);
393 ewma_avg_signal_init(&link_info->status_stats.avg_ack_signal);
394 for (i = 0; i < ARRAY_SIZE(link_info->rx_stats_avg.chain_signal); i++)
395 ewma_signal_init(&link_info->rx_stats_avg.chain_signal[i]);
396
397 return 0;
398}
399
400static void sta_info_add_link(struct sta_info *sta,
401 unsigned int link_id,
402 struct link_sta_info *link_info,
403 struct ieee80211_link_sta *link_sta)
404{
405 link_info->sta = sta;
406 link_info->link_id = link_id;
407 sta->link[link_id] = link_info;
408 sta->sta.link[link_id] = link_sta;
409}
410
385struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
411struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
386 const u8 *addr, gfp_t gfp)
412 const u8 *addr, int link_id, gfp_t gfp)
387{
388 struct ieee80211_local *local = sdata->local;
389 struct ieee80211_hw *hw = &local->hw;
390 struct sta_info *sta;
391 int i;
392
393 sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
394 if (!sta)
395 return NULL;
396
397 sta->local = local;
398 sta->sdata = sdata;
399
413{
414 struct ieee80211_local *local = sdata->local;
415 struct ieee80211_hw *hw = &local->hw;
416 struct sta_info *sta;
417 int i;
418
419 sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
420 if (!sta)
421 return NULL;
422
423 sta->local = local;
424 sta->sdata = sdata;
425
400 if (sta_info_init_link(sta, 0, &sta->deflink, &sta->sta.deflink, gfp))
426 if (sta_info_alloc_link(local, &sta->deflink, gfp))
401 return NULL;
402
427 return NULL;
428
429 if (link_id >= 0) {
430 sta_info_add_link(sta, link_id, &sta->deflink,
431 &sta->sta.deflink);
432 sta->sta.valid_links = BIT(link_id);
433 } else {
434 sta_info_add_link(sta, 0, &sta->deflink, &sta->sta.deflink);
435 }
436
403 spin_lock_init(&sta->lock);
404 spin_lock_init(&sta->ps_lock);
405 INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
406 INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
407 mutex_init(&sta->ampdu_mlme.mtx);
408#ifdef CONFIG_MAC80211_MESH
409 if (ieee80211_vif_is_mesh(&sdata->vif)) {
410 sta->mesh = kzalloc(sizeof(*sta->mesh), gfp);

--- 149 unchanged lines hidden (view full) ---

560 sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
561
562 return sta;
563
564free_txq:
565 if (sta->sta.txq[0])
566 kfree(to_txq_info(sta->sta.txq[0]));
567free:
437 spin_lock_init(&sta->lock);
438 spin_lock_init(&sta->ps_lock);
439 INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
440 INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
441 mutex_init(&sta->ampdu_mlme.mtx);
442#ifdef CONFIG_MAC80211_MESH
443 if (ieee80211_vif_is_mesh(&sdata->vif)) {
444 sta->mesh = kzalloc(sizeof(*sta->mesh), gfp);

--- 149 unchanged lines hidden (view full) ---

594 sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
595
596 return sta;
597
598free_txq:
599 if (sta->sta.txq[0])
600 kfree(to_txq_info(sta->sta.txq[0]));
601free:
568 sta_info_free_links(sta);
602 sta_info_free_link(&sta->deflink);
569#ifdef CONFIG_MAC80211_MESH
570 kfree(sta->mesh);
571#endif
572 kfree(sta);
573 return NULL;
574}
575
576static int sta_info_insert_check(struct sta_info *sta)

--- 2031 unchanged lines hidden (view full) ---

2608
2609void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
2610 u32 thr)
2611{
2612 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
2613
2614 sta_update_codel_params(sta, thr);
2615}
603#ifdef CONFIG_MAC80211_MESH
604 kfree(sta->mesh);
605#endif
606 kfree(sta);
607 return NULL;
608}
609
610static int sta_info_insert_check(struct sta_info *sta)

--- 2031 unchanged lines hidden (view full) ---

2642
2643void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
2644 u32 thr)
2645{
2646 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
2647
2648 sta_update_codel_params(sta, thr);
2649}
2650
2651int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id)
2652{
2653 struct ieee80211_sub_if_data *sdata = sta->sdata;
2654 struct sta_link_alloc *alloc;
2655 int ret;
2656
2657 lockdep_assert_held(&sdata->local->sta_mtx);
2658
2659 /* must represent an MLD from the start */
2660 if (WARN_ON(!sta->sta.valid_links))
2661 return -EINVAL;
2662
2663 if (WARN_ON(sta->sta.valid_links & BIT(link_id) ||
2664 sta->link[link_id]))
2665 return -EBUSY;
2666
2667 alloc = kzalloc(sizeof(*alloc), GFP_KERNEL);
2668 if (!alloc)
2669 return -ENOMEM;
2670
2671 ret = sta_info_alloc_link(sdata->local, &alloc->info, GFP_KERNEL);
2672 if (ret) {
2673 kfree(alloc);
2674 return ret;
2675 }
2676
2677 sta_info_add_link(sta, link_id, &alloc->info, &alloc->sta);
2678
2679 return 0;
2680}
2681
2682int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id)
2683{
2684 struct ieee80211_sub_if_data *sdata = sta->sdata;
2685 u16 old_links = sta->sta.valid_links;
2686 u16 new_links = old_links | BIT(link_id);
2687 int ret;
2688
2689 lockdep_assert_held(&sdata->local->sta_mtx);
2690
2691 if (WARN_ON(old_links == new_links || !sta->link[link_id]))
2692 return -EINVAL;
2693
2694 sta->sta.valid_links = new_links;
2695
2696 if (!test_sta_flag(sta, WLAN_STA_INSERTED))
2697 return 0;
2698
2699 ret = drv_change_sta_links(sdata->local, sdata, &sta->sta,
2700 old_links, new_links);
2701 if (ret) {
2702 sta->sta.valid_links = old_links;
2703 sta_remove_link(sta, link_id);
2704 }
2705
2706 return ret;
2707}
2708
2709void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
2710{
2711 struct ieee80211_sub_if_data *sdata = sta->sdata;
2712
2713 lockdep_assert_held(&sdata->local->sta_mtx);
2714
2715 sta->sta.valid_links &= ~BIT(link_id);
2716
2717 if (test_sta_flag(sta, WLAN_STA_INSERTED))
2718 drv_change_sta_links(sdata->local, sdata, &sta->sta,
2719 sta->sta.valid_links,
2720 sta->sta.valid_links & ~BIT(link_id));
2721
2722 sta_remove_link(sta, link_id);
2723}