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} |
|