Procházet zdrojové kódy

qcacmn: NDP_RESPONDER_REQ implementation

Add implementation for NDP_RESPONDER_REQ.

Change-Id: I27029eae88e0bc545c8444adf1342b2ec95f4d60
CRs-Fixed: 2014795
Naveen Rawat před 8 roky
rodič
revize
f2bc82eb18

+ 203 - 0
os_if/linux/nan/src/os_if_nan.c

@@ -310,6 +310,138 @@ initiator_req_failed:
 	return ret;
 }
 
+/**
+ * os_if_nan_process_ndp_responder_req() - NDP responder request handler
+ * @nan_ctx: hdd context
+ * @tb: parsed NL attribute list
+ *
+ * tb includes following vendor attributes:
+ * QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR
+ * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID
+ * QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID
+ * QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE
+ * QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO - optional
+ * QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS - optional
+ * QCA_WLAN_VENDOR_ATTR_NDP_PMK - optional
+ * QCA_WLAN_VENDOR_ATTR_NDP_NCS_SK_TYPE - optional
+ *
+ * Return: 0 on success or error code on failure
+ */
+static int os_if_nan_process_ndp_responder_req(struct wlan_objmgr_psoc *psoc,
+					       struct nlattr **tb)
+{
+	int ret = 0;
+	char *iface_name;
+	QDF_STATUS status;
+	uint32_t ndp_qos_cfg;
+	enum nan_datapath_state state;
+	struct wlan_objmgr_vdev *nan_vdev;
+	struct nan_datapath_responder_req req = {0};
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) {
+		cfg80211_err("Interface name string is unavailable");
+		return -EINVAL;
+	}
+
+	iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]);
+	/* Check if there is already an existing NAN interface */
+	nan_vdev = ucfg_nan_get_ndi_vdev(psoc, WLAN_NAN_ID);
+	if (!nan_vdev) {
+		cfg80211_err("NAN data interface %s not available", iface_name);
+		return -EINVAL;
+	}
+
+	state = ucfg_nan_get_ndi_state(nan_vdev);
+	if (state == NAN_DATA_NDI_DELETED_STATE ||
+	    state == NAN_DATA_NDI_DELETING_STATE ||
+	    state == NAN_DATA_NDI_CREATING_STATE) {
+		cfg80211_err("Data request not allowed in current NDI state:%d",
+			state);
+		ret = -EAGAIN;
+		goto responder_req_failed;
+	}
+
+	req.vdev = nan_vdev;
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) {
+		cfg80211_err("Transaction ID is unavailable");
+		ret = -EINVAL;
+		goto responder_req_failed;
+	}
+	req.transaction_id =
+		nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID]) {
+		cfg80211_err("Instance ID is unavailable");
+		ret = -EINVAL;
+		goto responder_req_failed;
+	}
+	req.ndp_instance_id =
+		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID]);
+
+	if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]) {
+		cfg80211_err("ndp_rsp is unavailable");
+		ret = -EINVAL;
+		goto responder_req_failed;
+	}
+	req.ndp_rsp = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE]);
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]) {
+		req.ndp_info.ndp_app_info_len =
+			nla_len(tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]);
+		if (req.ndp_info.ndp_app_info_len) {
+			req.ndp_info.ndp_app_info =
+				nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO]);
+		}
+	} else {
+		cfg80211_debug("NDP app info is unavailable");
+	}
+	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;
+		ndp_qos_cfg =
+			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS]);
+		req.ndp_config.ndp_cfg = (uint8_t *)&ndp_qos_cfg;
+	} else {
+		cfg80211_debug("NDP config data is unavailable");
+	}
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_NDP_NCS_SK_TYPE] &&
+		!tb[QCA_WLAN_VENDOR_ATTR_NDP_PMK]) {
+		cfg80211_err("PMK cannot be absent when CSID is present.");
+		ret = -EINVAL;
+		goto responder_req_failed;
+	}
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_NDP_PMK]) {
+		req.pmk.pmk = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_PMK]);
+		req.pmk.pmk_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_NDP_PMK]);
+		QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD,
+				QDF_TRACE_LEVEL_DEBUG,
+				req.pmk.pmk, req.pmk.pmk_len);
+	}
+
+	if (tb[QCA_WLAN_VENDOR_ATTR_NDP_NCS_SK_TYPE]) {
+		req.ncs_sk_type =
+			nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_NCS_SK_TYPE]);
+
+	}
+
+	cfg80211_debug("vdev_id: %d, transaction_id: %d, ndp_rsp %d, ndp_instance_id: %d, ndp_app_info_len: %d, csid: %d",
+		wlan_vdev_get_id(nan_vdev), req.transaction_id, req.ndp_rsp,
+		req.ndp_instance_id, req.ndp_info.ndp_app_info_len,
+		req.ncs_sk_type);
+
+	status = ucfg_nan_req_processor(nan_vdev, &req, NDP_RESPONDER_REQ);
+	ret = qdf_status_to_os_return(status);
+
+responder_req_failed:
+	wlan_objmgr_vdev_release_ref(nan_vdev, WLAN_NAN_ID);
+
+	return ret;
+
+}
+
 int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc,
 			      const void *data, int data_len)
 {
@@ -355,6 +487,8 @@ int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc,
 		return os_if_nan_process_ndi_delete(psoc, tb);
 	case QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST:
 		return os_if_nan_process_ndp_initiator_req(psoc, tb);
+	case QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST:
+		return os_if_nan_process_ndp_responder_req(psoc, tb);
 	default:
 		cfg80211_err("Unrecognized NDP vendor cmd %d", ndp_cmd_type);
 		return -EINVAL;
@@ -433,6 +567,72 @@ ndp_initiator_rsp_nla_failed:
 	kfree_skb(vendor_event);
 }
 
