From 33ad30cac0e2b9c5ddff17dbd98092c6ade83ed6 Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Fri, 7 Jun 2024 23:12:50 +0530 Subject: [PATCH] drivers: wifi: DMS support Support for Directed multicast service(DMS). Signed-off-by: Ajay Parida --- drivers/wifi/nrf700x/inc/fmac_main.h | 2 + drivers/wifi/nrf700x/inc/wifi_mgmt.h | 6 + drivers/wifi/nrf700x/src/fmac_main.c | 2 + drivers/wifi/nrf700x/src/wifi_mgmt.c | 191 ++++++++++++++++++++++++++- 4 files changed, 197 insertions(+), 4 deletions(-) diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index 6e2a2210e940..f92e3d0d795b 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -80,6 +80,8 @@ struct nrf_wifi_vif_ctx_zep { #endif /* CONFIG_NRF700X_DATA_TX */ unsigned long rssi_record_timestamp_us; signed short rssi; + unsigned char dms_id_map; + unsigned char dms_id_in_progress_map; #endif /* CONFIG_NRF700X_STA_MODE */ }; diff --git a/drivers/wifi/nrf700x/inc/wifi_mgmt.h b/drivers/wifi/nrf700x/inc/wifi_mgmt.h index cc2ca88117c5..96176a3227d9 100644 --- a/drivers/wifi/nrf700x/inc/wifi_mgmt.h +++ b/drivers/wifi/nrf700x/inc/wifi_mgmt.h @@ -70,4 +70,10 @@ int nrf_wifi_filter(const struct device *dev, struct wifi_filter_info *filter); #endif /* CONFIG_NRF700X_RAW_DATA_RX || CONFIG_NRF700X_PROMISC_DATA_RX */ +int nrf_wifi_req_dms(const struct device *dev, + struct wifi_dms_params *dms_params); + +void nrf_wifi_event_proc_dms_zep(void *vif_ctx, + struct nrf_wifi_umac_dms_op *dms_accept_info, + unsigned int event_len); #endif /* __ZEPHYR_WIFI_MGMT_H__ */ diff --git a/drivers/wifi/nrf700x/src/fmac_main.c b/drivers/wifi/nrf700x/src/fmac_main.c index 6a2a6d0bfa02..dd1e6d37b1b0 100644 --- a/drivers/wifi/nrf700x/src/fmac_main.c +++ b/drivers/wifi/nrf700x/src/fmac_main.c @@ -721,6 +721,7 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) callbk_fns.event_get_wiphy = nrf_wifi_wpa_supp_event_get_wiphy; callbk_fns.mgmt_rx_callbk_fn = nrf_wifi_wpa_supp_event_mgmt_rx_callbk_fn; callbk_fns.get_conn_info_callbk_fn = nrf_wifi_supp_event_proc_get_conn_info; + callbk_fns.dms_callbk_fn = nrf_wifi_event_proc_dms_zep; #endif /* CONFIG_NRF700X_STA_MODE */ rpu_drv_priv_zep.fmac_priv = nrf_wifi_fmac_init(&data_config, @@ -786,6 +787,7 @@ static struct wifi_mgmt_ops nrf_wifi_mgmt_ops = { .set_twt = nrf_wifi_set_twt, .reg_domain = nrf_wifi_reg_domain, .get_power_save_config = nrf_wifi_get_power_save_config, + .req_dms = nrf_wifi_req_dms, #endif /* CONFIG_NRF700X_STA_MODE */ #ifdef CONFIG_NRF700X_SYSTEM_MODE .mode = nrf_wifi_mode, diff --git a/drivers/wifi/nrf700x/src/wifi_mgmt.c b/drivers/wifi/nrf700x/src/wifi_mgmt.c index 23f0a533c3d3..0382b6de52df 100644 --- a/drivers/wifi/nrf700x/src/wifi_mgmt.c +++ b/drivers/wifi/nrf700x/src/wifi_mgmt.c @@ -508,20 +508,20 @@ int nrf_wifi_set_twt(const struct device *dev, twt_params->flow_id >= WIFI_MAX_TWT_FLOWS) { LOG_ERR("%s: Invalid flow id: %d", __func__, twt_params->flow_id); - twt_params->fail_reason = WIFI_TWT_FAIL_INVALID_FLOW_ID; + twt_params->fail_reason = WIFI_FAIL_INVALID_FLOW_ID; goto out; } switch (twt_params->operation) { case WIFI_TWT_SETUP: if (vif_ctx_zep->twt_flow_in_progress_map & BIT(twt_params->flow_id)) { - twt_params->fail_reason = WIFI_TWT_FAIL_OPERATION_IN_PROGRESS; + twt_params->fail_reason = WIFI_FAIL_OPERATION_IN_PROGRESS; goto out; } if (twt_params->setup_cmd == WIFI_TWT_SETUP_CMD_REQUEST) { if (vif_ctx_zep->twt_flows_map & BIT(twt_params->flow_id)) { - twt_params->fail_reason = WIFI_TWT_FAIL_FLOW_ALREADY_EXISTS; + twt_params->fail_reason = WIFI_FAIL_FLOW_ALREADY_EXISTS; goto out; } } @@ -559,7 +559,7 @@ int nrf_wifi_set_twt(const struct device *dev, if (!twt_params->teardown.teardown_all) { if (!(vif_ctx_zep->twt_flows_map & BIT(twt_params->flow_id))) { - twt_params->fail_reason = WIFI_TWT_FAIL_INVALID_FLOW_ID; + twt_params->fail_reason = WIFI_FAIL_INVALID_FLOW_ID; goto out; } start_flow_id = twt_params->flow_id; @@ -948,3 +948,186 @@ int nrf_wifi_filter(const struct device *dev, return ret; } #endif /* CONFIG_NRF700X_RAW_DATA_RX || CONFIG_NRF700X_PROMISC_DATA_RX */ + +static void nrf_wifi_dms_update_internal_state(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep, + bool add, unsigned char dmsid) +{ + if (add) { + vif_ctx_zep->dms_id_map |= BIT(dmsid); + vif_ctx_zep->dms_id_in_progress_map &= ~BIT(dmsid); + } else { + vif_ctx_zep->dms_id_map &= ~BIT(dmsid); + } +} + +int nrf_wifi_req_dms(const struct device *dev, + struct wifi_dms_params *dms_params) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; + struct nrf_wifi_umac_config_dms_info dms_info = {0}; + int ret = -1; + + if (!dev || !dms_params) { + LOG_ERR("%s: dev or dms_params is NULL", __func__); + return ret; + } + + vif_ctx_zep = dev->data; + + if (!vif_ctx_zep) { + LOG_ERR("%s: vif_ctx_zep is NULL", __func__); + return ret; + } + + rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + + if (!rpu_ctx_zep) { + LOG_ERR("%s: rpu_ctx_zep is NULL", __func__); + return ret; + } + + k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER); + if (!rpu_ctx_zep->rpu_ctx) { + LOG_DBG("%s: RPU context not initialized", __func__); + goto out; + } + + switch (dms_params->operation) { + case WIFI_DMS_REQ_ADD: + if (vif_ctx_zep->dms_id_in_progress_map & BIT(dms_params->dmsid)) { + dms_params->fail_reason = WIFI_FAIL_OPERATION_IN_PROGRESS; + goto out; + } + + if (dms_params->operation == WIFI_DMS_REQ_ADD) { + if (vif_ctx_zep->dms_id_map & BIT(dms_params->dmsid)) { + dms_params->fail_reason = WIFI_FAIL_FLOW_ALREADY_EXISTS; + goto out; + } + } + + dms_info.dmsid = dms_params->dmsid; + dms_info.dialog_token = dms_params->dialog_token; + + dms_info.up = dms_params->tclas_elem.up; + dms_info.tclas_type = dms_params->tclas_elem.classifier_info.type; + dms_info.tclas_mask = dms_params->tclas_elem.classifier_info.mask; + dms_info.version = dms_params->tclas_elem.classifier_info.param_info.version; + dms_info.src_ip_addr = dms_params->tclas_elem.classifier_info.param_info.src_ip_addr; + dms_info.src_port = dms_params->tclas_elem.classifier_info.param_info.src_port; + dms_info.dest_ip_addr = dms_params->tclas_elem.classifier_info.param_info.dest_ip_addr; + dms_info.dest_port = dms_params->tclas_elem.classifier_info.param_info.dest_port; + dms_info.dscp = dms_params->tclas_elem.classifier_info.param_info.dscp; + dms_info.protocol = dms_params->tclas_elem.classifier_info.param_info.protocol; + + status = nrf_wifi_fmac_req_add_dms(rpu_ctx_zep->rpu_ctx, + vif_ctx_zep->vif_idx, + &dms_info); + break; + case WIFI_DMS_REQ_REMOVE: + if (!(vif_ctx_zep->dms_id_map & BIT(dms_params->dmsid))) { + dms_params->fail_reason = WIFI_FAIL_INVALID_DMS_ID; + goto out; + } + dms_info.dmsid = dms_params->dmsid; + + status = nrf_wifi_fmac_req_remove_dms(vif_ctx_zep, + vif_ctx_zep->vif_idx, + &dms_info); + break; + case WIFI_DMS_REQ_CHANGE: + if (vif_ctx_zep->dms_id_in_progress_map & BIT(dms_params->dmsid)) { + dms_params->fail_reason = WIFI_FAIL_OPERATION_IN_PROGRESS; + goto out; + } + + if (!(vif_ctx_zep->dms_id_map & BIT(dms_params->dmsid))) { + dms_params->fail_reason = WIFI_FAIL_INVALID_DMS_ID; + goto out; + } + + dms_info.dmsid = dms_params->dmsid; + dms_info.dialog_token = dms_params->dialog_token; + + dms_info.up = dms_params->tclas_elem.up; + dms_info.tclas_type = dms_params->tclas_elem.classifier_info.type; + dms_info.tclas_mask = dms_params->tclas_elem.classifier_info.mask; + dms_info.version = dms_params->tclas_elem.classifier_info.param_info.version; + dms_info.src_ip_addr = dms_params->tclas_elem.classifier_info.param_info.src_ip_addr; + dms_info.src_port = dms_params->tclas_elem.classifier_info.param_info.src_port; + dms_info.dest_ip_addr = dms_params->tclas_elem.classifier_info.param_info.dest_ip_addr; + dms_info.dest_port = dms_params->tclas_elem.classifier_info.param_info.dest_port; + dms_info.dscp = dms_params->tclas_elem.classifier_info.param_info.dscp; + dms_info.protocol = dms_params->tclas_elem.classifier_info.param_info.protocol; + + status = nrf_wifi_fmac_req_change_dms(rpu_ctx_zep->rpu_ctx, + vif_ctx_zep->vif_idx, + &dms_info); + break; + default: + LOG_ERR("Unknown DMS operation"); + status = NRF_WIFI_STATUS_FAIL; + break; + } + + if (status != NRF_WIFI_STATUS_SUCCESS) { + LOG_ERR("%s: nrf_wifi_req_dms %s failed", + __func__, + (dms_params->operation == WIFI_DMS_REQ_ADD) ? "add" : + (dms_params->operation == WIFI_DMS_REQ_REMOVE) ? "remove" : "change"); + goto out; + } + + ret = 0; +out: + k_mutex_unlock(&vif_ctx_zep->vif_lock); + return ret; +} + +void nrf_wifi_event_proc_dms_zep(void *vif_ctx, + struct nrf_wifi_umac_dms_op *dms_info, + unsigned int event_len) +{ + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; + struct wifi_dms_params dms_params; + + if (!vif_ctx || !dms_info) { + return; + } + + vif_ctx_zep = vif_ctx; + + dms_params.dmsid = dms_info->info.dmsid; + dms_params.dialog_token = dms_info->info.dialog_token; + dms_params.tclas_elem.up = dms_info->info.up; + dms_params.tclas_elem.classifier_info.param_info.version = dms_info->info.version; + dms_params.tclas_elem.classifier_info.param_info.src_ip_addr = dms_info->info.src_ip_addr; + dms_params.tclas_elem.classifier_info.param_info.src_port = dms_info->info.src_port; + dms_params.tclas_elem.classifier_info.param_info.dest_ip_addr = dms_info->info.dest_ip_addr; + dms_params.tclas_elem.classifier_info.param_info.dest_port = dms_info->info.dest_port; + dms_params.tclas_elem.classifier_info.param_info.dscp = dms_info->info.dscp; + dms_params.tclas_elem.classifier_info.param_info.protocol = dms_info->info.protocol; + dms_params.tclas_elem.classifier_info.type = dms_info->info.tclas_type; + dms_params.tclas_elem.classifier_info.mask = dms_info->info.tclas_mask; + + switch(dms_info->info.event_type) { + case NRF_WIFI_DMS_EVENT_ACCEPT: + dms_params.operation = WIFI_DMS_REQ_ADD; + if (dms_info->info.dms_resp_status == 0) { + nrf_wifi_dms_update_internal_state(vif_ctx_zep, true, dms_params.dmsid); + } + break; + case NRF_WIFI_DMS_EVENT_REJECT: + break; + case NRF_WIFI_DMS_EVENT_TERMINATE: + nrf_wifi_dms_update_internal_state(vif_ctx_zep, false, dms_params.dmsid); + break; + case NRF_WIFI_DMS_EVENT_INVALID: + LOG_ERR("Unknown DMS event received"); + break; + } + + wifi_mgmt_raise_dms_event(vif_ctx_zep->zep_net_if_ctx, &dms_params); +}