summaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-03-01 02:10:13 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-03-04 04:34:11 -0500
commit98fc43864af9e74116eec81c290db048cded15d8 (patch)
treeed8b1e929f1cf0d5eb3eb0e2a2e1150faed72424 /net/wireless
parent88724a81b4ac2a755bf9c532cdbee08a52803852 (diff)
nl80211: prohibit mixing 'any' and regular wowlan triggers
If the device supports waking up on 'any' signal - i.e. it continues operating as usual and wakes up the host on pretty much anything that happens, then it makes no sense to also configure the more restricted WoWLAN mode where the device operates more autonomously but also in a more restricted fashion. Currently only cw2100 supports both 'any' and other triggers, but it seems to be broken as it doesn't configure anything to the device, so we can't currently get into a situation where both even can correctly be configured. This is about to change (Intel devices are going to support both and have different behaviour depending on configuration) so make sure the conflicting modes cannot be configured. (It seems that cw2100 advertises 'any' and 'disconnect' as a means of saying that's what it will always do, but that isn't really the way this API was meant to be used nor does it actually mean anything as 'any' always implies 'disconnect' already, and the driver doesn't change device configuration in any way depending on the settings.) Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 01874628ae00..07cef3d7653e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -9105,6 +9105,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
9105 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan; 9105 const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan;
9106 int err, i; 9106 int err, i;
9107 bool prev_enabled = rdev->wiphy.wowlan_config; 9107 bool prev_enabled = rdev->wiphy.wowlan_config;
9108 bool regular = false;
9108 9109
9109 if (!wowlan) 9110 if (!wowlan)
9110 return -EOPNOTSUPP; 9111 return -EOPNOTSUPP;
@@ -9132,12 +9133,14 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
9132 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT)) 9133 if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT))
9133 return -EINVAL; 9134 return -EINVAL;
9134 new_triggers.disconnect = true; 9135 new_triggers.disconnect = true;
9136 regular = true;
9135 } 9137 }
9136 9138
9137 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) { 9139 if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) {
9138 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT)) 9140 if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT))
9139 return -EINVAL; 9141 return -EINVAL;
9140 new_triggers.magic_pkt = true; 9142 new_triggers.magic_pkt = true;
9143 regular = true;
9141 } 9144 }
9142 9145
9143 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED]) 9146 if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED])
@@ -9147,24 +9150,28 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
9147 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE)) 9150 if (!(wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE))
9148 return -EINVAL; 9151 return -EINVAL;
9149 new_triggers.gtk_rekey_failure = true; 9152 new_triggers.gtk_rekey_failure = true;
9153 regular = true;
9150 } 9154 }
9151 9155
9152 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) { 9156 if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST]) {
9153 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ)) 9157 if (!(wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ))
9154 return -EINVAL; 9158 return -EINVAL;
9155 new_triggers.eap_identity_req = true; 9159 new_triggers.eap_identity_req = true;
9160 regular = true;
9156 } 9161 }
9157 9162
9158 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) { 9163 if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE]) {
9159 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE)) 9164 if (!(wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE))
9160 return -EINVAL; 9165 return -EINVAL;
9161 new_triggers.four_way_handshake = true; 9166 new_triggers.four_way_handshake = true;
9167 regular = true;
9162 } 9168 }
9163 9169
9164 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) { 9170 if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE]) {
9165 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE)) 9171 if (!(wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE))
9166 return -EINVAL; 9172 return -EINVAL;
9167 new_triggers.rfkill_release = true; 9173 new_triggers.rfkill_release = true;
9174 regular = true;
9168 } 9175 }
9169 9176
9170 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { 9177 if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) {
@@ -9173,6 +9180,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
9173 int rem, pat_len, mask_len, pkt_offset; 9180 int rem, pat_len, mask_len, pkt_offset;
9174 struct nlattr *pat_tb[NUM_NL80211_PKTPAT]; 9181 struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
9175 9182
9183 regular = true;
9184
9176 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], 9185 nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
9177 rem) 9186 rem)
9178 n_patterns++; 9187 n_patterns++;
@@ -9234,6 +9243,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
9234 } 9243 }
9235 9244
9236 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) { 9245 if (tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION]) {
9246 regular = true;
9237 err = nl80211_parse_wowlan_tcp( 9247 err = nl80211_parse_wowlan_tcp(
9238 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION], 9248 rdev, tb[NL80211_WOWLAN_TRIG_TCP_CONNECTION],
9239 &new_triggers); 9249 &new_triggers);
@@ -9242,6 +9252,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
9242 } 9252 }
9243 9253
9244 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) { 9254 if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
9255 regular = true;
9245 err = nl80211_parse_wowlan_nd( 9256 err = nl80211_parse_wowlan_nd(
9246 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT], 9257 rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
9247 &new_triggers); 9258 &new_triggers);
@@ -9249,6 +9260,17 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
9249 goto error; 9260 goto error;
9250 } 9261 }
9251 9262
9263 /* The 'any' trigger means the device continues operating more or less
9264 * as in its normal operation mode and wakes up the host on most of the
9265 * normal interrupts (like packet RX, ...)
9266 * It therefore makes little sense to combine with the more constrained
9267 * wakeup trigger modes.
9268 */
9269 if (new_triggers.any && regular) {
9270 err = -EINVAL;
9271 goto error;
9272 }
9273
9252 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL); 9274 ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
9253 if (!ntrig) { 9275 if (!ntrig) {
9254 err = -ENOMEM; 9276 err = -ENOMEM;