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
2602 * present has been registered with the wireless core that2602 * present has been registered with the wireless core that
2603 * has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a2603 * has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a
2604 * supported feature.2604 * supported feature.
2605 * @NL80211_USER_REG_HINT_INDOOR: a user sent an hint indicating that the
2606 * platform is operating in an indoor environment.
2605 */2607 */
2606enum nl80211_user_reg_hint_type {2608enum nl80211_user_reg_hint_type {
2607 NL80211_USER_REG_HINT_USER = 0,2609 NL80211_USER_REG_HINT_USER = 0,
2608 NL80211_USER_REG_HINT_CELL_BASE = 1,2610 NL80211_USER_REG_HINT_CELL_BASE = 1,
2611 NL80211_USER_REG_HINT_INDOOR = 2,
2609};2612};
2610 2613
2611/**2614/**
net/wireless/nl80211.c+7−11
@@ -4677,7 +4677,6 @@ static int parse_reg_rule(struct nlattr *tb[], · 4676 unmodified lines
4677 4677
4678static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)4678static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
4679{4679{
4680 int r;
4681 char *data = NULL;4680 char *data = NULL;
4682 enum nl80211_user_reg_hint_type user_reg_hint_type;4681 enum nl80211_user_reg_hint_type user_reg_hint_type;
4683 4682
@@ -4690,11 +4689,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) · 6 unmodified lines
4690 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))4689 if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
4691 return -EINPROGRESS;4690 return -EINPROGRESS;
4692 4691
4693 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
4694 return -EINVAL;
4695
4696 data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
4697
4698 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])4692 if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
4699 user_reg_hint_type =4693 user_reg_hint_type =
4700 nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);4694 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
4704 switch (user_reg_hint_type) {4698 switch (user_reg_hint_type) {
4705 case NL80211_USER_REG_HINT_USER:4699 case NL80211_USER_REG_HINT_USER:
4706 case NL80211_USER_REG_HINT_CELL_BASE:4700 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();
4708 default:4708 default:
4709 return -EINVAL;4709 return -EINVAL;
4710 }4710 }
4711
4712 r = regulatory_hint_user(data, user_reg_hint_type);
4713
4714 return r;
4715}4711}
4716 4712
4717static int nl80211_get_mesh_config(struct sk_buff *skb,4713static int nl80211_get_mesh_config(struct sk_buff *skb,
net/wireless/reg.c+57−1
@@ -65,11 +65,26 @@ · 64 unmodified lines
65#define REG_DBG_PRINT(args...)65#define REG_DBG_PRINT(args...)
66#endif66#endif
67 67
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 */
68enum reg_request_treatment {82enum reg_request_treatment {
69 REG_REQ_OK,83 REG_REQ_OK,
70 REG_REQ_IGNORE,84 REG_REQ_IGNORE,
71 REG_REQ_INTERSECT,85 REG_REQ_INTERSECT,
72 REG_REQ_ALREADY_SET,86 REG_REQ_ALREADY_SET,
87 REG_REQ_USER_HINT_HANDLED,
73};88};
74 89
75static struct regulatory_request core_request_world = {90static struct regulatory_request core_request_world = {
@@ -106,6 +121,14 @@ const struct ieee80211_regdomain __rcu *cfg80211_regdomain; · 30 unmodified lines
106 */121 */
107static int reg_num_devs_support_basehint;122static int reg_num_devs_support_basehint;
108 123
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 */
130static bool reg_is_indoor;
131
109static const struct ieee80211_regdomain *get_cfg80211_regdom(void)132static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
110{133{
111 return rtnl_dereference(cfg80211_regdomain);134 return rtnl_dereference(cfg80211_regdomain);
@@ -1128,6 +1151,13 @@ static bool reg_request_cell_base(struct regulatory_request *request) · 1016 unmodified lines
1128 return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE;1151 return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE;
1129}1152}
1130 1153
1154static 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
1131bool reg_last_request_cell_base(void)1161bool reg_last_request_cell_base(void)
1132{1162{
1133 return reg_request_cell_base(get_last_request());1163 return reg_request_cell_base(get_last_request());
@@ -1570,6 +1600,11 @@ __reg_process_hint_user(struct regulatory_request *user_request) · 436 unmodified lines
1570{1600{
1571 struct regulatory_request *lr = get_last_request();1601 struct regulatory_request *lr = get_last_request();
1572 1602
1603 if (reg_request_indoor(user_request)) {
1604 reg_is_indoor = true;
1605 return REG_REQ_USER_HINT_HANDLED;
1606 }
1607
1573 if (reg_request_cell_base(user_request))1608 if (reg_request_cell_base(user_request))
1574 return reg_ignore_cell_hint(user_request);1609 return reg_ignore_cell_hint(user_request);
1575 1610
@@ -1617,7 +1652,8 @@ reg_process_hint_user(struct regulatory_request *user_request) · 41 unmodified lines
1617 1652
1618 treatment = __reg_process_hint_user(user_request);1653 treatment = __reg_process_hint_user(user_request);
1619 if (treatment == REG_REQ_IGNORE ||1654 if (treatment == REG_REQ_IGNORE ||
1620 treatment == REG_REQ_ALREADY_SET) {1655 treatment == REG_REQ_ALREADY_SET ||
1656 treatment == REG_REQ_USER_HINT_HANDLED) {
1621 kfree(user_request);1657 kfree(user_request);
1622 return treatment;1658 return treatment;
1623 }1659 }
@@ -1678,6 +1714,7 @@ reg_process_hint_driver(struct wiphy *wiphy, · 54 unmodified lines
1678 case REG_REQ_OK:1714 case REG_REQ_OK:
1679 break;1715 break;
1680 case REG_REQ_IGNORE:1716 case REG_REQ_IGNORE:
1717 case REG_REQ_USER_HINT_HANDLED:
1681 kfree(driver_request);1718 kfree(driver_request);
1682 return treatment;1719 return treatment;
1683 case REG_REQ_INTERSECT:1720 case REG_REQ_INTERSECT:
@@ -1777,6 +1814,7 @@ reg_process_hint_country_ie(struct wiphy *wiphy, · 93 unmodified lines
1777 case REG_REQ_OK:1814 case REG_REQ_OK:
1778 break;1815 break;
1779 case REG_REQ_IGNORE:1816 case REG_REQ_IGNORE:
1817 case REG_REQ_USER_HINT_HANDLED:
1780 /* fall through */1818 /* fall through */
1781 case REG_REQ_ALREADY_SET:1819 case REG_REQ_ALREADY_SET:
1782 kfree(country_ie_request);1820 kfree(country_ie_request);
@@ -1969,6 +2007,22 @@ int regulatory_hint_user(const char *alpha2, · 186 unmodified lines
1969 return 0;2007 return 0;
1970}2008}
1971 2009
2010int 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
1972/* Driver hints */2026/* Driver hints */
1973int regulatory_hint(struct wiphy *wiphy, const char *alpha2)2027int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
1974{2028{
@@ -2136,6 +2190,8 @@ static void restore_regulatory_settings(bool reset_user) · 161 unmodified lines
2136 2190
2137 ASSERT_RTNL();2191 ASSERT_RTNL();
2138 2192
2193 reg_is_indoor = false;
2194
2139 reset_regdomains(true, &world_regdom);2195 reset_regdomains(true, &world_regdom);
2140 restore_alpha2(alpha2, reset_user);2196 restore_alpha2(alpha2, reset_user);
2141 2197
net/wireless/reg.h+1−0
@@ -25,6 +25,7 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy); · 24 unmodified lines
25 25
26int regulatory_hint_user(const char *alpha2,26int regulatory_hint_user(const char *alpha2,
27 enum nl80211_user_reg_hint_type user_reg_hint_type);27 enum nl80211_user_reg_hint_type user_reg_hint_type);
28int regulatory_hint_indoor_user(void);
28 29
29void wiphy_regulatory_register(struct wiphy *wiphy);30void wiphy_regulatory_register(struct wiphy *wiphy);
30void wiphy_regulatory_deregister(struct wiphy *wiphy);31void wiphy_regulatory_deregister(struct wiphy *wiphy);