From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Golle Date: Mon, 14 Nov 2011 14:02:02 +0100 Subject: [ath9k-devel] [PATCH v0 1/6] support for antenna configuration profiles Message-ID: <20111114130202.GA3106@localhost> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: ath9k-devel@lists.ath9k.org This introduces support for configuring an external antenna switch from userspace using the nl80211 API. Inspired by the previous discussion this is done by letting the user choose from a set of pre-defined values (=profiles). Supplying both, a profile name and a verbose description via platform-data might be overkill. Maybe just a profile name is enough and have verbose descriptions either in iw of libiwinfo? Signed-off-by: Daniel Golle --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1109,6 +1109,12 @@ enum nl80211_commands { * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be * used for asking the driver to perform a TDLS operation. * + * @NL80211_ATTR_WIPHY_EXTANT_SUPPORT: Flag indicating support for an external + * antenna switch. + * @NL80211_ATTR_WIPHY_EXTANT_STATE: Currently selected antenna switch profile. + * @NL80211_ATTR_WIPHY_EXTANT_SUPP_PROFILES: Nested attribute containing names + * and descriptions of the supported antenna switch configuration profiles. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1337,6 +1343,10 @@ enum nl80211_attrs { NL80211_ATTR_TDLS_SUPPORT, NL80211_ATTR_TDLS_EXTERNAL_SETUP, + NL80211_ATTR_WIPHY_EXTANT_SUPPORT, + NL80211_ATTR_WIPHY_EXTANT_STATE, + NL80211_ATTR_WIPHY_EXTANT_SUPP_PROFILES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1632,6 +1644,26 @@ enum nl80211_mpath_info { NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 }; + +/** + * enum nl80211_easp_attr - external antenna switch configuration profiles + * @__NL80211_EASP_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_EASP_ATTR_ID: unique identifier + * @NL80211_EASP_ATTR_NAME: human-readable name of the configuration profile + * @NL80211_EASP_ATTR_DESC: human-readable description of the configuration profile + * @NL80211_EASP_ATTR_MAX: highest profile attribute currently defined + * @__NL80211_EASP_ATTR_AFTER_LAST: internal use + */ +enum nl80211_easp_attr { + __NL80211_EASP_ATTR_INVALID, + NL80211_EASP_ATTR_ID, + NL80211_EASP_ATTR_NAME, + NL80211_EASP_ATTR_DESC, + /* keep last */ + __NL80211_EASP_ATTR_AFTER_LAST, + NL80211_EASP_ATTR_MAX = __NL80211_EASP_ATTR_AFTER_LAST - 1 +}; + /** * enum nl80211_band_attr - band attributes * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -197,6 +197,9 @@ static const struct nla_policy nl80211_p [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 }, [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG }, [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG }, + [NL80211_ATTR_WIPHY_EXTANT_SUPPORT] = { .type = NLA_FLAG }, + [NL80211_ATTR_WIPHY_EXTANT_STATE] = { .type = NLA_U32 }, + [NL80211_ATTR_WIPHY_EXTANT_SUPP_PROFILES] = { .type = NLA_NESTED }, }; /* policy for the key attributes */ @@ -245,6 +248,17 @@ nl80211_match_policy[NL80211_SCHED_SCAN_ .len = IEEE80211_MAX_SSID_LEN }, }; +/* policy for external antenna switch configuration profiles */ +static const struct nla_policy +nl80211_easp_policy[NL80211_EASP_ATTR_MAX + 1] = { + [NL80211_EASP_ATTR_ID] = { .type = NLA_U32 }, + [NL80211_EASP_ATTR_NAME] = { .type = NLA_STRING, + .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_EASP_ATTR_DESC] = { .type = NLA_STRING, + .len = IEEE80211_MAX_DATA_LEN }, +}; + + /* ifidx get helper */ static int nl80211_get_ifidx(struct netlink_callback *cb) { @@ -692,6 +706,7 @@ static int nl80211_send_wiphy(struct sk_ struct nlattr *nl_bands, *nl_band; struct nlattr *nl_freqs, *nl_freq; struct nlattr *nl_rates, *nl_rate; + struct nlattr *nl_easps, *nl_easp; struct nlattr *nl_cmds; enum ieee80211_band band; struct ieee80211_channel *chan; @@ -743,6 +758,8 @@ static int nl80211_send_wiphy(struct sk_ NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_SUPPORT); if (dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP); + if (dev->wiphy.flags & WIPHY_FLAG_HAS_EXTANT_SWITCH) + NLA_PUT_FLAG(msg, NL80211_ATTR_WIPHY_EXTANT_SUPPORT); NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES, sizeof(u32) * dev->wiphy.n_cipher_suites, @@ -770,6 +787,36 @@ static int nl80211_send_wiphy(struct sk_ } } +/* currently selected external antenna switch configuration profile */ + if ((dev->wiphy.flags & WIPHY_FLAG_HAS_EXTANT_SWITCH) && dev->ops->get_extant) { + u32 extant; + int res; + res = dev->ops->get_extant(&dev->wiphy, &extant); + if (!res) { + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_EXTANT_STATE, extant); + } + } + +/* available external antenna switch configuration profiles */ + if (dev->wiphy.flags & WIPHY_FLAG_HAS_EXTANT_SWITCH) { + nl_easps = nla_nest_start(msg, NL80211_ATTR_WIPHY_EXTANT_SUPP_PROFILES); + for (i = 0; dev->wiphy.extant[i].id >= 0; i++) { + nl_easp = nla_nest_start(msg, i); + if (!nl_easp) + goto nla_put_failure; + NLA_PUT_U32(msg, NL80211_EASP_ATTR_ID, + dev->wiphy.extant[i].id); + NLA_PUT(msg, NL80211_EASP_ATTR_NAME, + strlen(dev->wiphy.extant[i].name), + dev->wiphy.extant[i].name); + NLA_PUT(msg, NL80211_EASP_ATTR_DESC, + strlen(dev->wiphy.extant[i].desc), + dev->wiphy.extant[i].desc); + nla_nest_end(msg, nl_easp); + } + nla_nest_end(msg, nl_easps); + } + if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, dev->wiphy.interface_modes)) goto nla_put_failure; @@ -1335,6 +1382,17 @@ static int nl80211_set_wiphy(struct sk_b goto bad_res; } + if (info->attrs[NL80211_ATTR_WIPHY_EXTANT_STATE]) { + u32 extant; + if ((!rdev->ops->set_extant) || + (!rdev->wiphy.extant)) { + result = -EOPNOTSUPP; + goto bad_res; + } + extant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_EXTANT_STATE]); + result = rdev->ops->set_extant(&rdev->wiphy, extant); + } + changed = 0; if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1435,6 +1435,9 @@ struct cfg80211_gtk_rekey_data { * * @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant). * + * @set_extant: Select the external antenna switch configuration profile. + * @get_extant: Get currently selected antenna switch profile. + * * @set_ringparam: Set tx and rx ring sizes. * * @get_ringparam: Get tx and rx ring current and maximum sizes. @@ -1613,6 +1616,9 @@ struct cfg80211_ops { int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant); int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant); + int (*set_extant)(struct wiphy *wiphy, u32 extant); + int (*get_extant)(struct wiphy *wiphy, u32 *extant); + int (*set_ringparam)(struct wiphy *wiphy, u32 tx, u32 rx); void (*get_ringparam)(struct wiphy *wiphy, u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); @@ -1688,6 +1694,8 @@ struct cfg80211_ops { * teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT * command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be * used for asking the driver/firmware to perform a TDLS operation. + * @WIPHY_FLAG_HAS_EXTANT_SWITCH: The device got a configurable external antenna + * switch. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -1706,6 +1714,7 @@ enum wiphy_flags { WIPHY_FLAG_AP_UAPSD = BIT(14), WIPHY_FLAG_SUPPORTS_TDLS = BIT(15), WIPHY_FLAG_TDLS_EXTERNAL_SETUP = BIT(16), + WIPHY_FLAG_HAS_EXTANT_SWITCH = BIT(17), }; /** @@ -1833,6 +1842,21 @@ struct wiphy_wowlan_support { }; /** + * struct wiphy_extant_profile - User-parsable external antenna switch info + * + * This structure is used to provide the available switch configurations. + * @id: unique identifier of the profile + * @name: profile name (a short string) + * @description: user-parsable description of the profile + */ +struct wiphy_extant_profile { + int id; + char *name; + char *desc; +}; + + +/** * struct wiphy - wireless hardware description * @reg_notifier: the driver's regulatory notification callback, * note that if your driver uses wiphy_apply_custom_regulatory() @@ -1912,6 +1936,8 @@ struct wiphy_wowlan_support { * configured as RX antennas. Antenna configuration commands will be * rejected unless this or @available_antennas_tx is set. * + * @extant: struct holding the available external antenna switch configurations. + * * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation * may request, if implemented. * @@ -1972,6 +1998,8 @@ struct wiphy { u32 available_antennas_tx; u32 available_antennas_rx; + struct wiphy_extant_profile *extant; + /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't * know whether it points to a wiphy your driver has registered