From 5fad239daef2252c47842486c546c83e0ae6fc83 Mon Sep 17 00:00:00 2001 From: Jaya Prakash Sangaru Date: Tue, 23 Apr 2019 18:44:37 +0530 Subject: [PATCH] [NEUS7920-218] [9610][7885] wlbt: split NAN code Separate out NAN code from nl80211_vendor.c/h and mlme.c to new files. Change-Id: If25dc57cef1fa7245a74f6f170e33dad9e234421 SCSC-Bug-Id: SSB-51797 Signed-off-by: Jaya Prakash Sangaru --- drivers/net/wireless/scsc/Kconfig | 5 + drivers/net/wireless/scsc/Makefile | 4 + drivers/net/wireless/scsc/mlme.c | 566 ----- drivers/net/wireless/scsc/mlme.h | 4 +- drivers/net/wireless/scsc/mlme_nan.c | 612 ++++++ drivers/net/wireless/scsc/nl80211_vendor.c | 1922 ++--------------- drivers/net/wireless/scsc/nl80211_vendor.h | 731 +------ .../net/wireless/scsc/nl80211_vendor_nan.c | 1688 +++++++++++++++ .../net/wireless/scsc/nl80211_vendor_nan.h | 745 +++++++ drivers/net/wireless/scsc/procfs.c | 12 +- drivers/net/wireless/scsc/sap_mlme.c | 4 +- 11 files changed, 3202 insertions(+), 3091 deletions(-) create mode 100755 drivers/net/wireless/scsc/mlme_nan.c create mode 100755 drivers/net/wireless/scsc/nl80211_vendor_nan.c create mode 100755 drivers/net/wireless/scsc/nl80211_vendor_nan.h diff --git a/drivers/net/wireless/scsc/Kconfig b/drivers/net/wireless/scsc/Kconfig index 3037087e7b4a..02b041202ca0 100755 --- a/drivers/net/wireless/scsc/Kconfig +++ b/drivers/net/wireless/scsc/Kconfig @@ -209,3 +209,8 @@ config SCSC_ENHANCED_PACKET_STATS ---help--- This option tells whether enhanced packet stats collection is enabled or not. +config SCSC_WIFI_NAN_ENABLE + bool "Enable WiFi NAN" + default n + ---help--- + This option tells whether WiFi NAN is enabled or not. diff --git a/drivers/net/wireless/scsc/Makefile b/drivers/net/wireless/scsc/Makefile index 23bef07e9042..8abcb20895ae 100755 --- a/drivers/net/wireless/scsc/Makefile +++ b/drivers/net/wireless/scsc/Makefile @@ -80,6 +80,10 @@ ifeq ($(CONFIG_SCSC_WLAN_GSCAN_ENABLE),y) scsc_wlan-$(CONFIG_SCSC_WLAN) += nl80211_vendor.o ccflags-y += -DCONFIG_SCSC_WLAN_GSCAN_ENABLE endif +ifeq ($(CONFIG_SCSC_WIFI_NAN_ENABLE),y) +scsc_wlan-$(CONFIG_SCSC_WLAN) += nl80211_vendor_nan.o +scsc_wlan-$(CONFIG_SCSC_WLAN) += mlme_nan.o +endif ifeq ($(CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD),y) ccflags-y += -DCONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD diff --git a/drivers/net/wireless/scsc/mlme.c b/drivers/net/wireless/scsc/mlme.c index 156f11be0860..81c250ee96b9 100755 --- a/drivers/net/wireless/scsc/mlme.c +++ b/drivers/net/wireless/scsc/mlme.c @@ -4308,572 +4308,6 @@ int slsi_mlme_set_host_state(struct slsi_dev *sdev, struct net_device *dev, u8 h return r; } -static void slsi_mlme_nan_enable_fapi_data(struct sk_buff *req, struct slsi_hal_nan_enable_req *hal_req) -{ - u8 nan_config_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x01}; - u8 *header_ptr; - u16 attribute; - u8 band_usage = BIT(0) | BIT(1); - u8 scan_param[] = {0, 0, 0}; - int len = 0; - - header_ptr = fapi_append_data(req, nan_config_fields_header, sizeof(nan_config_fields_header)); - len += sizeof(nan_config_fields_header); - - if (hal_req->config_2dot4g_beacons && !hal_req->beacon_2dot4g_val) - band_usage &= ~BIT(0); - if (hal_req->config_2dot4g_sdf && !hal_req->sdf_2dot4g_val) - band_usage &= ~BIT(1); - if (hal_req->config_5g_beacons && hal_req->beacon_5g_val) - band_usage |= BIT(2); - if (hal_req->config_5g_sdf && hal_req->sdf_5g_val) - band_usage |= BIT(3); - - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, band_usage); - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, hal_req->master_pref); - len += 11; /* 5 for band_usage, 6 for master preference */ - - if (hal_req->config_sid_beacon) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->sid_beacon_val); - len += 5; - } - - if (hal_req->config_2dot4g_rssi_close) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_2dot4g_val); - len += 5; - } - - if (hal_req->config_2dot4g_rssi_middle) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_middle_2dot4g_val); - len += 5; - } - - if (hal_req->config_2dot4g_rssi_proximity) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_proximity_2dot4g_val); - len += 5; - } - - if (hal_req->config_5g_rssi_close) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_5g_val); - len += 5; - } - - if (hal_req->config_5g_rssi_middle) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_middle_5g_val); - len += 5; - } - - if (hal_req->config_5g_rssi_close_proximity) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_proximity_5g_val); - len += 5; - } - - if (hal_req->config_hop_count_limit) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->hop_count_limit_val); - len += 5; - } - - if (hal_req->config_rssi_window_size) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val); - len += 5; - } - - if (hal_req->config_scan_params) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4; - scan_param[0] = hal_req->scan_params_val.dwell_time[0]; - scan_param[1] = hal_req->scan_params_val.scan_period[0] & 0x00FF; - scan_param[2] = (hal_req->scan_params_val.scan_period[0] & 0xFF00) >> 8; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3); - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5; - scan_param[0] = hal_req->scan_params_val.dwell_time[1]; - scan_param[1] = hal_req->scan_params_val.scan_period[1] & 0x00FF; - scan_param[2] = (hal_req->scan_params_val.scan_period[1] & 0xFF00) >> 8; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3); - len += 7 * 2; - } - - /* update len */ - header_ptr[1] = len - 2; -} - -int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_enable_req *hal_req) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_oper_ctrl = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - - /* max mbulk data for mlme-nan-start.req is about 87 bytes but - * allocate 100 bytes - */ - req = fapi_alloc(mlme_nan_start_req, MLME_NAN_START_REQ, ndev_vif->ifnum, 100); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - if (hal_req->config_cluster_attribute_val) - nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_CLUSTER_SDF; - nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT | - FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT; - - fapi_set_u16(req, u.mlme_nan_start_req.cluster_low, hal_req->cluster_low); - fapi_set_u16(req, u.mlme_nan_start_req.cluster_high, hal_req->cluster_high); - fapi_set_u16(req, u.mlme_nan_start_req.nan_operation_control_flags, nan_oper_ctrl); - - slsi_mlme_nan_enable_fapi_data(req, hal_req); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_START_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_start_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_START_CFM(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -static void slsi_mlme_nan_append_tlv(struct sk_buff *req, __le16 tlv_t, __le16 tlv_l, u8 *tlv_v, u8 **header_ptr, - u8 header_ie_generic_len, u8 **end_ptr) -{ - u8 tmp_buf[255 + 4]; - u8 *tmp_buf_pos; - int tmp_buf_len, len1, ip_ie_len; - - memcpy(tmp_buf, &tlv_t, 2); - memcpy(tmp_buf + 2, &tlv_l, 2); - memcpy(tmp_buf + 4, tlv_v, tlv_l); - tmp_buf_len = 4 + tlv_l; - ip_ie_len = *end_ptr - *header_ptr - 2; - tmp_buf_pos = tmp_buf; - - while (tmp_buf_len + ip_ie_len > 255) { - len1 = 255 - ip_ie_len; - fapi_append_data(req, tmp_buf_pos, len1); - (*header_ptr)[1] = 255; - tmp_buf_len -= len1; - tmp_buf_pos += len1; - ip_ie_len = 0; - if (tmp_buf_len) { - *header_ptr = fapi_append_data(req, *header_ptr, header_ie_generic_len); - *end_ptr = *header_ptr + header_ie_generic_len; - } else { - *end_ptr = *header_ptr + header_ie_generic_len + 255; - } - } - if (tmp_buf_len) { - fapi_append_data(req, tmp_buf, tmp_buf_len); - *end_ptr += tmp_buf_len; - } -} - -static void slsi_mlme_nan_publish_fapi_data(struct sk_buff *req, struct slsi_hal_nan_publish_req *hal_req) -{ - u8 nan_publish_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x02}; - u8 *header_ptr, *end_ptr; - __le16 le16val; - u32 binding_mask = 0; - - header_ptr = fapi_append_data(req, nan_publish_fields_header, sizeof(nan_publish_fields_header)); - le16val = cpu_to_le16(hal_req->ttl); - fapi_append_data(req, (u8 *)&le16val, 2); - le16val = cpu_to_le16(hal_req->period); - fapi_append_data(req, (u8 *)&le16val, 2); - fapi_append_data(req, &hal_req->publish_type, 1); - fapi_append_data(req, &hal_req->tx_type, 1); - fapi_append_data(req, &hal_req->publish_count, 1); - fapi_append_data(req, &hal_req->publish_match_indicator, 1); - fapi_append_data(req, &hal_req->rssi_threshold_flag, 1); - end_ptr = fapi_append_data(req, (u8 *)&binding_mask, 4); - end_ptr += 4; - - if (hal_req->service_name_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_NAME), - cpu_to_le16 (hal_req->service_name_len), hal_req->service_name, &header_ptr, - sizeof(nan_publish_fields_header), &end_ptr); - - if (hal_req->service_specific_info_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO), - cpu_to_le16 (hal_req->service_specific_info_len), - hal_req->service_specific_info, &header_ptr, - sizeof(nan_publish_fields_header), &end_ptr); - - if (hal_req->rx_match_filter_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_RX_MATCH_FILTER), - cpu_to_le16 (hal_req->rx_match_filter_len), hal_req->rx_match_filter, - &header_ptr, sizeof(nan_publish_fields_header), &end_ptr); - - if (hal_req->tx_match_filter_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_TX_MATCH_FILTER), - cpu_to_le16 (hal_req->tx_match_filter_len), hal_req->tx_match_filter, - &header_ptr, sizeof(nan_publish_fields_header), &end_ptr); - - /* update len */ - header_ptr[1] = end_ptr - header_ptr - 2; -} - -int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_publish_req *hal_req, - u16 publish_id) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_sdf_flags = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - if (hal_req) { - /* max possible length for publish attributes : 8*255 */ - req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 8 * 255); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - /* Set/Enable corresponding bits to disable any indications - * that follow a publish. - * BIT0 - Disable publish termination indication. - * BIT1 - Disable match expired indication. - * BIT2 - Disable followUp indication received (OTA). - */ - if (hal_req->recv_indication_cfg & BIT(0)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_PUBLISH_END_EVENT; - if (hal_req->recv_indication_cfg & BIT(1)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT; - if (hal_req->recv_indication_cfg & BIT(2)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT; - } else { - req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 0); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - } - - fapi_set_u16(req, u.mlme_nan_publish_req.publish_id, publish_id); - fapi_set_u16(req, u.mlme_nan_publish_req.nan_sdf_flags, nan_sdf_flags); - - if (hal_req) - slsi_mlme_nan_publish_fapi_data(req, hal_req); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_PUBLISH_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_publish_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_PUBLISH_CFM(result:0x%04x) ERROR\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - if (hal_req && !r) - ndev_vif->nan.publish_id_map |= BIT(publish_id); - else - ndev_vif->nan.publish_id_map &= ~BIT(publish_id); - slsi_kfree_skb(cfm); - return r; -} - -static void slsi_mlme_nan_subscribe_fapi_data(struct sk_buff *req, struct slsi_hal_nan_subscribe_req *hal_req) -{ - u8 nan_subscribe_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x03}; - u8 *header_ptr, *end_ptr; - __le16 le16val; - u32 binding_mask = 0; - - header_ptr = fapi_append_data(req, nan_subscribe_fields_header, sizeof(nan_subscribe_fields_header)); - le16val = cpu_to_le16(hal_req->ttl); - fapi_append_data(req, (u8 *)&le16val, 2); - le16val = cpu_to_le16(hal_req->period); - fapi_append_data(req, (u8 *)&le16val, 2); - fapi_append_data(req, &hal_req->subscribe_type, 1); - fapi_append_data(req, &hal_req->service_response_filter, 1); - fapi_append_data(req, &hal_req->service_response_include, 1); - fapi_append_data(req, &hal_req->use_service_response_filter, 1); - fapi_append_data(req, &hal_req->ssi_required_for_match_indication, 1); - fapi_append_data(req, &hal_req->subscribe_match_indicator, 1); - fapi_append_data(req, &hal_req->subscribe_count, 1); - fapi_append_data(req, &hal_req->rssi_threshold_flag, 1); - end_ptr = fapi_append_data(req, (u8 *)&binding_mask, 4); - end_ptr += 4; - - if (hal_req->service_name_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_NAME), - cpu_to_le16 (hal_req->service_name_len), hal_req->service_name, &header_ptr, - sizeof(nan_subscribe_fields_header), &end_ptr); - - if (hal_req->service_specific_info_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO), - cpu_to_le16 (hal_req->service_specific_info_len), - hal_req->service_specific_info, &header_ptr, - sizeof(nan_subscribe_fields_header), &end_ptr); - - if (hal_req->rx_match_filter_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_RX_MATCH_FILTER), - cpu_to_le16 (hal_req->rx_match_filter_len), hal_req->rx_match_filter, - &header_ptr, sizeof(nan_subscribe_fields_header), &end_ptr); - - if (hal_req->tx_match_filter_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_TX_MATCH_FILTER), - cpu_to_le16 (hal_req->tx_match_filter_len), hal_req->tx_match_filter, - &header_ptr, sizeof(nan_subscribe_fields_header), &end_ptr); - - /* update len */ - header_ptr[1] = end_ptr - header_ptr - 2; -} - -int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_subscribe_req *hal_req, - u16 subscribe_id) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_sdf_flags = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - if (hal_req) { - /*max possible length for publish attributes: 8*255 */ - req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 8 * 255); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - /* Set/Enable corresponding bits to disable - * indications that follow a subscribe. - * BIT0 - Disable subscribe termination indication. - * BIT1 - Disable match expired indication. - * BIT2 - Disable followUp indication received (OTA). - */ - if (hal_req->recv_indication_cfg & BIT(0)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_SUBSCRIBE_END_EVENT; - if (hal_req->recv_indication_cfg & BIT(1)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT; - if (hal_req->recv_indication_cfg & BIT(2)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT; - } else { - req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 0); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - } - - fapi_set_u16(req, u.mlme_nan_subscribe_req.subscribe_id, subscribe_id); - fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags); - - if (hal_req) - slsi_mlme_nan_subscribe_fapi_data(req, hal_req); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_SUBSCRIBE_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_subscribe_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_SUBSCRIBE_CFM(res:0x%04x)\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - if (hal_req && !r) - ndev_vif->nan.subscribe_id_map |= BIT(subscribe_id); - else - ndev_vif->nan.subscribe_id_map &= ~BIT(subscribe_id); - slsi_kfree_skb(cfm); - return r; -} - -static void slsi_mlme_nan_followup_fapi_data(struct sk_buff *req, struct slsi_hal_nan_transmit_followup_req *hal_req) -{ - u8 nan_followup_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x05}; - u8 *header_ptr, *end_ptr; - - header_ptr = fapi_append_data(req, nan_followup_fields_header, sizeof(nan_followup_fields_header)); - fapi_append_data(req, hal_req->addr, ETH_ALEN); - fapi_append_data(req, &hal_req->priority, 1); - end_ptr = fapi_append_data(req, &hal_req->dw_or_faw, 1); - end_ptr += 1; - - if (hal_req->service_specific_info_len) - slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO), - cpu_to_le16 (hal_req->service_specific_info_len), - hal_req->service_specific_info, &header_ptr, - sizeof(nan_followup_fields_header), &end_ptr); - - /* update len */ - header_ptr[1] = end_ptr - header_ptr - 2; -} - -int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev, - struct slsi_hal_nan_transmit_followup_req *hal_req) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_sdf_flags = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - - /* max possible length for publish attributes: 5*255 */ - req = fapi_alloc(mlme_nan_followup_req, MLME_NAN_FOLLOWUP_REQ, ndev_vif->ifnum, 5 * 255); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - /* Set/Enable corresponding bits to disable responses after followUp. - * BIT0 - Disable followUp response from FW. - */ - if (hal_req->recv_indication_cfg & BIT(0)) - nan_sdf_flags |= FAPI_NANSDFCONTROL_DISABLE_RESPONSES_AFTER_FOLLOWUP; - - fapi_set_u16(req, u.mlme_nan_followup_req.requestor_instance_id, hal_req->publish_subscribe_id); - fapi_set_u16(req, u.mlme_nan_followup_req.requestor_instance_id, hal_req->requestor_instance_id); - fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags); - - slsi_mlme_nan_followup_fapi_data(req, hal_req); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - -static void slsi_mlme_nan_config_fapi_data(struct sk_buff *req, struct slsi_hal_nan_config_req *hal_req) -{ - u8 nan_config_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x01}; - u8 *header_ptr; - u16 attribute; - u8 scan_param[] = {0, 0, 0}; - int len = 0; - - header_ptr = fapi_append_data(req, nan_config_fields_header, sizeof(nan_config_fields_header)); - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, hal_req->master_pref); - len += sizeof(nan_config_fields_header) + 5; - - if (hal_req->config_sid_beacon) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->sid_beacon); - len += 5; - } - - if (hal_req->config_rssi_proximity) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_proximity); - len += 5; - } - - if (hal_req->config_5g_rssi_close_proximity) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_proximity_5g_val); - len += 5; - } - - if (hal_req->config_rssi_window_size) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val); - len += 5; - } - - if (hal_req->config_scan_params) { - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4; - scan_param[0] = hal_req->scan_params_val.dwell_time[0]; - scan_param[1] = hal_req->scan_params_val.scan_period[0] & 0x00FF; - scan_param[2] = (hal_req->scan_params_val.scan_period[0] & 0xFF00) >> 8; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3); - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5; - scan_param[0] = hal_req->scan_params_val.dwell_time[1]; - scan_param[1] = hal_req->scan_params_val.scan_period[1] & 0x00FF; - scan_param[2] = (hal_req->scan_params_val.scan_period[1] & 0xFF00) >> 8; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3); - len += 7 * 2; - } - - if (hal_req->config_conn_capability) { - u8 con_cap = 0; - - if (hal_req->conn_capability_val.is_wfd_supported) - con_cap |= BIT(0); - if (hal_req->conn_capability_val.is_wfds_supported) - con_cap |= BIT(1); - if (hal_req->conn_capability_val.is_tdls_supported) - con_cap |= BIT(2); - if (hal_req->conn_capability_val.wlan_infra_field) - con_cap |= BIT(3); - attribute = SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB; - SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val); - len += 5; - } - /* update len */ - header_ptr[1] = len - 2; -} - -int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_config_req *hal_req) -{ - struct netdev_vif *ndev_vif = netdev_priv(dev); - struct sk_buff *req; - struct sk_buff *cfm; - int r = 0; - u16 nan_oper_ctrl = 0; - - SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); - /* max possible length for publish attributes 5*255 */ - req = fapi_alloc(mlme_nan_config_req, MLME_NAN_CONFIG_REQ, ndev_vif->ifnum, 5 * 255); - if (!req) { - SLSI_NET_ERR(dev, "fapi alloc failure\n"); - return -ENOMEM; - } - - if (hal_req->config_cluster_attribute_val) - nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_CLUSTER_SDF; - nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT | - FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT; - fapi_set_u16(req, u.mlme_nan_config_req.nan_operation_control_flags, nan_oper_ctrl); - - slsi_mlme_nan_config_fapi_data(req, hal_req); - - cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM); - if (!cfm) - return -EIO; - - if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { - SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n", - fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); - r = -EINVAL; - } - - slsi_kfree_skb(cfm); - return r; -} - #ifdef CONFIG_SCSC_WLAN_DEBUG #define SLSI_TEST_CONFIG_MONITOR_MODE_DESCRIPTOR_SIZE (12) int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef) diff --git a/drivers/net/wireless/scsc/mlme.h b/drivers/net/wireless/scsc/mlme.h index 7aa9bea212db..fd2ed107168f 100755 --- a/drivers/net/wireless/scsc/mlme.h +++ b/drivers/net/wireless/scsc/mlme.h @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved + * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved * ****************************************************************************/ @@ -267,4 +267,6 @@ int slsi_mlme_set_p2p_noa(struct slsi_dev *sdev, struct net_device *dev, unsigne void slsi_fw_tx_rate_calc(u16 fw_rate, struct rate_info *tx_rate, unsigned long *data_rate_mbps); int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef); +struct sk_buff *slsi_mlme_req_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id); + #endif /*__SLSI_MLME_H__*/ diff --git a/drivers/net/wireless/scsc/mlme_nan.c b/drivers/net/wireless/scsc/mlme_nan.c new file mode 100755 index 000000000000..221702da83aa --- /dev/null +++ b/drivers/net/wireless/scsc/mlme_nan.c @@ -0,0 +1,612 @@ +/***************************************************************************** + * + * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved + * + ****************************************************************************/ + +#include "debug.h" +#include "mlme.h" + +#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, val) \ + { \ + u16 attribute_len = 1; \ + struct sk_buff *req_p = req; \ + fapi_append_data((req_p), (u8 *)&(attribute), 2); \ + fapi_append_data((req_p), (u8 *)&attribute_len, 2); \ + fapi_append_data((req_p), (u8 *)&(val), 1); \ + } + +#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, val) \ + { \ + u16 attribute_len = 2; \ + __le16 le16val = cpu_to_le16(val); \ + struct sk_buff *req_p = req; \ + fapi_append_data((req_p), (u8 *)&(attribute), 2); \ + fapi_append_data((req_p), (u8 *)&attribute_len, 2); \ + fapi_append_data((req_p), (u8 *)&le16val, 2); \ + } + +#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_U32(req, attribute, val) \ + { \ + u16 attribute_len = 4; \ + __le32 le32val = cpu_to_le32(val);\ + struct sk_buff *req_p = req; \ + fapi_append_data((req_p), (u8 *)&(attribute), 2); \ + fapi_append_data((req_p), (u8 *)&attribute_len, 2); \ + fapi_append_data((req_p), (u8 *)&le32val, 4); \ + } + +#define SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, val, val_len) \ + { \ + u16 attribute_len = (val_len); \ + struct sk_buff *req_p = req; \ + fapi_append_data((req_p), (u8 *)&(attribute), 2); \ + fapi_append_data((req_p), (u8 *)&attribute_len, 2); \ + fapi_append_data((req_p), (val), (attribute_len)); \ + } + +static void slsi_mlme_nan_enable_fapi_data(struct sk_buff *req, struct slsi_hal_nan_enable_req *hal_req) +{ + u8 nan_config_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x01}; + u8 *header_ptr; + u16 attribute; + u8 band_usage = BIT(0) | BIT(1); + u8 scan_param[] = {0, 0, 0}; + int len = 0; + + header_ptr = fapi_append_data(req, nan_config_fields_header, sizeof(nan_config_fields_header)); + len += sizeof(nan_config_fields_header); + + if (hal_req->config_2dot4g_beacons && !hal_req->beacon_2dot4g_val) + band_usage &= ~BIT(0); + if (hal_req->config_2dot4g_sdf && !hal_req->sdf_2dot4g_val) + band_usage &= ~BIT(1); + if (hal_req->config_5g_beacons && hal_req->beacon_5g_val) + band_usage |= BIT(2); + if (hal_req->config_5g_sdf && hal_req->sdf_5g_val) + band_usage |= BIT(3); + + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, band_usage); + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, hal_req->master_pref); + len += 11; /* 5 for band_usage, 6 for master preference */ + + if (hal_req->config_sid_beacon) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->sid_beacon_val); + len += 5; + } + + if (hal_req->config_2dot4g_rssi_close) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_2dot4g_val); + len += 5; + } + + if (hal_req->config_2dot4g_rssi_middle) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_middle_2dot4g_val); + len += 5; + } + + if (hal_req->config_2dot4g_rssi_proximity) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_proximity_2dot4g_val); + len += 5; + } + + if (hal_req->config_5g_rssi_close) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_5g_val); + len += 5; + } + + if (hal_req->config_5g_rssi_middle) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_middle_5g_val); + len += 5; + } + + if (hal_req->config_5g_rssi_close_proximity) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_proximity_5g_val); + len += 5; + } + + if (hal_req->config_hop_count_limit) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->hop_count_limit_val); + len += 5; + } + + if (hal_req->config_rssi_window_size) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val); + len += 5; + } + + if (hal_req->config_scan_params) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4; + scan_param[0] = hal_req->scan_params_val.dwell_time[0]; + scan_param[1] = hal_req->scan_params_val.scan_period[0] & 0x00FF; + scan_param[2] = (hal_req->scan_params_val.scan_period[0] & 0xFF00) >> 8; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3); + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5; + scan_param[0] = hal_req->scan_params_val.dwell_time[1]; + scan_param[1] = hal_req->scan_params_val.scan_period[1] & 0x00FF; + scan_param[2] = (hal_req->scan_params_val.scan_period[1] & 0xFF00) >> 8; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3); + len += 7 * 2; + } + + /* update len */ + header_ptr[1] = len - 2; +} + +int slsi_mlme_nan_enable(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_enable_req *hal_req) +{ + struct netdev_vif *ndev_vif = netdev_priv(dev); + struct sk_buff *req; + struct sk_buff *cfm; + int r = 0; + u16 nan_oper_ctrl = 0; + + SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); + + /* max mbulk data for mlme-nan-start.req is about 87 bytes but + * allocate 100 bytes + */ + req = fapi_alloc(mlme_nan_start_req, MLME_NAN_START_REQ, ndev_vif->ifnum, 100); + if (!req) { + SLSI_NET_ERR(dev, "fapi alloc failure\n"); + return -ENOMEM; + } + + if (hal_req->config_cluster_attribute_val) + nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_CLUSTER_SDF; + nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT | + FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT; + + fapi_set_u16(req, u.mlme_nan_start_req.cluster_low, hal_req->cluster_low); + fapi_set_u16(req, u.mlme_nan_start_req.cluster_high, hal_req->cluster_high); + fapi_set_u16(req, u.mlme_nan_start_req.nan_operation_control_flags, nan_oper_ctrl); + + slsi_mlme_nan_enable_fapi_data(req, hal_req); + + cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_START_CFM); + if (!cfm) + return -EIO; + + if (fapi_get_u16(cfm, u.mlme_nan_start_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { + SLSI_NET_ERR(dev, "MLME_NAN_START_CFM(result:0x%04x) ERROR\n", + fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); + r = -EINVAL; + } + + slsi_kfree_skb(cfm); + return r; +} + +static void slsi_mlme_nan_append_tlv(struct sk_buff *req, __le16 tlv_t, __le16 tlv_l, u8 *tlv_v, u8 **header_ptr, + u8 header_ie_generic_len, u8 **end_ptr) +{ + u8 tmp_buf[255 + 4]; + u8 *tmp_buf_pos; + int tmp_buf_len, len1, ip_ie_len; + + memcpy(tmp_buf, &tlv_t, 2); + memcpy(tmp_buf + 2, &tlv_l, 2); + memcpy(tmp_buf + 4, tlv_v, tlv_l); + tmp_buf_len = 4 + tlv_l; + ip_ie_len = *end_ptr - *header_ptr - 2; + tmp_buf_pos = tmp_buf; + + while (tmp_buf_len + ip_ie_len > 255) { + len1 = 255 - ip_ie_len; + fapi_append_data(req, tmp_buf_pos, len1); + (*header_ptr)[1] = 255; + tmp_buf_len -= len1; + tmp_buf_pos += len1; + ip_ie_len = 0; + if (tmp_buf_len) { + *header_ptr = fapi_append_data(req, *header_ptr, header_ie_generic_len); + *end_ptr = *header_ptr + header_ie_generic_len; + } else { + *end_ptr = *header_ptr + header_ie_generic_len + 255; + } + } + if (tmp_buf_len) { + fapi_append_data(req, tmp_buf, tmp_buf_len); + *end_ptr += tmp_buf_len; + } +} + +static void slsi_mlme_nan_publish_fapi_data(struct sk_buff *req, struct slsi_hal_nan_publish_req *hal_req) +{ + u8 nan_publish_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x02}; + u8 *header_ptr, *end_ptr; + __le16 le16val; + u32 binding_mask = 0; + + header_ptr = fapi_append_data(req, nan_publish_fields_header, sizeof(nan_publish_fields_header)); + le16val = cpu_to_le16(hal_req->ttl); + fapi_append_data(req, (u8 *)&le16val, 2); + le16val = cpu_to_le16(hal_req->period); + fapi_append_data(req, (u8 *)&le16val, 2); + fapi_append_data(req, &hal_req->publish_type, 1); + fapi_append_data(req, &hal_req->tx_type, 1); + fapi_append_data(req, &hal_req->publish_count, 1); + fapi_append_data(req, &hal_req->publish_match_indicator, 1); + fapi_append_data(req, &hal_req->rssi_threshold_flag, 1); + end_ptr = fapi_append_data(req, (u8 *)&binding_mask, 4); + end_ptr += 4; + + if (hal_req->service_name_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_NAME), + cpu_to_le16 (hal_req->service_name_len), hal_req->service_name, &header_ptr, + sizeof(nan_publish_fields_header), &end_ptr); + + if (hal_req->service_specific_info_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO), + cpu_to_le16 (hal_req->service_specific_info_len), + hal_req->service_specific_info, &header_ptr, + sizeof(nan_publish_fields_header), &end_ptr); + + if (hal_req->rx_match_filter_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_RX_MATCH_FILTER), + cpu_to_le16 (hal_req->rx_match_filter_len), hal_req->rx_match_filter, + &header_ptr, sizeof(nan_publish_fields_header), &end_ptr); + + if (hal_req->tx_match_filter_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_TX_MATCH_FILTER), + cpu_to_le16 (hal_req->tx_match_filter_len), hal_req->tx_match_filter, + &header_ptr, sizeof(nan_publish_fields_header), &end_ptr); + + /* update len */ + header_ptr[1] = end_ptr - header_ptr - 2; +} + +int slsi_mlme_nan_publish(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_publish_req *hal_req, + u16 publish_id) +{ + struct netdev_vif *ndev_vif = netdev_priv(dev); + struct sk_buff *req; + struct sk_buff *cfm; + int r = 0; + u16 nan_sdf_flags = 0; + + SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); + if (hal_req) { + /* max possible length for publish attributes : 8*255 */ + req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 8 * 255); + if (!req) { + SLSI_NET_ERR(dev, "fapi alloc failure\n"); + return -ENOMEM; + } + + /* Set/Enable corresponding bits to disable any indications + * that follow a publish. + * BIT0 - Disable publish termination indication. + * BIT1 - Disable match expired indication. + * BIT2 - Disable followUp indication received (OTA). + */ + if (hal_req->recv_indication_cfg & BIT(0)) + nan_sdf_flags |= FAPI_NANSDFCONTROL_PUBLISH_END_EVENT; + if (hal_req->recv_indication_cfg & BIT(1)) + nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT; + if (hal_req->recv_indication_cfg & BIT(2)) + nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT; + } else { + req = fapi_alloc(mlme_nan_publish_req, MLME_NAN_PUBLISH_REQ, ndev_vif->ifnum, 0); + if (!req) { + SLSI_NET_ERR(dev, "fapi alloc failure\n"); + return -ENOMEM; + } + } + + fapi_set_u16(req, u.mlme_nan_publish_req.publish_id, publish_id); + fapi_set_u16(req, u.mlme_nan_publish_req.nan_sdf_flags, nan_sdf_flags); + + if (hal_req) + slsi_mlme_nan_publish_fapi_data(req, hal_req); + + cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_PUBLISH_CFM); + if (!cfm) + return -EIO; + + if (fapi_get_u16(cfm, u.mlme_nan_publish_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { + SLSI_NET_ERR(dev, "MLME_NAN_PUBLISH_CFM(result:0x%04x) ERROR\n", + fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); + r = -EINVAL; + } + + if (hal_req && !r) + ndev_vif->nan.publish_id_map |= BIT(publish_id); + else + ndev_vif->nan.publish_id_map &= ~BIT(publish_id); + slsi_kfree_skb(cfm); + return r; +} + +static void slsi_mlme_nan_subscribe_fapi_data(struct sk_buff *req, struct slsi_hal_nan_subscribe_req *hal_req) +{ + u8 nan_subscribe_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x03}; + u8 *header_ptr, *end_ptr; + __le16 le16val; + u32 binding_mask = 0; + + header_ptr = fapi_append_data(req, nan_subscribe_fields_header, sizeof(nan_subscribe_fields_header)); + le16val = cpu_to_le16(hal_req->ttl); + fapi_append_data(req, (u8 *)&le16val, 2); + le16val = cpu_to_le16(hal_req->period); + fapi_append_data(req, (u8 *)&le16val, 2); + fapi_append_data(req, &hal_req->subscribe_type, 1); + fapi_append_data(req, &hal_req->service_response_filter, 1); + fapi_append_data(req, &hal_req->service_response_include, 1); + fapi_append_data(req, &hal_req->use_service_response_filter, 1); + fapi_append_data(req, &hal_req->ssi_required_for_match_indication, 1); + fapi_append_data(req, &hal_req->subscribe_match_indicator, 1); + fapi_append_data(req, &hal_req->subscribe_count, 1); + fapi_append_data(req, &hal_req->rssi_threshold_flag, 1); + end_ptr = fapi_append_data(req, (u8 *)&binding_mask, 4); + end_ptr += 4; + + if (hal_req->service_name_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_NAME), + cpu_to_le16 (hal_req->service_name_len), hal_req->service_name, &header_ptr, + sizeof(nan_subscribe_fields_header), &end_ptr); + + if (hal_req->service_specific_info_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO), + cpu_to_le16 (hal_req->service_specific_info_len), + hal_req->service_specific_info, &header_ptr, + sizeof(nan_subscribe_fields_header), &end_ptr); + + if (hal_req->rx_match_filter_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_RX_MATCH_FILTER), + cpu_to_le16 (hal_req->rx_match_filter_len), hal_req->rx_match_filter, + &header_ptr, sizeof(nan_subscribe_fields_header), &end_ptr); + + if (hal_req->tx_match_filter_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_TX_MATCH_FILTER), + cpu_to_le16 (hal_req->tx_match_filter_len), hal_req->tx_match_filter, + &header_ptr, sizeof(nan_subscribe_fields_header), &end_ptr); + + /* update len */ + header_ptr[1] = end_ptr - header_ptr - 2; +} + +int slsi_mlme_nan_subscribe(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_subscribe_req *hal_req, + u16 subscribe_id) +{ + struct netdev_vif *ndev_vif = netdev_priv(dev); + struct sk_buff *req; + struct sk_buff *cfm; + int r = 0; + u16 nan_sdf_flags = 0; + + SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); + if (hal_req) { + /*max possible length for publish attributes: 8*255 */ + req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 8 * 255); + if (!req) { + SLSI_NET_ERR(dev, "fapi alloc failure\n"); + return -ENOMEM; + } + /* Set/Enable corresponding bits to disable + * indications that follow a subscribe. + * BIT0 - Disable subscribe termination indication. + * BIT1 - Disable match expired indication. + * BIT2 - Disable followUp indication received (OTA). + */ + if (hal_req->recv_indication_cfg & BIT(0)) + nan_sdf_flags |= FAPI_NANSDFCONTROL_SUBSCRIBE_END_EVENT; + if (hal_req->recv_indication_cfg & BIT(1)) + nan_sdf_flags |= FAPI_NANSDFCONTROL_MATCH_EXPIRED_EVENT; + if (hal_req->recv_indication_cfg & BIT(2)) + nan_sdf_flags |= FAPI_NANSDFCONTROL_RECEIVED_FOLLOWUP_EVENT; + } else { + req = fapi_alloc(mlme_nan_subscribe_req, MLME_NAN_SUBSCRIBE_REQ, ndev_vif->ifnum, 0); + if (!req) { + SLSI_NET_ERR(dev, "fapi alloc failure\n"); + return -ENOMEM; + } + } + + fapi_set_u16(req, u.mlme_nan_subscribe_req.subscribe_id, subscribe_id); + fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags); + + if (hal_req) + slsi_mlme_nan_subscribe_fapi_data(req, hal_req); + + cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_SUBSCRIBE_CFM); + if (!cfm) + return -EIO; + + if (fapi_get_u16(cfm, u.mlme_nan_subscribe_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { + SLSI_NET_ERR(dev, "MLME_NAN_SUBSCRIBE_CFM(res:0x%04x)\n", + fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); + r = -EINVAL; + } + + if (hal_req && !r) + ndev_vif->nan.subscribe_id_map |= BIT(subscribe_id); + else + ndev_vif->nan.subscribe_id_map &= ~BIT(subscribe_id); + slsi_kfree_skb(cfm); + return r; +} + +static void slsi_mlme_nan_followup_fapi_data(struct sk_buff *req, struct slsi_hal_nan_transmit_followup_req *hal_req) +{ + u8 nan_followup_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x05}; + u8 *header_ptr, *end_ptr; + + header_ptr = fapi_append_data(req, nan_followup_fields_header, sizeof(nan_followup_fields_header)); + fapi_append_data(req, hal_req->addr, ETH_ALEN); + fapi_append_data(req, &hal_req->priority, 1); + end_ptr = fapi_append_data(req, &hal_req->dw_or_faw, 1); + end_ptr += 1; + + if (hal_req->service_specific_info_len) + slsi_mlme_nan_append_tlv(req, cpu_to_le16 (SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO), + cpu_to_le16 (hal_req->service_specific_info_len), + hal_req->service_specific_info, &header_ptr, + sizeof(nan_followup_fields_header), &end_ptr); + + /* update len */ + header_ptr[1] = end_ptr - header_ptr - 2; +} + +int slsi_mlme_nan_tx_followup(struct slsi_dev *sdev, struct net_device *dev, + struct slsi_hal_nan_transmit_followup_req *hal_req) +{ + struct netdev_vif *ndev_vif = netdev_priv(dev); + struct sk_buff *req; + struct sk_buff *cfm; + int r = 0; + u16 nan_sdf_flags = 0; + + SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); + + /* max possible length for publish attributes: 5*255 */ + req = fapi_alloc(mlme_nan_followup_req, MLME_NAN_FOLLOWUP_REQ, ndev_vif->ifnum, 5 * 255); + if (!req) { + SLSI_NET_ERR(dev, "fapi alloc failure\n"); + return -ENOMEM; + } + + /* Set/Enable corresponding bits to disable responses after followUp. + * BIT0 - Disable followUp response from FW. + */ + if (hal_req->recv_indication_cfg & BIT(0)) + nan_sdf_flags |= FAPI_NANSDFCONTROL_DISABLE_RESPONSES_AFTER_FOLLOWUP; + + fapi_set_u16(req, u.mlme_nan_followup_req.requestor_instance_id, hal_req->publish_subscribe_id); + fapi_set_u16(req, u.mlme_nan_followup_req.requestor_instance_id, hal_req->requestor_instance_id); + fapi_set_u16(req, u.mlme_nan_subscribe_req.nan_sdf_flags, nan_sdf_flags); + + slsi_mlme_nan_followup_fapi_data(req, hal_req); + + cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM); + if (!cfm) + return -EIO; + + if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { + SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n", + fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); + r = -EINVAL; + } + + slsi_kfree_skb(cfm); + return r; +} + +static void slsi_mlme_nan_config_fapi_data(struct sk_buff *req, struct slsi_hal_nan_config_req *hal_req) +{ + u8 nan_config_fields_header[] = {0xdd, 0x00, 0x00, 0x16, 0x32, 0x0b, 0x01}; + u8 *header_ptr; + u16 attribute; + u8 scan_param[] = {0, 0, 0}; + int len = 0; + + header_ptr = fapi_append_data(req, nan_config_fields_header, sizeof(nan_config_fields_header)); + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U16(req, attribute, hal_req->master_pref); + len += sizeof(nan_config_fields_header) + 5; + + if (hal_req->config_sid_beacon) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->sid_beacon); + len += 5; + } + + if (hal_req->config_rssi_proximity) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_proximity); + len += 5; + } + + if (hal_req->config_5g_rssi_close_proximity) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_close_proximity_5g_val); + len += 5; + } + + if (hal_req->config_rssi_window_size) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val); + len += 5; + } + + if (hal_req->config_scan_params) { + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4; + scan_param[0] = hal_req->scan_params_val.dwell_time[0]; + scan_param[1] = hal_req->scan_params_val.scan_period[0] & 0x00FF; + scan_param[2] = (hal_req->scan_params_val.scan_period[0] & 0xFF00) >> 8; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3); + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5; + scan_param[0] = hal_req->scan_params_val.dwell_time[1]; + scan_param[1] = hal_req->scan_params_val.scan_period[1] & 0x00FF; + scan_param[2] = (hal_req->scan_params_val.scan_period[1] & 0xFF00) >> 8; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_DATA(req, attribute, scan_param, 3); + len += 7 * 2; + } + + if (hal_req->config_conn_capability) { + u8 con_cap = 0; + + if (hal_req->conn_capability_val.is_wfd_supported) + con_cap |= BIT(0); + if (hal_req->conn_capability_val.is_wfds_supported) + con_cap |= BIT(1); + if (hal_req->conn_capability_val.is_tdls_supported) + con_cap |= BIT(2); + if (hal_req->conn_capability_val.wlan_infra_field) + con_cap |= BIT(3); + attribute = SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB; + SLSI_FAPI_NAN_ATTRIBUTE_PUT_U8(req, attribute, hal_req->rssi_window_size_val); + len += 5; + } + /* update len */ + header_ptr[1] = len - 2; +} + +int slsi_mlme_nan_set_config(struct slsi_dev *sdev, struct net_device *dev, struct slsi_hal_nan_config_req *hal_req) +{ + struct netdev_vif *ndev_vif = netdev_priv(dev); + struct sk_buff *req; + struct sk_buff *cfm; + int r = 0; + u16 nan_oper_ctrl = 0; + + SLSI_NET_DBG3(dev, SLSI_MLME, "\n"); + /* max possible length for publish attributes 5*255 */ + req = fapi_alloc(mlme_nan_config_req, MLME_NAN_CONFIG_REQ, ndev_vif->ifnum, 5 * 255); + if (!req) { + SLSI_NET_ERR(dev, "fapi alloc failure\n"); + return -ENOMEM; + } + + if (hal_req->config_cluster_attribute_val) + nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_CLUSTER_SDF; + nan_oper_ctrl |= FAPI_NANOPERATIONCONTROL_MAC_ADDRESS_EVENT | FAPI_NANOPERATIONCONTROL_START_CLUSTER_EVENT | + FAPI_NANOPERATIONCONTROL_JOINED_CLUSTER_EVENT; + fapi_set_u16(req, u.mlme_nan_config_req.nan_operation_control_flags, nan_oper_ctrl); + + slsi_mlme_nan_config_fapi_data(req, hal_req); + + cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_NAN_FOLLOWUP_CFM); + if (!cfm) + return -EIO; + + if (fapi_get_u16(cfm, u.mlme_nan_followup_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) { + SLSI_NET_ERR(dev, "MLME_NAN_FOLLOWUP_CFM(res:0x%04x)\n", + fapi_get_u16(cfm, u.mlme_host_state_cfm.result_code)); + r = -EINVAL; + } + + slsi_kfree_skb(cfm); + return r; +} diff --git a/drivers/net/wireless/scsc/nl80211_vendor.c b/drivers/net/wireless/scsc/nl80211_vendor.c index 861b2b1ae9fb..e22ec11c274d 100755 --- a/drivers/net/wireless/scsc/nl80211_vendor.c +++ b/drivers/net/wireless/scsc/nl80211_vendor.c @@ -163,15 +163,6 @@ static struct net_device *slsi_gscan_get_netdev(struct slsi_dev *sdev) return slsi_get_netdev(sdev, SLSI_NET_INDEX_WLAN); } -static struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev) -{ -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - return slsi_get_netdev(sdev, SLSI_NET_INDEX_NAN); -#else - return NULL; -#endif -} - static struct netdev_vif *slsi_gscan_get_vif(struct slsi_dev *sdev) { struct net_device *dev; @@ -3117,8 +3108,10 @@ static int slsi_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, c { int r, type, j = 0; struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); +#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE struct net_device *dev = slsi_nan_get_netdev(sdev); struct netdev_vif *ndev_vif; +#endif struct slsi_rtt_config *nl_rtt_params; const struct nlattr *iter, *outer, *inner; int tmp, tmp1, tmp2; @@ -3245,6 +3238,7 @@ static int slsi_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, c if (rtt_peer == SLSI_RTT_PEER_AP) { vif_idx = 0; } else if (rtt_peer == SLSI_RTT_PEER_NAN) { +#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE if (!slsi_dev_nan_supported(sdev)) { SLSI_ERR(sdev, "NAN not supported(mib:%d)\n", sdev->nan_enabled); kfree(nl_rtt_params); @@ -3258,6 +3252,10 @@ static int slsi_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, c kfree(nl_rtt_params); return -EINVAL; } +#else + SLSI_ERR(sdev, "NAN not enabled\n"); + return -ENOTSUPP; +#endif } r = slsi_mlme_add_range_req(sdev, num_devices, nl_rtt_params, rtt_id, vif_idx); if (r) { @@ -3516,1836 +3514,166 @@ static int slsi_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev return r; } -static int slsi_nan_get_new_id(u32 id_map, int max_ids) -{ - int i; - - for (i = 1; i <= max_ids; i++) { - if (!(id_map & BIT(i))) - return i; - } - return 0; -} - -static int slsi_nan_get_new_publish_id(struct netdev_vif *ndev_vif) -{ - return slsi_nan_get_new_id(ndev_vif->nan.publish_id_map, SLSI_NAN_MAX_PUBLISH_ID); -} - -static int slsi_nan_get_new_subscribe_id(struct netdev_vif *ndev_vif) -{ - return slsi_nan_get_new_id(ndev_vif->nan.subscribe_id_map, SLSI_NAN_MAX_SUBSCRIBE_ID); -} - -static bool slsi_nan_is_publish_id_active(struct netdev_vif *ndev_vif, u32 id) -{ - return ndev_vif->nan.publish_id_map & BIT(id); -} - -static bool slsi_nan_is_subscribe_id_active(struct netdev_vif *ndev_vif, u32 id) -{ - return ndev_vif->nan.subscribe_id_map & BIT(id); -} - -void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr) +static int slsi_configure_nd_offload(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { - memset(nan_mac_addr, 0, ETH_ALEN); -#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 - if (slsi_dev_nan_supported(sdev)) - ether_addr_copy(nan_mac_addr, sdev->netdev_addresses[SLSI_NET_INDEX_NAN]); -#endif -} + struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); + struct net_device *dev = wdev->netdev; + struct netdev_vif *ndev_vif; + int ret = 0; + int temp; + int type; + const struct nlattr *attr; + u8 nd_offload_enabled = 0; -static void slsi_vendor_nan_command_reply(struct wiphy *wiphy, u32 status, u32 error, u32 response_type, - u16 publish_subscribe_id, struct slsi_hal_nan_capabilities *capabilities) -{ - int reply_len; - struct sk_buff *reply; + SLSI_DBG3(sdev, SLSI_GSCAN, "Received nd_offload command\n"); - reply_len = SLSI_NL_VENDOR_REPLY_OVERHEAD + SLSI_NL_ATTRIBUTE_U32_LEN * - (3 + sizeof(struct slsi_hal_nan_capabilities)); - reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len); - if (!reply) { - SLSI_WARN_NODEV("SKB alloc failed for vendor_cmd reply\n"); - return; + if (!dev) { + SLSI_ERR(sdev, "dev is NULL!!\n"); + return -EINVAL; } - nla_put_u32(reply, NAN_REPLY_ATTR_STATUS_TYPE, status); - nla_put_u32(reply, NAN_REPLY_ATTR_VALUE, error); - nla_put_u32(reply, NAN_REPLY_ATTR_RESPONSE_TYPE, response_type); - - if (capabilities) { - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER, - capabilities->max_concurrent_nan_clusters); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_PUBLISHES, capabilities->max_publishes); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES, capabilities->max_subscribes); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN, capabilities->max_service_name_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN, capabilities->max_match_filter_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN, - capabilities->max_total_match_filter_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN, - capabilities->max_service_specific_info_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN, capabilities->max_vsa_data_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN, capabilities->max_mesh_data_len); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, capabilities->max_ndi_interfaces); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, capabilities->max_ndp_sessions); - nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN, capabilities->max_app_info_len); - } else if (publish_subscribe_id) { - nla_put_u16(reply, NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, publish_subscribe_id); - } - - if (cfg80211_vendor_cmd_reply(reply)) - SLSI_ERR_NODEV("FAILED to reply nan coammnd. response_type:%d\n", response_type); -} + ndev_vif = netdev_priv(dev); + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); -static int slsi_nan_enable_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_enable_req *hal_req, - const void *data, int len) -{ - int type, tmp; - const struct nlattr *iter; + if (!ndev_vif->activated || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || + (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { + SLSI_DBG3(sdev, SLSI_GSCAN, "vif error\n"); + ret = -EPERM; + goto exit; + } - memset(hal_req, 0, sizeof(*hal_req)); - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); + nla_for_each_attr(attr, data, len, temp) { + type = nla_type(attr); switch (type) { - case NAN_REQ_ATTR_MASTER_PREF: - hal_req->master_pref = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_CLUSTER_LOW: - hal_req->cluster_low = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_CLUSTER_HIGH: - hal_req->cluster_high = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUPPORT_5G_VAL: - hal_req->support_5g_val = nla_get_u8(iter); - hal_req->config_support_5g = 1; - break; - - case NAN_REQ_ATTR_SID_BEACON_VAL: - hal_req->sid_beacon_val = nla_get_u8(iter); - hal_req->config_sid_beacon = 1; - break; - - case NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL: - hal_req->rssi_close_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_rssi_close = 1; - break; - - case NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL: - hal_req->rssi_middle_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_rssi_middle = 1; - break; - - case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL: - hal_req->rssi_proximity_2dot4g_val = nla_get_u8(iter); - hal_req->rssi_proximity_2dot4g_val = 1; - break; - - case NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL: - hal_req->hop_count_limit_val = nla_get_u8(iter); - hal_req->config_hop_count_limit = 1; - break; - - case NAN_REQ_ATTR_SUPPORT_2G4_VAL: - hal_req->support_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_support = 1; - break; - - case NAN_REQ_ATTR_BEACONS_2G4_VAL: - hal_req->beacon_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_beacons = 1; - break; - - case NAN_REQ_ATTR_SDF_2G4_VAL: - hal_req->sdf_2dot4g_val = nla_get_u8(iter); - hal_req->config_2dot4g_sdf = 1; - break; - - case NAN_REQ_ATTR_BEACON_5G_VAL: - hal_req->beacon_5g_val = nla_get_u8(iter); - hal_req->config_5g_beacons = 1; - break; - - case NAN_REQ_ATTR_SDF_5G_VAL: - hal_req->sdf_5g_val = nla_get_u8(iter); - hal_req->config_5g_sdf = 1; - break; - - case NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL: - hal_req->rssi_close_5g_val = nla_get_u8(iter); - hal_req->config_5g_rssi_close = 1; - break; - - case NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL: - hal_req->rssi_middle_5g_val = nla_get_u8(iter); - hal_req->config_5g_rssi_middle = 1; - break; - - case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL: - hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter); - hal_req->config_5g_rssi_close_proximity = 1; - break; - - case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL: - hal_req->rssi_window_size_val = nla_get_u8(iter); - hal_req->config_rssi_window_size = 1; - break; - - case NAN_REQ_ATTR_OUI_VAL: - hal_req->oui_val = nla_get_u32(iter); - hal_req->config_oui = 1; - break; - - case NAN_REQ_ATTR_MAC_ADDR_VAL: - memcpy(hal_req->intf_addr_val, nla_data(iter), ETH_ALEN); - hal_req->config_intf_addr = 1; - break; - - case NAN_REQ_ATTR_CLUSTER_VAL: - hal_req->config_cluster_attribute_val = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME: - memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter), - sizeof(hal_req->scan_params_val.dwell_time)); - hal_req->config_scan_params = 1; - break; - - case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD: - memcpy(hal_req->scan_params_val.scan_period, nla_data(iter), - sizeof(hal_req->scan_params_val.scan_period)); - hal_req->config_scan_params = 1; - break; - - case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL: - hal_req->random_factor_force_val = nla_get_u8(iter); - hal_req->config_random_factor_force = 1; - break; - - case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL: - hal_req->hop_count_force_val = nla_get_u8(iter); - hal_req->config_hop_count_force = 1; - break; - - case NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL: - hal_req->channel_24g_val = nla_get_u32(iter); - hal_req->config_24g_channel = 1; - break; - - case NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL: - hal_req->channel_5g_val = nla_get_u8(iter); - hal_req->config_5g_channel = 1; + case SLSI_NL_ATTRIBUTE_ND_OFFLOAD_VALUE: + { + nd_offload_enabled = nla_get_u8(attr); break; - + } default: - SLSI_ERR(sdev, "Unexpected NAN enable attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; + SLSI_ERR(sdev, "Invalid type : %d\n", type); + ret = -EINVAL; + goto exit; } } - return SLSI_HAL_NAN_STATUS_SUCCESS; + + ndev_vif->sta.nd_offload_enabled = nd_offload_enabled; + ret = slsi_mlme_set_ipv6_address(sdev, dev); + if (ret < 0) { + SLSI_ERR(sdev, "Configure nd_offload failed ret:%d nd_offload_enabled: %d\n", ret, nd_offload_enabled); + ret = -EINVAL; + goto exit; + } +exit: + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); + return ret; } -static int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) +static int slsi_get_roaming_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct slsi_hal_nan_enable_req hal_req; - int ret; - struct net_device *dev = slsi_nan_get_netdev(sdev); + struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); + struct net_device *dev = wdev->netdev; struct netdev_vif *ndev_vif; - u8 nan_vif_mac_address[ETH_ALEN]; - u8 broadcast_mac[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; + int ret = 0; + struct slsi_mib_value *values = NULL; + struct slsi_mib_data mibrsp = { 0, NULL }; + struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_ROAM_BLACKLIST_SIZE, { 0, 0 } } }; + u32 max_blacklist_size = 0; + u32 max_whitelist_size = 0; + struct sk_buff *nl_skb; + struct nlattr *nlattr_start; if (!dev) { - SLSI_ERR(sdev, "No NAN interface\n"); - ret = -ENOTSUPP; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - if (!slsi_dev_nan_supported(sdev)) { - SLSI_ERR(sdev, "NAN not allowed(mib:%d)\n", sdev->nan_enabled); - ret = WIFI_HAL_ERROR_NOT_SUPPORTED; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; + SLSI_ERR(sdev, "dev is NULL!!\n"); + return -EINVAL; } ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_enable_get_nl_params(sdev, &hal_req, data, len); - if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { - ret = -EINVAL; + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); + + mibrsp.dataLength = 10; + mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); + if (!mibrsp.data) { + SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); + ret = -ENOMEM; goto exit; } + values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp); + if (values && (values[0].type == SLSI_MIB_TYPE_UINT || values[0].type == SLSI_MIB_TYPE_INT)) + max_blacklist_size = values[0].u.uintValue; + nl_skb = cfg80211_vendor_cmd_alloc_reply_skb(sdev->wiphy, NLMSG_DEFAULT_SIZE); + if (!nl_skb) { + SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); + ret = -ENOMEM; + goto exit_with_mib_resp; + } - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (ndev_vif->activated) { + nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); + if (!nlattr_start) { + SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); ret = -EINVAL; - SLSI_DBG1_NODEV(SLSI_GSCAN, "NAN opearations in progress. Reject new req\n"); - goto exit_with_mutex; + goto exit_with_mib_resp; } - ndev_vif->vif_type = FAPI_VIFTYPE_NAN; - - if (hal_req.config_intf_addr) - ether_addr_copy(nan_vif_mac_address, hal_req.intf_addr_val); - else - slsi_nan_get_mac(sdev, nan_vif_mac_address); - ret = slsi_mlme_add_vif(sdev, dev, nan_vif_mac_address, broadcast_mac); + ret = nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_BLACKLIST_SIZE, max_blacklist_size); + ret |= nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_WHITELIST_SIZE, max_whitelist_size); if (ret) { - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - SLSI_ERR(sdev, "failed to set unsync vif. Cannot start NAN\n"); - } else { - ret = slsi_mlme_nan_enable(sdev, dev, &hal_req); - if (ret) { - SLSI_ERR(sdev, "failed to enable NAN.\n"); - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - slsi_mlme_del_vif(sdev, dev); - ndev_vif->activated = false; - ndev_vif->nan.subscribe_id_map = 0; - ndev_vif->nan.publish_id_map = 0; - } else { - slsi_vif_activated(sdev, dev); - } + SLSI_ERR(sdev, "Error in nla_put*:%x\n", ret); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + goto exit_with_mib_resp; } -exit_with_mutex: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); + ret = cfg80211_vendor_cmd_reply(nl_skb); + if (ret) + SLSI_ERR(sdev, "cfg80211_vendor_cmd_reply failed :%d\n", ret); +exit_with_mib_resp: + kfree(mibrsp.data); + kfree(values); exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_ENABLED, 0, NULL); + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); return ret; } -static int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) +static int slsi_set_roaming_state(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_dev *sdev = SDEV_FROM_WIPHY(wiphy); + struct net_device *dev = wdev->netdev; + int temp = 0; + int type = 0; + const struct nlattr *attr; + int ret = 0; + int roam_state = 0; - if (dev) { - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (ndev_vif->activated) { - slsi_mlme_del_vif(sdev, dev); - ndev_vif->activated = false; - ndev_vif->nan.subscribe_id_map = 0; - ndev_vif->nan.publish_id_map = 0; - } else { - SLSI_WARN(sdev, "NAN FWif not active!!"); - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - } else { - SLSI_WARN(sdev, "No NAN interface!!"); + if (!dev) { + SLSI_WARN_NODEV("net_dev is NULL\n"); + return -EINVAL; } - slsi_vendor_nan_command_reply(wiphy, SLSI_HAL_NAN_STATUS_SUCCESS, 0, NAN_RESPONSE_DISABLED, 0, NULL); - - return 0; -} - -static int slsi_nan_publish_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_publish_req *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); + nla_for_each_attr(attr, data, len, temp) { + type = nla_type(attr); switch (type) { - case NAN_REQ_ATTR_PUBLISH_ID: - hal_req->publish_id = nla_get_u16(iter); - break; - case NAN_REQ_ATTR_PUBLISH_TTL: - hal_req->ttl = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_PERIOD: - hal_req->period = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_TYPE: - hal_req->publish_type = nla_get_u16(iter); + case SLSI_NL_ATTR_ROAM_STATE: + roam_state = nla_get_u8(attr); break; + default: + SLSI_ERR_NODEV("Unknown attribute: %d\n", type); + ret = -EINVAL; + goto exit; + } + } - case NAN_REQ_ATTR_PUBLISH_TX_TYPE: - hal_req->tx_type = nla_get_u16(iter); - break; + SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_SET_ROAMING_STATE roam_state = %d\n", roam_state); + ret = slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAMING_ENABLED, roam_state); + if (ret < 0) + SLSI_ERR_NODEV("Failed to set roaming state\n"); - case NAN_REQ_ATTR_PUBLISH_COUNT: - hal_req->publish_count = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN: - hal_req->service_name_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME: - memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len); - break; - - case NAN_REQ_ATTR_PUBLISH_MATCH_ALGO: - hal_req->publish_match_indicator = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN: - hal_req->service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO: - memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); - break; - - case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN: - hal_req->rx_match_filter_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER: - memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len); - break; - - case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN: - hal_req->tx_match_filter_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER: - memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len); - break; - - case NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG: - hal_req->rssi_threshold_flag = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_CONN_MAP: - hal_req->connmap = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG: - hal_req->recv_indication_cfg = nla_get_u8(iter); - break; - - default: - SLSI_ERR(sdev, "Unexpected NAN publish attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -static int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct slsi_hal_nan_publish_req hal_req; - struct net_device *dev = slsi_nan_get_netdev(sdev); - struct netdev_vif *ndev_vif; - int ret; - u32 reply_status; - u32 publish_id = 0; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - ret = -EINVAL; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_publish_get_nl_params(sdev, &hal_req, data, len); - if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { - ret = -EINVAL; - 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; - } - - if (!hal_req.publish_id) { - hal_req.publish_id = slsi_nan_get_new_publish_id(ndev_vif); - } else if (!slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_id)) { - SLSI_WARN(sdev, "Publish id %d not found. map:%x\n", hal_req.publish_id, - ndev_vif->nan.publish_id_map); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - ret = -EINVAL; - goto exit_with_lock; - } - - if (hal_req.publish_id) { - ret = slsi_mlme_nan_publish(sdev, dev, &hal_req, hal_req.publish_id); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - else - publish_id = hal_req.publish_id; - } else { - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - SLSI_WARN(sdev, "Too Many concurrent PUBLISH REQ(map:%x)\n", - ndev_vif->nan.publish_id_map); - ret = -ENOTSUPP; - } -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH, publish_id, NULL); - return ret; -} - -static int slsi_nan_publish_cancel(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; - int type, tmp, ret = 0; - u16 publish_id = 0; - const struct nlattr *iter; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = -EINVAL; - goto exit; - } - - ndev_vif = netdev_priv(dev); - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_PUBLISH_ID: - publish_id = nla_get_u16(iter); - break; - default: - SLSI_ERR(sdev, "Unexpected NAN publishcancel attribute TYPE:%d\n", type); - } - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (!ndev_vif->activated) { - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - goto exit_with_lock; - } - if (!publish_id || !slsi_nan_is_publish_id_active(ndev_vif, publish_id)) { - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - SLSI_WARN(sdev, "Publish_id(%d) not active. map:%x\n", - publish_id, ndev_vif->nan.publish_id_map); - } else { - ret = slsi_mlme_nan_publish(sdev, dev, NULL, publish_id); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - } -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH_CANCEL, publish_id, NULL); - return ret; -} - -static int slsi_nan_subscribe_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_subscribe_req *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); - switch (type) { - case NAN_REQ_ATTR_SUBSCRIBE_ID: - hal_req->subscribe_id = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_TTL: - hal_req->ttl = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_PERIOD: - hal_req->period = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_TYPE: - hal_req->subscribe_type = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE: - hal_req->service_response_filter = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE: - hal_req->service_response_include = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER: - hal_req->use_service_response_filter = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED: - hal_req->ssi_required_for_match_indication = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR: - hal_req->subscribe_match_indicator = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_COUNT: - hal_req->subscribe_count = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN: - hal_req->service_name_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME: - memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN: - hal_req->service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO: - memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN: - hal_req->rx_match_filter_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER: - memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN: - hal_req->tx_match_filter_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER: - memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG: - hal_req->rssi_threshold_flag = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP: - hal_req->connmap = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT: - hal_req->num_intf_addr_present = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR: - memcpy(hal_req->intf_addr, nla_data(iter), hal_req->num_intf_addr_present * ETH_ALEN); - break; - - case NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG: - hal_req->recv_indication_cfg = nla_get_u8(iter); - break; - - default: - SLSI_ERR(sdev, "Unexpected NAN subscribe attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -static int slsi_nan_subscribe(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_subscribe_req *hal_req; - int ret; - u32 reply_status; - u32 subscribe_id = 0; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!\n"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = -EINVAL; - 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 = -ENOMEM; - goto exit; - } - - ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_subscribe_get_nl_params(sdev, hal_req, data, len); - if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { - kfree(hal_req); - ret = -EINVAL; - 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; - } - - if (!hal_req->subscribe_id) { - hal_req->subscribe_id = slsi_nan_get_new_subscribe_id(ndev_vif); - } else if (!slsi_nan_is_subscribe_id_active(ndev_vif, hal_req->subscribe_id)) { - SLSI_WARN(sdev, "Subscribe id %d not found. map:%x\n", hal_req->subscribe_id, - ndev_vif->nan.subscribe_id_map); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - ret = -EINVAL; - goto exit_with_lock; - } - - ret = slsi_mlme_nan_subscribe(sdev, dev, hal_req, hal_req->subscribe_id); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - else - subscribe_id = hal_req->subscribe_id; - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - kfree(hal_req); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE, subscribe_id, NULL); - return ret; -} - -static int slsi_nan_subscribe_cancel(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; - int type, tmp, ret = WIFI_HAL_ERROR_UNKNOWN; - u16 subscribe_id = 0; - const struct nlattr *iter; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - goto exit; - } - - ndev_vif = netdev_priv(dev); - - nla_for_each_attr(iter, data, len, tmp) { - type = nla_type(iter); - switch (type) { - case NAN_REQ_ATTR_SUBSCRIBE_ID: - subscribe_id = nla_get_u16(iter); - break; - default: - SLSI_ERR(sdev, "Unexpected NAN subscribecancel attribute TYPE:%d\n", type); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM; - goto exit; - } - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - if (ndev_vif->activated) { - if (!subscribe_id || !slsi_nan_is_subscribe_id_active(ndev_vif, subscribe_id)) { - SLSI_WARN(sdev, "subscribe_id(%d) not active. map:%x\n", - subscribe_id, ndev_vif->nan.subscribe_id_map); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - } else { - ret = slsi_mlme_nan_subscribe(sdev, dev, NULL, subscribe_id); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - } - } else { - SLSI_ERR(sdev, "vif not activated\n"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = WIFI_HAL_ERROR_NOT_AVAILABLE; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE_CANCEL, subscribe_id, NULL); - return ret; -} - -static int slsi_nan_followup_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_transmit_followup_req *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); - switch (type) { - case NAN_REQ_ATTR_FOLLOWUP_ID: - hal_req->publish_subscribe_id = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID: - hal_req->requestor_instance_id = nla_get_u32(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_ADDR: - memcpy(hal_req->addr, nla_data(iter), ETH_ALEN); - break; - - case NAN_REQ_ATTR_FOLLOWUP_PRIORITY: - hal_req->priority = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW: - hal_req->dw_or_faw = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN: - hal_req->service_specific_info_len = nla_get_u16(iter); - break; - - case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME: - memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); - break; - - case NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG: - hal_req->recv_indication_cfg = nla_get_u8(iter); - break; - - default: - SLSI_ERR(sdev, "Unexpected NAN followup attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -static int slsi_nan_transmit_followup(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_transmit_followup_req hal_req; - int ret; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - ret = -EINVAL; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_followup_get_nl_params(sdev, &hal_req, data, len); - if (reply_status) { - ret = -EINVAL; - 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; - } - - if (!hal_req.publish_subscribe_id || - !(slsi_nan_is_subscribe_id_active(ndev_vif, hal_req.publish_subscribe_id) || - slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_subscribe_id))) { - SLSI_WARN(sdev, "publish/Subscribe id %d not found. map:%x\n", hal_req.publish_subscribe_id, - ndev_vif->nan.subscribe_id_map); - reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; - ret = -EINVAL; - goto exit_with_lock; - } - - ret = slsi_mlme_nan_tx_followup(sdev, dev, &hal_req); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - -exit_with_lock: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_TRANSMIT_FOLLOWUP, 0, NULL); - return ret; -} - -static int slsi_nan_config_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_config_req *hal_req, - const void *data, int len) -{ - int type, type1, tmp, tmp1, disc_attr_idx = 0, famchan_idx = 0; - const struct nlattr *iter, *iter1; - struct slsi_hal_nan_post_discovery_param *disc_attr; - struct slsi_hal_nan_further_availability_channel *famchan; - - 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_SID_BEACON_VAL: - hal_req->sid_beacon = nla_get_u8(iter); - hal_req->config_sid_beacon = 1; - break; - - case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL: - hal_req->rssi_proximity = nla_get_u8(iter); - hal_req->config_rssi_proximity = 1; - break; - - case NAN_REQ_ATTR_MASTER_PREF: - hal_req->master_pref = nla_get_u8(iter); - hal_req->config_master_pref = 1; - break; - - case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL: - hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter); - hal_req->config_5g_rssi_close_proximity = 1; - break; - - case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL: - hal_req->rssi_window_size_val = nla_get_u8(iter); - hal_req->config_rssi_window_size = 1; - break; - - case NAN_REQ_ATTR_CLUSTER_VAL: - hal_req->config_cluster_attribute_val = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME: - memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter), - sizeof(hal_req->scan_params_val.dwell_time)); - hal_req->config_scan_params = 1; - break; - - case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD: - memcpy(hal_req->scan_params_val.scan_period, nla_data(iter), - sizeof(hal_req->scan_params_val.scan_period)); - hal_req->config_scan_params = 1; - break; - - case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL: - hal_req->random_factor_force_val = nla_get_u8(iter); - hal_req->config_random_factor_force = 1; - break; - - case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL: - hal_req->hop_count_force_val = nla_get_u8(iter); - hal_req->config_hop_count_force = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX: - hal_req->conn_capability_val.payload_transmit_flag = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_WFD: - hal_req->conn_capability_val.is_wfd_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_WFDS: - hal_req->conn_capability_val.is_wfds_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_TDLS: - hal_req->conn_capability_val.is_tdls_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_MESH: - hal_req->conn_capability_val.is_mesh_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_IBSS: - hal_req->conn_capability_val.is_ibss_supported = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA: - hal_req->conn_capability_val.wlan_infra_field = nla_get_u8(iter); - hal_req->config_conn_capability = 1; - break; - - case NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES: - hal_req->num_config_discovery_attr = nla_get_u8(iter); - break; - - case NAN_REQ_ATTR_DISCOVERY_ATTR_VAL: - if (disc_attr_idx >= hal_req->num_config_discovery_attr) { - SLSI_ERR(sdev, - "disc attr(%d) > num disc attr(%d)\n", - disc_attr_idx + 1, hal_req->num_config_discovery_attr); - return -EINVAL; - } - disc_attr = &hal_req->discovery_attr_val[disc_attr_idx]; - disc_attr_idx++; - nla_for_each_nested(iter1, iter, tmp1) { - type1 = nla_type(iter1); - switch (type1) { - case NAN_REQ_ATTR_CONN_TYPE: - disc_attr->type = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_NAN_ROLE: - disc_attr->role = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_TRANSMIT_FREQ: - disc_attr->transmit_freq = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_AVAILABILITY_DURATION: - disc_attr->duration = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_AVAILABILITY_INTERVAL: - disc_attr->avail_interval_bitmap = nla_get_u32(iter1); - break; - - case NAN_REQ_ATTR_MAC_ADDR_VAL: - memcpy(disc_attr->addr, nla_data(iter1), ETH_ALEN); - break; - - case NAN_REQ_ATTR_MESH_ID_LEN: - disc_attr->mesh_id_len = nla_get_u16(iter1); - break; - - case NAN_REQ_ATTR_MESH_ID: - memcpy(disc_attr->mesh_id, nla_data(iter1), disc_attr->mesh_id_len); - break; - - case NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN: - disc_attr->infrastructure_ssid_len = nla_get_u16(iter1); - break; - - case NAN_REQ_ATTR_INFRASTRUCTURE_SSID: - memcpy(disc_attr->infrastructure_ssid_val, nla_data(iter1), - disc_attr->infrastructure_ssid_len); - break; - } - } - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES: - hal_req->fam_val.numchans = nla_get_u8(iter); - hal_req->config_fam = 1; - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_VAL: - hal_req->config_fam = 1; - if (famchan_idx >= hal_req->fam_val.numchans) { - SLSI_ERR(sdev, - "famchan attr(%d) > numchans(%d)\n", - famchan_idx + 1, hal_req->fam_val.numchans); - return -EINVAL; - } - famchan = &hal_req->fam_val.famchan[famchan_idx]; - famchan_idx++; - nla_for_each_nested(iter1, iter, tmp1) { - type1 = nla_type(iter1); - switch (type1) { - case NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL: - famchan->entry_control = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS: - famchan->class_val = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN: - famchan->channel = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID: - famchan->mapid = nla_get_u8(iter1); - break; - - case NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP: - famchan->avail_interval_bitmap = nla_get_u32(iter1); - break; - } - } - break; - default: - SLSI_ERR(sdev, "Unexpected NAN config attribute TYPE:%d\n", type); - return SLSI_HAL_NAN_STATUS_INVALID_PARAM; - } - } - return SLSI_HAL_NAN_STATUS_SUCCESS; -} - -static int slsi_nan_set_config(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_config_req hal_req; - int ret; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - ret = -EINVAL; - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - goto exit; - } - - ndev_vif = netdev_priv(dev); - reply_status = slsi_nan_config_get_nl_params(sdev, &hal_req, data, len); - if (reply_status) { - ret = -EINVAL; - 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; - } else { - ret = slsi_mlme_nan_set_config(sdev, dev, &hal_req); - if (ret) - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - } - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_CONFIG, 0, NULL); - return ret; -} - -static int slsi_nan_get_capabilities(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; - u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; - struct slsi_hal_nan_capabilities nan_capabilities; - int ret = 0, i; - struct slsi_mib_value *values = NULL; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_CLUSTERS, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_PUBLISHES, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_SUBSCRIBES, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_NAME_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_MATCH_FILTER_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_TOTAL_MATCH_FILTER_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_SPECIFIC_INFO_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_VSA_DATA_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_MESH_DATA_LENGTH, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_NDI_INTERFACES, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_NDP_SESSIONS, { 0, 0 } }, - { SLSI_PSID_UNIFI_NAN_MAX_APP_INFO_LENGTH, { 0, 0 } } }; - u32 *capabilities_mib_val[] = { &nan_capabilities.max_concurrent_nan_clusters, - &nan_capabilities.max_publishes, - &nan_capabilities.max_subscribes, - &nan_capabilities.max_service_name_len, - &nan_capabilities.max_match_filter_len, - &nan_capabilities.max_total_match_filter_len, - &nan_capabilities.max_service_specific_info_len, - &nan_capabilities.max_vsa_data_len, - &nan_capabilities.max_mesh_data_len, - &nan_capabilities.max_ndi_interfaces, - &nan_capabilities.max_ndp_sessions, - &nan_capabilities.max_app_info_len }; - - if (!dev) { - SLSI_ERR(sdev, "NAN netif not active!!"); - reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; - ret = -EINVAL; - goto exit; - } - - ndev_vif = netdev_priv(dev); - - /* Expect each mib length in response is 11 */ - mibrsp.dataLength = 11 * ARRAY_SIZE(get_values); - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE; - ret = -ENOMEM; - goto exit; - } - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp); - if (!values) { - ret = 0xFFFFFFFF; - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - goto exit_with_mibrsp; - } - - for (i = 0; i < ARRAY_SIZE(get_values); i++) { - if (values[i].type == SLSI_MIB_TYPE_UINT) { - *capabilities_mib_val[i] = values[i].u.uintValue; - SLSI_DBG2(sdev, SLSI_GSCAN, "MIB value = %ud\n", *capabilities_mib_val[i]); - } else { - SLSI_ERR(sdev, "invalid type(%d). iter:%d\n", values[i].type, i); - ret = 0xFFFFFFFF; - reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; - *capabilities_mib_val[i] = 0; - } - } - - kfree(values); -exit_with_mibrsp: - kfree(mibrsp.data); - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); -exit: - slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_GET_CAPABILITIES, 0, &nan_capabilities); - return ret; -} - -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 nlattr *nlattr_start; - 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); - evt_reason = fapi_get_u16(skb, u.mlme_nan_event_ind.reason_code); - - switch (event) { - case FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED: - hal_event = SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT; - break; - case FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED: - hal_event = SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT; - break; - case FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED: - 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; - 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; - 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; - break; - default: - return; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", - slsi_print_event_name(hal_event), hal_event); -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - 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"); - return; - } - - nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); - if (!nlattr_start) { - SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - return; - } - - switch (hal_event) { - case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT: - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, identifier); - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, evt_reason); - ndev_vif->nan.publish_id_map &= ~BIT(identifier); - break; - case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT: - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, identifier); - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, evt_reason); - break; - case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT: - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_ID, identifier); - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_REASON, evt_reason); - ndev_vif->nan.subscribe_id_map &= ~BIT(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; - } - - if (res) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - return; - } - - nla_nest_end(nl_skb, nlattr_start); - - cfg80211_vendor_event(nl_skb, GFP_KERNEL); -} - -void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 tag_id, tag_len; - u8 *fapi_data_p, *ptr; - u8 followup_ie_header[] = {0xdd, 0, 0, 0x16, 0x32, 0x0b, 0x05}; - int fapi_data_len; - struct slsi_hal_nan_followup_ind *hal_evt; - struct sk_buff *nl_skb; - int res; - struct nlattr *nlattr_start; - - hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL); - if (!hal_evt) { - SLSI_ERR(sdev, "No memory for service_ind\n"); - return; - } - hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.publish_subscribe_id); - hal_evt->requestor_instance_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.requestor_instance_id); - fapi_data_p = fapi_get_data(skb); - fapi_data_len = fapi_get_datalen(skb); - if (!fapi_data_len) { - SLSI_ERR(sdev, "mlme_nan_followup_ind no mbulk data\n"); - kfree(hal_evt); - return; - } - - memset(&hal_evt, 0, sizeof(hal_evt)); - - while (fapi_data_len) { - ptr = fapi_data_p; - if (fapi_data_len < ptr[1] + 2) { - SLSI_ERR(sdev, "len err[avail:%d,ie:%d]\n", fapi_data_len, fapi_data_p[1] + 2); - kfree(hal_evt); - return; - } - if (ptr[1] < sizeof(followup_ie_header) - 2 + 6 + 1 + 1) { - SLSI_ERR(sdev, "len err[min:%d,ie:%d]\n", (u32)sizeof(followup_ie_header) - 2 + 6 + 1 + 1, - fapi_data_p[1] + 2); - kfree(hal_evt); - return; - } - if (followup_ie_header[0] != ptr[0] || followup_ie_header[2] != ptr[2] || - followup_ie_header[3] != ptr[3] || followup_ie_header[4] != ptr[4] || - followup_ie_header[5] != ptr[5] || followup_ie_header[6] != ptr[6]) { - SLSI_ERR(sdev, "unknown IE:%x-%d\n", fapi_data_p[0], fapi_data_p[1] + 2); - kfree(hal_evt); - return; - } - - ptr += sizeof(followup_ie_header); - - ether_addr_copy(hal_evt->addr, ptr); - ptr += ETH_ALEN; - ptr += 1; /* skip priority */ - hal_evt->dw_or_faw = *ptr; - ptr += 1; - while (fapi_data_p[1] + 2 > (ptr - fapi_data_p) + 4) { - tag_id = *(u16 *)ptr; - ptr += 2; - tag_len = *(u16 *)ptr; - ptr += 2; - if (fapi_data_p[1] + 2 < (ptr - fapi_data_p) + tag_len) { - SLSI_ERR(sdev, "TLV error\n"); - kfree(hal_evt); - return; - } - if (tag_id == SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO) { - hal_evt->service_specific_info_len = tag_len; - memcpy(hal_evt->service_specific_info, ptr, tag_len); - } - ptr += tag_len; - } - - fapi_data_p += fapi_data_p[1] + 2; - fapi_data_len -= fapi_data_p[1] + 2; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", - slsi_print_event_name(SLSI_NL80211_NAN_FOLLOWUP_EVENT), SLSI_NL80211_NAN_FOLLOWUP_EVENT); -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT, - GFP_KERNEL); -#else - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT, - GFP_KERNEL); -#endif - - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - kfree(hal_evt); - return; - } - - nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); - if (!nlattr_start) { - SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); - kfree(hal_evt); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - return; - } - - res = nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID, - cpu_to_le16(hal_evt->publish_subscribe_id)); - res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID, - cpu_to_le16(hal_evt->requestor_instance_id)); - res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_ADDR, ETH_ALEN, hal_evt->addr); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW, hal_evt->dw_or_faw); - res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len); - if (hal_evt->service_specific_info_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len, - hal_evt->service_specific_info); - - if (res) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); - kfree(hal_evt); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - return; - } - - nla_nest_end(nl_skb, nlattr_start); - - cfg80211_vendor_event(nl_skb, GFP_KERNEL); - kfree(hal_evt); -} - -void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) -{ - u16 tag_id, tag_len; - u8 *fapi_data_p, *ptr; - u8 match_ie_header[] = {0xdd, 0, 0, 0x16, 0x32, 0x0b, 0x04}; - int fapi_data_len; - struct slsi_hal_nan_match_ind *hal_evt; - struct sk_buff *nl_skb; - int res, i; - struct slsi_hal_nan_receive_post_discovery *discovery_attr; - struct slsi_hal_nan_further_availability_channel *famchan; - struct nlattr *nlattr_start, *nlattr_nested; - - SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); - - hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL); - if (!hal_evt) { - SLSI_ERR(sdev, "No memory for service_ind\n"); - return; - } - - hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_service_ind.publish_subscribe_id); - hal_evt->requestor_instance_id = fapi_get_u32(skb, u.mlme_nan_service_ind.requestor_instance_id); - fapi_data_p = fapi_get_data(skb); - fapi_data_len = fapi_get_datalen(skb); - if (!fapi_data_len) { - SLSI_ERR(sdev, "mlme_nan_followup_ind no mbulk data\n"); - kfree(hal_evt); - return; - } - - memset(hal_evt, 0, sizeof(*hal_evt)); - - while (fapi_data_len) { - ptr = fapi_data_p; - if (fapi_data_len < ptr[1] + 2) { - SLSI_ERR(sdev, "len err[avail:%d,ie:%d]\n", fapi_data_len, fapi_data_p[1] + 2); - kfree(hal_evt); - return; - } - if (ptr[1] < sizeof(match_ie_header) - 2 + 6 + 1 + 1 + 1) { - SLSI_ERR(sdev, "len err[min:%d,ie:%d]\n", (u32)sizeof(match_ie_header) - 2 + 6 + 1 + 1, - fapi_data_p[1] + 2); - kfree(hal_evt); - return; - } - if (match_ie_header[0] != ptr[0] || match_ie_header[2] != ptr[2] || - match_ie_header[3] != ptr[3] || match_ie_header[4] != ptr[4] || - match_ie_header[5] != ptr[5] || match_ie_header[6] != ptr[6]) { - SLSI_ERR(sdev, "unknown IE:%x-%d\n", fapi_data_p[0], fapi_data_p[1] + 2); - kfree(hal_evt); - return; - } - - ptr += sizeof(match_ie_header); - - ether_addr_copy(hal_evt->addr, ptr); - ptr += ETH_ALEN; - hal_evt->match_occurred_flag = *ptr; - ptr += 1; - hal_evt->out_of_resource_flag = *ptr; - ptr += 1; - hal_evt->rssi_value = *ptr; - ptr += 1; - while (fapi_data_p[1] + 2 > (ptr - fapi_data_p) + 4) { - tag_id = *(u16 *)ptr; - ptr += 2; - tag_len = *(u16 *)ptr; - ptr += 2; - if (fapi_data_p[1] + 2 < (ptr - fapi_data_p) + tag_len) { - SLSI_ERR(sdev, "TLV error\n"); - kfree(hal_evt); - return; - } - switch (tag_id) { - case SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO: - hal_evt->service_specific_info_len = tag_len; - memcpy(hal_evt->service_specific_info, ptr, tag_len); - break; - case SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB: - hal_evt->is_conn_capability_valid = 1; - if (*ptr & BIT(0)) - hal_evt->conn_capability.is_wfd_supported = 1; - if (*ptr & BIT(1)) - hal_evt->conn_capability.is_wfds_supported = 1; - if (*ptr & BIT(2)) - hal_evt->conn_capability.is_tdls_supported = 1; - if (*ptr & BIT(3)) - hal_evt->conn_capability.wlan_infra_field = 1; - break; - case SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM: - discovery_attr = &hal_evt->discovery_attr[hal_evt->num_rx_discovery_attr]; - discovery_attr->type = ptr[0]; - discovery_attr->role = ptr[1]; - discovery_attr->duration = ptr[2]; - discovery_attr->avail_interval_bitmap = le32_to_cpu(*(__le32 *)&ptr[3]); - ether_addr_copy(discovery_attr->addr, &ptr[7]); - discovery_attr->infrastructure_ssid_len = ptr[13]; - if (discovery_attr->infrastructure_ssid_len) - memcpy(discovery_attr->infrastructure_ssid_val, &ptr[14], - discovery_attr->infrastructure_ssid_len); - hal_evt->num_rx_discovery_attr++; - break; - case SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP: - famchan = &hal_evt->famchan[hal_evt->num_chans]; - famchan->entry_control = ptr[0]; - famchan->class_val = ptr[1]; - famchan->channel = ptr[2]; - famchan->mapid = ptr[3]; - famchan->avail_interval_bitmap = le32_to_cpu(*(__le32 *)&ptr[4]); - hal_evt->num_chans++; - break; - case SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE: - break; - } - ptr += tag_len; - } - - fapi_data_p += fapi_data_p[1] + 2; - fapi_data_len -= fapi_data_p[1] + 2; - } - -#ifdef CONFIG_SCSC_WLAN_DEBUG - SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", - slsi_print_event_name(SLSI_NL80211_NAN_MATCH_EVENT), SLSI_NL80211_NAN_MATCH_EVENT); -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT, - GFP_KERNEL); -#else - nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT, GFP_KERNEL); -#endif - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - kfree(hal_evt); - return; - } - - nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); - if (!nlattr_start) { - SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); - kfree(hal_evt); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - return; - } - - res = nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, hal_evt->publish_subscribe_id); - res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, hal_evt->requestor_instance_id); - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_ADDR, ETH_ALEN, hal_evt->addr); - res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len); - if (hal_evt->service_specific_info_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len, - hal_evt->service_specific_info); - res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN, hal_evt->sdf_match_filter_len); - if (hal_evt->sdf_match_filter_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER, hal_evt->sdf_match_filter_len, - hal_evt->sdf_match_filter); - - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG, hal_evt->match_occurred_flag); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG, hal_evt->out_of_resource_flag); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_RSSI_VALUE, hal_evt->rssi_value); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED, - hal_evt->is_conn_capability_valid); - if (hal_evt->is_conn_capability_valid) { - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED, - hal_evt->conn_capability.is_ibss_supported); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED, - hal_evt->conn_capability.is_wfd_supported); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED, - hal_evt->conn_capability.is_wfds_supported); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED, - hal_evt->conn_capability.is_tdls_supported); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED, - hal_evt->conn_capability.is_mesh_supported); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD, - hal_evt->conn_capability.wlan_infra_field); - } - - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR, hal_evt->num_rx_discovery_attr); - for (i = 0; i < hal_evt->num_rx_discovery_attr; i++) { - nlattr_nested = nla_nest_start(nl_skb, NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR); - if (!nlattr_nested) { - SLSI_ERR(sdev, "Error in nla_nest_start\n"); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - kfree(hal_evt); - return; - } - discovery_attr = &hal_evt->discovery_attr[i]; - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE, discovery_attr->type); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE, discovery_attr->role); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION, discovery_attr->duration); - res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP, - discovery_attr->avail_interval_bitmap); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID, discovery_attr->mapid); - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR, ETH_ALEN, discovery_attr->addr); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN, discovery_attr->mesh_id_len); - if (discovery_attr->mesh_id_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID, discovery_attr->mesh_id_len, - discovery_attr->mesh_id); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN, - discovery_attr->infrastructure_ssid_len); - if (discovery_attr->infrastructure_ssid_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL, - discovery_attr->infrastructure_ssid_len, discovery_attr->infrastructure_ssid_val); - nla_nest_end(nl_skb, nlattr_nested); - } - - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_NUM_CHANS, hal_evt->num_chans); - for (i = 0; i < hal_evt->num_chans; i++) { - nlattr_nested = nla_nest_start(nl_skb, NAN_EVT_ATTR_MATCH_FAMCHAN); - if (!nlattr_nested) { - SLSI_ERR(sdev, "Error in nla_nest_start\n"); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - kfree(hal_evt); - return; - } - famchan = &hal_evt->famchan[i]; - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL, famchan->entry_control); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL, famchan->class_val); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_CHANNEL, famchan->channel); - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_MAPID, famchan->mapid); - res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP, - famchan->avail_interval_bitmap); - } - - res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN, hal_evt->cluster_attribute_len); - if (hal_evt->cluster_attribute_len) - res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE, hal_evt->cluster_attribute_len, - hal_evt->cluster_attribute); - - if (res) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - kfree(hal_evt); - return; - } - - nla_nest_end(nl_skb, nlattr_start); - - cfg80211_vendor_event(nl_skb, GFP_KERNEL); - kfree(hal_evt); -} - -static int slsi_configure_nd_offload(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - struct netdev_vif *ndev_vif; - int ret = 0; - int temp; - int type; - const struct nlattr *attr; - u8 nd_offload_enabled = 0; - - SLSI_DBG3(sdev, SLSI_GSCAN, "Received nd_offload command\n"); - - if (!dev) { - SLSI_ERR(sdev, "dev is NULL!!\n"); - return -EINVAL; - } - - ndev_vif = netdev_priv(dev); - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - if (!ndev_vif->activated || (ndev_vif->vif_type != FAPI_VIFTYPE_STATION) || - (ndev_vif->sta.vif_status != SLSI_VIF_STATUS_CONNECTED)) { - SLSI_DBG3(sdev, SLSI_GSCAN, "vif error\n"); - ret = -EPERM; - goto exit; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_NL_ATTRIBUTE_ND_OFFLOAD_VALUE: - { - nd_offload_enabled = nla_get_u8(attr); - break; - } - default: - SLSI_ERR(sdev, "Invalid type : %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - ndev_vif->sta.nd_offload_enabled = nd_offload_enabled; - ret = slsi_mlme_set_ipv6_address(sdev, dev); - if (ret < 0) { - SLSI_ERR(sdev, "Configure nd_offload failed ret:%d nd_offload_enabled: %d\n", ret, nd_offload_enabled); - ret = -EINVAL; - goto exit; - } -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return ret; -} - -static int slsi_get_roaming_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - struct netdev_vif *ndev_vif; - int ret = 0; - struct slsi_mib_value *values = NULL; - struct slsi_mib_data mibrsp = { 0, NULL }; - struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_ROAM_BLACKLIST_SIZE, { 0, 0 } } }; - u32 max_blacklist_size = 0; - u32 max_whitelist_size = 0; - struct sk_buff *nl_skb; - struct nlattr *nlattr_start; - - if (!dev) { - SLSI_ERR(sdev, "dev is NULL!!\n"); - return -EINVAL; - } - - ndev_vif = netdev_priv(dev); - - SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); - - mibrsp.dataLength = 10; - mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); - if (!mibrsp.data) { - SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); - ret = -ENOMEM; - goto exit; - } - values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp); - if (values && (values[0].type == SLSI_MIB_TYPE_UINT || values[0].type == SLSI_MIB_TYPE_INT)) - max_blacklist_size = values[0].u.uintValue; - nl_skb = cfg80211_vendor_cmd_alloc_reply_skb(sdev->wiphy, NLMSG_DEFAULT_SIZE); - if (!nl_skb) { - SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); - ret = -ENOMEM; - goto exit_with_mib_resp; - } - - nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); - if (!nlattr_start) { - SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - ret = -EINVAL; - goto exit_with_mib_resp; - } - - ret = nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_BLACKLIST_SIZE, max_blacklist_size); - ret |= nla_put_u32(nl_skb, SLSI_NL_ATTR_MAX_WHITELIST_SIZE, max_whitelist_size); - if (ret) { - SLSI_ERR(sdev, "Error in nla_put*:%x\n", ret); - /* Dont use slsi skb wrapper for this free */ - kfree_skb(nl_skb); - goto exit_with_mib_resp; - } - - ret = cfg80211_vendor_cmd_reply(nl_skb); - if (ret) - SLSI_ERR(sdev, "cfg80211_vendor_cmd_reply failed :%d\n", ret); -exit_with_mib_resp: - kfree(mibrsp.data); - kfree(values); -exit: - SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); - return ret; -} - -static int slsi_set_roaming_state(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) -{ - struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); - struct net_device *dev = wdev->netdev; - int temp = 0; - int type = 0; - const struct nlattr *attr; - int ret = 0; - int roam_state = 0; - - if (!dev) { - SLSI_WARN_NODEV("net_dev is NULL\n"); - return -EINVAL; - } - - nla_for_each_attr(attr, data, len, temp) { - type = nla_type(attr); - switch (type) { - case SLSI_NL_ATTR_ROAM_STATE: - roam_state = nla_get_u8(attr); - break; - default: - SLSI_ERR_NODEV("Unknown attribute: %d\n", type); - ret = -EINVAL; - goto exit; - } - } - - SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_SET_ROAMING_STATE roam_state = %d\n", roam_state); - ret = slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAMING_ENABLED, roam_state); - if (ret < 0) - SLSI_ERR_NODEV("Failed to set roaming state\n"); - -exit: - return ret; -} +exit: + return ret; +} char *slsi_get_roam_reason_str(int roam_reason) { @@ -6845,6 +5173,7 @@ static const struct wiphy_vendor_command slsi_vendor_cmd[] = { .doit = slsi_get_wake_reason_stats }, #endif /* CONFIG_SCSC_WLAN_ENHANCED_LOGGING */ +#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE { { .vendor_id = OUI_GOOGLE, @@ -6917,6 +5246,7 @@ static const struct wiphy_vendor_command slsi_vendor_cmd[] = { .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, .doit = slsi_nan_get_capabilities }, +#endif { { .vendor_id = OUI_GOOGLE, diff --git a/drivers/net/wireless/scsc/nl80211_vendor.h b/drivers/net/wireless/scsc/nl80211_vendor.h index 164c96e224e3..ec2c4aaa4fdb 100755 --- a/drivers/net/wireless/scsc/nl80211_vendor.h +++ b/drivers/net/wireless/scsc/nl80211_vendor.h @@ -3,6 +3,9 @@ * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved * ****************************************************************************/ + +#include "nl80211_vendor_nan.h" + #ifndef __SLSI_NL80211_VENDOR_H_ #define __SLSI_NL80211_VENDOR_H_ @@ -123,205 +126,6 @@ enum slsi_acs_hw_mode { SLSI_ACS_MODE_IEEE80211ANY, }; -enum SLSI_NAN_REPLY_ATTRIBUTES { - NAN_REPLY_ATTR_STATUS_TYPE, - NAN_REPLY_ATTR_VALUE, - NAN_REPLY_ATTR_RESPONSE_TYPE, - NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, - NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER, - NAN_REPLY_ATTR_CAP_MAX_PUBLISHES, - NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES, - NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN, - NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN, - NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN, - NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN, - NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN, - NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN, - NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, - NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, - NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN -}; - -enum SLSI_NAN_REQ_ATTRIBUTES { - NAN_REQ_ATTR_MASTER_PREF, - NAN_REQ_ATTR_CLUSTER_LOW, - NAN_REQ_ATTR_CLUSTER_HIGH, - NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL, - NAN_REQ_ATTR_SID_BEACON_VAL, - NAN_REQ_ATTR_SUPPORT_2G4_VAL, - NAN_REQ_ATTR_SUPPORT_5G_VAL, - NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL, - NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL, - NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL, - NAN_REQ_ATTR_BEACONS_2G4_VAL, - NAN_REQ_ATTR_SDF_2G4_VAL, - NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL, - NAN_REQ_ATTR_RSSI_PROXIMITY_VAL, - NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL, - NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL, - NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL, - NAN_REQ_ATTR_RSSI_PROXIMITY_5G_VAL, - NAN_REQ_ATTR_BEACON_5G_VAL, - NAN_REQ_ATTR_SDF_5G_VAL, - NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL, - NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL, - NAN_REQ_ATTR_OUI_VAL, - NAN_REQ_ATTR_MAC_ADDR_VAL, - NAN_REQ_ATTR_CLUSTER_VAL, - NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME, - NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD, - NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL, - NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL, - NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX, - NAN_REQ_ATTR_CONN_CAPABILITY_IBSS, - NAN_REQ_ATTR_CONN_CAPABILITY_WFD, - NAN_REQ_ATTR_CONN_CAPABILITY_WFDS, - NAN_REQ_ATTR_CONN_CAPABILITY_TDLS, - NAN_REQ_ATTR_CONN_CAPABILITY_MESH, - NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA, - NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES, - NAN_REQ_ATTR_DISCOVERY_ATTR_VAL, - NAN_REQ_ATTR_CONN_TYPE, - NAN_REQ_ATTR_NAN_ROLE, - NAN_REQ_ATTR_TRANSMIT_FREQ, - NAN_REQ_ATTR_AVAILABILITY_DURATION, - NAN_REQ_ATTR_AVAILABILITY_INTERVAL, - NAN_REQ_ATTR_MESH_ID_LEN, - NAN_REQ_ATTR_MESH_ID, - NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN, - NAN_REQ_ATTR_INFRASTRUCTURE_SSID, - NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES, - NAN_REQ_ATTR_FURTHER_AVAIL_VAL, - NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL, - NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS, - NAN_REQ_ATTR_FURTHER_AVAIL_CHAN, - NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID, - NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP, - NAN_REQ_ATTR_PUBLISH_ID, - NAN_REQ_ATTR_PUBLISH_TTL, - NAN_REQ_ATTR_PUBLISH_PERIOD, - NAN_REQ_ATTR_PUBLISH_TYPE, - NAN_REQ_ATTR_PUBLISH_TX_TYPE, - NAN_REQ_ATTR_PUBLISH_COUNT, - NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN, - NAN_REQ_ATTR_PUBLISH_SERVICE_NAME, - NAN_REQ_ATTR_PUBLISH_MATCH_ALGO, - NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN, - NAN_REQ_ATTR_PUBLISH_SERVICE_INFO, - NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN, - NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER, - NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN, - NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER, - NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG, - NAN_REQ_ATTR_PUBLISH_CONN_MAP, - NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG, - NAN_REQ_ATTR_SUBSCRIBE_ID, - NAN_REQ_ATTR_SUBSCRIBE_TTL, - NAN_REQ_ATTR_SUBSCRIBE_PERIOD, - NAN_REQ_ATTR_SUBSCRIBE_TYPE, - NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE, - NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE, - NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER, - NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED, - NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR, - NAN_REQ_ATTR_SUBSCRIBE_COUNT, - NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN, - NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME, - NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN, - NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO, - NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN, - NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER, - NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN, - NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER, - NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG, - NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP, - NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT, - NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR, - NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG, - NAN_REQ_ATTR_FOLLOWUP_ID, - NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID, - NAN_REQ_ATTR_FOLLOWUP_ADDR, - NAN_REQ_ATTR_FOLLOWUP_PRIORITY, - NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN, - NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME, - NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW, - NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG -}; - -enum SLSI_NAN_RESP_ATTRIBUTES { - NAN_RESP_ATTR_MAX_CONCURRENT_NAN_CLUSTERS, - NAN_RESP_ATTR_MAX_PUBLISHES, - NAN_RESP_ATTR_MAX_SUBSCRIBES, - NAN_RESP_ATTR_MAX_SERVICE_NAME_LEN, - NAN_RESP_ATTR_MAX_MATCH_FILTER_LEN, - NAN_RESP_ATTR_MAX_TOTAL_MATCH_FILTER_LEN, - NAN_RESP_ATTR_MAX_SERVICE_SPECIFIC_INFO_LEN, - NAN_RESP_ATTR_MAX_VSA_DATA_LEN, - NAN_RESP_ATTR_MAX_MESH_DATA_LEN, - NAN_RESP_ATTR_MAX_NDI_INTERFACES, - NAN_RESP_ATTR_MAX_NDP_SESSIONS, - NAN_RESP_ATTR_MAX_APP_INFO_LEN, - NAN_RESP_ATTR_SUBSCRIBE_ID, - NAN_RESP_ATTR_PUBLISH_ID -}; - -enum SLSI_NAN_EVT_ATTRIBUTES { - NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, - NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, - NAN_EVT_ATTR_MATCH_ADDR, - NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN, - NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO, - NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN, - NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER, - NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG, - NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG, - NAN_EVT_ATTR_MATCH_RSSI_VALUE, - /*CONN_CAPABILITY*/ - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED, - NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD, - NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR, - NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR, - /*NANRECEIVEPOSTDISCOVERY DISCOVERY_ATTR,*/ - NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE, - NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE, - NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION, - NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP, - NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID, - NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR, - NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN, - NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID, - NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN, - NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL, - NAN_EVT_ATTR_MATCH_NUM_CHANS, - NAN_EVT_ATTR_MATCH_FAMCHAN, - /*FAMCHAN[32],*/ - NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL, - NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL, - NAN_EVT_ATTR_MATCH_FAM_CHANNEL, - NAN_EVT_ATTR_MATCH_FAM_MAPID, - NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP, - NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN, - NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE, - NAN_EVT_ATTR_PUBLISH_ID, - NAN_EVT_ATTR_PUBLISH_REASON, - NAN_EVT_ATTR_SUBSCRIBE_ID, - NAN_EVT_ATTR_SUBSCRIBE_REASON, - NAN_EVT_ATTR_DISABLED_REASON, - NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID, - NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID, - NAN_EVT_ATTR_FOLLOWUP_ADDR, - NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW, - NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN, - NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO, - NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, - NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, - NAN_EVT_ATTR_DISCOVERY_ENGINE_CLUSTER -}; - enum GSCAN_ATTRIBUTE { GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, GSCAN_ATTRIBUTE_BASE_PERIOD, @@ -1072,37 +876,6 @@ struct slsi_lls_iface_stat { struct slsi_lls_peer_info peer_info[]; /* per peer statistics*/ }; -#define SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON 0X0003 -#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE 0X0004 -#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE 0X0005 -#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY 0X0006 -#define SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE 0X0007 -#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE 0X0008 -#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE 0X0009 -#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY 0X000A -#define SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT 0X000B -#define SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE 0X000C -#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4 0X000D -#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5 0X000E -#define SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE 0X000F -#define SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB 0X0010 -#define SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM 0X0011 -#define SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP 0X0012 -#define SLSI_FAPI_NAN_CONFIG_PARAM_ADDR_RANDOM_INTERVAL 0X0013 -#define SLSI_FAPI_NAN_SERVICE_NAME 0X0020 -#define SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO 0X0021 -#define SLSI_FAPI_NAN_RX_MATCH_FILTER 0X0022 -#define SLSI_FAPI_NAN_TX_MATCH_FILTER 0X0023 -#define SLSI_FAPI_NAN_SDF_MATCH_FILTER 0X0024 -#define SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE 0X0025 - -#define SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS 3 -#define SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN 255 -#define SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN 1024 -#define SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN 255 -#define SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS 42 -#define SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN 5 - enum slsi_wifi_hal_api_return_types { WIFI_HAL_SUCCESS = 0, WIFI_HAL_ERROR_NONE = 0, @@ -1117,497 +890,6 @@ enum slsi_wifi_hal_api_return_types { WIFI_HAL_ERROR_OUT_OF_MEMORY = -9 }; -enum slsi_wifi_hal_nan_status_type { - /* NAN Protocol Response Codes */ - SLSI_HAL_NAN_STATUS_SUCCESS = 0, - /* NAN Discovery Engine/Host driver failures */ - SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE = 1, - /* NAN OTA failures */ - SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE = 2, - /* if the publish/subscribe id is invalid */ - SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID = 3, - /* If we run out of resources allocated */ - SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE = 4, - /* if invalid params are passed */ - SLSI_HAL_NAN_STATUS_INVALID_PARAM = 5, - /* if the requestor instance id is invalid */ - SLSI_HAL_NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID = 6, - /* if the ndp id is invalid */ - SLSI_HAL_NAN_STATUS_INVALID_NDP_ID = 7, - /* if NAN is enabled when wifi is turned off */ - SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED = 8, - /* if over the air ack is not received */ - SLSI_HAL_NAN_STATUS_NO_OTA_ACK = 9, - /* If NAN is already enabled and we are try to re-enable the same */ - SLSI_HAL_NAN_STATUS_ALREADY_ENABLED = 10, - /* If followup message internal queue is full */ - SLSI_HAL_NAN_STATUS_FOLLOWUP_QUEUE_FULL = 11, - /* Unsupported concurrency session enabled, NAN disabled notified */ - SLSI_HAL_NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12 -}; - -enum slsi_nan_status_type { - /* NAN Protocol Response Codes */ - NAN_STATUS_SUCCESS = 0, - NAN_STATUS_TIMEOUT = 1, - NAN_STATUS_DE_FAILURE = 2, - NAN_STATUS_INVALID_MSG_VERSION = 3, - NAN_STATUS_INVALID_MSG_LEN = 4, - NAN_STATUS_INVALID_MSG_ID = 5, - NAN_STATUS_INVALID_HANDLE = 6, - NAN_STATUS_NO_SPACE_AVAILABLE = 7, - NAN_STATUS_INVALID_PUBLISH_TYPE = 8, - NAN_STATUS_INVALID_TX_TYPE = 9, - NAN_STATUS_INVALID_MATCH_ALGORITHM = 10, - NAN_STATUS_DISABLE_IN_PROGRESS = 11, - NAN_STATUS_INVALID_TLV_LEN = 12, - NAN_STATUS_INVALID_TLV_TYPE = 13, - NAN_STATUS_MISSING_TLV_TYPE = 14, - NAN_STATUS_INVALID_TOTAL_TLVS_LEN = 15, - NAN_STATUS_INVALID_MATCH_HANDLE = 16, - NAN_STATUS_INVALID_TLV_VALUE = 17, - NAN_STATUS_INVALID_TX_PRIORITY = 18, - NAN_STATUS_INVALID_CONNECTION_MAP = 19, - NAN_STATUS_INVALID_TCA_ID = 20, - NAN_STATUS_INVALID_STATS_ID = 21, - NAN_STATUS_NAN_NOT_ALLOWED = 22, - NAN_STATUS_NO_OTA_ACK = 23, - NAN_STATUS_TX_FAIL = 24, - /* 25-4095 Reserved */ - /* NAN Configuration Response codes */ - NAN_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096, - NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097, - NAN_STATUS_INVALID_HOP_COUNT_LIMIT = 4098, - NAN_STATUS_INVALID_MASTER_PREFERENCE_VALUE = 4099, - NAN_STATUS_INVALID_LOW_CLUSTER_ID_VALUE = 4100, - NAN_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE = 4101, - NAN_STATUS_INVALID_BACKGROUND_SCAN_PERIOD = 4102, - NAN_STATUS_INVALID_RSSI_PROXIMITY_VALUE = 4103, - NAN_STATUS_INVALID_SCAN_CHANNEL = 4104, - NAN_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP = 4105, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_NUMCHAN_VALUE = 4106, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_DURATION_VALUE = 4107, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CLASS_VALUE = 4108, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CHANNEL_VALUE = 4109, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE = 4110, - NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_MAP_ID = 4111, - NAN_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE = 4112, - NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE = 4113, - NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE = 4114, - NAN_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE = 4115, - NAN_STATUS_MISSING_FUTHER_AVAILABILITY_MAP = 4116, - NAN_STATUS_INVALID_BAND_CONFIG_FLAGS = 4117, - NAN_STATUS_INVALID_RANDOM_FACTOR_UPDATE_TIME_VALUE = 4118, - NAN_STATUS_INVALID_ONGOING_SCAN_PERIOD = 4119, - NAN_STATUS_INVALID_DW_INTERVAL_VALUE = 4120, - NAN_STATUS_INVALID_DB_INTERVAL_VALUE = 4121, - /* 4122-8191 RESERVED */ - NAN_TERMINATED_REASON_INVALID = 8192, - NAN_TERMINATED_REASON_TIMEOUT = 8193, - NAN_TERMINATED_REASON_USER_REQUEST = 8194, - NAN_TERMINATED_REASON_FAILURE = 8195, - NAN_TERMINATED_REASON_COUNT_REACHED = 8196, - NAN_TERMINATED_REASON_DE_SHUTDOWN = 8197, - NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198, - NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199, - NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200, - NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201 -}; - -enum slsi_nan_response_type { - NAN_RESPONSE_ENABLED = 0, - NAN_RESPONSE_DISABLED = 1, - NAN_RESPONSE_PUBLISH = 2, - NAN_RESPONSE_PUBLISH_CANCEL = 3, - NAN_RESPONSE_TRANSMIT_FOLLOWUP = 4, - NAN_RESPONSE_SUBSCRIBE = 5, - NAN_RESPONSE_SUBSCRIBE_CANCEL = 6, - NAN_RESPONSE_STATS = 7, - NAN_RESPONSE_CONFIG = 8, - NAN_RESPONSE_TCA = 9, - NAN_RESPONSE_ERROR = 10, - NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11, - NAN_RESPONSE_GET_CAPABILITIES = 12 -}; - -enum slsi_nan_disc_event_type { - NAN_EVENT_ID_DISC_MAC_ADDR = 0, - NAN_EVENT_ID_STARTED_CLUSTER, - NAN_EVENT_ID_JOINED_CLUSTER -}; - -struct slsi_hal_nan_social_channel_scan_params { - u8 dwell_time[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS]; - u16 scan_period[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS]; -}; - -struct slsi_hal_nan_connectivity_capability { - u8 payload_transmit_flag; - u8 is_wfd_supported; - u8 is_wfds_supported; - u8 is_tdls_supported; - u8 is_ibss_supported; - u8 is_mesh_supported; - u8 wlan_infra_field; -}; - -struct slsi_hal_nan_post_discovery_param { - u8 type; /* NanConnectionType */ - u8 role; /* NanDeviceRole */ - u8 transmit_freq; - u8 duration; /* NanAvailDuration */ - u32 avail_interval_bitmap; - u8 addr[ETH_ALEN]; - u16 mesh_id_len; - u8 mesh_id[32]; - u16 infrastructure_ssid_len; - u8 infrastructure_ssid_val[32]; -}; - -struct slsi_hal_nan_further_availability_channel { - /* struct slsi_hal_nan_further_availability_channel*/ - u8 entry_control; - u8 class_val; - u8 channel; - u8 mapid; - u32 avail_interval_bitmap; -}; - -struct slsi_hal_nan_further_availability_map { - u8 numchans; - struct slsi_hal_nan_further_availability_channel famchan[32]; -}; - -struct slsi_hal_nan_receive_post_discovery { - u8 type; - u8 role; - u8 duration; - u32 avail_interval_bitmap; - u8 mapid; - u8 addr[ETH_ALEN]; - u16 mesh_id_len; - u8 mesh_id[32]; - u16 infrastructure_ssid_len; - u8 infrastructure_ssid_val[32]; -}; - -struct slsi_hal_nan_enable_req { - /* Mandatory parameters below */ - u8 master_pref; - u16 cluster_low; - u16 cluster_high; - - u8 config_support_5g; - u8 support_5g_val; - u8 config_sid_beacon; - u8 sid_beacon_val; - u8 config_2dot4g_rssi_close; - u8 rssi_close_2dot4g_val; - - u8 config_2dot4g_rssi_middle; - u8 rssi_middle_2dot4g_val; - - u8 config_2dot4g_rssi_proximity; - u8 rssi_proximity_2dot4g_val; - - u8 config_hop_count_limit; - u8 hop_count_limit_val; - - u8 config_2dot4g_support; - u8 support_2dot4g_val; - - u8 config_2dot4g_beacons; - u8 beacon_2dot4g_val; - u8 config_2dot4g_sdf; - u8 sdf_2dot4g_val; - u8 config_5g_beacons; - u8 beacon_5g_val; - u8 config_5g_sdf; - u8 sdf_5g_val; - u8 config_5g_rssi_close; - u8 rssi_close_5g_val; - u8 config_5g_rssi_middle; - u8 rssi_middle_5g_val; - u8 config_5g_rssi_close_proximity; - u8 rssi_close_proximity_5g_val; - u8 config_rssi_window_size; - u8 rssi_window_size_val; - /* The 24 bit Organizationally Unique ID + the 8 bit Network Id. */ - u8 config_oui; - u32 oui_val; - u8 config_intf_addr; - u8 intf_addr_val[ETH_ALEN]; - - u8 config_cluster_attribute_val; - u8 config_scan_params; - struct slsi_hal_nan_social_channel_scan_params scan_params_val; - u8 config_random_factor_force; - u8 random_factor_force_val; - u8 config_hop_count_force; - u8 hop_count_force_val; - - /* channel frequency in MHz to enable Nan on */ - u8 config_24g_channel; - u32 channel_24g_val; - - u8 config_5g_channel; - int channel_5g_val; -}; - -struct slsi_hal_nan_publish_req { - /* id 0 means new publish, any other id is existing publish */ - u16 publish_id; - /* how many seconds to run for. 0 means forever until canceled */ - u16 ttl; - /* periodicity of OTA unsolicited publish. - * Specified in increments of 500 ms - */ - u16 period; - u8 publish_type;/* 0= unsolicited, solicited = 1, 2= both */ - u8 tx_type; /* 0 = broadcast, 1= unicast if solicited publish */ - /* number of OTA Publish, 0 means forever until canceled */ - u8 publish_count; - u16 service_name_len; - u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN]; - u8 publish_match_indicator; - - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - - u16 rx_match_filter_len; - u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - - u16 tx_match_filter_len; - u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - - u8 rssi_threshold_flag; - - /* 8-bit bitmap which allows the Host to associate this publish - * with a particular Post-NAN Connectivity attribute - * which has been sent down in a NanConfigureRequest/NanEnableRequest - * message. If the DE fails to find a configured Post-NAN - * connectivity attributes referenced by the bitmap, - * the DE will return an error code to the Host. - * If the Publish is configured to use a Post-NAN Connectivity - * attribute and the Host does not refresh the Post-NAN Connectivity - * attribute the Publish will be canceled and the Host will be sent - * a PublishTerminatedIndication message. - */ - u8 connmap; - /* Set/Enable corresponding bits to disable any - * indications that follow a publish. - * BIT0 - Disable publish termination indication. - * BIT1 - Disable match expired indication. - * BIT2 - Disable followUp indication received (OTA). - */ - u8 recv_indication_cfg; -}; - -struct slsi_hal_nan_subscribe_req { - /* id 0 means new subscribe, non zero is existing subscribe */ - u16 subscribe_id; - /* how many seconds to run for. 0 means forever until canceled */ - u16 ttl; - /* periodicity of OTA Active Subscribe. Units in increments - * of 500 ms , 0 = attempt every DW - */ - u16 period; - - /* Flag which specifies how the Subscribe request shall be processed. */ - u8 subscribe_type; /* 0 - PASSIVE , 1- ACTIVE */ - - /* Flag which specifies on Active Subscribes how the Service Response - * Filter attribute is populated. - */ - u8 service_response_filter; /* 0 - Bloom Filter, 1 - MAC Addr */ - - /* Flag which specifies how the Service Response Filter Include - * bit is populated. - * 0=Do not respond if in the Address Set, 1= Respond - */ - u8 service_response_include; - - /* Flag which specifies if the Service Response Filter - * should be used when creating Subscribes. - * 0=Do not send the Service Response Filter,1= send - */ - u8 use_service_response_filter; - - /* Flag which specifies if the Service Specific Info is needed in - * the Publish message before creating the MatchIndication - */ - u8 ssi_required_for_match_indication; /* 0=Not needed, 1= Required */ - - /* Field which specifies how matching indication to host is controlled. - * 0 - Match and Indicate Once - * 1 - Match and Indicate continuous - * 2 - Match and Indicate never. This means don't - * indicate match to host. - * 3 - Reserved - */ - u8 subscribe_match_indicator; - - /* The number of Subscribe Matches which should occur - * before the Subscribe request is automatically terminated. - */ - /* If this value is 0 this field is not used by DE.*/ - u8 subscribe_count; - - /* length of service name */ - /* UTF-8 encoded string identifying the service */ - u16 service_name_len; - u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN]; - - /* Sequence of values which further specify the published service - * beyond the service name - */ - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - - /* Ordered sequence of pairs used to filter out - * received publish discovery messages. - * This can be sent both for a Passive or an Active Subscribe - */ - u16 rx_match_filter_len; - u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - - /* Ordered sequence of pairs included in the - * Discovery Frame when an Active Subscribe is used. - */ - u16 tx_match_filter_len; - u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - u8 rssi_threshold_flag; - - u8 connmap; - /* NAN Interface Address, conforming to the format as described in - * 8.2.4.3.2 of IEEE Std. 802.11-2012. - */ - u8 num_intf_addr_present; - u8 intf_addr[SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS][ETH_ALEN]; - /* Set/Enable corresponding bits to disable - * indications that follow a subscribe. - * BIT0 - Disable subscribe termination indication. - * BIT1 - Disable match expired indication. - * BIT2 - Disable followUp indication received (OTA). - */ - u8 recv_indication_cfg; -}; - -struct slsi_hal_nan_transmit_followup_req { - /* Publish or Subscribe Id of an earlier Publish/Subscribe */ - u16 publish_subscribe_id; - - /* This Id is the Requestor Instance that is passed as - * part of earlier MatchInd/FollowupInd message. - */ - u32 requestor_instance_id; - u8 addr[ETH_ALEN]; /* Unicast address */ - u8 priority; /* priority of the request 2=high */ - u8 dw_or_faw; /* 0= send in a DW, 1=send in FAW */ - - /* Sequence of values which further specify the published service beyond - * the service name. - */ - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - /* Set/Enable corresponding bits to disable - * responses after followUp. - * BIT0 - Disable followUp response from FW. - */ - u8 recv_indication_cfg; -}; - -struct slsi_hal_nan_config_req { - u8 config_sid_beacon; - u8 sid_beacon; - u8 config_rssi_proximity; - u8 rssi_proximity; - u8 config_master_pref; - u8 master_pref; - /* 1 byte value which defines the RSSI filter threshold. - * Any Service Descriptors received above this value - * that are configured for RSSI filtering will be dropped. - * The rssi values should be specified without sign. - * For eg: -70dBm should be specified as 70. - */ - u8 config_5g_rssi_close_proximity; - u8 rssi_close_proximity_5g_val; - u8 config_rssi_window_size; - u16 rssi_window_size_val; - /* If set to 1, the Discovery Engine will enclose the Cluster - * Attribute only sent in Beacons in a Vendor Specific Attribute - * and transmit in a Service Descriptor Frame. - */ - u8 config_cluster_attribute_val; - u8 config_scan_params; - struct slsi_hal_nan_social_channel_scan_params scan_params_val; - /* 1 byte quantity which forces the Random Factor to a particular - * value for all transmitted Sync/Discovery beacons - */ - u8 config_random_factor_force; - u8 random_factor_force_val; - /* 1 byte quantity which forces the HC for all transmitted Sync and - * Discovery Beacon NO matter the real HC being received over the - * air. - */ - u8 config_hop_count_force; - u8 hop_count_force_val; - /* NAN Post Connectivity Capability */ - u8 config_conn_capability; - struct slsi_hal_nan_connectivity_capability conn_capability_val; - /* NAN Post Discover Capability */ - u8 num_config_discovery_attr; - struct slsi_hal_nan_post_discovery_param discovery_attr_val[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN]; - /* NAN Further availability Map */ - u8 config_fam; - struct slsi_hal_nan_further_availability_map fam_val; -}; - -struct slsi_hal_nan_capabilities { - u32 max_concurrent_nan_clusters; - u32 max_publishes; - u32 max_subscribes; - u32 max_service_name_len; - u32 max_match_filter_len; - u32 max_total_match_filter_len; - u32 max_service_specific_info_len; - u32 max_vsa_data_len; - u32 max_mesh_data_len; - u32 max_ndi_interfaces; - u32 max_ndp_sessions; - u32 max_app_info_len; -}; - -struct slsi_hal_nan_followup_ind { - u16 publish_subscribe_id; - u32 requestor_instance_id; - u8 addr[ETH_ALEN]; - u8 dw_or_faw; - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; -}; - -struct slsi_hal_nan_match_ind { - u16 publish_subscribe_id; - u32 requestor_instance_id; - u8 addr[ETH_ALEN]; - u16 service_specific_info_len; - u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; - u16 sdf_match_filter_len; - u8 sdf_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; - u8 match_occurred_flag; - u8 out_of_resource_flag; - u8 rssi_value; - u8 is_conn_capability_valid; - struct slsi_hal_nan_connectivity_capability conn_capability; - u8 num_rx_discovery_attr; - struct slsi_hal_nan_receive_post_discovery discovery_attr[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN]; - u8 num_chans; - struct slsi_hal_nan_further_availability_channel famchan[32]; - u8 cluster_attribute_len; - u8 cluster_attribute[32]; -}; - struct slsi_rtt_capabilities { u8 rtt_one_sided_supported; /* if 1-sided rtt data collection is supported */ u8 rtt_ftm_supported; /* if ftm rtt data collection is supported */ @@ -1719,10 +1001,9 @@ void slsi_rx_range_done_ind(struct slsi_dev *sdev, struct net_device *dev, struc int slsi_tx_rate_calc(struct sk_buff *nl_skb, u16 fw_rate, int res, bool tx_rate); void slsi_check_num_radios(struct slsi_dev *sdev); void slsi_rx_event_log_indication(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); -void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr); +#ifdef CONFIG_SCSC_WLAN_DEBUG +char *slsi_print_event_name(int event_id); +#endif static inline bool slsi_is_gscan_id(u16 scan_id) diff --git a/drivers/net/wireless/scsc/nl80211_vendor_nan.c b/drivers/net/wireless/scsc/nl80211_vendor_nan.c new file mode 100755 index 000000000000..417aab00a36f --- /dev/null +++ b/drivers/net/wireless/scsc/nl80211_vendor_nan.c @@ -0,0 +1,1688 @@ +/***************************************************************************** + * + * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved + * + ****************************************************************************/ + +#include "cfg80211_ops.h" +#include "debug.h" +#include "mgt.h" +#include "mlme.h" + +struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev) +{ +#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 + return slsi_get_netdev(sdev, SLSI_NET_INDEX_NAN); +#else + return NULL; +#endif +} + +static int slsi_nan_get_new_id(u32 id_map, int max_ids) +{ + int i; + + for (i = 1; i <= max_ids; i++) { + if (!(id_map & BIT(i))) + return i; + } + return 0; +} + +static int slsi_nan_get_new_publish_id(struct netdev_vif *ndev_vif) +{ + return slsi_nan_get_new_id(ndev_vif->nan.publish_id_map, SLSI_NAN_MAX_PUBLISH_ID); +} + +static int slsi_nan_get_new_subscribe_id(struct netdev_vif *ndev_vif) +{ + return slsi_nan_get_new_id(ndev_vif->nan.subscribe_id_map, SLSI_NAN_MAX_SUBSCRIBE_ID); +} + +static bool slsi_nan_is_publish_id_active(struct netdev_vif *ndev_vif, u32 id) +{ + return ndev_vif->nan.publish_id_map & BIT(id); +} + +static bool slsi_nan_is_subscribe_id_active(struct netdev_vif *ndev_vif, u32 id) +{ + return ndev_vif->nan.subscribe_id_map & BIT(id); +} + +void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr) +{ + memset(nan_mac_addr, 0, ETH_ALEN); +#if CONFIG_SCSC_WLAN_MAX_INTERFACES >= 4 + if (slsi_dev_nan_supported(sdev)) + ether_addr_copy(nan_mac_addr, sdev->netdev_addresses[SLSI_NET_INDEX_NAN]); +#endif +} + +static void slsi_vendor_nan_command_reply(struct wiphy *wiphy, u32 status, u32 error, u32 response_type, + u16 publish_subscribe_id, struct slsi_hal_nan_capabilities *capabilities) +{ + int reply_len; + struct sk_buff *reply; + + reply_len = SLSI_NL_VENDOR_REPLY_OVERHEAD + SLSI_NL_ATTRIBUTE_U32_LEN * + (3 + sizeof(struct slsi_hal_nan_capabilities)); + reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, reply_len); + if (!reply) { + SLSI_WARN_NODEV("SKB alloc failed for vendor_cmd reply\n"); + return; + } + + nla_put_u32(reply, NAN_REPLY_ATTR_STATUS_TYPE, status); + nla_put_u32(reply, NAN_REPLY_ATTR_VALUE, error); + nla_put_u32(reply, NAN_REPLY_ATTR_RESPONSE_TYPE, response_type); + + if (capabilities) { + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER, + capabilities->max_concurrent_nan_clusters); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_PUBLISHES, capabilities->max_publishes); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES, capabilities->max_subscribes); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN, capabilities->max_service_name_len); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN, capabilities->max_match_filter_len); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN, + capabilities->max_total_match_filter_len); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN, + capabilities->max_service_specific_info_len); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN, capabilities->max_vsa_data_len); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN, capabilities->max_mesh_data_len); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, capabilities->max_ndi_interfaces); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, capabilities->max_ndp_sessions); + nla_put_u32(reply, NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN, capabilities->max_app_info_len); + } else if (publish_subscribe_id) { + nla_put_u16(reply, NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, publish_subscribe_id); + } + + if (cfg80211_vendor_cmd_reply(reply)) + SLSI_ERR_NODEV("FAILED to reply nan coammnd. response_type:%d\n", response_type); +} + +static int slsi_nan_enable_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_enable_req *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); + switch (type) { + case NAN_REQ_ATTR_MASTER_PREF: + hal_req->master_pref = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_CLUSTER_LOW: + hal_req->cluster_low = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_CLUSTER_HIGH: + hal_req->cluster_high = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUPPORT_5G_VAL: + hal_req->support_5g_val = nla_get_u8(iter); + hal_req->config_support_5g = 1; + break; + + case NAN_REQ_ATTR_SID_BEACON_VAL: + hal_req->sid_beacon_val = nla_get_u8(iter); + hal_req->config_sid_beacon = 1; + break; + + case NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL: + hal_req->rssi_close_2dot4g_val = nla_get_u8(iter); + hal_req->config_2dot4g_rssi_close = 1; + break; + + case NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL: + hal_req->rssi_middle_2dot4g_val = nla_get_u8(iter); + hal_req->config_2dot4g_rssi_middle = 1; + break; + + case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL: + hal_req->rssi_proximity_2dot4g_val = nla_get_u8(iter); + hal_req->rssi_proximity_2dot4g_val = 1; + break; + + case NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL: + hal_req->hop_count_limit_val = nla_get_u8(iter); + hal_req->config_hop_count_limit = 1; + break; + + case NAN_REQ_ATTR_SUPPORT_2G4_VAL: + hal_req->support_2dot4g_val = nla_get_u8(iter); + hal_req->config_2dot4g_support = 1; + break; + + case NAN_REQ_ATTR_BEACONS_2G4_VAL: + hal_req->beacon_2dot4g_val = nla_get_u8(iter); + hal_req->config_2dot4g_beacons = 1; + break; + + case NAN_REQ_ATTR_SDF_2G4_VAL: + hal_req->sdf_2dot4g_val = nla_get_u8(iter); + hal_req->config_2dot4g_sdf = 1; + break; + + case NAN_REQ_ATTR_BEACON_5G_VAL: + hal_req->beacon_5g_val = nla_get_u8(iter); + hal_req->config_5g_beacons = 1; + break; + + case NAN_REQ_ATTR_SDF_5G_VAL: + hal_req->sdf_5g_val = nla_get_u8(iter); + hal_req->config_5g_sdf = 1; + break; + + case NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL: + hal_req->rssi_close_5g_val = nla_get_u8(iter); + hal_req->config_5g_rssi_close = 1; + break; + + case NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL: + hal_req->rssi_middle_5g_val = nla_get_u8(iter); + hal_req->config_5g_rssi_middle = 1; + break; + + case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL: + hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter); + hal_req->config_5g_rssi_close_proximity = 1; + break; + + case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL: + hal_req->rssi_window_size_val = nla_get_u8(iter); + hal_req->config_rssi_window_size = 1; + break; + + case NAN_REQ_ATTR_OUI_VAL: + hal_req->oui_val = nla_get_u32(iter); + hal_req->config_oui = 1; + break; + + case NAN_REQ_ATTR_MAC_ADDR_VAL: + memcpy(hal_req->intf_addr_val, nla_data(iter), ETH_ALEN); + hal_req->config_intf_addr = 1; + break; + + case NAN_REQ_ATTR_CLUSTER_VAL: + hal_req->config_cluster_attribute_val = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME: + memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter), + sizeof(hal_req->scan_params_val.dwell_time)); + hal_req->config_scan_params = 1; + break; + + case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD: + memcpy(hal_req->scan_params_val.scan_period, nla_data(iter), + sizeof(hal_req->scan_params_val.scan_period)); + hal_req->config_scan_params = 1; + break; + + case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL: + hal_req->random_factor_force_val = nla_get_u8(iter); + hal_req->config_random_factor_force = 1; + break; + + case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL: + hal_req->hop_count_force_val = nla_get_u8(iter); + hal_req->config_hop_count_force = 1; + break; + + case NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL: + hal_req->channel_24g_val = nla_get_u32(iter); + hal_req->config_24g_channel = 1; + break; + + case NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL: + hal_req->channel_5g_val = nla_get_u8(iter); + hal_req->config_5g_channel = 1; + break; + + default: + SLSI_ERR(sdev, "Unexpected NAN enable attribute TYPE:%d\n", type); + return SLSI_HAL_NAN_STATUS_INVALID_PARAM; + } + } + return SLSI_HAL_NAN_STATUS_SUCCESS; +} + +int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) +{ + struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); + struct slsi_hal_nan_enable_req hal_req; + int ret; + struct net_device *dev = slsi_nan_get_netdev(sdev); + struct netdev_vif *ndev_vif; + u8 nan_vif_mac_address[ETH_ALEN]; + u8 broadcast_mac[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; + + if (!dev) { + SLSI_ERR(sdev, "No NAN interface\n"); + ret = -ENOTSUPP; + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + goto exit; + } + + if (!slsi_dev_nan_supported(sdev)) { + SLSI_ERR(sdev, "NAN not allowed(mib:%d)\n", sdev->nan_enabled); + ret = WIFI_HAL_ERROR_NOT_SUPPORTED; + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + goto exit; + } + + ndev_vif = netdev_priv(dev); + + reply_status = slsi_nan_enable_get_nl_params(sdev, &hal_req, data, len); + if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { + ret = -EINVAL; + goto exit; + } + + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); + if (ndev_vif->activated) { + ret = -EINVAL; + SLSI_DBG1(sdev, SLSI_GSCAN, "Already Enabled. Req Rejected\n"); + goto exit_with_mutex; + } + ndev_vif->vif_type = FAPI_VIFTYPE_NAN; + + if (hal_req.config_intf_addr) + ether_addr_copy(nan_vif_mac_address, hal_req.intf_addr_val); + else + slsi_nan_get_mac(sdev, nan_vif_mac_address); + + ret = slsi_mlme_add_vif(sdev, dev, nan_vif_mac_address, broadcast_mac); + if (ret) { + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + SLSI_ERR(sdev, "failed to set unsync vif. Cannot start NAN\n"); + } else { + ret = slsi_mlme_nan_enable(sdev, dev, &hal_req); + if (ret) { + SLSI_ERR(sdev, "failed to enable NAN.\n"); + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + slsi_mlme_del_vif(sdev, dev); + ndev_vif->activated = false; + ndev_vif->nan.subscribe_id_map = 0; + ndev_vif->nan.publish_id_map = 0; + } else { + slsi_vif_activated(sdev, dev); + } + } + +exit_with_mutex: + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); +exit: + slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_ENABLED, 0, NULL); + return ret; +} + +int slsi_nan_disable(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; + + if (dev) { + ndev_vif = netdev_priv(dev); + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); + if (ndev_vif->activated) { + slsi_mlme_del_vif(sdev, dev); + ndev_vif->activated = false; + ndev_vif->nan.subscribe_id_map = 0; + ndev_vif->nan.publish_id_map = 0; + } else { + SLSI_WARN(sdev, "NAN FWif not active!!"); + } + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); + } else { + SLSI_WARN(sdev, "No NAN interface!!"); + } + + slsi_vendor_nan_command_reply(wiphy, SLSI_HAL_NAN_STATUS_SUCCESS, 0, NAN_RESPONSE_DISABLED, 0, NULL); + + return 0; +} + +static int slsi_nan_publish_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_publish_req *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); + switch (type) { + case NAN_REQ_ATTR_PUBLISH_ID: + hal_req->publish_id = nla_get_u16(iter); + break; + case NAN_REQ_ATTR_PUBLISH_TTL: + hal_req->ttl = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_PERIOD: + hal_req->period = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_TYPE: + hal_req->publish_type = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_TX_TYPE: + hal_req->tx_type = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_COUNT: + hal_req->publish_count = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN: + hal_req->service_name_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_SERVICE_NAME: + memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len); + break; + + case NAN_REQ_ATTR_PUBLISH_MATCH_ALGO: + hal_req->publish_match_indicator = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN: + hal_req->service_specific_info_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_SERVICE_INFO: + memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); + break; + + case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN: + hal_req->rx_match_filter_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER: + memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len); + break; + + case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN: + hal_req->tx_match_filter_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER: + memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len); + break; + + case NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG: + hal_req->rssi_threshold_flag = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_CONN_MAP: + hal_req->connmap = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG: + hal_req->recv_indication_cfg = nla_get_u8(iter); + break; + + default: + SLSI_ERR(sdev, "Unexpected NAN publish attribute TYPE:%d\n", type); + return SLSI_HAL_NAN_STATUS_INVALID_PARAM; + } + } + return SLSI_HAL_NAN_STATUS_SUCCESS; +} + +int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) +{ + struct slsi_dev *sdev = SDEV_FROM_WIPHY(wiphy); + struct slsi_hal_nan_publish_req hal_req; + struct net_device *dev = slsi_nan_get_netdev(sdev); + struct netdev_vif *ndev_vif; + int ret; + u32 reply_status; + u32 publish_id = 0; + + if (!dev) { + SLSI_ERR(sdev, "NAN netif not active!!"); + ret = -EINVAL; + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + goto exit; + } + + ndev_vif = netdev_priv(dev); + reply_status = slsi_nan_publish_get_nl_params(sdev, &hal_req, data, len); + if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { + ret = -EINVAL; + 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; + } + + if (!hal_req.publish_id) { + hal_req.publish_id = slsi_nan_get_new_publish_id(ndev_vif); + } else if (!slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_id)) { + SLSI_WARN(sdev, "Publish id %d not found. map:%x\n", hal_req.publish_id, + ndev_vif->nan.publish_id_map); + reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; + ret = -EINVAL; + goto exit_with_lock; + } + + if (hal_req.publish_id) { + ret = slsi_mlme_nan_publish(sdev, dev, &hal_req, hal_req.publish_id); + if (ret) + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + else + publish_id = hal_req.publish_id; + } else { + reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; + SLSI_WARN(sdev, "Too Many concurrent PUBLISH REQ(map:%x)\n", + ndev_vif->nan.publish_id_map); + ret = -ENOTSUPP; + } +exit_with_lock: + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); +exit: + slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH, publish_id, NULL); + return ret; +} + +int slsi_nan_publish_cancel(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; + int type, tmp, ret = 0; + u16 publish_id = 0; + const struct nlattr *iter; + u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; + + if (!dev) { + SLSI_ERR(sdev, "NAN netif not active!!"); + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + ret = -EINVAL; + goto exit; + } + + ndev_vif = netdev_priv(dev); + nla_for_each_attr(iter, data, len, tmp) { + type = nla_type(iter); + switch (type) { + case NAN_REQ_ATTR_PUBLISH_ID: + publish_id = nla_get_u16(iter); + break; + default: + SLSI_ERR(sdev, "Unexpected NAN publishcancel attribute TYPE:%d\n", type); + } + } + + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); + if (!ndev_vif->activated) { + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + ret = WIFI_HAL_ERROR_NOT_AVAILABLE; + goto exit_with_lock; + } + if (!publish_id || !slsi_nan_is_publish_id_active(ndev_vif, publish_id)) { + reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; + SLSI_WARN(sdev, "Publish_id(%d) not active. map:%x\n", + publish_id, ndev_vif->nan.publish_id_map); + } else { + ret = slsi_mlme_nan_publish(sdev, dev, NULL, publish_id); + if (ret) + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + } +exit_with_lock: + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); +exit: + slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_PUBLISH_CANCEL, publish_id, NULL); + return ret; +} + +static int slsi_nan_subscribe_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_subscribe_req *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); + switch (type) { + case NAN_REQ_ATTR_SUBSCRIBE_ID: + hal_req->subscribe_id = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_TTL: + hal_req->ttl = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_PERIOD: + hal_req->period = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_TYPE: + hal_req->subscribe_type = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE: + hal_req->service_response_filter = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE: + hal_req->service_response_include = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER: + hal_req->use_service_response_filter = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED: + hal_req->ssi_required_for_match_indication = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR: + hal_req->subscribe_match_indicator = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_COUNT: + hal_req->subscribe_count = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN: + hal_req->service_name_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME: + memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN: + hal_req->service_specific_info_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO: + memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN: + hal_req->rx_match_filter_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER: + memcpy(hal_req->rx_match_filter, nla_data(iter), hal_req->rx_match_filter_len); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN: + hal_req->tx_match_filter_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER: + memcpy(hal_req->tx_match_filter, nla_data(iter), hal_req->tx_match_filter_len); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG: + hal_req->rssi_threshold_flag = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP: + hal_req->connmap = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT: + hal_req->num_intf_addr_present = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR: + memcpy(hal_req->intf_addr, nla_data(iter), hal_req->num_intf_addr_present * ETH_ALEN); + break; + + case NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG: + hal_req->recv_indication_cfg = nla_get_u8(iter); + break; + + default: + SLSI_ERR(sdev, "Unexpected NAN subscribe attribute TYPE:%d\n", type); + return SLSI_HAL_NAN_STATUS_INVALID_PARAM; + } + } + return SLSI_HAL_NAN_STATUS_SUCCESS; +} + +int slsi_nan_subscribe(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_subscribe_req *hal_req; + int ret; + u32 reply_status; + u32 subscribe_id = 0; + + if (!dev) { + SLSI_ERR(sdev, "NAN netif not active!!\n"); + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + ret = -EINVAL; + 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 = -ENOMEM; + goto exit; + } + + ndev_vif = netdev_priv(dev); + reply_status = slsi_nan_subscribe_get_nl_params(sdev, hal_req, data, len); + if (reply_status != SLSI_HAL_NAN_STATUS_SUCCESS) { + kfree(hal_req); + ret = -EINVAL; + 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; + } + + if (!hal_req->subscribe_id) { + hal_req->subscribe_id = slsi_nan_get_new_subscribe_id(ndev_vif); + } else if (!slsi_nan_is_subscribe_id_active(ndev_vif, hal_req->subscribe_id)) { + SLSI_WARN(sdev, "Subscribe id %d not found. map:%x\n", hal_req->subscribe_id, + ndev_vif->nan.subscribe_id_map); + reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; + ret = -EINVAL; + goto exit_with_lock; + } + + ret = slsi_mlme_nan_subscribe(sdev, dev, hal_req, hal_req->subscribe_id); + if (ret) + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + else + subscribe_id = hal_req->subscribe_id; + +exit_with_lock: + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); + kfree(hal_req); +exit: + slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE, subscribe_id, NULL); + return ret; +} + +int slsi_nan_subscribe_cancel(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; + int type, tmp, ret = WIFI_HAL_ERROR_UNKNOWN; + u16 subscribe_id = 0; + const struct nlattr *iter; + u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; + + if (!dev) { + SLSI_ERR(sdev, "NAN netif not active!!"); + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + ret = WIFI_HAL_ERROR_NOT_AVAILABLE; + goto exit; + } + + ndev_vif = netdev_priv(dev); + + nla_for_each_attr(iter, data, len, tmp) { + type = nla_type(iter); + switch (type) { + case NAN_REQ_ATTR_SUBSCRIBE_ID: + subscribe_id = nla_get_u16(iter); + break; + default: + SLSI_ERR(sdev, "Unexpected NAN subscribecancel attribute TYPE:%d\n", type); + reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM; + goto exit; + } + } + + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); + if (ndev_vif->activated) { + if (!subscribe_id || !slsi_nan_is_subscribe_id_active(ndev_vif, subscribe_id)) { + SLSI_WARN(sdev, "subscribe_id(%d) not active. map:%x\n", + subscribe_id, ndev_vif->nan.subscribe_id_map); + reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; + } else { + ret = slsi_mlme_nan_subscribe(sdev, dev, NULL, subscribe_id); + if (ret) + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + } + } else { + SLSI_ERR(sdev, "vif not activated\n"); + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + ret = WIFI_HAL_ERROR_NOT_AVAILABLE; + } + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); +exit: + slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_SUBSCRIBE_CANCEL, subscribe_id, NULL); + return ret; +} + +static int slsi_nan_followup_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_transmit_followup_req *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); + switch (type) { + case NAN_REQ_ATTR_FOLLOWUP_ID: + hal_req->publish_subscribe_id = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID: + hal_req->requestor_instance_id = nla_get_u32(iter); + break; + + case NAN_REQ_ATTR_FOLLOWUP_ADDR: + memcpy(hal_req->addr, nla_data(iter), ETH_ALEN); + break; + + case NAN_REQ_ATTR_FOLLOWUP_PRIORITY: + hal_req->priority = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW: + hal_req->dw_or_faw = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN: + hal_req->service_specific_info_len = nla_get_u16(iter); + break; + + case NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME: + memcpy(hal_req->service_specific_info, nla_data(iter), hal_req->service_specific_info_len); + break; + + case NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG: + hal_req->recv_indication_cfg = nla_get_u8(iter); + break; + + default: + SLSI_ERR(sdev, "Unexpected NAN followup attribute TYPE:%d\n", type); + return SLSI_HAL_NAN_STATUS_INVALID_PARAM; + } + } + return SLSI_HAL_NAN_STATUS_SUCCESS; +} + +int slsi_nan_transmit_followup(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_transmit_followup_req hal_req; + int ret; + u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; + + if (!dev) { + SLSI_ERR(sdev, "NAN netif not active!!"); + ret = -EINVAL; + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + goto exit; + } + + ndev_vif = netdev_priv(dev); + reply_status = slsi_nan_followup_get_nl_params(sdev, &hal_req, data, len); + if (reply_status) { + ret = -EINVAL; + 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; + } + + if (!hal_req.publish_subscribe_id || + !(slsi_nan_is_subscribe_id_active(ndev_vif, hal_req.publish_subscribe_id) || + slsi_nan_is_publish_id_active(ndev_vif, hal_req.publish_subscribe_id))) { + SLSI_WARN(sdev, "publish/Subscribe id %d not found. map:%x\n", hal_req.publish_subscribe_id, + ndev_vif->nan.subscribe_id_map); + reply_status = SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID; + ret = -EINVAL; + goto exit_with_lock; + } + + ret = slsi_mlme_nan_tx_followup(sdev, dev, &hal_req); + if (ret) + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + +exit_with_lock: + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); +exit: + slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_TRANSMIT_FOLLOWUP, 0, NULL); + return ret; +} + +static int slsi_nan_config_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_config_req *hal_req, + const void *data, int len) +{ + int type, type1, tmp, tmp1, disc_attr_idx = 0, famchan_idx = 0; + const struct nlattr *iter, *iter1; + struct slsi_hal_nan_post_discovery_param *disc_attr; + struct slsi_hal_nan_further_availability_channel *famchan; + + 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_SID_BEACON_VAL: + hal_req->sid_beacon = nla_get_u8(iter); + hal_req->config_sid_beacon = 1; + break; + + case NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL: + hal_req->rssi_proximity = nla_get_u8(iter); + hal_req->config_rssi_proximity = 1; + break; + + case NAN_REQ_ATTR_MASTER_PREF: + hal_req->master_pref = nla_get_u8(iter); + hal_req->config_master_pref = 1; + break; + + case NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL: + hal_req->rssi_close_proximity_5g_val = nla_get_u8(iter); + hal_req->config_5g_rssi_close_proximity = 1; + break; + + case NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL: + hal_req->rssi_window_size_val = nla_get_u8(iter); + hal_req->config_rssi_window_size = 1; + break; + + case NAN_REQ_ATTR_CLUSTER_VAL: + hal_req->config_cluster_attribute_val = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME: + memcpy(hal_req->scan_params_val.dwell_time, nla_data(iter), + sizeof(hal_req->scan_params_val.dwell_time)); + hal_req->config_scan_params = 1; + break; + + case NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD: + memcpy(hal_req->scan_params_val.scan_period, nla_data(iter), + sizeof(hal_req->scan_params_val.scan_period)); + hal_req->config_scan_params = 1; + break; + + case NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL: + hal_req->random_factor_force_val = nla_get_u8(iter); + hal_req->config_random_factor_force = 1; + break; + + case NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL: + hal_req->hop_count_force_val = nla_get_u8(iter); + hal_req->config_hop_count_force = 1; + break; + + case NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX: + hal_req->conn_capability_val.payload_transmit_flag = nla_get_u8(iter); + hal_req->config_conn_capability = 1; + break; + + case NAN_REQ_ATTR_CONN_CAPABILITY_WFD: + hal_req->conn_capability_val.is_wfd_supported = nla_get_u8(iter); + hal_req->config_conn_capability = 1; + break; + + case NAN_REQ_ATTR_CONN_CAPABILITY_WFDS: + hal_req->conn_capability_val.is_wfds_supported = nla_get_u8(iter); + hal_req->config_conn_capability = 1; + break; + + case NAN_REQ_ATTR_CONN_CAPABILITY_TDLS: + hal_req->conn_capability_val.is_tdls_supported = nla_get_u8(iter); + hal_req->config_conn_capability = 1; + break; + + case NAN_REQ_ATTR_CONN_CAPABILITY_MESH: + hal_req->conn_capability_val.is_mesh_supported = nla_get_u8(iter); + hal_req->config_conn_capability = 1; + break; + + case NAN_REQ_ATTR_CONN_CAPABILITY_IBSS: + hal_req->conn_capability_val.is_ibss_supported = nla_get_u8(iter); + hal_req->config_conn_capability = 1; + break; + + case NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA: + hal_req->conn_capability_val.wlan_infra_field = nla_get_u8(iter); + hal_req->config_conn_capability = 1; + break; + + case NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES: + hal_req->num_config_discovery_attr = nla_get_u8(iter); + break; + + case NAN_REQ_ATTR_DISCOVERY_ATTR_VAL: + if (disc_attr_idx >= hal_req->num_config_discovery_attr) { + SLSI_ERR(sdev, + "disc attr(%d) > num disc attr(%d)\n", + disc_attr_idx + 1, hal_req->num_config_discovery_attr); + return -EINVAL; + } + disc_attr = &hal_req->discovery_attr_val[disc_attr_idx]; + disc_attr_idx++; + nla_for_each_nested(iter1, iter, tmp1) { + type1 = nla_type(iter1); + switch (type1) { + case NAN_REQ_ATTR_CONN_TYPE: + disc_attr->type = nla_get_u8(iter1); + break; + + case NAN_REQ_ATTR_NAN_ROLE: + disc_attr->role = nla_get_u8(iter1); + break; + + case NAN_REQ_ATTR_TRANSMIT_FREQ: + disc_attr->transmit_freq = nla_get_u8(iter1); + break; + + case NAN_REQ_ATTR_AVAILABILITY_DURATION: + disc_attr->duration = nla_get_u8(iter1); + break; + + case NAN_REQ_ATTR_AVAILABILITY_INTERVAL: + disc_attr->avail_interval_bitmap = nla_get_u32(iter1); + break; + + case NAN_REQ_ATTR_MAC_ADDR_VAL: + memcpy(disc_attr->addr, nla_data(iter1), ETH_ALEN); + break; + + case NAN_REQ_ATTR_MESH_ID_LEN: + disc_attr->mesh_id_len = nla_get_u16(iter1); + break; + + case NAN_REQ_ATTR_MESH_ID: + memcpy(disc_attr->mesh_id, nla_data(iter1), disc_attr->mesh_id_len); + break; + + case NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN: + disc_attr->infrastructure_ssid_len = nla_get_u16(iter1); + break; + + case NAN_REQ_ATTR_INFRASTRUCTURE_SSID: + memcpy(disc_attr->infrastructure_ssid_val, nla_data(iter1), + disc_attr->infrastructure_ssid_len); + break; + } + } + break; + + case NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES: + hal_req->fam_val.numchans = nla_get_u8(iter); + hal_req->config_fam = 1; + break; + + case NAN_REQ_ATTR_FURTHER_AVAIL_VAL: + hal_req->config_fam = 1; + if (famchan_idx >= hal_req->fam_val.numchans) { + SLSI_ERR(sdev, + "famchan attr(%d) > numchans(%d)\n", + famchan_idx + 1, hal_req->fam_val.numchans); + return -EINVAL; + } + famchan = &hal_req->fam_val.famchan[famchan_idx]; + famchan_idx++; + nla_for_each_nested(iter1, iter, tmp1) { + type1 = nla_type(iter1); + switch (type1) { + case NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL: + famchan->entry_control = nla_get_u8(iter1); + break; + + case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS: + famchan->class_val = nla_get_u8(iter1); + break; + + case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN: + famchan->channel = nla_get_u8(iter1); + break; + + case NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID: + famchan->mapid = nla_get_u8(iter1); + break; + + case NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP: + famchan->avail_interval_bitmap = nla_get_u32(iter1); + break; + } + } + break; + default: + SLSI_ERR(sdev, "Unexpected NAN config attribute TYPE:%d\n", type); + return SLSI_HAL_NAN_STATUS_INVALID_PARAM; + } + } + return SLSI_HAL_NAN_STATUS_SUCCESS; +} + +int slsi_nan_set_config(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_config_req hal_req; + int ret; + u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; + + if (!dev) { + SLSI_ERR(sdev, "NAN netif not active!!"); + ret = -EINVAL; + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + goto exit; + } + + ndev_vif = netdev_priv(dev); + reply_status = slsi_nan_config_get_nl_params(sdev, &hal_req, data, len); + if (reply_status) { + ret = -EINVAL; + 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; + } else { + ret = slsi_mlme_nan_set_config(sdev, dev, &hal_req); + if (ret) + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + } + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); +exit: + slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_CONFIG, 0, NULL); + return ret; +} + +int slsi_nan_get_capabilities(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; + u32 reply_status = SLSI_HAL_NAN_STATUS_SUCCESS; + struct slsi_hal_nan_capabilities nan_capabilities; + int ret = 0, i; + struct slsi_mib_value *values = NULL; + struct slsi_mib_data mibrsp = { 0, NULL }; + struct slsi_mib_get_entry get_values[] = {{ SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_CLUSTERS, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_PUBLISHES, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_CONCURRENT_SUBSCRIBES, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_NAME_LENGTH, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_MATCH_FILTER_LENGTH, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_TOTAL_MATCH_FILTER_LENGTH, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_SERVICE_SPECIFIC_INFO_LENGTH, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_VSA_DATA_LENGTH, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_MESH_DATA_LENGTH, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_NDI_INTERFACES, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_NDP_SESSIONS, { 0, 0 } }, + { SLSI_PSID_UNIFI_NAN_MAX_APP_INFO_LENGTH, { 0, 0 } } }; + u32 *capabilities_mib_val[] = { &nan_capabilities.max_concurrent_nan_clusters, + &nan_capabilities.max_publishes, + &nan_capabilities.max_subscribes, + &nan_capabilities.max_service_name_len, + &nan_capabilities.max_match_filter_len, + &nan_capabilities.max_total_match_filter_len, + &nan_capabilities.max_service_specific_info_len, + &nan_capabilities.max_vsa_data_len, + &nan_capabilities.max_mesh_data_len, + &nan_capabilities.max_ndi_interfaces, + &nan_capabilities.max_ndp_sessions, + &nan_capabilities.max_app_info_len }; + + if (!dev) { + SLSI_ERR(sdev, "NAN netif not active!!"); + reply_status = SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED; + ret = -EINVAL; + goto exit; + } + + ndev_vif = netdev_priv(dev); + + /* Expect each mib length in response is 11 */ + mibrsp.dataLength = 11 * ARRAY_SIZE(get_values); + mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL); + if (!mibrsp.data) { + SLSI_ERR(sdev, "Cannot kmalloc %d bytes\n", mibrsp.dataLength); + reply_status = SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE; + ret = -ENOMEM; + goto exit; + } + + SLSI_MUTEX_LOCK(ndev_vif->vif_mutex); + + values = slsi_read_mibs(sdev, NULL, get_values, ARRAY_SIZE(get_values), &mibrsp); + if (!values) { + ret = 0xFFFFFFFF; + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + goto exit_with_mibrsp; + } + + for (i = 0; i < ARRAY_SIZE(get_values); i++) { + if (values[i].type == SLSI_MIB_TYPE_UINT) { + *capabilities_mib_val[i] = values[i].u.uintValue; + SLSI_DBG2(sdev, SLSI_GSCAN, "MIB value = %ud\n", *capabilities_mib_val[i]); + } else { + SLSI_ERR(sdev, "invalid type(%d). iter:%d\n", values[i].type, i); + ret = 0xFFFFFFFF; + reply_status = SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE; + *capabilities_mib_val[i] = 0; + } + } + + kfree(values); +exit_with_mibrsp: + kfree(mibrsp.data); + SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); +exit: + slsi_vendor_nan_command_reply(wiphy, reply_status, ret, NAN_RESPONSE_GET_CAPABILITIES, 0, &nan_capabilities); + return ret; +} + +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 nlattr *nlattr_start; + 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); + evt_reason = fapi_get_u16(skb, u.mlme_nan_event_ind.reason_code); + + switch (event) { + case FAPI_EVENT_WIFI_EVENT_NAN_PUBLISH_TERMINATED: + hal_event = SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT; + break; + case FAPI_EVENT_WIFI_EVENT_NAN_MATCH_EXPIRED: + hal_event = SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT; + break; + case FAPI_EVENT_WIFI_EVENT_NAN_SUBSCRIBE_TERMINATED: + 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; + 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; + 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; + break; + default: + return; + } + +#ifdef CONFIG_SCSC_WLAN_DEBUG + SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", + slsi_print_event_name(hal_event), hal_event); +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) + 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"); + return; + } + + nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); + if (!nlattr_start) { + SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + return; + } + + switch (hal_event) { + case SLSI_NL80211_NAN_PUBLISH_TERMINATED_EVENT: + res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, identifier); + res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_PUBLISH_ID, evt_reason); + ndev_vif->nan.publish_id_map &= ~BIT(identifier); + break; + case SLSI_NL80211_NAN_MATCH_EXPIRED_EVENT: + res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, identifier); + res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, evt_reason); + break; + case SLSI_NL80211_NAN_SUBSCRIBE_TERMINATED_EVENT: + res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_ID, identifier); + res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_SUBSCRIBE_REASON, evt_reason); + ndev_vif->nan.subscribe_id_map &= ~BIT(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; + } + + if (res) { + SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + return; + } + + nla_nest_end(nl_skb, nlattr_start); + + cfg80211_vendor_event(nl_skb, GFP_KERNEL); +} + +void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) +{ + u16 tag_id, tag_len; + u8 *fapi_data_p, *ptr; + u8 followup_ie_header[] = {0xdd, 0, 0, 0x16, 0x32, 0x0b, 0x05}; + int fapi_data_len; + struct slsi_hal_nan_followup_ind *hal_evt; + struct sk_buff *nl_skb; + int res; + struct nlattr *nlattr_start; + + hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL); + if (!hal_evt) { + SLSI_ERR(sdev, "No memory for service_ind\n"); + return; + } + hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.publish_subscribe_id); + hal_evt->requestor_instance_id = fapi_get_u16(skb, u.mlme_nan_followup_ind.requestor_instance_id); + fapi_data_p = fapi_get_data(skb); + fapi_data_len = fapi_get_datalen(skb); + if (!fapi_data_len) { + SLSI_ERR(sdev, "mlme_nan_followup_ind no mbulk data\n"); + kfree(hal_evt); + return; + } + + memset(&hal_evt, 0, sizeof(hal_evt)); + + while (fapi_data_len) { + ptr = fapi_data_p; + if (fapi_data_len < ptr[1] + 2) { + SLSI_ERR(sdev, "len err[avail:%d,ie:%d]\n", fapi_data_len, fapi_data_p[1] + 2); + kfree(hal_evt); + return; + } + if (ptr[1] < sizeof(followup_ie_header) - 2 + 6 + 1 + 1) { + SLSI_ERR(sdev, "len err[min:%d,ie:%d]\n", (u32)sizeof(followup_ie_header) - 2 + 6 + 1 + 1, + fapi_data_p[1] + 2); + kfree(hal_evt); + return; + } + if (followup_ie_header[0] != ptr[0] || followup_ie_header[2] != ptr[2] || + followup_ie_header[3] != ptr[3] || followup_ie_header[4] != ptr[4] || + followup_ie_header[5] != ptr[5] || followup_ie_header[6] != ptr[6]) { + SLSI_ERR(sdev, "unknown IE:%x-%d\n", fapi_data_p[0], fapi_data_p[1] + 2); + kfree(hal_evt); + return; + } + + ptr += sizeof(followup_ie_header); + + ether_addr_copy(hal_evt->addr, ptr); + ptr += ETH_ALEN; + ptr += 1; /* skip priority */ + hal_evt->dw_or_faw = *ptr; + ptr += 1; + while (fapi_data_p[1] + 2 > (ptr - fapi_data_p) + 4) { + tag_id = *(u16 *)ptr; + ptr += 2; + tag_len = *(u16 *)ptr; + ptr += 2; + if (fapi_data_p[1] + 2 < (ptr - fapi_data_p) + tag_len) { + SLSI_ERR(sdev, "TLV error\n"); + kfree(hal_evt); + return; + } + if (tag_id == SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO) { + hal_evt->service_specific_info_len = tag_len; + memcpy(hal_evt->service_specific_info, ptr, tag_len); + } + ptr += tag_len; + } + + fapi_data_p += fapi_data_p[1] + 2; + fapi_data_len -= fapi_data_p[1] + 2; + } + +#ifdef CONFIG_SCSC_WLAN_DEBUG + SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", + slsi_print_event_name(SLSI_NL80211_NAN_FOLLOWUP_EVENT), SLSI_NL80211_NAN_FOLLOWUP_EVENT); +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) + nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT, + GFP_KERNEL); +#else + nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_FOLLOWUP_EVENT, + GFP_KERNEL); +#endif + + if (!nl_skb) { + SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); + kfree(hal_evt); + return; + } + + nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); + if (!nlattr_start) { + SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); + kfree(hal_evt); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + return; + } + + res = nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID, + cpu_to_le16(hal_evt->publish_subscribe_id)); + res |= nla_put_be16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID, + cpu_to_le16(hal_evt->requestor_instance_id)); + res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_ADDR, ETH_ALEN, hal_evt->addr); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW, hal_evt->dw_or_faw); + res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len); + if (hal_evt->service_specific_info_len) + res |= nla_put(nl_skb, NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len, + hal_evt->service_specific_info); + + if (res) { + SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); + kfree(hal_evt); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + return; + } + + nla_nest_end(nl_skb, nlattr_start); + + cfg80211_vendor_event(nl_skb, GFP_KERNEL); + kfree(hal_evt); +} + +void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb) +{ + u16 tag_id, tag_len; + u8 *fapi_data_p, *ptr; + u8 match_ie_header[] = {0xdd, 0, 0, 0x16, 0x32, 0x0b, 0x04}; + int fapi_data_len; + struct slsi_hal_nan_match_ind *hal_evt; + struct sk_buff *nl_skb; + int res, i; + struct slsi_hal_nan_receive_post_discovery *discovery_attr; + struct slsi_hal_nan_further_availability_channel *famchan; + struct nlattr *nlattr_start, *nlattr_nested; + + SLSI_DBG3(sdev, SLSI_GSCAN, "\n"); + + hal_evt = kmalloc(sizeof(*hal_evt), GFP_KERNEL); + if (!hal_evt) { + SLSI_ERR(sdev, "No memory for service_ind\n"); + return; + } + + hal_evt->publish_subscribe_id = fapi_get_u16(skb, u.mlme_nan_service_ind.publish_subscribe_id); + hal_evt->requestor_instance_id = fapi_get_u32(skb, u.mlme_nan_service_ind.requestor_instance_id); + fapi_data_p = fapi_get_data(skb); + fapi_data_len = fapi_get_datalen(skb); + if (!fapi_data_len) { + SLSI_ERR(sdev, "mlme_nan_followup_ind no mbulk data\n"); + kfree(hal_evt); + return; + } + + memset(hal_evt, 0, sizeof(*hal_evt)); + + while (fapi_data_len) { + ptr = fapi_data_p; + if (fapi_data_len < ptr[1] + 2) { + SLSI_ERR(sdev, "len err[avail:%d,ie:%d]\n", fapi_data_len, fapi_data_p[1] + 2); + kfree(hal_evt); + return; + } + if (ptr[1] < sizeof(match_ie_header) - 2 + 6 + 1 + 1 + 1) { + SLSI_ERR(sdev, "len err[min:%d,ie:%d]\n", (u32)sizeof(match_ie_header) - 2 + 6 + 1 + 1, + fapi_data_p[1] + 2); + kfree(hal_evt); + return; + } + if (match_ie_header[0] != ptr[0] || match_ie_header[2] != ptr[2] || + match_ie_header[3] != ptr[3] || match_ie_header[4] != ptr[4] || + match_ie_header[5] != ptr[5] || match_ie_header[6] != ptr[6]) { + SLSI_ERR(sdev, "unknown IE:%x-%d\n", fapi_data_p[0], fapi_data_p[1] + 2); + kfree(hal_evt); + return; + } + + ptr += sizeof(match_ie_header); + + ether_addr_copy(hal_evt->addr, ptr); + ptr += ETH_ALEN; + hal_evt->match_occurred_flag = *ptr; + ptr += 1; + hal_evt->out_of_resource_flag = *ptr; + ptr += 1; + hal_evt->rssi_value = *ptr; + ptr += 1; + while (fapi_data_p[1] + 2 > (ptr - fapi_data_p) + 4) { + tag_id = *(u16 *)ptr; + ptr += 2; + tag_len = *(u16 *)ptr; + ptr += 2; + if (fapi_data_p[1] + 2 < (ptr - fapi_data_p) + tag_len) { + SLSI_ERR(sdev, "TLV error\n"); + kfree(hal_evt); + return; + } + switch (tag_id) { + case SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO: + hal_evt->service_specific_info_len = tag_len; + memcpy(hal_evt->service_specific_info, ptr, tag_len); + break; + case SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB: + hal_evt->is_conn_capability_valid = 1; + if (*ptr & BIT(0)) + hal_evt->conn_capability.is_wfd_supported = 1; + if (*ptr & BIT(1)) + hal_evt->conn_capability.is_wfds_supported = 1; + if (*ptr & BIT(2)) + hal_evt->conn_capability.is_tdls_supported = 1; + if (*ptr & BIT(3)) + hal_evt->conn_capability.wlan_infra_field = 1; + break; + case SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM: + discovery_attr = &hal_evt->discovery_attr[hal_evt->num_rx_discovery_attr]; + discovery_attr->type = ptr[0]; + discovery_attr->role = ptr[1]; + discovery_attr->duration = ptr[2]; + discovery_attr->avail_interval_bitmap = le32_to_cpu(*(__le32 *)&ptr[3]); + ether_addr_copy(discovery_attr->addr, &ptr[7]); + discovery_attr->infrastructure_ssid_len = ptr[13]; + if (discovery_attr->infrastructure_ssid_len) + memcpy(discovery_attr->infrastructure_ssid_val, &ptr[14], + discovery_attr->infrastructure_ssid_len); + hal_evt->num_rx_discovery_attr++; + break; + case SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP: + famchan = &hal_evt->famchan[hal_evt->num_chans]; + famchan->entry_control = ptr[0]; + famchan->class_val = ptr[1]; + famchan->channel = ptr[2]; + famchan->mapid = ptr[3]; + famchan->avail_interval_bitmap = le32_to_cpu(*(__le32 *)&ptr[4]); + hal_evt->num_chans++; + break; + case SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE: + break; + } + ptr += tag_len; + } + + fapi_data_p += fapi_data_p[1] + 2; + fapi_data_len -= fapi_data_p[1] + 2; + } + +#ifdef CONFIG_SCSC_WLAN_DEBUG + SLSI_DBG1_NODEV(SLSI_GSCAN, "Event: %s(%d)\n", + slsi_print_event_name(SLSI_NL80211_NAN_MATCH_EVENT), SLSI_NL80211_NAN_MATCH_EVENT); +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) + nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT, + GFP_KERNEL); +#else + nl_skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_NAN_MATCH_EVENT, GFP_KERNEL); +#endif + if (!nl_skb) { + SLSI_ERR(sdev, "NO MEM for nl_skb!!!\n"); + kfree(hal_evt); + return; + } + + nlattr_start = nla_nest_start(nl_skb, NL80211_ATTR_VENDOR_DATA); + if (!nlattr_start) { + SLSI_ERR(sdev, "failed to put NL80211_ATTR_VENDOR_DATA\n"); + kfree(hal_evt); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + return; + } + + res = nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, hal_evt->publish_subscribe_id); + res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, hal_evt->requestor_instance_id); + res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_ADDR, ETH_ALEN, hal_evt->addr); + res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN, hal_evt->service_specific_info_len); + if (hal_evt->service_specific_info_len) + res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO, hal_evt->service_specific_info_len, + hal_evt->service_specific_info); + res |= nla_put_u16(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN, hal_evt->sdf_match_filter_len); + if (hal_evt->sdf_match_filter_len) + res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER, hal_evt->sdf_match_filter_len, + hal_evt->sdf_match_filter); + + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG, hal_evt->match_occurred_flag); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG, hal_evt->out_of_resource_flag); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_RSSI_VALUE, hal_evt->rssi_value); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED, + hal_evt->is_conn_capability_valid); + if (hal_evt->is_conn_capability_valid) { + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED, + hal_evt->conn_capability.is_ibss_supported); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED, + hal_evt->conn_capability.is_wfd_supported); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED, + hal_evt->conn_capability.is_wfds_supported); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED, + hal_evt->conn_capability.is_tdls_supported); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED, + hal_evt->conn_capability.is_mesh_supported); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD, + hal_evt->conn_capability.wlan_infra_field); + } + + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR, hal_evt->num_rx_discovery_attr); + for (i = 0; i < hal_evt->num_rx_discovery_attr; i++) { + nlattr_nested = nla_nest_start(nl_skb, NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR); + if (!nlattr_nested) { + SLSI_ERR(sdev, "Error in nla_nest_start\n"); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + kfree(hal_evt); + return; + } + discovery_attr = &hal_evt->discovery_attr[i]; + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE, discovery_attr->type); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE, discovery_attr->role); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION, discovery_attr->duration); + res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP, + discovery_attr->avail_interval_bitmap); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID, discovery_attr->mapid); + res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR, ETH_ALEN, discovery_attr->addr); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN, discovery_attr->mesh_id_len); + if (discovery_attr->mesh_id_len) + res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID, discovery_attr->mesh_id_len, + discovery_attr->mesh_id); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN, + discovery_attr->infrastructure_ssid_len); + if (discovery_attr->infrastructure_ssid_len) + res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL, + discovery_attr->infrastructure_ssid_len, discovery_attr->infrastructure_ssid_val); + nla_nest_end(nl_skb, nlattr_nested); + } + + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_NUM_CHANS, hal_evt->num_chans); + for (i = 0; i < hal_evt->num_chans; i++) { + nlattr_nested = nla_nest_start(nl_skb, NAN_EVT_ATTR_MATCH_FAMCHAN); + if (!nlattr_nested) { + SLSI_ERR(sdev, "Error in nla_nest_start\n"); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + kfree(hal_evt); + return; + } + famchan = &hal_evt->famchan[i]; + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL, famchan->entry_control); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL, famchan->class_val); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_CHANNEL, famchan->channel); + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_FAM_MAPID, famchan->mapid); + res |= nla_put_u32(nl_skb, NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP, + famchan->avail_interval_bitmap); + } + + res |= nla_put_u8(nl_skb, NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN, hal_evt->cluster_attribute_len); + if (hal_evt->cluster_attribute_len) + res |= nla_put(nl_skb, NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE, hal_evt->cluster_attribute_len, + hal_evt->cluster_attribute); + + if (res) { + SLSI_ERR(sdev, "Error in nla_put*:%x\n", res); + /* Dont use slsi skb wrapper for this free */ + kfree_skb(nl_skb); + kfree(hal_evt); + return; + } + + nla_nest_end(nl_skb, nlattr_start); + + cfg80211_vendor_event(nl_skb, GFP_KERNEL); + kfree(hal_evt); +} diff --git a/drivers/net/wireless/scsc/nl80211_vendor_nan.h b/drivers/net/wireless/scsc/nl80211_vendor_nan.h new file mode 100755 index 000000000000..c6ceed1122b3 --- /dev/null +++ b/drivers/net/wireless/scsc/nl80211_vendor_nan.h @@ -0,0 +1,745 @@ +/***************************************************************************** + * + * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved + * + ****************************************************************************/ +#ifndef __SLSI_NL80211_VENDOR_NAN_H_ +#define __SLSI_NL80211_VENDOR_NAN_H_ + +enum SLSI_NAN_REPLY_ATTRIBUTES { + NAN_REPLY_ATTR_STATUS_TYPE, + NAN_REPLY_ATTR_VALUE, + NAN_REPLY_ATTR_RESPONSE_TYPE, + NAN_REPLY_ATTR_PUBLISH_SUBSCRIBE_TYPE, + NAN_REPLY_ATTR_CAP_MAX_CONCURRENT_CLUSTER, + NAN_REPLY_ATTR_CAP_MAX_PUBLISHES, + NAN_REPLY_ATTR_CAP_MAX_SUBSCRIBES, + NAN_REPLY_ATTR_CAP_MAX_SERVICE_NAME_LEN, + NAN_REPLY_ATTR_CAP_MAX_MATCH_FILTER_LEN, + NAN_REPLY_ATTR_CAP_MAX_TOTAL_MATCH_FILTER_LEN, + NAN_REPLY_ATTR_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN, + NAN_REPLY_ATTR_CAP_MAX_VSA_DATA_LEN, + NAN_REPLY_ATTR_CAP_MAX_MESH_DATA_LEN, + NAN_REPLY_ATTR_CAP_MAX_NDI_INTERFACES, + NAN_REPLY_ATTR_CAP_MAX_NDP_SESSIONS, + NAN_REPLY_ATTR_CAP_MAX_APP_INFO_LEN +}; + +enum SLSI_NAN_REQ_ATTRIBUTES { + NAN_REQ_ATTR_MASTER_PREF, + NAN_REQ_ATTR_CLUSTER_LOW, + NAN_REQ_ATTR_CLUSTER_HIGH, + NAN_REQ_ATTR_HOP_COUNT_LIMIT_VAL, + NAN_REQ_ATTR_SID_BEACON_VAL, + NAN_REQ_ATTR_SUPPORT_2G4_VAL, + NAN_REQ_ATTR_SUPPORT_5G_VAL, + NAN_REQ_ATTR_RSSI_CLOSE_2G4_VAL, + NAN_REQ_ATTR_RSSI_MIDDLE_2G4_VAL, + NAN_REQ_ATTR_RSSI_PROXIMITY_2G4_VAL, + NAN_REQ_ATTR_BEACONS_2G4_VAL, + NAN_REQ_ATTR_SDF_2G4_VAL, + NAN_REQ_ATTR_CHANNEL_2G4_MHZ_VAL, + NAN_REQ_ATTR_RSSI_PROXIMITY_VAL, + NAN_REQ_ATTR_RSSI_CLOSE_5G_VAL, + NAN_REQ_ATTR_RSSI_CLOSE_PROXIMITY_5G_VAL, + NAN_REQ_ATTR_RSSI_MIDDLE_5G_VAL, + NAN_REQ_ATTR_RSSI_PROXIMITY_5G_VAL, + NAN_REQ_ATTR_BEACON_5G_VAL, + NAN_REQ_ATTR_SDF_5G_VAL, + NAN_REQ_ATTR_CHANNEL_5G_MHZ_VAL, + NAN_REQ_ATTR_RSSI_WINDOW_SIZE_VAL, + NAN_REQ_ATTR_OUI_VAL, + NAN_REQ_ATTR_MAC_ADDR_VAL, + NAN_REQ_ATTR_CLUSTER_VAL, + NAN_REQ_ATTR_SOCIAL_CH_SCAN_DWELL_TIME, + NAN_REQ_ATTR_SOCIAL_CH_SCAN_PERIOD, + NAN_REQ_ATTR_RANDOM_FACTOR_FORCE_VAL, + NAN_REQ_ATTR_HOP_COUNT_FORCE_VAL, + NAN_REQ_ATTR_CONN_CAPABILITY_PAYLOAD_TX, + NAN_REQ_ATTR_CONN_CAPABILITY_IBSS, + NAN_REQ_ATTR_CONN_CAPABILITY_WFD, + NAN_REQ_ATTR_CONN_CAPABILITY_WFDS, + NAN_REQ_ATTR_CONN_CAPABILITY_TDLS, + NAN_REQ_ATTR_CONN_CAPABILITY_MESH, + NAN_REQ_ATTR_CONN_CAPABILITY_WLAN_INFRA, + NAN_REQ_ATTR_DISCOVERY_ATTR_NUM_ENTRIES, + NAN_REQ_ATTR_DISCOVERY_ATTR_VAL, + NAN_REQ_ATTR_CONN_TYPE, + NAN_REQ_ATTR_NAN_ROLE, + NAN_REQ_ATTR_TRANSMIT_FREQ, + NAN_REQ_ATTR_AVAILABILITY_DURATION, + NAN_REQ_ATTR_AVAILABILITY_INTERVAL, + NAN_REQ_ATTR_MESH_ID_LEN, + NAN_REQ_ATTR_MESH_ID, + NAN_REQ_ATTR_INFRASTRUCTURE_SSID_LEN, + NAN_REQ_ATTR_INFRASTRUCTURE_SSID, + NAN_REQ_ATTR_FURTHER_AVAIL_NUM_ENTRIES, + NAN_REQ_ATTR_FURTHER_AVAIL_VAL, + NAN_REQ_ATTR_FURTHER_AVAIL_ENTRY_CTRL, + NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_CLASS, + NAN_REQ_ATTR_FURTHER_AVAIL_CHAN, + NAN_REQ_ATTR_FURTHER_AVAIL_CHAN_MAPID, + NAN_REQ_ATTR_FURTHER_AVAIL_INTERVAL_BITMAP, + NAN_REQ_ATTR_PUBLISH_ID, + NAN_REQ_ATTR_PUBLISH_TTL, + NAN_REQ_ATTR_PUBLISH_PERIOD, + NAN_REQ_ATTR_PUBLISH_TYPE, + NAN_REQ_ATTR_PUBLISH_TX_TYPE, + NAN_REQ_ATTR_PUBLISH_COUNT, + NAN_REQ_ATTR_PUBLISH_SERVICE_NAME_LEN, + NAN_REQ_ATTR_PUBLISH_SERVICE_NAME, + NAN_REQ_ATTR_PUBLISH_MATCH_ALGO, + NAN_REQ_ATTR_PUBLISH_SERVICE_INFO_LEN, + NAN_REQ_ATTR_PUBLISH_SERVICE_INFO, + NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER_LEN, + NAN_REQ_ATTR_PUBLISH_RX_MATCH_FILTER, + NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER_LEN, + NAN_REQ_ATTR_PUBLISH_TX_MATCH_FILTER, + NAN_REQ_ATTR_PUBLISH_RSSI_THRESHOLD_FLAG, + NAN_REQ_ATTR_PUBLISH_CONN_MAP, + NAN_REQ_ATTR_PUBLISH_RECV_IND_CFG, + NAN_REQ_ATTR_SUBSCRIBE_ID, + NAN_REQ_ATTR_SUBSCRIBE_TTL, + NAN_REQ_ATTR_SUBSCRIBE_PERIOD, + NAN_REQ_ATTR_SUBSCRIBE_TYPE, + NAN_REQ_ATTR_SUBSCRIBE_RESP_FILTER_TYPE, + NAN_REQ_ATTR_SUBSCRIBE_RESP_INCLUDE, + NAN_REQ_ATTR_SUBSCRIBE_USE_RESP_FILTER, + NAN_REQ_ATTR_SUBSCRIBE_SSI_REQUIRED, + NAN_REQ_ATTR_SUBSCRIBE_MATCH_INDICATOR, + NAN_REQ_ATTR_SUBSCRIBE_COUNT, + NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME_LEN, + NAN_REQ_ATTR_SUBSCRIBE_SERVICE_NAME, + NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO_LEN, + NAN_REQ_ATTR_SUBSCRIBE_SERVICE_INFO, + NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER_LEN, + NAN_REQ_ATTR_SUBSCRIBE_RX_MATCH_FILTER, + NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER_LEN, + NAN_REQ_ATTR_SUBSCRIBE_TX_MATCH_FILTER, + NAN_REQ_ATTR_SUBSCRIBE_RSSI_THRESHOLD_FLAG, + NAN_REQ_ATTR_SUBSCRIBE_CONN_MAP, + NAN_REQ_ATTR_SUBSCRIBE_NUM_INTF_ADDR_PRESENT, + NAN_REQ_ATTR_SUBSCRIBE_INTF_ADDR, + NAN_REQ_ATTR_SUBSCRIBE_RECV_IND_CFG, + NAN_REQ_ATTR_FOLLOWUP_ID, + NAN_REQ_ATTR_FOLLOWUP_REQUESTOR_ID, + NAN_REQ_ATTR_FOLLOWUP_ADDR, + NAN_REQ_ATTR_FOLLOWUP_PRIORITY, + NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME_LEN, + NAN_REQ_ATTR_FOLLOWUP_SERVICE_NAME, + NAN_REQ_ATTR_FOLLOWUP_TX_WINDOW, + NAN_REQ_ATTR_FOLLOWUP_RECV_IND_CFG +}; + +enum SLSI_NAN_RESP_ATTRIBUTES { + NAN_RESP_ATTR_MAX_CONCURRENT_NAN_CLUSTERS, + NAN_RESP_ATTR_MAX_PUBLISHES, + NAN_RESP_ATTR_MAX_SUBSCRIBES, + NAN_RESP_ATTR_MAX_SERVICE_NAME_LEN, + NAN_RESP_ATTR_MAX_MATCH_FILTER_LEN, + NAN_RESP_ATTR_MAX_TOTAL_MATCH_FILTER_LEN, + NAN_RESP_ATTR_MAX_SERVICE_SPECIFIC_INFO_LEN, + NAN_RESP_ATTR_MAX_VSA_DATA_LEN, + NAN_RESP_ATTR_MAX_MESH_DATA_LEN, + NAN_RESP_ATTR_MAX_NDI_INTERFACES, + NAN_RESP_ATTR_MAX_NDP_SESSIONS, + NAN_RESP_ATTR_MAX_APP_INFO_LEN, + NAN_RESP_ATTR_SUBSCRIBE_ID, + NAN_RESP_ATTR_PUBLISH_ID +}; + +enum SLSI_NAN_EVT_ATTRIBUTES { + NAN_EVT_ATTR_MATCH_PUBLISH_SUBSCRIBE_ID, + NAN_EVT_ATTR_MATCH_REQUESTOR_INSTANCE_ID, + NAN_EVT_ATTR_MATCH_ADDR, + NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO_LEN, + NAN_EVT_ATTR_MATCH_SERVICE_SPECIFIC_INFO, + NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER_LEN, + NAN_EVT_ATTR_MATCH_SDF_MATCH_FILTER, + NAN_EVT_ATTR_MATCH_MATCH_OCCURRED_FLAG, + NAN_EVT_ATTR_MATCH_OUT_OF_RESOURCE_FLAG, + NAN_EVT_ATTR_MATCH_RSSI_VALUE, + /*CONN_CAPABILITY*/ + NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFD_SUPPORTED, + NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_WFDS_SUPPORTED, + NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_TDLS_SUPPORTED, + NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_IBSS_SUPPORTED, + NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_IS_MESH_SUPPORTED, + NAN_EVT_ATTR_MATCH_CONN_CAPABILITY_WLAN_INFRA_FIELD, + NAN_EVT_ATTR_MATCH_NUM_RX_DISCOVERY_ATTR, + NAN_EVT_ATTR_MATCH_RX_DISCOVERY_ATTR, + /*NANRECEIVEPOSTDISCOVERY DISCOVERY_ATTR,*/ + NAN_EVT_ATTR_MATCH_DISC_ATTR_TYPE, + NAN_EVT_ATTR_MATCH_DISC_ATTR_ROLE, + NAN_EVT_ATTR_MATCH_DISC_ATTR_DURATION, + NAN_EVT_ATTR_MATCH_DISC_ATTR_AVAIL_INTERVAL_BITMAP, + NAN_EVT_ATTR_MATCH_DISC_ATTR_MAPID, + NAN_EVT_ATTR_MATCH_DISC_ATTR_ADDR, + NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID_LEN, + NAN_EVT_ATTR_MATCH_DISC_ATTR_MESH_ID, + NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_LEN, + NAN_EVT_ATTR_MATCH_DISC_ATTR_INFRASTRUCTURE_SSID_VAL, + NAN_EVT_ATTR_MATCH_NUM_CHANS, + NAN_EVT_ATTR_MATCH_FAMCHAN, + /*FAMCHAN[32],*/ + NAN_EVT_ATTR_MATCH_FAM_ENTRY_CONTROL, + NAN_EVT_ATTR_MATCH_FAM_CLASS_VAL, + NAN_EVT_ATTR_MATCH_FAM_CHANNEL, + NAN_EVT_ATTR_MATCH_FAM_MAPID, + NAN_EVT_ATTR_MATCH_FAM_AVAIL_INTERVAL_BITMAP, + NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE_LEN, + NAN_EVT_ATTR_MATCH_CLUSTER_ATTRIBUTE, + NAN_EVT_ATTR_PUBLISH_ID, + NAN_EVT_ATTR_PUBLISH_REASON, + NAN_EVT_ATTR_SUBSCRIBE_ID, + NAN_EVT_ATTR_SUBSCRIBE_REASON, + NAN_EVT_ATTR_DISABLED_REASON, + NAN_EVT_ATTR_FOLLOWUP_PUBLISH_SUBSCRIBE_ID, + NAN_EVT_ATTR_FOLLOWUP_REQUESTOR_INSTANCE_ID, + NAN_EVT_ATTR_FOLLOWUP_ADDR, + NAN_EVT_ATTR_FOLLOWUP_DW_OR_FAW, + NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO_LEN, + NAN_EVT_ATTR_FOLLOWUP_SERVICE_SPECIFIC_INFO, + NAN_EVT_ATTR_DISCOVERY_ENGINE_EVT_TYPE, + NAN_EVT_ATTR_DISCOVERY_ENGINE_MAC_ADDR, + NAN_EVT_ATTR_DISCOVERY_ENGINE_CLUSTER +}; + +#define SLSI_FAPI_NAN_CONFIG_PARAM_SID_BEACON 0X0003 +#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_CLOSE 0X0004 +#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_MIDDLE 0X0005 +#define SLSI_FAPI_NAN_CONFIG_PARAM_2_4_RSSI_PROXIMITY 0X0006 +#define SLSI_FAPI_NAN_CONFIG_PARAM_BAND_USAGE 0X0007 +#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_CLOSE 0X0008 +#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_MIDDLE 0X0009 +#define SLSI_FAPI_NAN_CONFIG_PARAM_5_RSSI_PROXIMITY 0X000A +#define SLSI_FAPI_NAN_CONFIG_PARAM_HOP_COUNT_LIMIT 0X000B +#define SLSI_FAPI_NAN_CONFIG_PARAM_RSSI_WINDOW_SIZE 0X000C +#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_2_4 0X000D +#define SLSI_FAPI_NAN_CONFIG_PARAM_SCAN_PARAMETER_5 0X000E +#define SLSI_FAPI_NAN_CONFIG_PARAM_MASTER_PREFERENCE 0X000F +#define SLSI_FAPI_NAN_CONFIG_PARAM_CONNECTION_CAPAB 0X0010 +#define SLSI_FAPI_NAN_CONFIG_PARAM_POST_DISCOVER_PARAM 0X0011 +#define SLSI_FAPI_NAN_CONFIG_PARAM_FURTHER_AVAIL_CHANNEL_MAP 0X0012 +#define SLSI_FAPI_NAN_CONFIG_PARAM_ADDR_RANDOM_INTERVAL 0X0013 +#define SLSI_FAPI_NAN_SERVICE_NAME 0X0020 +#define SLSI_FAPI_NAN_SERVICE_SPECIFIC_INFO 0X0021 +#define SLSI_FAPI_NAN_RX_MATCH_FILTER 0X0022 +#define SLSI_FAPI_NAN_TX_MATCH_FILTER 0X0023 +#define SLSI_FAPI_NAN_SDF_MATCH_FILTER 0X0024 +#define SLSI_FAPI_NAN_CLUSTER_ATTRIBUTE 0X0025 + +#define SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS 3 +#define SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN 255 +#define SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN 1024 +#define SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN 255 +#define SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS 42 +#define SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN 5 + +enum slsi_wifi_hal_nan_status_type { + /* NAN Protocol Response Codes */ + SLSI_HAL_NAN_STATUS_SUCCESS = 0, + /* NAN Discovery Engine/Host driver failures */ + SLSI_HAL_NAN_STATUS_INTERNAL_FAILURE = 1, + /* NAN OTA failures */ + SLSI_HAL_NAN_STATUS_PROTOCOL_FAILURE = 2, + /* if the publish/subscribe id is invalid */ + SLSI_HAL_NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID = 3, + /* If we run out of resources allocated */ + SLSI_HAL_NAN_STATUS_NO_RESOURCE_AVAILABLE = 4, + /* if invalid params are passed */ + SLSI_HAL_NAN_STATUS_INVALID_PARAM = 5, + /* if the requestor instance id is invalid */ + SLSI_HAL_NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID = 6, + /* if the ndp id is invalid */ + SLSI_HAL_NAN_STATUS_INVALID_NDP_ID = 7, + /* if NAN is enabled when wifi is turned off */ + SLSI_HAL_NAN_STATUS_NAN_NOT_ALLOWED = 8, + /* if over the air ack is not received */ + SLSI_HAL_NAN_STATUS_NO_OTA_ACK = 9, + /* If NAN is already enabled and we are try to re-enable the same */ + SLSI_HAL_NAN_STATUS_ALREADY_ENABLED = 10, + /* If followup message internal queue is full */ + SLSI_HAL_NAN_STATUS_FOLLOWUP_QUEUE_FULL = 11, + /* Unsupported concurrency session enabled, NAN disabled notified */ + SLSI_HAL_NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED = 12 +}; + +enum slsi_nan_status_type { + /* NAN Protocol Response Codes */ + NAN_STATUS_SUCCESS = 0, + NAN_STATUS_TIMEOUT = 1, + NAN_STATUS_DE_FAILURE = 2, + NAN_STATUS_INVALID_MSG_VERSION = 3, + NAN_STATUS_INVALID_MSG_LEN = 4, + NAN_STATUS_INVALID_MSG_ID = 5, + NAN_STATUS_INVALID_HANDLE = 6, + NAN_STATUS_NO_SPACE_AVAILABLE = 7, + NAN_STATUS_INVALID_PUBLISH_TYPE = 8, + NAN_STATUS_INVALID_TX_TYPE = 9, + NAN_STATUS_INVALID_MATCH_ALGORITHM = 10, + NAN_STATUS_DISABLE_IN_PROGRESS = 11, + NAN_STATUS_INVALID_TLV_LEN = 12, + NAN_STATUS_INVALID_TLV_TYPE = 13, + NAN_STATUS_MISSING_TLV_TYPE = 14, + NAN_STATUS_INVALID_TOTAL_TLVS_LEN = 15, + NAN_STATUS_INVALID_MATCH_HANDLE = 16, + NAN_STATUS_INVALID_TLV_VALUE = 17, + NAN_STATUS_INVALID_TX_PRIORITY = 18, + NAN_STATUS_INVALID_CONNECTION_MAP = 19, + NAN_STATUS_INVALID_TCA_ID = 20, + NAN_STATUS_INVALID_STATS_ID = 21, + NAN_STATUS_NAN_NOT_ALLOWED = 22, + NAN_STATUS_NO_OTA_ACK = 23, + NAN_STATUS_TX_FAIL = 24, + /* 25-4095 Reserved */ + /* NAN Configuration Response codes */ + NAN_STATUS_INVALID_RSSI_CLOSE_VALUE = 4096, + NAN_STATUS_INVALID_RSSI_MIDDLE_VALUE = 4097, + NAN_STATUS_INVALID_HOP_COUNT_LIMIT = 4098, + NAN_STATUS_INVALID_MASTER_PREFERENCE_VALUE = 4099, + NAN_STATUS_INVALID_LOW_CLUSTER_ID_VALUE = 4100, + NAN_STATUS_INVALID_HIGH_CLUSTER_ID_VALUE = 4101, + NAN_STATUS_INVALID_BACKGROUND_SCAN_PERIOD = 4102, + NAN_STATUS_INVALID_RSSI_PROXIMITY_VALUE = 4103, + NAN_STATUS_INVALID_SCAN_CHANNEL = 4104, + NAN_STATUS_INVALID_POST_NAN_CONNECTIVITY_CAPABILITIES_BITMAP = 4105, + NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_NUMCHAN_VALUE = 4106, + NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_DURATION_VALUE = 4107, + NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CLASS_VALUE = 4108, + NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_CHANNEL_VALUE = 4109, + NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_AVAILABILITY_INTERVAL_BITMAP_VALUE = 4110, + NAN_STATUS_INVALID_FURTHER_AVAILABILITY_MAP_MAP_ID = 4111, + NAN_STATUS_INVALID_POST_NAN_DISCOVERY_CONN_TYPE_VALUE = 4112, + NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DEVICE_ROLE_VALUE = 4113, + NAN_STATUS_INVALID_POST_NAN_DISCOVERY_DURATION_VALUE = 4114, + NAN_STATUS_INVALID_POST_NAN_DISCOVERY_BITMAP_VALUE = 4115, + NAN_STATUS_MISSING_FUTHER_AVAILABILITY_MAP = 4116, + NAN_STATUS_INVALID_BAND_CONFIG_FLAGS = 4117, + NAN_STATUS_INVALID_RANDOM_FACTOR_UPDATE_TIME_VALUE = 4118, + NAN_STATUS_INVALID_ONGOING_SCAN_PERIOD = 4119, + NAN_STATUS_INVALID_DW_INTERVAL_VALUE = 4120, + NAN_STATUS_INVALID_DB_INTERVAL_VALUE = 4121, + /* 4122-8191 RESERVED */ + NAN_TERMINATED_REASON_INVALID = 8192, + NAN_TERMINATED_REASON_TIMEOUT = 8193, + NAN_TERMINATED_REASON_USER_REQUEST = 8194, + NAN_TERMINATED_REASON_FAILURE = 8195, + NAN_TERMINATED_REASON_COUNT_REACHED = 8196, + NAN_TERMINATED_REASON_DE_SHUTDOWN = 8197, + NAN_TERMINATED_REASON_DISABLE_IN_PROGRESS = 8198, + NAN_TERMINATED_REASON_POST_DISC_ATTR_EXPIRED = 8199, + NAN_TERMINATED_REASON_POST_DISC_LEN_EXCEEDED = 8200, + NAN_TERMINATED_REASON_FURTHER_AVAIL_MAP_EMPTY = 8201 +}; + +enum slsi_nan_response_type { + NAN_RESPONSE_ENABLED = 0, + NAN_RESPONSE_DISABLED = 1, + NAN_RESPONSE_PUBLISH = 2, + NAN_RESPONSE_PUBLISH_CANCEL = 3, + NAN_RESPONSE_TRANSMIT_FOLLOWUP = 4, + NAN_RESPONSE_SUBSCRIBE = 5, + NAN_RESPONSE_SUBSCRIBE_CANCEL = 6, + NAN_RESPONSE_STATS = 7, + NAN_RESPONSE_CONFIG = 8, + NAN_RESPONSE_TCA = 9, + NAN_RESPONSE_ERROR = 10, + NAN_RESPONSE_BEACON_SDF_PAYLOAD = 11, + NAN_RESPONSE_GET_CAPABILITIES = 12 +}; + +enum slsi_nan_disc_event_type { + NAN_EVENT_ID_DISC_MAC_ADDR = 0, + NAN_EVENT_ID_STARTED_CLUSTER, + NAN_EVENT_ID_JOINED_CLUSTER +}; + +struct slsi_hal_nan_social_channel_scan_params { + u8 dwell_time[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS]; + u16 scan_period[SLSI_HAL_NAN_MAX_SOCIAL_CHANNELS]; +}; + +struct slsi_hal_nan_connectivity_capability { + u8 payload_transmit_flag; + u8 is_wfd_supported; + u8 is_wfds_supported; + u8 is_tdls_supported; + u8 is_ibss_supported; + u8 is_mesh_supported; + u8 wlan_infra_field; +}; + +struct slsi_hal_nan_post_discovery_param { + u8 type; /* NanConnectionType */ + u8 role; /* NanDeviceRole */ + u8 transmit_freq; + u8 duration; /* NanAvailDuration */ + u32 avail_interval_bitmap; + u8 addr[ETH_ALEN]; + u16 mesh_id_len; + u8 mesh_id[32]; + u16 infrastructure_ssid_len; + u8 infrastructure_ssid_val[32]; +}; + +struct slsi_hal_nan_further_availability_channel { + /* struct slsi_hal_nan_further_availability_channel*/ + u8 entry_control; + u8 class_val; + u8 channel; + u8 mapid; + u32 avail_interval_bitmap; +}; + +struct slsi_hal_nan_further_availability_map { + u8 numchans; + struct slsi_hal_nan_further_availability_channel famchan[32]; +}; + +struct slsi_hal_nan_receive_post_discovery { + u8 type; + u8 role; + u8 duration; + u32 avail_interval_bitmap; + u8 mapid; + u8 addr[ETH_ALEN]; + u16 mesh_id_len; + u8 mesh_id[32]; + u16 infrastructure_ssid_len; + u8 infrastructure_ssid_val[32]; +}; + +struct slsi_hal_nan_enable_req { + /* Mandatory parameters below */ + u8 master_pref; + u16 cluster_low; + u16 cluster_high; + + u8 config_support_5g; + u8 support_5g_val; + u8 config_sid_beacon; + u8 sid_beacon_val; + u8 config_2dot4g_rssi_close; + u8 rssi_close_2dot4g_val; + + u8 config_2dot4g_rssi_middle; + u8 rssi_middle_2dot4g_val; + + u8 config_2dot4g_rssi_proximity; + u8 rssi_proximity_2dot4g_val; + + u8 config_hop_count_limit; + u8 hop_count_limit_val; + + u8 config_2dot4g_support; + u8 support_2dot4g_val; + + u8 config_2dot4g_beacons; + u8 beacon_2dot4g_val; + u8 config_2dot4g_sdf; + u8 sdf_2dot4g_val; + u8 config_5g_beacons; + u8 beacon_5g_val; + u8 config_5g_sdf; + u8 sdf_5g_val; + u8 config_5g_rssi_close; + u8 rssi_close_5g_val; + u8 config_5g_rssi_middle; + u8 rssi_middle_5g_val; + u8 config_5g_rssi_close_proximity; + u8 rssi_close_proximity_5g_val; + u8 config_rssi_window_size; + u8 rssi_window_size_val; + /* The 24 bit Organizationally Unique ID + the 8 bit Network Id. */ + u8 config_oui; + u32 oui_val; + u8 config_intf_addr; + u8 intf_addr_val[ETH_ALEN]; + + u8 config_cluster_attribute_val; + u8 config_scan_params; + struct slsi_hal_nan_social_channel_scan_params scan_params_val; + u8 config_random_factor_force; + u8 random_factor_force_val; + u8 config_hop_count_force; + u8 hop_count_force_val; + + /* channel frequency in MHz to enable Nan on */ + u8 config_24g_channel; + u32 channel_24g_val; + + u8 config_5g_channel; + int channel_5g_val; +}; + +struct slsi_hal_nan_publish_req { + /* id 0 means new publish, any other id is existing publish */ + u16 publish_id; + /* how many seconds to run for. 0 means forever until canceled */ + u16 ttl; + /* periodicity of OTA unsolicited publish. + * Specified in increments of 500 ms + */ + u16 period; + u8 publish_type;/* 0= unsolicited, solicited = 1, 2= both */ + u8 tx_type; /* 0 = broadcast, 1= unicast if solicited publish */ + /* number of OTA Publish, 0 means forever until canceled */ + u8 publish_count; + u16 service_name_len; + u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN]; + u8 publish_match_indicator; + + u16 service_specific_info_len; + u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + u16 rx_match_filter_len; + u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; + + u16 tx_match_filter_len; + u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; + + u8 rssi_threshold_flag; + + /* 8-bit bitmap which allows the Host to associate this publish + * with a particular Post-NAN Connectivity attribute + * which has been sent down in a NanConfigureRequest/NanEnableRequest + * message. If the DE fails to find a configured Post-NAN + * connectivity attributes referenced by the bitmap, + * the DE will return an error code to the Host. + * If the Publish is configured to use a Post-NAN Connectivity + * attribute and the Host does not refresh the Post-NAN Connectivity + * attribute the Publish will be canceled and the Host will be sent + * a PublishTerminatedIndication message. + */ + u8 connmap; + /* Set/Enable corresponding bits to disable any + * indications that follow a publish. + * BIT0 - Disable publish termination indication. + * BIT1 - Disable match expired indication. + * BIT2 - Disable followUp indication received (OTA). + */ + u8 recv_indication_cfg; +}; + +struct slsi_hal_nan_subscribe_req { + /* id 0 means new subscribe, non zero is existing subscribe */ + u16 subscribe_id; + /* how many seconds to run for. 0 means forever until canceled */ + u16 ttl; + /* periodicity of OTA Active Subscribe. Units in increments + * of 500 ms , 0 = attempt every DW + */ + u16 period; + + /* Flag which specifies how the Subscribe request shall be processed. */ + u8 subscribe_type; /* 0 - PASSIVE , 1- ACTIVE */ + + /* Flag which specifies on Active Subscribes how the Service Response + * Filter attribute is populated. + */ + u8 service_response_filter; /* 0 - Bloom Filter, 1 - MAC Addr */ + + /* Flag which specifies how the Service Response Filter Include + * bit is populated. + * 0=Do not respond if in the Address Set, 1= Respond + */ + u8 service_response_include; + + /* Flag which specifies if the Service Response Filter + * should be used when creating Subscribes. + * 0=Do not send the Service Response Filter,1= send + */ + u8 use_service_response_filter; + + /* Flag which specifies if the Service Specific Info is needed in + * the Publish message before creating the MatchIndication + */ + u8 ssi_required_for_match_indication; /* 0=Not needed, 1= Required */ + + /* Field which specifies how matching indication to host is controlled. + * 0 - Match and Indicate Once + * 1 - Match and Indicate continuous + * 2 - Match and Indicate never. This means don't + * indicate match to host. + * 3 - Reserved + */ + u8 subscribe_match_indicator; + + /* The number of Subscribe Matches which should occur + * before the Subscribe request is automatically terminated. + */ + /* If this value is 0 this field is not used by DE.*/ + u8 subscribe_count; + + /* length of service name */ + /* UTF-8 encoded string identifying the service */ + u16 service_name_len; + u8 service_name[SLSI_HAL_NAN_MAX_SERVICE_NAME_LEN]; + + /* Sequence of values which further specify the published service + * beyond the service name + */ + u16 service_specific_info_len; + u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + + /* Ordered sequence of pairs used to filter out + * received publish discovery messages. + * This can be sent both for a Passive or an Active Subscribe + */ + u16 rx_match_filter_len; + u8 rx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; + + /* Ordered sequence of pairs included in the + * Discovery Frame when an Active Subscribe is used. + */ + u16 tx_match_filter_len; + u8 tx_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; + u8 rssi_threshold_flag; + + u8 connmap; + /* NAN Interface Address, conforming to the format as described in + * 8.2.4.3.2 of IEEE Std. 802.11-2012. + */ + u8 num_intf_addr_present; + u8 intf_addr[SLSI_HAL_NAN_MAX_SUBSCRIBE_MAX_ADDRESS][ETH_ALEN]; + /* Set/Enable corresponding bits to disable + * indications that follow a subscribe. + * BIT0 - Disable subscribe termination indication. + * BIT1 - Disable match expired indication. + * BIT2 - Disable followUp indication received (OTA). + */ + u8 recv_indication_cfg; +}; + +struct slsi_hal_nan_transmit_followup_req { + /* Publish or Subscribe Id of an earlier Publish/Subscribe */ + u16 publish_subscribe_id; + + /* This Id is the Requestor Instance that is passed as + * part of earlier MatchInd/FollowupInd message. + */ + u32 requestor_instance_id; + u8 addr[ETH_ALEN]; /* Unicast address */ + u8 priority; /* priority of the request 2=high */ + u8 dw_or_faw; /* 0= send in a DW, 1=send in FAW */ + + /* Sequence of values which further specify the published service beyond + * the service name. + */ + u16 service_specific_info_len; + u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + /* Set/Enable corresponding bits to disable + * responses after followUp. + * BIT0 - Disable followUp response from FW. + */ + u8 recv_indication_cfg; +}; + +struct slsi_hal_nan_config_req { + u8 config_sid_beacon; + u8 sid_beacon; + u8 config_rssi_proximity; + u8 rssi_proximity; + u8 config_master_pref; + u8 master_pref; + /* 1 byte value which defines the RSSI filter threshold. + * Any Service Descriptors received above this value + * that are configured for RSSI filtering will be dropped. + * The rssi values should be specified without sign. + * For eg: -70dBm should be specified as 70. + */ + u8 config_5g_rssi_close_proximity; + u8 rssi_close_proximity_5g_val; + u8 config_rssi_window_size; + u16 rssi_window_size_val; + /* If set to 1, the Discovery Engine will enclose the Cluster + * Attribute only sent in Beacons in a Vendor Specific Attribute + * and transmit in a Service Descriptor Frame. + */ + u8 config_cluster_attribute_val; + u8 config_scan_params; + struct slsi_hal_nan_social_channel_scan_params scan_params_val; + /* 1 byte quantity which forces the Random Factor to a particular + * value for all transmitted Sync/Discovery beacons + */ + u8 config_random_factor_force; + u8 random_factor_force_val; + /* 1 byte quantity which forces the HC for all transmitted Sync and + * Discovery Beacon NO matter the real HC being received over the + * air. + */ + u8 config_hop_count_force; + u8 hop_count_force_val; + /* NAN Post Connectivity Capability */ + u8 config_conn_capability; + struct slsi_hal_nan_connectivity_capability conn_capability_val; + /* NAN Post Discover Capability */ + u8 num_config_discovery_attr; + struct slsi_hal_nan_post_discovery_param discovery_attr_val[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN]; + /* NAN Further availability Map */ + u8 config_fam; + struct slsi_hal_nan_further_availability_map fam_val; +}; + +struct slsi_hal_nan_capabilities { + u32 max_concurrent_nan_clusters; + u32 max_publishes; + u32 max_subscribes; + u32 max_service_name_len; + u32 max_match_filter_len; + u32 max_total_match_filter_len; + u32 max_service_specific_info_len; + u32 max_vsa_data_len; + u32 max_mesh_data_len; + u32 max_ndi_interfaces; + u32 max_ndp_sessions; + u32 max_app_info_len; +}; + +struct slsi_hal_nan_followup_ind { + u16 publish_subscribe_id; + u32 requestor_instance_id; + u8 addr[ETH_ALEN]; + u8 dw_or_faw; + u16 service_specific_info_len; + u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; +}; + +struct slsi_hal_nan_match_ind { + u16 publish_subscribe_id; + u32 requestor_instance_id; + u8 addr[ETH_ALEN]; + u16 service_specific_info_len; + u8 service_specific_info[SLSI_HAL_NAN_MAX_SERVICE_SPECIFIC_INFO_LEN]; + u16 sdf_match_filter_len; + u8 sdf_match_filter[SLSI_HAL_NAN_MAX_MATCH_FILTER_LEN]; + u8 match_occurred_flag; + u8 out_of_resource_flag; + u8 rssi_value; + u8 is_conn_capability_valid; + struct slsi_hal_nan_connectivity_capability conn_capability; + u8 num_rx_discovery_attr; + struct slsi_hal_nan_receive_post_discovery discovery_attr[SLSI_HAL_NAN_MAX_POSTDISCOVERY_LEN]; + u8 num_chans; + struct slsi_hal_nan_further_availability_channel famchan[32]; + u8 cluster_attribute_len; + u8 cluster_attribute[32]; +}; + +void slsi_nan_event(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); +void slsi_nan_followup_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); +void slsi_nan_service_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb); +void slsi_nan_get_mac(struct slsi_dev *sdev, char *nan_mac_addr); +struct net_device *slsi_nan_get_netdev(struct slsi_dev *sdev); +int slsi_nan_enable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); +int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); +int slsi_nan_publish(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); +int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int len); +int slsi_nan_subscribe(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); +int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); +int slsi_nan_transmit_followup(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); +int slsi_nan_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); +int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); +#endif diff --git a/drivers/net/wireless/scsc/procfs.c b/drivers/net/wireless/scsc/procfs.c index 6f0fb481ef13..3e29ac500f2e 100755 --- a/drivers/net/wireless/scsc/procfs.c +++ b/drivers/net/wireless/scsc/procfs.c @@ -399,6 +399,11 @@ static int slsi_procfs_build_show(struct seq_file *m, void *v) #ifdef CONFIG_SCSC_AP_INTERFACE_NAME seq_printf(m, "CONFIG_SCSC_AP_INTERFACE_NAME : %s\n", CONFIG_SCSC_AP_INTERFACE_NAME); #endif +#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE + seq_puts(m, "CONFIG_SCSC_WIFI_NAN_ENABLE : y\n"); +#else + seq_puts(m, "CONFIG_SCSC_WIFI_NAN_ENABLE : n\n"); +#endif return 0; } @@ -1050,10 +1055,15 @@ static ssize_t slsi_procfs_nan_mac_addr_read(struct file *file, char __user *use char buf[20]; char nan_mac[ETH_ALEN]; int pos = 0; +#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE struct slsi_dev *sdev = (struct slsi_dev *)file->private_data; - SLSI_UNUSED_PARAMETER(file); slsi_nan_get_mac(sdev, nan_mac); +#else + + SLSI_UNUSED_PARAMETER(file); + memset(nan_mac, 0, ETH_ALEN); +#endif pos = scnprintf(buf, sizeof(buf), "%pM", nan_mac); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } diff --git a/drivers/net/wireless/scsc/sap_mlme.c b/drivers/net/wireless/scsc/sap_mlme.c index 21584c2f9fdb..af4076fd621b 100755 --- a/drivers/net/wireless/scsc/sap_mlme.c +++ b/drivers/net/wireless/scsc/sap_mlme.c @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved + * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved * ****************************************************************************/ #include @@ -177,7 +177,7 @@ static int slsi_rx_netdev_mlme(struct slsi_dev *sdev, struct net_device *dev, st case MLME_EVENT_LOG_IND: slsi_rx_event_log_indication(sdev, dev, skb); break; -#ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE +#ifdef CONFIG_SCSC_WIFI_NAN_ENABLE case MLME_NAN_EVENT_IND: slsi_nan_event(sdev, dev, skb); slsi_kfree_skb(skb); -- 2.20.1