diff options
author | David S. Miller <davem@davemloft.net> | 2008-09-08 19:10:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-08 19:10:53 -0400 |
commit | 9bff9dbd00e5907f5c36e72bae8aee8a46440e11 (patch) | |
tree | 4a5666939b61a13e7cde01b29baf4cb609fb8c90 /net | |
parent | e2a6b85247aacc52d6ba0d9b37a99b8d1a3e0d83 (diff) | |
parent | d10c4ec8b4bc02f3874c7ef3c3539e4e7e123969 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/main.c | 7 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 90 | ||||
-rw-r--r-- | net/mac80211/rx.c | 4 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 1 | ||||
-rw-r--r-- | net/wireless/core.c | 9 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 22 |
6 files changed, 100 insertions, 33 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 638b75f36e23..396cfb2d0f46 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1675,6 +1675,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1675 | } | 1675 | } |
1676 | } | 1676 | } |
1677 | 1677 | ||
1678 | /* if low-level driver supports AP, we also support VLAN */ | ||
1679 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) | ||
1680 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | ||
1681 | |||
1682 | /* mac80211 always supports monitor */ | ||
1683 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | ||
1684 | |||
1678 | result = wiphy_register(local->hw.wiphy); | 1685 | result = wiphy_register(local->hw.wiphy); |
1679 | if (result < 0) | 1686 | if (result < 0) |
1680 | return result; | 1687 | return result; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7d53382f1a5b..c396c3522f7b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2557,6 +2557,33 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
2557 | return supp_rates; | 2557 | return supp_rates; |
2558 | } | 2558 | } |
2559 | 2559 | ||
2560 | static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, | ||
2561 | enum ieee80211_band band) | ||
2562 | { | ||
2563 | struct ieee80211_supported_band *sband; | ||
2564 | struct ieee80211_rate *bitrates; | ||
2565 | u64 mandatory_rates; | ||
2566 | enum ieee80211_rate_flags mandatory_flag; | ||
2567 | int i; | ||
2568 | |||
2569 | sband = local->hw.wiphy->bands[band]; | ||
2570 | if (!sband) { | ||
2571 | WARN_ON(1); | ||
2572 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
2573 | } | ||
2574 | |||
2575 | if (band == IEEE80211_BAND_2GHZ) | ||
2576 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; | ||
2577 | else | ||
2578 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; | ||
2579 | |||
2580 | bitrates = sband->bitrates; | ||
2581 | mandatory_rates = 0; | ||
2582 | for (i = 0; i < sband->n_bitrates; i++) | ||
2583 | if (bitrates[i].flags & mandatory_flag) | ||
2584 | mandatory_rates |= BIT(i); | ||
2585 | return mandatory_rates; | ||
2586 | } | ||
2560 | 2587 | ||
2561 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 2588 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
2562 | struct ieee80211_mgmt *mgmt, | 2589 | struct ieee80211_mgmt *mgmt, |
@@ -2568,9 +2595,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2568 | int freq, clen; | 2595 | int freq, clen; |
2569 | struct ieee80211_sta_bss *bss; | 2596 | struct ieee80211_sta_bss *bss; |
2570 | struct sta_info *sta; | 2597 | struct sta_info *sta; |
2571 | u64 beacon_timestamp, rx_timestamp; | ||
2572 | struct ieee80211_channel *channel; | 2598 | struct ieee80211_channel *channel; |
2599 | u64 beacon_timestamp, rx_timestamp; | ||
2600 | u64 supp_rates = 0; | ||
2573 | bool beacon = ieee80211_is_beacon(mgmt->frame_control); | 2601 | bool beacon = ieee80211_is_beacon(mgmt->frame_control); |
2602 | enum ieee80211_band band = rx_status->band; | ||
2574 | DECLARE_MAC_BUF(mac); | 2603 | DECLARE_MAC_BUF(mac); |
2575 | DECLARE_MAC_BUF(mac2); | 2604 | DECLARE_MAC_BUF(mac2); |
2576 | 2605 | ||
@@ -2578,30 +2607,41 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2578 | 2607 | ||
2579 | if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && | 2608 | if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && |
2580 | elems->mesh_config && mesh_matches_local(elems, sdata)) { | 2609 | elems->mesh_config && mesh_matches_local(elems, sdata)) { |
2581 | u64 rates = ieee80211_sta_get_rates(local, elems, | 2610 | supp_rates = ieee80211_sta_get_rates(local, elems, band); |
2582 | rx_status->band); | ||
2583 | 2611 | ||
2584 | mesh_neighbour_update(mgmt->sa, rates, sdata, | 2612 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, |
2585 | mesh_peer_accepts_plinks(elems)); | 2613 | mesh_peer_accepts_plinks(elems)); |
2586 | } | 2614 | } |
2587 | 2615 | ||
2588 | rcu_read_lock(); | 2616 | rcu_read_lock(); |
2589 | 2617 | ||
2590 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && | 2618 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && |
2591 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && | 2619 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { |
2592 | (sta = sta_info_get(local, mgmt->sa))) { | 2620 | |
2593 | u64 prev_rates; | 2621 | supp_rates = ieee80211_sta_get_rates(local, elems, band); |
2594 | u64 supp_rates = ieee80211_sta_get_rates(local, elems, | 2622 | |
2595 | rx_status->band); | 2623 | sta = sta_info_get(local, mgmt->sa); |
2596 | 2624 | if (sta) { | |
2597 | prev_rates = sta->supp_rates[rx_status->band]; | 2625 | u64 prev_rates; |
2598 | sta->supp_rates[rx_status->band] &= supp_rates; | 2626 | |
2599 | if (sta->supp_rates[rx_status->band] == 0) { | 2627 | prev_rates = sta->supp_rates[band]; |
2600 | /* No matching rates - this should not really happen. | 2628 | /* make sure mandatory rates are always added */ |
2601 | * Make sure that at least one rate is marked | 2629 | sta->supp_rates[band] = supp_rates | |
2602 | * supported to avoid issues with TX rate ctrl. */ | 2630 | ieee80211_sta_get_mandatory_rates(local, band); |
2603 | sta->supp_rates[rx_status->band] = | 2631 | |
2604 | sdata->u.sta.supp_rates_bits[rx_status->band]; | 2632 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2633 | if (sta->supp_rates[band] != prev_rates) | ||
2634 | printk(KERN_DEBUG "%s: updated supp_rates set " | ||
2635 | "for %s based on beacon info (0x%llx | " | ||
2636 | "0x%llx -> 0x%llx)\n", | ||
2637 | sdata->dev->name, print_mac(mac, sta->addr), | ||
2638 | (unsigned long long) prev_rates, | ||
2639 | (unsigned long long) supp_rates, | ||
2640 | (unsigned long long) sta->supp_rates[band]); | ||
2641 | #endif | ||
2642 | } else { | ||
2643 | ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, | ||
2644 | mgmt->sa, supp_rates); | ||
2605 | } | 2645 | } |
2606 | } | 2646 | } |
2607 | 2647 | ||
@@ -2683,7 +2723,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2683 | bss->supp_rates_len += clen; | 2723 | bss->supp_rates_len += clen; |
2684 | } | 2724 | } |
2685 | 2725 | ||
2686 | bss->band = rx_status->band; | 2726 | bss->band = band; |
2687 | 2727 | ||
2688 | bss->timestamp = beacon_timestamp; | 2728 | bss->timestamp = beacon_timestamp; |
2689 | bss->last_update = jiffies; | 2729 | bss->last_update = jiffies; |
@@ -2738,7 +2778,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2738 | * e.g: at 1 MBit that means mactime is 192 usec earlier | 2778 | * e.g: at 1 MBit that means mactime is 192 usec earlier |
2739 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. | 2779 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. |
2740 | */ | 2780 | */ |
2741 | int rate = local->hw.wiphy->bands[rx_status->band]-> | 2781 | int rate = local->hw.wiphy->bands[band]-> |
2742 | bitrates[rx_status->rate_idx].bitrate; | 2782 | bitrates[rx_status->rate_idx].bitrate; |
2743 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | 2783 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); |
2744 | } else if (local && local->ops && local->ops->get_tsf) | 2784 | } else if (local && local->ops && local->ops->get_tsf) |
@@ -2766,7 +2806,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2766 | ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); | 2806 | ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); |
2767 | ieee80211_ibss_add_sta(sdata, NULL, | 2807 | ieee80211_ibss_add_sta(sdata, NULL, |
2768 | mgmt->bssid, mgmt->sa, | 2808 | mgmt->bssid, mgmt->sa, |
2769 | BIT(rx_status->rate_idx)); | 2809 | supp_rates); |
2770 | } | 2810 | } |
2771 | } | 2811 | } |
2772 | 2812 | ||
@@ -3032,7 +3072,6 @@ void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff * | |||
3032 | kfree_skb(skb); | 3072 | kfree_skb(skb); |
3033 | } | 3073 | } |
3034 | 3074 | ||
3035 | |||
3036 | static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 3075 | static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
3037 | struct sk_buff *skb) | 3076 | struct sk_buff *skb) |
3038 | { | 3077 | { |
@@ -4316,10 +4355,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
4316 | 4355 | ||
4317 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | 4356 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); |
4318 | 4357 | ||
4319 | if (supp_rates) | 4358 | /* make sure mandatory rates are always added */ |
4320 | sta->supp_rates[band] = supp_rates; | 4359 | sta->supp_rates[band] = supp_rates | |
4321 | else | 4360 | ieee80211_sta_get_mandatory_rates(local, band); |
4322 | sta->supp_rates[band] = sdata->u.sta.supp_rates_bits[band]; | ||
4323 | 4361 | ||
4324 | rate_control_rate_init(sta, local); | 4362 | rate_control_rate_init(sta, local); |
4325 | 4363 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fd83ef760a37..7e09b30dd393 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1743,10 +1743,6 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1743 | if (!bssid) | 1743 | if (!bssid) |
1744 | return 0; | 1744 | return 0; |
1745 | if (ieee80211_is_beacon(hdr->frame_control)) { | 1745 | if (ieee80211_is_beacon(hdr->frame_control)) { |
1746 | if (!rx->sta) | ||
1747 | rx->sta = ieee80211_ibss_add_sta(sdata, | ||
1748 | rx->skb, bssid, hdr->addr2, | ||
1749 | BIT(rx->status->rate_idx)); | ||
1750 | return 1; | 1746 | return 1; |
1751 | } | 1747 | } |
1752 | else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { | 1748 | else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 109db787ccb7..4a581a5b5766 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -204,6 +204,7 @@ struct sta_ampdu_mlme { | |||
204 | * @tx_fragments: number of transmitted MPDUs | 204 | * @tx_fragments: number of transmitted MPDUs |
205 | * @txrate_idx: TBD | 205 | * @txrate_idx: TBD |
206 | * @last_txrate_idx: TBD | 206 | * @last_txrate_idx: TBD |
207 | * @tid_seq: TBD | ||
207 | * @wme_tx_queue: TBD | 208 | * @wme_tx_queue: TBD |
208 | * @ampdu_mlme: TBD | 209 | * @ampdu_mlme: TBD |
209 | * @timer_to_tid: identity mapping to ID timers | 210 | * @timer_to_tid: identity mapping to ID timers |
diff --git a/net/wireless/core.c b/net/wireless/core.c index f1da0b93bc56..7e995ac06a0c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This is the linux wireless configuration interface. | 2 | * This is the linux wireless configuration interface. |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/if.h> | 7 | #include <linux/if.h> |
@@ -259,6 +259,13 @@ int wiphy_register(struct wiphy *wiphy) | |||
259 | struct ieee80211_supported_band *sband; | 259 | struct ieee80211_supported_band *sband; |
260 | bool have_band = false; | 260 | bool have_band = false; |
261 | int i; | 261 | int i; |
262 | u16 ifmodes = wiphy->interface_modes; | ||
263 | |||
264 | /* sanity check ifmodes */ | ||
265 | WARN_ON(!ifmodes); | ||
266 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; | ||
267 | if (WARN_ON(ifmodes != wiphy->interface_modes)) | ||
268 | wiphy->interface_modes = ifmodes; | ||
262 | 269 | ||
263 | /* sanity check supported bands/channels */ | 270 | /* sanity check supported bands/channels */ |
264 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 271 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4d6c02afd6f5..77880ba8b619 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -113,10 +113,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
113 | struct nlattr *nl_bands, *nl_band; | 113 | struct nlattr *nl_bands, *nl_band; |
114 | struct nlattr *nl_freqs, *nl_freq; | 114 | struct nlattr *nl_freqs, *nl_freq; |
115 | struct nlattr *nl_rates, *nl_rate; | 115 | struct nlattr *nl_rates, *nl_rate; |
116 | struct nlattr *nl_modes; | ||
116 | enum ieee80211_band band; | 117 | enum ieee80211_band band; |
117 | struct ieee80211_channel *chan; | 118 | struct ieee80211_channel *chan; |
118 | struct ieee80211_rate *rate; | 119 | struct ieee80211_rate *rate; |
119 | int i; | 120 | int i; |
121 | u16 ifmodes = dev->wiphy.interface_modes; | ||
120 | 122 | ||
121 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); | 123 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); |
122 | if (!hdr) | 124 | if (!hdr) |
@@ -125,6 +127,20 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
125 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); | 127 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); |
126 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); | 128 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); |
127 | 129 | ||
130 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); | ||
131 | if (!nl_modes) | ||
132 | goto nla_put_failure; | ||
133 | |||
134 | i = 0; | ||
135 | while (ifmodes) { | ||
136 | if (ifmodes & 1) | ||
137 | NLA_PUT_FLAG(msg, i); | ||
138 | ifmodes >>= 1; | ||
139 | i++; | ||
140 | } | ||
141 | |||
142 | nla_nest_end(msg, nl_modes); | ||
143 | |||
128 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | 144 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); |
129 | if (!nl_bands) | 145 | if (!nl_bands) |
130 | goto nla_put_failure; | 146 | goto nla_put_failure; |
@@ -415,7 +431,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
415 | ifindex = dev->ifindex; | 431 | ifindex = dev->ifindex; |
416 | dev_put(dev); | 432 | dev_put(dev); |
417 | 433 | ||
418 | if (!drv->ops->change_virtual_intf) { | 434 | if (!drv->ops->change_virtual_intf || |
435 | !(drv->wiphy.interface_modes & (1 << type))) { | ||
419 | err = -EOPNOTSUPP; | 436 | err = -EOPNOTSUPP; |
420 | goto unlock; | 437 | goto unlock; |
421 | } | 438 | } |
@@ -462,7 +479,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
462 | if (IS_ERR(drv)) | 479 | if (IS_ERR(drv)) |
463 | return PTR_ERR(drv); | 480 | return PTR_ERR(drv); |
464 | 481 | ||
465 | if (!drv->ops->add_virtual_intf) { | 482 | if (!drv->ops->add_virtual_intf || |
483 | !(drv->wiphy.interface_modes & (1 << type))) { | ||
466 | err = -EOPNOTSUPP; | 484 | err = -EOPNOTSUPP; |
467 | goto unlock; | 485 | goto unlock; |
468 | } | 486 | } |