Bläddra i källkod

qcacld-3.0: Add wifi config vtable support

One of the HDD functions with the highest cyclomatic complexity is
__wlan_hdd_cfg80211_wifi_configuration_set(). In order to reduce the
complexity there is a plan to replace the inline attribute handling
with a vtable-based approach

As the first step of this refactoring add the actual vtable
infrastructure.  Later changes will refactor the attribute handling
and populate the vtables.

Change-Id: If79fc61f84bf17a39e300c18681961a4a0e01408
CRs-Fixed: 2371558
Jeff Johnson 6 år sedan
förälder
incheckning
b48efe27f1
1 ändrade filer med 129 tillägg och 4 borttagningar
  1. 129 4
      core/hdd/src/wlan_hdd_cfg80211.c

+ 129 - 4
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;
 }
 
 /**