Path: blob/master/ALFA-W1F1/RTL8814AU/os_dep/linux/rtw_cfgvendor.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/1415#include <drv_types.h>1617#ifdef CONFIG_IOCTL_CFG802111819#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)2021/*22#include <linux/kernel.h>23#include <linux/if_arp.h>24#include <asm/uaccess.h>2526#include <linux/kernel.h>27#include <linux/kthread.h>28#include <linux/netdevice.h>29#include <linux/sched.h>30#include <linux/etherdevice.h>31#include <linux/wireless.h>32#include <linux/ieee80211.h>33#include <linux/wait.h>34#include <net/cfg80211.h>35*/3637#include <net/rtnetlink.h>3839#ifdef DBG_MEM_ALLOC40extern bool match_mstat_sniff_rules(const enum mstat_f flags, const size_t size);41struct sk_buff *dbg_rtw_cfg80211_vendor_event_alloc(struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp42, const enum mstat_f flags, const char *func, const int line)43{44struct sk_buff *skb;45unsigned int truesize = 0;4647#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))48skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);49#else50skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);51#endif5253if (skb)54truesize = skb->truesize;5556if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))57RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, len, skb, truesize);5859rtw_mstat_update(60flags61, skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL62, truesize63);6465return skb;66}6768void dbg_rtw_cfg80211_vendor_event(struct sk_buff *skb, gfp_t gfp69, const enum mstat_f flags, const char *func, const int line)70{71unsigned int truesize = skb->truesize;7273if (match_mstat_sniff_rules(flags, truesize))74RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);7576cfg80211_vendor_event(skb, gfp);7778rtw_mstat_update(79flags80, MSTAT_FREE81, truesize82);83}8485struct sk_buff *dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int len86, const enum mstat_f flags, const char *func, const int line)87{88struct sk_buff *skb;89unsigned int truesize = 0;9091skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);9293if (skb)94truesize = skb->truesize;9596if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))97RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, len, skb, truesize);9899rtw_mstat_update(100flags101, skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL102, truesize103);104105return skb;106}107108int dbg_rtw_cfg80211_vendor_cmd_reply(struct sk_buff *skb109, const enum mstat_f flags, const char *func, const int line)110{111unsigned int truesize = skb->truesize;112int ret;113114if (match_mstat_sniff_rules(flags, truesize))115RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);116117ret = cfg80211_vendor_cmd_reply(skb);118119rtw_mstat_update(120flags121, MSTAT_FREE122, truesize123);124125return ret;126}127128#define rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp) \129dbg_rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)130131#define rtw_cfg80211_vendor_event(skb, gfp) \132dbg_rtw_cfg80211_vendor_event(skb, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)133134#define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \135dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)136137#define rtw_cfg80211_vendor_cmd_reply(skb) \138dbg_rtw_cfg80211_vendor_cmd_reply(skb, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)139#else140141struct sk_buff *rtw_cfg80211_vendor_event_alloc(142struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp)143{144struct sk_buff *skb;145146#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))147skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);148#else149skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);150#endif151return skb;152}153154#define rtw_cfg80211_vendor_event(skb, gfp) \155cfg80211_vendor_event(skb, gfp)156157#define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \158cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len)159160#define rtw_cfg80211_vendor_cmd_reply(skb) \161cfg80211_vendor_cmd_reply(skb)162#endif /* DBG_MEM_ALLOC */163164/*165* This API is to be used for asynchronous vendor events. This166* shouldn't be used in response to a vendor command from its167* do_it handler context (instead rtw_cfgvendor_send_cmd_reply should168* be used).169*/170int rtw_cfgvendor_send_async_event(struct wiphy *wiphy,171struct net_device *dev, int event_id, const void *data, int len)172{173u16 kflags;174struct sk_buff *skb;175176kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;177178/* Alloc the SKB for vendor_event */179skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), len, event_id, kflags);180if (!skb) {181RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));182return -ENOMEM;183}184185/* Push the data to the skb */186nla_put_nohdr(skb, len, data);187188rtw_cfg80211_vendor_event(skb, kflags);189190return 0;191}192193static int rtw_cfgvendor_send_cmd_reply(struct wiphy *wiphy,194struct net_device *dev, const void *data, int len)195{196struct sk_buff *skb;197198/* Alloc the SKB for vendor_event */199skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);200if (unlikely(!skb)) {201RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));202return -ENOMEM;203}204205/* Push the data to the skb */206nla_put_nohdr(skb, len, data);207208return rtw_cfg80211_vendor_cmd_reply(skb);209}210211/* Feature enums */212#define WIFI_FEATURE_INFRA 0x0001 // Basic infrastructure mode213#define WIFI_FEATURE_INFRA_5G 0x0002 // Support for 5 GHz Band214#define WIFI_FEATURE_HOTSPOT 0x0004 // Support for GAS/ANQP215#define WIFI_FEATURE_P2P 0x0008 // Wifi-Direct216#define WIFI_FEATURE_SOFT_AP 0x0010 // Soft AP217#define WIFI_FEATURE_GSCAN 0x0020 // Google-Scan APIs218#define WIFI_FEATURE_NAN 0x0040 // Neighbor Awareness Networking219#define WIFI_FEATURE_D2D_RTT 0x0080 // Device-to-device RTT220#define WIFI_FEATURE_D2AP_RTT 0x0100 // Device-to-AP RTT221#define WIFI_FEATURE_BATCH_SCAN 0x0200 // Batched Scan (legacy)222#define WIFI_FEATURE_PNO 0x0400 // Preferred network offload223#define WIFI_FEATURE_ADDITIONAL_STA 0x0800 // Support for two STAs224#define WIFI_FEATURE_TDLS 0x1000 // Tunnel directed link setup225#define WIFI_FEATURE_TDLS_OFFCHANNEL 0x2000 // Support for TDLS off channel226#define WIFI_FEATURE_EPR 0x4000 // Enhanced power reporting227#define WIFI_FEATURE_AP_STA 0x8000 // Support for AP STA Concurrency228#define WIFI_FEATURE_LINK_LAYER_STATS 0x10000 // Link layer stats collection229#define WIFI_FEATURE_LOGGER 0x20000 // WiFi Logger230#define WIFI_FEATURE_HAL_EPNO 0x40000 // WiFi PNO enhanced231#define WIFI_FEATURE_RSSI_MONITOR 0x80000 // RSSI Monitor232#define WIFI_FEATURE_MKEEP_ALIVE 0x100000 // WiFi mkeep_alive233#define WIFI_FEATURE_CONFIG_NDO 0x200000 // ND offload configure234#define WIFI_FEATURE_TX_TRANSMIT_POWER 0x400000 // Capture Tx transmit power levels235#define WIFI_FEATURE_CONTROL_ROAMING 0x800000 // Enable/Disable firmware roaming236#define WIFI_FEATURE_IE_WHITELIST 0x1000000 // Support Probe IE white listing237#define WIFI_FEATURE_SCAN_RAND 0x2000000 // Support MAC & Probe Sequence Number randomization238// Add more features here239240#define MAX_FEATURE_SET_CONCURRRENT_GROUPS 3241242#include <hal_data.h>243int rtw_dev_get_feature_set(struct net_device *dev)244{245_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);246HAL_DATA_TYPE *HalData = GET_HAL_DATA(adapter);247int feature_set = 0;248249feature_set |= WIFI_FEATURE_INFRA;250251#ifdef CONFIG_IEEE80211_BAND_5GHZ252if (is_supported_5g(adapter_to_regsty(adapter)->wireless_mode))253feature_set |= WIFI_FEATURE_INFRA_5G;254#endif255256feature_set |= WIFI_FEATURE_P2P;257feature_set |= WIFI_FEATURE_SOFT_AP;258259feature_set |= WIFI_FEATURE_ADDITIONAL_STA;260#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS261feature_set |= WIFI_FEATURE_LINK_LAYER_STATS;262#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */263264#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR265feature_set |= WIFI_FEATURE_RSSI_MONITOR;266#endif267268#ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER269feature_set |= WIFI_FEATURE_LOGGER;270#endif271272#ifdef CONFIG_RTW_WIFI_HAL273feature_set |= WIFI_FEATURE_CONFIG_NDO;274feature_set |= WIFI_FEATURE_SCAN_RAND;275#endif276277return feature_set;278}279280int *rtw_dev_get_feature_set_matrix(struct net_device *dev, int *num)281{282int feature_set_full, mem_needed;283int *ret;284285*num = 0;286mem_needed = sizeof(int) * MAX_FEATURE_SET_CONCURRRENT_GROUPS;287ret = (int *)rtw_malloc(mem_needed);288289if (!ret) {290RTW_ERR(FUNC_NDEV_FMT" failed to allocate %d bytes\n"291, FUNC_NDEV_ARG(dev), mem_needed);292return ret;293}294295feature_set_full = rtw_dev_get_feature_set(dev);296297ret[0] = (feature_set_full & WIFI_FEATURE_INFRA) |298(feature_set_full & WIFI_FEATURE_INFRA_5G) |299(feature_set_full & WIFI_FEATURE_NAN) |300(feature_set_full & WIFI_FEATURE_D2D_RTT) |301(feature_set_full & WIFI_FEATURE_D2AP_RTT) |302(feature_set_full & WIFI_FEATURE_PNO) |303(feature_set_full & WIFI_FEATURE_BATCH_SCAN) |304(feature_set_full & WIFI_FEATURE_GSCAN) |305(feature_set_full & WIFI_FEATURE_HOTSPOT) |306(feature_set_full & WIFI_FEATURE_ADDITIONAL_STA) |307(feature_set_full & WIFI_FEATURE_EPR);308309ret[1] = (feature_set_full & WIFI_FEATURE_INFRA) |310(feature_set_full & WIFI_FEATURE_INFRA_5G) |311/* Not yet verified NAN with P2P */312/* (feature_set_full & WIFI_FEATURE_NAN) | */313(feature_set_full & WIFI_FEATURE_P2P) |314(feature_set_full & WIFI_FEATURE_D2AP_RTT) |315(feature_set_full & WIFI_FEATURE_D2D_RTT) |316(feature_set_full & WIFI_FEATURE_EPR);317318ret[2] = (feature_set_full & WIFI_FEATURE_INFRA) |319(feature_set_full & WIFI_FEATURE_INFRA_5G) |320(feature_set_full & WIFI_FEATURE_NAN) |321(feature_set_full & WIFI_FEATURE_D2D_RTT) |322(feature_set_full & WIFI_FEATURE_D2AP_RTT) |323(feature_set_full & WIFI_FEATURE_TDLS) |324(feature_set_full & WIFI_FEATURE_TDLS_OFFCHANNEL) |325(feature_set_full & WIFI_FEATURE_EPR);326*num = MAX_FEATURE_SET_CONCURRRENT_GROUPS;327328return ret;329}330331static int rtw_cfgvendor_get_feature_set(struct wiphy *wiphy,332struct wireless_dev *wdev, const void *data, int len)333{334int err = 0;335int reply;336337reply = rtw_dev_get_feature_set(wdev_to_ndev(wdev));338339err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), &reply, sizeof(int));340341if (unlikely(err))342RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"343, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);344345return err;346}347348static int rtw_cfgvendor_get_feature_set_matrix(struct wiphy *wiphy,349struct wireless_dev *wdev, const void *data, int len)350{351int err = 0;352struct sk_buff *skb;353int *reply;354int num, mem_needed, i;355356reply = rtw_dev_get_feature_set_matrix(wdev_to_ndev(wdev), &num);357358if (!reply) {359RTW_ERR(FUNC_NDEV_FMT" Could not get feature list matrix\n"360, FUNC_NDEV_ARG(wdev_to_ndev(wdev)));361err = -EINVAL;362return err;363}364365mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * num) +366ATTRIBUTE_U32_LEN;367368/* Alloc the SKB for vendor_event */369skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);370if (unlikely(!skb)) {371RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(wdev_to_ndev(wdev)));372err = -ENOMEM;373goto exit;374}375376nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, num);377for (i = 0; i < num; i++)378nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, reply[i]);379380err = rtw_cfg80211_vendor_cmd_reply(skb);381382if (unlikely(err))383RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"384, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);385exit:386rtw_mfree((u8 *)reply, sizeof(int) * num);387return err;388}389390#if defined(GSCAN_SUPPORT) && 0391int rtw_cfgvendor_send_hotlist_event(struct wiphy *wiphy,392struct net_device *dev, void *data, int len, rtw_vendor_event_t event)393{394u16 kflags;395const void *ptr;396struct sk_buff *skb;397int malloc_len, total, iter_cnt_to_send, cnt;398gscan_results_cache_t *cache = (gscan_results_cache_t *)data;399400total = len / sizeof(wifi_gscan_result_t);401while (total > 0) {402malloc_len = (total * sizeof(wifi_gscan_result_t)) + VENDOR_DATA_OVERHEAD;403if (malloc_len > NLMSG_DEFAULT_SIZE)404malloc_len = NLMSG_DEFAULT_SIZE;405iter_cnt_to_send =406(malloc_len - VENDOR_DATA_OVERHEAD) / sizeof(wifi_gscan_result_t);407total = total - iter_cnt_to_send;408409kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;410411/* Alloc the SKB for vendor_event */412skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), malloc_len, event, kflags);413if (!skb) {414WL_ERR(("skb alloc failed"));415return -ENOMEM;416}417418while (cache && iter_cnt_to_send) {419ptr = (const void *) &cache->results[cache->tot_consumed];420421if (iter_cnt_to_send < (cache->tot_count - cache->tot_consumed))422cnt = iter_cnt_to_send;423else424cnt = (cache->tot_count - cache->tot_consumed);425426iter_cnt_to_send -= cnt;427cache->tot_consumed += cnt;428/* Push the data to the skb */429nla_append(skb, cnt * sizeof(wifi_gscan_result_t), ptr);430if (cache->tot_consumed == cache->tot_count)431cache = cache->next;432433}434435rtw_cfg80211_vendor_event(skb, kflags);436}437438return 0;439}440441442static int rtw_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,443struct wireless_dev *wdev, const void *data, int len)444{445int err = 0;446struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);447dhd_pno_gscan_capabilities_t *reply = NULL;448uint32 reply_len = 0;449450451reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),452DHD_PNO_GET_CAPABILITIES, NULL, &reply_len);453if (!reply) {454WL_ERR(("Could not get capabilities\n"));455err = -EINVAL;456return err;457}458459err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),460reply, reply_len);461462if (unlikely(err))463WL_ERR(("Vendor Command reply failed ret:%d\n", err));464465kfree(reply);466return err;467}468469static int rtw_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,470struct wireless_dev *wdev, const void *data, int len)471{472int err = 0, type, band;473struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);474uint16 *reply = NULL;475uint32 reply_len = 0, num_channels, mem_needed;476struct sk_buff *skb;477478type = nla_type(data);479480if (type == GSCAN_ATTRIBUTE_BAND)481band = nla_get_u32(data);482else483return -1;484485reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),486DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);487488if (!reply) {489WL_ERR(("Could not get channel list\n"));490err = -EINVAL;491return err;492}493num_channels = reply_len / sizeof(uint32);494mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);495496/* Alloc the SKB for vendor_event */497skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);498if (unlikely(!skb)) {499WL_ERR(("skb alloc failed"));500err = -ENOMEM;501goto exit;502}503504nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);505nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);506507err = rtw_cfg80211_vendor_cmd_reply(skb);508509if (unlikely(err))510WL_ERR(("Vendor Command reply failed ret:%d\n", err));511exit:512kfree(reply);513return err;514}515516static int rtw_cfgvendor_gscan_get_batch_results(struct wiphy *wiphy,517struct wireless_dev *wdev, const void *data, int len)518{519int err = 0;520struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);521gscan_results_cache_t *results, *iter;522uint32 reply_len, complete = 0, num_results_iter;523int32 mem_needed;524wifi_gscan_result_t *ptr;525uint16 num_scan_ids, num_results;526struct sk_buff *skb;527struct nlattr *scan_hdr;528529dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg));530dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));531results = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),532DHD_PNO_GET_BATCH_RESULTS, NULL, &reply_len);533534if (!results) {535WL_ERR(("No results to send %d\n", err));536err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),537results, 0);538539if (unlikely(err))540WL_ERR(("Vendor Command reply failed ret:%d\n", err));541dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));542return err;543}544num_scan_ids = reply_len & 0xFFFF;545num_results = (reply_len & 0xFFFF0000) >> 16;546mem_needed = (num_results * sizeof(wifi_gscan_result_t)) +547(num_scan_ids * GSCAN_BATCH_RESULT_HDR_LEN) +548VENDOR_REPLY_OVERHEAD + SCAN_RESULTS_COMPLETE_FLAG_LEN;549550if (mem_needed > (int32)NLMSG_DEFAULT_SIZE) {551mem_needed = (int32)NLMSG_DEFAULT_SIZE;552complete = 0;553} else554complete = 1;555556WL_TRACE(("complete %d mem_needed %d max_mem %d\n", complete, mem_needed,557(int)NLMSG_DEFAULT_SIZE));558/* Alloc the SKB for vendor_event */559skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);560if (unlikely(!skb)) {561WL_ERR(("skb alloc failed"));562dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));563return -ENOMEM;564}565iter = results;566567nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, complete);568569mem_needed = mem_needed - (SCAN_RESULTS_COMPLETE_FLAG_LEN + VENDOR_REPLY_OVERHEAD);570571while (iter && ((mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) > 0)) {572scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS);573nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id);574nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag);575num_results_iter =576(mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) / sizeof(wifi_gscan_result_t);577578if ((iter->tot_count - iter->tot_consumed) < num_results_iter)579num_results_iter = iter->tot_count - iter->tot_consumed;580581nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter);582if (num_results_iter) {583ptr = &iter->results[iter->tot_consumed];584iter->tot_consumed += num_results_iter;585nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS,586num_results_iter * sizeof(wifi_gscan_result_t), ptr);587}588nla_nest_end(skb, scan_hdr);589mem_needed -= GSCAN_BATCH_RESULT_HDR_LEN +590(num_results_iter * sizeof(wifi_gscan_result_t));591iter = iter->next;592}593594dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));595dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));596597return rtw_cfg80211_vendor_cmd_reply(skb);598}599600static int rtw_cfgvendor_initiate_gscan(struct wiphy *wiphy,601struct wireless_dev *wdev, const void *data, int len)602{603int err = 0;604struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);605int type, tmp = len;606int run = 0xFF;607int flush = 0;608const struct nlattr *iter;609610nla_for_each_attr(iter, data, len, tmp) {611type = nla_type(iter);612if (type == GSCAN_ATTRIBUTE_ENABLE_FEATURE)613run = nla_get_u32(iter);614else if (type == GSCAN_ATTRIBUTE_FLUSH_FEATURE)615flush = nla_get_u32(iter);616}617618if (run != 0xFF) {619err = dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg), run, flush);620621if (unlikely(err))622WL_ERR(("Could not run gscan:%d\n", err));623return err;624} else625return -1;626627628}629630static int rtw_cfgvendor_enable_full_scan_result(struct wiphy *wiphy,631struct wireless_dev *wdev, const void *data, int len)632{633int err = 0;634struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);635int type;636bool real_time = FALSE;637638type = nla_type(data);639640if (type == GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS) {641real_time = nla_get_u32(data);642643err = dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg), real_time);644645if (unlikely(err))646WL_ERR(("Could not run gscan:%d\n", err));647648} else649err = -1;650651return err;652}653654static int rtw_cfgvendor_set_scan_cfg(struct wiphy *wiphy,655struct wireless_dev *wdev, const void *data, int len)656{657int err = 0;658struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);659gscan_scan_params_t *scan_param;660int j = 0;661int type, tmp, tmp1, tmp2, k = 0;662const struct nlattr *iter, *iter1, *iter2;663struct dhd_pno_gscan_channel_bucket *ch_bucket;664665scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL);666if (!scan_param) {667WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));668err = -EINVAL;669return err;670671}672673scan_param->scan_fr = PNO_SCAN_MIN_FW_SEC;674nla_for_each_attr(iter, data, len, tmp) {675type = nla_type(iter);676677if (j >= GSCAN_MAX_CH_BUCKETS)678break;679680switch (type) {681case GSCAN_ATTRIBUTE_BASE_PERIOD:682scan_param->scan_fr = nla_get_u32(iter) / 1000;683break;684case GSCAN_ATTRIBUTE_NUM_BUCKETS:685scan_param->nchannel_buckets = nla_get_u32(iter);686break;687case GSCAN_ATTRIBUTE_CH_BUCKET_1:688case GSCAN_ATTRIBUTE_CH_BUCKET_2:689case GSCAN_ATTRIBUTE_CH_BUCKET_3:690case GSCAN_ATTRIBUTE_CH_BUCKET_4:691case GSCAN_ATTRIBUTE_CH_BUCKET_5:692case GSCAN_ATTRIBUTE_CH_BUCKET_6:693case GSCAN_ATTRIBUTE_CH_BUCKET_7:694nla_for_each_nested(iter1, iter, tmp1) {695type = nla_type(iter1);696ch_bucket =697scan_param->channel_bucket;698699switch (type) {700case GSCAN_ATTRIBUTE_BUCKET_ID:701break;702case GSCAN_ATTRIBUTE_BUCKET_PERIOD:703ch_bucket[j].bucket_freq_multiple =704nla_get_u32(iter1) / 1000;705break;706case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:707ch_bucket[j].num_channels =708nla_get_u32(iter1);709break;710case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:711nla_for_each_nested(iter2, iter1, tmp2) {712if (k >= PFN_SWC_RSSI_WINDOW_MAX)713break;714ch_bucket[j].chan_list[k] =715nla_get_u32(iter2);716k++;717}718k = 0;719break;720case GSCAN_ATTRIBUTE_BUCKETS_BAND:721ch_bucket[j].band = (uint16)722nla_get_u32(iter1);723break;724case GSCAN_ATTRIBUTE_REPORT_EVENTS:725ch_bucket[j].report_flag = (uint8)726nla_get_u32(iter1);727break;728}729}730j++;731break;732}733}734735if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),736DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) {737WL_ERR(("Could not set GSCAN scan cfg\n"));738err = -EINVAL;739}740741kfree(scan_param);742return err;743744}745746static int rtw_cfgvendor_hotlist_cfg(struct wiphy *wiphy,747struct wireless_dev *wdev, const void *data, int len)748{749int err = 0;750struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);751gscan_hotlist_scan_params_t *hotlist_params;752int tmp, tmp1, tmp2, type, j = 0, dummy;753const struct nlattr *outer, *inner, *iter;754uint8 flush = 0;755struct bssid_t *pbssid;756757hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);758if (!hotlist_params) {759WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));760return -1;761}762763hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;764765nla_for_each_attr(iter, data, len, tmp2) {766type = nla_type(iter);767switch (type) {768case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:769pbssid = hotlist_params->bssid;770nla_for_each_nested(outer, iter, tmp) {771nla_for_each_nested(inner, outer, tmp1) {772type = nla_type(inner);773774switch (type) {775case GSCAN_ATTRIBUTE_BSSID:776memcpy(&(pbssid[j].macaddr),777nla_data(inner), ETHER_ADDR_LEN);778break;779case GSCAN_ATTRIBUTE_RSSI_LOW:780pbssid[j].rssi_reporting_threshold =781(int8) nla_get_u8(inner);782break;783case GSCAN_ATTRIBUTE_RSSI_HIGH:784dummy = (int8) nla_get_u8(inner);785break;786}787}788j++;789}790hotlist_params->nbssid = j;791break;792case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:793flush = nla_get_u8(iter);794break;795case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:796hotlist_params->lost_ap_window = nla_get_u32(iter);797break;798}799800}801802if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),803DHD_PNO_GEOFENCE_SCAN_CFG_ID, hotlist_params, flush) < 0) {804WL_ERR(("Could not set GSCAN HOTLIST cfg\n"));805err = -EINVAL;806goto exit;807}808exit:809kfree(hotlist_params);810return err;811}812static int rtw_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy,813struct wireless_dev *wdev, const void *data, int len)814{815int err = 0, tmp, type;816struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);817gscan_batch_params_t batch_param;818const struct nlattr *iter;819820batch_param.mscan = batch_param.bestn = 0;821batch_param.buffer_threshold = GSCAN_BATCH_NO_THR_SET;822823nla_for_each_attr(iter, data, len, tmp) {824type = nla_type(iter);825826switch (type) {827case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN:828batch_param.bestn = nla_get_u32(iter);829break;830case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE:831batch_param.mscan = nla_get_u32(iter);832break;833case GSCAN_ATTRIBUTE_REPORT_THRESHOLD:834batch_param.buffer_threshold = nla_get_u32(iter);835break;836}837}838839if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),840DHD_PNO_BATCH_SCAN_CFG_ID, &batch_param, 0) < 0) {841WL_ERR(("Could not set batch cfg\n"));842err = -EINVAL;843return err;844}845846return err;847}848849static int rtw_cfgvendor_significant_change_cfg(struct wiphy *wiphy,850struct wireless_dev *wdev, const void *data, int len)851{852int err = 0;853struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);854gscan_swc_params_t *significant_params;855int tmp, tmp1, tmp2, type, j = 0;856const struct nlattr *outer, *inner, *iter;857uint8 flush = 0;858wl_pfn_significant_bssid_t *pbssid;859860significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL);861if (!significant_params) {862WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));863return -1;864}865866867nla_for_each_attr(iter, data, len, tmp2) {868type = nla_type(iter);869870switch (type) {871case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:872flush = nla_get_u8(iter);873break;874case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:875significant_params->rssi_window = nla_get_u16(iter);876break;877case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:878significant_params->lost_ap_window = nla_get_u16(iter);879break;880case GSCAN_ATTRIBUTE_MIN_BREACHING:881significant_params->swc_threshold = nla_get_u16(iter);882break;883case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS:884pbssid = significant_params->bssid_elem_list;885nla_for_each_nested(outer, iter, tmp) {886nla_for_each_nested(inner, outer, tmp1) {887switch (nla_type(inner)) {888case GSCAN_ATTRIBUTE_BSSID:889memcpy(&(pbssid[j].macaddr),890nla_data(inner),891ETHER_ADDR_LEN);892break;893case GSCAN_ATTRIBUTE_RSSI_HIGH:894pbssid[j].rssi_high_threshold =895(int8) nla_get_u8(inner);896break;897case GSCAN_ATTRIBUTE_RSSI_LOW:898pbssid[j].rssi_low_threshold =899(int8) nla_get_u8(inner);900break;901}902}903j++;904}905break;906}907}908significant_params->nbssid = j;909910if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),911DHD_PNO_SIGNIFICANT_SCAN_CFG_ID, significant_params, flush) < 0) {912WL_ERR(("Could not set GSCAN significant cfg\n"));913err = -EINVAL;914goto exit;915}916exit:917kfree(significant_params);918return err;919}920#endif /* GSCAN_SUPPORT */921922#if defined(RTT_SUPPORT) && 0923void rtw_cfgvendor_rtt_evt(void *ctx, void *rtt_data)924{925struct wireless_dev *wdev = (struct wireless_dev *)ctx;926struct wiphy *wiphy;927struct sk_buff *skb;928uint32 tot_len = NLMSG_DEFAULT_SIZE, entry_len = 0;929gfp_t kflags;930rtt_report_t *rtt_report = NULL;931rtt_result_t *rtt_result = NULL;932struct list_head *rtt_list;933wiphy = wdev->wiphy;934935WL_DBG(("In\n"));936/* Push the data to the skb */937if (!rtt_data) {938WL_ERR(("rtt_data is NULL\n"));939goto exit;940}941rtt_list = (struct list_head *)rtt_data;942kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;943/* Alloc the SKB for vendor_event */944skb = rtw_cfg80211_vendor_event_alloc(wiphy, wdev, tot_len, GOOGLE_RTT_COMPLETE_EVENT, kflags);945if (!skb) {946WL_ERR(("skb alloc failed"));947goto exit;948}949/* fill in the rtt results on each entry */950list_for_each_entry(rtt_result, rtt_list, list) {951entry_len = 0;952if (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) {953entry_len = sizeof(rtt_report_t);954rtt_report = kzalloc(entry_len, kflags);955if (!rtt_report) {956WL_ERR(("rtt_report alloc failed"));957goto exit;958}959rtt_report->addr = rtt_result->peer_mac;960rtt_report->num_measurement = 1; /* ONE SHOT */961rtt_report->status = rtt_result->err_code;962rtt_report->type = (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) ? RTT_ONE_WAY : RTT_TWO_WAY;963rtt_report->peer = rtt_result->target_info->peer;964rtt_report->channel = rtt_result->target_info->channel;965rtt_report->rssi = rtt_result->avg_rssi;966/* tx_rate */967rtt_report->tx_rate = rtt_result->tx_rate;968/* RTT */969rtt_report->rtt = rtt_result->meanrtt;970rtt_report->rtt_sd = rtt_result->sdrtt;971/* convert to centi meter */972if (rtt_result->distance != 0xffffffff)973rtt_report->distance = (rtt_result->distance >> 2) * 25;974else /* invalid distance */975rtt_report->distance = -1;976977rtt_report->ts = rtt_result->ts;978nla_append(skb, entry_len, rtt_report);979kfree(rtt_report);980}981}982rtw_cfg80211_vendor_event(skb, kflags);983exit:984return;985}986987static int rtw_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev,988const void *data, int len)989{990int err = 0, rem, rem1, rem2, type;991rtt_config_params_t rtt_param;992rtt_target_info_t *rtt_target = NULL;993const struct nlattr *iter, *iter1, *iter2;994int8 eabuf[ETHER_ADDR_STR_LEN];995int8 chanbuf[CHANSPEC_STR_LEN];996struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);997998WL_DBG(("In\n"));999err = dhd_dev_rtt_register_noti_callback(wdev->netdev, wdev, wl_cfgvendor_rtt_evt);1000if (err < 0) {1001WL_ERR(("failed to register rtt_noti_callback\n"));1002goto exit;1003}1004memset(&rtt_param, 0, sizeof(rtt_param));1005nla_for_each_attr(iter, data, len, rem) {1006type = nla_type(iter);1007switch (type) {1008case RTT_ATTRIBUTE_TARGET_CNT:1009rtt_param.rtt_target_cnt = nla_get_u8(iter);1010if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) {1011WL_ERR(("exceed max target count : %d\n",1012rtt_param.rtt_target_cnt));1013err = BCME_RANGE;1014}1015break;1016case RTT_ATTRIBUTE_TARGET_INFO:1017rtt_target = rtt_param.target_info;1018nla_for_each_nested(iter1, iter, rem1) {1019nla_for_each_nested(iter2, iter1, rem2) {1020type = nla_type(iter2);1021switch (type) {1022case RTT_ATTRIBUTE_TARGET_MAC:1023memcpy(&rtt_target->addr, nla_data(iter2), ETHER_ADDR_LEN);1024break;1025case RTT_ATTRIBUTE_TARGET_TYPE:1026rtt_target->type = nla_get_u8(iter2);1027break;1028case RTT_ATTRIBUTE_TARGET_PEER:1029rtt_target->peer = nla_get_u8(iter2);1030break;1031case RTT_ATTRIBUTE_TARGET_CHAN:1032memcpy(&rtt_target->channel, nla_data(iter2),1033sizeof(rtt_target->channel));1034break;1035case RTT_ATTRIBUTE_TARGET_MODE:1036rtt_target->continuous = nla_get_u8(iter2);1037break;1038case RTT_ATTRIBUTE_TARGET_INTERVAL:1039rtt_target->interval = nla_get_u32(iter2);1040break;1041case RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT:1042rtt_target->measure_cnt = nla_get_u32(iter2);1043break;1044case RTT_ATTRIBUTE_TARGET_NUM_PKT:1045rtt_target->ftm_cnt = nla_get_u32(iter2);1046break;1047case RTT_ATTRIBUTE_TARGET_NUM_RETRY:1048rtt_target->retry_cnt = nla_get_u32(iter2);1049}1050}1051/* convert to chanspec value */1052rtt_target->chanspec = dhd_rtt_convert_to_chspec(rtt_target->channel);1053if (rtt_target->chanspec == 0) {1054WL_ERR(("Channel is not valid\n"));1055goto exit;1056}1057WL_INFORM(("Target addr %s, Channel : %s for RTT\n",1058bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr, eabuf),1059wf_chspec_ntoa(rtt_target->chanspec, chanbuf)));1060rtt_target++;1061}1062break;1063}1064}1065WL_DBG(("leave :target_cnt : %d\n", rtt_param.rtt_target_cnt));1066if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg), &rtt_param) < 0) {1067WL_ERR(("Could not set RTT configuration\n"));1068err = -EINVAL;1069}1070exit:1071return err;1072}10731074static int rtw_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev,1075const void *data, int len)1076{1077int err = 0, rem, type, target_cnt = 0;1078const struct nlattr *iter;1079struct ether_addr *mac_list = NULL, *mac_addr = NULL;1080struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);10811082nla_for_each_attr(iter, data, len, rem) {1083type = nla_type(iter);1084switch (type) {1085case RTT_ATTRIBUTE_TARGET_CNT:1086target_cnt = nla_get_u8(iter);1087mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN , GFP_KERNEL);1088if (mac_list == NULL) {1089WL_ERR(("failed to allocate mem for mac list\n"));1090goto exit;1091}1092mac_addr = &mac_list[0];1093break;1094case RTT_ATTRIBUTE_TARGET_MAC:1095if (mac_addr)1096memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN);1097else {1098WL_ERR(("mac_list is NULL\n"));1099goto exit;1100}1101break;1102}1103if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg), mac_list, target_cnt) < 0) {1104WL_ERR(("Could not cancel RTT configuration\n"));1105err = -EINVAL;1106goto exit;1107}1108}1109exit:1110if (mac_list)1111kfree(mac_list);1112return err;1113}1114static int rtw_cfgvendor_rtt_get_capability(struct wiphy *wiphy, struct wireless_dev *wdev,1115const void *data, int len)1116{1117int err = 0;1118struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);1119rtt_capabilities_t capability;11201121err = dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg), &capability);1122if (unlikely(err)) {1123WL_ERR(("Vendor Command reply failed ret:%d\n", err));1124goto exit;1125}1126err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),1127&capability, sizeof(capability));11281129if (unlikely(err))1130WL_ERR(("Vendor Command reply failed ret:%d\n", err));1131exit:1132return err;1133}11341135#endif /* RTT_SUPPORT */11361137#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS1138enum {1139LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,1140LSTATS_SUBCMD_SET_INFO,1141LSTATS_SUBCMD_CLEAR_INFO,1142};1143static void LinkLayerStats(_adapter *padapter)1144{1145struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1146struct recv_priv *precvpriv = &(padapter->recvpriv);1147struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);1148struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);1149u32 ps_time, trx_total_time;1150u64 tx_bytes, rx_bytes, trx_total_bytes = 0;1151u64 tmp = 0;11521153RTW_DBG("%s adapter type : %u\n", __func__, padapter->adapter_type);11541155tx_bytes = 0;1156rx_bytes = 0;1157ps_time = 0;1158trx_total_time = 0;11591160if ( padapter->netif_up == _TRUE ) {11611162pwrpriv->on_time = rtw_get_passing_time_ms(pwrpriv->radio_on_start_time);11631164if (rtw_mi_check_fwstate(padapter, _FW_LINKED)) {1165if ( pwrpriv->bpower_saving == _TRUE ) {1166pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);1167pwrpriv->pwr_saving_start_time = rtw_get_current_time();1168}1169} else {1170#ifdef CONFIG_IPS1171if ( pwrpriv->bpower_saving == _TRUE ) {1172pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);1173pwrpriv->pwr_saving_start_time = rtw_get_current_time();1174}1175#else1176pwrpriv->pwr_saving_time = pwrpriv->on_time;1177#endif1178}11791180ps_time = pwrpriv->pwr_saving_time;11811182/* Deviation caused by caculation start time */1183if ( ps_time > pwrpriv->on_time )1184ps_time = pwrpriv->on_time;11851186tx_bytes = pdvobjpriv->traffic_stat.last_tx_bytes;1187rx_bytes = pdvobjpriv->traffic_stat.last_rx_bytes;1188trx_total_bytes = tx_bytes + rx_bytes;11891190trx_total_time = pwrpriv->on_time - ps_time;11911192if ( trx_total_bytes == 0) {1193pwrpriv->tx_time = 0;1194pwrpriv->rx_time = 0;1195} else {11961197/* tx_time = (trx_total_time * tx_total_bytes) / trx_total_bytes; */1198/* rx_time = (trx_total_time * rx_total_bytes) / trx_total_bytes; */11991200tmp = (tx_bytes * trx_total_time);1201tmp = rtw_division64(tmp, trx_total_bytes);1202pwrpriv->tx_time = tmp;12031204tmp = (rx_bytes * trx_total_time);1205tmp = rtw_division64(tmp, trx_total_bytes);1206pwrpriv->rx_time = tmp;12071208}12091210}1211else {1212pwrpriv->on_time = 0;1213pwrpriv->tx_time = 0;1214pwrpriv->rx_time = 0;1215}12161217#ifdef CONFIG_RTW_WIFI_HAL_DEBUG1218RTW_INFO("- tx_bytes : %llu rx_bytes : %llu total bytes : %llu\n", tx_bytes, rx_bytes, trx_total_bytes);1219RTW_INFO("- netif_up = %s, on_time : %u ms\n", padapter->netif_up ? "1":"0", pwrpriv->on_time);1220RTW_INFO("- pwr_saving_time : %u (%u) ms\n", pwrpriv->pwr_saving_time, ps_time);1221RTW_INFO("- trx_total_time : %u ms\n", trx_total_time);1222RTW_INFO("- tx_time : %u ms\n", pwrpriv->tx_time);1223RTW_INFO("- rx_time : %u ms\n", pwrpriv->rx_time);1224#endif /* CONFIG_RTW_WIFI_HAL_DEBUG */12251226}12271228#define DUMMY_TIME_STATICS 991229static int rtw_cfgvendor_lstats_get_info(struct wiphy *wiphy,1230struct wireless_dev *wdev, const void *data, int len)1231{1232int err = 0;1233_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));1234struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);1235wifi_radio_stat_internal *radio;1236wifi_iface_stat *iface;1237char *output;12381239output = rtw_malloc(sizeof(wifi_radio_stat_internal) + sizeof(wifi_iface_stat));1240if (output == NULL) {1241RTW_DBG("Allocate lstats info buffer fail!\n");1242}12431244radio = (wifi_radio_stat_internal *)output;12451246radio->num_channels = 0;1247radio->radio = 1;12481249/* to get on_time, tx_time, rx_time */1250LinkLayerStats(padapter);12511252radio->on_time = pwrpriv->on_time;1253radio->tx_time = pwrpriv->tx_time;1254radio->rx_time = pwrpriv->rx_time;1255radio->on_time_scan = 0;1256radio->on_time_nbd = 0;1257radio->on_time_gscan = 0;1258radio->on_time_pno_scan = 0;1259radio->on_time_hs20 = 0;1260#ifdef CONFIG_RTW_WIFI_HAL_DEBUG1261RTW_INFO("==== %s ====\n", __func__);1262RTW_INFO("radio->radio : %d\n", (radio->radio));1263RTW_INFO("pwrpriv->on_time : %u ms\n", (pwrpriv->on_time));1264RTW_INFO("pwrpriv->tx_time : %u ms\n", (pwrpriv->tx_time));1265RTW_INFO("pwrpriv->rx_time : %u ms\n", (pwrpriv->rx_time));1266RTW_INFO("radio->on_time : %u ms\n", (radio->on_time));1267RTW_INFO("radio->tx_time : %u ms\n", (radio->tx_time));1268RTW_INFO("radio->rx_time : %u ms\n", (radio->rx_time));1269#endif /* CONFIG_RTW_WIFI_HAL_DEBUG */12701271RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);1272err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev),1273output, sizeof(wifi_iface_stat) + sizeof(wifi_radio_stat_internal));1274if (unlikely(err))1275RTW_ERR(FUNC_NDEV_FMT"Vendor Command reply failed ret:%d \n"1276, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);1277rtw_mfree(output, sizeof(wifi_iface_stat) + sizeof(wifi_radio_stat_internal));1278return err;1279}1280static int rtw_cfgvendor_lstats_set_info(struct wiphy *wiphy,1281struct wireless_dev *wdev, const void *data, int len)1282{1283int err = 0;1284RTW_INFO("%s\n", __func__);1285return err;1286}1287static int rtw_cfgvendor_lstats_clear_info(struct wiphy *wiphy,1288struct wireless_dev *wdev, const void *data, int len)1289{1290int err = 0;1291RTW_INFO("%s\n", __func__);1292return err;1293}1294#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */1295#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR1296static int rtw_cfgvendor_set_rssi_monitor(struct wiphy *wiphy,1297struct wireless_dev *wdev, const void *data, int len)1298{1299_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));1300struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);13011302struct recv_priv *precvpriv = &padapter->recvpriv;1303int err = 0, rem, type;1304const struct nlattr *iter;13051306RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);13071308nla_for_each_attr(iter, data, len, rem) {1309type = nla_type(iter);13101311switch (type) {1312case RSSI_MONITOR_ATTRIBUTE_MAX_RSSI:1313pwdev_priv->rssi_monitor_max = (s8)nla_get_u32(iter);;1314break;1315case RSSI_MONITOR_ATTRIBUTE_MIN_RSSI:1316pwdev_priv->rssi_monitor_min = (s8)nla_get_u32(iter);1317break;1318case RSSI_MONITOR_ATTRIBUTE_START:1319pwdev_priv->rssi_monitor_enable = (u8)nla_get_u32(iter);1320break;1321}1322}13231324return err;1325}13261327void rtw_cfgvendor_rssi_monitor_evt(_adapter *padapter) {1328struct wireless_dev *wdev = padapter->rtw_wdev;1329struct wiphy *wiphy= wdev->wiphy;1330struct recv_priv *precvpriv = &padapter->recvpriv;1331struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1332struct wlan_network *pcur_network = &pmlmepriv->cur_network;1333struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);1334struct sk_buff *skb;1335u32 tot_len = NLMSG_DEFAULT_SIZE;1336gfp_t kflags;1337rssi_monitor_evt data ;1338s8 rssi = precvpriv->rssi;13391340if (pwdev_priv->rssi_monitor_enable == 0 || check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE)1341return;13421343if (rssi < pwdev_priv->rssi_monitor_max || rssi > pwdev_priv->rssi_monitor_min)1344return;13451346kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;13471348/* Alloc the SKB for vendor_event */1349skb = rtw_cfg80211_vendor_event_alloc(wiphy, wdev, tot_len, GOOGLE_RSSI_MONITOR_EVENT, kflags);1350if (!skb) {1351goto exit;1352}13531354_rtw_memset(&data, 0, sizeof(data));13551356data.version = RSSI_MONITOR_EVT_VERSION;1357data.cur_rssi = rssi;1358_rtw_memcpy(data.BSSID, pcur_network->network.MacAddress, sizeof(mac_addr));13591360nla_append(skb, sizeof(data), &data);13611362rtw_cfg80211_vendor_event(skb, kflags);1363exit:1364return;1365}1366#endif /* CONFIG_RTW_CFGVEDNOR_RSSIMONITR */13671368#ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER1369static int rtw_cfgvendor_logger_start_logging(struct wiphy *wiphy,1370struct wireless_dev *wdev, const void *data, int len)1371{1372int ret = 0, rem, type;1373char ring_name[32] = {0};1374int log_level = 0, flags = 0, time_intval = 0, threshold = 0;1375const struct nlattr *iter;13761377nla_for_each_attr(iter, data, len, rem) {1378type = nla_type(iter);1379switch (type) {1380case LOGGER_ATTRIBUTE_RING_NAME:1381strncpy(ring_name, nla_data(iter),1382MIN(sizeof(ring_name) -1, nla_len(iter)));1383break;1384case LOGGER_ATTRIBUTE_LOG_LEVEL:1385log_level = nla_get_u32(iter);1386break;1387case LOGGER_ATTRIBUTE_RING_FLAGS:1388flags = nla_get_u32(iter);1389break;1390case LOGGER_ATTRIBUTE_LOG_TIME_INTVAL:1391time_intval = nla_get_u32(iter);1392break;1393case LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE:1394threshold = nla_get_u32(iter);1395break;1396default:1397RTW_ERR("Unknown type: %d\n", type);1398ret = WIFI_ERROR_INVALID_ARGS;1399goto exit;1400}1401}14021403exit:1404return ret;1405}1406static int rtw_cfgvendor_logger_get_feature(struct wiphy *wiphy,1407struct wireless_dev *wdev, const void *data, int len)1408{1409int err = 0;1410u32 supported_features = 0;14111412err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), &supported_features, sizeof(supported_features));14131414if (unlikely(err))1415RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"1416, FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);14171418return err;1419}1420static int rtw_cfgvendor_logger_get_version(struct wiphy *wiphy,1421struct wireless_dev *wdev, const void *data, int len)1422{1423_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));1424HAL_DATA_TYPE *hal = GET_HAL_DATA(padapter);1425int ret = 0, rem, type;1426int buf_len = 1024;1427char *buf_ptr;1428const struct nlattr *iter;1429gfp_t kflags;14301431kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;1432buf_ptr = kzalloc(buf_len, kflags);1433if (!buf_ptr) {1434RTW_ERR("failed to allocate the buffer for version n");1435ret = -ENOMEM;1436goto exit;1437}1438nla_for_each_attr(iter, data, len, rem) {1439type = nla_type(iter);1440switch (type) {1441case LOGGER_ATTRIBUTE_GET_DRIVER:1442memcpy(buf_ptr, DRIVERVERSION, strlen(DRIVERVERSION)+1);1443break;1444case LOGGER_ATTRIBUTE_GET_FW:1445sprintf(buf_ptr, "v%d.%d", hal->firmware_version, hal->firmware_sub_version);1446break;1447default:1448RTW_ERR("Unknown type: %d\n", type);1449ret = -EINVAL;1450goto exit;1451}1452}1453if (ret < 0) {1454RTW_ERR("failed to get the version %d\n", ret);1455goto exit;1456}145714581459ret = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), buf_ptr, strlen(buf_ptr));1460exit:1461kfree(buf_ptr);1462return ret;1463}14641465static int rtw_cfgvendor_logger_get_ring_status(struct wiphy *wiphy,1466struct wireless_dev *wdev, const void *data, int len)1467{1468int ret = 0;1469int ring_id;1470char ring_buf_name[] = "RTW_RING_BUFFER";14711472struct sk_buff *skb;1473wifi_ring_buffer_status ring_status;147414751476_rtw_memcpy(ring_status.name, ring_buf_name, strlen(ring_buf_name)+1);1477ring_status.ring_id = 1;1478/* Alloc the SKB for vendor_event */1479skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,1480sizeof(wifi_ring_buffer_status));1481if (!skb) {1482RTW_ERR("skb allocation is failed\n");1483ret = FAIL;1484goto exit;1485}14861487nla_put_u32(skb, LOGGER_ATTRIBUTE_RING_NUM, 1);1488nla_put(skb, LOGGER_ATTRIBUTE_RING_STATUS, sizeof(wifi_ring_buffer_status),1489&ring_status);1490ret = cfg80211_vendor_cmd_reply(skb);14911492if (ret) {1493RTW_ERR("Vendor Command reply failed ret:%d \n", ret);1494}1495exit:1496return ret;1497}14981499static int rtw_cfgvendor_logger_get_ring_data(struct wiphy *wiphy,1500struct wireless_dev *wdev, const void *data, int len)1501{1502int ret = 0, rem, type;1503char ring_name[32] = {0};1504const struct nlattr *iter;15051506nla_for_each_attr(iter, data, len, rem) {1507type = nla_type(iter);1508switch (type) {1509case LOGGER_ATTRIBUTE_RING_NAME:1510strncpy(ring_name, nla_data(iter),1511MIN(sizeof(ring_name) -1, nla_len(iter)));1512RTW_INFO(" %s LOGGER_ATTRIBUTE_RING_NAME : %s\n", __func__, ring_name);1513break;1514default:1515RTW_ERR("Unknown type: %d\n", type);1516return ret;1517}1518}151915201521return ret;1522}15231524static int rtw_cfgvendor_logger_get_firmware_memory_dump(struct wiphy *wiphy,1525struct wireless_dev *wdev, const void *data, int len)1526{1527int ret = WIFI_ERROR_NOT_SUPPORTED;15281529return ret;1530}15311532static int rtw_cfgvendor_logger_start_pkt_fate_monitoring(struct wiphy *wiphy,1533struct wireless_dev *wdev, const void *data, int len)1534{1535int ret = WIFI_SUCCESS;15361537return ret;1538}15391540static int rtw_cfgvendor_logger_get_tx_pkt_fates(struct wiphy *wiphy,1541struct wireless_dev *wdev, const void *data, int len)1542{1543int ret = WIFI_SUCCESS;15441545return ret;1546}15471548static int rtw_cfgvendor_logger_get_rx_pkt_fates(struct wiphy *wiphy,1549struct wireless_dev *wdev, const void *data, int len)1550{1551int ret = WIFI_SUCCESS;15521553return ret;1554}15551556#endif /* CONFIG_RTW_CFGVENDOR_WIFI_LOGGER */1557#ifdef CONFIG_RTW_WIFI_HAL1558#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI15591560#ifndef ETHER_ISMULTI1561#define ETHER_ISMULTI(ea) (((const u8 *)(ea))[0] & 1)1562#endif156315641565static u8 null_addr[ETH_ALEN] = {0};1566static void rtw_hal_random_gen_mac_addr(u8 *mac_addr)1567{1568do {1569get_random_bytes(&mac_addr[3], ETH_ALEN-3);1570if (memcmp(mac_addr, null_addr, ETH_ALEN) != 0)1571break;1572} while(1);1573}15741575void rtw_hal_pno_random_gen_mac_addr(PADAPTER adapter)1576{1577u8 mac_addr[ETH_ALEN];1578struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);15791580memcpy(mac_addr, pwdev_priv->pno_mac_addr, ETH_ALEN);1581if (mac_addr[0] == 0xFF) return;1582rtw_hal_random_gen_mac_addr(mac_addr);1583memcpy(pwdev_priv->pno_mac_addr, mac_addr, ETH_ALEN);1584#ifdef CONFIG_RTW_DEBUG1585print_hex_dump(KERN_DEBUG, "pno_mac_addr: ",1586DUMP_PREFIX_OFFSET, 16, 1, pwdev_priv->pno_mac_addr,1587ETH_ALEN, 1);1588#endif1589}15901591void rtw_hal_set_hw_mac_addr(PADAPTER adapter, u8 *mac_addr)1592{1593rtw_ps_deny(adapter, PS_DENY_IOCTL);1594LeaveAllPowerSaveModeDirect(adapter);15951596rtw_hal_set_hwreg(adapter, HW_VAR_MAC_ADDR, mac_addr);1597#ifdef CONFIG_RTW_DEBUG1598rtw_hal_dump_macaddr(RTW_DBGDUMP, adapter);1599#endif1600rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);1601}16021603static int rtw_cfgvendor_set_rand_mac_oui(struct wiphy *wiphy,1604struct wireless_dev *wdev, const void *data, int len)1605{1606int err = 0;1607PADAPTER adapter;1608void *devaddr;1609struct net_device *netdev;1610int type, mac_len;1611u8 pno_random_mac_oui[3];1612u8 mac_addr[ETH_ALEN] = {0};1613struct pwrctrl_priv *pwrctl;1614struct rtw_wdev_priv *pwdev_priv;16151616type = nla_type(data);1617mac_len = nla_len(data);1618if (mac_len != 3) {1619RTW_ERR("%s oui len error %d != 3\n", __func__, mac_len);1620return -1;1621}16221623if (type == ANDR_WIFI_ATTRIBUTE_RANDOM_MAC_OUI) {1624memcpy(pno_random_mac_oui, nla_data(data), 3);1625print_hex_dump(KERN_DEBUG, "pno_random_mac_oui: ",1626DUMP_PREFIX_OFFSET, 16, 1, pno_random_mac_oui,16273, 1);16281629if (ETHER_ISMULTI(pno_random_mac_oui)) {1630pr_err("%s: oui is multicast address\n", __func__);1631return -1;1632}16331634adapter = wiphy_to_adapter(wiphy);1635if (adapter == NULL) {1636pr_err("%s: wiphy_to_adapter == NULL\n", __func__);1637return -1;1638}16391640pwdev_priv = adapter_wdev_data(adapter);16411642memcpy(mac_addr, pno_random_mac_oui, 3);1643rtw_hal_random_gen_mac_addr(mac_addr);1644memcpy(pwdev_priv->pno_mac_addr, mac_addr, ETH_ALEN);1645#ifdef CONFIG_RTW_DEBUG1646print_hex_dump(KERN_DEBUG, "pno_mac_addr: ",1647DUMP_PREFIX_OFFSET, 16, 1, pwdev_priv->pno_mac_addr,1648ETH_ALEN, 1);1649#endif1650} else {1651RTW_ERR("%s oui type error %x != 0x2\n", __func__, type);1652err = -1;1653}165416551656return err;1657}16581659#endif166016611662static int rtw_cfgvendor_set_nodfs_flag(struct wiphy *wiphy,1663struct wireless_dev *wdev, const void *data, int len)1664{1665int err = 0;1666int type;1667u32 nodfs = 0;1668_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));16691670RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);16711672type = nla_type(data);1673if (type == ANDR_WIFI_ATTRIBUTE_NODFS_SET) {1674nodfs = nla_get_u32(data);1675adapter_to_dvobj(padapter)->nodfs = nodfs;1676} else {1677err = -EINVAL;1678}16791680RTW_INFO("%s nodfs=%d, err=%d\n", __func__, nodfs, err);16811682return err;1683}16841685static int rtw_cfgvendor_set_country(struct wiphy *wiphy,1686struct wireless_dev *wdev, const void *data, int len)1687{1688#define CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */1689int err = 0, rem, type;1690char country_code[CNTRY_BUF_SZ] = {0};1691const struct nlattr *iter;1692_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));16931694RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);16951696nla_for_each_attr(iter, data, len, rem) {1697type = nla_type(iter);1698switch (type) {1699case ANDR_WIFI_ATTRIBUTE_COUNTRY:1700_rtw_memcpy(country_code, nla_data(iter),1701MIN(nla_len(iter), CNTRY_BUF_SZ));1702break;1703default:1704RTW_ERR("Unknown type: %d\n", type);1705return -EINVAL;1706}1707}17081709RTW_INFO("%s country_code:\"%c%c\" \n", __func__, country_code[0], country_code[1]);17101711rtw_set_country(padapter, country_code);17121713return err;1714}17151716static int rtw_cfgvendor_set_nd_offload(struct wiphy *wiphy,1717struct wireless_dev *wdev, const void *data, int len)1718{1719int err = 0;1720int type;1721u8 nd_en = 0;1722_adapter *padapter = GET_PRIMARY_ADAPTER(wiphy_to_adapter(wiphy));17231724RTW_DBG(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char*)data);17251726type = nla_type(data);1727if (type == ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE) {1728nd_en = nla_get_u8(data);1729/* ND has been enabled when wow is enabled */1730} else {1731err = -EINVAL;1732}17331734RTW_INFO("%s nd_en=%d, err=%d\n", __func__, nd_en, err);17351736return err;1737}1738#endif /* CONFIG_RTW_WIFI_HAL */17391740static const struct wiphy_vendor_command rtw_vendor_cmds[] = {1741#if defined(GSCAN_SUPPORT) && 01742{1743{1744.vendor_id = OUI_GOOGLE,1745.subcmd = GSCAN_SUBCMD_GET_CAPABILITIES1746},1747.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1748.doit = rtw_cfgvendor_gscan_get_capabilities1749#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1750,1751.policy = VENDOR_CMD_RAW_DATA,1752.maxattr = 11753#endif1754},1755{1756{1757.vendor_id = OUI_GOOGLE,1758.subcmd = GSCAN_SUBCMD_SET_CONFIG1759},1760.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1761.doit = rtw_cfgvendor_set_scan_cfg1762#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1763,1764.policy = VENDOR_CMD_RAW_DATA,1765.maxattr = 11766#endif1767},1768{1769{1770.vendor_id = OUI_GOOGLE,1771.subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG1772},1773.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1774.doit = rtw_cfgvendor_set_batch_scan_cfg1775#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1776,1777.policy = VENDOR_CMD_RAW_DATA,1778.maxattr = 11779#endif1780},1781{1782{1783.vendor_id = OUI_GOOGLE,1784.subcmd = GSCAN_SUBCMD_ENABLE_GSCAN1785},1786.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1787.doit = rtw_cfgvendor_initiate_gscan1788#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1789,1790.policy = VENDOR_CMD_RAW_DATA,1791.maxattr = 11792#endif1793},1794{1795{1796.vendor_id = OUI_GOOGLE,1797.subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS1798},1799.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1800.doit = rtw_cfgvendor_enable_full_scan_result1801#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1802,1803.policy = VENDOR_CMD_RAW_DATA,1804.maxattr = 11805#endif1806},1807{1808{1809.vendor_id = OUI_GOOGLE,1810.subcmd = GSCAN_SUBCMD_SET_HOTLIST1811},1812.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1813.doit = rtw_cfgvendor_hotlist_cfg1814#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1815,1816.policy = VENDOR_CMD_RAW_DATA,1817.maxattr = 11818#endif1819},1820{1821{1822.vendor_id = OUI_GOOGLE,1823.subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG1824},1825.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1826.doit = rtw_cfgvendor_significant_change_cfg1827#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1828,1829.policy = VENDOR_CMD_RAW_DATA,1830.maxattr = 11831#endif1832},1833{1834{1835.vendor_id = OUI_GOOGLE,1836.subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS1837},1838.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1839.doit = rtw_cfgvendor_gscan_get_batch_results1840#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1841,1842.policy = VENDOR_CMD_RAW_DATA,1843.maxattr = 11844#endif1845},1846{1847{1848.vendor_id = OUI_GOOGLE,1849.subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST1850},1851.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1852.doit = rtw_cfgvendor_gscan_get_channel_list1853#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1854,1855.policy = VENDOR_CMD_RAW_DATA,1856.maxattr = 11857#endif1858},1859#endif /* GSCAN_SUPPORT */1860#if defined(RTT_SUPPORT) && 01861{1862{1863.vendor_id = OUI_GOOGLE,1864.subcmd = RTT_SUBCMD_SET_CONFIG1865},1866.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1867.doit = rtw_cfgvendor_rtt_set_config1868#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1869,1870.policy = VENDOR_CMD_RAW_DATA,1871.maxattr = 11872#endif1873},1874{1875{1876.vendor_id = OUI_GOOGLE,1877.subcmd = RTT_SUBCMD_CANCEL_CONFIG1878},1879.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1880.doit = rtw_cfgvendor_rtt_cancel_config1881#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1882,1883.policy = VENDOR_CMD_RAW_DATA,1884.maxattr = 11885#endif1886},1887{1888{1889.vendor_id = OUI_GOOGLE,1890.subcmd = RTT_SUBCMD_GETCAPABILITY1891},1892.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1893.doit = rtw_cfgvendor_rtt_get_capability1894#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1895,1896.policy = VENDOR_CMD_RAW_DATA,1897.maxattr = 11898#endif1899},1900#endif /* RTT_SUPPORT */1901#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS1902{1903{1904.vendor_id = OUI_GOOGLE,1905.subcmd = LSTATS_SUBCMD_GET_INFO1906},1907.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1908.doit = rtw_cfgvendor_lstats_get_info1909#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1910,1911.policy = VENDOR_CMD_RAW_DATA,1912.maxattr = 11913#endif1914},1915{1916{1917.vendor_id = OUI_GOOGLE,1918.subcmd = LSTATS_SUBCMD_SET_INFO1919},1920.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1921.doit = rtw_cfgvendor_lstats_set_info1922#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1923,1924.policy = VENDOR_CMD_RAW_DATA,1925.maxattr = 11926#endif1927},1928{1929{1930.vendor_id = OUI_GOOGLE,1931.subcmd = LSTATS_SUBCMD_CLEAR_INFO1932},1933.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1934.doit = rtw_cfgvendor_lstats_clear_info1935#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1936,1937.policy = VENDOR_CMD_RAW_DATA,1938.maxattr = 11939#endif1940},1941#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */1942#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR1943{1944{1945.vendor_id = OUI_GOOGLE,1946.subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR1947},1948.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1949.doit = rtw_cfgvendor_set_rssi_monitor1950#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1951,1952.policy = VENDOR_CMD_RAW_DATA,1953.maxattr = 11954#endif1955},1956#endif /* CONFIG_RTW_CFGVEDNOR_RSSIMONITOR */1957#ifdef CONFIG_RTW_CFGVENDOR_WIFI_LOGGER1958{1959{1960.vendor_id = OUI_GOOGLE,1961.subcmd = LOGGER_START_LOGGING1962},1963.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1964.doit = rtw_cfgvendor_logger_start_logging1965#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1966,1967.policy = VENDOR_CMD_RAW_DATA,1968.maxattr = 11969#endif1970},1971{1972{1973.vendor_id = OUI_GOOGLE,1974.subcmd = LOGGER_GET_FEATURE1975},1976.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1977.doit = rtw_cfgvendor_logger_get_feature1978#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1979,1980.policy = VENDOR_CMD_RAW_DATA,1981.maxattr = 11982#endif1983},1984{1985{1986.vendor_id = OUI_GOOGLE,1987.subcmd = LOGGER_GET_VER1988},1989.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,1990.doit = rtw_cfgvendor_logger_get_version1991#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))1992,1993.policy = VENDOR_CMD_RAW_DATA,1994.maxattr = 11995#endif1996},1997{1998{1999.vendor_id = OUI_GOOGLE,2000.subcmd = LOGGER_GET_RING_STATUS2001},2002.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2003.doit = rtw_cfgvendor_logger_get_ring_status2004#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2005,2006.policy = VENDOR_CMD_RAW_DATA,2007.maxattr = 12008#endif2009},2010{2011{2012.vendor_id = OUI_GOOGLE,2013.subcmd = LOGGER_GET_RING_DATA2014},2015.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2016.doit = rtw_cfgvendor_logger_get_ring_data2017#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2018,2019.policy = VENDOR_CMD_RAW_DATA,2020.maxattr = 12021#endif2022},2023{2024{2025.vendor_id = OUI_GOOGLE,2026.subcmd = LOGGER_TRIGGER_MEM_DUMP2027},2028.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2029.doit = rtw_cfgvendor_logger_get_firmware_memory_dump2030#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2031,2032.policy = VENDOR_CMD_RAW_DATA,2033.maxattr = 12034#endif2035},2036{2037{2038.vendor_id = OUI_GOOGLE,2039.subcmd = LOGGER_START_PKT_FATE_MONITORING2040},2041.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2042.doit = rtw_cfgvendor_logger_start_pkt_fate_monitoring2043#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2044,2045.policy = VENDOR_CMD_RAW_DATA,2046.maxattr = 12047#endif2048},2049{2050{2051.vendor_id = OUI_GOOGLE,2052.subcmd = LOGGER_GET_TX_PKT_FATES2053},2054.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2055.doit = rtw_cfgvendor_logger_get_tx_pkt_fates2056#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2057,2058.policy = VENDOR_CMD_RAW_DATA,2059.maxattr = 12060#endif2061},2062{2063{2064.vendor_id = OUI_GOOGLE,2065.subcmd = LOGGER_GET_RX_PKT_FATES2066},2067.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2068.doit = rtw_cfgvendor_logger_get_rx_pkt_fates2069#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2070,2071.policy = VENDOR_CMD_RAW_DATA,2072.maxattr = 12073#endif2074},2075#endif /* CONFIG_RTW_CFGVENDOR_WIFI_LOGGER */2076#ifdef CONFIG_RTW_WIFI_HAL2077#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI2078{2079{2080.vendor_id = OUI_GOOGLE,2081.subcmd = WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI2082},2083.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2084.doit = rtw_cfgvendor_set_rand_mac_oui2085#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2086,2087.policy = VENDOR_CMD_RAW_DATA,2088.maxattr = 12089#endif2090},2091#endif2092{2093{2094.vendor_id = OUI_GOOGLE,2095.subcmd = WIFI_SUBCMD_NODFS_SET2096},2097.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2098.doit = rtw_cfgvendor_set_nodfs_flag2099#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2100,2101.policy = VENDOR_CMD_RAW_DATA,2102.maxattr = 12103#endif2104},2105{2106{2107.vendor_id = OUI_GOOGLE,2108.subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE2109},2110.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2111.doit = rtw_cfgvendor_set_country2112#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2113,2114.policy = VENDOR_CMD_RAW_DATA,2115.maxattr = 12116#endif2117},2118{2119{2120.vendor_id = OUI_GOOGLE,2121.subcmd = WIFI_SUBCMD_CONFIG_ND_OFFLOAD2122},2123.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2124.doit = rtw_cfgvendor_set_nd_offload2125#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2126,2127.policy = VENDOR_CMD_RAW_DATA,2128.maxattr = 12129#endif2130},2131#endif /* CONFIG_RTW_WIFI_HAL */2132{2133{2134.vendor_id = OUI_GOOGLE,2135.subcmd = WIFI_SUBCMD_GET_FEATURE_SET2136},2137.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2138.doit = rtw_cfgvendor_get_feature_set2139#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2140,2141.policy = VENDOR_CMD_RAW_DATA,2142.maxattr = 12143#endif2144},2145{2146{2147.vendor_id = OUI_GOOGLE,2148.subcmd = WIFI_SUBCMD_GET_FEATURE_SET_MATRIX2149},2150.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,2151.doit = rtw_cfgvendor_get_feature_set_matrix2152#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))2153,2154.policy = VENDOR_CMD_RAW_DATA,2155.maxattr = 12156#endif2157}2158};21592160static const struct nl80211_vendor_cmd_info rtw_vendor_events[] = {2161#if defined(GSCAN_SUPPORT) && 02162{ OUI_GOOGLE, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS },2163{ OUI_GOOGLE, GSCAN_EVENT_HOTLIST_RESULTS_FOUND },2164{ OUI_GOOGLE, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE },2165{ OUI_GOOGLE, GSCAN_EVENT_FULL_SCAN_RESULTS },2166#endif /* GSCAN_SUPPORT */2167#if defined(RTT_SUPPORT) && 02168{ OUI_GOOGLE, RTT_EVENT_COMPLETE },2169#endif /* RTT_SUPPORT */21702171#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR2172{ OUI_GOOGLE, GOOGLE_RSSI_MONITOR_EVENT },2173#endif /* RTW_CFGVEDNOR_RSSIMONITR */21742175#if defined(GSCAN_SUPPORT) && 02176{ OUI_GOOGLE, GSCAN_EVENT_COMPLETE_SCAN },2177{ OUI_GOOGLE, GSCAN_EVENT_HOTLIST_RESULTS_LOST }2178#endif /* GSCAN_SUPPORT */2179};21802181int rtw_cfgvendor_attach(struct wiphy *wiphy)2182{21832184RTW_INFO("Register RTW cfg80211 vendor cmd(0x%x) interface\n", NL80211_CMD_VENDOR);21852186wiphy->vendor_commands = rtw_vendor_cmds;2187wiphy->n_vendor_commands = ARRAY_SIZE(rtw_vendor_cmds);2188wiphy->vendor_events = rtw_vendor_events;2189wiphy->n_vendor_events = ARRAY_SIZE(rtw_vendor_events);21902191return 0;2192}21932194int rtw_cfgvendor_detach(struct wiphy *wiphy)2195{2196RTW_INFO("Vendor: Unregister RTW cfg80211 vendor interface\n");21972198wiphy->vendor_commands = NULL;2199wiphy->vendor_events = NULL;2200wiphy->n_vendor_commands = 0;2201wiphy->n_vendor_events = 0;22022203return 0;2204}2205#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT) */22062207#endif /* CONFIG_IOCTL_CFG80211 */220822092210