History

cfg80211: Add an option to hint indoor operation

Add the option to hint the wireless core that it is operating in an indoor environment.

Ilan Peer committed 12 years ago

Commit 52616f21 parent 174e0cd4 files · +68 −12Browse files

Unified · Split

4 files
  1. include/uapi/linux/nl80211.h +3 −0
  2. net/wireless/nl80211.c +7 −11
  3. net/wireless/reg.c +57 −1
  4. net/wireless/reg.h +1 −0
include/uapi/linux/nl80211.h+3−0
@@ -2602,10 +2602,13 @@ enum nl80211_dfs_regions { · 2601 unmodified lines
26022602 * present has been registered with the wireless core that
26032603 * has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a
26042604 * supported feature.
2605+ * @NL80211_USER_REG_HINT_INDOOR: a user sent an hint indicating that the
2606+ * platform is operating in an indoor environment.
26052607 */
26062608 enum nl80211_user_reg_hint_type {
26072609 NL80211_USER_REG_HINT_USER = 0,
26082610 NL80211_USER_REG_HINT_CELL_BASE = 1,
2611+ NL80211_USER_REG_HINT_INDOOR = 2,
26092612 };
26102613
26112614 /**
net/wireless/nl80211.c+7−11
@@ -4677,7 +4677,6 @@ static int parse_reg_rule(struct nlattr *tb[], · 4676 unmodified lines
46774677
46784678 static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
46794679 {
4680− int r;
46814680 char *data = NULL;
46824681 enum nl80211_user_reg_hint_type user_reg_hint_type;
46834682
@@ -4690,11 +4689,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) · 6 unmodified lines
46904689 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
46914690 return -EINPROGRESS;
46924691
4693− if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
4694− return -EINVAL;
4695−
4696− data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
4697−
46984692 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
46994693 user_reg_hint_type =
47004694 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
@@ -4704,14 +4698,16 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) · 3 unmodified lines
47044698 switch (user_reg_hint_type) {
47054699 case NL80211_USER_REG_HINT_USER:
47064700 case NL80211_USER_REG_HINT_CELL_BASE:
4707− break;
4701+ if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
4702+ return -EINVAL;
4703+
4704+ data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
4705+ return regulatory_hint_user(data, user_reg_hint_type);
4706+ case NL80211_USER_REG_HINT_INDOOR:
4707+ return regulatory_hint_indoor_user();
47084708 default:
47094709 return -EINVAL;
47104710 }
4711−
4712− r = regulatory_hint_user(data, user_reg_hint_type);
4713−
4714− return r;
47154711 }
47164712
47174713 static int nl80211_get_mesh_config(struct sk_buff *skb,
net/wireless/reg.c+57−1
@@ -65,11 +65,26 @@ · 64 unmodified lines
6565 #define REG_DBG_PRINT(args...)
6666 #endif
6767
68+/**
69+ * enum reg_request_treatment - regulatory request treatment
70+ *
71+ * @REG_REQ_OK: continue processing the regulatory request
72+ * @REG_REQ_IGNORE: ignore the regulatory request
73+ * @REG_REQ_INTERSECT: the regulatory domain resulting from this request should
74+ * be intersected with the current one.
75+ * @REG_REQ_ALREADY_SET: the regulatory request will not change the current
76+ * regulatory settings, and no further processing is required.
77+ * @REG_REQ_USER_HINT_HANDLED: a non alpha2 user hint was handled and no
78+ * further processing is required, i.e., not need to update last_request
79+ * etc. This should be used for user hints that do not provide an alpha2
80+ * but some other type of regulatory hint, i.e., indoor operation.
81+ */
6882 enum reg_request_treatment {
6983 REG_REQ_OK,
7084 REG_REQ_IGNORE,
7185 REG_REQ_INTERSECT,
7286 REG_REQ_ALREADY_SET,
87+ REG_REQ_USER_HINT_HANDLED,
7388 };
7489
7590 static struct regulatory_request core_request_world = {
@@ -106,6 +121,14 @@ const struct ieee80211_regdomain __rcu *cfg80211_regdomain; · 30 unmodified lines
106121 */
107122 static int reg_num_devs_support_basehint;
108123
124+/*
125+ * State variable indicating if the platform on which the devices
126+ * are attached is operating in an indoor environment. The state variable
127+ * is relevant for all registered devices.
128+ * (protected by RTNL)
129+ */
130+static bool reg_is_indoor;
131+
109132 static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
110133 {
111134 return rtnl_dereference(cfg80211_regdomain);
@@ -1128,6 +1151,13 @@ static bool reg_request_cell_base(struct regulatory_request *request) · 1016 unmodified lines
11281151 return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE;
11291152 }
11301153
1154+static bool reg_request_indoor(struct regulatory_request *request)
1155+{
1156+ if (request->initiator != NL80211_REGDOM_SET_BY_USER)
1157+ return false;
1158+ return request->user_reg_hint_type == NL80211_USER_REG_HINT_INDOOR;
1159+}
1160+
11311161 bool reg_last_request_cell_base(void)
11321162 {
11331163 return reg_request_cell_base(get_last_request());
@@ -1570,6 +1600,11 @@ __reg_process_hint_user(struct regulatory_request *user_request) · 436 unmodified lines
15701600 {
15711601 struct regulatory_request *lr = get_last_request();
15721602
1603+ if (reg_request_indoor(user_request)) {
1604+ reg_is_indoor = true;
1605+ return REG_REQ_USER_HINT_HANDLED;
1606+ }
1607+
15731608 if (reg_request_cell_base(user_request))
15741609 return reg_ignore_cell_hint(user_request);
15751610
@@ -1617,7 +1652,8 @@ reg_process_hint_user(struct regulatory_request *user_request) · 41 unmodified lines
16171652
16181653 treatment = __reg_process_hint_user(user_request);
16191654 if (treatment == REG_REQ_IGNORE ||
1620− treatment == REG_REQ_ALREADY_SET) {
1655+ treatment == REG_REQ_ALREADY_SET ||
1656+ treatment == REG_REQ_USER_HINT_HANDLED) {
16211657 kfree(user_request);
16221658 return treatment;
16231659 }
@@ -1678,6 +1714,7 @@ reg_process_hint_driver(struct wiphy *wiphy, · 54 unmodified lines
16781714 case REG_REQ_OK:
16791715 break;
16801716 case REG_REQ_IGNORE:
1717+ case REG_REQ_USER_HINT_HANDLED:
16811718 kfree(driver_request);
16821719 return treatment;
16831720 case REG_REQ_INTERSECT:
@@ -1777,6 +1814,7 @@ reg_process_hint_country_ie(struct wiphy *wiphy, · 93 unmodified lines
17771814 case REG_REQ_OK:
17781815 break;
17791816 case REG_REQ_IGNORE:
1817+ case REG_REQ_USER_HINT_HANDLED:
17801818 /* fall through */
17811819 case REG_REQ_ALREADY_SET:
17821820 kfree(country_ie_request);
@@ -1969,6 +2007,22 @@ int regulatory_hint_user(const char *alpha2, · 186 unmodified lines
19692007 return 0;
19702008 }
19712009
2010+int regulatory_hint_indoor_user(void)
2011+{
2012+ struct regulatory_request *request;
2013+
2014+ request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
2015+ if (!request)
2016+ return -ENOMEM;
2017+
2018+ request->wiphy_idx = WIPHY_IDX_INVALID;
2019+ request->initiator = NL80211_REGDOM_SET_BY_USER;
2020+ request->user_reg_hint_type = NL80211_USER_REG_HINT_INDOOR;
2021+ queue_regulatory_request(request);
2022+
2023+ return 0;
2024+}
2025+
19722026 /* Driver hints */
19732027 int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
19742028 {
@@ -2136,6 +2190,8 @@ static void restore_regulatory_settings(bool reset_user) · 161 unmodified lines
21362190
21372191 ASSERT_RTNL();
21382192
2193+ reg_is_indoor = false;
2194+
21392195 reset_regdomains(true, &world_regdom);
21402196 restore_alpha2(alpha2, reset_user);
21412197
net/wireless/reg.h+1−0
@@ -25,6 +25,7 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy); · 24 unmodified lines
2525
2626 int regulatory_hint_user(const char *alpha2,
2727 enum nl80211_user_reg_hint_type user_reg_hint_type);
28+int regulatory_hint_indoor_user(void);
2829
2930 void wiphy_regulatory_register(struct wiphy *wiphy);
3031 void wiphy_regulatory_deregister(struct wiphy *wiphy);