+
+/*
+ * os_if_ndp_responder_rsp_handler() - NDP responder response handler
+ * @vdev: pointer to vdev object
+ * @rsp: response parameters
+ *
+ * Following vendor event is sent to cfg80211:
+ * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD =
+ *         QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_RESPONSE (4 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE (4 bytes)
+ * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE (4 bytes)
+ *
+ * Return: none
+ */
+static void os_if_ndp_responder_rsp_handler(struct wlan_objmgr_vdev *vdev,
+				      struct nan_datapath_responder_rsp *rsp)
+{
+	uint16_t data_len;
+	struct sk_buff *vendor_event;
+	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
+	struct pdev_osif_priv *os_priv = wlan_pdev_get_ospriv(pdev);
+
+	if (!rsp) {
+		cfg80211_err("Invalid NDP Responder response");
+		return;
+	}
+
+	cfg80211_debug("NDP Responder,vdev id %d transaction_id %d status code: %d reason %d",
+		wlan_vdev_get_id(rsp->vdev), rsp->transaction_id,
+		rsp->status, rsp->reason);
+	data_len = 3 * sizeof(uint32_t) + sizeof(uint16_t) +
+		4 * NLA_HDRLEN + NLMSG_HDRLEN;
+	vendor_event = cfg80211_vendor_event_alloc(os_priv->wiphy, NULL,
+				data_len, QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX,
+				GFP_ATOMIC);
+	if (!vendor_event) {
+		cfg80211_err("cfg80211_vendor_event_alloc failed");
+		return;
+	}
+
+	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD,
+	   QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_RESPONSE))
+		goto ndp_responder_rsp_nla_failed;
+
+	if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID,
+	   rsp->transaction_id))
+		goto ndp_responder_rsp_nla_failed;
+
+	if (nla_put_u32(vendor_event,
+			QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE,
+	   rsp->status))
+		goto ndp_responder_rsp_nla_failed;
+
+	if (nla_put_u32(vendor_event,
+	   QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE,
+	   rsp->reason))
+		goto ndp_responder_rsp_nla_failed;
+
+	cfg80211_vendor_event(vendor_event, GFP_ATOMIC);
+	return;
+ndp_responder_rsp_nla_failed:
+	cfg80211_err("nla_put api failed");
+	kfree_skb(vendor_event);
+}
+
 /**
  * os_if_ndp_indication_handler() - NDP indication handler
  * @vdev: pointer to vdev object
@@ -911,6 +1111,9 @@ void os_if_nan_event_handler(struct wlan_objmgr_psoc *psoc,
 	case NDP_NEW_PEER:
 		os_if_new_peer_ind_handler(vdev, msg);
 		break;
+	case NDP_RESPONDER_RSP:
+		os_if_ndp_responder_rsp_handler(vdev, msg);
+		break;
 	default:
 		break;
 	}

+ 234 - 0
target_if/nan/src/target_if_nan.c

@@ -49,6 +49,11 @@ static QDF_STATUS target_if_nan_event_dispatcher(struct scheduler_msg *msg)
 		vdev = confirm->vdev;
 		break;
 	}
+	case NDP_RESPONDER_RSP: {
+		struct nan_datapath_responder_rsp *rsp = msg->bodyptr;
+		vdev = rsp->vdev;
+		break;
+	}
 	default:
 		target_if_err("invalid msg type %d", msg->type);
 		qdf_mem_free(msg->bodyptr);
@@ -516,6 +521,215 @@ static int target_if_ndp_confirm_handler(ol_scn_t scn, uint8_t *data,
 	return 0;
 }
 
+static QDF_STATUS target_if_nan_ndp_responder_req(
+				struct nan_datapath_responder_req *req)
+{
+	int ret;
+	uint16_t len;
+	wmi_buf_t buf;
+	uint8_t *tlv_ptr;
+	QDF_STATUS status;
+	wmi_unified_t wmi_handle;
+	struct wlan_objmgr_psoc *psoc;
+	struct scheduler_msg pe_msg = {0};
+	wmi_ndp_responder_req_fixed_param *cmd;
+	struct wlan_lmac_if_nan_rx_ops *nan_rx_ops;
+	struct nan_datapath_responder_rsp rsp = {0};
+	uint32_t vdev_id = 0, ndp_cfg_len, ndp_app_info_len, pmk_len;
+
+	if (!req) {
+		target_if_err("Invalid req.");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc = wlan_vdev_get_psoc(req->vdev);
+	if (!psoc) {
+		target_if_err("psoc is null.");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
+	if (!wmi_handle) {
+		target_if_err("wmi_handle is null.");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	nan_rx_ops = target_if_nan_get_rx_ops(psoc);
+	if (!nan_rx_ops) {
+		target_if_err("nan_rx_ops is null.");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	vdev_id = wlan_vdev_get_id(req->vdev);
+	target_if_debug("vdev_id: %d, transaction_id: %d, ndp_rsp %d, ndp_instance_id: %d, ndp_app_info_len: %d",
+			vdev_id, req->transaction_id,
+			req->ndp_rsp,
+			req->ndp_instance_id,
+			req->ndp_info.ndp_app_info_len);
+
+	/*
+	 * WMI command expects 4 byte alligned len:
+	 * round up ndp_cfg_len and ndp_app_info_len to 4 bytes
+	 */
+	ndp_cfg_len = qdf_roundup(req->ndp_config.ndp_cfg_len, 4);
+	ndp_app_info_len = qdf_roundup(req->ndp_info.ndp_app_info_len, 4);
+	pmk_len = qdf_roundup(req->pmk.pmk_len, 4);
+	/* allocated memory for fixed params as well as variable size data */
+	len = sizeof(*cmd) + 3*WMI_TLV_HDR_SIZE + ndp_cfg_len + ndp_app_info_len
+		+ pmk_len;
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf) {
+		target_if_err("wmi_buf_alloc failed");
+		status = QDF_STATUS_E_NOMEM;
+		goto send_ndp_responder_fail;
+	}
+	cmd = (wmi_ndp_responder_req_fixed_param *) wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+			WMITLV_TAG_STRUC_wmi_ndp_responder_req_fixed_param,
+			WMITLV_GET_STRUCT_TLVLEN(
+				wmi_ndp_responder_req_fixed_param));
+	cmd->vdev_id = vdev_id;
+	cmd->transaction_id = req->transaction_id;
+	cmd->ndp_instance_id = req->ndp_instance_id;
+	cmd->rsp_code = req->ndp_rsp;
+	cmd->ndp_cfg_len = req->ndp_config.ndp_cfg_len;
+	cmd->ndp_app_info_len = req->ndp_info.ndp_app_info_len;
+	cmd->nan_pmk_len = req->pmk.pmk_len;
+	cmd->nan_csid = req->ncs_sk_type;
+
+	tlv_ptr = (uint8_t *)&cmd[1];
+	WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len);
+	qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
+		req->ndp_config.ndp_cfg, cmd->ndp_cfg_len);
+
+	tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len;
+	WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len);
+	qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
+		     req->ndp_info.ndp_app_info,
+		     req->ndp_info.ndp_app_info_len);
+
+	tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len;
+	WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len);
+	qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], req->pmk.pmk,
+		     cmd->nan_pmk_len);
+
+	tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len;
+	target_if_debug("vdev_id = %d, transaction_id: %d, csid: %d",
+		cmd->vdev_id, cmd->transaction_id, cmd->nan_csid);
+
+	target_if_debug("ndp_config len: %d",
+		req->ndp_config.ndp_cfg_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+			req->ndp_config.ndp_cfg,
+			req->ndp_config.ndp_cfg_len);
+
+	target_if_debug("ndp_app_info len: %d",
+		req->ndp_info.ndp_app_info_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+			req->ndp_info.ndp_app_info,
+			req->ndp_info.ndp_app_info_len);
+
+	target_if_debug("pmk len: %d", cmd->nan_pmk_len);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+			   req->pmk.pmk, cmd->nan_pmk_len);
+
+	target_if_debug("sending WMI_NDP_RESPONDER_REQ_CMDID(0x%X)",
+		WMI_NDP_RESPONDER_REQ_CMDID);
+	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+				   WMI_NDP_RESPONDER_REQ_CMDID);
+	if (ret < 0) {
+		target_if_err("WMI_NDP_RESPONDER_REQ_CMDID failed, ret: %d",
+				ret);
+		wmi_buf_free(buf);
+		status = QDF_STATUS_E_FAILURE;
+		goto send_ndp_responder_fail;
+	}
+	return QDF_STATUS_SUCCESS;
+
+send_ndp_responder_fail:
+	rsp.vdev = req->vdev;
+	rsp.transaction_id = req->transaction_id;
+	rsp.status = NAN_DATAPATH_RSP_STATUS_ERROR;
+	rsp.reason = NAN_DATAPATH_DATA_RESPONDER_REQ_FAILED;
+	pe_msg.bodyptr = &rsp;
+	pe_msg.type = NDP_RESPONDER_RSP;
+	if (nan_rx_ops && nan_rx_ops->nan_event_rx)
+		nan_rx_ops->nan_event_rx(&pe_msg);
+
+	return status;
+}
+
+static int target_if_ndp_responder_rsp_handler(ol_scn_t scn, uint8_t *data,
+						uint32_t len)
+{
+	QDF_STATUS status;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_vdev *vdev;
+	struct scheduler_msg msg = {0};
+	struct wlan_lmac_if_nan_rx_ops *nan_rx_ops;
+	struct nan_datapath_responder_rsp *rsp;
+	WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *event;
+	wmi_ndp_responder_rsp_event_fixed_param  *fixed_params;
+
+	psoc = target_if_get_psoc_from_scn_hdl(scn);
+	if (!psoc) {
+		target_if_err("psoc is null");
+		return -EINVAL;
+	}
+
+	nan_rx_ops = target_if_nan_get_rx_ops(psoc);
+	/* process even here and call callback */
+	if (!nan_rx_ops || !nan_rx_ops->nan_event_rx) {
+		target_if_err("lmac callbacks not registered");
+		return -EINVAL;
+	}
+
+	event = (WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *)data;
+	fixed_params = event->fixed_param;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+					fixed_params->vdev_id, WLAN_NAN_ID);
+	if (!vdev) {
+		target_if_err("vdev is null");
+		return -EINVAL;
+	}
+
+	rsp = qdf_mem_malloc(sizeof(*rsp));
+	if (!rsp) {
+		target_if_err("malloc failed");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_NAN_ID);
+		return -ENOMEM;
+	}
+
+	rsp->vdev = vdev;
+	rsp->transaction_id = fixed_params->transaction_id;
+	rsp->reason = fixed_params->reason_code;
+	rsp->status = fixed_params->rsp_status;
+	rsp->create_peer = fixed_params->create_peer;
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
+				rsp->peer_mac_addr.bytes);
+
+	target_if_debug("WMI_NDP_RESPONDER_RSP_EVENTID(0x%X) received. vdev_id: %d, peer_mac_addr: %pM,transaction_id: %d, status_code %d, reason_code: %d, create_peer: %d",
+			WMI_NDP_RESPONDER_RSP_EVENTID, fixed_params->vdev_id,
+			rsp->peer_mac_addr.bytes, rsp->transaction_id,
+			rsp->status, rsp->reason, rsp->create_peer);
+	msg.bodyptr = rsp;
+	msg.type = NDP_RESPONDER_RSP;
+	msg.callback = target_if_nan_event_dispatcher;
+
+	target_if_debug("NDP_INITIATOR_RSP sent: %d", msg.type);
+	status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_NAN_ID);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		target_if_err("failed to post msg, status: %d", status);
+		qdf_mem_free(rsp);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static QDF_STATUS target_if_nan_req(void *req, uint32_t req_type)
 {
 	/* send cmd to fw */
@@ -523,6 +737,9 @@ static QDF_STATUS target_if_nan_req(void *req, uint32_t req_type)
 	case NDP_INITIATOR_REQ:
 		target_if_nan_ndp_intiaitor_req(req);
 		break;
+	case NDP_RESPONDER_REQ:
+		target_if_nan_ndp_responder_req(req);
+		break;
 	default:
 		target_if_err("invalid req type");
 		break;
@@ -596,6 +813,16 @@ QDF_STATUS target_if_nan_register_events(struct wlan_objmgr_psoc *psoc)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	ret = wmi_unified_register_event_handler(handle,
+		WMI_NDP_RESPONDER_RSP_EVENTID,
+		target_if_ndp_responder_rsp_handler,
+		WMI_RX_UMAC_CTX);
+	if (ret) {
+		target_if_err("wmi event registration failed, ret: %d", ret);
+		target_if_nan_deregister_events(psoc);
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -625,6 +852,13 @@ QDF_STATUS target_if_nan_deregister_events(struct wlan_objmgr_psoc *psoc)
 		status = ret;
 	}
 
+	ret = wmi_unified_unregister_event_handler(handle,
+				WMI_NDP_RESPONDER_RSP_EVENTID);
+	if (ret) {
+		target_if_err("wmi event deregistration failed, ret: %d", ret);
+		status = ret;
+	}
+
 	if (status)
 		return QDF_STATUS_E_FAILURE;
 	else

+ 41 - 0
umac/nan/core/src/nan_main.c

@@ -377,6 +377,42 @@ ndp_indication_failed:
 	return status;
 }
 
