From 0f076bd0db250b57fb8dcd709721b0883b52f5da Mon Sep 17 00:00:00 2001 From: Deepak Dhamdhere Date: Thu, 2 Jun 2016 11:29:21 -0700 Subject: [PATCH] qcacld-3.0: Add support for NDP data initiator request qcacld-2.0 to qcacld-3.0 propagation Add host side changes to handle INITIATOR_REQ, INITIATOR_RSP, NEW_PEER_IND and NDP_CONFIRM_IND to support NDP data initiator request. Change-Id: I10bf88d3fff27e1f842b720a598c923983c06c90 CRs-Fixed: 962367 --- core/hdd/inc/wlan_hdd_assoc.h | 8 + core/hdd/src/wlan_hdd_assoc.c | 44 +- core/hdd/src/wlan_hdd_nan_datapath.c | 358 ++++++++++++++++- core/hdd/src/wlan_hdd_nan_datapath.h | 10 +- core/mac/inc/sir_api.h | 12 +- core/mac/inc/wni_api.h | 1 + core/mac/src/include/sir_params.h | 24 +- .../src/pe/lim/lim_process_message_queue.c | 4 +- .../src/pe/lim/lim_process_sme_req_messages.c | 9 +- core/mac/src/pe/lim/lim_utils.c | 42 +- core/mac/src/pe/nan/nan_datapath.c | 306 +++++++++++++- core/mac/src/pe/nan/nan_datapath.h | 16 +- core/sme/inc/csr_api.h | 2 +- core/sme/inc/sme_api.h | 2 +- core/sme/inc/sme_inside.h | 3 + core/sme/inc/sme_internal.h | 1 + core/sme/inc/sme_nan_datapath.h | 40 +- core/sme/src/common/sme_api.c | 33 +- core/sme/src/nan/nan_datapath_api.c | 216 +++++++++- core/wma/inc/wma.h | 6 +- core/wma/inc/wma_api.h | 4 +- core/wma/inc/wma_if.h | 1 + core/wma/src/wma_dev_if.c | 5 + core/wma/src/wma_main.c | 4 + core/wma/src/wma_nan_datapath.c | 377 +++++++++++++++++- core/wma/src/wma_nan_datapath.h | 15 +- 26 files changed, 1431 insertions(+), 112 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index 969cadf2d645..9ecdf7397041 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -269,4 +269,12 @@ static inline bool hdd_is_roam_sync_in_progress(tCsrRoamInfo *roaminfo) } #endif +QDF_STATUS hdd_roam_register_sta(struct hdd_adapter_s *adapter, + struct tagCsrRoamInfo *roam_info, + uint8_t sta_id, + struct qdf_mac_addr *peer_mac_addr, + struct sSirBssDescription *bss_desc); + +bool hdd_save_peer(hdd_station_ctx_t *sta_ctx, uint8_t sta_id, + struct qdf_mac_addr *peer_mac_addr); #endif diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 0d65b55c40c8..4db478d079fe 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1338,7 +1338,7 @@ QDF_STATUS hdd_change_peer_state(hdd_adapter_t *pAdapter, * * Return: QDF_STATUS enumeration */ -static QDF_STATUS hdd_roam_register_sta(hdd_adapter_t *pAdapter, +QDF_STATUS hdd_roam_register_sta(hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, uint8_t staId, struct qdf_mac_addr *pPeerMacAddress, @@ -2551,37 +2551,31 @@ static void hdd_roam_ibss_indication_handler(hdd_adapter_t *pAdapter, } /** - * roam_save_ibss_station() - Save the IBSS peer MAC address in the adapter - * @pHddStaCtx: pointer to global HDD station context - * @staId: station id - * @peerMacAddress: pointer to peer MAC address + * hdd_save_peer() - Save peer MAC address in adapter peer table. + * @sta_ctx: pointer to hdd station context + * @sta_id: station ID + * @peer_mac_addr: mac address of new peer * * This information is passed to iwconfig later. The peer that joined * last is passed as information to iwconfig. - * - * Return: - * true if we add MAX_IBSS_PEERS or less STA - * false otherwise. + + * Return: true if success, false otherwise */ -static bool roam_save_ibss_station(hdd_station_ctx_t *pHddStaCtx, uint8_t staId, - struct qdf_mac_addr *peerMacAddress) +bool hdd_save_peer(hdd_station_ctx_t *sta_ctx, uint8_t sta_id, + struct qdf_mac_addr *peer_mac_addr) { - bool fSuccess = false; - int idx = 0; + int idx; - for (idx = 0; idx < MAX_IBSS_PEERS; idx++) { - if (0 == pHddStaCtx->conn_info.staId[idx]) { - pHddStaCtx->conn_info.staId[idx] = staId; - - qdf_copy_macaddr(&pHddStaCtx->conn_info. - peerMacAddress[idx], peerMacAddress); - - fSuccess = true; - break; + for (idx = 0; idx < SIR_MAX_NUM_STA_IN_IBSS; idx++) { + if (0 == sta_ctx->conn_info.staId[idx]) { + sta_ctx->conn_info.staId[idx] = sta_id; + qdf_copy_macaddr( + &sta_ctx->conn_info.peerMacAddress[idx], + peer_mac_addr); + return true; } } - - return fSuccess; + return false; } /** @@ -2790,7 +2784,7 @@ roam_roam_connect_status_update_handler(hdd_adapter_t *pAdapter, MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId.bytes), pRoamInfo->staId); - if (!roam_save_ibss_station + if (!hdd_save_peer (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pRoamInfo->staId, &pRoamInfo->peerMac)) { diff --git a/core/hdd/src/wlan_hdd_nan_datapath.c b/core/hdd/src/wlan_hdd_nan_datapath.c index 8e4e08c15a57..0278f19aeb83 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.c +++ b/core/hdd/src/wlan_hdd_nan_datapath.c @@ -31,6 +31,8 @@ #include "wlan_hdd_includes.h" #include "wlan_hdd_p2p.h" #include "wma_api.h" +#include "wlan_hdd_assoc.h" +#include "sme_nan_datapath.h" /* NLA policy */ static const struct nla_policy @@ -39,8 +41,8 @@ qca_wlan_vendor_ndp_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = { [QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID] = { .type = NLA_U16 }, [QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR] = { .type = NLA_STRING, .len = IFNAMSIZ }, - [QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID] = { .type = NLA_U32 }, - [QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID] = { .type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL] = { .type = NLA_U32 }, [QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR] = { .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE }, @@ -51,7 +53,7 @@ qca_wlan_vendor_ndp_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = { [QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO] = { .type = NLA_BINARY, .len = NDP_APP_INFO_LEN }, [QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID] = { .type = NLA_U32 }, - [QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_RESPONSE_CODE] = { .type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE] = { .type = NLA_U16 }, [QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_STATUS_CODE] = { .type = NLA_U16 }, [QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR] = { .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE }, @@ -148,6 +150,52 @@ static int hdd_close_ndi(hdd_adapter_t *adapter) return 0; } +/** + * hdd_is_ndp_allowed() - Indicates if NDP is allowed + * @hdd_ctx: hdd context + * + * NDP is not allowed with any other role active except STA. + * + * Return: true if allowed, false otherwise + */ +static bool hdd_is_ndp_allowed(hdd_context_t *hdd_ctx) +{ + hdd_adapter_t *adapter; + hdd_station_ctx_t *sta_ctx; + QDF_STATUS status; + hdd_adapter_list_node_t *curr = NULL, *next = NULL; + + status = hdd_get_front_adapter(hdd_ctx, &curr); + while (QDF_STATUS_SUCCESS == status) { + adapter = curr->pAdapter; + if (!adapter) + goto next_adapter; + + switch (adapter->device_mode) { + case QDF_P2P_GO_MODE: + case QDF_SAP_MODE: + if (test_bit(SOFTAP_BSS_STARTED, + &adapter->event_flags)) + return false; + break; + case QDF_P2P_CLIENT_MODE: + case QDF_IBSS_MODE: + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (hdd_conn_is_connected(sta_ctx) || + hdd_is_connecting(sta_ctx)) + return false; + break; + default: + break; + } +next_adapter: + status = hdd_get_next_adapter(hdd_ctx, curr, &next); + curr = next; + } + + return true; +} + /** * hdd_ndi_start_bss() - Start BSS on NAN data interface * @adapter: adapter context @@ -383,7 +431,6 @@ static int hdd_ndi_delete_req_handler(hdd_context_t *hdd_ctx, return ret; } - /** * hdd_ndp_initiator_req_handler() - NDP initiator request handler * @hdd_ctx: hdd context @@ -394,6 +441,114 @@ static int hdd_ndi_delete_req_handler(hdd_context_t *hdd_ctx, static int hdd_ndp_initiator_req_handler(hdd_context_t *hdd_ctx, struct nlattr **tb) { + hdd_adapter_t *adapter; + char *iface_name; + struct ndp_initiator_req req; + QDF_STATUS status; + uint32_t ndp_qos_cfg; + tHalHandle hal = hdd_ctx->hHal; + struct nan_datapath_ctx *ndp_ctx; + + ENTER(); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) { + hdd_err(FL("Interface name string is unavailable")); + return -EINVAL; + } + + iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]); + /* Check for interface in NDI mode */ + adapter = hdd_get_adapter(hdd_ctx, QDF_NDI_MODE); + if (!adapter) { + hdd_err(FL("NAN data interface %s not available"), + iface_name); + return -EINVAL; + } + + /* NAN data path coexists only with STA interface */ + if (false == hdd_is_ndp_allowed(hdd_ctx)) { + hdd_err(FL("Unsupported concurrency for NAN datapath")); + return -EPERM; + } + + ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter); + + if (ndp_ctx->state == NAN_DATA_NDI_DELETED_STATE || + ndp_ctx->state == NAN_DATA_NDI_DELETING_STATE || + ndp_ctx->state == NAN_DATA_NDI_CREATING_STATE) { + hdd_err(FL("Data request not allowed in NDI current state: %d"), + ndp_ctx->state); + return -EINVAL; + } + + req.vdev_id = adapter->sessionId; + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) { + hdd_err(FL("Transaction ID is unavailable")); + return -EINVAL; + } + req.transaction_id = + nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL]) { + hdd_err(FL("NDP channel is unavailable")); + return -EINVAL; + } + req.channel = + nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL]); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID]) { + hdd_err(FL("NDP service instance ID is unavailable")); + return -EINVAL; + } + req.service_instance_id = + nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID]); + + qdf_mem_copy(req.self_ndi_mac_addr.bytes, + adapter->macAddressCurrent.bytes, QDF_MAC_ADDR_SIZE); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]) { + hdd_err(FL("NDI peer discovery mac addr is unavailable")); + return -EINVAL; + } + qdf_mem_copy(req.peer_discovery_mac_addr.bytes, + nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR]), + QDF_MAC_ADDR_SIZE); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO_LEN]) { + hdd_err(FL("NDP app info len is unavailable")); + return -EINVAL; + } + req.ndp_info.ndp_app_info_len = + nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO_LEN]); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]) { + hdd_err(FL("NDP app info is unavailable")); + return -EINVAL; + } + req.ndp_info.ndp_app_info = + nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]); + + if (tb[QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS]) { + /* at present ndp config stores 4 bytes QOS info only */ + req.ndp_config.ndp_cfg_len = 4; + req.ndp_config.ndp_cfg = (uint8_t *)&ndp_qos_cfg; + ndp_qos_cfg = + nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS]); + } + + hddLog(LOG1, + FL("vdev_id: %d, transaction_id: %d, channel: %d, service_instance_id: %d, ndp_app_info_len: %d, peer_discovery_mac_addr: %pM"), + req.vdev_id, req.transaction_id, req.channel, + req.service_instance_id, req.ndp_info.ndp_app_info_len, + req.peer_discovery_mac_addr.bytes); + status = sme_ndp_initiator_req_handler(hal, &req); + if (status != QDF_STATUS_SUCCESS) { + hdd_err(FL("sme_ndp_initiator_req_handler failed, status: %d"), + status); + return -ECOMM; + } + EXIT(); return 0; } @@ -714,12 +869,74 @@ failure: * @adapter: pointer to adapter context * @rsp_params: response parameters * + * Following vendor event is sent to cfg80211: + * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD = + * QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE (4 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID (4 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE (4 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE (4 bytes) + * * Return: none */ static void hdd_ndp_initiator_rsp_handler(hdd_adapter_t *adapter, void *rsp_params) { + struct sk_buff *vendor_event; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct ndp_initiator_rsp *rsp = rsp_params; + uint32_t data_len = (4 * sizeof(uint32_t)) + (1 * sizeof(uint16_t)) + + NLMSG_HDRLEN + (5 * NLA_HDRLEN); + + ENTER(); + + if (!rsp) { + hdd_err(FL("Invalid NDP Initator response")); + return; + } + + if (0 != wlan_hdd_validate_context(hdd_ctx)) + return; + + vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL, + data_len, QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX, + GFP_KERNEL); + if (!vendor_event) { + hdd_err(FL("cfg80211_vendor_event_alloc failed")); + return; + } + + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD, + QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE)) + goto ndp_initiator_rsp_nla_failed; + + if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID, + rsp->transaction_id)) + goto ndp_initiator_rsp_nla_failed; + + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID, + rsp->ndp_instance_id)) + goto ndp_initiator_rsp_nla_failed; + + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, + rsp->status)) + goto ndp_initiator_rsp_nla_failed; + + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, + 0)) + goto ndp_initiator_rsp_nla_failed; + + hddLog(LOG1, + FL("NDP Initiator rsp sent, tid:%d, instance id:%d, status:%d"), + rsp->transaction_id, rsp->ndp_instance_id, rsp->status); + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + EXIT(); return; +ndp_initiator_rsp_nla_failed: + hdd_err(FL("nla_put api failed")); + kfree_skb(vendor_event); + EXIT(); } /** @@ -732,7 +949,41 @@ static void hdd_ndp_initiator_rsp_handler(hdd_adapter_t *adapter, static void hdd_ndp_new_peer_ind_handler(hdd_adapter_t *adapter, void *ind_params) { - return; + struct sme_ndp_peer_ind *new_peer_ind = ind_params; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + tSirBssDescription tmp_bss_descp = {0}; + tCsrRoamInfo roam_info = {0}; + struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter); + hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + ENTER(); + + if (NULL == ind_params) { + hdd_err(FL("Invalid new NDP peer params")); + return; + } + + /* save peer in ndp ctx */ + if (false == hdd_save_peer(sta_ctx, new_peer_ind->sta_id, + &new_peer_ind->peer_mac_addr)) { + hdd_err(FL("Ndp peer table full. cannot save new peer")); + return; + } + + /* this function is called for each new peer */ + ndp_ctx->active_ndp_peers++; + hdd_roam_register_sta(adapter, &roam_info, new_peer_ind->sta_id, + &new_peer_ind->peer_mac_addr, &tmp_bss_descp); + hdd_ctx->sta_to_adapter[new_peer_ind->sta_id] = adapter; + /* perform following steps for first new peer ind */ + if (ndp_ctx->active_ndp_peers == 1) { + hddLog(LOG1, FL("Set ctx connection state to connected")); + sta_ctx->conn_info.connState = eConnectionState_NdiConnected; + hdd_wmm_connect(adapter, &roam_info, eCSR_BSS_TYPE_NDI); + netif_carrier_on(adapter->dev); + netif_tx_start_all_queues(adapter->dev); + } + EXIT(); } /** @@ -753,12 +1004,109 @@ static void hdd_ndp_peer_departed_ind_handler( * @adapter: pointer to adapter context * @ind_params: indication parameters * + * Following vendor event is sent to cfg80211: + * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD = + * QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND (4 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID (4 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR (6 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR (IFNAMSIZ) + * QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO (ndp_app_info_len size) + * QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE (4 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_RETURN_VALUE (4 bytes) + * * Return: none */ static void hdd_ndp_confirm_ind_handler(hdd_adapter_t *adapter, void *ind_params) { + uint32_t ndp_qos_config = 0; + struct ndp_confirm_event *ndp_confirm = ind_params; + struct sk_buff *vendor_event; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + struct nan_datapath_ctx *ndp_ctx = WLAN_HDD_GET_NDP_CTX_PTR(adapter); + uint32_t data_len; + + ENTER(); + if (!ndp_confirm) { + hdd_err(FL("Invalid NDP Initator response")); + return; + } + + if (0 != wlan_hdd_validate_context(hdd_ctx)) + return; + + /* ndp_confirm is called each time user generated npd req succeeds */ + ndp_ctx->active_ndp_sessions++; + + data_len = (4 * sizeof(uint32_t)) + QDF_MAC_ADDR_SIZE + IFNAMSIZ + + sizeof(uint16_t) + NLMSG_HDRLEN + (8 * NLA_HDRLEN) + + ndp_confirm->ndp_info.ndp_app_info_len; + + vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL, + data_len, QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX, + GFP_KERNEL); + if (!vendor_event) { + hdd_err(FL("cfg80211_vendor_event_alloc failed")); + return; + } + + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD, + QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND)) + goto ndp_confirm_nla_failed; + + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID, + ndp_confirm->ndp_instance_id)) + goto ndp_confirm_nla_failed; + + if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR, + QDF_MAC_ADDR_SIZE, ndp_confirm->peer_ndi_mac_addr.bytes)) + goto ndp_confirm_nla_failed; + + if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, + IFNAMSIZ, adapter->dev->name)) + goto ndp_confirm_nla_failed; + + if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO_LEN, + ndp_confirm->ndp_info.ndp_app_info_len)) + goto ndp_confirm_nla_failed; + + if (ndp_confirm->ndp_info.ndp_app_info_len && nla_put(vendor_event, + QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO, + ndp_confirm->ndp_info.ndp_app_info_len, + ndp_confirm->ndp_info.ndp_app_info)) + goto ndp_confirm_nla_failed; + + if (ndp_confirm->ndp_config.ndp_cfg_len) { + ndp_qos_config = *((uint32_t *)ndp_confirm->ndp_config.ndp_cfg); + /* at present ndp config stores 4 bytes QOS info only */ + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS, + ndp_qos_config)) + goto ndp_confirm_nla_failed; + } + + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE, + ndp_confirm->rsp_code)) + goto ndp_confirm_nla_failed; + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + hddLog(LOG1, + FL("NDP confim sent, ndp instance id: %d, peer addr: %pM, ndp_cfg: %d, rsp_code: %d"), + ndp_confirm->ndp_instance_id, + ndp_confirm->peer_ndi_mac_addr.bytes, + ndp_qos_config, ndp_confirm->rsp_code); + + hddLog(LOG1, FL("NDP confim, ndp app info dump")); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG, + ndp_confirm->ndp_info.ndp_app_info, + ndp_confirm->ndp_info.ndp_app_info_len); + EXIT(); return; +ndp_confirm_nla_failed: + hdd_err(FL("nla_put api failed")); + kfree_skb(vendor_event); + EXIT(); } /** diff --git a/core/hdd/src/wlan_hdd_nan_datapath.h b/core/hdd/src/wlan_hdd_nan_datapath.h index 1480f6640c95..93c6b7f7868e 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.h +++ b/core/hdd/src/wlan_hdd_nan_datapath.h @@ -57,7 +57,7 @@ struct wireless_dev; * @QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID: Transaction id reference * @QCA_WLAN_VENDOR_ATTR_NDP_STATUS_ID: NDP status id * @QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID: Service instance id - * @QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_SPEC_CHANNEL: Requested channel + * @QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL: Requested channel * @QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR: Peer discovery mac addr * @QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR: Iface name * @QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY: Security configuration @@ -67,7 +67,7 @@ struct wireless_dev; * @QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID: NDP instance id * @QCA_WLAN_VENDOR_ATTR_NDP_NUM_INSTANCE_ID: Number of NDP instance ids * @QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY: NDP instance id array - * @QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_RESPONSE_CODE: Schedule response + * @QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE: Schedule response * @QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_STATUS_CODE: schedule status * @QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR: NDI mac address * @QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE: Driver return status @@ -78,7 +78,7 @@ enum qca_wlan_vendor_attr_ndp_params { QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID, QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID, - QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_SPEC_CHANNEL, + QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL, QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR, QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY, @@ -88,7 +88,7 @@ enum qca_wlan_vendor_attr_ndp_params { QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID, QCA_WLAN_VENDOR_ATTR_NDP_NUM_INSTANCE_ID, QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY, - QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_RESPONSE_CODE, + QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE, QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_STATUS_CODE, QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR, QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_TYPE, @@ -180,6 +180,7 @@ enum nan_datapath_state { * struct nan_datapath_ctx - context for nan data path * @state: Current state of NDP * @active_ndp_sessions: active ndp sessions per adapter + * @active_ndp_peers: number of active ndp peers * @ndp_create_transaction_id: transaction id for create req * @ndp_delete_transaction_id: transaction id for delete req * @ndp_key_installed: NDP security key installed @@ -189,6 +190,7 @@ enum nan_datapath_state { struct nan_datapath_ctx { enum nan_datapath_state state; uint32_t active_ndp_sessions; + uint32_t active_ndp_peers; uint16_t ndp_create_transaction_id; uint16_t ndp_delete_transaction_id; bool ndp_key_installed; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 6cb946b455d3..15e2c25c5df4 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -5927,7 +5927,7 @@ enum ndp_response_code { struct ndp_cfg { uint32_t tag; uint32_t ndp_cfg_len; - uint8_t ndp_cfg[]; + uint8_t *ndp_cfg; }; /** @@ -5953,7 +5953,7 @@ struct ndp_qos_cfg { struct ndp_app_info { uint32_t tag; uint32_t ndp_app_info_len; - uint8_t ndp_app_info[]; + uint8_t *ndp_app_info; }; /** @@ -6028,7 +6028,7 @@ struct ndp_initiator_req { }; /** - * struct ndp_initiator_rsp_event - response event from FW + * struct ndp_initiator_rsp - response event from FW * @transaction_id: unique identifier * @vdev_id: session id of the interface over which ndp is being created * @ndp_instance_id: locally created NDP instance ID @@ -6036,12 +6036,11 @@ struct ndp_initiator_req { * @reason: reason for failure if any * */ -struct ndp_initiator_rsp_event { +struct ndp_initiator_rsp { uint32_t transaction_id; uint32_t vdev_id; uint32_t ndp_instance_id; uint32_t status; - uint32_t reason; }; /** @@ -6049,6 +6048,7 @@ struct ndp_initiator_rsp_event { * @vdev_id: session id of the interface over which ndp is being created * @service_instance_id: Service identifier * @peer_discovery_mac_addr: Peer's discovery mac address + * @peer_mac_addr: Peer's NDI mac address * @ndp_initiator_mac_addr: NDI mac address of the peer initiating NDP * @ndp_instance_id: locally created NDP instance ID * @role: self role for NDP @@ -6061,7 +6061,7 @@ struct ndp_indication_event { uint32_t vdev_id; uint32_t service_instance_id; struct qdf_mac_addr peer_discovery_mac_addr; - struct qdf_mac_addr ndp_initiator_mac_addr; + struct qdf_mac_addr peer_mac_addr; uint32_t ndp_instance_id; enum ndp_self_role role; enum ndp_accept_policy policy; diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index 3d32c889e55f..74d48f51cb16 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -252,6 +252,7 @@ enum eWniMsgTypes { eWNI_SME_TSF_EVENT, eWNI_SME_MON_INIT_SESSION, eWNI_SME_PDEV_SET_HT_VHT_IE, + eWNI_SME_NDP_INITIATOR_REQ, eWNI_SME_NDP_INITIATOR_RSP, eWNI_SME_NDP_NEW_PEER_IND, eWNI_SME_NDP_CONFIRM_IND, diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 5bc816b1a6b4..746e065e1f35 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -606,7 +606,7 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_ADD_BCN_FILTER_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 339) #define SIR_HAL_REMOVE_BCN_FILTER_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 340) -#define SIR_HAL_BPF_GET_CAPABILITIES_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 341) +#define SIR_HAL_BPF_GET_CAPABILITIES_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 341) #define SIR_HAL_BPF_SET_INSTRUCTIONS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 342) #define SIR_HAL_SET_WISA_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 343) @@ -617,17 +617,17 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_TDLS_CONNECTION_TRACKER_NOTIFICATION (SIR_HAL_ITC_MSG_TYPES_BEGIN + 346) #endif -#define SIR_HAL_NDP_GET_CAP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 344) -#define SIR_HAL_NDP_INITIATOR_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 345) -#define SIR_HAL_NDP_RESPONDER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 346) -#define SIR_HAL_NDP_END_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 347) -#define SIR_HAL_NDI_CAP_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 348) -#define SIR_HAL_NDP_INITIATOR_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 349) -#define SIR_HAL_NDP_RESPONDER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 350) -#define SIR_HAL_NDP_END_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 351) -#define SIR_HAL_NDP_INDICATION (SIR_HAL_ITC_MSG_TYPES_BEGIN + 352) -#define SIR_HAL_NDP_CONFIRM (SIR_HAL_ITC_MSG_TYPES_BEGIN + 353) -#define SIR_HAL_NDP_END_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 354) +#define SIR_HAL_NDP_GET_CAP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 347) +#define SIR_HAL_NDP_INITIATOR_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 348) +#define SIR_HAL_NDP_RESPONDER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 349) +#define SIR_HAL_NDP_END_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 350) +#define SIR_HAL_NDI_CAP_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 351) +#define SIR_HAL_NDP_INITIATOR_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 352) +#define SIR_HAL_NDP_RESPONDER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 353) +#define SIR_HAL_NDP_END_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 354) +#define SIR_HAL_NDP_INDICATION (SIR_HAL_ITC_MSG_TYPES_BEGIN + 355) +#define SIR_HAL_NDP_CONFIRM (SIR_HAL_ITC_MSG_TYPES_BEGIN + 356) +#define SIR_HAL_NDP_END_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 357) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index d8031c2c5bfa..d1df82532d9b 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -63,6 +63,7 @@ #include "cds_packet.h" #include "qdf_mem.h" #include "cds_concurrency.h" +#include "nan_datapath.h" void lim_log_session_states(tpAniSirGlobal pMac); static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx, @@ -1451,7 +1452,8 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) #endif /* FEATURE_WLAN_ESE */ case eWNI_SME_REGISTER_MGMT_FRAME_CB: case eWNI_SME_EXT_CHANGE_CHANNEL: - /* These messages are from HDD.No need to respond to HDD */ + case eWNI_SME_NDP_INITIATOR_REQ: + /* These messages are from HDD.No need to respond to HDD */ lim_process_normal_hdd_msg(mac_ctx, msg, false); break; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 1f7364ee4837..9f53b3ca59e4 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -57,6 +57,7 @@ #include "wmm_apsd.h" #include "sir_mac_prot_def.h" #include "rrm_api.h" +#include "nan_datapath.h" #include "sap_api.h" @@ -170,7 +171,7 @@ static QDF_STATUS lim_process_set_hw_mode(tpAniSirGlobal mac, uint32_t *msg) status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!QDF_IS_STATUS_SUCCESS(status)) { lim_log(mac, LOGE, - FL("vos_mq_post_message failed!(err=%d)"), + FL("cds_mq_post_message failed!(err=%d)"), status); qdf_mem_free(req_msg); goto fail; @@ -245,7 +246,7 @@ static QDF_STATUS lim_process_set_dual_mac_cfg_req(tpAniSirGlobal mac, status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!QDF_IS_STATUS_SUCCESS(status)) { lim_log(mac, LOGE, - FL("vos_mq_post_message failed!(err=%d)"), + FL("cds_mq_post_message failed!(err=%d)"), status); qdf_mem_free(req_msg); goto fail; @@ -311,7 +312,7 @@ static QDF_STATUS lim_process_set_antenna_mode_req(tpAniSirGlobal mac, status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!QDF_IS_STATUS_SUCCESS(status)) { lim_log(mac, LOGE, - FL("vos_mq_post_message failed!(err=%d)"), + FL("cds_mq_post_message failed!(err=%d)"), status); qdf_mem_free(req_msg); goto fail; @@ -5169,6 +5170,8 @@ bool lim_process_sme_req_messages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) break; case eWNI_SME_PDEV_SET_HT_VHT_IE: lim_process_set_pdev_IEs(pMac, pMsgBuf); + case eWNI_SME_NDP_INITIATOR_REQ: + lim_handle_ndp_request_message(pMac, pMsg); break; default: qdf_mem_free((void *)pMsg->bodyptr); diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 2efea04ce500..49009b8ca2f8 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -56,6 +56,7 @@ #include "lim_ft_defs.h" #include "lim_session.h" #include "cds_reg_service.h" +#include "nan_datapath.h" #ifdef WLAN_FEATURE_11W #include "wni_cfg.h" @@ -5591,32 +5592,41 @@ uint8_t lim_get_current_operating_channel(tpAniSirGlobal pMac) return 0; } -void lim_process_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) +/** + * lim_process_add_sta_rsp() - process WDA_ADD_STA_RSP from WMA + * @mac_ctx: Pointer to Global MAC structure + * @msg: msg from WMA + * + * @Return: void + */ +void lim_process_add_sta_rsp(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) { - tpPESession psessionEntry; - tpAddStaParams pAddStaParams; + tpPESession session; + tpAddStaParams add_sta_params; - pAddStaParams = (tpAddStaParams) limMsgQ->bodyptr; + add_sta_params = (tpAddStaParams) msg->bodyptr; - psessionEntry = pe_find_session_by_session_id(pMac, - pAddStaParams->sessionId); - if (psessionEntry == NULL) { - lim_log(pMac, LOGP, + session = pe_find_session_by_session_id(mac_ctx, + add_sta_params->sessionId); + if (session == NULL) { + lim_log(mac_ctx, LOGP, FL("Session Does not exist for given sessionID")); - qdf_mem_free(pAddStaParams); + qdf_mem_free(add_sta_params); return; } - psessionEntry->csaOffloadEnable = pAddStaParams->csaOffloadEnable; - if (LIM_IS_IBSS_ROLE(psessionEntry)) - (void)lim_ibss_add_sta_rsp(pMac, limMsgQ->bodyptr, psessionEntry); + session->csaOffloadEnable = add_sta_params->csaOffloadEnable; + if (LIM_IS_IBSS_ROLE(session)) + (void)lim_ibss_add_sta_rsp(mac_ctx, msg->bodyptr, session); + else if (LIM_IS_NDI_ROLE(session)) + lim_ndp_add_sta_rsp(mac_ctx, session, msg->bodyptr); #ifdef FEATURE_WLAN_TDLS - else if (pMac->lim.gLimAddStaTdls) { - lim_process_tdls_add_sta_rsp(pMac, limMsgQ->bodyptr, psessionEntry); - pMac->lim.gLimAddStaTdls = false; + else if (mac_ctx->lim.gLimAddStaTdls) { + lim_process_tdls_add_sta_rsp(mac_ctx, msg->bodyptr, session); + mac_ctx->lim.gLimAddStaTdls = false; } #endif else - lim_process_mlm_add_sta_rsp(pMac, limMsgQ, psessionEntry); + lim_process_mlm_add_sta_rsp(mac_ctx, msg, session); } diff --git a/core/mac/src/pe/nan/nan_datapath.c b/core/mac/src/pe/nan/nan_datapath.c index 3c7ec25929a5..584adba16652 100644 --- a/core/mac/src/pe/nan/nan_datapath.c +++ b/core/mac/src/pe/nan/nan_datapath.c @@ -26,20 +26,117 @@ #include "lim_utils.h" #include "lim_api.h" +#include "lim_assoc_utils.h" #include "nan_datapath.h" #include "lim_types.h" #include "lim_send_messages.h" +#include "wma_nan_datapath.h" /** - * handle_ndp_request_message() - Function to handle NDP requests from SME + * lim_send_ndp_event_to_sme() - generic function to pepare and send NDP message + * to SME directly. * @mac_ctx: handle to mac structure - * @msg: pointer to message + * @msg_type: sme message type to send + * @body_ptr: buffer + * @len: buffer length + * @body_val: value + * + * Return: Nothing + */ +static void lim_send_ndp_event_to_sme(tpAniSirGlobal mac_ctx, uint32_t msg_type, + void *body_ptr, uint32_t len, uint32_t body_val) +{ + tSirMsgQ mmh_msg = {0}; + + mmh_msg.type = msg_type; + if (len && body_ptr) { + mmh_msg.bodyptr = qdf_mem_malloc(len); + if (NULL == mmh_msg.bodyptr) { + lim_log(mac_ctx, LOGE, FL("Malloc failed")); + return; + } + qdf_mem_copy(mmh_msg.bodyptr, body_ptr, len); + } else { + mmh_msg.bodyval = body_val; + } + lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT); +} + +/** + * lim_handle_ndp_indication_event() - Function to handle SIR_HAL_NDP_INDICATION + * event from WMA + * @mac_ctx: handle to mac structure + * @ndp_ind: ndp indication event params * * Return: QDF_STATUS_SUCCESS on success; error number otherwise */ -QDF_STATUS handle_ndp_request_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +static QDF_STATUS lim_handle_ndp_indication_event(tpAniSirGlobal mac_ctx, + struct ndp_indication_event *ndp_ind) { + tpPESession session; + tpDphHashNode sta_ds; + uint16_t assoc_id, peer_idx; + tSirRetStatus status; + + lim_log(mac_ctx, LOG1, + FL("role: %d, vdev: %d, peer_mac_addr "MAC_ADDRESS_STR), + ndp_ind->role, ndp_ind->vdev_id, + MAC_ADDR_ARRAY(ndp_ind->peer_mac_addr.bytes)); + + if (ndp_ind->role == NDP_ROLE_INITIATOR) { + + session = pe_find_session_by_sme_session_id(mac_ctx, + ndp_ind->vdev_id); + if (session == NULL) { + lim_log(mac_ctx, LOGE, + FL("Couldn't find session, vdev_id: %d, ndp_role: %d"), + ndp_ind->vdev_id, ndp_ind->role); + goto ndp_indication_failed; + } + sta_ds = dph_lookup_hash_entry(mac_ctx, + ndp_ind->peer_mac_addr.bytes, + &assoc_id, &session->dph.dphHashTable); + /* peer exists, don't do anything */ + if (sta_ds != NULL) { + lim_log(mac_ctx, LOGE, FL("NDI Peer already exists!!")); + return QDF_STATUS_SUCCESS; + } + + /* else create one */ + lim_log(mac_ctx, LOG1, FL("Need to create NDI Peer!!")); + peer_idx = lim_assign_peer_idx(mac_ctx, session); + sta_ds = dph_add_hash_entry(mac_ctx, + ndp_ind->peer_mac_addr.bytes, + peer_idx, &session->dph.dphHashTable); + if (sta_ds == NULL) { + lim_log(mac_ctx, LOGE, + FL("Couldn't add dph entry, ndp_role: %d"), + ndp_ind->role); + goto ndp_indication_failed; + } + /* wma decides NDI mode from wma->inferface struct */ + sta_ds->staType = STA_ENTRY_NDI_PEER; + status = lim_add_sta(mac_ctx, sta_ds, false, session); + if (eSIR_SUCCESS != status) { + lim_log(mac_ctx, LOGE, + FL("limAddSta failed status: %d, ndp_role: %d"), + status, ndp_ind->role); + goto ndp_indication_failed; + } + } else { + /* Processing for NDP Data Reponder role */ + } + /* + * With NDP indication if peer does not exists already add_sta is + * executed resulting in new peer else no action is taken. Note that + * new_peer event is not necessary event and should not be sent if case + * anything fails in this function. Rather eWNI_SME_NDP_CONFIRM_IND is + * used to indicate success of final operation and abscence of it can be + * used by service layer to identify failure. + */ return QDF_STATUS_SUCCESS; +ndp_indication_failed: + return QDF_STATUS_E_FAILURE; } /** @@ -49,9 +146,115 @@ QDF_STATUS handle_ndp_request_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) * * Return: QDF_STATUS_SUCCESS on success; error number otherwise */ -QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, cds_msg_t *msg) { + QDF_STATUS status = QDF_STATUS_SUCCESS; + + switch (msg->type) { + case SIR_HAL_NDP_CONFIRM: + lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_CONFIRM_IND, + msg->bodyptr, sizeof(struct ndp_confirm_event), + msg->bodyval); + break; + case SIR_HAL_NDP_INITIATOR_RSP: + lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_INITIATOR_RSP, + msg->bodyptr, sizeof(struct ndp_initiator_rsp), + msg->bodyval); + break; + case SIR_HAL_NDP_INDICATION: { + struct ndp_indication_event *ndp_ind = msg->bodyptr; + status = lim_handle_ndp_indication_event(mac_ctx, ndp_ind); + qdf_mem_free(ndp_ind->ndp_config.ndp_cfg); + qdf_mem_free(ndp_ind->ndp_info.ndp_app_info); + break; + } + default: + lim_log(mac_ctx, LOGE, + FL("Unhandled NDP event: %d"), msg->type); + status = QDF_STATUS_E_NOSUPPORT; + break; + } + /* + * No need to free body pointer, since the function is serving purpose + * of callback and bodyptr if allocated is freed by caller itself + */ + return status; +} + +/** + * lim_process_sme_ndp_initiator_req() - Handler for eWNI_SME_NDP_INITIATOR_REQ + * from SME. + * @mac_ctx: handle to mac structure + * @ndp_msg: ndp initiator request msg + * + * Return: Status of operation + */ +QDF_STATUS lim_process_sme_ndp_initiator_req(tpAniSirGlobal mac_ctx, + void *ndp_msg) +{ + tSirMsgQ msg; + QDF_STATUS status; + + struct sir_sme_ndp_initiator_req *sme_req = + (struct sir_sme_ndp_initiator_req *)ndp_msg; + struct ndp_initiator_req *wma_req; + + if (NULL == ndp_msg) { + lim_log(mac_ctx, LOGE, FL("invalid ndp_req")); + status = QDF_STATUS_E_INVAL; + goto send_initiator_rsp; + } + wma_req = qdf_mem_malloc(sizeof(*wma_req)); + if (wma_req == NULL) { + lim_log(mac_ctx, LOGE, FL("malloc failed")); + status = QDF_STATUS_E_NOMEM; + goto send_initiator_rsp; + } + + qdf_mem_copy(wma_req, &sme_req->req, sizeof(*wma_req)); + msg.type = SIR_HAL_NDP_INITIATOR_REQ; + msg.reserved = 0; + msg.bodyptr = wma_req; + msg.bodyval = 0; + + lim_log(mac_ctx, LOG1, FL("sending WDA_NDP_INITIATOR_REQ to WMA")); + MTRACE(mac_trace_msg_tx(mac_ctx, NO_SESSION, msg.type)); + + if (eSIR_SUCCESS != wma_post_ctrl_msg(mac_ctx, &msg)) + lim_log(mac_ctx, LOGP, FL("wma_post_ctrl_msg failed")); + return QDF_STATUS_SUCCESS; +send_initiator_rsp: + /* msg to unblock SME, but not send rsp to HDD */ + lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_INITIATOR_RSP, + NULL, 0, true); + return status; +} + +/** +* lim_handle_ndp_request_message() - Handler for NDP req from SME +* @mac_ctx: handle to mac structure +* @msg: pointer to message +* +* Return: QDF_STATUS_SUCCESS on success; error number otherwise +*/ +QDF_STATUS lim_handle_ndp_request_message(tpAniSirGlobal mac_ctx, + tpSirMsgQ msg) +{ + QDF_STATUS status; + + switch (msg->type) { + case eWNI_SME_NDP_INITIATOR_REQ: + status = lim_process_sme_ndp_initiator_req(mac_ctx, + msg->bodyptr); + break; + default: + lim_log(mac_ctx, LOGE, FL("Unhandled NDP request: %d"), + msg->type); + status = QDF_STATUS_E_NOSUPPORT; + break; + } + return status; } /** @@ -160,3 +363,98 @@ end: session_entry = NULL; } } + + +/** + * lim_send_sme_ndp_add_sta_rsp() - prepares and send new peer ind to SME + * @mac_ctx: handle to mac structure + * @session: session pointer + * @add_sta_rsp: add sta response struct + * + * Return: status of operation + */ +static QDF_STATUS lim_send_sme_ndp_add_sta_rsp(tpAniSirGlobal mac_ctx, + tpPESession session, + tAddStaParams *add_sta_rsp) +{ + tSirMsgQ mmh_msg = {0}; + struct sme_ndp_peer_ind *new_peer_ind; + + mmh_msg.type = eWNI_SME_NDP_NEW_PEER_IND; + + if (NULL == add_sta_rsp) { + lim_log(mac_ctx, LOGE, FL("Invalid add_sta_rsp")); + return QDF_STATUS_E_INVAL; + } + + new_peer_ind = qdf_mem_malloc(sizeof(*new_peer_ind)); + if (NULL == new_peer_ind) { + lim_log(mac_ctx, LOGE, FL("Failed to allocate memory")); + return QDF_STATUS_E_NOMEM; + } + + /* this message is going to HDD, fill in sme session id */ + new_peer_ind->session_id = add_sta_rsp->smesessionId; + new_peer_ind->msg_len = sizeof(struct sme_ndp_peer_ind); + new_peer_ind->msg_type = eWNI_SME_NDP_NEW_PEER_IND; + qdf_mem_copy(new_peer_ind->peer_mac_addr.bytes, add_sta_rsp->staMac, + sizeof(tSirMacAddr)); + new_peer_ind->sta_id = add_sta_rsp->staIdx; + + mmh_msg.bodyptr = new_peer_ind; + mmh_msg.bodyval = 0; + lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT); + return QDF_STATUS_SUCCESS; +} + +/** + * lim_ndp_add_sta_rsp() - handles add sta rsp for NDP from WMA + * @mac_ctx: handle to mac structure + * @session: session pointer + * @add_sta_rsp: add sta response struct + * + * Return: None + */ +void lim_ndp_add_sta_rsp(tpAniSirGlobal mac_ctx, tpPESession session, + tAddStaParams *add_sta_rsp) +{ + tpDphHashNode sta_ds; + uint16_t peer_idx; + + if (NULL == add_sta_rsp) { + lim_log(mac_ctx, LOGE, FL("Invalid add_sta_rsp")); + qdf_mem_free(add_sta_rsp); + return; + } + + SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); + sta_ds = dph_lookup_hash_entry(mac_ctx, add_sta_rsp->staMac, &peer_idx, + &session->dph.dphHashTable); + if (sta_ds == NULL) { + lim_log(mac_ctx, LOGE, + FL("NAN: ADD_STA_RSP for unknown MAC addr " + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(add_sta_rsp->staMac)); + qdf_mem_free(add_sta_rsp); + return; + } + + if (add_sta_rsp->status != QDF_STATUS_SUCCESS) { + lim_log(mac_ctx, LOGE, + FL("NAN: ADD_STA_RSP error %x for MAC addr: %pM"), + add_sta_rsp->status, add_sta_rsp->staMac); + /* delete the sta_ds allocated during ADD STA */ + lim_delete_dph_hash_entry(mac_ctx, add_sta_rsp->staMac, + peer_idx, session); + qdf_mem_free(add_sta_rsp); + return; + } + sta_ds->bssId = add_sta_rsp->bssIdx; + sta_ds->staIndex = add_sta_rsp->staIdx; + sta_ds->ucUcastSig = add_sta_rsp->ucUcastSig; + sta_ds->ucBcastSig = add_sta_rsp->ucBcastSig; + sta_ds->valid = 1; + sta_ds->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + lim_send_sme_ndp_add_sta_rsp(mac_ctx, session, add_sta_rsp); + qdf_mem_free(add_sta_rsp); +} diff --git a/core/mac/src/pe/nan/nan_datapath.h b/core/mac/src/pe/nan/nan_datapath.h index 62115f199b3c..556de8d5a732 100644 --- a/core/mac/src/pe/nan/nan_datapath.h +++ b/core/mac/src/pe/nan/nan_datapath.h @@ -104,23 +104,29 @@ struct ndp_peer_node { QDF_STATUS lim_handle_ndp_request_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg); /* Function to process NDP events */ -QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg); +QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, cds_msg_t *msg); void lim_process_ndi_mlm_add_bss_rsp(tpAniSirGlobal mac_ctx, tpSirMsgQ lim_msg_q, tpPESession session_entry); /* Handler for DEL BSS resp for NDI interface */ void lim_ndi_del_bss_rsp(tpAniSirGlobal mac_ctx, void *msg, tpPESession session_entry); + +void lim_ndp_add_sta_rsp(tpAniSirGlobal mac_ctx, tpPESession session_entry, + tAddStaParams *add_sta_rsp); + #else + /* Function to process NDP requests */ static inline QDF_STATUS lim_handle_ndp_request_message(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) { return QDF_STATUS_SUCCESS; } + /* Function to process NDP events */ static inline QDF_STATUS lim_handle_ndp_event_message(tpAniSirGlobal mac_ctx, - tpSirMsgQ msg) + cds_msg_t *msg) { return QDF_STATUS_SUCCESS; } @@ -136,6 +142,12 @@ static inline void lim_ndi_del_bss_rsp(tpAniSirGlobal mac_ctx, { } +static inline void lim_ndp_add_sta_rsp(tpAniSirGlobal mac_ctx, + tpPESession session_entry, + tAddStaParams *add_sta_rsp) +{ +} + #endif /* WLAN_FEATURE_NAN_DATAPATH */ #endif /* __MAC_NAN_DATAPATH_H */ diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 5bd8301e7d74..084d85ee96f4 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1388,7 +1388,7 @@ typedef struct tagCsrRoamInfo { struct ndp_confirm_event ndp_confirm_params; struct ndp_responder_rsp_event ndp_responder_rsp_params; struct ndp_indication_event ndp_indication_params; - struct ndp_initiator_rsp_event ndp_init_rsp_params; + struct ndp_initiator_rsp ndp_init_rsp_params; struct ndi_create_rsp ndi_create_params; struct ndi_delete_rsp ndi_delete_params; } ndp; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 804dc1e8ff4f..29909124e9c3 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -914,7 +914,7 @@ QDF_STATUS sme_set_scanning_mac_oui(tHalHandle hHal, \param hHal - The handle returned by macOpen. \param sessionId - Session Identifier \param pRequest - Pointer to the offload request. - \return eHalStatus + \return QDF_STATUS ---------------------------------------------------------------------------*/ QDF_STATUS sme_ipa_offload_enable_disable(tHalHandle hal, uint8_t session_id, diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h index 5a6600a7d983..68a26a67725f 100644 --- a/core/sme/inc/sme_inside.h +++ b/core/sme/inc/sme_inside.h @@ -192,6 +192,9 @@ typedef struct tagSmeCmd { struct s_nss_update_cmd nss_update_cmd; struct sir_dual_mac_config set_dual_mac_cmd; struct sir_antenna_mode_param set_antenna_mode_cmd; +#ifdef WLAN_FEATURE_NAN_DATAPATH + struct ndp_initiator_req initiator_req; +#endif } u; } tSmeCmd; diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index d6d0e50f5757..cdd19227ed20 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -93,6 +93,7 @@ typedef enum eSmeCommandType { e_sme_command_nss_update, e_sme_command_set_dual_mac_config, e_sme_command_set_antenna_mode, + eSmeCommandNdpInitiatorRequest, } eSmeCommandType; typedef enum eSmeState { diff --git a/core/sme/inc/sme_nan_datapath.h b/core/sme/inc/sme_nan_datapath.h index a57f1fbf9576..74102e6cf270 100644 --- a/core/sme/inc/sme_nan_datapath.h +++ b/core/sme/inc/sme_nan_datapath.h @@ -31,9 +31,23 @@ #include "qdf_types.h" #include "sir_api.h" #include "ani_global.h" +#include "sme_inside.h" + +/** + * struct sir_sme_ndp_initiator_req - sme request struct for ndp initiator req + * @mesgType: SME msg type(eWNI_SME_NDP_INITIATOR_REQ) + * @mesgLen: lenght of message + * @req: actual ndp initiator request + * + */ +struct sir_sme_ndp_initiator_req { + uint16_t msg_type; + uint16_t msg_len; + struct ndp_initiator_req req; +}; /* NAN initiator request handler */ -QDF_STATUS sme_ndp_initiator_req_handler(uint32_t session_id, +QDF_STATUS sme_ndp_initiator_req_handler(tHalHandle hal, struct ndp_initiator_req *req_params); /* NAN responder request handler */ @@ -73,6 +87,11 @@ void csr_roam_update_ndp_return_params(tpAniSirGlobal mac_ctx, uint32_t *roam_status, uint32_t *roam_result, struct tagCsrRoamInfo *roam_info); +QDF_STATUS csr_process_ndp_initiator_request(tpAniSirGlobal mac_ctx, + tSmeCmd *cmd); + +void sme_ndp_msg_processor(tpAniSirGlobal mac_ctx, cds_msg_t *msg); + #else /* Start NDI BSS */ @@ -107,5 +126,24 @@ static inline void csr_roam_update_ndp_return_params(tpAniSirGlobal mac_ctx, struct tagCsrRoamInfo *roam_info) { } + +/* NaN indication response handler */ +QDF_STATUS sme_ndp_end_req_handler(uint32_t session_id, + struct ndp_end_req *req_params); + +/* NaN schedule update request handler */ +QDF_STATUS sme_ndp_sched_req_handler(uint32_t session_id, + struct ndp_schedule_update_req *req_params); + +static inline eHalStatus csr_process_ndp_initiator_request( + tpAniSirGlobal mac_ctx, tSmeCmd *cmd) +{ + return QDF_STATUS_SUCCESS; +} + +static inline void sme_ndp_msg_processor(tpAniSirGlobal mac_ctx, cds_msg_t *msg) +{ +} + #endif /* WLAN_FEATURE_NAN_DATAPATH */ #endif /* __SME_NAN_DATAPATH_H */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 6c7766e5aa00..1601666a74d6 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -59,6 +59,7 @@ #include "sme_power_save_api.h" #include "wma.h" #include "sch_api.h" +#include "sme_nan_datapath.h" extern tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, tSirMbMsg *pMb); @@ -956,6 +957,15 @@ sme_process_cmd: csr_ll_unlock(&pMac->sme.smeCmdActiveList); csr_process_add_sta_session_command(pMac, pCommand); break; + case eSmeCommandNdpInitiatorRequest: + csr_ll_unlock(&pMac->sme.smeCmdActiveList); + if (csr_process_ndp_initiator_request(pMac, pCommand) != + QDF_STATUS_SUCCESS) + if (csr_ll_remove_entry( + &pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK)) + csr_release_command(pMac, pCommand); + break; case eSmeCommandDelStaSession: csr_ll_unlock(&pMac->sme.smeCmdActiveList); csr_process_del_sta_session_command(pMac, pCommand); @@ -2985,6 +2995,11 @@ QDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg) pMsg->type); } break; + case eWNI_SME_NDP_CONFIRM_IND: + case eWNI_SME_NDP_NEW_PEER_IND: + case eWNI_SME_NDP_INITIATOR_RSP: + sme_ndp_msg_processor(pMac, pMsg); + break; default: if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN) @@ -13178,13 +13193,13 @@ QDF_STATUS sme_get_cached_results(tHalHandle hHal, /** * sme_set_epno_list() - set epno network list - * @hHal: global hal handle + * @hal: global hal handle * @input: request message * * This function constructs the cds message and fill in message type, * bodyptr with %input and posts it to WDA queue. * - * Return: eHalStatus enumeration + * Return: QDF_STATUS enumeration */ QDF_STATUS sme_set_epno_list(tHalHandle hal, struct wifi_epno_params *input) @@ -13253,7 +13268,7 @@ QDF_STATUS sme_set_epno_list(tHalHandle hal, * This function constructs the cds message and fill in message type, * bodyptr with @input and posts it to WDA queue. * - * Return: eHalStatus enumeration + * Return: QDF_STATUS enumeration */ QDF_STATUS sme_set_passpoint_list(tHalHandle hal, struct wifi_passpoint_req *input) @@ -13320,7 +13335,7 @@ QDF_STATUS sme_set_passpoint_list(tHalHandle hal, * @hHal: global hal handle * @input: request message * - * Return: eHalStatus enumeration + * Return: QDF_STATUS enumeration */ QDF_STATUS sme_reset_passpoint_list(tHalHandle hal, struct wifi_passpoint_req *input) @@ -13370,7 +13385,7 @@ QDF_STATUS sme_reset_passpoint_list(tHalHandle hal, * @hal: SME handle * @request: set ssid hotlist request * - * Return: eHalStatus + * Return: QDF_STATUS */ QDF_STATUS sme_set_ssid_hotlist(tHalHandle hal, @@ -14262,7 +14277,7 @@ bool sme_neighbor_middle_of_roaming(tHalHandle hHal, uint8_t sessionId) * This function is used to send the command that will * be used to flush the logs in the firmware * - * Return: eHalStatus + * Return: QDF_STATUS */ QDF_STATUS sme_send_flush_logs_cmd_to_fw(tpAniSirGlobal mac) { @@ -14691,8 +14706,8 @@ QDF_STATUS sme_pdev_set_pcl(tHalHandle hal, status = sme_acquire_global_lock(&mac->sme); if (status != QDF_STATUS_SUCCESS) { sms_log(mac, LOGE, - FL("sme_AcquireGlobalLock failed!(status=%d)"), - status); + FL("sme_acquire_global_lock failed!(status=%d)"), + status); qdf_mem_free(req_msg); return status; } @@ -14703,7 +14718,7 @@ QDF_STATUS sme_pdev_set_pcl(tHalHandle hal, status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!QDF_IS_STATUS_SUCCESS(status)) { sms_log(mac, LOGE, - FL("vos_mq_post_message failed!(err=%d)"), + FL("cds_mq_post_message failed!(err=%d)"), status); qdf_mem_free(req_msg); status = QDF_STATUS_E_FAILURE; diff --git a/core/sme/src/nan/nan_datapath_api.c b/core/sme/src/nan/nan_datapath_api.c index 3efd69b7f8c4..a36a64459ffa 100644 --- a/core/sme/src/nan/nan_datapath_api.c +++ b/core/sme/src/nan/nan_datapath_api.c @@ -32,17 +32,83 @@ /** * sme_ndp_initiator_req_handler() - ndp initiator req handler - * @session_id: session id over which the ndp is being created + * @hal: hal handle * @req_params: request parameters * * Return: QDF_STATUS_SUCCESS on success; error number otherwise */ -QDF_STATUS sme_ndp_initiator_req_handler(uint32_t session_id, - struct ndp_initiator_req *req_params) +QDF_STATUS sme_ndp_initiator_req_handler(tHalHandle hal, + struct ndp_initiator_req *req_params) { - return QDF_STATUS_SUCCESS; -} + QDF_STATUS status = QDF_STATUS_SUCCESS; + tSmeCmd *cmd; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + if (NULL == req_params) { + sms_log(mac_ctx, LOGE, FL("Invalid req_params")); + return QDF_STATUS_E_INVAL; + } + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (QDF_STATUS_SUCCESS != status) { + sms_log(mac_ctx, LOGE, + FL("SME lock failed, status:%d"), status); + return status; + } + cmd = csr_get_command_buffer(mac_ctx); + if (NULL == cmd) { + sme_release_global_lock(&mac_ctx->sme); + return QDF_STATUS_E_RESOURCES; + } + + cmd->command = eSmeCommandNdpInitiatorRequest; + cmd->sessionId = (uint8_t)req_params->vdev_id; + qdf_mem_copy(&cmd->u.initiator_req, req_params, + sizeof(struct ndp_initiator_req)); + /* pointers copied as part of above operation are to be overwritten */ + cmd->u.initiator_req.ndp_info.ndp_app_info = NULL; + cmd->u.initiator_req.ndp_config.ndp_cfg = NULL; + + if (req_params->ndp_info.ndp_app_info_len) { + cmd->u.initiator_req.ndp_info.ndp_app_info = + qdf_mem_malloc(req_params->ndp_info.ndp_app_info_len); + if (NULL == cmd->u.initiator_req.ndp_info.ndp_app_info) { + sme_release_global_lock(&mac_ctx->sme); + return QDF_STATUS_E_NOMEM; + } + qdf_mem_copy(cmd->u.initiator_req.ndp_info.ndp_app_info, + req_params->ndp_info.ndp_app_info, + req_params->ndp_info.ndp_app_info_len); + } + + if (req_params->ndp_config.ndp_cfg_len) { + cmd->u.initiator_req.ndp_config.ndp_cfg = + qdf_mem_malloc(req_params->ndp_config.ndp_cfg_len); + if (NULL == cmd->u.initiator_req.ndp_config.ndp_cfg) { + sme_release_global_lock(&mac_ctx->sme); + qdf_mem_free( + cmd->u.initiator_req.ndp_info.ndp_app_info); + cmd->u.initiator_req.ndp_info.ndp_app_info_len = 0; + return QDF_STATUS_E_NOMEM; + } + qdf_mem_copy(cmd->u.initiator_req.ndp_config.ndp_cfg, + req_params->ndp_config.ndp_cfg, + req_params->ndp_config.ndp_cfg_len); + } + + status = csr_queue_sme_command(mac_ctx, cmd, true); + if (QDF_STATUS_SUCCESS != status) { + sms_log(mac_ctx, LOGE, FL("SME enqueue failed, status:%d"), + status); + qdf_mem_free(cmd->u.initiator_req.ndp_info.ndp_app_info); + qdf_mem_free(cmd->u.initiator_req.ndp_config.ndp_cfg); + cmd->u.initiator_req.ndp_info.ndp_app_info_len = 0; + cmd->u.initiator_req.ndp_config.ndp_cfg_len = 0; + } + + sme_release_global_lock(&mac_ctx->sme); + return status; +} /** * sme_ndp_responder_req_handler() - ndp responder request handler * @session_id: session id over which the ndp is being created @@ -245,3 +311,143 @@ void csr_roam_update_ndp_return_params(tpAniSirGlobal mac_ctx, break; } } + + +/** + * csr_process_ndp_initiator_request() - process ndp initiator request + * @mac_ctx: Global MAC context + * @cmd: ndp initiator sme cmd + * + * Return: status of operation + */ +QDF_STATUS csr_process_ndp_initiator_request(tpAniSirGlobal mac_ctx, + tSmeCmd *cmd) +{ + struct sir_sme_ndp_initiator_req *lim_msg; + uint16_t msg_len; + uint8_t *self_mac_addr = NULL; + struct ndp_initiator_req *req; + + if (NULL == cmd) { + sms_log(mac_ctx, LOGE, FL("Invalid req_params")); + return QDF_STATUS_E_INVAL; + } + req = &cmd->u.initiator_req; + + msg_len = sizeof(*lim_msg); + lim_msg = qdf_mem_malloc(msg_len); + if (NULL == lim_msg) + return QDF_STATUS_E_NOMEM; + + qdf_mem_set(lim_msg, msg_len, 0); + lim_msg->msg_type = eWNI_SME_NDP_INITIATOR_REQ; + lim_msg->msg_len = msg_len; + /* + * following is being copied from p_cmd->u.initiator_req, + * no need to perform deep copy, as we are going to use memory + * allocated at SME in p_cmd->u.initiator_req and pass it all the way + * to WMA. + */ + qdf_mem_copy(&lim_msg->req, req, sizeof(struct ndp_initiator_req)); + + self_mac_addr = lim_msg->req.self_ndi_mac_addr.bytes; + sms_log(mac_ctx, LOG1, FL("selfMac = "MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(self_mac_addr)); + + return cds_send_mb_message_to_mac(lim_msg); +} + +/** + * sme_ndp_msg_processor() - message processor for ndp/ndi north-bound SME msg. + * @mac_ctx: Global MAC context + * @msg: ndp/ndi SME message + * + * This function will further call csrRoamCallCallback with appropriate + * roam_status and roam_result thus allowing hdd to correctly identify NDP/NDI + * response. + * + * Return: nothing + */ +void sme_ndp_msg_processor(tpAniSirGlobal mac_ctx, cds_msg_t *msg) +{ + tCsrRoamInfo roam_info = {0}; + eCsrRoamResult result; + uint32_t session_id; + tListElem *entry = NULL; + tSmeCmd *cmd = NULL; + bool release_active_cmd = false; + eSmeCommandType cmd_to_rel = eSmeNoCommand; + bool send_to_user = true; + + switch (msg->type) { + case eWNI_SME_NDP_CONFIRM_IND: { + result = eCSR_ROAM_RESULT_NDP_CONFIRM_IND; + /* copy msg from msg body to roam info passed to callback */ + qdf_mem_copy(&roam_info.ndp.ndp_confirm_params, msg->bodyptr, + sizeof(roam_info.ndp.ndp_confirm_params)); + session_id = roam_info.ndp.ndp_confirm_params.vdev_id; + break; + } + case eWNI_SME_NDP_INITIATOR_RSP: { + if (true == msg->bodyval) { + /* rsp was locally generated, do not send to HDD */ + send_to_user = false; + } else { + result = eCSR_ROAM_RESULT_NDP_INITIATOR_RSP; + qdf_mem_copy(&roam_info.ndp.ndp_init_rsp_params, + msg->bodyptr, + sizeof(roam_info.ndp.ndp_init_rsp_params)); + session_id = roam_info.ndp.ndp_init_rsp_params.vdev_id; + } + release_active_cmd = true; + cmd_to_rel = eSmeCommandNdpInitiatorRequest; + entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (entry != NULL) { + cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (cmd_to_rel == cmd->command) { + qdf_mem_free( + cmd->u.initiator_req.ndp_config.ndp_cfg); + qdf_mem_free( + cmd->u.initiator_req.ndp_info.ndp_app_info); + } + } + break; + } + case eWNI_SME_NDP_NEW_PEER_IND: { + result = eCSR_ROAM_RESULT_NDP_NEW_PEER_IND; + /* copy msg from msg body to roam info passed to callback */ + qdf_mem_copy(&roam_info.ndp.ndp_peer_ind_params, + msg->bodyptr, + sizeof(roam_info.ndp.ndp_peer_ind_params)); + session_id = roam_info.ndp.ndp_peer_ind_params.session_id; + break; + } + default: + sms_log(mac_ctx, LOGE, FL("Unhandled NDP rsp")); + qdf_mem_free(msg->bodyptr); + return; + } + + if (true == send_to_user) { + csr_roam_call_callback(mac_ctx, session_id, &roam_info, 0, + eCSR_ROAM_NDP_STATUS_UPDATE, result); + } + qdf_mem_free(msg->bodyptr); + if (release_active_cmd == false) + return; + + entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList, + LL_ACCESS_LOCK); + if (entry == NULL) + return; + + cmd = GET_BASE_ADDR(entry, tSmeCmd, Link); + if (cmd_to_rel == cmd->command) { + /* Now put this cmd back on the avilable command list */ + if (csr_ll_remove_entry(&mac_ctx->sme.smeCmdActiveList, + entry, LL_ACCESS_LOCK)) + sme_release_command(mac_ctx, cmd); + sme_process_pending_queue(mac_ctx); + } +} diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index e374df2d353c..957af8074d3d 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1434,7 +1434,7 @@ typedef struct { /* NAN datapath support enabled in firmware */ bool nan_datapath_enabled; QDF_STATUS (*pe_ndp_event_handler)(tpAniSirGlobal mac_ctx, - tpSirMsgQ msg); + cds_msg_t *msg); } t_wma_handle, *tp_wma_handle; /** @@ -2133,6 +2133,10 @@ QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma, uint32_t vdev_id, uint32_t bitmap, bool enable); +QDF_STATUS wma_create_peer(tp_wma_handle wma, ol_txrx_pdev_handle pdev, + ol_txrx_vdev_handle vdev, u8 peer_addr[6], + u_int32_t peer_type, u_int8_t vdev_id, + bool roam_synch_in_progress); #endif struct wma_ini_config *wma_get_ini_handle(tp_wma_handle wma_handle); diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 9e3e6ab1f73a..c690f55529c9 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -254,11 +254,11 @@ QDF_STATUS wma_set_tx_power_scale_decr_db(uint8_t vdev_id, int value); #ifdef WLAN_FEATURE_NAN_DATAPATH QDF_STATUS wma_register_ndp_cb(QDF_STATUS (*pe_ndp_event_handler) (tpAniSirGlobal mac_ctx, - tpSirMsgQ msg)); + cds_msg_t *msg)); #else static inline QDF_STATUS wma_register_ndp_cb(QDF_STATUS (*pe_ndp_event_handler) (tpAniSirGlobal mac_ctx, - tpSirMsgQ msg)) + cds_msg_t *msg)) { return QDF_STATUS_SUCCESS; } diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 39aab20b6312..58b0dac039bd 100644 --- a/core/wma/inc/wma_if.h +++ b/core/wma/inc/wma_if.h @@ -84,6 +84,7 @@ #ifdef FEATURE_WLAN_TDLS #define STA_ENTRY_TDLS_PEER 4 #endif /* FEATURE_WLAN_TDLS */ +#define STA_ENTRY_NDI_PEER 5 #define STA_INVALID_IDX 0xFF diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 8b46b6450a63..e785e2b1fc7e 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -4067,6 +4067,8 @@ void wma_add_sta(tp_wma_handle wma, tpAddStaParams add_sta) else if (wma_is_vdev_in_ibss_mode(wma, add_sta->smesessionId)) oper_mode = BSS_OPERATIONAL_MODE_IBSS; + if (WMA_IS_VDEV_IN_NDI_MODE(wma->interfaces, add_sta->smesessionId)) + oper_mode = BSS_OPERATIONAL_MODE_NDI; switch (oper_mode) { case BSS_OPERATIONAL_MODE_STA: wma_add_sta_req_sta_mode(wma, add_sta); @@ -4078,6 +4080,9 @@ void wma_add_sta(tp_wma_handle wma, tpAddStaParams add_sta) htc_vote_link_down(wma->htc_handle); wma_add_sta_req_ap_mode(wma, add_sta); break; + case BSS_OPERATIONAL_MODE_NDI: + wma_add_sta_ndi_mode(wma, add_sta); + break; } #ifdef QCA_IBSS_SUPPORT diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index f38b2e3739b7..85463a1488a2 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -5946,6 +5946,10 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) wma_set_bpf_instructions(wma_handle, msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case SIR_HAL_NDP_INITIATOR_REQ: + wma_handle_ndp_initiator_req(wma_handle, msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; default: WMA_LOGD("unknow msg type %x", msg->type); diff --git a/core/wma/src/wma_nan_datapath.c b/core/wma/src/wma_nan_datapath.c index e77f93ccbb4f..83deb25e9ada 100644 --- a/core/wma/src/wma_nan_datapath.c +++ b/core/wma/src/wma_nan_datapath.c @@ -30,18 +30,138 @@ #include "wmi_unified.h" #include "wma_nan_datapath.h" #include "wma_internal.h" +#include "cds_utils.h" /** * wma_handle_ndp_initiator_req() - NDP initiator request handler * @wma_handle: wma handle - * @req_params: request parameters + * @req: request parameters * * Return: QDF_STATUS_SUCCESS on success; error number otherwise */ -QDF_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle, - struct ndp_initiator_req *req_params) +QDF_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle, void *req) { + QDF_STATUS status; + int ret; + uint16_t len; + uint32_t vdev_id, ndp_cfg_len, ndp_app_info_len; + struct ndp_initiator_rsp ndp_rsp = {0}; + uint8_t *cfg_info, *app_info; + ol_txrx_vdev_handle vdev; + wmi_buf_t buf; + wmi_ndp_initiator_req_fixed_param *cmd; + cds_msg_t pe_msg = {0}; + struct ndp_initiator_req *ndp_req = req; + wmi_channel *ch_tlv; + + if (NULL == ndp_req) { + WMA_LOGE(FL("Invalid ndp_req.")); + goto send_ndi_initiator_fail; + } + vdev_id = ndp_req->vdev_id; + vdev = wma_find_vdev_by_id(wma_handle, vdev_id); + if (!vdev) { + WMA_LOGE(FL("vdev not found for vdev id %d."), vdev_id); + goto send_ndi_initiator_fail; + } + + if (!WMA_IS_VDEV_IN_NDI_MODE(wma_handle->interfaces, vdev_id)) { + WMA_LOGE(FL("vdev :%d, not in NDI mode"), vdev_id); + goto send_ndi_initiator_fail; + } + + /* + * WMI command expects 4 byte alligned len: + * round up ndp_cfg_len and ndp_app_info_len to 4 bytes + */ + ndp_cfg_len = roundup(ndp_req->ndp_config.ndp_cfg_len, 4); + ndp_app_info_len = roundup(ndp_req->ndp_info.ndp_app_info_len, 4); + /* allocated memory for fixed params as well as variable size data */ + len = sizeof(*cmd) + ndp_cfg_len + ndp_app_info_len + + (2 * WMI_TLV_HDR_SIZE) + sizeof(*ch_tlv); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + goto send_ndi_initiator_fail; + } + cmd = (wmi_ndp_initiator_req_fixed_param *) wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ndp_initiator_req_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_ndp_initiator_req_fixed_param)); + cmd->vdev_id = ndp_req->vdev_id; + cmd->transaction_id = ndp_req->transaction_id; + cmd->service_instance_id = ndp_req->service_instance_id; + WMI_CHAR_ARRAY_TO_MAC_ADDR(ndp_req->peer_discovery_mac_addr.bytes, + &cmd->peer_discovery_mac_addr); + + cmd->ndp_cfg_len = ndp_req->ndp_config.ndp_cfg_len; + cmd->ndp_app_info_len = ndp_req->ndp_info.ndp_app_info_len; + + ch_tlv = (wmi_channel *)&cmd[1]; + WMITLV_SET_HDR(ch_tlv, WMITLV_TAG_STRUC_wmi_channel, + WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); + ch_tlv->mhz = ndp_req->channel; + ch_tlv->band_center_freq1 = + cds_chan_to_freq(cds_freq_to_chan(ndp_req->channel)); + + cfg_info = (uint8_t *)&ch_tlv[1]; + WMITLV_SET_HDR(cfg_info, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len); + qdf_mem_copy(&cfg_info[WMI_TLV_HDR_SIZE], ndp_req->ndp_config.ndp_cfg, + cmd->ndp_cfg_len); + + app_info = &cfg_info[WMI_TLV_HDR_SIZE + ndp_cfg_len]; + WMITLV_SET_HDR(app_info, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len); + qdf_mem_copy(&app_info[WMI_TLV_HDR_SIZE], + ndp_req->ndp_info.ndp_app_info, + cmd->ndp_app_info_len); + + WMA_LOGE(FL("vdev_id = %d, transaction_id: %d, service_instance_id, %d channel: %d"), + cmd->vdev_id, cmd->transaction_id, cmd->service_instance_id, + ch_tlv->mhz); + WMA_LOGE(FL("peer mac addr: mac_addr31to0: 0x%x, mac_addr47to32: 0x%x"), + cmd->peer_discovery_mac_addr.mac_addr31to0, + cmd->peer_discovery_mac_addr.mac_addr47to32); + + WMA_LOGE(FL("ndp_config len: %d"), cmd->ndp_cfg_len); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + ndp_req->ndp_config.ndp_cfg, + ndp_req->ndp_config.ndp_cfg_len); + + WMA_LOGE(FL("ndp_app_info len: %d"), cmd->ndp_app_info_len); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + ndp_req->ndp_info.ndp_app_info, + ndp_req->ndp_info.ndp_app_info_len); + + WMA_LOGE(FL("sending WMI_NDP_INITIATOR_REQ_CMDID(0x%X)"), + WMI_NDP_INITIATOR_REQ_CMDID); + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_NDP_INITIATOR_REQ_CMDID); + if (ret < 0) { + WMA_LOGE(FL("WMI_NDP_INITIATOR_REQ_CMDID failed, ret: %d"), + ret); + wmi_buf_free(buf); + goto send_ndi_initiator_fail; + } + return QDF_STATUS_SUCCESS; + +send_ndi_initiator_fail: + status = QDF_STATUS_E_FAILURE; + if (ndp_req) { + ndp_rsp.vdev_id = ndp_req->vdev_id; + ndp_rsp.transaction_id = ndp_req->transaction_id; + ndp_rsp.ndp_instance_id = ndp_req->service_instance_id; + ndp_rsp.status = NDP_CMD_RSP_STATUS_ERROR; + } else { + /* unblock SME queue, but do not send rsp to HDD */ + pe_msg.bodyval = true; + } + + pe_msg.type = SIR_HAL_NDP_INITIATOR_RSP; + pe_msg.bodyptr = &ndp_rsp; + return wma_handle->pe_ndp_event_handler(wma_handle->mac_context, + &pe_msg); } /** @@ -92,12 +212,78 @@ QDF_STATUS wma_handle_ndp_sched_update_req(tp_wma_handle wma_handle, * Handler for WMI_NDP_INDICATION_EVENTID * Return: 0 on success, negative errno on failure */ -static int wma_ndp_indication_event_handler(void *handle, - uint8_t *event_info, uint32_t len) +static int wma_ndp_indication_event_handler(void *handle, uint8_t *event_info, + uint32_t len) { - return 0; + WMI_NDP_INDICATION_EVENTID_param_tlvs *event; + wmi_ndp_indication_event_fixed_param *fixed_params; + cds_msg_t pe_msg = {0}; + struct ndp_indication_event ind_event = {0}; + tp_wma_handle wma_handle = handle; + + event = (WMI_NDP_INDICATION_EVENTID_param_tlvs *)event_info; + fixed_params = + (wmi_ndp_indication_event_fixed_param *)event->fixed_param; + + WMA_LOGD(FL("WMI_NDP_INDICATION_EVENTID(0x%X) received. vdev %d, service_instance %d, ndp_instance %d, role %d, policy %d"), + WMI_NDP_INDICATION_EVENTID, fixed_params->vdev_id, + fixed_params->service_instance_id, + fixed_params->ndp_instance_id, fixed_params->self_ndp_role, + fixed_params->accept_policy); + + WMA_LOGD(FL("ndp_cfg - %d bytes"), fixed_params->ndp_cfg_len); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + &event->ndp_cfg, fixed_params->ndp_cfg_len); + + WMA_LOGD(FL("ndp_app_info - %d bytes"), fixed_params->ndp_app_info_len); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + &event->ndp_app_info, fixed_params->ndp_app_info_len); + + ind_event.vdev_id = fixed_params->vdev_id; + ind_event.service_instance_id = fixed_params->service_instance_id; + ind_event.ndp_instance_id = fixed_params->ndp_instance_id; + ind_event.role = fixed_params->self_ndp_role; + ind_event.policy = fixed_params->accept_policy; + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, + ind_event.peer_mac_addr.bytes); + WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_discovery_mac_addr, + ind_event.peer_discovery_mac_addr.bytes); + + ind_event.ndp_config.ndp_cfg_len = fixed_params->ndp_cfg_len; + ind_event.ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len; + + if (ind_event.ndp_config.ndp_cfg_len) { + ind_event.ndp_config.ndp_cfg = + qdf_mem_malloc(fixed_params->ndp_cfg_len); + if (NULL == ind_event.ndp_config.ndp_cfg) { + WMA_LOGE(FL("malloc failed")); + return QDF_STATUS_E_NOMEM; + } + qdf_mem_copy(ind_event.ndp_config.ndp_cfg, event->ndp_cfg, + ind_event.ndp_config.ndp_cfg_len); + } + + if (ind_event.ndp_info.ndp_app_info_len) { + ind_event.ndp_info.ndp_app_info = + qdf_mem_malloc(ind_event.ndp_info.ndp_app_info_len); + if (NULL == ind_event.ndp_info.ndp_app_info) { + WMA_LOGE(FL("malloc failed")); + qdf_mem_free(ind_event.ndp_config.ndp_cfg); + return QDF_STATUS_E_NOMEM; + } + qdf_mem_copy(ind_event.ndp_info.ndp_app_info, + event->ndp_app_info, + ind_event.ndp_info.ndp_app_info_len); + } + pe_msg.type = SIR_HAL_NDP_INDICATION; + pe_msg.bodyptr = &ind_event; + pe_msg.bodyval = 0; + return wma_handle->pe_ndp_event_handler(wma_handle->mac_context, + &pe_msg); } + /** * wma_ndp_responder_rsp_event_handler() - NDP responder response event handler * @handle: wma handle @@ -122,10 +308,70 @@ static int wma_ndp_responder_rsp_event_handler(void *handle, * Handler for WMI_NDP_CONFIRM_EVENTID * Return: 0 on success, negative errno on failure */ -static int wma_ndp_confirm_event_handler(void *handle, - uint8_t *event_info, uint32_t len) +static int wma_ndp_confirm_event_handler(void *handle, uint8_t *event_info, + uint32_t len) { - return 0; + struct ndp_confirm_event ndp_confirm = {0}; + cds_msg_t msg = {0}; + WMI_NDP_CONFIRM_EVENTID_param_tlvs *event; + wmi_ndp_confirm_event_fixed_param *fixed_params; + tp_wma_handle wma_handle = handle; + + event = (WMI_NDP_CONFIRM_EVENTID_param_tlvs *) event_info; + fixed_params = (wmi_ndp_confirm_event_fixed_param *)event->fixed_param; + WMA_LOGE(FL("WMI_NDP_CONFIRM_EVENTID(0x%X) recieved. vdev %d, ndp_instance %d, rsp_code %d"), + WMI_NDP_CONFIRM_EVENTID, fixed_params->vdev_id, + fixed_params->ndp_instance_id, fixed_params->rsp_code); + + WMA_LOGE(FL("ndp_cfg - %d bytes"), fixed_params->ndp_cfg_len); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + &event->ndp_cfg, fixed_params->ndp_cfg_len); + + WMA_LOGE(FL("ndp_app_info - %d bytes"), fixed_params->ndp_app_info_len); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, + &event->ndp_app_info, fixed_params->ndp_app_info_len); + + ndp_confirm.vdev_id = fixed_params->vdev_id; + ndp_confirm.ndp_instance_id = fixed_params->ndp_instance_id; + ndp_confirm.rsp_code = fixed_params->rsp_code; + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, + ndp_confirm.peer_ndi_mac_addr.bytes); + + qdf_mem_copy(&ndp_confirm.ndp_config, event->ndp_cfg, + fixed_params->ndp_cfg_len); + + ndp_confirm.ndp_config.ndp_cfg_len = fixed_params->ndp_cfg_len; + ndp_confirm.ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len; + + if (ndp_confirm.ndp_config.ndp_cfg_len) { + ndp_confirm.ndp_config.ndp_cfg = + qdf_mem_malloc(ndp_confirm.ndp_config.ndp_cfg_len); + if (NULL == ndp_confirm.ndp_config.ndp_cfg) { + WMA_LOGE(FL("malloc failed")); + return QDF_STATUS_E_NOMEM; + } + qdf_mem_copy(ndp_confirm.ndp_config.ndp_cfg, + event->ndp_cfg, + ndp_confirm.ndp_config.ndp_cfg_len); + } + + if (ndp_confirm.ndp_info.ndp_app_info_len) { + ndp_confirm.ndp_info.ndp_app_info = + qdf_mem_malloc(fixed_params->ndp_app_info_len); + if (NULL == ndp_confirm.ndp_info.ndp_app_info) { + WMA_LOGE(FL("malloc failed")); + qdf_mem_free(ndp_confirm.ndp_config.ndp_cfg); + return QDF_STATUS_E_NOMEM; + } + qdf_mem_copy(&ndp_confirm.ndp_info.ndp_app_info, + event->ndp_app_info, + ndp_confirm.ndp_info.ndp_app_info_len); + } + msg.type = SIR_HAL_NDP_CONFIRM; + msg.bodyptr = &ndp_confirm; + msg.bodyval = 0; + return wma_handle->pe_ndp_event_handler(wma_handle->mac_context, &msg); } /** @@ -170,7 +416,24 @@ static int wma_ndp_end_indication_event_handler(void *handle, static int wma_ndp_initiator_rsp_event_handler(void *handle, uint8_t *event_info, uint32_t len) { - return 0; + cds_msg_t pe_msg = {0}; + WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *event; + wmi_ndp_initiator_rsp_event_fixed_param *fixed_params; + struct ndp_initiator_rsp ndp_rsp = {0}; + tp_wma_handle wma_handle = handle; + + event = (WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *)event_info; + fixed_params = event->fixed_param; + + ndp_rsp.vdev_id = fixed_params->vdev_id; + ndp_rsp.transaction_id = fixed_params->transaction_id; + ndp_rsp.ndp_instance_id = fixed_params->ndp_instance_id; + ndp_rsp.status = fixed_params->rsp_status; + + pe_msg.type = SIR_HAL_NDP_INITIATOR_RSP; + pe_msg.bodyptr = &ndp_rsp; + return wma_handle->pe_ndp_event_handler(wma_handle->mac_context, + &pe_msg); } /** @@ -551,7 +814,7 @@ void wma_delete_all_nan_remote_peers(tp_wma_handle wma, uint32_t vdev_id) * Return: Success or Failure Status */ QDF_STATUS wma_register_ndp_cb(QDF_STATUS (*pe_ndp_event_handler) - (tpAniSirGlobal mac_ctx, tpSirMsgQ msg)) + (tpAniSirGlobal mac_ctx, cds_msg_t *msg)) { tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); @@ -565,3 +828,95 @@ QDF_STATUS wma_register_ndp_cb(QDF_STATUS (*pe_ndp_event_handler) return QDF_STATUS_SUCCESS; } +/** + * wma_add_sta_ndi_mode() - Process ADD_STA for NaN Data path + * @wma: wma handle + * @add_sta: Parameters of ADD_STA command + * + * Sends CREATE_PEER command to firmware + * Return: void + */ +void wma_add_sta_ndi_mode(tp_wma_handle wma, tpAddStaParams add_sta) +{ + enum ol_txrx_peer_state state = OL_TXRX_PEER_STATE_CONN; + ol_txrx_pdev_handle pdev; + ol_txrx_vdev_handle vdev; + ol_txrx_peer_handle peer; + u_int8_t peer_id; + QDF_STATUS status; + struct wma_txrx_node *iface; + + pdev = cds_get_context(QDF_MODULE_ID_TXRX); + + if (NULL == pdev) { + WMA_LOGE(FL("Failed to find pdev")); + add_sta->status = QDF_STATUS_E_FAILURE; + goto send_rsp; + } + + vdev = wma_find_vdev_by_id(wma, add_sta->smesessionId); + if (!vdev) { + WMA_LOGE(FL("Failed to find vdev")); + add_sta->status = QDF_STATUS_E_FAILURE; + goto send_rsp; + } + + iface = &wma->interfaces[vdev->vdev_id]; + WMA_LOGD(FL("vdev: %d, peer_mac_addr: "MAC_ADDRESS_STR), + add_sta->smesessionId, MAC_ADDR_ARRAY(add_sta->staMac)); + + peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, add_sta->staMac, + &peer_id); + if (peer) { + WMA_LOGE(FL("NDI peer already exists, peer_addr %pM"), + add_sta->staMac); + add_sta->status = QDF_STATUS_E_EXISTS; + goto send_rsp; + } + + /* + * The code above only checks the peer existence on its own vdev. + * Need to check whether the peer exists on other vDevs because firmware + * can't create the peer if the peer with same MAC address already + * exists on the pDev. As this peer belongs to other vDevs, just return + * here. + */ + peer = ol_txrx_find_peer_by_addr(pdev, add_sta->staMac, &peer_id); + if (peer) { + WMA_LOGE(FL("vdev:%d, peer exists on other vdev with peer_addr %pM and peer_id %d"), + vdev->vdev_id, add_sta->staMac, peer_id); + add_sta->status = QDF_STATUS_E_EXISTS; + goto send_rsp; + } + + status = wma_create_peer(wma, pdev, vdev, add_sta->staMac, + WMI_PEER_TYPE_NAN_DATA, add_sta->smesessionId, + false); + if (status != QDF_STATUS_SUCCESS) { + WMA_LOGE(FL("Failed to create peer for %pM"), add_sta->staMac); + add_sta->status = status; + goto send_rsp; + } + + peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, add_sta->staMac, + &peer_id); + if (!peer) { + WMA_LOGE(FL("Failed to find peer handle using peer mac %pM"), + add_sta->staMac); + add_sta->status = QDF_STATUS_E_FAILURE; + wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, + peer, false); + goto send_rsp; + } + + WMA_LOGD(FL("Moving peer %pM to state %d"), add_sta->staMac, state); + ol_txrx_peer_state_update(pdev, add_sta->staMac, state); + + add_sta->staIdx = ol_txrx_local_peer_id(peer); + add_sta->nss = iface->nss; + add_sta->status = QDF_STATUS_SUCCESS; +send_rsp: + WMA_LOGD(FL("Sending add sta rsp to umac (mac:%pM, status:%d)"), + add_sta->staMac, add_sta->status); + wma_send_msg(wma, WMA_ADD_STA_RSP, (void *)add_sta, 0); +} diff --git a/core/wma/src/wma_nan_datapath.h b/core/wma/src/wma_nan_datapath.h index b230a10d49c8..f498a7ffd634 100644 --- a/core/wma/src/wma_nan_datapath.h +++ b/core/wma/src/wma_nan_datapath.h @@ -29,13 +29,11 @@ #include "wma.h" #include "sir_api.h" +#include "sme_nan_datapath.h" #ifdef WLAN_FEATURE_NAN_DATAPATH #define WMA_IS_VDEV_IN_NDI_MODE(intf, vdev_id) \ (WMI_VDEV_TYPE_NDI == intf[vdev_id].type) - -void wma_add_bss_ndi_mode(tp_wma_handle wma, tpAddBssParams add_bss); - /** * wma_update_hdd_cfg_ndp() - Update target device NAN datapath capability * @wma_handle: pointer to WMA context @@ -56,6 +54,9 @@ void wma_ndp_unregister_all_event_handlers(tp_wma_handle wma_handle); void wma_ndp_add_wow_wakeup_event(tp_wma_handle wma_handle, uint8_t vdev_id); void wma_ndp_wow_event_callback(void *handle, void *event, uint32_t len); +void wma_add_bss_ndi_mode(tp_wma_handle wma, tpAddBssParams add_bss); +void wma_add_sta_ndi_mode(tp_wma_handle wma, tpAddStaParams add_sta); +QDF_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle, void *req); #else #define WMA_IS_VDEV_IN_NDI_MODE(intf, vdev_id) (false) static inline void wma_update_hdd_cfg_ndp(tp_wma_handle wma_handle, @@ -80,5 +81,13 @@ static inline void wma_ndp_add_wow_wakeup_event(tp_wma_handle wma_handle, uint8_t vdev_id) {} static inline void wma_ndp_wow_event_callback(void *handle, void *event, uint32_t len) {} +static inline void wma_add_sta_ndi_mode(tp_wma_handle wma, + tpAddStaParams add_sta) {} +static inline QDF_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle, + void *req) +{ + return QDF_STATUS_SUCCESS; +} + #endif /* WLAN_FEATURE_NAN_DATAPATH */ #endif /* __WMA_NAN_DATAPATH_H */