diff options
Diffstat (limited to 'package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch')
-rw-r--r-- | package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch | 398 |
1 files changed, 0 insertions, 398 deletions
diff --git a/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch b/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch deleted file mode 100644 index a47e29794c..0000000000 --- a/package/kernel/mac80211/patches/subsys/384-nl80211-add-common-API-to-configure-SAR-power-limita.patch +++ /dev/null @@ -1,398 +0,0 @@ -From: Carl Huang <cjhuang@codeaurora.org> -Date: Thu, 3 Dec 2020 05:37:26 -0500 -Subject: [PATCH] nl80211: add common API to configure SAR power limitations - -NL80211_CMD_SET_SAR_SPECS is added to configure SAR from -user space. NL80211_ATTR_SAR_SPEC is used to pass the SAR -power specification when used with NL80211_CMD_SET_SAR_SPECS. - -Wireless driver needs to register SAR type, supported frequency -ranges to wiphy, so user space can query it. The index in -frequency range is used to specify which sub band the power -limitation applies to. The SAR type is for compatibility, so later -other SAR mechanism can be implemented without breaking the user -space SAR applications. - -Normal process is user space queries the SAR capability, and -gets the index of supported frequency ranges and associates the -power limitation with this index and sends to kernel. - -Here is an example of message send to kernel: -8c 00 00 00 08 00 01 00 00 00 00 00 38 00 2b 81 -08 00 01 00 00 00 00 00 2c 00 02 80 14 00 00 80 -08 00 02 00 00 00 00 00 08 00 01 00 38 00 00 00 -14 00 01 80 08 00 02 00 01 00 00 00 08 00 01 00 -48 00 00 00 - -NL80211_CMD_SET_SAR_SPECS: 0x8c -NL80211_ATTR_WIPHY: 0x01(phy idx is 0) -NL80211_ATTR_SAR_SPEC: 0x812b (NLA_NESTED) -NL80211_SAR_ATTR_TYPE: 0x00 (NL80211_SAR_TYPE_POWER) -NL80211_SAR_ATTR_SPECS: 0x8002 (NLA_NESTED) -freq range 0 power: 0x38 in 0.25dbm unit (14dbm) -freq range 1 power: 0x48 in 0.25dbm unit (18dbm) - -Signed-off-by: Carl Huang <cjhuang@codeaurora.org> -Reviewed-by: Brian Norris <briannorris@chromium.org> -Reviewed-by: Abhishek Kumar <kuabhs@chromium.org> -Link: https://lore.kernel.org/r/20201203103728.3034-2-cjhuang@codeaurora.org -[minor edits, NLA parse cleanups] -Signed-off-by: Johannes Berg <johannes.berg@intel.com> ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1737,6 +1737,54 @@ struct station_info { - u8 connected_to_as; - }; - -+/** -+ * struct cfg80211_sar_sub_specs - sub specs limit -+ * @power: power limitation in 0.25dbm -+ * @freq_range_index: index the power limitation applies to -+ */ -+struct cfg80211_sar_sub_specs { -+ s32 power; -+ u32 freq_range_index; -+}; -+ -+/** -+ * struct cfg80211_sar_specs - sar limit specs -+ * @type: it's set with power in 0.25dbm or other types -+ * @num_sub_specs: number of sar sub specs -+ * @sub_specs: memory to hold the sar sub specs -+ */ -+struct cfg80211_sar_specs { -+ enum nl80211_sar_type type; -+ u32 num_sub_specs; -+ struct cfg80211_sar_sub_specs sub_specs[]; -+}; -+ -+ -+/** -+ * @struct cfg80211_sar_chan_ranges - sar frequency ranges -+ * @start_freq: start range edge frequency -+ * @end_freq: end range edge frequency -+ */ -+struct cfg80211_sar_freq_ranges { -+ u32 start_freq; -+ u32 end_freq; -+}; -+ -+/** -+ * struct cfg80211_sar_capa - sar limit capability -+ * @type: it's set via power in 0.25dbm or other types -+ * @num_freq_ranges: number of frequency ranges -+ * @freq_ranges: memory to hold the freq ranges. -+ * -+ * Note: WLAN driver may append new ranges or split an existing -+ * range to small ones and then append them. -+ */ -+struct cfg80211_sar_capa { -+ enum nl80211_sar_type type; -+ u32 num_freq_ranges; -+ const struct cfg80211_sar_freq_ranges *freq_ranges; -+}; -+ - #if IS_ENABLED(CPTCFG_CFG80211) - /** - * cfg80211_get_station - retrieve information about a given station -@@ -4259,6 +4307,8 @@ struct cfg80211_ops { - struct cfg80211_tid_config *tid_conf); - int (*reset_tid_config)(struct wiphy *wiphy, struct net_device *dev, - const u8 *peer, u8 tids); -+ int (*set_sar_specs)(struct wiphy *wiphy, -+ struct cfg80211_sar_specs *sar); - }; - - /* -@@ -5030,6 +5080,8 @@ struct wiphy { - - u8 max_data_retry_count; - -+ const struct cfg80211_sar_capa *sar_capa; -+ - char priv[] __aligned(NETDEV_ALIGN); - }; - ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -405,6 +405,18 @@ nl80211_unsol_bcast_probe_resp_policy[NL - .len = IEEE80211_MAX_DATA_LEN } - }; - -+static const struct nla_policy -+sar_specs_policy[NL80211_SAR_ATTR_SPECS_MAX + 1] = { -+ [NL80211_SAR_ATTR_SPECS_POWER] = { .type = NLA_S32 }, -+ [NL80211_SAR_ATTR_SPECS_RANGE_INDEX] = {.type = NLA_U32 }, -+}; -+ -+static const struct nla_policy -+sar_policy[NL80211_SAR_ATTR_MAX + 1] = { -+ [NL80211_SAR_ATTR_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_SAR_TYPE), -+ [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy), -+}; -+ - static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { - [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD }, - [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, -@@ -739,6 +751,7 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_SAE_PWE] = - NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK, - NL80211_SAE_PWE_BOTH), -+ [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy), - [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT }, - }; - -@@ -2117,6 +2130,56 @@ fail: - return -ENOBUFS; - } - -+static int -+nl80211_put_sar_specs(struct cfg80211_registered_device *rdev, -+ struct sk_buff *msg) -+{ -+ struct nlattr *sar_capa, *specs, *sub_freq_range; -+ u8 num_freq_ranges; -+ int i; -+ -+ if (!rdev->wiphy.sar_capa) -+ return 0; -+ -+ num_freq_ranges = rdev->wiphy.sar_capa->num_freq_ranges; -+ -+ sar_capa = nla_nest_start(msg, NL80211_ATTR_SAR_SPEC); -+ if (!sar_capa) -+ return -ENOSPC; -+ -+ if (nla_put_u32(msg, NL80211_SAR_ATTR_TYPE, rdev->wiphy.sar_capa->type)) -+ goto fail; -+ -+ specs = nla_nest_start(msg, NL80211_SAR_ATTR_SPECS); -+ if (!specs) -+ goto fail; -+ -+ /* report supported freq_ranges */ -+ for (i = 0; i < num_freq_ranges; i++) { -+ sub_freq_range = nla_nest_start(msg, i + 1); -+ if (!sub_freq_range) -+ goto fail; -+ -+ if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_START_FREQ, -+ rdev->wiphy.sar_capa->freq_ranges[i].start_freq)) -+ goto fail; -+ -+ if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_END_FREQ, -+ rdev->wiphy.sar_capa->freq_ranges[i].end_freq)) -+ goto fail; -+ -+ nla_nest_end(msg, sub_freq_range); -+ } -+ -+ nla_nest_end(msg, specs); -+ nla_nest_end(msg, sar_capa); -+ -+ return 0; -+fail: -+ nla_nest_cancel(msg, sar_capa); -+ return -ENOBUFS; -+} -+ - struct nl80211_dump_wiphy_state { - s64 filter_wiphy; - long start; -@@ -2366,6 +2429,8 @@ static int nl80211_send_wiphy(struct cfg - CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST); - CMD(update_connect_params, UPDATE_CONNECT_PARAMS); - CMD(update_ft_ies, UPDATE_FT_IES); -+ if (rdev->wiphy.sar_capa) -+ CMD(set_sar_specs, SET_SAR_SPECS); - } - #undef CMD - -@@ -2691,6 +2756,11 @@ static int nl80211_send_wiphy(struct cfg - - if (nl80211_put_tid_config_support(rdev, msg)) - goto nla_put_failure; -+ state->split_start++; -+ break; -+ case 16: -+ if (nl80211_put_sar_specs(rdev, msg)) -+ goto nla_put_failure; - - /* done */ - state->split_start = 0; -@@ -14712,6 +14782,111 @@ static void nl80211_post_doit(__genl_con - } - } - -+static int nl80211_set_sar_sub_specs(struct cfg80211_registered_device *rdev, -+ struct cfg80211_sar_specs *sar_specs, -+ struct nlattr *spec[], int index) -+{ -+ u32 range_index, i; -+ -+ if (!sar_specs || !spec) -+ return -EINVAL; -+ -+ if (!spec[NL80211_SAR_ATTR_SPECS_POWER] || -+ !spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]) -+ return -EINVAL; -+ -+ range_index = nla_get_u32(spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]); -+ -+ /* check if range_index exceeds num_freq_ranges */ -+ if (range_index >= rdev->wiphy.sar_capa->num_freq_ranges) -+ return -EINVAL; -+ -+ /* check if range_index duplicates */ -+ for (i = 0; i < index; i++) { -+ if (sar_specs->sub_specs[i].freq_range_index == range_index) -+ return -EINVAL; -+ } -+ -+ sar_specs->sub_specs[index].power = -+ nla_get_s32(spec[NL80211_SAR_ATTR_SPECS_POWER]); -+ -+ sar_specs->sub_specs[index].freq_range_index = range_index; -+ -+ return 0; -+} -+ -+static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info) -+{ -+ struct cfg80211_registered_device *rdev = info->user_ptr[0]; -+ struct nlattr *spec[NL80211_SAR_ATTR_SPECS_MAX + 1]; -+ struct nlattr *tb[NL80211_SAR_ATTR_MAX + 1]; -+ struct cfg80211_sar_specs *sar_spec; -+ enum nl80211_sar_type type; -+ struct nlattr *spec_list; -+ u32 specs; -+ int rem, err; -+ -+ if (!rdev->wiphy.sar_capa || !rdev->ops->set_sar_specs) -+ return -EOPNOTSUPP; -+ -+ if (!info->attrs[NL80211_ATTR_SAR_SPEC]) -+ return -EINVAL; -+ -+ nla_parse_nested(tb, NL80211_SAR_ATTR_MAX, -+ info->attrs[NL80211_ATTR_SAR_SPEC], -+ NULL, NULL); -+ -+ if (!tb[NL80211_SAR_ATTR_TYPE] || !tb[NL80211_SAR_ATTR_SPECS]) -+ return -EINVAL; -+ -+ type = nla_get_u32(tb[NL80211_SAR_ATTR_TYPE]); -+ if (type != rdev->wiphy.sar_capa->type) -+ return -EINVAL; -+ -+ specs = 0; -+ nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) -+ specs++; -+ -+ if (specs > rdev->wiphy.sar_capa->num_freq_ranges) -+ return -EINVAL; -+ -+ sar_spec = kzalloc(sizeof(*sar_spec) + -+ specs * sizeof(struct cfg80211_sar_sub_specs), -+ GFP_KERNEL); -+ if (!sar_spec) -+ return -ENOMEM; -+ -+ sar_spec->type = type; -+ specs = 0; -+ nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) { -+ nla_parse_nested(spec, NL80211_SAR_ATTR_SPECS_MAX, -+ spec_list, NULL, NULL); -+ -+ switch (type) { -+ case NL80211_SAR_TYPE_POWER: -+ if (nl80211_set_sar_sub_specs(rdev, sar_spec, -+ spec, specs)) { -+ err = -EINVAL; -+ goto error; -+ } -+ break; -+ default: -+ err = -EINVAL; -+ goto error; -+ } -+ specs++; -+ } -+ -+ sar_spec->num_sub_specs = specs; -+ -+ rdev->cur_cmd_info = info; -+ err = rdev_set_sar_specs(rdev, sar_spec); -+ rdev->cur_cmd_info = NULL; -+error: -+ kfree(sar_spec); -+ return err; -+} -+ - static __genl_const struct genl_ops nl80211_ops[] = { - { - .cmd = NL80211_CMD_GET_WIPHY, -@@ -15575,6 +15750,14 @@ static const struct genl_small_ops nl802 - .internal_flags = NL80211_FLAG_NEED_NETDEV | - NL80211_FLAG_NEED_RTNL, - }, -+ { -+ .cmd = NL80211_CMD_SET_SAR_SPECS, -+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, -+ .doit = nl80211_set_sar_specs, -+ .flags = GENL_UNS_ADMIN_PERM, -+ .internal_flags = NL80211_FLAG_NEED_WIPHY | -+ NL80211_FLAG_NEED_RTNL, -+ }, - }; - - static struct genl_family nl80211_fam __genl_ro_after_init = { ---- a/net/wireless/rdev-ops.h -+++ b/net/wireless/rdev-ops.h -@@ -1356,4 +1356,16 @@ static inline int rdev_reset_tid_config( - return ret; - } - -+static inline int rdev_set_sar_specs(struct cfg80211_registered_device *rdev, -+ struct cfg80211_sar_specs *sar) -+{ -+ int ret; -+ -+ trace_rdev_set_sar_specs(&rdev->wiphy, sar); -+ ret = rdev->ops->set_sar_specs(&rdev->wiphy, sar); -+ trace_rdev_return_int(&rdev->wiphy, ret); -+ -+ return ret; -+} -+ - #endif /* __CFG80211_RDEV_OPS */ ---- a/net/wireless/trace.h -+++ b/net/wireless/trace.h -@@ -3551,6 +3551,25 @@ TRACE_EVENT(rdev_reset_tid_config, - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", tids: 0x%x", - WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tids) - ); -+ -+TRACE_EVENT(rdev_set_sar_specs, -+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_sar_specs *sar), -+ TP_ARGS(wiphy, sar), -+ TP_STRUCT__entry( -+ WIPHY_ENTRY -+ __field(u16, type) -+ __field(u16, num) -+ ), -+ TP_fast_assign( -+ WIPHY_ASSIGN; -+ __entry->type = sar->type; -+ __entry->num = sar->num_sub_specs; -+ -+ ), -+ TP_printk(WIPHY_PR_FMT ", Set type:%d, num_specs:%d", -+ WIPHY_PR_ARG, __entry->type, __entry->num) -+); -+ - #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ - - #undef TRACE_INCLUDE_PATH |