+static QDF_STATUS nan_handle_responder_rsp(
+				struct nan_datapath_responder_rsp *rsp,
+				struct wlan_objmgr_vdev **vdev)
+{
+	struct wlan_objmgr_psoc *psoc;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct nan_psoc_priv_obj *psoc_nan_obj;
+
+	*vdev = rsp->vdev;
+	psoc = wlan_vdev_get_psoc(rsp->vdev);
+	if (!psoc) {
+		nan_err("psoc is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	psoc_nan_obj = nan_get_psoc_priv_obj(psoc);
+	if (!psoc_nan_obj) {
+		nan_err("psoc_nan_obj is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (QDF_IS_STATUS_SUCCESS(rsp->status) && rsp->create_peer == true) {
+		status = psoc_nan_obj->cb_obj.add_ndi_peer(
+						wlan_vdev_get_id(rsp->vdev),
+						rsp->peer_mac_addr);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			nan_err("Couldn't add ndi peer");
+			rsp->status = QDF_STATUS_E_FAILURE;
+		}
+	}
+	psoc_nan_obj->cb_obj.os_if_event_handler(psoc, rsp->vdev,
+						 NDP_RESPONDER_RSP, rsp);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS nan_event_handler(struct scheduler_msg *pe_msg)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -407,6 +443,11 @@ QDF_STATUS nan_event_handler(struct scheduler_msg *pe_msg)
 		nan_handle_ndp_ind(pe_msg->bodyptr);
 		break;
 	}
+	case NDP_RESPONDER_RSP:
+		nan_handle_responder_rsp(pe_msg->bodyptr, &cmd.vdev);
+		cmd.cmd_type = WLAN_SER_CMD_NDP_RESP_REQ;
+		wlan_serialization_remove_cmd(&cmd);
+		break;
 	default:
 		nan_alert("Unhandled NDP event: %d", pe_msg->type);
 		status = QDF_STATUS_E_NOSUPPORT;

+ 62 - 0
umac/nan/dispatcher/src/nan_ucfg_api.c

@@ -381,6 +381,65 @@ free_resources:
 	return NULL;
 }
 
+static struct nan_datapath_responder_req *ucfg_nan_copy_responder_req(
+				struct wlan_objmgr_vdev *vdev,
+				struct nan_datapath_responder_req *in_req)
+{
+	struct nan_datapath_responder_req *req;
+
+	req = qdf_mem_malloc(sizeof(*req));
+	if (!req) {
+		nan_alert("malloc failed");
+		return NULL;
+	}
+
+	qdf_mem_copy(req, in_req, sizeof(*req));
+	if (in_req->ndp_config.ndp_cfg_len) {
+		req->ndp_config.ndp_cfg =
+			qdf_mem_malloc(in_req->ndp_config.ndp_cfg_len);
+		if (!req->ndp_config.ndp_cfg) {
+			nan_alert("malloc failed");
+			goto free_resources;
+		}
+		qdf_mem_copy(req->ndp_config.ndp_cfg,
+			     in_req->ndp_config.ndp_cfg,
+			     in_req->ndp_config.ndp_cfg_len);
+	}
+
+	if (in_req->ndp_info.ndp_app_info_len) {
+		req->ndp_info.ndp_app_info =
+			qdf_mem_malloc(in_req->ndp_info.ndp_app_info_len);
+		if (!req->ndp_info.ndp_app_info) {
+			nan_alert("malloc failed");
+			goto free_resources;
+		}
+		qdf_mem_copy(req->ndp_info.ndp_app_info,
+			     in_req->ndp_info.ndp_app_info,
+			     in_req->ndp_info.ndp_app_info_len);
+	}
+
+	if (in_req->pmk.pmk_len) {
+		req->pmk.pmk = qdf_mem_malloc(in_req->pmk.pmk_len);
+		if (!req->pmk.pmk) {
+			nan_alert("malloc failed");
+			goto free_resources;
+		}
+		qdf_mem_copy(req->pmk.pmk, in_req->pmk.pmk,
+				in_req->pmk.pmk_len);
+	}
+
+	/* do not get ref here, rather take ref when request is activated */
+	req->vdev = vdev;
+	return req;
+
+free_resources:
+	qdf_mem_free(req->pmk.pmk);
+	qdf_mem_free(req->ndp_info.ndp_app_info);
+	qdf_mem_free(req->ndp_config.ndp_cfg);
+	qdf_mem_free(req);
+	return NULL;
+}
+
 QDF_STATUS ucfg_nan_req_processor(struct wlan_objmgr_vdev *vdev,
 				  void *in_req, uint32_t req_type)
 {
@@ -397,6 +456,9 @@ QDF_STATUS ucfg_nan_req_processor(struct wlan_objmgr_vdev *vdev,
 	case NDP_INITIATOR_REQ:
 		req = ucfg_nan_copy_intiator_req(vdev, in_req);
 		break;
+	case NDP_RESPONDER_REQ:
+		req = ucfg_nan_copy_responder_req(vdev, in_req);
+		break;
 	default:
 		nan_err("in correct message req type: %d", req_type);
 		return QDF_STATUS_E_INVAL;