diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index b1d17d0f7891..c1463bd255e9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5624,6 +5624,117 @@ static int hdd_config_scan_default_ies(struct hdd_adapter *adapter, return 0; } +/** + * typedef independent_setter_fn - independent attribute handler + * @adapter: The adapter being configured + * @attr: The nl80211 attribute being applied + * + * Defines the signature of functions in the independent attribute vtable + * + * Return: 0 if the attribute was handled successfully, otherwise an errno + */ +typedef int (*independent_setter_fn)(struct hdd_adapter *adapter, + const struct nlattr *attr); + +/** + * struct independent_setters + * @id: vendor attribute which this entry handles + * @cb: callback function to invoke to process the attribute when present + */ +struct independent_setters { + uint32_t id; + independent_setter_fn cb; +}; + +/* vtable for independent setters */ +static const struct independent_setters independent_setters[] = { +}; + +/** + * hdd_set_independent_configuration() - Handle independent attributes + * @adapter: adapter upon which the vendor command was received + * @tb: parsed attribute array + * + * This is a table-driven function which dispatches independent + * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION + * vendor command. An attribute is considered independent if it + * doesn't depend upon any other attributes + * + * Return: 0 if there were no issues, otherwise errno of the last issue + */ +static int hdd_set_independent_configuration(struct hdd_adapter *adapter, + struct nlattr **tb) +{ + uint32_t i; + uint32_t id; + struct nlattr *attr; + independent_setter_fn cb; + int errno = 0; + int ret; + + for (i = 0; i < QDF_ARRAY_SIZE(independent_setters); i++) { + id = independent_setters[i].id; + attr = tb[id]; + if (!attr) + continue; + + cb = independent_setters[i].cb; + ret = cb(adapter, attr); + if (ret) + errno = ret; + } + + return errno; +} + +/** + * typedef interdependent_setter_fn - interdependent attribute handler + * @adapter: The adapter being configured + * @tb: The parsed nl80211 attributes being applied + * + * Defines the signature of functions in the interdependent attribute vtable + * + * Return: 0 if attributes were handled successfully, otherwise an errno + */ +typedef int (*interdependent_setter_fn)(struct hdd_adapter *adapter, + struct nlattr **tb); + +/* vtable for interdependent setters */ +static const interdependent_setter_fn interdependent_setters[] = { +}; + +/** + * hdd_set_interdependent_configuration() - Handle interdependent attributes + * @adapter: adapter upon which the vendor command was received + * @tb: parsed attribute array + * + * This is a table-driven function which handles interdependent + * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION + * vendor command. A set of attributes is considered interdependent if + * they depend upon each other. In the typical case if one of the + * attributes is present in the the attribute array, then all of the + * attributes must be present. + * + * Return: 0 if there were no issues, otherwise errno of the last issue + */ +static int hdd_set_interdependent_configuration(struct hdd_adapter *adapter, + struct nlattr **tb) +{ + uint32_t i; + interdependent_setter_fn cb; + int errno = 0; + int ret; + + for (i = 0; i < QDF_ARRAY_SIZE(interdependent_setters); i++) { + cb = interdependent_setters[i]; + ret = cb(adapter, tb); + if (ret) + errno = ret; + } + + return errno; +} + /** * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration * vendor command @@ -5648,6 +5759,7 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, struct hdd_context *hdd_ctx = wiphy_priv(wiphy); struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1]; const struct nlattr *attr; + int errno; int ret; int ret_val = 0; u32 modulated_dtim, override_li; @@ -5687,9 +5799,9 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, return -EPERM; } - ret_val = wlan_hdd_validate_context(hdd_ctx); - if (ret_val) - return ret_val; + errno = wlan_hdd_validate_context(hdd_ctx); + if (errno) + return errno; if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data, data_len, wlan_hdd_wifi_config_policy)) { @@ -5697,6 +5809,16 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, return -EINVAL; } + ret = hdd_set_independent_configuration(adapter, tb); + if (ret) + errno = ret; + + ret = hdd_set_interdependent_configuration(adapter, tb); + if (ret) + errno = ret; + + /* return errno here when all attributes have been refactored */ + mac_handle = hdd_ctx->mac_handle; if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) { @@ -6283,7 +6405,10 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, hdd_err("Failed to set GTX"); } - return ret_val; + if (ret_val) + errno = ret_val; + + return errno; } /**