diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-04-12 16:18:44 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-12 16:18:44 -0400 |
commit | 252f4bf400df1712408fe83ba199a66a1b57ab1d (patch) | |
tree | e07fa00abdd55b31e22567786c78635f32c6a66c /net/wireless | |
parent | 6ba1037c3d871ab70e342631516dbf841c35b086 (diff) | |
parent | b37e3b6d64358604960b35e8ecbb7aed22e0926e (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/ath/ar9170/main.c
drivers/net/wireless/ath/ar9170/phy.c
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/mlme.c | 9 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 55 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 3 | ||||
-rw-r--r-- | net/wireless/reg.c | 71 |
4 files changed, 135 insertions, 3 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index aa5df8865ff7..16881fea4ce6 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -770,6 +770,15 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
770 | } | 770 | } |
771 | EXPORT_SYMBOL(cfg80211_new_sta); | 771 | EXPORT_SYMBOL(cfg80211_new_sta); |
772 | 772 | ||
773 | void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp) | ||
774 | { | ||
775 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
776 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
777 | |||
778 | nl80211_send_sta_del_event(rdev, dev, mac_addr, gfp); | ||
779 | } | ||
780 | EXPORT_SYMBOL(cfg80211_del_sta); | ||
781 | |||
773 | struct cfg80211_mgmt_registration { | 782 | struct cfg80211_mgmt_registration { |
774 | struct list_head list; | 783 | struct list_head list; |
775 | 784 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4ebce4284e9d..297d7ce4117b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2002,7 +2002,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
2002 | const u8 *mac_addr, struct station_info *sinfo) | 2002 | const u8 *mac_addr, struct station_info *sinfo) |
2003 | { | 2003 | { |
2004 | void *hdr; | 2004 | void *hdr; |
2005 | struct nlattr *sinfoattr; | 2005 | struct nlattr *sinfoattr, *bss_param; |
2006 | 2006 | ||
2007 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); | 2007 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); |
2008 | if (!hdr) | 2008 | if (!hdr) |
@@ -2062,6 +2062,25 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
2062 | if (sinfo->filled & STATION_INFO_TX_FAILED) | 2062 | if (sinfo->filled & STATION_INFO_TX_FAILED) |
2063 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, | 2063 | NLA_PUT_U32(msg, NL80211_STA_INFO_TX_FAILED, |
2064 | sinfo->tx_failed); | 2064 | sinfo->tx_failed); |
2065 | if (sinfo->filled & STATION_INFO_BSS_PARAM) { | ||
2066 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); | ||
2067 | if (!bss_param) | ||
2068 | goto nla_put_failure; | ||
2069 | |||
2070 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_CTS_PROT) | ||
2071 | NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_CTS_PROT); | ||
2072 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_PREAMBLE) | ||
2073 | NLA_PUT_FLAG(msg, NL80211_STA_BSS_PARAM_SHORT_PREAMBLE); | ||
2074 | if (sinfo->bss_param.flags & BSS_PARAM_FLAGS_SHORT_SLOT_TIME) | ||
2075 | NLA_PUT_FLAG(msg, | ||
2076 | NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME); | ||
2077 | NLA_PUT_U8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, | ||
2078 | sinfo->bss_param.dtim_period); | ||
2079 | NLA_PUT_U16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, | ||
2080 | sinfo->bss_param.beacon_interval); | ||
2081 | |||
2082 | nla_nest_end(msg, bss_param); | ||
2083 | } | ||
2065 | nla_nest_end(msg, sinfoattr); | 2084 | nla_nest_end(msg, sinfoattr); |
2066 | 2085 | ||
2067 | return genlmsg_end(msg, hdr); | 2086 | return genlmsg_end(msg, hdr); |
@@ -5966,6 +5985,40 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
5966 | nl80211_mlme_mcgrp.id, gfp); | 5985 | nl80211_mlme_mcgrp.id, gfp); |
5967 | } | 5986 | } |
5968 | 5987 | ||
5988 | void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | ||
5989 | struct net_device *dev, const u8 *mac_addr, | ||
5990 | gfp_t gfp) | ||
5991 | { | ||
5992 | struct sk_buff *msg; | ||
5993 | void *hdr; | ||
5994 | |||
5995 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
5996 | if (!msg) | ||
5997 | return; | ||
5998 | |||
5999 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION); | ||
6000 | if (!hdr) { | ||
6001 | nlmsg_free(msg); | ||
6002 | return; | ||
6003 | } | ||
6004 | |||
6005 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | ||
6006 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); | ||
6007 | |||
6008 | if (genlmsg_end(msg, hdr) < 0) { | ||
6009 | nlmsg_free(msg); | ||
6010 | return; | ||
6011 | } | ||
6012 | |||
6013 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
6014 | nl80211_mlme_mcgrp.id, gfp); | ||
6015 | return; | ||
6016 | |||
6017 | nla_put_failure: | ||
6018 | genlmsg_cancel(msg, hdr); | ||
6019 | nlmsg_free(msg); | ||
6020 | } | ||
6021 | |||
5969 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 6022 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
5970 | struct net_device *netdev, u32 nlpid, | 6023 | struct net_device *netdev, u32 nlpid, |
5971 | int freq, const u8 *buf, size_t len, gfp_t gfp) | 6024 | int freq, const u8 *buf, size_t len, gfp_t gfp) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index e3f7fa886966..dcac5cd6f017 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -79,6 +79,9 @@ void nl80211_send_remain_on_channel_cancel( | |||
79 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | 79 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, |
80 | struct net_device *dev, const u8 *mac_addr, | 80 | struct net_device *dev, const u8 *mac_addr, |
81 | struct station_info *sinfo, gfp_t gfp); | 81 | struct station_info *sinfo, gfp_t gfp); |
82 | void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, | ||
83 | struct net_device *dev, const u8 *mac_addr, | ||
84 | gfp_t gfp); | ||
82 | 85 | ||
83 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | 86 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
84 | struct net_device *netdev, u32 nlpid, int freq, | 87 | struct net_device *netdev, u32 nlpid, int freq, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index ab801a1097b2..58d69959ab28 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -106,6 +106,9 @@ struct reg_beacon { | |||
106 | static void reg_todo(struct work_struct *work); | 106 | static void reg_todo(struct work_struct *work); |
107 | static DECLARE_WORK(reg_work, reg_todo); | 107 | static DECLARE_WORK(reg_work, reg_todo); |
108 | 108 | ||
109 | static void reg_timeout_work(struct work_struct *work); | ||
110 | static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work); | ||
111 | |||
109 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | 112 | /* We keep a static world regulatory domain in case of the absence of CRDA */ |
110 | static const struct ieee80211_regdomain world_regdom = { | 113 | static const struct ieee80211_regdomain world_regdom = { |
111 | .n_reg_rules = 5, | 114 | .n_reg_rules = 5, |
@@ -1330,6 +1333,9 @@ static void reg_set_request_processed(void) | |||
1330 | need_more_processing = true; | 1333 | need_more_processing = true; |
1331 | spin_unlock(®_requests_lock); | 1334 | spin_unlock(®_requests_lock); |
1332 | 1335 | ||
1336 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) | ||
1337 | cancel_delayed_work_sync(®_timeout); | ||
1338 | |||
1333 | if (need_more_processing) | 1339 | if (need_more_processing) |
1334 | schedule_work(®_work); | 1340 | schedule_work(®_work); |
1335 | } | 1341 | } |
@@ -1440,8 +1446,17 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1440 | r = __regulatory_hint(wiphy, reg_request); | 1446 | r = __regulatory_hint(wiphy, reg_request); |
1441 | /* This is required so that the orig_* parameters are saved */ | 1447 | /* This is required so that the orig_* parameters are saved */ |
1442 | if (r == -EALREADY && wiphy && | 1448 | if (r == -EALREADY && wiphy && |
1443 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) | 1449 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { |
1444 | wiphy_update_regulatory(wiphy, initiator); | 1450 | wiphy_update_regulatory(wiphy, initiator); |
1451 | return; | ||
1452 | } | ||
1453 | |||
1454 | /* | ||
1455 | * We only time out user hints, given that they should be the only | ||
1456 | * source of bogus requests. | ||
1457 | */ | ||
1458 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER) | ||
1459 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | ||
1445 | } | 1460 | } |
1446 | 1461 | ||
1447 | /* | 1462 | /* |
@@ -1744,6 +1759,8 @@ static void restore_regulatory_settings(bool reset_user) | |||
1744 | { | 1759 | { |
1745 | char alpha2[2]; | 1760 | char alpha2[2]; |
1746 | struct reg_beacon *reg_beacon, *btmp; | 1761 | struct reg_beacon *reg_beacon, *btmp; |
1762 | struct regulatory_request *reg_request, *tmp; | ||
1763 | LIST_HEAD(tmp_reg_req_list); | ||
1747 | 1764 | ||
1748 | mutex_lock(&cfg80211_mutex); | 1765 | mutex_lock(&cfg80211_mutex); |
1749 | mutex_lock(®_mutex); | 1766 | mutex_lock(®_mutex); |
@@ -1751,6 +1768,25 @@ static void restore_regulatory_settings(bool reset_user) | |||
1751 | reset_regdomains(); | 1768 | reset_regdomains(); |
1752 | restore_alpha2(alpha2, reset_user); | 1769 | restore_alpha2(alpha2, reset_user); |
1753 | 1770 | ||
1771 | /* | ||
1772 | * If there's any pending requests we simply | ||
1773 | * stash them to a temporary pending queue and | ||
1774 | * add then after we've restored regulatory | ||
1775 | * settings. | ||
1776 | */ | ||
1777 | spin_lock(®_requests_lock); | ||
1778 | if (!list_empty(®_requests_list)) { | ||
1779 | list_for_each_entry_safe(reg_request, tmp, | ||
1780 | ®_requests_list, list) { | ||
1781 | if (reg_request->initiator != | ||
1782 | NL80211_REGDOM_SET_BY_USER) | ||
1783 | continue; | ||
1784 | list_del(®_request->list); | ||
1785 | list_add_tail(®_request->list, &tmp_reg_req_list); | ||
1786 | } | ||
1787 | } | ||
1788 | spin_unlock(®_requests_lock); | ||
1789 | |||
1754 | /* Clear beacon hints */ | 1790 | /* Clear beacon hints */ |
1755 | spin_lock_bh(®_pending_beacons_lock); | 1791 | spin_lock_bh(®_pending_beacons_lock); |
1756 | if (!list_empty(®_pending_beacons)) { | 1792 | if (!list_empty(®_pending_beacons)) { |
@@ -1785,8 +1821,31 @@ static void restore_regulatory_settings(bool reset_user) | |||
1785 | */ | 1821 | */ |
1786 | if (is_an_alpha2(alpha2)) | 1822 | if (is_an_alpha2(alpha2)) |
1787 | regulatory_hint_user(user_alpha2); | 1823 | regulatory_hint_user(user_alpha2); |
1788 | } | ||
1789 | 1824 | ||
1825 | if (list_empty(&tmp_reg_req_list)) | ||
1826 | return; | ||
1827 | |||
1828 | mutex_lock(&cfg80211_mutex); | ||
1829 | mutex_lock(®_mutex); | ||
1830 | |||
1831 | spin_lock(®_requests_lock); | ||
1832 | list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) { | ||
1833 | REG_DBG_PRINT("Adding request for country %c%c back " | ||
1834 | "into the queue\n", | ||
1835 | reg_request->alpha2[0], | ||
1836 | reg_request->alpha2[1]); | ||
1837 | list_del(®_request->list); | ||
1838 | list_add_tail(®_request->list, ®_requests_list); | ||
1839 | } | ||
1840 | spin_unlock(®_requests_lock); | ||
1841 | |||
1842 | mutex_unlock(®_mutex); | ||
1843 | mutex_unlock(&cfg80211_mutex); | ||
1844 | |||
1845 | REG_DBG_PRINT("Kicking the queue\n"); | ||
1846 | |||
1847 | schedule_work(®_work); | ||
1848 | } | ||
1790 | 1849 | ||
1791 | void regulatory_hint_disconnect(void) | 1850 | void regulatory_hint_disconnect(void) |
1792 | { | 1851 | { |
@@ -2125,6 +2184,13 @@ out: | |||
2125 | mutex_unlock(®_mutex); | 2184 | mutex_unlock(®_mutex); |
2126 | } | 2185 | } |
2127 | 2186 | ||
2187 | static void reg_timeout_work(struct work_struct *work) | ||
2188 | { | ||
2189 | REG_DBG_PRINT("Timeout while waiting for CRDA to reply, " | ||
2190 | "restoring regulatory settings"); | ||
2191 | restore_regulatory_settings(true); | ||
2192 | } | ||
2193 | |||
2128 | int __init regulatory_init(void) | 2194 | int __init regulatory_init(void) |
2129 | { | 2195 | { |
2130 | int err = 0; | 2196 | int err = 0; |
@@ -2178,6 +2244,7 @@ void /* __init_or_exit */ regulatory_exit(void) | |||
2178 | struct reg_beacon *reg_beacon, *btmp; | 2244 | struct reg_beacon *reg_beacon, *btmp; |
2179 | 2245 | ||
2180 | cancel_work_sync(®_work); | 2246 | cancel_work_sync(®_work); |
2247 | cancel_delayed_work_sync(®_timeout); | ||
2181 | 2248 | ||
2182 | mutex_lock(&cfg80211_mutex); | 2249 | mutex_lock(&cfg80211_mutex); |
2183 | mutex_lock(®_mutex); | 2250 | mutex_lock(®_mutex); |