qcacld-3.0: Implementation of NDI Create/Delete
Add MCL changes for NDI create and NDI delete commands.
Change-Id: I270cd213d89224f73ff2ce9fad784cec3e0f8fa3
CRs-Fixed: 2014795
diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c
index 50d4ae2..947a86b 100644
--- a/core/hdd/src/wlan_hdd_nan_datapath.c
+++ b/core/hdd/src/wlan_hdd_nan_datapath.c
@@ -36,6 +36,8 @@
#include "wlan_hdd_object_manager.h"
#include <qca_vendor.h>
#include "os_if_nan.h"
+#include "wlan_nan_api.h"
+#include "nan_public_structs.h"
#ifndef WLAN_FEATURE_NAN_CONVERGENCE
/* NLA policy */
@@ -103,7 +105,10 @@
hdd_ctx->nan_datapath_enabled =
hdd_ctx->config->enable_nan_datapath &&
cfg->nan_datapath_enabled;
- hdd_info("enable_nan_datapath: %d", hdd_ctx->nan_datapath_enabled);
+ hdd_info("enable_nan_datapath: final: %d, host: %d, fw: %d",
+ hdd_ctx->nan_datapath_enabled,
+ hdd_ctx->config->enable_nan_datapath,
+ cfg->nan_datapath_enabled);
}
/**
@@ -1820,6 +1825,35 @@
tCsrRoamInfo *roam_info, uint32_t roam_id, eRoamCmdStatus roam_status,
eCsrRoamResult roam_result)
{
+ bool success;
+ struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(adapter->hdd_vdev);
+
+ if (roam_status == eCSR_ROAM_NDP_STATUS_UPDATE) {
+ switch (roam_result) {
+ case eCSR_ROAM_RESULT_NDI_CREATE_RSP:
+ success = (roam_info->ndp.ndi_create_params.status ==
+ NAN_DATAPATH_RSP_STATUS_SUCCESS);
+ hdd_debug("posting ndi create status: %d to umac",
+ success);
+ os_if_nan_post_ndi_create_rsp(psoc, adapter->sessionId,
+ success);
+ return;
+ case eCSR_ROAM_RESULT_NDI_DELETE_RSP:
+ success = (roam_info->ndp.ndi_create_params.status ==
+ NAN_DATAPATH_RSP_STATUS_SUCCESS);
+ hdd_debug("posting ndi delete status: %d to umac",
+ success);
+ os_if_nan_post_ndi_delete_rsp(psoc, adapter->sessionId,
+ success);
+ return;
+ default:
+ hdd_err("in correct roam_result: %d", roam_result);
+ return;
+ }
+ } else {
+ hdd_err("in correct roam_status: %d", roam_status);
+ return;
+ }
}
#endif
@@ -1976,6 +2010,21 @@
return ret;
}
+#ifndef WLAN_FEATURE_NAN_CONVERGENCE
+static int update_ndi_state(struct hdd_adapter_s *adapter, uint32_t state)
+{
+ struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
+
+ ndp_ctx->state = state;
+ return 0;
+}
+#else
+static int update_ndi_state(struct hdd_adapter_s *adapter, uint32_t state)
+{
+ return os_if_nan_set_ndi_state(adapter->hdd_vdev, state);
+}
+#endif
+
/**
* hdd_init_nan_data_mode() - initialize nan data mode
* @adapter: adapter context
@@ -1985,7 +2034,6 @@
int hdd_init_nan_data_mode(struct hdd_adapter_s *adapter)
{
struct net_device *wlan_dev = adapter->dev;
- struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter);
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
QDF_STATUS status;
int32_t ret_val = 0;
@@ -2033,7 +2081,7 @@
hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val);
}
- ndp_ctx->state = NAN_DATA_NDI_CREATING_STATE;
+ update_ndi_state(adapter, NAN_DATA_NDI_CREATING_STATE);
return ret_val;
error_wmm_init:
@@ -2048,3 +2096,155 @@
return ret_val;
}
+
+#ifdef WLAN_FEATURE_NAN_CONVERGENCE
+struct wlan_objmgr_vdev *hdd_ndi_open(char *iface_name)
+{
+ hdd_adapter_t *adapter;
+ hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+
+ ENTER();
+ /* Check for an existing interface of NDI type */
+ adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE);
+ if (adapter) {
+ hdd_err("Cannot support more than one NDI");
+ return NULL;
+ }
+
+ adapter = hdd_open_adapter(hdd_ctx, QDF_NDI_MODE, iface_name,
+ wlan_hdd_get_intf_addr(hdd_ctx), NET_NAME_UNKNOWN,
+ true);
+ if (!adapter) {
+ hdd_err("hdd_open_adapter failed");
+ return NULL;
+ }
+
+ EXIT();
+ return adapter->hdd_vdev;
+}
+
+int hdd_ndi_start(uint8_t vdev_id)
+{
+ hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+ uint8_t op_channel = hdd_ctx->config->nan_datapath_ndi_channel;
+ hdd_adapter_t *adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+
+ ENTER();
+ /*
+ * The NAN data interface has been created at this point.
+ * Unlike traditional device modes, where the higher application
+ * layer initiates connect / join / start, the NAN data
+ * interface does not have any such formal requests. The NDI
+ * create request is responsible for starting the BSS as well.
+ */
+ if (op_channel != NAN_SOCIAL_CHANNEL_2_4GHZ ||
+ op_channel != NAN_SOCIAL_CHANNEL_5GHZ_LOWER_BAND ||
+ op_channel != NAN_SOCIAL_CHANNEL_5GHZ_UPPER_BAND) {
+ /* start NDI on the default 2.4 GHz social channel */
+ op_channel = NAN_SOCIAL_CHANNEL_2_4GHZ;
+ }
+ if (hdd_ndi_start_bss(adapter, op_channel)) {
+ hdd_err("NDI start bss failed");
+ /* Start BSS failed, delete the interface */
+ hdd_close_ndi(adapter);
+ EXIT();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int hdd_ndi_delete(uint8_t vdev_id, char *iface_name, uint16_t transaction_id)
+{
+ int ret;
+ hdd_adapter_t *adapter;
+ hdd_station_ctx_t *sta_ctx;
+ hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+
+ /* Check if there is already an existing inteface with the same name */
+ adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+ if (!adapter || !WLAN_HDD_IS_NDI(adapter)) {
+ hdd_err("NAN data interface %s is not available", iface_name);
+ return -EINVAL;
+ }
+
+ sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ if (!sta_ctx) {
+ hdd_err("sta_ctx is NULL");
+ return -EINVAL;
+ }
+
+ /* Since, the interface is being deleted, remove the broadcast id. */
+ hdd_ctx->sta_to_adapter[sta_ctx->broadcast_staid] = 0;
+ sta_ctx->broadcast_staid = HDD_WLAN_INVALID_STA_ID;
+
+ os_if_nan_set_ndp_delete_transaction_id(adapter->hdd_vdev,
+ transaction_id);
+ os_if_nan_set_ndi_state(adapter->hdd_vdev, NAN_DATA_NDI_DELETING_STATE);
+
+ /* Delete the interface */
+ ret = __wlan_hdd_del_virtual_intf(hdd_ctx->wiphy, &adapter->wdev);
+ if (ret)
+ hdd_err("NDI delete request failed");
+ else
+ hdd_err("NDI delete request successfully issued");
+
+ return ret;
+}
+
+void hdd_ndi_drv_ndi_create_rsp_handler(uint8_t vdev_id,
+ struct nan_datapath_inf_create_rsp *ndi_rsp)
+{
+ tCsrRoamInfo roam_info = {0};
+ tSirBssDescription tmp_bss_descp = {0};
+ hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+ hdd_adapter_t *adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+ struct qdf_mac_addr bc_mac_addr = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
+ hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+ if (ndi_rsp->status == QDF_STATUS_SUCCESS) {
+ hdd_alert("NDI interface successfully created");
+ os_if_nan_set_ndp_create_transaction_id(adapter->hdd_vdev, 0);
+ os_if_nan_set_ndi_state(adapter->hdd_vdev,
+ NAN_DATA_NDI_CREATED_STATE);
+ wlan_hdd_netif_queue_control(adapter,
+ WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
+ WLAN_CONTROL_PATH);
+ } else {
+ hdd_alert("NDI interface creation failed with reason %d",
+ ndi_rsp->reason /* create_reason */);
+ }
+
+ sta_ctx->broadcast_staid = ndi_rsp->sta_id;
+ hdd_save_peer(sta_ctx, sta_ctx->broadcast_staid, &bc_mac_addr);
+ hdd_roam_register_sta(adapter, &roam_info,
+ sta_ctx->broadcast_staid,
+ &bc_mac_addr, &tmp_bss_descp);
+ hdd_ctx->sta_to_adapter[sta_ctx->broadcast_staid] = adapter;
+}
+
+void hdd_ndi_close(uint8_t vdev_id)
+{
+ hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+ hdd_adapter_t *adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+ hdd_close_ndi(adapter);
+}
+
+void hdd_ndi_drv_ndi_delete_rsp_handler(uint8_t vdev_id)
+{
+ hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+ hdd_adapter_t *adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+
+ wlan_hdd_netif_queue_control(adapter,
+ WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
+ WLAN_CONTROL_PATH);
+
+ complete(&adapter->disconnect_comp_var);
+}
+
+void hdd_ndp_session_end_handler(hdd_adapter_t *adapter)
+{
+ os_if_nan_ndi_session_end(adapter->hdd_vdev);
+}
+
+#endif