|
@@ -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
|