diff options
| author | Ashok Raj Nagarajan <arnagara@codeaurora.org> | 2019-03-29 06:48:21 -0400 |
|---|---|---|
| committer | Johannes Berg <johannes.berg@intel.com> | 2019-04-26 07:02:11 -0400 |
| commit | e96d1cd2635c05efdd01b4eafcfc50c22c40751f (patch) | |
| tree | 713f5f5037e3ce6c1b114e2873e7e94376dd97a2 | |
| parent | dbd50a851c50bb95e457c99306eff298afd3d731 (diff) | |
cfg80211: Add support to set tx power for a station associated
This patch adds support to set transmit power setting type and transmit
power level attributes to NL80211_CMD_SET_STATION in order to facilitate
adjusting the transmit power level of a station associated to the AP.
The added attributes allow selection of automatic and limited transmit
power level, with the level defined in dBm format.
Co-developed-by: Balaji Pothunoori <bpothuno@codeaurora.org>
Signed-off-by: Ashok Raj Nagarajan <arnagara@codeaurora.org>
Signed-off-by: Balaji Pothunoori <bpothuno@codeaurora.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
| -rw-r--r-- | include/net/cfg80211.h | 22 | ||||
| -rw-r--r-- | include/uapi/linux/nl80211.h | 15 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 43 |
3 files changed, 80 insertions, 0 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2b039802ae2e..2ea04e94b522 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
| @@ -975,6 +975,27 @@ enum station_parameters_apply_mask { | |||
| 975 | STATION_PARAM_APPLY_UAPSD = BIT(0), | 975 | STATION_PARAM_APPLY_UAPSD = BIT(0), |
| 976 | STATION_PARAM_APPLY_CAPABILITY = BIT(1), | 976 | STATION_PARAM_APPLY_CAPABILITY = BIT(1), |
| 977 | STATION_PARAM_APPLY_PLINK_STATE = BIT(2), | 977 | STATION_PARAM_APPLY_PLINK_STATE = BIT(2), |
| 978 | STATION_PARAM_APPLY_STA_TXPOWER = BIT(3), | ||
| 979 | }; | ||
| 980 | |||
| 981 | /** | ||
| 982 | * struct sta_txpwr - station txpower configuration | ||
| 983 | * | ||
| 984 | * Used to configure txpower for station. | ||
| 985 | * | ||
| 986 | * @power: tx power (in dBm) to be used for sending data traffic. If tx power | ||
| 987 | * is not provided, the default per-interface tx power setting will be | ||
| 988 | * overriding. Driver should be picking up the lowest tx power, either tx | ||
| 989 | * power per-interface or per-station. | ||
| 990 | * @type: In particular if TPC %type is NL80211_TX_POWER_LIMITED then tx power | ||
| 991 | * will be less than or equal to specified from userspace, whereas if TPC | ||
| 992 | * %type is NL80211_TX_POWER_AUTOMATIC then it indicates default tx power. | ||
| 993 | * NL80211_TX_POWER_FIXED is not a valid configuration option for | ||
| 994 | * per peer TPC. | ||
| 995 | */ | ||
| 996 | struct sta_txpwr { | ||
| 997 | s16 power; | ||
| 998 | enum nl80211_tx_power_setting type; | ||
| 978 | }; | 999 | }; |
| 979 | 1000 | ||
| 980 | /** | 1001 | /** |
| @@ -1049,6 +1070,7 @@ struct station_parameters { | |||
| 1049 | const struct ieee80211_he_cap_elem *he_capa; | 1070 | const struct ieee80211_he_cap_elem *he_capa; |
| 1050 | u8 he_capa_len; | 1071 | u8 he_capa_len; |
| 1051 | u16 airtime_weight; | 1072 | u16 airtime_weight; |
| 1073 | struct sta_txpwr txpwr; | ||
| 1052 | }; | 1074 | }; |
| 1053 | 1075 | ||
| 1054 | /** | 1076 | /** |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index e75615bf4453..25f70dd2b583 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
| @@ -2315,6 +2315,15 @@ enum nl80211_commands { | |||
| 2315 | * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime | 2315 | * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime |
| 2316 | * scheduler. | 2316 | * scheduler. |
| 2317 | * | 2317 | * |
| 2318 | * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for | ||
| 2319 | * station associated with the AP. See &enum nl80211_tx_power_setting for | ||
| 2320 | * possible values. | ||
| 2321 | * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This | ||
| 2322 | * allows to set Tx power for a station. If this attribute is not included, | ||
| 2323 | * the default per-interface tx power setting will be overriding. Driver | ||
| 2324 | * should be picking up the lowest tx power, either tx power per-interface | ||
| 2325 | * or per-station. | ||
| 2326 | * | ||
| 2318 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available | 2327 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
| 2319 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 2328 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 2320 | * @__NL80211_ATTR_AFTER_LAST: internal use | 2329 | * @__NL80211_ATTR_AFTER_LAST: internal use |
| @@ -2765,6 +2774,8 @@ enum nl80211_attrs { | |||
| 2765 | NL80211_ATTR_PEER_MEASUREMENTS, | 2774 | NL80211_ATTR_PEER_MEASUREMENTS, |
| 2766 | 2775 | ||
| 2767 | NL80211_ATTR_AIRTIME_WEIGHT, | 2776 | NL80211_ATTR_AIRTIME_WEIGHT, |
| 2777 | NL80211_ATTR_STA_TX_POWER_SETTING, | ||
| 2778 | NL80211_ATTR_STA_TX_POWER, | ||
| 2768 | 2779 | ||
| 2769 | /* add attributes here, update the policy in nl80211.c */ | 2780 | /* add attributes here, update the policy in nl80211.c */ |
| 2770 | 2781 | ||
| @@ -5391,6 +5402,9 @@ enum nl80211_feature_flags { | |||
| 5391 | * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports | 5402 | * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports |
| 5392 | * filtering of sched scan results using band specific RSSI thresholds. | 5403 | * filtering of sched scan results using band specific RSSI thresholds. |
| 5393 | * | 5404 | * |
| 5405 | * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power | ||
| 5406 | * to a station. | ||
| 5407 | * | ||
| 5394 | * @NUM_NL80211_EXT_FEATURES: number of extended features. | 5408 | * @NUM_NL80211_EXT_FEATURES: number of extended features. |
| 5395 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. | 5409 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. |
| 5396 | */ | 5410 | */ |
| @@ -5434,6 +5448,7 @@ enum nl80211_ext_feature_index { | |||
| 5434 | NL80211_EXT_FEATURE_AP_PMKSA_CACHING, | 5448 | NL80211_EXT_FEATURE_AP_PMKSA_CACHING, |
| 5435 | NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, | 5449 | NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, |
| 5436 | NL80211_EXT_FEATURE_EXT_KEY_ID, | 5450 | NL80211_EXT_FEATURE_EXT_KEY_ID, |
| 5451 | NL80211_EXT_FEATURE_STA_TX_PWR, | ||
| 5437 | 5452 | ||
| 5438 | /* add new features before the definition below */ | 5453 | /* add new features before the definition below */ |
| 5439 | NUM_NL80211_EXT_FEATURES, | 5454 | NUM_NL80211_EXT_FEATURES, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 64f191244c67..0524a6fb84ad 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -331,6 +331,11 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { | |||
| 331 | .len = NL80211_MAX_SUPP_RATES }, | 331 | .len = NL80211_MAX_SUPP_RATES }, |
| 332 | [NL80211_ATTR_STA_PLINK_ACTION] = | 332 | [NL80211_ATTR_STA_PLINK_ACTION] = |
| 333 | NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1), | 333 | NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_ACTIONS - 1), |
| 334 | [NL80211_ATTR_STA_TX_POWER_SETTING] = | ||
| 335 | NLA_POLICY_RANGE(NLA_U8, | ||
| 336 | NL80211_TX_POWER_AUTOMATIC, | ||
| 337 | NL80211_TX_POWER_FIXED), | ||
| 338 | [NL80211_ATTR_STA_TX_POWER] = { .type = NLA_S16 }, | ||
| 334 | [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, | 339 | [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, |
| 335 | [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, | 340 | [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, |
| 336 | [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, | 341 | [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, |
| @@ -5420,6 +5425,36 @@ static int nl80211_set_station_tdls(struct genl_info *info, | |||
| 5420 | return nl80211_parse_sta_wme(info, params); | 5425 | return nl80211_parse_sta_wme(info, params); |
| 5421 | } | 5426 | } |
| 5422 | 5427 | ||
| 5428 | static int nl80211_parse_sta_txpower_setting(struct genl_info *info, | ||
| 5429 | struct station_parameters *params) | ||
| 5430 | { | ||
| 5431 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
| 5432 | int idx; | ||
| 5433 | |||
| 5434 | if (info->attrs[NL80211_ATTR_STA_TX_POWER_SETTING]) { | ||
| 5435 | if (!rdev->ops->set_tx_power || | ||
| 5436 | !wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 5437 | NL80211_EXT_FEATURE_STA_TX_PWR)) | ||
| 5438 | return -EOPNOTSUPP; | ||
| 5439 | |||
| 5440 | idx = NL80211_ATTR_STA_TX_POWER_SETTING; | ||
| 5441 | params->txpwr.type = nla_get_u8(info->attrs[idx]); | ||
| 5442 | |||
| 5443 | if (params->txpwr.type == NL80211_TX_POWER_LIMITED) { | ||
| 5444 | idx = NL80211_ATTR_STA_TX_POWER; | ||
| 5445 | |||
| 5446 | if (info->attrs[idx]) | ||
| 5447 | params->txpwr.power = | ||
| 5448 | nla_get_s16(info->attrs[idx]); | ||
| 5449 | else | ||
| 5450 | return -EINVAL; | ||
| 5451 | } | ||
| 5452 | params->sta_modify_mask |= STATION_PARAM_APPLY_STA_TXPOWER; | ||
| 5453 | } | ||
| 5454 | |||
| 5455 | return 0; | ||
| 5456 | } | ||
| 5457 | |||
| 5423 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | 5458 | static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) |
| 5424 | { | 5459 | { |
| 5425 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5460 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| @@ -5513,6 +5548,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
| 5513 | NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) | 5548 | NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) |
| 5514 | return -EOPNOTSUPP; | 5549 | return -EOPNOTSUPP; |
| 5515 | 5550 | ||
| 5551 | err = nl80211_parse_sta_txpower_setting(info, ¶ms); | ||
| 5552 | if (err) | ||
| 5553 | return err; | ||
| 5554 | |||
| 5516 | /* Include parameters for TDLS peer (will check later) */ | 5555 | /* Include parameters for TDLS peer (will check later) */ |
| 5517 | err = nl80211_set_station_tdls(info, ¶ms); | 5556 | err = nl80211_set_station_tdls(info, ¶ms); |
| 5518 | if (err) | 5557 | if (err) |
| @@ -5650,6 +5689,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
| 5650 | NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) | 5689 | NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) |
| 5651 | return -EOPNOTSUPP; | 5690 | return -EOPNOTSUPP; |
| 5652 | 5691 | ||
| 5692 | err = nl80211_parse_sta_txpower_setting(info, ¶ms); | ||
| 5693 | if (err) | ||
| 5694 | return err; | ||
| 5695 | |||
| 5653 | err = nl80211_parse_sta_channel_info(info, ¶ms); | 5696 | err = nl80211_parse_sta_channel_info(info, ¶ms); |
| 5654 | if (err) | 5697 | if (err) |
| 5655 | return err; | 5698 | return err; |
