+ dev_ndp = slsi_get_netdev_locked(sdev, if_idx);
+ err = slsi_netif_register_locked(sdev, dev_ndp);
+ if (err) {
+ SLSI_ERR(sdev, "NAN fail netdev err:%d if_name:%s, if_idx:%d\n", err);
+ ret = WIFI_HAL_ERROR_UNKNOWN;
+ reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ } else {
+ SLSI_INFO(sdev, "trans_id:%d, if_name:%s, if_idx:%d\n", transaction_id, iface_name, if_idx);
+ }
+
+exit_with_lock:
+ SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_INTERFACE_CREATE, 0, NULL, transaction_id);
+ return ret;
+}
+
+int slsi_nan_data_iface_delete(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ u8 *iface_name = NULL;
+ int ret = 0, if_idx, type, tmp;
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct net_device *dev_ndp = NULL;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+ const struct nlattr *iter;
+ u16 transaction_id = 0;
+
+ slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+ if (ret != WIFI_HAL_SUCCESS)
+ goto exit;
+
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ if (type == NAN_REQ_ATTR_DATA_INTERFACE_NAME)
+ iface_name = nla_data(iter);
+ else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
+ transaction_id = nla_get_u16(iter);
+ }
+ if (!iface_name) {
+ SLSI_ERR(sdev, "No NAN data interface name\n");
+ ret = WIFI_HAL_ERROR_INVALID_ARGS;
+ reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex);
+ for (if_idx = SLSI_NAN_DATA_IFINDEX_START; if_idx < CONFIG_SCSC_WLAN_MAX_INTERFACES + 1; if_idx++) {
+ dev_ndp = slsi_get_netdev_locked(sdev, if_idx);
+ if (dev_ndp && strcmp(iface_name, dev_ndp->name) == 0)
+ break;
+ dev_ndp = NULL;
+ }
+
+ if (dev_ndp) {
+ slsi_netif_remove_locked(sdev, dev_ndp);
+ SLSI_INFO(sdev, "Success transId:%d ifaceName:%s\n", transaction_id, iface_name);
+ }
+
+ SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_INTERFACE_DELETE, 0, NULL, transaction_id);
+ return ret;
+}
+
+int slsi_nan_ndp_initiate_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_data_path_initiator_req *hal_req,
+ const void *data, int len)
+{
+ int type, tmp, r;
+ const struct nlattr *iter;
+
+ memset(hal_req, 0, sizeof(*hal_req));
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_REQ_INSTANCE_ID:
+ hal_req->requestor_instance_id = nla_get_u32(iter);
+ break;
+
+ case NAN_REQ_ATTR_CHAN_REQ_TYPE:
+ hal_req->channel_request_type = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_CHAN:
+ hal_req->channel = nla_get_u32(iter);
+ break;
+
+ case NAN_REQ_ATTR_MAC_ADDR_VAL:
+ ether_addr_copy(hal_req->peer_disc_mac_addr, nla_data(iter));
+ break;
+
+ case NAN_REQ_ATTR_DATA_INTERFACE_NAME:
+ memcpy(hal_req->ndp_iface, nla_data(iter), IFNAMSIZ);
+ break;
+
+ case NAN_REQ_ATTR_DATA_INTERFACE_NAME_LEN:
+ break;
+
+ case NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG:
+ hal_req->ndp_cfg.security_cfg = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG:
+ hal_req->ndp_cfg.qos_cfg = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_APP_INFO_LEN:
+ hal_req->app_info.ndp_app_info_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_APP_INFO:
+ memcpy(hal_req->app_info.ndp_app_info, nla_data(iter), hal_req->app_info.ndp_app_info_len);
+ break;
+
+ case NAN_REQ_ATTR_SERVICE_NAME_LEN:
+ hal_req->service_name_len = nla_get_u32(iter);
+ break;
+
+ case NAN_REQ_ATTR_SERVICE_NAME:
+ memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
+ break;
+
+ case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+ hal_req->transaction_id = nla_get_u16(iter);
+ break;
+
+ default:
+ r = slsi_nan_get_security_info_nl(sdev, &hal_req->key_info, iter, type);
+ if (r)
+ SLSI_ERR(sdev, "Unexpected NAN ndp attribute TYPE:%d\n", type);
+ }
+ }
+ return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_ndp_initiate(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ struct slsi_hal_nan_data_path_initiator_req *hal_req = NULL;
+ int ret;
+ u32 ndp_id = 0;
+ u16 ndl_vif_id, transaction_id = 0;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+ slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+ if (ret != WIFI_HAL_SUCCESS)
+ goto exit;
+
+ hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL);
+ if (!hal_req) {
+ SLSI_ERR(sdev, "Failed to alloc hal_req structure!!!\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ ret = WIFI_HAL_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+ reply_status = slsi_nan_ndp_initiate_get_nl_params(sdev, hal_req, data, len);
+ if (reply_status) {
+ ret = WIFI_HAL_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+ transaction_id = hal_req->transaction_id;
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (!ndev_vif->activated) {
+ SLSI_WARN(sdev, "NAN vif not activated\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ goto exit_with_lock;
+ }
+
+ ndp_id = slsi_nan_get_new_ndp_id(ndev_vif);
+ if (!ndp_id) {
+ SLSI_WARN(sdev, "NAN no free ndp slots\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ ret = WIFI_HAL_ERROR_TOO_MANY_REQUESTS;
+ goto exit_with_lock;
+ }
+
+ ndl_vif_id = slsi_nan_ndp_get_ndl_vif_id(hal_req->peer_disc_mac_addr, ndev_vif->nan.ndl_list);
+ if (ndl_vif_id >= SLSI_NAN_MAX_NDP_INSTANCES + SLSI_NAN_DATA_IFINDEX_START) {
+ SLSI_WARN(sdev, "NAN no free ndl slots\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ ret = WIFI_HAL_ERROR_TOO_MANY_REQUESTS;
+ goto exit_with_lock;
+ }
+ ret = slsi_mlme_ndp_request(sdev, dev, hal_req, ndp_id, ndl_vif_id);
+ if (ret) {
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ ret = WIFI_HAL_ERROR_UNKNOWN;
+ } else {
+ SLSI_INFO(sdev, "transId:%d ndpId:%d ndlVifId:%d iface:%s\n",
+ hal_req->transaction_id, ndp_id, ndl_vif_id, hal_req->ndp_iface);
+ ret = WIFI_HAL_SUCCESS;
+ }
+
+exit_with_lock:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_INITIATOR_RESPONSE, (u16)ndp_id, NULL, transaction_id);
+ kfree(hal_req);
+ return ret;
+}
+
+int slsi_nan_ndp_respond_get_nl_param(struct slsi_dev *sdev, struct slsi_hal_nan_data_path_indication_response *hal_req,
+ const void *data, int len)
+{
+ int type, tmp, r;
+ const struct nlattr *iter;
+
+ memset(hal_req, 0, sizeof(*hal_req));
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ switch (type) {
+ case NAN_REQ_ATTR_NDP_INSTANCE_ID:
+ hal_req->ndp_instance_id = nla_get_u32(iter);
+ break;
+
+ case NAN_REQ_ATTR_DATA_INTERFACE_NAME:
+ memcpy(hal_req->ndp_iface, nla_data(iter), IFNAMSIZ);
+ break;
+ case NAN_REQ_ATTR_DATA_INTERFACE_NAME_LEN:
+ break;
+
+ case NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG:
+ hal_req->ndp_cfg.security_cfg = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG:
+ hal_req->ndp_cfg.qos_cfg = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_APP_INFO_LEN:
+ hal_req->app_info.ndp_app_info_len = nla_get_u16(iter);
+ break;
+
+ case NAN_REQ_ATTR_APP_INFO:
+ memcpy(hal_req->app_info.ndp_app_info, nla_data(iter), hal_req->app_info.ndp_app_info_len);
+ break;
+
+ case NAN_REQ_ATTR_NDP_RESPONSE_CODE:
+ hal_req->rsp_code = nla_get_u8(iter);
+ break;
+
+ case NAN_REQ_ATTR_SERVICE_NAME_LEN:
+ hal_req->service_name_len = nla_get_u32(iter);
+ break;
+
+ case NAN_REQ_ATTR_SERVICE_NAME:
+ memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
+ break;
+
+ case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
+ hal_req->transaction_id = nla_get_u16(iter);
+ break;
+
+ default:
+ r = 0;
+ r = slsi_nan_get_security_info_nl(sdev, &hal_req->key_info, iter, type);
+ if (r)
+ SLSI_ERR(sdev, "Unexpected NAN ndp attribute TYPE:%d\n", type);
+ }
+ }
+ return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_ndp_respond(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ struct slsi_hal_nan_data_path_indication_response *hal_req = NULL;
+ int ret;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+ u16 transaction_id = 0, ndp_instance_id = 0;
+
+ slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+ if (ret != WIFI_HAL_SUCCESS)
+ goto exit;
+
+ hal_req = kmalloc(sizeof(*hal_req), GFP_KERNEL);
+ if (!hal_req) {
+ SLSI_ERR(sdev, "Failed to alloc hal_req structure!!!\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE;
+ ret = WIFI_HAL_ERROR_OUT_OF_MEMORY;
+ goto exit;
+ }
+
+ ndev_vif = netdev_priv(dev);
+ reply_status = slsi_nan_ndp_respond_get_nl_param(sdev, hal_req, data, len);
+ transaction_id = hal_req->transaction_id;
+ ndp_instance_id = hal_req->ndp_instance_id;
+ if (reply_status) {
+ ret = WIFI_HAL_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (!ndev_vif->activated) {
+ SLSI_WARN(sdev, "NAN vif not activated\n");
+ reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED;
+ ret = WIFI_HAL_ERROR_NOT_AVAILABLE;
+ goto exit_with_lock;
+ }
+
+ ret = slsi_mlme_ndp_response(sdev, dev, hal_req, ndev_vif->nan.ndp_local_ndp_id[hal_req->ndp_instance_id - 1]);
+ if (ret) {
+ reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ ret = WIFI_HAL_ERROR_UNKNOWN;
+ } else {
+ SLSI_INFO(sdev, "transId:%d ndpId:%d iface:%s\n",
+ hal_req->transaction_id, hal_req->ndp_instance_id, hal_req->ndp_iface);
+ ret = WIFI_HAL_SUCCESS;
+ }
+
+exit_with_lock:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_RESPONDER_RESPONSE,
+ ndp_instance_id, NULL, transaction_id);
+ kfree(hal_req);
+ return ret;
+}
+
+int slsi_nan_ndp_end_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_data_end *hal_req,
+ const void *data, int len)
+{
+ int type, tmp;
+ const struct nlattr *iter;
+
+ memset(hal_req, 0, sizeof(*hal_req));
+ nla_for_each_attr(iter, data, len, tmp) {
+ type = nla_type(iter);
+ if (type == NAN_REQ_ATTR_NDP_INSTANCE_ID && hal_req->num_ndp_instances < SLSI_NAN_MAX_NDP_INSTANCES)
+ hal_req->ndp_instance_id[hal_req->num_ndp_instances++] = nla_get_u32(iter);
+ else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
+ hal_req->transaction_id = nla_get_u16(iter);
+ }
+ return SLSI_HAL_NAN_STATUS_SUCCESS;
+}
+
+int slsi_nan_ndp_end(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
+{
+ struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy);
+ struct net_device *dev = slsi_nan_get_netdev(sdev);
+ struct netdev_vif *ndev_vif;
+ struct slsi_hal_nan_data_end hal_req;
+ int ret, i;
+ u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS;
+
+ hal_req.transaction_id = 0;
+ slsi_nan_pre_check(sdev, dev, &ret, &reply_status);
+ if (ret != WIFI_HAL_SUCCESS)
+ goto exit;
+
+ ndev_vif = netdev_priv(dev);
+ reply_status = slsi_nan_ndp_end_get_nl_params(sdev, &hal_req, data, len);
+
+ if (reply_status) {
+ ret = WIFI_HAL_ERROR_INVALID_ARGS;
+ goto exit;
+ }
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+ if (!ndev_vif->activated) {
+ SLSI_WARN(sdev, "NAN vif not activated\n");
+ slsi_nan_ndp_termination_handler(sdev, dev, 0, 0, NULL);
+ ret = WIFI_HAL_SUCCESS;
+ goto exit_with_lock;
+ }
+ for (i = 0; i < hal_req.num_ndp_instances; i++)
+ if (hal_req.ndp_instance_id[i] > 0 && hal_req.ndp_instance_id[i] <= SLSI_NAN_MAX_NDP_INSTANCES) {
+ ndev_vif->nan.ndp_state[hal_req.ndp_instance_id[i] - 1] = ndp_slot_status_terminating;
+ slsi_mlme_ndp_terminate(sdev, dev, hal_req.ndp_instance_id[i]);
+ SLSI_INFO(sdev, "transId:%d ndpId:%d [%d/%d]\n",
+ hal_req.transaction_id, hal_req.ndp_instance_id[i], i, hal_req.num_ndp_instances);
+ } else {
+ SLSI_ERR(sdev, "Ignore invalid ndp_id:%d\n", hal_req.ndp_instance_id[i]);
+ }
+
+exit_with_lock:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+exit:
+ slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_DP_END, 0, NULL, hal_req.transaction_id);
+ return ret;
+}
+
+/* NAN HAL EVENTS */
+
+void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
+{
+ struct sk_buff *nl_skb = NULL;
+ int res = 0;
+ u16 event, identifier, evt_reason;
+ u8 *mac_addr;
+ u16 hal_event;
+ struct netdev_vif *ndev_vif;
+ enum slsi_nan_disc_event_type disc_event_type = 0;
+
+ ndev_vif = netdev_priv(dev);
+ event = fapi_get_u16(skb, u.mlme_nan_event_ind.event);
+ identifier = fapi_get_u16(skb, u.mlme_nan_event_ind.identifier);
+ mac_addr = fapi_get_buff(skb, u.mlme_nan_event_ind.address_or_identifier);
+
+ SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
+
+ switch (fapi_get_u16(skb, u.mlme_nan_event_ind.reason_code)) {
+ case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_TIMEOUT:
+ case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_COUNT_REACHED:
+ case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_DISCOVERY_SHUTDOWN:
+ case FAPI_REASONCODE_NAN_SERVICE_TERMINATED_USER_REQUEST:
+ case FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_SUCCESS:
+ evt_reason = SLSI_HAL_NAN_STATUS_SUCCESS;
+ break;
+ case FAPI_REASONCODE_NAN_TRANSMIT_FOLLOWUP_FAILURE:
+ evt_reason = SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE;
+ break;
+ default:
+ evt_reason = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE;
+ break;
+ }
+
+ switch (event) {
+ case FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED:
+ ndev_vif->nan.service_id_map &= (u32)~BIT(identifier);
+ if (ndev_vif->nan.nan_sdf_flags[identifier] & FAPI_NANSDFCONTROL_PUBLISH_END_EVENT)
+ goto exit;
+ hal_event = SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT;
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED:
+ if (ndev_vif->nan.nan_sdf_flags[identifier] & FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT)
+ goto exit;
+ hal_event = SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT;
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED:
+ ndev_vif->nan.service_id_map &= (u32)~BIT(identifier);
+ if (ndev_vif->nan.nan_sdf_flags[identifier] & FAPI_NANSDFCONTROL_SUBSCRIBE_END_EVENT)
+ goto exit;
+ hal_event = SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT;
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_ADDRESS_CHANGED:
+ disc_event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+ hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+ ether_addr_copy(ndev_vif->nan.local_nmi, mac_addr);
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_STARTED:
+ disc_event_type = NAN_EVENT_ID_STARTED_CLUSTER;
+ hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+ ether_addr_copy(ndev_vif->nan.cluster_id, mac_addr);
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_CLUSTER_JOINED:
+ disc_event_type = NAN_EVENT_ID_JOINED_CLUSTER;
+ hal_event = SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT;
+ ether_addr_copy(ndev_vif->nan.cluster_id, mac_addr);
+ break;
+ case FAPI_EVENT_WIFI_EVENT_NAN_TRANSMIT_FOLLOWUP:
+ if (ndev_vif->nan.nan_sdf_flags[identifier] & FAPI_NANSDFCONTROL_FOLLOWUP_TRANSMIT_STATUS)
+ goto exit;
+ hal_event = SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS;
+ break;
+ default:
+ goto exit;
+ }
+
+#ifdef CONFIG_SCSC_WLAN_DEBUG
+ SLSI_INFO(sdev, "Event: %s(%d)\n",
+ slsi_print_event_name(hal_event), hal_event);
+#endif
+
+#if (KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE)
+ nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
+#else
+ nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, hal_event, GFP_KERNEL);
+#endif
+ if (!nl_skb) {
+ SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n");
+ goto exit;
+ }
+
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_STATUS, evt_reason);
+ switch (hal_event) {
+ case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT:
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, identifier);
+ break;
+ case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT:
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, identifier);
+ break;
+ case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT:
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_ID, identifier);
+ break;
+ case SLSI_NL80211_NAN_DISCOVERY_ENGINE_EVENT:
+ res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, disc_event_type);
+ res |= nla_put(nl_skb, NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, ETH_ALEN, mac_addr);
+ break;
+ case SLSI_NL80211_NAN_TRANSMIT_FOLLOWUP_STATUS:
+ res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_HAL_TRANSACTION_ID, ndev_vif->nan.followup_trans_id);
+ ndev_vif->nan.followup_trans_id = 0;
+ break;
+ }
+
+ if (res) {
+ SLSI_ERR(sdev, "Error in nla_put*:%x\n", res);
+ /* Dont use slsi skb wrapper for this free */
+ kfree_skb(nl_skb);
+ goto exit;
+ }
+
+ cfg80211_vendor_event(nl_skb, GFP_KERNEL);
+
+exit:
+ SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
+ slsi_kfree_skb(skb);
+}