aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-04-12 16:18:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-12 16:18:44 -0400
commit252f4bf400df1712408fe83ba199a66a1b57ab1d (patch)
treee07fa00abdd55b31e22567786c78635f32c6a66c /net/wireless
parent6ba1037c3d871ab70e342631516dbf841c35b086 (diff)
parentb37e3b6d64358604960b35e8ecbb7aed22e0926e (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.c9
-rw-r--r--net/wireless/nl80211.c55
-rw-r--r--net/wireless/nl80211.h3
-rw-r--r--net/wireless/reg.c71
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}
771EXPORT_SYMBOL(cfg80211_new_sta); 771EXPORT_SYMBOL(cfg80211_new_sta);
772 772
773void 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}
780EXPORT_SYMBOL(cfg80211_del_sta);
781
773struct cfg80211_mgmt_registration { 782struct 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
5988void 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
5969int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, 6022int 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(
79void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, 79void 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);
82void 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
83int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, 86int 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 {
106static void reg_todo(struct work_struct *work); 106static void reg_todo(struct work_struct *work);
107static DECLARE_WORK(reg_work, reg_todo); 107static DECLARE_WORK(reg_work, reg_todo);
108 108
109static void reg_timeout_work(struct work_struct *work);
110static 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 */
110static const struct ieee80211_regdomain world_regdom = { 113static 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(&reg_requests_lock); 1334 spin_unlock(&reg_requests_lock);
1332 1335
1336 if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
1337 cancel_delayed_work_sync(&reg_timeout);
1338
1333 if (need_more_processing) 1339 if (need_more_processing)
1334 schedule_work(&reg_work); 1340 schedule_work(&reg_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(&reg_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(&reg_mutex); 1766 mutex_lock(&reg_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(&reg_requests_lock);
1778 if (!list_empty(&reg_requests_list)) {
1779 list_for_each_entry_safe(reg_request, tmp,
1780 &reg_requests_list, list) {
1781 if (reg_request->initiator !=
1782 NL80211_REGDOM_SET_BY_USER)
1783 continue;
1784 list_del(&reg_request->list);
1785 list_add_tail(&reg_request->list, &tmp_reg_req_list);
1786 }
1787 }
1788 spin_unlock(&reg_requests_lock);
1789
1754 /* Clear beacon hints */ 1790 /* Clear beacon hints */
1755 spin_lock_bh(&reg_pending_beacons_lock); 1791 spin_lock_bh(&reg_pending_beacons_lock);
1756 if (!list_empty(&reg_pending_beacons)) { 1792 if (!list_empty(&reg_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(&reg_mutex);
1830
1831 spin_lock(&reg_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(&reg_request->list);
1838 list_add_tail(&reg_request->list, &reg_requests_list);
1839 }
1840 spin_unlock(&reg_requests_lock);
1841
1842 mutex_unlock(&reg_mutex);
1843 mutex_unlock(&cfg80211_mutex);
1844
1845 REG_DBG_PRINT("Kicking the queue\n");
1846
1847 schedule_work(&reg_work);
1848}
1790 1849
1791void regulatory_hint_disconnect(void) 1850void regulatory_hint_disconnect(void)
1792{ 1851{
@@ -2125,6 +2184,13 @@ out:
2125 mutex_unlock(&reg_mutex); 2184 mutex_unlock(&reg_mutex);
2126} 2185}
2127 2186
2187static 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
2128int __init regulatory_init(void) 2194int __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(&reg_work); 2246 cancel_work_sync(&reg_work);
2247 cancel_delayed_work_sync(&reg_timeout);
2181 2248
2182 mutex_lock(&cfg80211_mutex); 2249 mutex_lock(&cfg80211_mutex);
2183 mutex_lock(&reg_mutex); 2250 mutex_lock(&reg_mutex);