aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-09-08 19:10:53 -0400
committerDavid S. Miller <davem@davemloft.net>2008-09-08 19:10:53 -0400
commit9bff9dbd00e5907f5c36e72bae8aee8a46440e11 (patch)
tree4a5666939b61a13e7cde01b29baf4cb609fb8c90 /net
parente2a6b85247aacc52d6ba0d9b37a99b8d1a3e0d83 (diff)
parentd10c4ec8b4bc02f3874c7ef3c3539e4e7e123969 (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.c7
-rw-r--r--net/mac80211/mlme.c90
-rw-r--r--net/mac80211/rx.c4
-rw-r--r--net/mac80211/sta_info.h1
-rw-r--r--net/wireless/core.c9
-rw-r--r--net/wireless/nl80211.c22
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
2560static 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
2561static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 2588static 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
3036static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, 3075static 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 }