Commit 17b94247 authored by Ayala Beker's avatar Ayala Beker Committed by Johannes Berg

cfg80211: allow userspace to specify client P2P PS support

Legacy clients don't support P2P power save mechanisms, and thus
if a P2P GO has a legacy client connected to it, it has to make
some changes in the PS behavior.

To handle this, add an attribute to specify whether a station supports
P2P PS or not. If the attribute was not specified cfg80211 will assume
that station supports it for P2P GO interface, and does NOT support it
for AP interface, matching the current assumptions in the code.
Signed-off-by: default avatarAyala Beker <ayala.beker@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent b100e5d6
...@@ -816,6 +816,7 @@ enum station_parameters_apply_mask { ...@@ -816,6 +816,7 @@ enum station_parameters_apply_mask {
* @supported_oper_classes_len: number of supported operating classes * @supported_oper_classes_len: number of supported operating classes
* @opmode_notif: operating mode field from Operating Mode Notification * @opmode_notif: operating mode field from Operating Mode Notification
* @opmode_notif_used: information if operating mode field is used * @opmode_notif_used: information if operating mode field is used
* @support_p2p_ps: information if station supports P2P PS mechanism
*/ */
struct station_parameters { struct station_parameters {
const u8 *supported_rates; const u8 *supported_rates;
...@@ -841,6 +842,7 @@ struct station_parameters { ...@@ -841,6 +842,7 @@ struct station_parameters {
u8 supported_oper_classes_len; u8 supported_oper_classes_len;
u8 opmode_notif; u8 opmode_notif;
bool opmode_notif_used; bool opmode_notif_used;
int support_p2p_ps;
}; };
/** /**
......
...@@ -1804,6 +1804,9 @@ enum nl80211_commands { ...@@ -1804,6 +1804,9 @@ enum nl80211_commands {
* it contains the behaviour-specific attribute containing the parameters for * it contains the behaviour-specific attribute containing the parameters for
* BSS selection to be done by driver and/or firmware. * BSS selection to be done by driver and/or firmware.
* *
* @NL80211_ATTR_STA_SUPPORT_P2P_PS: whether P2P PS mechanism supported
* or not. u8, one of the values of &enum nl80211_sta_p2p_ps_status
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
...@@ -2182,6 +2185,8 @@ enum nl80211_attrs { ...@@ -2182,6 +2185,8 @@ enum nl80211_attrs {
NL80211_ATTR_BSS_SELECT, NL80211_ATTR_BSS_SELECT,
NL80211_ATTR_STA_SUPPORT_P2P_PS,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, __NL80211_ATTR_AFTER_LAST,
...@@ -2325,6 +2330,20 @@ enum nl80211_sta_flags { ...@@ -2325,6 +2330,20 @@ enum nl80211_sta_flags {
NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
}; };
/**
* enum nl80211_sta_p2p_ps_status - station support of P2P PS
*
* @NL80211_P2P_PS_UNSUPPORTED: station doesn't support P2P PS mechanism
* @@NL80211_P2P_PS_SUPPORTED: station supports P2P PS mechanism
* @NUM_NL80211_P2P_PS_STATUS: number of values
*/
enum nl80211_sta_p2p_ps_status {
NL80211_P2P_PS_UNSUPPORTED = 0,
NL80211_P2P_PS_SUPPORTED,
NUM_NL80211_P2P_PS_STATUS,
};
#define NL80211_STA_FLAG_MAX_OLD_API NL80211_STA_FLAG_TDLS_PEER #define NL80211_STA_FLAG_MAX_OLD_API NL80211_STA_FLAG_TDLS_PEER
/** /**
......
...@@ -403,6 +403,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { ...@@ -403,6 +403,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG }, [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
[NL80211_ATTR_PBSS] = { .type = NLA_FLAG }, [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
[NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED }, [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
[NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 },
}; };
/* policy for the key attributes */ /* policy for the key attributes */
...@@ -4006,6 +4007,10 @@ int cfg80211_check_station_change(struct wiphy *wiphy, ...@@ -4006,6 +4007,10 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
statype != CFG80211_STA_AP_CLIENT_UNASSOC) statype != CFG80211_STA_AP_CLIENT_UNASSOC)
return -EINVAL; return -EINVAL;
if (params->support_p2p_ps != -1 &&
statype != CFG80211_STA_AP_CLIENT_UNASSOC)
return -EINVAL;
if (params->aid && if (params->aid &&
!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
statype != CFG80211_STA_AP_CLIENT_UNASSOC) statype != CFG80211_STA_AP_CLIENT_UNASSOC)
...@@ -4299,6 +4304,18 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) ...@@ -4299,6 +4304,18 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
else else
params.listen_interval = -1; params.listen_interval = -1;
if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
u8 tmp;
tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
if (tmp >= NUM_NL80211_P2P_PS_STATUS)
return -EINVAL;
params.support_p2p_ps = tmp;
} else {
params.support_p2p_ps = -1;
}
if (!info->attrs[NL80211_ATTR_MAC]) if (!info->attrs[NL80211_ATTR_MAC])
return -EINVAL; return -EINVAL;
...@@ -4422,6 +4439,23 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) ...@@ -4422,6 +4439,23 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
params.listen_interval = params.listen_interval =
nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
u8 tmp;
tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
if (tmp >= NUM_NL80211_P2P_PS_STATUS)
return -EINVAL;
params.support_p2p_ps = tmp;
} else {
/*
* if not specified, assume it's supported for P2P GO interface,
* and is NOT supported for AP interface
*/
params.support_p2p_ps =
dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
}
if (info->attrs[NL80211_ATTR_PEER_AID]) if (info->attrs[NL80211_ATTR_PEER_AID])
params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment