diff options
author | Ilan Peer <ilan.peer@intel.com> | 2014-02-25 09:26:00 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-04-09 04:55:35 -0400 |
commit | 52616f2b446eaad8eb2cd78bbd052f0066069757 (patch) | |
tree | e410fdc5238dc4d1aec48035ecef7ff51f579730 /net/wireless/reg.c | |
parent | 174e0cd28af0fe3c6c634c3e4d9e042c683bd7f7 (diff) |
cfg80211: Add an option to hint indoor operation
Add the option to hint the wireless core that it is operating in an indoor
environment.
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r-- | net/wireless/reg.c | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 58f48b8f42ae..55d68c31ad72 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -65,11 +65,26 @@ | |||
65 | #define REG_DBG_PRINT(args...) | 65 | #define REG_DBG_PRINT(args...) |
66 | #endif | 66 | #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 | */ | ||
68 | enum reg_request_treatment { | 82 | enum 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 | ||
75 | static struct regulatory_request core_request_world = { | 90 | static struct regulatory_request core_request_world = { |
@@ -106,6 +121,14 @@ const struct ieee80211_regdomain __rcu *cfg80211_regdomain; | |||
106 | */ | 121 | */ |
107 | static int reg_num_devs_support_basehint; | 122 | static 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 | */ | ||
130 | static bool reg_is_indoor; | ||
131 | |||
109 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) | 132 | static 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) | |||
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 | ||
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 | |||
1131 | bool reg_last_request_cell_base(void) | 1161 | bool 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) | |||
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) | |||
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, | |||
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, | |||
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, | |||
1969 | return 0; | 2007 | return 0; |
1970 | } | 2008 | } |
1971 | 2009 | ||
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 | |||
1972 | /* Driver hints */ | 2026 | /* Driver hints */ |
1973 | int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | 2027 | int regulatory_hint(struct wiphy *wiphy, const char *alpha2) |
1974 | { | 2028 | { |
@@ -2136,6 +2190,8 @@ static void restore_regulatory_settings(bool reset_user) | |||
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 | ||