Explorar o código

qcacld-3.0: process set and get MLO links state information

Add a new vendor command and attributes to control and fetch
the state information of the MLO links affiliated with a
specific interface.

This will enable user space to dynamically control the MLO
links states based on the latency, throughput and power save
requirements.

Change-Id: I273049ccc92ada2624132f031a9c79d76e977a3c
CRs-Fixed: 3529429
abhinav kumar hai 1 ano
pai
achega
fb6284e06d
Modificáronse 2 ficheiros con 120 adicións e 22 borrados
  1. 5 4
      core/hdd/inc/wlan_hdd_mlo.h
  2. 115 18
      core/hdd/src/wlan_hdd_mlo.c

+ 5 - 4
core/hdd/inc/wlan_hdd_mlo.h

@@ -209,9 +209,10 @@ void hdd_mlo_t2lm_unregister_callback(struct wlan_objmgr_vdev *vdev);
  * @data_len: length of @data
  *
  * Based on the data get or set the mlo link state
- * Return: QDF_STATUS
+ *
+ * Return: 0 on success and error number otherwise.
  */
-QDF_STATUS
+int
 wlan_handle_mlo_link_state_operation(struct wiphy *wiphy,
 				     struct wlan_objmgr_vdev *vdev,
 				     const void *data, int data_len);
@@ -318,12 +319,12 @@ void hdd_mlo_t2lm_unregister_callback(struct wlan_objmgr_vdev *vdev)
 {
 }
 
-static inline QDF_STATUS
+static inline int
 wlan_handle_mlo_link_state_operation(struct wiphy *wiphy,
 				     struct wlan_objmgr_vdev *vdev,
 				     const void *data, int data_len)
 {
-	return QDF_STATUS_SUCCESS;
+	return 0;
 }
 
 static inline

+ 115 - 18
core/hdd/src/wlan_hdd_mlo.c

@@ -367,9 +367,19 @@ int hdd_update_vdev_mac_address(struct hdd_adapter *adapter,
 }
 #endif
 
+const struct nla_policy
+ml_link_state_config_policy [QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX + 1] = {
+	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID] =  {.type = NLA_U8},
+	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE] =    {.type = NLA_U32},
+};
+
 const struct nla_policy
 ml_link_state_request_policy[QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_OP_TYPE] = {.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE] = {.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG] = {.type = NLA_NESTED},
+	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_MIXED_MODE_ACTIVE_NUM_LINKS] = {
+							.type = NLA_U8},
 };
 
 static int
@@ -387,12 +397,15 @@ __wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy,
 	if (hdd_validate_adapter(adapter))
 		return -EINVAL;
 
+	if (adapter->device_mode != QDF_STA_MODE)
+		return -EINVAL;
+
 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
 
 	if (!vdev)
 		return -EINVAL;
 
-	wlan_handle_mlo_link_state_operation(wiphy, vdev, data, data_len);
+	ret = wlan_handle_mlo_link_state_operation(wiphy, vdev, data, data_len);
 
 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
 
@@ -620,49 +633,133 @@ free_event:
 	return status;
 }
 
-QDF_STATUS
+#define MLD_MAX_SUPPORTED_LINKS 2
+
+int
 wlan_handle_mlo_link_state_operation(struct wiphy *wiphy,
 				     struct wlan_objmgr_vdev *vdev,
 				     const void *data, int data_len)
 {
 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX + 1];
+	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX + 1];
 	enum qca_wlan_vendor_link_state_op_types ml_link_op;
-	struct nlattr *link_oper_attr;
-	uint32_t id;
-	int ret = 0;
+	struct nlattr *link_oper_attr, *mode_attr, *curr_attr, *num_link_attr;
+	int rem_len = 0, rc = 0;
+	uint32_t attr_id, ml_config_state = 0;
+	uint8_t ml_active_num_links = 0, ml_link_control_mode = 0;
+	uint8_t ml_config_link_id = 0, num_links = 0;
+	uint8_t vdev_id = vdev->vdev_objmgr.vdev_id;
+	uint8_t link_id_list[MLD_MAX_SUPPORTED_LINKS] = {0};
+	uint32_t config_state_list[MLD_MAX_SUPPORTED_LINKS] = {0};
 
 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX,
 				    data,
 				    data_len,
 				    ml_link_state_request_policy)) {
-		hdd_err_rl("invalid twt attr");
+		hdd_debug("vdev %d: invalid mlo link state attr", vdev_id);
 		return -EINVAL;
 	}
 
