aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c22
-rw-r--r--net/mac80211/ieee80211_i.h12
-rw-r--r--net/mac80211/key.c101
-rw-r--r--net/mac80211/key.h11
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/mlme.c144
-rw-r--r--net/mac80211/wext.c8
-rw-r--r--net/tipc/ref.c211
-rw-r--r--net/tipc/ref.h89
9 files changed, 363 insertions, 237 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 8af576c1d2f1..699d97b8de5e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -33,6 +33,8 @@ nl80211_type_to_mac80211_type(enum nl80211_iftype type)
33 case NL80211_IFTYPE_MESH_POINT: 33 case NL80211_IFTYPE_MESH_POINT:
34 return IEEE80211_IF_TYPE_MESH_POINT; 34 return IEEE80211_IF_TYPE_MESH_POINT;
35#endif 35#endif
36 case NL80211_IFTYPE_WDS:
37 return IEEE80211_IF_TYPE_WDS;
36 default: 38 default:
37 return IEEE80211_IF_TYPE_INVALID; 39 return IEEE80211_IF_TYPE_INVALID;
38 } 40 }
@@ -718,12 +720,18 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
718 struct sta_info *sta; 720 struct sta_info *sta;
719 721
720 if (mac) { 722 if (mac) {
723 rcu_read_lock();
724
721 /* XXX: get sta belonging to dev */ 725 /* XXX: get sta belonging to dev */
722 sta = sta_info_get(local, mac); 726 sta = sta_info_get(local, mac);
723 if (!sta) 727 if (!sta) {
728 rcu_read_unlock();
724 return -ENOENT; 729 return -ENOENT;
730 }
725 731
726 sta_info_unlink(&sta); 732 sta_info_unlink(&sta);
733 rcu_read_unlock();
734
727 sta_info_destroy(sta); 735 sta_info_destroy(sta);
728 } else 736 } else
729 sta_info_flush(local, sdata); 737 sta_info_flush(local, sdata);
@@ -740,17 +748,23 @@ static int ieee80211_change_station(struct wiphy *wiphy,
740 struct sta_info *sta; 748 struct sta_info *sta;
741 struct ieee80211_sub_if_data *vlansdata; 749 struct ieee80211_sub_if_data *vlansdata;
742 750
751 rcu_read_lock();
752
743 /* XXX: get sta belonging to dev */ 753 /* XXX: get sta belonging to dev */
744 sta = sta_info_get(local, mac); 754 sta = sta_info_get(local, mac);
745 if (!sta) 755 if (!sta) {
756 rcu_read_unlock();
746 return -ENOENT; 757 return -ENOENT;
758 }
747 759
748 if (params->vlan && params->vlan != sta->sdata->dev) { 760 if (params->vlan && params->vlan != sta->sdata->dev) {
749 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); 761 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
750 762
751 if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN || 763 if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
752 vlansdata->vif.type != IEEE80211_IF_TYPE_AP) 764 vlansdata->vif.type != IEEE80211_IF_TYPE_AP) {
765 rcu_read_unlock();
753 return -EINVAL; 766 return -EINVAL;
767 }
754 768
755 sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); 769 sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
756 ieee80211_send_layer2_update(sta); 770 ieee80211_send_layer2_update(sta);
@@ -758,6 +772,8 @@ static int ieee80211_change_station(struct wiphy *wiphy,
758 772
759 sta_apply_parameters(local, sta, params); 773 sta_apply_parameters(local, sta, params);
760 774
775 rcu_read_unlock();
776
761 return 0; 777 return 0;
762} 778}
763 779
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c642538e8282..8e53ce7ed444 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -102,7 +102,7 @@ struct ieee80211_sta_bss {
102 u64 timestamp; 102 u64 timestamp;
103 int beacon_int; 103 int beacon_int;
104 104
105 int probe_resp; 105 bool probe_resp;
106 unsigned long last_update; 106 unsigned long last_update;
107 107
108 /* during assocation, we save an ERP value from a probe response so 108 /* during assocation, we save an ERP value from a probe response so
@@ -600,8 +600,7 @@ struct ieee80211_local {
600 /* 600 /*
601 * The lock only protects the list, hash, timer and counter 601 * The lock only protects the list, hash, timer and counter
602 * against manipulation, reads are done in RCU. Additionally, 602 * against manipulation, reads are done in RCU. Additionally,
603 * the lock protects each BSS's TIM bitmap, a few items in 603 * the lock protects each BSS's TIM bitmap.
604 * STA info structures and various key pointers.
605 */ 604 */
606 spinlock_t sta_lock; 605 spinlock_t sta_lock;
607 unsigned long num_sta; 606 unsigned long num_sta;
@@ -635,6 +634,13 @@ struct ieee80211_local {
635 634
636 struct list_head interfaces; 635 struct list_head interfaces;
637 636
637 /*
638 * Key lock, protects sdata's key_list and sta_info's
639 * key pointers (write access, they're RCU.)
640 */
641 spinlock_t key_lock;
642
643
638 bool sta_sw_scanning; 644 bool sta_sw_scanning;
639 bool sta_hw_scanning; 645 bool sta_hw_scanning;
640 int scan_channel_idx; 646 int scan_channel_idx;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 711e36e54ff8..150d66dbda9d 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -74,9 +74,12 @@ static void add_todo(struct ieee80211_key *key, u32 flag)
74 74
75 spin_lock(&todo_lock); 75 spin_lock(&todo_lock);
76 key->flags |= flag; 76 key->flags |= flag;
77 /* only add if not already added */ 77 /*
78 if (list_empty(&key->todo)) 78 * Remove again if already on the list so that we move it to the end.
79 list_add(&key->todo, &todo_list); 79 */
80 if (!list_empty(&key->todo))
81 list_del(&key->todo);
82 list_add_tail(&key->todo, &todo_list);
80 schedule_work(&todo_work); 83 schedule_work(&todo_work);
81 spin_unlock(&todo_lock); 84 spin_unlock(&todo_lock);
82} 85}
@@ -210,9 +213,9 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
210{ 213{
211 unsigned long flags; 214 unsigned long flags;
212 215
213 spin_lock_irqsave(&sdata->local->sta_lock, flags); 216 spin_lock_irqsave(&sdata->local->key_lock, flags);
214 __ieee80211_set_default_key(sdata, idx); 217 __ieee80211_set_default_key(sdata, idx);
215 spin_unlock_irqrestore(&sdata->local->sta_lock, flags); 218 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
216} 219}
217 220
218 221
@@ -339,7 +342,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
339 } 342 }
340 } 343 }
341 344
342 spin_lock_irqsave(&sdata->local->sta_lock, flags); 345 spin_lock_irqsave(&sdata->local->key_lock, flags);
343 346
344 if (sta) 347 if (sta)
345 old_key = sta->key; 348 old_key = sta->key;
@@ -348,68 +351,81 @@ void ieee80211_key_link(struct ieee80211_key *key,
348 351
349 __ieee80211_key_replace(sdata, sta, old_key, key); 352 __ieee80211_key_replace(sdata, sta, old_key, key);
350 353
351 spin_unlock_irqrestore(&sdata->local->sta_lock, flags); 354 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
352 355
353 /* free old key later */ 356 /* free old key later */
354 add_todo(old_key, KEY_FLAG_TODO_DELETE); 357 add_todo(old_key, KEY_FLAG_TODO_DELETE);
355 358
356 add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); 359 add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
357 if (netif_running(sdata->dev)) 360 if (netif_running(sdata->dev))
358 add_todo(key, KEY_FLAG_TODO_HWACCEL); 361 add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
359} 362}
360 363
361void ieee80211_key_free(struct ieee80211_key *key) 364static void __ieee80211_key_free(struct ieee80211_key *key)
362{ 365{
363 unsigned long flags;
364
365 if (!key)
366 return;
367
368 /* 366 /*
369 * Replace key with nothingness if it was ever used. 367 * Replace key with nothingness if it was ever used.
370 */ 368 */
371 if (key->sdata) { 369 if (key->sdata)
372 spin_lock_irqsave(&key->sdata->local->sta_lock, flags);
373 __ieee80211_key_replace(key->sdata, key->sta, 370 __ieee80211_key_replace(key->sdata, key->sta,
374 key, NULL); 371 key, NULL);
375 spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags);
376 }
377 372
378 add_todo(key, KEY_FLAG_TODO_DELETE); 373 add_todo(key, KEY_FLAG_TODO_DELETE);
379} 374}
380 375
381void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) 376void ieee80211_key_free(struct ieee80211_key *key)
382{ 377{
383 struct ieee80211_key *key; 378 unsigned long flags;
384
385 might_sleep();
386 379
387 if (WARN_ON(!netif_running(sdata->dev))) 380 if (!key)
388 return; 381 return;
389 382
390 ieee80211_key_lock(); 383 spin_lock_irqsave(&key->sdata->local->key_lock, flags);
384 __ieee80211_key_free(key);
385 spin_unlock_irqrestore(&key->sdata->local->key_lock, flags);
386}
387
388/*
389 * To be safe against concurrent manipulations of the list (which shouldn't
390 * actually happen) we need to hold the spinlock. But under the spinlock we
391 * can't actually do much, so we defer processing to the todo list. Then run
392 * the todo list to be sure the operation and possibly previously pending
393 * operations are completed.
394 */
395static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
396 u32 todo_flags)
397{
398 struct ieee80211_key *key;
399 unsigned long flags;
391 400
401 might_sleep();
402
403 spin_lock_irqsave(&sdata->local->key_lock, flags);
392 list_for_each_entry(key, &sdata->key_list, list) 404 list_for_each_entry(key, &sdata->key_list, list)
393 ieee80211_key_enable_hw_accel(key); 405 add_todo(key, todo_flags);
406 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
394 407
395 ieee80211_key_unlock(); 408 ieee80211_key_todo();
396} 409}
397 410
398void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) 411void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
399{ 412{
400 struct ieee80211_key *key; 413 ASSERT_RTNL();
401 414
402 might_sleep(); 415 if (WARN_ON(!netif_running(sdata->dev)))
416 return;
403 417
404 ieee80211_key_lock(); 418 ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
419}
405 420
406 list_for_each_entry(key, &sdata->key_list, list) 421void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
407 ieee80211_key_disable_hw_accel(key); 422{
423 ASSERT_RTNL();
408 424
409 ieee80211_key_unlock(); 425 ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE);
410} 426}
411 427
412static void __ieee80211_key_free(struct ieee80211_key *key) 428static void __ieee80211_key_destroy(struct ieee80211_key *key)
413{ 429{
414 if (!key) 430 if (!key)
415 return; 431 return;
@@ -440,7 +456,8 @@ static void __ieee80211_key_todo(void)
440 list_del_init(&key->todo); 456 list_del_init(&key->todo);
441 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | 457 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
442 KEY_FLAG_TODO_DEFKEY | 458 KEY_FLAG_TODO_DEFKEY |
443 KEY_FLAG_TODO_HWACCEL | 459 KEY_FLAG_TODO_HWACCEL_ADD |
460 KEY_FLAG_TODO_HWACCEL_REMOVE |
444 KEY_FLAG_TODO_DELETE); 461 KEY_FLAG_TODO_DELETE);
445 key->flags &= ~todoflags; 462 key->flags &= ~todoflags;
446 spin_unlock(&todo_lock); 463 spin_unlock(&todo_lock);
@@ -456,12 +473,16 @@ static void __ieee80211_key_todo(void)
456 ieee80211_debugfs_key_add_default(key->sdata); 473 ieee80211_debugfs_key_add_default(key->sdata);
457 work_done = true; 474 work_done = true;
458 } 475 }
459 if (todoflags & KEY_FLAG_TODO_HWACCEL) { 476 if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
460 ieee80211_key_enable_hw_accel(key); 477 ieee80211_key_enable_hw_accel(key);
461 work_done = true; 478 work_done = true;
462 } 479 }
480 if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
481 ieee80211_key_disable_hw_accel(key);
482 work_done = true;
483 }
463 if (todoflags & KEY_FLAG_TODO_DELETE) { 484 if (todoflags & KEY_FLAG_TODO_DELETE) {
464 __ieee80211_key_free(key); 485 __ieee80211_key_destroy(key);
465 work_done = true; 486 work_done = true;
466 } 487 }
467 488
@@ -482,14 +503,16 @@ void ieee80211_key_todo(void)
482void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) 503void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
483{ 504{
484 struct ieee80211_key *key, *tmp; 505 struct ieee80211_key *key, *tmp;
485 LIST_HEAD(tmp_list); 506 unsigned long flags;
486 507
487 ieee80211_key_lock(); 508 ieee80211_key_lock();
488 509
489 ieee80211_debugfs_key_remove_default(sdata); 510 ieee80211_debugfs_key_remove_default(sdata);
490 511
512 spin_lock_irqsave(&sdata->local->key_lock, flags);
491 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 513 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
492 ieee80211_key_free(key); 514 __ieee80211_key_free(key);
515 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
493 516
494 __ieee80211_key_todo(); 517 __ieee80211_key_todo();
495 518
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 5d48518985b3..f52c3df1fe9a 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -54,16 +54,19 @@ struct sta_info;
54 * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an 54 * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an
55 * RCU grace period, no longer be reachable other than from the 55 * RCU grace period, no longer be reachable other than from the
56 * todo list. 56 * todo list.
57 * @KEY_FLAG_TODO_HWACCEL: Key needs to be added to hardware acceleration. 57 * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration.
58 * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware
59 * acceleration.
58 * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. 60 * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated.
59 * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. 61 * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
60 */ 62 */
61enum ieee80211_internal_key_flags { 63enum ieee80211_internal_key_flags {
62 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), 64 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
63 KEY_FLAG_TODO_DELETE = BIT(1), 65 KEY_FLAG_TODO_DELETE = BIT(1),
64 KEY_FLAG_TODO_HWACCEL = BIT(2), 66 KEY_FLAG_TODO_HWACCEL_ADD = BIT(2),
65 KEY_FLAG_TODO_DEFKEY = BIT(3), 67 KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3),
66 KEY_FLAG_TODO_ADD_DEBUGFS = BIT(4), 68 KEY_FLAG_TODO_DEFKEY = BIT(4),
69 KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5),
67}; 70};
68 71
69struct ieee80211_key { 72struct ieee80211_key {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index bfcbcf5353ad..e9a978979d38 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1587,6 +1587,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
1587 1587
1588 INIT_LIST_HEAD(&local->interfaces); 1588 INIT_LIST_HEAD(&local->interfaces);
1589 1589
1590 spin_lock_init(&local->key_lock);
1591
1590 INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); 1592 INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
1591 1593
1592 sta_info_init(local); 1594 sta_info_init(local);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index bdaab1391d4e..6b75cb6c6300 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -350,14 +350,12 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
350 } 350 }
351} 351}
352 352
353 353static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
354static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, 354 bool use_protection,
355 u8 erp_value) 355 bool use_short_preamble)
356{ 356{
357 struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; 357 struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
358 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 358 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
359 bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
360 bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
361 DECLARE_MAC_BUF(mac); 359 DECLARE_MAC_BUF(mac);
362 u32 changed = 0; 360 u32 changed = 0;
363 361
@@ -388,6 +386,32 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
388 return changed; 386 return changed;
389} 387}
390 388
389static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
390 u8 erp_value)
391{
392 bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
393 bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
394
395 return ieee80211_handle_protect_preamb(sdata,
396 use_protection, use_short_preamble);
397}
398
399static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
400 struct ieee80211_sta_bss *bss)
401{
402 u32 changed = 0;
403
404 if (bss->has_erp_value)
405 changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
406 else {
407 u16 capab = bss->capability;
408 changed |= ieee80211_handle_protect_preamb(sdata, false,
409 (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
410 }
411
412 return changed;
413}
414
391int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, 415int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
392 struct ieee80211_ht_info *ht_info) 416 struct ieee80211_ht_info *ht_info)
393{ 417{
@@ -511,9 +535,7 @@ static void ieee80211_set_associated(struct net_device *dev,
511 sdata->bss_conf.beacon_int = bss->beacon_int; 535 sdata->bss_conf.beacon_int = bss->beacon_int;
512 sdata->bss_conf.timestamp = bss->timestamp; 536 sdata->bss_conf.timestamp = bss->timestamp;
513 537
514 if (bss->has_erp_value) 538 changed |= ieee80211_handle_bss_capability(sdata, bss);
515 changed |= ieee80211_handle_erp_ie(
516 sdata, bss->erp_value);
517 539
518 ieee80211_rx_bss_put(dev, bss); 540 ieee80211_rx_bss_put(dev, bss);
519 } 541 }
@@ -2566,22 +2588,29 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2566#endif 2588#endif
2567 } 2589 }
2568 2590
2569 bss->band = rx_status->band;
2570
2571 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
2572 bss->probe_resp && beacon) {
2573 /* STA mode:
2574 * Do not allow beacon to override data from Probe Response. */
2575 ieee80211_rx_bss_put(dev, bss);
2576 return;
2577 }
2578
2579 /* save the ERP value so that it is available at association time */ 2591 /* save the ERP value so that it is available at association time */
2580 if (elems.erp_info && elems.erp_info_len >= 1) { 2592 if (elems.erp_info && elems.erp_info_len >= 1) {
2581 bss->erp_value = elems.erp_info[0]; 2593 bss->erp_value = elems.erp_info[0];
2582 bss->has_erp_value = 1; 2594 bss->has_erp_value = 1;
2583 } 2595 }
2584 2596
2597 if (elems.ht_cap_elem &&
2598 (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
2599 memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
2600 kfree(bss->ht_ie);
2601 bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
2602 if (bss->ht_ie) {
2603 memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
2604 elems.ht_cap_elem_len + 2);
2605 bss->ht_ie_len = elems.ht_cap_elem_len + 2;
2606 } else
2607 bss->ht_ie_len = 0;
2608 } else if (!elems.ht_cap_elem && bss->ht_ie) {
2609 kfree(bss->ht_ie);
2610 bss->ht_ie = NULL;
2611 bss->ht_ie_len = 0;
2612 }
2613
2585 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); 2614 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
2586 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); 2615 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
2587 2616
@@ -2603,6 +2632,26 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2603 bss->supp_rates_len += clen; 2632 bss->supp_rates_len += clen;
2604 } 2633 }
2605 2634
2635 bss->band = rx_status->band;
2636
2637 bss->timestamp = beacon_timestamp;
2638 bss->last_update = jiffies;
2639 bss->rssi = rx_status->ssi;
2640 bss->signal = rx_status->signal;
2641 bss->noise = rx_status->noise;
2642 if (!beacon && !bss->probe_resp)
2643 bss->probe_resp = true;
2644
2645 /*
2646 * In STA mode, the remaining parameters should not be overridden
2647 * by beacons because they're not necessarily accurate there.
2648 */
2649 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
2650 bss->probe_resp && beacon) {
2651 ieee80211_rx_bss_put(dev, bss);
2652 return;
2653 }
2654
2606 if (elems.wpa && 2655 if (elems.wpa &&
2607 (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len || 2656 (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
2608 memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { 2657 memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
@@ -2635,6 +2684,20 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2635 bss->rsn_ie_len = 0; 2684 bss->rsn_ie_len = 0;
2636 } 2685 }
2637 2686
2687 /*
2688 * Cf.
2689 * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC
2690 *
2691 * quoting:
2692 *
2693 * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia
2694 * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi
2695 * Alliance (September 1, 2004) is incorporated by reference herein.
2696 * The inclusion of the WMM Parameters in probe responses and
2697 * association responses is mandatory for WMM enabled networks. The
2698 * inclusion of the WMM Parameters in beacons, however, is optional.
2699 */
2700
2638 if (elems.wmm_param && 2701 if (elems.wmm_param &&
2639 (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len || 2702 (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
2640 memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { 2703 memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
@@ -2651,30 +2714,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2651 bss->wmm_ie = NULL; 2714 bss->wmm_ie = NULL;
2652 bss->wmm_ie_len = 0; 2715 bss->wmm_ie_len = 0;
2653 } 2716 }
2654 if (elems.ht_cap_elem &&
2655 (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
2656 memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
2657 kfree(bss->ht_ie);
2658 bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
2659 if (bss->ht_ie) {
2660 memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
2661 elems.ht_cap_elem_len + 2);
2662 bss->ht_ie_len = elems.ht_cap_elem_len + 2;
2663 } else
2664 bss->ht_ie_len = 0;
2665 } else if (!elems.ht_cap_elem && bss->ht_ie) {
2666 kfree(bss->ht_ie);
2667 bss->ht_ie = NULL;
2668 bss->ht_ie_len = 0;
2669 }
2670
2671 bss->timestamp = beacon_timestamp;
2672 bss->last_update = jiffies;
2673 bss->rssi = rx_status->ssi;
2674 bss->signal = rx_status->signal;
2675 bss->noise = rx_status->noise;
2676 if (!beacon)
2677 bss->probe_resp++;
2678 2717
2679 /* check if we need to merge IBSS */ 2718 /* check if we need to merge IBSS */
2680 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && 2719 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
@@ -2775,8 +2814,24 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
2775 2814
2776 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); 2815 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
2777 2816
2817 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
2818 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
2819 elems.wmm_param_len);
2820 }
2821
2822 /* Do not send changes to driver if we are scanning. This removes
2823 * requirement that driver's bss_info_changed function needs to be
2824 * atomic. */
2825 if (local->sta_sw_scanning || local->sta_hw_scanning)
2826 return;
2827
2778 if (elems.erp_info && elems.erp_info_len >= 1) 2828 if (elems.erp_info && elems.erp_info_len >= 1)
2779 changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); 2829 changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
2830 else {
2831 u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
2832 changed |= ieee80211_handle_protect_preamb(sdata, false,
2833 (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
2834 }
2780 2835
2781 if (elems.ht_cap_elem && elems.ht_info_elem && 2836 if (elems.ht_cap_elem && elems.ht_info_elem &&
2782 elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { 2837 elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
@@ -2789,11 +2844,6 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
2789 &bss_info); 2844 &bss_info);
2790 } 2845 }
2791 2846
2792 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
2793 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
2794 elems.wmm_param_len);
2795 }
2796
2797 ieee80211_bss_info_change_notify(sdata, changed); 2847 ieee80211_bss_info_change_notify(sdata, changed);
2798} 2848}
2799 2849
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 69aed16faff3..76e1de1dc735 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -236,6 +236,9 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev,
236 case IW_MODE_ADHOC: 236 case IW_MODE_ADHOC:
237 type = IEEE80211_IF_TYPE_IBSS; 237 type = IEEE80211_IF_TYPE_IBSS;
238 break; 238 break;
239 case IW_MODE_REPEAT:
240 type = IEEE80211_IF_TYPE_WDS;
241 break;
239 case IW_MODE_MONITOR: 242 case IW_MODE_MONITOR:
240 type = IEEE80211_IF_TYPE_MNTR; 243 type = IEEE80211_IF_TYPE_MNTR;
241 break; 244 break;
@@ -980,6 +983,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev
980 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 983 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
981 struct sta_info *sta = NULL; 984 struct sta_info *sta = NULL;
982 985
986 rcu_read_lock();
987
983 if (sdata->vif.type == IEEE80211_IF_TYPE_STA || 988 if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
984 sdata->vif.type == IEEE80211_IF_TYPE_IBSS) 989 sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
985 sta = sta_info_get(local, sdata->u.sta.bssid); 990 sta = sta_info_get(local, sdata->u.sta.bssid);
@@ -996,6 +1001,9 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev
996 wstats->qual.noise = sta->last_noise; 1001 wstats->qual.noise = sta->last_noise;
997 wstats->qual.updated = local->wstats_flags; 1002 wstats->qual.updated = local->wstats_flags;
998 } 1003 }
1004
1005 rcu_read_unlock();
1006
999 return wstats; 1007 return wstats;
1000} 1008}
1001 1009
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
index c38744c96ed1..89cbab24d08f 100644
--- a/net/tipc/ref.c
+++ b/net/tipc/ref.c
@@ -2,7 +2,7 @@
2 * net/tipc/ref.c: TIPC object registry code 2 * net/tipc/ref.c: TIPC object registry code
3 * 3 *
4 * Copyright (c) 1991-2006, Ericsson AB 4 * Copyright (c) 1991-2006, Ericsson AB
5 * Copyright (c) 2004-2005, Wind River Systems 5 * Copyright (c) 2004-2007, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -36,32 +36,60 @@
36 36
37#include "core.h" 37#include "core.h"
38#include "ref.h" 38#include "ref.h"
39#include "port.h" 39
40#include "subscr.h" 40/**
41#include "name_distr.h" 41 * struct reference - TIPC object reference entry
42#include "name_table.h" 42 * @object: pointer to object associated with reference entry
43#include "config.h" 43 * @lock: spinlock controlling access to object
44#include "discover.h" 44 * @ref: reference value for object (combines instance & array index info)
45#include "bearer.h" 45 */
46#include "node.h" 46
47#include "bcast.h" 47struct reference {
48 void *object;
49 spinlock_t lock;
50 u32 ref;
51};
52
53/**
54 * struct tipc_ref_table - table of TIPC object reference entries
55 * @entries: pointer to array of reference entries
56 * @capacity: array index of first unusable entry
57 * @init_point: array index of first uninitialized entry
58 * @first_free: array index of first unused object reference entry
59 * @last_free: array index of last unused object reference entry
60 * @index_mask: bitmask for array index portion of reference values
61 * @start_mask: initial value for instance value portion of reference values
62 */
63
64struct ref_table {
65 struct reference *entries;
66 u32 capacity;
67 u32 init_point;
68 u32 first_free;
69 u32 last_free;
70 u32 index_mask;
71 u32 start_mask;
72};
48 73
49/* 74/*
50 * Object reference table consists of 2**N entries. 75 * Object reference table consists of 2**N entries.
51 * 76 *
52 * A used entry has object ptr != 0, reference == XXXX|own index 77 * State Object ptr Reference
53 * (XXXX changes each time entry is acquired) 78 * ----- ---------- ---------
54 * A free entry has object ptr == 0, reference == YYYY|next free index 79 * In use non-NULL XXXX|own index
55 * (YYYY is one more than last used XXXX) 80 * (XXXX changes each time entry is acquired)
81 * Free NULL YYYY|next free index
82 * (YYYY is one more than last used XXXX)
83 * Uninitialized NULL 0
56 * 84 *
57 * Free list is initially chained from entry (2**N)-1 to entry 1. 85 * Entry 0 is not used; this allows index 0 to denote the end of the free list.
58 * Entry 0 is not used to allow index 0 to indicate the end of the free list.
59 * 86 *
60 * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0 87 * Note that a reference value of 0 does not necessarily indicate that an
61 * because entry 0's reference field has the form XXXX|1--1. 88 * entry is uninitialized, since the last entry in the free list could also
89 * have a reference value of 0 (although this is unlikely).
62 */ 90 */
63 91
64struct ref_table tipc_ref_table = { NULL }; 92static struct ref_table tipc_ref_table = { NULL };
65 93
66static DEFINE_RWLOCK(ref_table_lock); 94static DEFINE_RWLOCK(ref_table_lock);
67 95
@@ -72,29 +100,29 @@ static DEFINE_RWLOCK(ref_table_lock);
72int tipc_ref_table_init(u32 requested_size, u32 start) 100int tipc_ref_table_init(u32 requested_size, u32 start)
73{ 101{
74 struct reference *table; 102 struct reference *table;
75 u32 sz = 1 << 4; 103 u32 actual_size;
76 u32 index_mask;
77 int i;
78 104
79 while (sz < requested_size) { 105 /* account for unused entry, then round up size to a power of 2 */
80 sz <<= 1; 106
81 } 107 requested_size++;
82 table = vmalloc(sz * sizeof(*table)); 108 for (actual_size = 16; actual_size < requested_size; actual_size <<= 1)
109 /* do nothing */ ;
110
111 /* allocate table & mark all entries as uninitialized */
112
113 table = __vmalloc(actual_size * sizeof(struct reference),
114 GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
83 if (table == NULL) 115 if (table == NULL)
84 return -ENOMEM; 116 return -ENOMEM;
85 117
86 write_lock_bh(&ref_table_lock);
87 index_mask = sz - 1;
88 for (i = sz - 1; i >= 0; i--) {
89 table[i].object = NULL;
90 spin_lock_init(&table[i].lock);
91 table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
92 }
93 tipc_ref_table.entries = table; 118 tipc_ref_table.entries = table;
94 tipc_ref_table.index_mask = index_mask; 119 tipc_ref_table.capacity = requested_size;
95 tipc_ref_table.first_free = sz - 1; 120 tipc_ref_table.init_point = 1;
96 tipc_ref_table.last_free = 1; 121 tipc_ref_table.first_free = 0;
97 write_unlock_bh(&ref_table_lock); 122 tipc_ref_table.last_free = 0;
123 tipc_ref_table.index_mask = actual_size - 1;
124 tipc_ref_table.start_mask = start & ~tipc_ref_table.index_mask;
125
98 return TIPC_OK; 126 return TIPC_OK;
99} 127}
100 128
@@ -125,7 +153,7 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
125 u32 index; 153 u32 index;
126 u32 index_mask; 154 u32 index_mask;
127 u32 next_plus_upper; 155 u32 next_plus_upper;
128 u32 reference = 0; 156 u32 ref;
129 157
130 if (!object) { 158 if (!object) {
131 err("Attempt to acquire reference to non-existent object\n"); 159 err("Attempt to acquire reference to non-existent object\n");
@@ -136,6 +164,8 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
136 return 0; 164 return 0;
137 } 165 }
138 166
167 /* take a free entry, if available; otherwise initialize a new entry */
168
139 write_lock_bh(&ref_table_lock); 169 write_lock_bh(&ref_table_lock);
140 if (tipc_ref_table.first_free) { 170 if (tipc_ref_table.first_free) {
141 index = tipc_ref_table.first_free; 171 index = tipc_ref_table.first_free;
@@ -143,17 +173,29 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
143 index_mask = tipc_ref_table.index_mask; 173 index_mask = tipc_ref_table.index_mask;
144 /* take lock in case a previous user of entry still holds it */ 174 /* take lock in case a previous user of entry still holds it */
145 spin_lock_bh(&entry->lock); 175 spin_lock_bh(&entry->lock);
146 next_plus_upper = entry->data.next_plus_upper; 176 next_plus_upper = entry->ref;
147 tipc_ref_table.first_free = next_plus_upper & index_mask; 177 tipc_ref_table.first_free = next_plus_upper & index_mask;
148 reference = (next_plus_upper & ~index_mask) + index; 178 ref = (next_plus_upper & ~index_mask) + index;
149 entry->data.reference = reference; 179 entry->ref = ref;
150 entry->object = object; 180 entry->object = object;
151 if (lock != NULL)
152 *lock = &entry->lock;
153 spin_unlock_bh(&entry->lock); 181 spin_unlock_bh(&entry->lock);
182 *lock = &entry->lock;
183 }
184 else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {
185 index = tipc_ref_table.init_point++;
186 entry = &(tipc_ref_table.entries[index]);
187 spin_lock_init(&entry->lock);
188 ref = tipc_ref_table.start_mask + index;
189 entry->ref = ref;
190 entry->object = object;
191 *lock = &entry->lock;
192 }
193 else {
194 ref = 0;
154 } 195 }
155 write_unlock_bh(&ref_table_lock); 196 write_unlock_bh(&ref_table_lock);
156 return reference; 197
198 return ref;
157} 199}
158 200
159/** 201/**
@@ -169,42 +211,99 @@ void tipc_ref_discard(u32 ref)
169 u32 index; 211 u32 index;
170 u32 index_mask; 212 u32 index_mask;
171 213
172 if (!ref) {
173 err("Attempt to discard reference 0\n");
174 return;
175 }
176 if (!tipc_ref_table.entries) { 214 if (!tipc_ref_table.entries) {
177 err("Reference table not found during discard attempt\n"); 215 err("Reference table not found during discard attempt\n");
178 return; 216 return;
179 } 217 }
180 218
181 write_lock_bh(&ref_table_lock);
182 index_mask = tipc_ref_table.index_mask; 219 index_mask = tipc_ref_table.index_mask;
183 index = ref & index_mask; 220 index = ref & index_mask;
184 entry = &(tipc_ref_table.entries[index]); 221 entry = &(tipc_ref_table.entries[index]);
185 222
223 write_lock_bh(&ref_table_lock);
224
186 if (!entry->object) { 225 if (!entry->object) {
187 err("Attempt to discard reference to non-existent object\n"); 226 err("Attempt to discard reference to non-existent object\n");
188 goto exit; 227 goto exit;
189 } 228 }
190 if (entry->data.reference != ref) { 229 if (entry->ref != ref) {
191 err("Attempt to discard non-existent reference\n"); 230 err("Attempt to discard non-existent reference\n");
192 goto exit; 231 goto exit;
193 } 232 }
194 233
195 /* mark entry as unused */ 234 /*
235 * mark entry as unused; increment instance part of entry's reference
236 * to invalidate any subsequent references
237 */
238
196 entry->object = NULL; 239 entry->object = NULL;
240 entry->ref = (ref & ~index_mask) + (index_mask + 1);
241
242 /* append entry to free entry list */
243
197 if (tipc_ref_table.first_free == 0) 244 if (tipc_ref_table.first_free == 0)
198 tipc_ref_table.first_free = index; 245 tipc_ref_table.first_free = index;
199 else 246 else
200 /* next_plus_upper is always XXXX|0--0 for last free entry */ 247 tipc_ref_table.entries[tipc_ref_table.last_free].ref |= index;
201 tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper
202 |= index;
203 tipc_ref_table.last_free = index; 248 tipc_ref_table.last_free = index;
204 249
205 /* increment upper bits of entry to invalidate subsequent references */
206 entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
207exit: 250exit:
208 write_unlock_bh(&ref_table_lock); 251 write_unlock_bh(&ref_table_lock);
209} 252}
210 253
254/**
255 * tipc_ref_lock - lock referenced object and return pointer to it
256 */
257
258void *tipc_ref_lock(u32 ref)
259{
260 if (likely(tipc_ref_table.entries)) {
261 struct reference *entry;
262
263 entry = &tipc_ref_table.entries[ref &
264 tipc_ref_table.index_mask];
265 if (likely(entry->ref != 0)) {
266 spin_lock_bh(&entry->lock);
267 if (likely((entry->ref == ref) && (entry->object)))
268 return entry->object;
269 spin_unlock_bh(&entry->lock);
270 }
271 }
272 return NULL;
273}
274
275/**
276 * tipc_ref_unlock - unlock referenced object
277 */
278
279void tipc_ref_unlock(u32 ref)
280{
281 if (likely(tipc_ref_table.entries)) {
282 struct reference *entry;
283
284 entry = &tipc_ref_table.entries[ref &
285 tipc_ref_table.index_mask];
286 if (likely((entry->ref == ref) && (entry->object)))
287 spin_unlock_bh(&entry->lock);
288 else
289 err("Attempt to unlock non-existent reference\n");
290 }
291}
292
293/**
294 * tipc_ref_deref - return pointer referenced object (without locking it)
295 */
296
297void *tipc_ref_deref(u32 ref)
298{
299 if (likely(tipc_ref_table.entries)) {
300 struct reference *entry;
301
302 entry = &tipc_ref_table.entries[ref &
303 tipc_ref_table.index_mask];
304 if (likely(entry->ref == ref))
305 return entry->object;
306 }
307 return NULL;
308}
309
diff --git a/net/tipc/ref.h b/net/tipc/ref.h
index 38f3a7f4a78d..7e3798ea93b9 100644
--- a/net/tipc/ref.h
+++ b/net/tipc/ref.h
@@ -2,7 +2,7 @@
2 * net/tipc/ref.h: Include file for TIPC object registry code 2 * net/tipc/ref.h: Include file for TIPC object registry code
3 * 3 *
4 * Copyright (c) 1991-2006, Ericsson AB 4 * Copyright (c) 1991-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems 5 * Copyright (c) 2005-2006, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -37,95 +37,14 @@
37#ifndef _TIPC_REF_H 37#ifndef _TIPC_REF_H
38#define _TIPC_REF_H 38#define _TIPC_REF_H
39 39
40/**
41 * struct reference - TIPC object reference entry
42 * @object: pointer to object associated with reference entry
43 * @lock: spinlock controlling access to object
44 * @data: reference value associated with object (or link to next unused entry)
45 */
46
47struct reference {
48 void *object;
49 spinlock_t lock;
50 union {
51 u32 next_plus_upper;
52 u32 reference;
53 } data;
54};
55
56/**
57 * struct tipc_ref_table - table of TIPC object reference entries
58 * @entries: pointer to array of reference entries
59 * @index_mask: bitmask for array index portion of reference values
60 * @first_free: array index of first unused object reference entry
61 * @last_free: array index of last unused object reference entry
62 */
63
64struct ref_table {
65 struct reference *entries;
66 u32 index_mask;
67 u32 first_free;
68 u32 last_free;
69};
70
71extern struct ref_table tipc_ref_table;
72
73int tipc_ref_table_init(u32 requested_size, u32 start); 40int tipc_ref_table_init(u32 requested_size, u32 start);
74void tipc_ref_table_stop(void); 41void tipc_ref_table_stop(void);
75 42
76u32 tipc_ref_acquire(void *object, spinlock_t **lock); 43u32 tipc_ref_acquire(void *object, spinlock_t **lock);
77void tipc_ref_discard(u32 ref); 44void tipc_ref_discard(u32 ref);
78 45
79 46void *tipc_ref_lock(u32 ref);
80/** 47void tipc_ref_unlock(u32 ref);
81 * tipc_ref_lock - lock referenced object and return pointer to it 48void *tipc_ref_deref(u32 ref);
82 */
83
84static inline void *tipc_ref_lock(u32 ref)
85{
86 if (likely(tipc_ref_table.entries)) {
87 struct reference *r =
88 &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
89
90 spin_lock_bh(&r->lock);
91 if (likely(r->data.reference == ref))
92 return r->object;
93 spin_unlock_bh(&r->lock);
94 }
95 return NULL;
96}
97
98/**
99 * tipc_ref_unlock - unlock referenced object
100 */
101
102static inline void tipc_ref_unlock(u32 ref)
103{
104 if (likely(tipc_ref_table.entries)) {
105 struct reference *r =
106 &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
107
108 if (likely(r->data.reference == ref))
109 spin_unlock_bh(&r->lock);
110 else
111 err("tipc_ref_unlock() invoked using obsolete reference\n");
112 }
113}
114
115/**
116 * tipc_ref_deref - return pointer referenced object (without locking it)
117 */
118
119static inline void *tipc_ref_deref(u32 ref)
120{
121 if (likely(tipc_ref_table.entries)) {
122 struct reference *r =
123 &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
124
125 if (likely(r->data.reference == ref))
126 return r->object;
127 }
128 return NULL;
129}
130 49
131#endif 50#endif