-	id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_OP_TYPE;
-	link_oper_attr = tb[id];
+	attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_OP_TYPE;
+	link_oper_attr = tb[attr_id];
 	if (!link_oper_attr) {
-		hdd_err_rl("link state operation NOT specified");
+		hdd_debug("vdev %d: link state op not specified", vdev_id);
 		return -EINVAL;
 	}
-
 	ml_link_op = nla_get_u8(link_oper_attr);
-
-	hdd_debug("ml link state request:%d", ml_link_op);
 	switch (ml_link_op) {
 	case QCA_WLAN_VENDOR_LINK_STATE_OP_GET:
-		ret = wlan_hdd_link_state_request(wiphy, vdev);
-		break;
+		return wlan_hdd_link_state_request(wiphy, vdev);
 	case QCA_WLAN_VENDOR_LINK_STATE_OP_SET:
-		hdd_debug_rl("ml link SET state not supported");
 		break;
 	default:
-		hdd_err_rl("Invalid link state operation");
-		ret = -EINVAL;
+		hdd_debug("vdev %d: Invalid op type:%d", vdev_id, ml_link_op);
+		return -EINVAL;
+	}
+
+	attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE;
+	mode_attr = tb[attr_id];
+	if (!mode_attr) {
+		hdd_debug("vdev %d: ml links control mode attr not present",
+			  vdev_id);
+		return -EINVAL;
+	}
+	ml_link_control_mode = nla_get_u8(mode_attr);
+
+	switch (ml_link_control_mode) {
+	case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_DEFAULT:
+		/* TODO: restore mlo link(s) state as per driver */
 		break;
+	case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_USER:
+		attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG;
+		if (!tb[attr_id]) {
+			hdd_debug("vdev %d: state config attr not present",
+				  vdev_id);
+			return -EINVAL;
+		}
+
+		nla_for_each_nested(curr_attr, tb[attr_id], rem_len) {
+			rc = wlan_cfg80211_nla_parse_nested(
+				tb2, QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX,
+				curr_attr,
+				ml_link_state_config_policy);
+			if (rc) {
+				hdd_debug("vdev %d: nested attr not present",
+					     vdev_id);
+				return -EINVAL;
+			}
+
+			attr_id =
+				QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID;
+			if (!tb2[attr_id]) {
+				hdd_debug("vdev %d: link id attr not present",
+					  vdev_id);
+				return -EINVAL;
+			}
+
+			ml_config_link_id = nla_get_u8(tb2[attr_id]);
+
+			attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE;
+			if (!tb2[attr_id]) {
+				hdd_debug("vdev %d: config attr not present",
+					  vdev_id);
+				return -EINVAL;
+			}
+
+			ml_config_state = nla_get_u32(tb2[attr_id]);
+			hdd_debug("vdev %d: ml_link_id %d, ml_link_state:%d",
+				  vdev_id, ml_config_link_id, ml_config_state);
+			link_id_list[num_links] = ml_config_link_id;
+			config_state_list[num_links] = ml_config_state;
+			num_links++;
+
+			if (num_links >= MLD_MAX_SUPPORTED_LINKS)
+				break;
+		}
+		/* TODO: send link(s) enable/disable command to FW */
+		break;
+	case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_MIXED:
+		attr_id =
+		   QCA_WLAN_VENDOR_ATTR_LINK_STATE_MIXED_MODE_ACTIVE_NUM_LINKS;
+		num_link_attr = tb[attr_id];
+		if (!num_link_attr) {
+			hdd_debug("number of active state links not specified");
+			return -EINVAL;
+		}
+		ml_active_num_links = nla_get_u8(num_link_attr);
+		hdd_debug("vdev %d: ml_active_num_links: %d", vdev_id,
+			  ml_active_num_links);
+		if (ml_active_num_links > MLD_MAX_SUPPORTED_LINKS)
+			return -EINVAL;
+		/* TODO: Send num link(s) as per user space request to FW */
+		break;
+	default:
+		hdd_debug("vdev %d: invalid ml_link_control_mode: %d", vdev_id,
+			  ml_link_control_mode);
+		return -EINVAL;
 	}
 
-	return ret;
+	return 0;
 }
 
 static uint32_t