Path: blob/master/ALFA-W1F1/RTL8814AU/os_dep/linux/ioctl_cfg80211.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*****************************************************************************/14#define _IOCTL_CFG80211_C_1516#include <drv_types.h>17#include <hal_data.h>1819#ifdef CONFIG_IOCTL_CFG802112021#ifndef DBG_RTW_CFG80211_STA_PARAM22#define DBG_RTW_CFG80211_STA_PARAM 023#endif2425#ifndef DBG_RTW_CFG80211_MESH_CONF26#define DBG_RTW_CFG80211_MESH_CONF 027#endif2829#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))30#define STATION_INFO_INACTIVE_TIME BIT(NL80211_STA_INFO_INACTIVE_TIME)31#define STATION_INFO_LLID BIT(NL80211_STA_INFO_LLID)32#define STATION_INFO_PLID BIT(NL80211_STA_INFO_PLID)33#define STATION_INFO_PLINK_STATE BIT(NL80211_STA_INFO_PLINK_STATE)34#define STATION_INFO_SIGNAL BIT(NL80211_STA_INFO_SIGNAL)35#define STATION_INFO_TX_BITRATE BIT(NL80211_STA_INFO_TX_BITRATE)36#define STATION_INFO_RX_PACKETS BIT(NL80211_STA_INFO_RX_PACKETS)37#define STATION_INFO_TX_PACKETS BIT(NL80211_STA_INFO_TX_PACKETS)38#define STATION_INFO_TX_FAILED BIT(NL80211_STA_INFO_TX_FAILED)39#define STATION_INFO_LOCAL_PM BIT(NL80211_STA_INFO_LOCAL_PM)40#define STATION_INFO_PEER_PM BIT(NL80211_STA_INFO_PEER_PM)41#define STATION_INFO_NONPEER_PM BIT(NL80211_STA_INFO_NONPEER_PM)42#define STATION_INFO_ASSOC_REQ_IES 043#endif /* Linux kernel >= 4.0.0 */4445#include <rtw_wifi_regd.h>4647#define RTW_MAX_MGMT_TX_CNT (8)48#define RTW_MAX_MGMT_TX_MS_GAS (500)4950#define RTW_SCAN_IE_LEN_MAX 230451#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 5000 /* ms */52#define RTW_MAX_NUM_PMKIDS 45354#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */5556#ifdef CONFIG_WAPI_SUPPORT5758#ifndef WLAN_CIPHER_SUITE_SMS459#define WLAN_CIPHER_SUITE_SMS4 0x0014720160#endif6162#ifndef WLAN_AKM_SUITE_WAPI_PSK63#define WLAN_AKM_SUITE_WAPI_PSK 0x000FAC0464#endif6566#ifndef WLAN_AKM_SUITE_WAPI_CERT67#define WLAN_AKM_SUITE_WAPI_CERT 0x000FAC1268#endif6970#ifndef NL80211_WAPI_VERSION_171#define NL80211_WAPI_VERSION_1 (1 << 2)72#endif7374#endif /* CONFIG_WAPI_SUPPORT */7576#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 12))77#ifdef CONFIG_RTW_80211R78#define WLAN_AKM_SUITE_FT_8021X 0x000FAC0379#define WLAN_AKM_SUITE_FT_PSK 0x000FAC0480#endif81#endif8283/*84* In the current design of Wi-Fi driver, it will return success to the system (e.g. supplicant)85* when Wi-Fi driver decides to abort the scan request in the scan flow by default.86* Defining this flag makes Wi-Fi driver to return -EBUSY to the system if Wi-Fi driver is too busy to do the scan.87*/88#ifndef CONFIG_NOTIFY_SCAN_ABORT_WITH_BUSY89#define CONFIG_NOTIFY_SCAN_ABORT_WITH_BUSY 090#endif9192static const u32 rtw_cipher_suites[] = {93WLAN_CIPHER_SUITE_WEP40,94WLAN_CIPHER_SUITE_WEP104,95WLAN_CIPHER_SUITE_TKIP,96WLAN_CIPHER_SUITE_CCMP,97#ifdef CONFIG_WAPI_SUPPORT98WLAN_CIPHER_SUITE_SMS4,99#endif /* CONFIG_WAPI_SUPPORT */100#ifdef CONFIG_IEEE80211W101WLAN_CIPHER_SUITE_AES_CMAC,102#endif /* CONFIG_IEEE80211W */103};104105#define RATETAB_ENT(_rate, _rateid, _flags) \106{ \107.bitrate = (_rate), \108.hw_value = (_rateid), \109.flags = (_flags), \110}111112#define CHAN2G(_channel, _freq, _flags) { \113.band = NL80211_BAND_2GHZ, \114.center_freq = (_freq), \115.hw_value = (_channel), \116.flags = (_flags), \117.max_antenna_gain = 0, \118.max_power = 30, \119}120121#define CHAN5G(_channel, _flags) { \122.band = NL80211_BAND_5GHZ, \123.center_freq = 5000 + (5 * (_channel)), \124.hw_value = (_channel), \125.flags = (_flags), \126.max_antenna_gain = 0, \127.max_power = 30, \128}129130#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))131/* if wowlan is not supported, kernel generate a disconnect at each suspend132* cf: /net/wireless/sysfs.c, so register a stub wowlan.133* Moreover wowlan has to be enabled via a the nl80211_set_wowlan callback.134* (from user space, e.g. iw phy0 wowlan enable)135*/136static const struct wiphy_wowlan_support wowlan_stub = {137.flags = WIPHY_WOWLAN_ANY,138.n_patterns = 0,139.pattern_max_len = 0,140.pattern_min_len = 0,141#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))142.max_pkt_offset = 0,143#endif144};145#endif146147static struct ieee80211_rate rtw_rates[] = {148RATETAB_ENT(10, 0x1, 0),149RATETAB_ENT(20, 0x2, 0),150RATETAB_ENT(55, 0x4, 0),151RATETAB_ENT(110, 0x8, 0),152RATETAB_ENT(60, 0x10, 0),153RATETAB_ENT(90, 0x20, 0),154RATETAB_ENT(120, 0x40, 0),155RATETAB_ENT(180, 0x80, 0),156RATETAB_ENT(240, 0x100, 0),157RATETAB_ENT(360, 0x200, 0),158RATETAB_ENT(480, 0x400, 0),159RATETAB_ENT(540, 0x800, 0),160};161162#define rtw_a_rates (rtw_rates + 4)163#define RTW_A_RATES_NUM 8164#define rtw_g_rates (rtw_rates + 0)165#define RTW_G_RATES_NUM 12166167/* from center_ch_2g */168static struct ieee80211_channel rtw_2ghz_channels[MAX_CHANNEL_NUM_2G] = {169CHAN2G(1, 2412, 0),170CHAN2G(2, 2417, 0),171CHAN2G(3, 2422, 0),172CHAN2G(4, 2427, 0),173CHAN2G(5, 2432, 0),174CHAN2G(6, 2437, 0),175CHAN2G(7, 2442, 0),176CHAN2G(8, 2447, 0),177CHAN2G(9, 2452, 0),178CHAN2G(10, 2457, 0),179CHAN2G(11, 2462, 0),180CHAN2G(12, 2467, 0),181CHAN2G(13, 2472, 0),182CHAN2G(14, 2484, 0),183};184185/* from center_ch_5g_20m */186static struct ieee80211_channel rtw_5ghz_a_channels[MAX_CHANNEL_NUM_5G] = {187CHAN5G(36, 0), CHAN5G(40, 0), CHAN5G(44, 0), CHAN5G(48, 0),188189CHAN5G(52, 0), CHAN5G(56, 0), CHAN5G(60, 0), CHAN5G(64, 0),190191CHAN5G(100, 0), CHAN5G(104, 0), CHAN5G(108, 0), CHAN5G(112, 0),192CHAN5G(116, 0), CHAN5G(120, 0), CHAN5G(124, 0), CHAN5G(128, 0),193CHAN5G(132, 0), CHAN5G(136, 0), CHAN5G(140, 0), CHAN5G(144, 0),194195CHAN5G(149, 0), CHAN5G(153, 0), CHAN5G(157, 0), CHAN5G(161, 0),196CHAN5G(165, 0), CHAN5G(169, 0), CHAN5G(173, 0), CHAN5G(177, 0),197};198199#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))200static u8 rtw_chbw_to_cfg80211_chan_def(struct wiphy *wiphy, struct cfg80211_chan_def *chdef, u8 ch, u8 bw, u8 offset, u8 ht)201{202int freq, cfreq;203struct ieee80211_channel *chan;204u8 ret = _FAIL;205206freq = rtw_ch2freq(ch);207if (!freq)208goto exit;209210cfreq = rtw_get_center_ch(ch, bw, offset);211if (!cfreq)212goto exit;213cfreq = rtw_ch2freq(cfreq);214if (!cfreq)215goto exit;216217chan = ieee80211_get_channel(wiphy, freq);218if (!chan)219goto exit;220221if (bw == CHANNEL_WIDTH_20)222chdef->width = ht ? NL80211_CHAN_WIDTH_20 : NL80211_CHAN_WIDTH_20_NOHT;223else if (bw == CHANNEL_WIDTH_40)224chdef->width = NL80211_CHAN_WIDTH_40;225else if (bw == CHANNEL_WIDTH_80)226chdef->width = NL80211_CHAN_WIDTH_80;227else if (bw == CHANNEL_WIDTH_160)228chdef->width = NL80211_CHAN_WIDTH_160;229else {230rtw_warn_on(1);231goto exit;232}233234chdef->chan = chan;235chdef->center_freq1 = cfreq;236chdef->center_freq2 = 0;237238ret = _SUCCESS;239240exit:241return ret;242}243244#ifdef CONFIG_RTW_MESH245static const char *nl80211_chan_width_str(enum nl80211_chan_width cwidth)246{247switch (cwidth) {248case NL80211_CHAN_WIDTH_20_NOHT:249return "20_NOHT";250case NL80211_CHAN_WIDTH_20:251return "20";252case NL80211_CHAN_WIDTH_40:253return "40";254case NL80211_CHAN_WIDTH_80:255return "80";256case NL80211_CHAN_WIDTH_80P80:257return "80+80";258case NL80211_CHAN_WIDTH_160:259return "160";260#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))261case NL80211_CHAN_WIDTH_5:262return "5";263case NL80211_CHAN_WIDTH_10:264return "10";265#endif266default:267return "INVALID";268};269}270271static void rtw_get_chbw_from_cfg80211_chan_def(struct cfg80211_chan_def *chdef, u8 *ht, u8 *ch, u8 *bw, u8 *offset)272{273int pri_freq;274struct ieee80211_channel *chan = chdef->chan;275276pri_freq = rtw_ch2freq(chan->hw_value);277if (!pri_freq) {278RTW_INFO("invalid channel:%d\n", chan->hw_value);279rtw_warn_on(1);280*ch = 0;281return;282}283284switch (chdef->width) {285case NL80211_CHAN_WIDTH_20_NOHT:286*ht = 0;287*bw = CHANNEL_WIDTH_20;288*offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;289*ch = chan->hw_value;290break;291case NL80211_CHAN_WIDTH_20:292*ht = 1;293*bw = CHANNEL_WIDTH_20;294*offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;295*ch = chan->hw_value;296break;297case NL80211_CHAN_WIDTH_40:298*ht = 1;299*bw = CHANNEL_WIDTH_40;300*offset = pri_freq > chdef->center_freq1 ? HAL_PRIME_CHNL_OFFSET_UPPER : HAL_PRIME_CHNL_OFFSET_LOWER;301if (rtw_get_offset_by_chbw(chan->hw_value, *bw, offset))302*ch = chan->hw_value;303break;304case NL80211_CHAN_WIDTH_80:305*ht = 1;306*bw = CHANNEL_WIDTH_80;307if (rtw_get_offset_by_chbw(chan->hw_value, *bw, offset))308*ch = chan->hw_value;309break;310case NL80211_CHAN_WIDTH_160:311*ht = 1;312*bw = CHANNEL_WIDTH_160;313if (rtw_get_offset_by_chbw(chan->hw_value, *bw, offset))314*ch = chan->hw_value;315break;316case NL80211_CHAN_WIDTH_80P80:317#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))318case NL80211_CHAN_WIDTH_5:319case NL80211_CHAN_WIDTH_10:320#endif321default:322*ht = 0;323*bw = CHANNEL_WIDTH_20;324*offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;325RTW_INFO("unsupported cwidth:%s\n", nl80211_chan_width_str(chdef->width));326rtw_warn_on(1);327};328}329#endif /* CONFIG_RTW_MESH */330#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))331static const char *nl80211_channel_type_str(enum nl80211_channel_type ctype)332{333switch (ctype) {334case NL80211_CHAN_NO_HT:335return "NO_HT";336case NL80211_CHAN_HT20:337return "HT20";338case NL80211_CHAN_HT40MINUS:339return "HT40-";340case NL80211_CHAN_HT40PLUS:341return "HT40+";342default:343return "INVALID";344};345}346347static enum nl80211_channel_type rtw_chbw_to_nl80211_channel_type(u8 ch, u8 bw, u8 offset, u8 ht)348{349rtw_warn_on(!ht && (bw >= CHANNEL_WIDTH_40 || offset != HAL_PRIME_CHNL_OFFSET_DONT_CARE));350351if (!ht)352return NL80211_CHAN_NO_HT;353if (bw >= CHANNEL_WIDTH_40) {354if (offset == HAL_PRIME_CHNL_OFFSET_UPPER)355return NL80211_CHAN_HT40MINUS;356else if (offset == HAL_PRIME_CHNL_OFFSET_LOWER)357return NL80211_CHAN_HT40PLUS;358else359rtw_warn_on(1);360}361return NL80211_CHAN_HT20;362}363364static void rtw_get_chbw_from_nl80211_channel_type(struct ieee80211_channel *chan, enum nl80211_channel_type ctype, u8 *ht, u8 *ch, u8 *bw, u8 *offset)365{366int pri_freq;367368pri_freq = rtw_ch2freq(chan->hw_value);369if (!pri_freq) {370RTW_INFO("invalid channel:%d\n", chan->hw_value);371rtw_warn_on(1);372*ch = 0;373return;374}375*ch = chan->hw_value;376377switch (ctype) {378case NL80211_CHAN_NO_HT:379*ht = 0;380*bw = CHANNEL_WIDTH_20;381*offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;382break;383case NL80211_CHAN_HT20:384*ht = 1;385*bw = CHANNEL_WIDTH_20;386*offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;387break;388case NL80211_CHAN_HT40MINUS:389*ht = 1;390*bw = CHANNEL_WIDTH_40;391*offset = HAL_PRIME_CHNL_OFFSET_UPPER;392break;393case NL80211_CHAN_HT40PLUS:394*ht = 1;395*bw = CHANNEL_WIDTH_40;396*offset = HAL_PRIME_CHNL_OFFSET_LOWER;397break;398default:399*ht = 0;400*bw = CHANNEL_WIDTH_20;401*offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;402RTW_INFO("unsupported ctype:%s\n", nl80211_channel_type_str(ctype));403rtw_warn_on(1);404};405}406#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) */407408#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))409u8 rtw_cfg80211_ch_switch_notify(_adapter *adapter, u8 ch, u8 bw, u8 offset,410u8 ht, bool started)411{412struct wiphy *wiphy = adapter_to_wiphy(adapter);413u8 ret = _SUCCESS;414415#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))416struct cfg80211_chan_def chdef = {};417418ret = rtw_chbw_to_cfg80211_chan_def(wiphy, &chdef, ch, bw, offset, ht);419if (ret != _SUCCESS)420goto exit;421422#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))423if (started) {424#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0))425426/* --- cfg80211_ch_switch_started_notfiy() ---427* A new parameter, bool quiet, is added from Linux kernel v5.11,428* to see if block-tx was requested by the AP. since currently,429* the API is used for station before connected in rtw_chk_start_clnt_join()430* the quiet is set to false here first. May need to refine it if431* called by others with block-tx.432*/433434#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))435#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0))436cfg80211_ch_switch_started_notify(adapter->pnetdev, &chdef, 0, 0, false, 0);437#else438cfg80211_ch_switch_started_notify(adapter->pnetdev, &chdef, 0, 0, false);439#endif440#else441cfg80211_ch_switch_started_notify(adapter->pnetdev, &chdef, 0, false);442#endif443#else444cfg80211_ch_switch_started_notify(adapter->pnetdev, &chdef, 0);445#endif446goto exit;447}448#endif449//450// if (!rtw_cfg80211_allow_ch_switch_notify(adapter))451// goto exit;452453#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2))454#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0))455cfg80211_ch_switch_notify(adapter->pnetdev, &chdef, 0, 0);456#else457cfg80211_ch_switch_notify(adapter->pnetdev, &chdef, 0);458#endif459#else460cfg80211_ch_switch_notify(adapter->pnetdev, &chdef);461#endif462463#else464int freq = rtw_ch2freq(ch);465enum nl80211_channel_type ctype;466467if (!freq) {468ret = _FAIL;469goto exit;470}471472ctype = rtw_chbw_to_nl80211_channel_type(ch, bw, offset, ht);473#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2))474cfg80211_ch_switch_notify(adapter->pnetdev, freq, ctype, 0);475#else476cfg80211_ch_switch_notify(adapter->pnetdev, freq, ctype);477#endif478#endif479480exit:481return ret;482}483#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */484485void rtw_2g_channels_init(struct ieee80211_channel *channels)486{487_rtw_memcpy((void *)channels, (void *)rtw_2ghz_channels, sizeof(rtw_2ghz_channels));488}489490void rtw_5g_channels_init(struct ieee80211_channel *channels)491{492_rtw_memcpy((void *)channels, (void *)rtw_5ghz_a_channels, sizeof(rtw_5ghz_a_channels));493}494495void rtw_2g_rates_init(struct ieee80211_rate *rates)496{497_rtw_memcpy(rates, rtw_g_rates,498sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM499);500}501502void rtw_5g_rates_init(struct ieee80211_rate *rates)503{504_rtw_memcpy(rates, rtw_a_rates,505sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM506);507}508509struct ieee80211_supported_band *rtw_spt_band_alloc(BAND_TYPE band)510{511struct ieee80211_supported_band *spt_band = NULL;512int n_channels, n_bitrates;513514if (band == BAND_ON_2_4G) {515n_channels = MAX_CHANNEL_NUM_2G;516n_bitrates = RTW_G_RATES_NUM;517} else if (band == BAND_ON_5G) {518n_channels = MAX_CHANNEL_NUM_5G;519n_bitrates = RTW_A_RATES_NUM;520} else521goto exit;522523spt_band = (struct ieee80211_supported_band *)rtw_zmalloc(524sizeof(struct ieee80211_supported_band)525+ sizeof(struct ieee80211_channel) * n_channels526+ sizeof(struct ieee80211_rate) * n_bitrates527);528if (!spt_band)529goto exit;530531spt_band->channels = (struct ieee80211_channel *)(((u8 *)spt_band) + sizeof(struct ieee80211_supported_band));532spt_band->bitrates = (struct ieee80211_rate *)(((u8 *)spt_band->channels) + sizeof(struct ieee80211_channel) * n_channels);533spt_band->band = rtw_band_to_nl80211_band(band);534spt_band->n_channels = n_channels;535spt_band->n_bitrates = n_bitrates;536537if (band == BAND_ON_2_4G) {538rtw_2g_channels_init(spt_band->channels);539rtw_2g_rates_init(spt_band->bitrates);540} else if (band == BAND_ON_5G) {541rtw_5g_channels_init(spt_band->channels);542rtw_5g_rates_init(spt_band->bitrates);543}544545/* spt_band.ht_cap */546547exit:548549return spt_band;550}551552void rtw_spt_band_free(struct ieee80211_supported_band *spt_band)553{554u32 size = 0;555556if (!spt_band)557return;558559if (spt_band->band == NL80211_BAND_2GHZ) {560size = sizeof(struct ieee80211_supported_band)561+ sizeof(struct ieee80211_channel) * MAX_CHANNEL_NUM_2G562+ sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM;563} else if (spt_band->band == NL80211_BAND_5GHZ) {564size = sizeof(struct ieee80211_supported_band)565+ sizeof(struct ieee80211_channel) * MAX_CHANNEL_NUM_5G566+ sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM;567} else {568569}570rtw_mfree((u8 *)spt_band, size);571}572573#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)574static const struct ieee80211_txrx_stypes575rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {576[NL80211_IFTYPE_ADHOC] = {577.tx = 0xffff,578.rx = BIT(IEEE80211_STYPE_ACTION >> 4)579},580[NL80211_IFTYPE_STATION] = {581.tx = 0xffff,582.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |583BIT(IEEE80211_STYPE_AUTH >> 4) |584BIT(IEEE80211_STYPE_PROBE_REQ >> 4)585},586[NL80211_IFTYPE_AP] = {587.tx = 0xffff,588.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |589BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |590BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |591BIT(IEEE80211_STYPE_DISASSOC >> 4) |592BIT(IEEE80211_STYPE_AUTH >> 4) |593BIT(IEEE80211_STYPE_DEAUTH >> 4) |594BIT(IEEE80211_STYPE_ACTION >> 4)595},596[NL80211_IFTYPE_AP_VLAN] = {597/* copy AP */598.tx = 0xffff,599.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |600BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |601BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |602BIT(IEEE80211_STYPE_DISASSOC >> 4) |603BIT(IEEE80211_STYPE_AUTH >> 4) |604BIT(IEEE80211_STYPE_DEAUTH >> 4) |605BIT(IEEE80211_STYPE_ACTION >> 4)606},607[NL80211_IFTYPE_P2P_CLIENT] = {608.tx = 0xffff,609.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |610BIT(IEEE80211_STYPE_PROBE_REQ >> 4)611},612[NL80211_IFTYPE_P2P_GO] = {613.tx = 0xffff,614.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |615BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |616BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |617BIT(IEEE80211_STYPE_DISASSOC >> 4) |618BIT(IEEE80211_STYPE_AUTH >> 4) |619BIT(IEEE80211_STYPE_DEAUTH >> 4) |620BIT(IEEE80211_STYPE_ACTION >> 4)621},622#if defined(RTW_DEDICATED_P2P_DEVICE)623[NL80211_IFTYPE_P2P_DEVICE] = {624.tx = 0xffff,625.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |626BIT(IEEE80211_STYPE_PROBE_REQ >> 4)627},628#endif629#if defined(CONFIG_RTW_MESH)630[NL80211_IFTYPE_MESH_POINT] = {631.tx = 0xffff,632.rx = BIT(IEEE80211_STYPE_ACTION >> 4)633| BIT(IEEE80211_STYPE_AUTH >> 4)634},635#endif636637};638#endif639640NDIS_802_11_NETWORK_INFRASTRUCTURE nl80211_iftype_to_rtw_network_type(enum nl80211_iftype type)641{642switch (type) {643case NL80211_IFTYPE_ADHOC:644return Ndis802_11IBSS;645646#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))647case NL80211_IFTYPE_P2P_CLIENT:648#endif649case NL80211_IFTYPE_STATION:650return Ndis802_11Infrastructure;651652#ifdef CONFIG_AP_MODE653#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))654case NL80211_IFTYPE_P2P_GO:655#endif656case NL80211_IFTYPE_AP:657return Ndis802_11APMode;658#endif659660#ifdef CONFIG_RTW_MESH661case NL80211_IFTYPE_MESH_POINT:662return Ndis802_11_mesh;663#endif664665case NL80211_IFTYPE_MONITOR:666return Ndis802_11Monitor;667668default:669return Ndis802_11InfrastructureMax;670}671}672673u32 nl80211_iftype_to_rtw_mlme_state(enum nl80211_iftype type)674{675switch (type) {676case NL80211_IFTYPE_ADHOC:677return WIFI_ADHOC_STATE;678679#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))680case NL80211_IFTYPE_P2P_CLIENT:681#endif682case NL80211_IFTYPE_STATION:683return WIFI_STATION_STATE;684685#ifdef CONFIG_AP_MODE686#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))687case NL80211_IFTYPE_P2P_GO:688#endif689case NL80211_IFTYPE_AP:690return WIFI_AP_STATE;691#endif692693#ifdef CONFIG_RTW_MESH694case NL80211_IFTYPE_MESH_POINT:695return WIFI_MESH_STATE;696#endif697698case NL80211_IFTYPE_MONITOR:699return WIFI_MONITOR_STATE;700701default:702return WIFI_NULL_STATE;703}704}705706static int rtw_cfg80211_sync_iftype(_adapter *adapter)707{708struct wireless_dev *rtw_wdev = adapter->rtw_wdev;709710if (!(nl80211_iftype_to_rtw_mlme_state(rtw_wdev->iftype) & MLME_STATE(adapter))) {711/* iftype and mlme state is not syc */712NDIS_802_11_NETWORK_INFRASTRUCTURE network_type;713714network_type = nl80211_iftype_to_rtw_network_type(rtw_wdev->iftype);715if (network_type != Ndis802_11InfrastructureMax) {716if (rtw_pwr_wakeup(adapter) == _FAIL) {717RTW_WARN(FUNC_ADPT_FMT" call rtw_pwr_wakeup fail\n", FUNC_ADPT_ARG(adapter));718return _FAIL;719}720721rtw_set_802_11_infrastructure_mode(adapter, network_type, 0);722rtw_setopmode_cmd(adapter, network_type, RTW_CMDF_WAIT_ACK);723} else {724rtw_warn_on(1);725RTW_WARN(FUNC_ADPT_FMT" iftype:%u is not support\n", FUNC_ADPT_ARG(adapter), rtw_wdev->iftype);726return _FAIL;727}728}729730return _SUCCESS;731}732733static u64 rtw_get_systime_us(void)734{735#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))736return ktime_to_us(ktime_get_boottime());737#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))738struct timespec ts;739get_monotonic_boottime(&ts);740return ((u64)ts.tv_sec * 1000000) + ts.tv_nsec / 1000;741#else742struct timeval tv;743do_gettimeofday(&tv);744return ((u64)tv.tv_sec * 1000000) + tv.tv_usec;745#endif746}747748/* Try to remove non target BSS's SR to reduce PBC overlap rate */749static int rtw_cfg80211_clear_wps_sr_of_non_target_bss(_adapter *padapter, struct wlan_network *pnetwork, struct cfg80211_ssid *req_ssid)750{751int ret = 0;752u8 *psr = NULL, sr = 0;753NDIS_802_11_SSID *pssid = &pnetwork->network.Ssid;754u32 wpsielen = 0;755u8 *wpsie = NULL;756757if (pssid->SsidLength == req_ssid->ssid_len758&& _rtw_memcmp(pssid->Ssid, req_ssid->ssid, req_ssid->ssid_len) == _TRUE)759goto exit;760761wpsie = rtw_get_wps_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_762, pnetwork->network.IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);763if (wpsie && wpsielen > 0)764psr = rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_SELECTED_REGISTRAR, &sr, NULL);765766if (psr && sr) {767if (0)768RTW_INFO("clear sr of non target bss:%s("MAC_FMT")\n"769, pssid->Ssid, MAC_ARG(pnetwork->network.MacAddress));770*psr = 0; /* clear sr */771ret = 1;772}773774exit:775return ret;776}777778#define MAX_BSSINFO_LEN 1000779struct cfg80211_bss *rtw_cfg80211_inform_bss(_adapter *padapter, struct wlan_network *pnetwork)780{781struct ieee80211_channel *notify_channel;782struct cfg80211_bss *bss = NULL;783/* struct ieee80211_supported_band *band; */784u16 channel;785u32 freq;786u64 notify_timestamp;787u16 notify_capability;788u16 notify_interval;789u8 *notify_ie;790size_t notify_ielen;791s32 notify_signal;792/* u8 buf[MAX_BSSINFO_LEN]; */793794u8 *pbuf;795size_t buf_size = MAX_BSSINFO_LEN;796size_t len, bssinf_len = 0;797struct rtw_ieee80211_hdr *pwlanhdr;798unsigned short *fctrl;799u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};800801struct wireless_dev *wdev = padapter->rtw_wdev;802struct wiphy *wiphy = wdev->wiphy;803struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);804805pbuf = rtw_zmalloc(buf_size);806if (pbuf == NULL) {807RTW_INFO("%s pbuf allocate failed !!\n", __FUNCTION__);808return bss;809}810811/* RTW_INFO("%s\n", __func__); */812813bssinf_len = pnetwork->network.IELength + sizeof(struct rtw_ieee80211_hdr_3addr);814if (bssinf_len > buf_size) {815RTW_INFO("%s IE Length too long > %zu byte\n", __FUNCTION__, buf_size);816goto exit;817}818819#ifndef CONFIG_WAPI_SUPPORT820{821u16 wapi_len = 0;822823if (rtw_get_wapi_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &wapi_len) > 0) {824if (wapi_len > 0) {825RTW_INFO("%s, no support wapi!\n", __FUNCTION__);826goto exit;827}828}829}830#endif /* !CONFIG_WAPI_SUPPORT */831832channel = pnetwork->network.Configuration.DSConfig;833freq = rtw_ch2freq(channel);834notify_channel = ieee80211_get_channel(wiphy, freq);835836if (0)837notify_timestamp = le64_to_cpu(*(u64 *)rtw_get_timestampe_from_ie(pnetwork->network.IEs));838else839notify_timestamp = rtw_get_systime_us();840841notify_interval = le16_to_cpu(*(u16 *)rtw_get_beacon_interval_from_ie(pnetwork->network.IEs));842notify_capability = le16_to_cpu(*(u16 *)rtw_get_capability_from_ie(pnetwork->network.IEs));843844notify_ie = pnetwork->network.IEs + _FIXED_IE_LENGTH_;845notify_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;846847/* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm) */848if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&849is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {850notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */851} else {852notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength); /* dbm */853}854855#if 0856RTW_INFO("bssid: "MAC_FMT"\n", MAC_ARG(pnetwork->network.MacAddress));857RTW_INFO("Channel: %d(%d)\n", channel, freq);858RTW_INFO("Capability: %X\n", notify_capability);859RTW_INFO("Beacon interval: %d\n", notify_interval);860RTW_INFO("Signal: %d\n", notify_signal);861RTW_INFO("notify_timestamp: %llu\n", notify_timestamp);862#endif863864/* pbuf = buf; */865866pwlanhdr = (struct rtw_ieee80211_hdr *)pbuf;867fctrl = &(pwlanhdr->frame_ctl);868*(fctrl) = 0;869870SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);871/* pmlmeext->mgnt_seq++; */872873if (pnetwork->network.Reserved[0] == BSS_TYPE_BCN) { /* WIFI_BEACON */874_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);875set_frame_sub_type(pbuf, WIFI_BEACON);876} else {877_rtw_memcpy(pwlanhdr->addr1, adapter_mac_addr(padapter), ETH_ALEN);878set_frame_sub_type(pbuf, WIFI_PROBERSP);879}880881_rtw_memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);882_rtw_memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);883884885/* pbuf += sizeof(struct rtw_ieee80211_hdr_3addr); */886len = sizeof(struct rtw_ieee80211_hdr_3addr);887_rtw_memcpy((pbuf + len), pnetwork->network.IEs, pnetwork->network.IELength);888*((u64 *)(pbuf + len)) = cpu_to_le64(notify_timestamp);889890len += pnetwork->network.IELength;891892#if defined(CONFIG_P2P) && 0893if(rtw_get_p2p_ie(pnetwork->network.IEs+12, pnetwork->network.IELength-12, NULL, NULL))894RTW_INFO("%s, got p2p_ie\n", __func__);895#endif896897#if 1898bss = cfg80211_inform_bss_frame(wiphy, notify_channel, (struct ieee80211_mgmt *)pbuf,899len, notify_signal, GFP_ATOMIC);900#else901902bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)pnetwork->network.MacAddress,903notify_timestamp, notify_capability, notify_interval, notify_ie,904notify_ielen, notify_signal, GFP_ATOMIC/*GFP_KERNEL*/);905#endif906907if (unlikely(!bss)) {908RTW_INFO(FUNC_ADPT_FMT" bss NULL\n", FUNC_ADPT_ARG(padapter));909goto exit;910}911912#ifdef CONFIG_NET_NS913wiphy->flags |= WIPHY_FLAG_NETNS_OK;914#endif //CONFIG_NET_NS915916#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38))917#ifndef COMPAT_KERNEL_RELEASE918/* patch for cfg80211, update beacon ies to information_elements */919if (pnetwork->network.Reserved[0] == BSS_TYPE_BCN) { /* WIFI_BEACON */920921if (bss->len_information_elements != bss->len_beacon_ies) {922bss->information_elements = bss->beacon_ies;923bss->len_information_elements = bss->len_beacon_ies;924}925}926#endif /* COMPAT_KERNEL_RELEASE */927#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) */928929#if 0930{931if (bss->information_elements == bss->proberesp_ies) {932if (bss->len_information_elements != bss->len_proberesp_ies)933RTW_INFO("error!, len_information_elements != bss->len_proberesp_ies\n");934} else if (bss->len_information_elements < bss->len_beacon_ies) {935bss->information_elements = bss->beacon_ies;936bss->len_information_elements = bss->len_beacon_ies;937}938}939#endif940#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)941cfg80211_put_bss(wiphy, bss);942#else943cfg80211_put_bss(bss);944#endif945946exit:947if (pbuf)948rtw_mfree(pbuf, buf_size);949return bss;950951}952953/*954Check the given bss is valid by kernel API cfg80211_get_bss()955@padapter : the given adapter956957return _TRUE if bss is valid, _FALSE for not found.958*/959int rtw_cfg80211_check_bss(_adapter *padapter)960{961WLAN_BSSID_EX *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);962struct cfg80211_bss *bss = NULL;963struct ieee80211_channel *notify_channel = NULL;964u32 freq;965966if (!(pnetwork) || !(padapter->rtw_wdev))967return _FALSE;968969freq = rtw_ch2freq(pnetwork->Configuration.DSConfig);970notify_channel = ieee80211_get_channel(padapter->rtw_wdev->wiphy, freq);971bss = cfg80211_get_bss(padapter->rtw_wdev->wiphy, notify_channel,972pnetwork->MacAddress, pnetwork->Ssid.Ssid,973pnetwork->Ssid.SsidLength,974#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)975pnetwork->InfrastructureMode == Ndis802_11Infrastructure?IEEE80211_BSS_TYPE_ESS:IEEE80211_BSS_TYPE_IBSS,976IEEE80211_PRIVACY(pnetwork->Privacy));977#else978pnetwork->InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS, pnetwork->InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS);979#endif980981#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)982cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);983#else984cfg80211_put_bss(bss);985#endif986987return bss != NULL;988}989990void rtw_cfg80211_ibss_indicate_connect(_adapter *padapter)991{992struct mlme_priv *pmlmepriv = &padapter->mlmepriv;993struct wlan_network *cur_network = &(pmlmepriv->cur_network);994struct wireless_dev *pwdev = padapter->rtw_wdev;995#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))996struct wiphy *wiphy = pwdev->wiphy;997int freq = 2412;998struct ieee80211_channel *notify_channel;999#endif10001001RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));10021003if (pwdev->iftype != NL80211_IFTYPE_ADHOC)1004return;10051006if (!rtw_cfg80211_check_bss(padapter)) {1007WLAN_BSSID_EX *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);1008struct wlan_network *scanned = pmlmepriv->cur_network_scanned;10091010if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) {10111012_rtw_memcpy(&cur_network->network, pnetwork, sizeof(WLAN_BSSID_EX));1013if (cur_network) {1014if (!rtw_cfg80211_inform_bss(padapter, cur_network))1015RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));1016else1017RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter));1018} else {1019RTW_INFO("cur_network is not exist!!!\n");1020return ;1021}1022} else {1023if (scanned == NULL)1024rtw_warn_on(1);10251026if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE1027&& _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE1028) {1029if (!rtw_cfg80211_inform_bss(padapter, scanned))1030RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));1031else {1032/* RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter)); */1033}1034} else {1035RTW_INFO("scanned & pnetwork compare fail\n");1036rtw_warn_on(1);1037}1038}10391040if (!rtw_cfg80211_check_bss(padapter))1041RTW_PRINT(FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter));1042}1043/* notify cfg80211 that device joined an IBSS */1044#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))1045freq = rtw_ch2freq(cur_network->network.Configuration.DSConfig);1046if (1)1047RTW_INFO("chan: %d, freq: %d\n", cur_network->network.Configuration.DSConfig, freq);1048notify_channel = ieee80211_get_channel(wiphy, freq);1049cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, notify_channel, GFP_ATOMIC);1050#else1051cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, GFP_ATOMIC);1052#endif1053}10541055void rtw_cfg80211_indicate_connect(_adapter *padapter)1056{1057struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1058struct wlan_network *cur_network = &(pmlmepriv->cur_network);1059struct wireless_dev *pwdev = padapter->rtw_wdev;1060struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);1061_irqL irqL;1062#ifdef CONFIG_P2P1063struct wifidirect_info *pwdinfo = &(padapter->wdinfo);1064#endif1065#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)1066struct cfg80211_roam_info roam_info ={};1067#endif10681069RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));1070if (pwdev->iftype != NL80211_IFTYPE_STATION1071#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1072&& pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT1073#endif1074)1075return;10761077if (!MLME_IS_STA(padapter))1078return;10791080#ifdef CONFIG_P2P1081if (pwdinfo->driver_interface == DRIVER_CFG80211) {1082#if !RTW_P2P_GROUP_INTERFACE1083if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {1084rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));1085rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);1086rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);1087RTW_INFO("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));1088}1089#endif1090}1091#endif /* CONFIG_P2P */10921093if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != _TRUE) {1094WLAN_BSSID_EX *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);1095struct wlan_network *scanned = pmlmepriv->cur_network_scanned;10961097/* RTW_INFO(FUNC_ADPT_FMT" BSS not found\n", FUNC_ADPT_ARG(padapter)); */10981099if (scanned == NULL) {1100rtw_warn_on(1);1101goto check_bss;1102}11031104if (_rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE1105&& _rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE1106) {1107if (!rtw_cfg80211_inform_bss(padapter, scanned))1108RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));1109else {1110/* RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter)); */1111}1112} else {1113RTW_INFO("scanned: %s("MAC_FMT"), cur: %s("MAC_FMT")\n",1114scanned->network.Ssid.Ssid, MAC_ARG(scanned->network.MacAddress),1115pnetwork->Ssid.Ssid, MAC_ARG(pnetwork->MacAddress)1116);1117rtw_warn_on(1);1118}1119}11201121check_bss:1122if (!rtw_cfg80211_check_bss(padapter))1123RTW_PRINT(FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter));11241125_enter_critical_bh(&pwdev_priv->connect_req_lock, &irqL);11261127if (rtw_to_roam(padapter) > 0) {1128#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)1129struct wiphy *wiphy = pwdev->wiphy;1130struct ieee80211_channel *notify_channel;1131u32 freq;1132u16 channel = cur_network->network.Configuration.DSConfig;11331134freq = rtw_ch2freq(channel);1135notify_channel = ieee80211_get_channel(wiphy, freq);1136#endif11371138#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)1139#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0))1140roam_info.links[0].bssid = cur_network->network.MacAddress;1141#else1142roam_info.bssid = cur_network->network.MacAddress;1143#endif1144roam_info.req_ie = pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 2;1145roam_info.req_ie_len = pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 2;1146roam_info.resp_ie = pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6;1147roam_info.resp_ie_len = pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6;11481149cfg80211_roamed(padapter->pnetdev, &roam_info, GFP_ATOMIC);1150#else1151cfg80211_roamed(padapter->pnetdev1152#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)1153, notify_channel1154#endif1155, cur_network->network.MacAddress1156, pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 21157, pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 21158, pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 61159, pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 61160, GFP_ATOMIC);1161#endif /*LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)*/11621163RTW_INFO(FUNC_ADPT_FMT" call cfg80211_roamed\n", FUNC_ADPT_ARG(padapter));11641165#ifdef CONFIG_RTW_80211R1166if (rtw_ft_roam(padapter))1167rtw_ft_set_status(padapter, RTW_FT_ASSOCIATED_STA);1168#endif1169} else {1170#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)1171RTW_INFO("pwdev->sme_state(b)=%d\n", pwdev->sme_state);1172#endif11731174if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != _TRUE)1175rtw_cfg80211_connect_result(pwdev, cur_network->network.MacAddress1176, pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 21177, pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 21178, pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 61179, pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 61180, WLAN_STATUS_SUCCESS, GFP_ATOMIC);1181#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)1182RTW_INFO("pwdev->sme_state(a)=%d\n", pwdev->sme_state);1183#endif1184}11851186rtw_wdev_free_connect_req(pwdev_priv);11871188_exit_critical_bh(&pwdev_priv->connect_req_lock, &irqL);1189}11901191void rtw_cfg80211_indicate_disconnect(_adapter *padapter, u16 reason, u8 locally_generated)1192{1193struct wireless_dev *pwdev = padapter->rtw_wdev;1194struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);1195_irqL irqL;1196#ifdef CONFIG_P2P1197struct wifidirect_info *pwdinfo = &(padapter->wdinfo);1198#endif11991200RTW_INFO(FUNC_ADPT_FMT" ,reason = %d\n", FUNC_ADPT_ARG(padapter), reason);12011202/*always replace privated definitions with wifi reserved value 0*/1203if (WLAN_REASON_IS_PRIVATE(reason))1204reason = 0;12051206if (pwdev->iftype != NL80211_IFTYPE_STATION1207#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1208&& pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT1209#endif1210)1211return;12121213if (!MLME_IS_STA(padapter))1214return;12151216#ifdef CONFIG_P2P1217if (pwdinfo->driver_interface == DRIVER_CFG80211) {1218if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {1219rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));12201221#if RTW_P2P_GROUP_INTERFACE1222#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1223if (pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)1224#endif1225#endif1226rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);12271228RTW_INFO("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));1229}1230}1231#endif /* CONFIG_P2P */12321233_enter_critical_bh(&pwdev_priv->connect_req_lock, &irqL);12341235if (padapter->ndev_unregistering || !rtw_wdev_not_indic_disco(pwdev_priv)) {1236#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)1237RTW_INFO("pwdev->sme_state(b)=%d\n", pwdev->sme_state);12381239if (pwdev->sme_state == CFG80211_SME_CONNECTING) {1240RTW_INFO(FUNC_ADPT_FMT" call cfg80211_connect_result, reason:%d\n", FUNC_ADPT_ARG(padapter), reason);1241rtw_cfg80211_connect_result(pwdev, NULL, NULL, 0, NULL, 0,1242reason?reason:WLAN_STATUS_UNSPECIFIED_FAILURE,1243GFP_ATOMIC);1244} else if (pwdev->sme_state == CFG80211_SME_CONNECTED) {1245RTW_INFO(FUNC_ADPT_FMT" call cfg80211_disconnected, reason:%d\n", FUNC_ADPT_ARG(padapter), reason);1246rtw_cfg80211_disconnected(pwdev, reason, NULL, 0, locally_generated, GFP_ATOMIC);1247}12481249RTW_INFO("pwdev->sme_state(a)=%d\n", pwdev->sme_state);1250#else1251if (pwdev_priv->connect_req) {1252RTW_INFO(FUNC_ADPT_FMT" call cfg80211_connect_result, reason:%d\n", FUNC_ADPT_ARG(padapter), reason);1253rtw_cfg80211_connect_result(pwdev, NULL, NULL, 0, NULL, 0,1254reason?reason:WLAN_STATUS_UNSPECIFIED_FAILURE,1255GFP_ATOMIC);1256} else {1257RTW_INFO(FUNC_ADPT_FMT" call cfg80211_disconnected, reason:%d\n", FUNC_ADPT_ARG(padapter), reason);1258rtw_cfg80211_disconnected(pwdev, reason, NULL, 0, locally_generated, GFP_ATOMIC);12591260cfg80211_connect_result(padapter->pnetdev, NULL, NULL, 0, NULL, 0,1261WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC);1262}1263#endif1264}12651266rtw_wdev_free_connect_req(pwdev_priv);12671268_exit_critical_bh(&pwdev_priv->connect_req_lock, &irqL);1269}127012711272#ifdef CONFIG_AP_MODE1273static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_param *param)1274{1275int ret = 0;1276u32 wep_key_idx, wep_key_len;1277struct sta_info *psta = NULL, *pbcmc_sta = NULL;1278_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);1279struct security_priv *psecuritypriv = &(padapter->securitypriv);1280struct sta_priv *pstapriv = &padapter->stapriv;12811282RTW_INFO("%s\n", __FUNCTION__);12831284param->u.crypt.err = 0;1285param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';12861287if (is_broadcast_mac_addr(param->sta_addr)) {1288if (param->u.crypt.idx >= WEP_KEYS1289#ifdef CONFIG_IEEE80211W1290&& param->u.crypt.idx > BIP_MAX_KEYID1291#endif1292) {1293ret = -EINVAL;1294goto exit;1295}1296} else {1297psta = rtw_get_stainfo(pstapriv, param->sta_addr);1298if (!psta) {1299ret = -EINVAL;1300RTW_INFO(FUNC_ADPT_FMT", sta "MAC_FMT" not found\n"1301, FUNC_ADPT_ARG(padapter), MAC_ARG(param->sta_addr));1302goto exit;1303}1304}13051306if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {1307/* todo:clear default encryption keys */13081309RTW_INFO("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);13101311goto exit;1312}131313141315if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {1316RTW_INFO("r871x_set_encryption, crypt.alg = WEP\n");13171318wep_key_idx = param->u.crypt.idx;1319wep_key_len = param->u.crypt.key_len;13201321RTW_INFO("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);13221323if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {1324ret = -EINVAL;1325goto exit;1326}13271328if (wep_key_len > 0)1329wep_key_len = wep_key_len <= 5 ? 5 : 13;13301331if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {1332/* wep default key has not been set, so use this key index as default key. */13331334psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;1335psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;1336psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;1337psecuritypriv->dot118021XGrpPrivacy = _WEP40_;13381339if (wep_key_len == 13) {1340psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;1341psecuritypriv->dot118021XGrpPrivacy = _WEP104_;1342}13431344psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;1345}13461347_rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);13481349psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;13501351rtw_ap_set_wep_key(padapter, param->u.crypt.key, wep_key_len, wep_key_idx, 1);13521353goto exit;13541355}13561357if (!psta) { /* group key */1358if (param->u.crypt.set_tx == 0) { /* group key, TX only */1359if (strcmp(param->u.crypt.alg, "WEP") == 0) {1360RTW_INFO(FUNC_ADPT_FMT" set WEP TX GTK idx:%u, len:%u\n"1361, FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);1362_rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));1363psecuritypriv->dot118021XGrpPrivacy = _WEP40_;1364if (param->u.crypt.key_len == 13)1365psecuritypriv->dot118021XGrpPrivacy = _WEP104_;13661367} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {1368RTW_INFO(FUNC_ADPT_FMT" set TKIP TX GTK idx:%u, len:%u\n"1369, FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);1370psecuritypriv->dot118021XGrpPrivacy = _TKIP_;1371_rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));1372/* set mic key */1373_rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);1374_rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);1375psecuritypriv->busetkipkey = _TRUE;13761377} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {1378RTW_INFO(FUNC_ADPT_FMT" set CCMP TX GTK idx:%u, len:%u\n"1379, FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);1380psecuritypriv->dot118021XGrpPrivacy = _AES_;1381_rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));13821383#ifdef CONFIG_IEEE80211W1384} else if (strcmp(param->u.crypt.alg, "BIP") == 0) {1385RTW_INFO(FUNC_ADPT_FMT" set TX IGTK idx:%u, len:%u\n"1386, FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);1387_rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));1388padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;1389psecuritypriv->dot11wBIPtxpn.val = RTW_GET_LE64(param->u.crypt.seq);1390padapter->securitypriv.binstallBIPkey = _TRUE;1391goto exit;1392#endif /* CONFIG_IEEE80211W */13931394} else if (strcmp(param->u.crypt.alg, "none") == 0) {1395RTW_INFO(FUNC_ADPT_FMT" clear group key, idx:%u\n"1396, FUNC_ADPT_ARG(padapter), param->u.crypt.idx);1397psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;1398} else {1399RTW_WARN(FUNC_ADPT_FMT" set group key, not support\n"1400, FUNC_ADPT_ARG(padapter));1401goto exit;1402}14031404psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;1405pbcmc_sta = rtw_get_bcmc_stainfo(padapter);1406if (pbcmc_sta) {1407pbcmc_sta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);1408pbcmc_sta->ieee8021x_blocked = _FALSE;1409pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy */1410}1411psecuritypriv->binstallGrpkey = _TRUE;1412psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */14131414rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);1415}14161417goto exit;14181419}14201421if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */1422if (param->u.crypt.set_tx == 1) {1423/* pairwise key */1424_rtw_memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));14251426if (strcmp(param->u.crypt.alg, "WEP") == 0) {1427RTW_INFO(FUNC_ADPT_FMT" set WEP PTK of "MAC_FMT" idx:%u, len:%u\n"1428, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)1429, param->u.crypt.idx, param->u.crypt.key_len);1430psta->dot118021XPrivacy = _WEP40_;1431if (param->u.crypt.key_len == 13)1432psta->dot118021XPrivacy = _WEP104_;14331434} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {1435RTW_INFO(FUNC_ADPT_FMT" set TKIP PTK of "MAC_FMT" idx:%u, len:%u\n"1436, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)1437, param->u.crypt.idx, param->u.crypt.key_len);1438psta->dot118021XPrivacy = _TKIP_;1439/* set mic key */1440_rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);1441_rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);1442psecuritypriv->busetkipkey = _TRUE;14431444} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {1445RTW_INFO(FUNC_ADPT_FMT" set CCMP PTK of "MAC_FMT" idx:%u, len:%u\n"1446, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)1447, param->u.crypt.idx, param->u.crypt.key_len);1448psta->dot118021XPrivacy = _AES_;14491450} else if (strcmp(param->u.crypt.alg, "none") == 0) {1451RTW_INFO(FUNC_ADPT_FMT" clear pairwise key of "MAC_FMT" idx:%u\n"1452, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)1453, param->u.crypt.idx);1454psta->dot118021XPrivacy = _NO_PRIVACY_;1455} else {1456RTW_WARN(FUNC_ADPT_FMT" set pairwise key of "MAC_FMT", not support\n"1457, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));1458goto exit;1459}14601461psta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);1462psta->dot11rxpn.val = RTW_GET_LE64(param->u.crypt.seq);1463psta->ieee8021x_blocked = _FALSE;14641465if (psta->dot118021XPrivacy != _NO_PRIVACY_) {1466psta->bpairwise_key_installed = _TRUE;14671468/* WPA2 key-handshake has completed */1469if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK)1470psta->state &= (~WIFI_UNDER_KEY_HANDSHAKE);1471}14721473rtw_ap_set_pairwise_key(padapter, psta);1474} else {1475/* peer's group key, RX only */1476#ifdef CONFIG_RTW_MESH1477if (strcmp(param->u.crypt.alg, "CCMP") == 0) {1478RTW_INFO(FUNC_ADPT_FMT" set CCMP GTK of "MAC_FMT", idx:%u, len:%u\n"1479, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)1480, param->u.crypt.idx, param->u.crypt.key_len);1481psta->group_privacy = _AES_;1482_rtw_memcpy(psta->gtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));1483psta->gtk_bmp |= BIT(param->u.crypt.idx);1484psta->gtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);14851486#ifdef CONFIG_IEEE80211W1487} else if (strcmp(param->u.crypt.alg, "BIP") == 0) {1488RTW_INFO(FUNC_ADPT_FMT" set IGTK of "MAC_FMT", idx:%u, len:%u\n"1489, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)1490, param->u.crypt.idx, param->u.crypt.key_len);1491_rtw_memcpy(psta->igtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));1492psta->igtk_bmp |= BIT(param->u.crypt.idx);1493psta->igtk_id = param->u.crypt.idx;1494psta->igtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);1495goto exit;1496#endif /* CONFIG_IEEE80211W */14971498} else if (strcmp(param->u.crypt.alg, "none") == 0) {1499RTW_INFO(FUNC_ADPT_FMT" clear group key of "MAC_FMT", idx:%u\n"1500, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)1501, param->u.crypt.idx);1502psta->group_privacy = _NO_PRIVACY_;1503psta->gtk_bmp &= ~BIT(param->u.crypt.idx);1504} else1505#endif /* CONFIG_RTW_MESH */1506{1507RTW_WARN(FUNC_ADPT_FMT" set group key of "MAC_FMT", not support\n"1508, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));1509goto exit;1510}15111512#ifdef CONFIG_RTW_MESH1513rtw_ap_set_sta_key(padapter, psta->cmn.mac_addr, psta->group_privacy1514, param->u.crypt.key, param->u.crypt.idx, 1);1515#endif1516}15171518}15191520exit:1521return ret;1522}1523#endif /* CONFIG_AP_MODE */15241525static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param)1526{1527int ret = 0;1528u32 wep_key_idx, wep_key_len;1529_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);1530struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1531struct security_priv *psecuritypriv = &padapter->securitypriv;1532#ifdef CONFIG_P2P1533struct wifidirect_info *pwdinfo = &padapter->wdinfo;1534#endif /* CONFIG_P2P */15351536RTW_INFO("%s\n", __func__);15371538param->u.crypt.err = 0;1539param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';15401541if (is_broadcast_mac_addr(param->sta_addr)) {1542if (param->u.crypt.idx >= WEP_KEYS1543#ifdef CONFIG_IEEE80211W1544&& param->u.crypt.idx > BIP_MAX_KEYID1545#endif1546) {1547ret = -EINVAL;1548goto exit;1549}1550} else {1551#ifdef CONFIG_WAPI_SUPPORT1552if (strcmp(param->u.crypt.alg, "SMS4"))1553#endif1554{1555ret = -EINVAL;1556goto exit;1557}1558}15591560if (strcmp(param->u.crypt.alg, "WEP") == 0) {1561RTW_INFO("wpa_set_encryption, crypt.alg = WEP\n");15621563wep_key_idx = param->u.crypt.idx;1564wep_key_len = param->u.crypt.key_len;15651566if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {1567ret = -EINVAL;1568goto exit;1569}15701571if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {1572/* wep default key has not been set, so use this key index as default key. */15731574wep_key_len = wep_key_len <= 5 ? 5 : 13;15751576psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;1577psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;1578psecuritypriv->dot118021XGrpPrivacy = _WEP40_;15791580if (wep_key_len == 13) {1581psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;1582psecuritypriv->dot118021XGrpPrivacy = _WEP104_;1583}15841585psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;1586}15871588_rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);15891590psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;15911592rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, _TRUE);15931594goto exit;1595}15961597if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */1598struct sta_info *psta, *pbcmc_sta;1599struct sta_priv *pstapriv = &padapter->stapriv;16001601/* RTW_INFO("%s, : dot11AuthAlgrthm == dot11AuthAlgrthm_8021X\n", __func__); */16021603if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == _TRUE) { /* sta mode */1604#ifdef CONFIG_RTW_80211R1605if (rtw_ft_roam(padapter))1606psta = rtw_get_stainfo(pstapriv, pmlmepriv->assoc_bssid);1607else1608#endif1609psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));1610if (psta == NULL) {1611/* DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail\n")); */1612RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);1613} else {1614/* Jeff: don't disable ieee8021x_blocked while clearing key */1615if (strcmp(param->u.crypt.alg, "none") != 0)1616psta->ieee8021x_blocked = _FALSE;16171618if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||1619(padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))1620psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;16211622if (param->u.crypt.set_tx == 1) { /* pairwise key */1623RTW_INFO(FUNC_ADPT_FMT" set %s PTK idx:%u, len:%u\n"1624, FUNC_ADPT_ARG(padapter), param->u.crypt.alg, param->u.crypt.idx, param->u.crypt.key_len);1625_rtw_memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));1626if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */1627_rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);1628_rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);1629padapter->securitypriv.busetkipkey = _FALSE;1630}1631psta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);1632psta->dot11rxpn.val = RTW_GET_LE64(param->u.crypt.seq);1633psta->bpairwise_key_installed = _TRUE;1634#ifdef CONFIG_RTW_80211R1635psta->ft_pairwise_key_installed = _TRUE;1636#endif1637rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _TRUE);16381639} else { /* group key */1640if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {1641RTW_INFO(FUNC_ADPT_FMT" set %s GTK idx:%u, len:%u\n"1642, FUNC_ADPT_ARG(padapter), param->u.crypt.alg, param->u.crypt.idx, param->u.crypt.key_len);1643_rtw_memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key,1644(param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));1645_rtw_memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);1646_rtw_memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);1647padapter->securitypriv.binstallGrpkey = _TRUE;1648if (param->u.crypt.idx < 4)1649_rtw_memcpy(padapter->securitypriv.iv_seq[param->u.crypt.idx], param->u.crypt.seq, 8);1650padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;1651rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, _TRUE);16521653#ifdef CONFIG_IEEE80211W1654} else if (strcmp(param->u.crypt.alg, "BIP") == 0) {1655RTW_INFO(FUNC_ADPT_FMT" set IGTK idx:%u, len:%u\n"1656, FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);1657_rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key,1658(param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));1659psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;1660psecuritypriv->dot11wBIPrxpn.val = RTW_GET_LE64(param->u.crypt.seq);1661psecuritypriv->binstallBIPkey = _TRUE;1662#endif /* CONFIG_IEEE80211W */16631664}16651666#ifdef CONFIG_P2P1667if (pwdinfo->driver_interface == DRIVER_CFG80211) {1668if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))1669rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);1670}1671#endif /* CONFIG_P2P */16721673/* WPA/WPA2 key-handshake has completed */1674clr_fwstate(pmlmepriv, WIFI_UNDER_KEY_HANDSHAKE);16751676}1677}16781679pbcmc_sta = rtw_get_bcmc_stainfo(padapter);1680if (pbcmc_sta == NULL) {1681/* DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */1682} else {1683/* Jeff: don't disable ieee8021x_blocked while clearing key */1684if (strcmp(param->u.crypt.alg, "none") != 0)1685pbcmc_sta->ieee8021x_blocked = _FALSE;16861687if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||1688(padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))1689pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;1690}1691} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */1692}1693}16941695#ifdef CONFIG_WAPI_SUPPORT1696if (strcmp(param->u.crypt.alg, "SMS4") == 0)1697rtw_wapi_set_set_encryption(padapter, param);1698#endif16991700exit:17011702RTW_INFO("%s, ret=%d\n", __func__, ret);170317041705return ret;1706}17071708static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev1709#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))1710, int link_id1711#endif1712, u8 key_index1713#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1714, bool pairwise1715#endif1716, const u8 *mac_addr, struct key_params *params)1717{1718char *alg_name;1719u32 param_len;1720struct ieee_param *param = NULL;1721int ret = 0;1722_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);1723struct wireless_dev *rtw_wdev = padapter->rtw_wdev;1724struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1725#ifdef CONFIG_TDLS1726struct sta_info *ptdls_sta;1727#endif /* CONFIG_TDLS */17281729if (mac_addr)1730RTW_INFO(FUNC_NDEV_FMT" adding key for %pM\n", FUNC_NDEV_ARG(ndev), mac_addr);1731RTW_INFO(FUNC_NDEV_FMT" cipher=0x%x\n", FUNC_NDEV_ARG(ndev), params->cipher);1732RTW_INFO(FUNC_NDEV_FMT" key_len=%d, key_index=%d\n", FUNC_NDEV_ARG(ndev), params->key_len, key_index);1733#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1734RTW_INFO(FUNC_NDEV_FMT" pairwise=%d\n", FUNC_NDEV_ARG(ndev), pairwise);1735#endif17361737if (rtw_cfg80211_sync_iftype(padapter) != _SUCCESS) {1738ret = -ENOTSUPP;1739goto addkey_end;1740}17411742param_len = sizeof(struct ieee_param) + params->key_len;1743param = rtw_malloc(param_len);1744if (param == NULL)1745return -1;17461747_rtw_memset(param, 0, param_len);17481749param->cmd = IEEE_CMD_SET_ENCRYPTION;1750_rtw_memset(param->sta_addr, 0xff, ETH_ALEN);17511752switch (params->cipher) {1753case IW_AUTH_CIPHER_NONE:1754/* todo: remove key */1755/* remove = 1; */1756alg_name = "none";1757break;1758case WLAN_CIPHER_SUITE_WEP40:1759case WLAN_CIPHER_SUITE_WEP104:1760alg_name = "WEP";1761break;1762case WLAN_CIPHER_SUITE_TKIP:1763alg_name = "TKIP";1764break;1765case WLAN_CIPHER_SUITE_CCMP:1766alg_name = "CCMP";1767break;1768#ifdef CONFIG_IEEE80211W1769case WLAN_CIPHER_SUITE_AES_CMAC:1770alg_name = "BIP";1771break;1772#endif /* CONFIG_IEEE80211W */1773#ifdef CONFIG_WAPI_SUPPORT1774case WLAN_CIPHER_SUITE_SMS4:1775alg_name = "SMS4";1776if (pairwise == NL80211_KEYTYPE_PAIRWISE) {1777if (key_index != 0 && key_index != 1) {1778ret = -ENOTSUPP;1779goto addkey_end;1780}1781_rtw_memcpy((void *)param->sta_addr, (void *)mac_addr, ETH_ALEN);1782} else1783RTW_INFO("mac_addr is null\n");1784RTW_INFO("rtw_wx_set_enc_ext: SMS4 case\n");1785break;1786#endif17871788default:1789ret = -ENOTSUPP;1790goto addkey_end;1791}17921793strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);179417951796if (!mac_addr || is_broadcast_ether_addr(mac_addr)1797#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1798|| !pairwise1799#endif1800) {1801param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */1802} else {1803param->u.crypt.set_tx = 1; /* for wpa/wpa2 pairwise key */1804}18051806param->u.crypt.idx = key_index;18071808if (params->seq_len && params->seq) {1809_rtw_memcpy(param->u.crypt.seq, (u8 *)params->seq, params->seq_len);1810RTW_INFO(FUNC_NDEV_FMT" seq_len:%u, seq:0x%llx\n", FUNC_NDEV_ARG(ndev)1811, params->seq_len, RTW_GET_LE64(param->u.crypt.seq));1812}18131814if (params->key_len && params->key) {1815param->u.crypt.key_len = params->key_len;1816_rtw_memcpy(param->u.crypt.key, (u8 *)params->key, params->key_len);1817}18181819if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) {1820#ifdef CONFIG_TDLS1821if (rtw_tdls_is_driver_setup(padapter) == _FALSE && mac_addr) {1822ptdls_sta = rtw_get_stainfo(&padapter->stapriv, (void *)mac_addr);1823if (ptdls_sta != NULL && ptdls_sta->tdls_sta_state) {1824_rtw_memcpy(ptdls_sta->tpk.tk, params->key, params->key_len);1825rtw_tdls_set_key(padapter, ptdls_sta);1826goto addkey_end;1827}1828}1829#endif /* CONFIG_TDLS */1830ret = rtw_cfg80211_set_encryption(ndev, param);1831} else if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {1832#ifdef CONFIG_AP_MODE1833if (mac_addr)1834_rtw_memcpy(param->sta_addr, (void *)mac_addr, ETH_ALEN);18351836ret = rtw_cfg80211_ap_set_encryption(ndev, param);1837#endif1838} else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE1839|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE1840) {1841/* RTW_INFO("@@@@@@@@@@ fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype); */1842ret = rtw_cfg80211_set_encryption(ndev, param);1843} else1844RTW_INFO("error! fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype);184518461847addkey_end:1848if (param)1849rtw_mfree(param, param_len);18501851return ret;18521853}18541855static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev1856#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))1857, int link_id1858#endif1859, u8 keyid1860#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1861, bool pairwise1862#endif1863, const u8 *mac_addr, void *cookie1864, void (*callback)(void *cookie, struct key_params *))1865{1866#define GET_KEY_PARAM_FMT_S " keyid=%d"1867#define GET_KEY_PARAM_ARG_S , keyid1868#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1869#define GET_KEY_PARAM_FMT_2_6_37 ", pairwise=%d"1870#define GET_KEY_PARAM_ARG_2_6_37 , pairwise1871#else1872#define GET_KEY_PARAM_FMT_2_6_37 ""1873#define GET_KEY_PARAM_ARG_2_6_371874#endif1875#define GET_KEY_PARAM_FMT_E ", addr=%pM"1876#define GET_KEY_PARAM_ARG_E , mac_addr18771878_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);1879struct security_priv *sec = &adapter->securitypriv;1880struct sta_priv *stapriv = &adapter->stapriv;1881struct sta_info *sta = NULL;1882u32 cipher = _NO_PRIVACY_;1883union Keytype *key = NULL;1884u8 key_len = 0;1885u64 *pn = NULL;1886u8 pn_len = 0;1887u8 pn_val[8] = {0};18881889struct key_params params;1890int ret = -ENOENT;18911892if (keyid >= WEP_KEYS1893#ifdef CONFIG_IEEE80211W1894&& keyid > BIP_MAX_KEYID1895#endif1896)1897goto exit;18981899if (!mac_addr || is_broadcast_ether_addr(mac_addr)1900#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)1901|| (MLME_IS_STA(adapter) && !pairwise)1902#endif1903) {1904/* WEP key, TX GTK/IGTK, RX GTK/IGTK(for STA mode) */1905if (is_wep_enc(sec->dot118021XGrpPrivacy)) {1906if (keyid >= WEP_KEYS)1907goto exit;1908if (!(sec->key_mask & BIT(keyid)))1909goto exit;1910cipher = sec->dot118021XGrpPrivacy;1911key = &sec->dot11DefKey[keyid];1912} else {1913if (keyid < WEP_KEYS) {1914if (sec->binstallGrpkey != _TRUE)1915goto exit;1916cipher = sec->dot118021XGrpPrivacy;1917key = &sec->dot118021XGrpKey[keyid];1918sta = rtw_get_bcmc_stainfo(adapter);1919if (sta)1920pn = &sta->dot11txpn.val;1921#ifdef CONFIG_IEEE80211W1922} else if (keyid <= BIP_MAX_KEYID) {1923if (SEC_IS_BIP_KEY_INSTALLED(sec) != _TRUE)1924goto exit;1925cipher = _BIP_;1926key = &sec->dot11wBIPKey[keyid];1927pn = &sec->dot11wBIPtxpn.val;1928#endif1929}1930}1931} else {1932/* Pairwise key, RX GTK/IGTK for specific peer */1933sta = rtw_get_stainfo(stapriv, mac_addr);1934if (!sta)1935goto exit;19361937if (keyid < WEP_KEYS && pairwise) {1938if (sta->bpairwise_key_installed != _TRUE)1939goto exit;1940cipher = sta->dot118021XPrivacy;1941key = &sta->dot118021x_UncstKey;1942#ifdef CONFIG_RTW_MESH1943} else if (keyid < WEP_KEYS && !pairwise) {1944if (!(sta->gtk_bmp & BIT(keyid)))1945goto exit;1946cipher = sta->group_privacy;1947key = &sta->gtk;1948#ifdef CONFIG_IEEE80211W1949} else if (keyid <= BIP_MAX_KEYID && !pairwise) {1950if (!(sta->igtk_bmp & BIT(keyid)))1951goto exit;1952cipher = _BIP_;1953key = &sta->igtk;1954pn = &sta->igtk_pn.val;1955#endif1956#endif /* CONFIG_RTW_MESH */1957}1958}19591960if (!key)1961goto exit;19621963if (cipher == _WEP40_) {1964cipher = WLAN_CIPHER_SUITE_WEP40;1965key_len = sec->dot11DefKeylen[keyid];1966} else if (cipher == _WEP104_) {1967cipher = WLAN_CIPHER_SUITE_WEP104;1968key_len = sec->dot11DefKeylen[keyid];1969} else if (cipher == _TKIP_) {1970cipher = WLAN_CIPHER_SUITE_TKIP;1971key_len = 16;1972} else if (cipher == _AES_) {1973cipher = WLAN_CIPHER_SUITE_CCMP;1974key_len = 16;1975#ifdef CONFIG_IEEE80211W1976} else if (cipher == _BIP_) {1977cipher = WLAN_CIPHER_SUITE_AES_CMAC;1978key_len = 16;1979#endif1980} else {1981RTW_WARN(FUNC_NDEV_FMT" unknown cipher:%u\n", FUNC_NDEV_ARG(ndev), cipher);1982rtw_warn_on(1);1983goto exit;1984}19851986if (pn) {1987*((u64 *)pn_val) = cpu_to_le64(*pn);1988pn_len = 6;1989}19901991ret = 0;19921993exit:1994RTW_INFO(FUNC_NDEV_FMT1995GET_KEY_PARAM_FMT_S1996GET_KEY_PARAM_FMT_2_6_371997GET_KEY_PARAM_FMT_E1998" ret %d\n", FUNC_NDEV_ARG(ndev)1999GET_KEY_PARAM_ARG_S2000GET_KEY_PARAM_ARG_2_6_372001GET_KEY_PARAM_ARG_E2002, ret);2003if (pn)2004RTW_INFO(FUNC_NDEV_FMT " seq:0x%llx\n", FUNC_NDEV_ARG(ndev), *pn);20052006if (ret == 0) {2007_rtw_memset(¶ms, 0, sizeof(params));20082009params.cipher = cipher;2010params.key = key->skey;2011params.key_len = key_len;2012if (pn) {2013params.seq = pn_val;2014params.seq_len = pn_len;2015}20162017callback(cookie, ¶ms);2018}20192020return ret;2021}20222023static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,2024#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))2025int link_id,2026#endif2027#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)2028u8 key_index, bool pairwise, const u8 *mac_addr)2029#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */2030u8 key_index, const u8 *mac_addr)2031#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */2032{2033_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);2034struct security_priv *psecuritypriv = &padapter->securitypriv;20352036RTW_INFO(FUNC_NDEV_FMT" key_index=%d, addr=%pM\n", FUNC_NDEV_ARG(ndev), key_index, mac_addr);20372038if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {2039/* clear the flag of wep default key set. */2040psecuritypriv->bWepDefaultKeyIdxSet = 0;2041}20422043return 0;2044}20452046static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,2047struct net_device *ndev,2048#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))2049int link_id,2050#endif2051u8 key_index2052#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)2053, bool unicast, bool multicast2054#endif2055)2056{2057_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);2058struct security_priv *psecuritypriv = &padapter->securitypriv;20592060#define SET_DEF_KEY_PARAM_FMT " key_index=%d"2061#define SET_DEF_KEY_PARAM_ARG , key_index2062#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)2063#define SET_DEF_KEY_PARAM_FMT_2_6_38 ", unicast=%d, multicast=%d"2064#define SET_DEF_KEY_PARAM_ARG_2_6_38 , unicast, multicast2065#else2066#define SET_DEF_KEY_PARAM_FMT_2_6_38 ""2067#define SET_DEF_KEY_PARAM_ARG_2_6_382068#endif20692070RTW_INFO(FUNC_NDEV_FMT2071SET_DEF_KEY_PARAM_FMT2072SET_DEF_KEY_PARAM_FMT_2_6_382073"\n", FUNC_NDEV_ARG(ndev)2074SET_DEF_KEY_PARAM_ARG2075SET_DEF_KEY_PARAM_ARG_2_6_382076);20772078if ((key_index < WEP_KEYS) && ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_))) { /* set wep default key */2079psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;20802081psecuritypriv->dot11PrivacyKeyIndex = key_index;20822083psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;2084psecuritypriv->dot118021XGrpPrivacy = _WEP40_;2085if (psecuritypriv->dot11DefKeylen[key_index] == 13) {2086psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;2087psecuritypriv->dot118021XGrpPrivacy = _WEP104_;2088}20892090psecuritypriv->bWepDefaultKeyIdxSet = 1; /* set the flag to represent that wep default key has been set */2091}20922093return 0;20942095}20962097#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))2098int cfg80211_rtw_set_default_mgmt_key(struct wiphy *wiphy,2099struct net_device *ndev,2100#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))2101int link_id,2102#endif2103u8 key_index)2104{2105#define SET_DEF_KEY_PARAM_FMT " key_index=%d"2106#define SET_DEF_KEY_PARAM_ARG , key_index21072108RTW_INFO(FUNC_NDEV_FMT2109SET_DEF_KEY_PARAM_FMT2110"\n", FUNC_NDEV_ARG(ndev)2111SET_DEF_KEY_PARAM_ARG2112);21132114return 0;2115}2116#endif21172118#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))2119static int cfg80211_rtw_set_rekey_data(struct wiphy *wiphy,2120struct net_device *ndev,2121struct cfg80211_gtk_rekey_data *data)2122{2123/*int i;*/2124struct sta_info *psta;2125_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);2126struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2127struct sta_priv *pstapriv = &padapter->stapriv;2128struct security_priv *psecuritypriv = &(padapter->securitypriv);21292130psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));2131if (psta == NULL) {2132RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);2133return -1;2134}21352136_rtw_memcpy(psta->kek, data->kek, NL80211_KEK_LEN);2137/*printk("\ncfg80211_rtw_set_rekey_data KEK:");2138for(i=0;i<NL80211_KEK_LEN; i++)2139printk(" %02x ", psta->kek[i]);*/2140_rtw_memcpy(psta->kck, data->kck, NL80211_KCK_LEN);2141/*printk("\ncfg80211_rtw_set_rekey_data KCK:");2142for(i=0;i<NL80211_KCK_LEN; i++)2143printk(" %02x ", psta->kck[i]);*/2144_rtw_memcpy(psta->replay_ctr, data->replay_ctr, NL80211_REPLAY_CTR_LEN);2145psecuritypriv->binstallKCK_KEK = _TRUE;2146/*printk("\nREPLAY_CTR: ");2147for(i=0;i<RTW_REPLAY_CTR_LEN; i++)2148printk(" %02x ", psta->replay_ctr[i]);*/21492150return 0;2151}2152#endif /*CONFIG_GTK_OL*/21532154#ifdef CONFIG_RTW_MESH2155#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))2156static enum nl80211_mesh_power_mode rtw_mesh_ps_to_nl80211_mesh_power_mode(u8 ps)2157{2158if (ps == RTW_MESH_PS_UNKNOWN)2159return NL80211_MESH_POWER_UNKNOWN;2160if (ps == RTW_MESH_PS_ACTIVE)2161return NL80211_MESH_POWER_ACTIVE;2162if (ps == RTW_MESH_PS_LSLEEP)2163return NL80211_MESH_POWER_LIGHT_SLEEP;2164if (ps == RTW_MESH_PS_DSLEEP)2165return NL80211_MESH_POWER_DEEP_SLEEP;21662167rtw_warn_on(1);2168return NL80211_MESH_POWER_UNKNOWN;2169}2170#endif21712172#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))2173enum nl80211_plink_state rtw_plink_state_to_nl80211_plink_state(u8 plink_state)2174{2175if (plink_state == RTW_MESH_PLINK_UNKNOWN)2176return NUM_NL80211_PLINK_STATES;2177if (plink_state == RTW_MESH_PLINK_LISTEN)2178return NL80211_PLINK_LISTEN;2179if (plink_state == RTW_MESH_PLINK_OPN_SNT)2180return NL80211_PLINK_OPN_SNT;2181if (plink_state == RTW_MESH_PLINK_OPN_RCVD)2182return NL80211_PLINK_OPN_RCVD;2183if (plink_state == RTW_MESH_PLINK_CNF_RCVD)2184return NL80211_PLINK_CNF_RCVD;2185if (plink_state == RTW_MESH_PLINK_ESTAB)2186return NL80211_PLINK_ESTAB;2187if (plink_state == RTW_MESH_PLINK_HOLDING)2188return NL80211_PLINK_HOLDING;2189if (plink_state == RTW_MESH_PLINK_BLOCKED)2190return NL80211_PLINK_BLOCKED;21912192rtw_warn_on(1);2193return NUM_NL80211_PLINK_STATES;2194}21952196u8 nl80211_plink_state_to_rtw_plink_state(enum nl80211_plink_state plink_state)2197{2198if (plink_state == NL80211_PLINK_LISTEN)2199return RTW_MESH_PLINK_LISTEN;2200if (plink_state == NL80211_PLINK_OPN_SNT)2201return RTW_MESH_PLINK_OPN_SNT;2202if (plink_state == NL80211_PLINK_OPN_RCVD)2203return RTW_MESH_PLINK_OPN_RCVD;2204if (plink_state == NL80211_PLINK_CNF_RCVD)2205return RTW_MESH_PLINK_CNF_RCVD;2206if (plink_state == NL80211_PLINK_ESTAB)2207return RTW_MESH_PLINK_ESTAB;2208if (plink_state == NL80211_PLINK_HOLDING)2209return RTW_MESH_PLINK_HOLDING;2210if (plink_state == NL80211_PLINK_BLOCKED)2211return RTW_MESH_PLINK_BLOCKED;22122213rtw_warn_on(1);2214return RTW_MESH_PLINK_UNKNOWN;2215}2216#endif22172218static void rtw_cfg80211_fill_mesh_only_sta_info(struct mesh_plink_ent *plink, struct sta_info *sta, struct station_info *sinfo)2219{2220sinfo->filled |= STATION_INFO_LLID;2221sinfo->llid = plink->llid;2222sinfo->filled |= STATION_INFO_PLID;2223sinfo->plid = plink->plid;2224sinfo->filled |= STATION_INFO_PLINK_STATE;2225sinfo->plink_state = rtw_plink_state_to_nl80211_plink_state(plink->plink_state);2226if (!sta && plink->scanned) {2227sinfo->filled |= STATION_INFO_SIGNAL;2228sinfo->signal = translate_percentage_to_dbm(plink->scanned->network.PhyInfo.SignalStrength);2229sinfo->filled |= STATION_INFO_INACTIVE_TIME;2230if (plink->plink_state == RTW_MESH_PLINK_UNKNOWN)2231sinfo->inactive_time = 0 - 1;2232else2233sinfo->inactive_time = rtw_get_passing_time_ms(plink->scanned->last_scanned);2234}2235#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))2236if (sta) {2237sinfo->filled |= STATION_INFO_LOCAL_PM;2238sinfo->local_pm = rtw_mesh_ps_to_nl80211_mesh_power_mode(sta->local_mps);2239sinfo->filled |= STATION_INFO_PEER_PM;2240sinfo->peer_pm = rtw_mesh_ps_to_nl80211_mesh_power_mode(sta->peer_mps);2241sinfo->filled |= STATION_INFO_NONPEER_PM;2242sinfo->nonpeer_pm = rtw_mesh_ps_to_nl80211_mesh_power_mode(sta->nonpeer_mps);2243}2244#endif2245}2246#endif /* CONFIG_RTW_MESH */22472248static int cfg80211_rtw_get_station(struct wiphy *wiphy,2249struct net_device *ndev,2250#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))2251u8 *mac,2252#else2253const u8 *mac,2254#endif2255struct station_info *sinfo)2256{2257int ret = 0;2258_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);2259struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2260struct sta_info *psta = NULL;2261struct sta_priv *pstapriv = &padapter->stapriv;2262#ifdef CONFIG_RTW_MESH2263struct mesh_plink_ent *plink = NULL;2264#endif22652266sinfo->filled = 0;22672268if (!mac) {2269RTW_INFO(FUNC_NDEV_FMT" mac==%p\n", FUNC_NDEV_ARG(ndev), mac);2270ret = -ENOENT;2271goto exit;2272}22732274psta = rtw_get_stainfo(pstapriv, mac);2275#ifdef CONFIG_RTW_MESH2276if (MLME_IS_MESH(padapter)) {2277if (psta)2278plink = psta->plink;2279if (!plink)2280plink = rtw_mesh_plink_get(padapter, mac);2281}2282#endif /* CONFIG_RTW_MESH */22832284if ((!MLME_IS_MESH(padapter) && !psta)2285#ifdef CONFIG_RTW_MESH2286|| (MLME_IS_MESH(padapter) && !plink)2287#endif2288) {2289RTW_INFO(FUNC_NDEV_FMT" no sta info for mac="MAC_FMT"\n"2290, FUNC_NDEV_ARG(ndev), MAC_ARG(mac));2291ret = -ENOENT;2292goto exit;2293}22942295#ifdef CONFIG_DEBUG_CFG802112296RTW_INFO(FUNC_NDEV_FMT" mac="MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(mac));2297#endif22982299/* for infra./P2PClient mode */2300if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)2301&& check_fwstate(pmlmepriv, _FW_LINKED)2302) {2303struct wlan_network *cur_network = &(pmlmepriv->cur_network);23042305if (_rtw_memcmp((u8 *)mac, cur_network->network.MacAddress, ETH_ALEN) == _FALSE) {2306RTW_INFO("%s, mismatch bssid="MAC_FMT"\n", __func__, MAC_ARG(cur_network->network.MacAddress));2307ret = -ENOENT;2308goto exit;2309}23102311sinfo->filled |= STATION_INFO_SIGNAL;2312sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);23132314sinfo->filled |= STATION_INFO_TX_BITRATE;2315sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);2316}23172318if (psta) {2319if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE2320|| check_fwstate(pmlmepriv, _FW_LINKED) == _FALSE2321) {2322sinfo->filled |= STATION_INFO_SIGNAL;2323sinfo->signal = translate_percentage_to_dbm(psta->cmn.rssi_stat.rssi);2324}2325sinfo->filled |= STATION_INFO_INACTIVE_TIME;2326sinfo->inactive_time = rtw_get_passing_time_ms(psta->sta_stats.last_rx_time);2327sinfo->filled |= STATION_INFO_RX_PACKETS;2328sinfo->rx_packets = sta_rx_data_pkts(psta);2329sinfo->filled |= STATION_INFO_TX_PACKETS;2330sinfo->tx_packets = psta->sta_stats.tx_pkts;2331sinfo->filled |= STATION_INFO_TX_FAILED;2332sinfo->tx_failed = psta->sta_stats.tx_fail_cnt;2333}23342335#ifdef CONFIG_RTW_MESH2336if (MLME_IS_MESH(padapter))2337rtw_cfg80211_fill_mesh_only_sta_info(plink, psta, sinfo);2338#endif23392340exit:2341return ret;2342}23432344extern int netdev_open(struct net_device *pnetdev);23452346#if 02347enum nl80211_iftype {2348NL80211_IFTYPE_UNSPECIFIED,2349NL80211_IFTYPE_ADHOC, /* 1 */2350NL80211_IFTYPE_STATION, /* 2 */2351NL80211_IFTYPE_AP, /* 3 */2352NL80211_IFTYPE_AP_VLAN,2353NL80211_IFTYPE_WDS,2354NL80211_IFTYPE_MONITOR, /* 6 */2355NL80211_IFTYPE_MESH_POINT,2356NL80211_IFTYPE_P2P_CLIENT, /* 8 */2357NL80211_IFTYPE_P2P_GO, /* 9 */2358/* keep last */2359NUM_NL80211_IFTYPES,2360NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 12361};2362#endif2363static int cfg80211_rtw_change_iface(struct wiphy *wiphy,2364struct net_device *ndev,2365enum nl80211_iftype type,2366#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))2367u32 *flags,2368#endif2369struct vif_params *params)2370{2371enum nl80211_iftype old_type;2372NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;2373_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);2374struct wireless_dev *rtw_wdev = padapter->rtw_wdev;2375struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);2376#ifdef CONFIG_P2P2377struct wifidirect_info *pwdinfo = &(padapter->wdinfo);2378#endif2379#ifdef CONFIG_MONITOR_MODE_XMIT2380struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);2381#endif2382int ret = 0;2383u8 change = _FALSE;23842385RTW_INFO(FUNC_NDEV_FMT" type=%d, hw_port:%d\n", FUNC_NDEV_ARG(ndev), type, padapter->hw_port);23862387if (adapter_to_dvobj(padapter)->processing_dev_remove == _TRUE) {2388ret = -EPERM;2389goto exit;2390}239123922393RTW_INFO(FUNC_NDEV_FMT" call netdev_open\n", FUNC_NDEV_ARG(ndev));2394if (netdev_open(ndev) != 0) {2395RTW_INFO(FUNC_NDEV_FMT" call netdev_open fail\n", FUNC_NDEV_ARG(ndev));2396ret = -EPERM;2397goto exit;2398}239924002401if (_FAIL == rtw_pwr_wakeup(padapter)) {2402RTW_INFO(FUNC_NDEV_FMT" call rtw_pwr_wakeup fail\n", FUNC_NDEV_ARG(ndev));2403ret = -EPERM;2404goto exit;2405}24062407old_type = rtw_wdev->iftype;2408RTW_INFO(FUNC_NDEV_FMT" old_iftype=%d, new_iftype=%d\n",2409FUNC_NDEV_ARG(ndev), old_type, type);24102411if (old_type != type) {2412change = _TRUE;2413pmlmeext->action_public_rxseq = 0xffff;2414pmlmeext->action_public_dialog_token = 0xff;2415}24162417/* initial default type */2418ndev->type = ARPHRD_ETHER;24192420/*2421* Disable Power Save in moniter mode,2422* and enable it after leaving moniter mode.2423*/2424if (type == NL80211_IFTYPE_MONITOR) {2425rtw_ps_deny(padapter, PS_DENY_MONITOR_MODE);2426LeaveAllPowerSaveMode(padapter);2427} else if (old_type == NL80211_IFTYPE_MONITOR) {2428/* driver in moniter mode in last time */2429rtw_ps_deny_cancel(padapter, PS_DENY_MONITOR_MODE);2430}24312432switch (type) {2433case NL80211_IFTYPE_ADHOC:2434networkType = Ndis802_11IBSS;2435break;24362437case NL80211_IFTYPE_STATION:2438networkType = Ndis802_11Infrastructure;2439#ifdef CONFIG_P2P2440if (change && pwdinfo->driver_interface == DRIVER_CFG80211) {2441#if !RTW_P2P_GROUP_INTERFACE2442if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)2443|| rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)2444) {2445/* it means remove GC/GO and change mode from GC/GO to station(P2P DEVICE) */2446rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);2447}2448#endif2449}2450#endif /* CONFIG_P2P */2451break;24522453case NL80211_IFTYPE_AP:2454networkType = Ndis802_11APMode;2455#ifdef CONFIG_P2P2456if (change && pwdinfo->driver_interface == DRIVER_CFG80211) {2457#if !RTW_P2P_GROUP_INTERFACE2458if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {2459/* it means P2P Group created, we will be GO and change mode from P2P DEVICE to AP(GO) */2460rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);2461}2462#endif2463}2464#endif /* CONFIG_P2P */2465break;24662467#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))2468case NL80211_IFTYPE_P2P_CLIENT:2469networkType = Ndis802_11Infrastructure;2470if (change && pwdinfo->driver_interface == DRIVER_CFG80211)2471rtw_p2p_enable(padapter, P2P_ROLE_CLIENT);2472break;24732474case NL80211_IFTYPE_P2P_GO:2475networkType = Ndis802_11APMode;2476if (change && pwdinfo->driver_interface == DRIVER_CFG80211)2477rtw_p2p_enable(padapter, P2P_ROLE_GO);2478break;2479#endif /* defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)) */24802481#ifdef CONFIG_RTW_MESH2482case NL80211_IFTYPE_MESH_POINT:2483networkType = Ndis802_11_mesh;2484break;2485#endif24862487case NL80211_IFTYPE_MONITOR:2488networkType = Ndis802_11Monitor;2489#if 02490ndev->type = ARPHRD_IEEE80211; /* IEEE 802.11 : 801 */2491#endif2492ndev->type = ARPHRD_IEEE80211_RADIOTAP; /* IEEE 802.11 + radiotap header : 803 */2493break;2494default:2495ret = -EOPNOTSUPP;2496goto exit;2497}24982499rtw_wdev->iftype = type;25002501if (rtw_set_802_11_infrastructure_mode(padapter, networkType, 0) == _FALSE) {2502rtw_wdev->iftype = old_type;2503ret = -EPERM;2504goto exit;2505}25062507rtw_setopmode_cmd(padapter, networkType, RTW_CMDF_WAIT_ACK);2508#ifdef CONFIG_MONITOR_MODE_XMIT2509if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) == _TRUE)2510rtw_indicate_connect(padapter);2511#endif2512exit:25132514RTW_INFO(FUNC_NDEV_FMT" ret:%d\n", FUNC_NDEV_ARG(ndev), ret);2515return ret;2516}25172518void rtw_cfg80211_indicate_scan_done(_adapter *adapter, bool aborted)2519{2520struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);2521_irqL irqL;25222523#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)2524struct cfg80211_scan_info info;25252526memset(&info, 0, sizeof(info));2527info.aborted = aborted;2528#endif25292530_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);2531if (pwdev_priv->scan_request != NULL) {2532#ifdef CONFIG_DEBUG_CFG802112533RTW_INFO("%s with scan req\n", __FUNCTION__);2534#endif25352536/* avoid WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); */2537if (pwdev_priv->scan_request->wiphy != pwdev_priv->rtw_wdev->wiphy)2538RTW_INFO("error wiphy compare\n");2539else2540#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)2541cfg80211_scan_done(pwdev_priv->scan_request, &info);2542#else2543cfg80211_scan_done(pwdev_priv->scan_request, aborted);2544#endif25452546pwdev_priv->scan_request = NULL;2547} else {2548#ifdef CONFIG_DEBUG_CFG802112549RTW_INFO("%s without scan req\n", __FUNCTION__);2550#endif2551}2552_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);2553}25542555u32 rtw_cfg80211_wait_scan_req_empty(_adapter *adapter, u32 timeout_ms)2556{2557struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);2558u8 empty = _FALSE;2559systime start;2560u32 pass_ms;25612562start = rtw_get_current_time();25632564while (rtw_get_passing_time_ms(start) <= timeout_ms) {25652566if (RTW_CANNOT_RUN(adapter))2567break;25682569if (!wdev_priv->scan_request) {2570empty = _TRUE;2571break;2572}25732574rtw_msleep_os(10);2575}25762577pass_ms = rtw_get_passing_time_ms(start);25782579if (empty == _FALSE && pass_ms > timeout_ms)2580RTW_PRINT(FUNC_ADPT_FMT" pass_ms:%u, timeout\n"2581, FUNC_ADPT_ARG(adapter), pass_ms);25822583return pass_ms;2584}25852586void rtw_cfg80211_unlink_bss(_adapter *padapter, struct wlan_network *pnetwork)2587{2588struct wireless_dev *pwdev = padapter->rtw_wdev;2589struct wiphy *wiphy = pwdev->wiphy;2590struct cfg80211_bss *bss = NULL;2591WLAN_BSSID_EX select_network = pnetwork->network;25922593bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/,2594select_network.MacAddress, select_network.Ssid.Ssid,2595select_network.Ssid.SsidLength,2596#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)2597select_network.InfrastructureMode == Ndis802_11Infrastructure?IEEE80211_BSS_TYPE_ESS:IEEE80211_BSS_TYPE_IBSS,2598IEEE80211_PRIVACY(select_network.Privacy));2599#else2600select_network.InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS,2601select_network.InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS);2602#endif26032604if (bss) {2605cfg80211_unlink_bss(wiphy, bss);2606RTW_INFO("%s(): cfg80211_unlink %s!!\n", __func__, select_network.Ssid.Ssid);2607#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)2608cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);2609#else2610cfg80211_put_bss(bss);2611#endif2612}2613return;2614}26152616/* if target wps scan ongoing, target_ssid is filled */2617int rtw_cfg80211_is_target_wps_scan(struct cfg80211_scan_request *scan_req, struct cfg80211_ssid *target_ssid)2618{2619int ret = 0;26202621if (scan_req->n_ssids != 12622|| scan_req->ssids[0].ssid_len == 02623|| scan_req->n_channels != 12624)2625goto exit;26262627/* under target WPS scan */2628_rtw_memcpy(target_ssid, scan_req->ssids, sizeof(struct cfg80211_ssid));2629ret = 1;26302631exit:2632return ret;2633}26342635static void _rtw_cfg80211_surveydone_event_callback(_adapter *padapter, struct cfg80211_scan_request *scan_req)2636{2637struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);2638RT_CHANNEL_INFO *chset = rfctl->channel_set;2639_irqL irqL;2640_list *plist, *phead;2641struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);2642_queue *queue = &(pmlmepriv->scanned_queue);2643struct wlan_network *pnetwork = NULL;2644struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);2645struct cfg80211_ssid target_ssid;2646u8 target_wps_scan = 0;2647u8 ch;26482649#ifdef CONFIG_DEBUG_CFG802112650RTW_INFO("%s\n", __func__);2651#endif26522653if (scan_req)2654target_wps_scan = rtw_cfg80211_is_target_wps_scan(scan_req, &target_ssid);2655else {2656_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);2657if (pwdev_priv->scan_request != NULL)2658target_wps_scan = rtw_cfg80211_is_target_wps_scan(pwdev_priv->scan_request, &target_ssid);2659_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);2660}26612662_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);26632664phead = get_list_head(queue);2665plist = get_next(phead);26662667while (1) {2668if (rtw_end_of_queue_search(phead, plist) == _TRUE)2669break;26702671pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);2672ch = pnetwork->network.Configuration.DSConfig;26732674/* report network only if the current channel set contains the channel to which this network belongs */2675if (rtw_chset_search_ch(chset, ch) >= 02676&& rtw_mlme_band_check(padapter, ch) == _TRUE2677&& _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))2678&& (!IS_DFS_SLAVE_WITH_RD(rfctl)2679|| rtw_odm_dfs_domain_unknown(rfctl_to_dvobj(rfctl))2680|| !rtw_chset_is_ch_non_ocp(chset, ch))2681) {2682if (target_wps_scan)2683rtw_cfg80211_clear_wps_sr_of_non_target_bss(padapter, pnetwork, &target_ssid);2684rtw_cfg80211_inform_bss(padapter, pnetwork);2685}2686#if 02687/* check ralink testbed RSN IE length */2688{2689if (_rtw_memcmp(pnetwork->network.Ssid.Ssid, "Ralink_11n_AP", 13)) {2690uint ie_len = 0;2691u8 *p = NULL;2692p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_));2693RTW_INFO("ie_len=%d\n", ie_len);2694}2695}2696#endif2697plist = get_next(plist);26982699}27002701_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);2702}27032704inline void rtw_cfg80211_surveydone_event_callback(_adapter *padapter)2705{2706_rtw_cfg80211_surveydone_event_callback(padapter, NULL);2707}27082709static int rtw_cfg80211_set_probe_req_wpsp2pie(_adapter *padapter, char *buf, int len)2710{2711int ret = 0;2712uint wps_ielen = 0;2713u8 *wps_ie;2714u32 p2p_ielen = 0;2715u8 *p2p_ie;2716u32 wfd_ielen = 0;2717u8 *wfd_ie;2718struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);27192720#ifdef CONFIG_DEBUG_CFG802112721RTW_INFO("%s, ielen=%d\n", __func__, len);2722#endif27232724if (len > 0) {2725wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);2726if (wps_ie) {2727#ifdef CONFIG_DEBUG_CFG802112728RTW_INFO("probe_req_wps_ielen=%d\n", wps_ielen);2729#endif27302731if (pmlmepriv->wps_probe_req_ie) {2732u32 free_len = pmlmepriv->wps_probe_req_ie_len;2733pmlmepriv->wps_probe_req_ie_len = 0;2734rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);2735pmlmepriv->wps_probe_req_ie = NULL;2736}27372738pmlmepriv->wps_probe_req_ie = rtw_malloc(wps_ielen);2739if (pmlmepriv->wps_probe_req_ie == NULL) {2740RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);2741return -EINVAL;27422743}2744_rtw_memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);2745pmlmepriv->wps_probe_req_ie_len = wps_ielen;2746}27472748/* buf += wps_ielen; */2749/* len -= wps_ielen; */27502751#ifdef CONFIG_P2P2752p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);2753if (p2p_ie) {2754struct wifidirect_info *wdinfo = &padapter->wdinfo;2755u32 attr_contentlen = 0;2756u8 listen_ch_attr[5];27572758#ifdef CONFIG_DEBUG_CFG802112759RTW_INFO("probe_req_p2p_ielen=%d\n", p2p_ielen);2760#endif27612762if (pmlmepriv->p2p_probe_req_ie) {2763u32 free_len = pmlmepriv->p2p_probe_req_ie_len;2764pmlmepriv->p2p_probe_req_ie_len = 0;2765rtw_mfree(pmlmepriv->p2p_probe_req_ie, free_len);2766pmlmepriv->p2p_probe_req_ie = NULL;2767}27682769pmlmepriv->p2p_probe_req_ie = rtw_malloc(p2p_ielen);2770if (pmlmepriv->p2p_probe_req_ie == NULL) {2771RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);2772return -EINVAL;27732774}2775_rtw_memcpy(pmlmepriv->p2p_probe_req_ie, p2p_ie, p2p_ielen);2776pmlmepriv->p2p_probe_req_ie_len = p2p_ielen;27772778if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen)2779&& attr_contentlen == 5) {2780if (wdinfo->listen_channel != listen_ch_attr[4]) {2781RTW_INFO(FUNC_ADPT_FMT" listen channel - country:%c%c%c, class:%u, ch:%u\n",2782FUNC_ADPT_ARG(padapter), listen_ch_attr[0], listen_ch_attr[1], listen_ch_attr[2],2783listen_ch_attr[3], listen_ch_attr[4]);2784wdinfo->listen_channel = listen_ch_attr[4];2785}2786}2787}2788#endif /* CONFIG_P2P */27892790#ifdef CONFIG_WFD2791wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);2792if (wfd_ie) {2793#ifdef CONFIG_DEBUG_CFG802112794RTW_INFO("probe_req_wfd_ielen=%d\n", wfd_ielen);2795#endif27962797if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_PROBE_REQ_IE, wfd_ie, wfd_ielen) != _SUCCESS)2798return -EINVAL;2799}2800#endif /* CONFIG_WFD */2801}28022803return ret;28042805}28062807#ifdef CONFIG_CONCURRENT_MODE2808u8 rtw_cfg80211_scan_via_buddy(_adapter *padapter, struct cfg80211_scan_request *request)2809{2810int i;2811u8 ret = _FALSE;2812_adapter *iface = NULL;2813_irqL irqL;2814struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);2815struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);2816struct mlme_priv *pmlmepriv = &padapter->mlmepriv;28172818for (i = 0; i < dvobj->iface_nums; i++) {2819struct mlme_priv *buddy_mlmepriv;2820struct rtw_wdev_priv *buddy_wdev_priv;28212822iface = dvobj->padapters[i];2823if (iface == NULL)2824continue;28252826if (iface == padapter)2827continue;28282829if (rtw_is_adapter_up(iface) == _FALSE)2830continue;28312832buddy_mlmepriv = &iface->mlmepriv;2833if (!check_fwstate(buddy_mlmepriv, _FW_UNDER_SURVEY))2834continue;28352836buddy_wdev_priv = adapter_wdev_data(iface);2837_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);2838_enter_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);2839if (buddy_wdev_priv->scan_request) {2840pmlmepriv->scanning_via_buddy_intf = _TRUE;2841_enter_critical_bh(&pmlmepriv->lock, &irqL);2842set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);2843_exit_critical_bh(&pmlmepriv->lock, &irqL);2844pwdev_priv->scan_request = request;2845ret = _TRUE;2846}2847_exit_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);2848_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);28492850if (ret == _TRUE)2851goto exit;2852}28532854exit:2855return ret;2856}28572858void rtw_cfg80211_indicate_scan_done_for_buddy(_adapter *padapter, bool bscan_aborted)2859{2860int i;2861_adapter *iface = NULL;2862_irqL irqL;2863struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);2864struct mlme_priv *mlmepriv;2865struct rtw_wdev_priv *wdev_priv;2866bool indicate_buddy_scan;28672868for (i = 0; i < dvobj->iface_nums; i++) {2869iface = dvobj->padapters[i];2870if ((iface) && rtw_is_adapter_up(iface)) {28712872if (iface == padapter)2873continue;28742875mlmepriv = &(iface->mlmepriv);2876wdev_priv = adapter_wdev_data(iface);28772878indicate_buddy_scan = _FALSE;2879_enter_critical_bh(&wdev_priv->scan_req_lock, &irqL);2880if (mlmepriv->scanning_via_buddy_intf == _TRUE) {2881mlmepriv->scanning_via_buddy_intf = _FALSE;2882clr_fwstate(mlmepriv, _FW_UNDER_SURVEY);2883if (wdev_priv->scan_request)2884indicate_buddy_scan = _TRUE;2885}2886_exit_critical_bh(&wdev_priv->scan_req_lock, &irqL);28872888if (indicate_buddy_scan == _TRUE) {2889rtw_cfg80211_surveydone_event_callback(iface);2890rtw_indicate_scan_done(iface, bscan_aborted);2891}28922893}2894}2895}2896#endif /* CONFIG_CONCURRENT_MODE */28972898static int cfg80211_rtw_scan(struct wiphy *wiphy2899#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))2900, struct net_device *ndev2901#endif2902, struct cfg80211_scan_request *request)2903{2904int i;2905u8 _status = _FALSE;2906int ret = 0;2907struct sitesurvey_parm parm;2908_irqL irqL;2909u8 survey_times = 3;2910u8 survey_times_for_one_ch = 6;2911struct cfg80211_ssid *ssids = request->ssids;2912int social_channel = 0, j = 0;2913bool need_indicate_scan_done = _FALSE;2914bool ps_denied = _FALSE;2915u8 ssc_chk;2916_adapter *padapter;2917struct wireless_dev *wdev;2918struct rtw_wdev_priv *pwdev_priv;2919struct mlme_priv *pmlmepriv = NULL;2920#ifdef CONFIG_P2P2921struct wifidirect_info *pwdinfo;2922#endif /* CONFIG_P2P */29232924#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))2925wdev = request->wdev;2926#if defined(RTW_DEDICATED_P2P_DEVICE)2927if (wdev == wiphy_to_pd_wdev(wiphy))2928padapter = wiphy_to_adapter(wiphy);2929else2930#endif2931if (wdev_to_ndev(wdev))2932padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));2933else {2934ret = -EINVAL;2935goto exit;2936}2937#else2938if (ndev == NULL) {2939ret = -EINVAL;2940goto exit;2941}2942padapter = (_adapter *)rtw_netdev_priv(ndev);2943wdev = ndev_to_wdev(ndev);2944#endif29452946pwdev_priv = adapter_wdev_data(padapter);2947pmlmepriv = &padapter->mlmepriv;2948#ifdef CONFIG_P2P2949pwdinfo = &(padapter->wdinfo);2950#endif /* CONFIG_P2P */29512952RTW_INFO(FUNC_ADPT_FMT"%s\n", FUNC_ADPT_ARG(padapter)2953, wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : "");29542955#if 12956ssc_chk = rtw_sitesurvey_condition_check(padapter, _TRUE);29572958if (ssc_chk == SS_DENY_MP_MODE)2959goto bypass_p2p_chk;2960#ifdef DBG_LA_MODE2961if (ssc_chk == SS_DENY_LA_MODE)2962goto bypass_p2p_chk;2963#endif2964#ifdef CONFIG_P2P2965if (pwdinfo->driver_interface == DRIVER_CFG80211) {2966if (request->n_ssids && ssids2967&& _rtw_memcmp(ssids[0].ssid, "DIRECT-", 7)2968&& rtw_get_p2p_ie((u8 *)request->ie, request->ie_len, NULL, NULL)2969) {2970if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))2971rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);2972else {2973rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));2974#ifdef CONFIG_DEBUG_CFG802112975RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));2976#endif2977}2978rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);29792980if (request->n_channels == 3 &&2981request->channels[0]->hw_value == 1 &&2982request->channels[1]->hw_value == 6 &&2983request->channels[2]->hw_value == 112984)2985social_channel = 1;2986}2987}2988#endif /*CONFIG_P2P*/29892990if (request->ie && request->ie_len > 0)2991rtw_cfg80211_set_probe_req_wpsp2pie(padapter, (u8 *)request->ie, request->ie_len);29922993bypass_p2p_chk:29942995switch (ssc_chk) {2996case SS_ALLOW :2997break;29982999case SS_DENY_MP_MODE:3000ret = -EPERM;3001goto exit;3002#ifdef DBG_LA_MODE3003case SS_DENY_LA_MODE:3004ret = -EPERM;3005goto exit;3006#endif3007#ifdef CONFIG_RTW_REPEATER_SON3008case SS_DENY_RSON_SCANING :3009#endif3010case SS_DENY_BLOCK_SCAN :3011case SS_DENY_SELF_AP_UNDER_WPS :3012case SS_DENY_SELF_AP_UNDER_LINKING :3013case SS_DENY_SELF_AP_UNDER_SURVEY :3014case SS_DENY_SELF_STA_UNDER_SURVEY :3015#ifdef CONFIG_CONCURRENT_MODE3016case SS_DENY_BUDDY_UNDER_LINK_WPS :3017#endif3018case SS_DENY_BUSY_TRAFFIC :3019need_indicate_scan_done = _TRUE;3020goto check_need_indicate_scan_done;30213022case SS_DENY_BY_DRV :3023#if CONFIG_NOTIFY_SCAN_ABORT_WITH_BUSY3024ret = -EBUSY;3025goto exit;3026#else3027need_indicate_scan_done = _TRUE;3028goto check_need_indicate_scan_done;3029#endif3030break;30313032case SS_DENY_SELF_STA_UNDER_LINKING :3033ret = -EBUSY;3034goto check_need_indicate_scan_done;30353036#ifdef CONFIG_CONCURRENT_MODE3037case SS_DENY_BUDDY_UNDER_SURVEY :3038{3039bool scan_via_buddy = rtw_cfg80211_scan_via_buddy(padapter, request);30403041if (scan_via_buddy == _FALSE)3042need_indicate_scan_done = _TRUE;30433044goto check_need_indicate_scan_done;3045}3046#endif30473048default :3049RTW_ERR("site survey check code (%d) unknown\n", ssc_chk);3050need_indicate_scan_done = _TRUE;3051goto check_need_indicate_scan_done;3052}30533054rtw_ps_deny(padapter, PS_DENY_SCAN);3055ps_denied = _TRUE;3056if (_FAIL == rtw_pwr_wakeup(padapter)) {3057need_indicate_scan_done = _TRUE;3058goto check_need_indicate_scan_done;3059}30603061#else306230633064#ifdef CONFIG_MP_INCLUDED3065if (rtw_mp_mode_check(padapter)) {3066RTW_INFO("MP mode block Scan request\n");3067ret = -EPERM;3068goto exit;3069}3070#endif30713072#ifdef CONFIG_P2P3073if (pwdinfo->driver_interface == DRIVER_CFG80211) {3074if (request->n_ssids && ssids3075&& _rtw_memcmp(ssids[0].ssid, "DIRECT-", 7)3076&& rtw_get_p2p_ie((u8 *)request->ie, request->ie_len, NULL, NULL)3077) {3078if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))3079rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);3080else {3081rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));3082#ifdef CONFIG_DEBUG_CFG802113083RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));3084#endif3085}3086rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);30873088if (request->n_channels == 3 &&3089request->channels[0]->hw_value == 1 &&3090request->channels[1]->hw_value == 6 &&3091request->channels[2]->hw_value == 113092)3093social_channel = 1;3094}3095}3096#endif /*CONFIG_P2P*/30973098if (request->ie && request->ie_len > 0)3099rtw_cfg80211_set_probe_req_wpsp2pie(padapter, (u8 *)request->ie, request->ie_len);31003101#ifdef CONFIG_RTW_REPEATER_SON3102if (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS) {3103RTW_INFO(FUNC_ADPT_FMT" blocking scan for under rson scanning process\n", FUNC_ADPT_ARG(padapter));3104need_indicate_scan_done = _TRUE;3105goto check_need_indicate_scan_done;3106}3107#endif31083109if (adapter_wdev_data(padapter)->block_scan == _TRUE) {3110RTW_INFO(FUNC_ADPT_FMT" wdev_priv.block_scan is set\n", FUNC_ADPT_ARG(padapter));3111need_indicate_scan_done = _TRUE;3112goto check_need_indicate_scan_done;3113}31143115rtw_ps_deny(padapter, PS_DENY_SCAN);3116ps_denied = _TRUE;3117if (_FAIL == rtw_pwr_wakeup(padapter)) {3118need_indicate_scan_done = _TRUE;3119goto check_need_indicate_scan_done;3120}31213122if (rtw_is_scan_deny(padapter)) {3123RTW_INFO(FUNC_ADPT_FMT ": scan deny\n", FUNC_ADPT_ARG(padapter));3124#if CONFIG_NOTIFY_SCAN_ABORT_WITH_BUSY3125ret = -EBUSY;3126goto exit;3127#else3128need_indicate_scan_done = _TRUE;3129goto check_need_indicate_scan_done;3130#endif3131}31323133/* check fw state*/3134if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) {31353136#ifdef CONFIG_DEBUG_CFG802113137RTW_INFO(FUNC_ADPT_FMT" under WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter));3138#endif31393140if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS | _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == _TRUE) {3141RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);31423143if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS))3144RTW_INFO("AP mode process WPS\n");31453146need_indicate_scan_done = _TRUE;3147goto check_need_indicate_scan_done;3148}3149}31503151if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {3152RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);3153need_indicate_scan_done = _TRUE;3154goto check_need_indicate_scan_done;3155} else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) {3156RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);3157ret = -EBUSY;3158goto check_need_indicate_scan_done;3159}31603161#ifdef CONFIG_CONCURRENT_MODE3162if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | WIFI_UNDER_WPS)) {3163RTW_INFO("%s exit due to buddy_intf's mlme state under linking or wps\n", __func__);3164need_indicate_scan_done = _TRUE;3165goto check_need_indicate_scan_done;31663167} else if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_SURVEY)) {3168bool scan_via_buddy = rtw_cfg80211_scan_via_buddy(padapter, request);31693170if (scan_via_buddy == _FALSE)3171need_indicate_scan_done = _TRUE;31723173goto check_need_indicate_scan_done;3174}3175#endif /* CONFIG_CONCURRENT_MODE */31763177/* busy traffic check*/3178if (rtw_mi_busy_traffic_check(padapter, _TRUE)) {3179need_indicate_scan_done = _TRUE;3180goto check_need_indicate_scan_done;3181}3182#endif31833184#ifdef CONFIG_P2P3185if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {3186rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);31873188if (social_channel == 0)3189rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);3190else3191rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_SOCIAL_LAST);3192}3193#endif /* CONFIG_P2P */31943195rtw_init_sitesurvey_parm(padapter, &parm);31963197/* parsing request ssids, n_ssids */3198for (i = 0; i < request->n_ssids && ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {3199#ifdef CONFIG_DEBUG_CFG802113200RTW_INFO("ssid=%s, len=%d\n", ssids[i].ssid, ssids[i].ssid_len);3201#endif3202_rtw_memcpy(&parm.ssid[i].Ssid, ssids[i].ssid, ssids[i].ssid_len);3203parm.ssid[i].SsidLength = ssids[i].ssid_len;3204}3205parm.ssid_num = i;32063207/* no ssid entry, set the scan type as passvie */3208if (request->n_ssids == 0)3209parm.scan_mode = SCAN_PASSIVE;32103211/* parsing channels, n_channels */3212for (i = 0; i < request->n_channels && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {3213#ifdef CONFIG_DEBUG_CFG802113214RTW_INFO(FUNC_ADPT_FMT CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(request->channels[i]));3215#endif3216parm.ch[i].hw_value = request->channels[i]->hw_value;3217parm.ch[i].flags = request->channels[i]->flags;3218}3219parm.ch_num = i;32203221if (request->n_channels == 1) {3222for (i = 1; i < survey_times_for_one_ch; i++)3223_rtw_memcpy(&parm.ch[i], &parm.ch[0], sizeof(struct rtw_ieee80211_channel));3224parm.ch_num = survey_times_for_one_ch;3225} else if (request->n_channels <= 4) {3226for (j = request->n_channels - 1; j >= 0; j--)3227for (i = 0; i < survey_times; i++)3228_rtw_memcpy(&parm.ch[j * survey_times + i], &parm.ch[j], sizeof(struct rtw_ieee80211_channel));3229parm.ch_num = survey_times * request->n_channels;3230}32313232_enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);3233_enter_critical_bh(&pmlmepriv->lock, &irqL);3234_status = rtw_sitesurvey_cmd(padapter, &parm);3235if (_status == _SUCCESS)3236pwdev_priv->scan_request = request;3237else3238ret = -1;3239_exit_critical_bh(&pmlmepriv->lock, &irqL);3240_exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);32413242check_need_indicate_scan_done:3243if (_TRUE == need_indicate_scan_done) {3244#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)3245struct cfg80211_scan_info info;32463247memset(&info, 0, sizeof(info));3248info.aborted = 0;3249#endif32503251_rtw_cfg80211_surveydone_event_callback(padapter, request);3252#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)3253cfg80211_scan_done(request, &info);3254#else3255cfg80211_scan_done(request, 0);3256#endif3257}32583259if (ps_denied == _TRUE)3260rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);32613262exit:3263if (pmlmepriv)3264pmlmepriv->lastscantime = rtw_get_current_time();32653266return ret;3267}32683269static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)3270{3271#if 03272struct iwm_priv *iwm = wiphy_to_iwm(wiphy);32733274if (changed & WIPHY_PARAM_RTS_THRESHOLD &&3275(iwm->conf.rts_threshold != wiphy->rts_threshold)) {3276int ret;32773278iwm->conf.rts_threshold = wiphy->rts_threshold;32793280ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,3281CFG_RTS_THRESHOLD,3282iwm->conf.rts_threshold);3283if (ret < 0)3284return ret;3285}32863287if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&3288(iwm->conf.frag_threshold != wiphy->frag_threshold)) {3289int ret;32903291iwm->conf.frag_threshold = wiphy->frag_threshold;32923293ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,3294CFG_FRAG_THRESHOLD,3295iwm->conf.frag_threshold);3296if (ret < 0)3297return ret;3298}3299#endif3300RTW_INFO("%s\n", __func__);3301return 0;3302}3303330433053306static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, u32 wpa_version)3307{3308RTW_INFO("%s, wpa_version=%d\n", __func__, wpa_version);33093310if (!wpa_version) {3311psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;3312return 0;3313}331433153316if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))3317psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;33183319#if 03320if (wpa_version & NL80211_WPA_VERSION_2)3321psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;3322#endif33233324#ifdef CONFIG_WAPI_SUPPORT3325if (wpa_version & NL80211_WAPI_VERSION_1)3326psecuritypriv->ndisauthtype = Ndis802_11AuthModeWAPI;3327#endif33283329return 0;33303331}33323333static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,3334enum nl80211_auth_type sme_auth_type)3335{3336RTW_INFO("%s, nl80211_auth_type=%d\n", __func__, sme_auth_type);33373338psecuritypriv->auth_type = sme_auth_type;33393340if (sme_auth_type == NL80211_AUTHTYPE_SAE) {3341psecuritypriv->auth_alg = WLAN_AUTH_SAE;3342return 0;3343}33443345switch (sme_auth_type) {3346case NL80211_AUTHTYPE_AUTOMATIC:33473348psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;33493350break;3351case NL80211_AUTHTYPE_OPEN_SYSTEM:33523353psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;33543355if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)3356psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;33573358#ifdef CONFIG_WAPI_SUPPORT3359if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWAPI)3360psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;3361#endif33623363break;3364case NL80211_AUTHTYPE_SHARED_KEY:33653366psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;33673368psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;336933703371break;3372default:3373psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;3374/* return -ENOTSUPP; */3375}33763377return 0;33783379}33803381static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 cipher, bool ucast)3382{3383u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;33843385u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :3386&psecuritypriv->dot118021XGrpPrivacy;33873388RTW_INFO("%s, ucast=%d, cipher=0x%x\n", __func__, ucast, cipher);338933903391if (!cipher) {3392*profile_cipher = _NO_PRIVACY_;3393psecuritypriv->ndisencryptstatus = ndisencryptstatus;3394return 0;3395}33963397switch (cipher) {3398case IW_AUTH_CIPHER_NONE:3399*profile_cipher = _NO_PRIVACY_;3400ndisencryptstatus = Ndis802_11EncryptionDisabled;3401#ifdef CONFIG_WAPI_SUPPORT3402if (psecuritypriv->dot11PrivacyAlgrthm == _SMS4_)3403*profile_cipher = _SMS4_;3404#endif3405break;3406case WLAN_CIPHER_SUITE_WEP40:3407*profile_cipher = _WEP40_;3408ndisencryptstatus = Ndis802_11Encryption1Enabled;3409break;3410case WLAN_CIPHER_SUITE_WEP104:3411*profile_cipher = _WEP104_;3412ndisencryptstatus = Ndis802_11Encryption1Enabled;3413break;3414case WLAN_CIPHER_SUITE_TKIP:3415*profile_cipher = _TKIP_;3416ndisencryptstatus = Ndis802_11Encryption2Enabled;3417break;3418case WLAN_CIPHER_SUITE_CCMP:3419*profile_cipher = _AES_;3420ndisencryptstatus = Ndis802_11Encryption3Enabled;3421break;3422#ifdef CONFIG_WAPI_SUPPORT3423case WLAN_CIPHER_SUITE_SMS4:3424*profile_cipher = _SMS4_;3425ndisencryptstatus = Ndis802_11_EncrypteionWAPI;3426break;3427#endif3428default:3429RTW_INFO("Unsupported cipher: 0x%x\n", cipher);3430return -ENOTSUPP;3431}34323433if (ucast) {3434psecuritypriv->ndisencryptstatus = ndisencryptstatus;34353436/* if(psecuritypriv->dot11PrivacyAlgrthm >= _AES_) */3437/* psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK; */3438}34393440return 0;3441}34423443static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv, u32 key_mgt)3444{3445RTW_INFO("%s, key_mgt=0x%x\n", __func__, key_mgt);34463447if (key_mgt == WLAN_AKM_SUITE_8021X) {3448/* *auth_type = UMAC_AUTH_TYPE_8021X; */3449psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;3450psecuritypriv->rsn_akm_suite_type = 1;3451} else if (key_mgt == WLAN_AKM_SUITE_PSK) {3452psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;3453psecuritypriv->rsn_akm_suite_type = 2;3454}3455#ifdef CONFIG_WAPI_SUPPORT3456else if (key_mgt == WLAN_AKM_SUITE_WAPI_PSK)3457psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;3458else if (key_mgt == WLAN_AKM_SUITE_WAPI_CERT)3459psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;3460#endif3461#ifdef CONFIG_RTW_80211R3462else if (key_mgt == WLAN_AKM_SUITE_FT_8021X) {3463psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;3464psecuritypriv->rsn_akm_suite_type = 3;3465} else if (key_mgt == WLAN_AKM_SUITE_FT_PSK) {3466psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;3467psecuritypriv->rsn_akm_suite_type = 4;3468}3469#endif3470else {3471RTW_INFO("Invalid key mgt: 0x%x\n", key_mgt);3472/* return -EINVAL; */3473}34743475return 0;3476}34773478static int rtw_cfg80211_set_wpa_ie(_adapter *padapter, u8 *pie, size_t ielen)3479{3480u8 *buf = NULL, *pos = NULL;3481int group_cipher = 0, pairwise_cipher = 0;3482u8 mfp_opt = MFP_NO;3483int ret = 0;3484int wpa_ielen = 0;3485int wpa2_ielen = 0;3486u8 *pwpa, *pwpa2;3487u8 null_addr[] = {0, 0, 0, 0, 0, 0};34883489if (pie == NULL || !ielen) {3490/* Treat this as normal case, but need to clear WIFI_UNDER_WPS */3491_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);3492goto exit;3493}34943495if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {3496ret = -EINVAL;3497goto exit;3498}34993500buf = rtw_zmalloc(ielen);3501if (buf == NULL) {3502ret = -ENOMEM;3503goto exit;3504}35053506_rtw_memcpy(buf, pie , ielen);35073508RTW_INFO("set wpa_ie(length:%zu):\n", ielen);3509RTW_INFO_DUMP(NULL, buf, ielen);35103511pos = buf;3512if (ielen < RSN_HEADER_LEN) {3513ret = -1;3514goto exit;3515}35163517pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen);3518if (pwpa && wpa_ielen > 0) {3519if (rtw_parse_wpa_ie(pwpa, wpa_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {3520padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;3521padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;3522_rtw_memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen + 2);35233524RTW_INFO("got wpa_ie, wpa_ielen:%u\n", wpa_ielen);3525}3526}35273528pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen);3529if (pwpa2 && wpa2_ielen > 0) {3530if (rtw_parse_wpa2_ie(pwpa2, wpa2_ielen + 2, &group_cipher, &pairwise_cipher, NULL, &mfp_opt) == _SUCCESS) {3531padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;3532padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;3533_rtw_memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0], wpa2_ielen + 2);35343535RTW_INFO("got wpa2_ie, wpa2_ielen:%u\n", wpa2_ielen);3536}3537}35383539if (group_cipher == 0)3540group_cipher = WPA_CIPHER_NONE;3541if (pairwise_cipher == 0)3542pairwise_cipher = WPA_CIPHER_NONE;35433544switch (group_cipher) {3545case WPA_CIPHER_NONE:3546padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;3547padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;3548break;3549case WPA_CIPHER_WEP40:3550padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;3551padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;3552break;3553case WPA_CIPHER_TKIP:3554padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;3555padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;3556break;3557case WPA_CIPHER_CCMP:3558padapter->securitypriv.dot118021XGrpPrivacy = _AES_;3559padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;3560break;3561case WPA_CIPHER_WEP104:3562padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;3563padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;3564break;3565}35663567switch (pairwise_cipher) {3568case WPA_CIPHER_NONE:3569padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;3570padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;3571break;3572case WPA_CIPHER_WEP40:3573padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;3574padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;3575break;3576case WPA_CIPHER_TKIP:3577padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;3578padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;3579break;3580case WPA_CIPHER_CCMP:3581padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;3582padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;3583break;3584case WPA_CIPHER_WEP104:3585padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;3586padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;3587break;3588}35893590if (mfp_opt == MFP_INVALID) {3591RTW_INFO(FUNC_ADPT_FMT" invalid MFP setting\n", FUNC_ADPT_ARG(padapter));3592ret = -EINVAL;3593goto exit;3594}3595padapter->securitypriv.mfp_opt = mfp_opt;35963597{/* handle wps_ie */3598uint wps_ielen;3599u8 *wps_ie;36003601wps_ie = rtw_get_wps_ie(buf, ielen, NULL, &wps_ielen);3602if (wps_ie && wps_ielen > 0) {3603RTW_INFO("got wps_ie, wps_ielen:%u\n", wps_ielen);3604padapter->securitypriv.wps_ie_len = wps_ielen < MAX_WPS_IE_LEN ? wps_ielen : MAX_WPS_IE_LEN;3605_rtw_memcpy(padapter->securitypriv.wps_ie, wps_ie, padapter->securitypriv.wps_ie_len);3606set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);3607} else3608_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);3609}36103611#ifdef CONFIG_P2P3612{/* check p2p_ie for assoc req; */3613uint p2p_ielen = 0;3614u8 *p2p_ie;3615struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);36163617p2p_ie = rtw_get_p2p_ie(buf, ielen, NULL, &p2p_ielen);3618if (p2p_ie) {3619#ifdef CONFIG_DEBUG_CFG802113620RTW_INFO("%s p2p_assoc_req_ielen=%d\n", __FUNCTION__, p2p_ielen);3621#endif36223623if (pmlmepriv->p2p_assoc_req_ie) {3624u32 free_len = pmlmepriv->p2p_assoc_req_ie_len;3625pmlmepriv->p2p_assoc_req_ie_len = 0;3626rtw_mfree(pmlmepriv->p2p_assoc_req_ie, free_len);3627pmlmepriv->p2p_assoc_req_ie = NULL;3628}36293630pmlmepriv->p2p_assoc_req_ie = rtw_malloc(p2p_ielen);3631if (pmlmepriv->p2p_assoc_req_ie == NULL) {3632RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);3633goto exit;3634}3635_rtw_memcpy(pmlmepriv->p2p_assoc_req_ie, p2p_ie, p2p_ielen);3636pmlmepriv->p2p_assoc_req_ie_len = p2p_ielen;3637}3638}3639#endif /* CONFIG_P2P */36403641#ifdef CONFIG_WFD3642{3643uint wfd_ielen = 0;3644u8 *wfd_ie;3645struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);36463647wfd_ie = rtw_get_wfd_ie(buf, ielen, NULL, &wfd_ielen);3648if (wfd_ie) {3649#ifdef CONFIG_DEBUG_CFG802113650RTW_INFO("%s wfd_assoc_req_ielen=%d\n", __FUNCTION__, wfd_ielen);3651#endif36523653if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_ASSOC_REQ_IE, wfd_ie, wfd_ielen) != _SUCCESS)3654goto exit;3655}3656}3657#endif /* CONFIG_WFD */36583659/* TKIP and AES disallow multicast packets until installing group key */3660if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_3661|| padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_3662|| padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)3663/* WPS open need to enable multicast */3664/* || check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == _TRUE) */3665rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);366636673668exit:3669if (buf)3670rtw_mfree(buf, ielen);3671if (ret)3672_clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);36733674return ret;3675}36763677static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,3678struct cfg80211_ibss_params *params)3679{3680_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);3681NDIS_802_11_SSID ndis_ssid;3682struct security_priv *psecuritypriv = &padapter->securitypriv;3683struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;3684#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))3685struct cfg80211_chan_def *pch_def;3686#endif3687struct ieee80211_channel *pch;3688int ret = 0;36893690#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))3691pch_def = (struct cfg80211_chan_def *)(¶ms->chandef);3692pch = (struct ieee80211_channel *) pch_def->chan;3693#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))3694pch = (struct ieee80211_channel *)(params->channel);3695#endif36963697if (!params->ssid || !params->ssid_len) {3698ret = -EINVAL;3699goto exit;3700}37013702if (params->ssid_len > IW_ESSID_MAX_SIZE) {3703ret = -E2BIG;3704goto exit;3705}37063707rtw_ps_deny(padapter, PS_DENY_JOIN);3708if (_FAIL == rtw_pwr_wakeup(padapter)) {3709ret = -EPERM;3710goto cancel_ps_deny;3711}37123713#ifdef CONFIG_CONCURRENT_MODE3714if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING)) {3715RTW_INFO("%s, but buddy_intf is under linking\n", __FUNCTION__);3716ret = -EINVAL;3717goto cancel_ps_deny;3718}3719rtw_mi_buddy_scan_abort(padapter, _TRUE); /* OR rtw_mi_scan_abort(padapter, _TRUE);*/3720#endif /*CONFIG_CONCURRENT_MODE*/372137223723_rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));3724ndis_ssid.SsidLength = params->ssid_len;3725_rtw_memcpy(ndis_ssid.Ssid, (u8 *)params->ssid, params->ssid_len);37263727/* RTW_INFO("ssid=%s, len=%zu\n", ndis_ssid.Ssid, params->ssid_len); */37283729psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;3730psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;3731psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;3732psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */3733psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;37343735ret = rtw_cfg80211_set_auth_type(psecuritypriv, NL80211_AUTHTYPE_OPEN_SYSTEM);3736rtw_set_802_11_authentication_mode(padapter, psecuritypriv->ndisauthtype);37373738RTW_INFO("%s: center_freq = %d\n", __func__, pch->center_freq);3739pmlmeext->cur_channel = rtw_freq2ch(pch->center_freq);37403741if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) {3742ret = -1;3743goto cancel_ps_deny;3744}37453746cancel_ps_deny:3747rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);3748exit:3749return ret;3750}37513752static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)3753{3754_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);3755struct wireless_dev *rtw_wdev = padapter->rtw_wdev;3756enum nl80211_iftype old_type;3757int ret = 0;37583759RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));37603761#if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_DISCONNECT)3762rtw_wdev_set_not_indic_disco(adapter_wdev_data(padapter), 1);3763#endif37643765old_type = rtw_wdev->iftype;37663767rtw_set_to_roam(padapter, 0);37683769if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {3770rtw_scan_abort(padapter);3771LeaveAllPowerSaveMode(padapter);37723773rtw_wdev->iftype = NL80211_IFTYPE_STATION;37743775if (rtw_set_802_11_infrastructure_mode(padapter, Ndis802_11Infrastructure, 0) == _FALSE) {3776rtw_wdev->iftype = old_type;3777ret = -EPERM;3778goto leave_ibss;3779}3780rtw_setopmode_cmd(padapter, Ndis802_11Infrastructure, RTW_CMDF_WAIT_ACK);3781}37823783leave_ibss:3784#if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_DISCONNECT)3785rtw_wdev_set_not_indic_disco(adapter_wdev_data(padapter), 0);3786#endif37873788return 0;3789}37903791bool rtw_cfg80211_is_connect_requested(_adapter *adapter)3792{3793struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);3794_irqL irqL;3795bool requested;37963797_enter_critical_bh(&pwdev_priv->connect_req_lock, &irqL);3798requested = pwdev_priv->connect_req ? 1 : 0;3799_exit_critical_bh(&pwdev_priv->connect_req_lock, &irqL);38003801return requested;3802}38033804static int _rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev)3805{3806_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);380738083809/* if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)) */3810{3811rtw_scan_abort(padapter);3812rtw_join_abort_timeout(padapter, 300);3813LeaveAllPowerSaveMode(padapter);3814rtw_disassoc_cmd(padapter, 500, RTW_CMDF_WAIT_ACK);3815#ifdef CONFIG_RTW_REPEATER_SON3816rtw_rson_do_disconnect(padapter);3817#endif3818RTW_INFO("%s...call rtw_indicate_disconnect\n", __func__);38193820rtw_free_assoc_resources_cmd(padapter, _TRUE, RTW_CMDF_WAIT_ACK);38213822/* indicate locally_generated = 0 when suspend */3823#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))3824rtw_indicate_disconnect(padapter, 0, wiphy->dev.power.is_prepared ? _FALSE : _TRUE);3825#else3826/*3827* for kernel < 4.2, DISCONNECT event is hardcoded with3828* NL80211_ATTR_DISCONNECTED_BY_AP=1 in NL80211 layer3829* no need to judge if under suspend3830*/3831rtw_indicate_disconnect(padapter, 0, _TRUE);3832#endif38333834rtw_pwr_wakeup(padapter);3835}3836return 0;3837}38383839#if (KERNEL_VERSION(4, 17, 0) > LINUX_VERSION_CODE)3840static bool rtw_check_connect_sae_compat(struct cfg80211_connect_params *sme)3841{3842struct rtw_ieee802_11_elems elems;3843struct rsne_info info;3844u8 AKM_SUITE_SAE[] = { 0x00, 0x0f, 0xac, 8 };3845int i;38463847if (sme->auth_type != 1)3848return false;38493850if (rtw_ieee802_11_parse_elems((u8 *)sme->ie, sme->ie_len, &elems, 0)3851== ParseFailed)3852return false;38533854if (!elems.rsn_ie)3855return false;38563857if (rtw_rsne_info_parse(elems.rsn_ie - 2, elems.rsn_ie_len + 2, &info) == _FAIL)3858return false;38593860for (i = 0; i < info.akm_cnt; i++)3861if (memcmp(info.akm_list + i * RSN_SELECTOR_LEN,3862AKM_SUITE_SAE, RSN_SELECTOR_LEN) == 0)3863return true;38643865return false;3866}3867#else3868#define rtw_check_connect_sae_compat(sme) false3869#endif38703871static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,3872struct cfg80211_connect_params *sme)3873{3874int ret = 0;3875NDIS_802_11_AUTHENTICATION_MODE authmode;3876NDIS_802_11_SSID ndis_ssid;3877/* u8 matched_by_bssid=_FALSE; */3878/* u8 matched_by_ssid=_FALSE; */3879_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);3880struct security_priv *psecuritypriv = &padapter->securitypriv;3881struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);3882struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3883_irqL irqL;38843885#if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_CONNECT)3886rtw_wdev_set_not_indic_disco(pwdev_priv, 1);3887#endif38883889RTW_INFO("=>"FUNC_NDEV_FMT" - Start to Connection\n", FUNC_NDEV_ARG(ndev));3890RTW_INFO("privacy=%d, key=%p, key_len=%d, key_idx=%d, auth_type=%d\n",3891sme->privacy, sme->key, sme->key_len, sme->key_idx, sme->auth_type);38923893if (rtw_check_connect_sae_compat(sme)) {3894sme->auth_type = NL80211_AUTHTYPE_SAE;3895RTW_INFO("%s set sme->auth_type=%d for SAE compat\n", __FUNCTION__,3896NL80211_AUTHTYPE_SAE);3897}38983899if (pwdev_priv->block == _TRUE) {3900ret = -EBUSY;3901RTW_INFO("%s wdev_priv.block is set\n", __FUNCTION__);3902goto exit;3903}39043905if (check_fwstate(pmlmepriv, _FW_LINKED | _FW_UNDER_LINKING) == _TRUE) {39063907_rtw_disconnect(wiphy, ndev);3908RTW_INFO("%s disconnect before connecting! fw_state=0x%x\n",3909__FUNCTION__, pmlmepriv->fw_state);3910}39113912#ifdef CONFIG_PLATFORM_MSTAR_SCAN_BEFORE_CONNECT3913printk("MStar Android!\n");3914if (pwdev_priv->bandroid_scan == _FALSE) {3915#ifdef CONFIG_P2P3916struct wifidirect_info *pwdinfo = &(padapter->wdinfo);3917if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))3918#endif /* CONFIG_P2P */3919{3920ret = -EBUSY;3921printk("Android hasn't attached yet!\n");3922goto exit;3923}3924}3925#endif39263927if (!sme->ssid || !sme->ssid_len) {3928ret = -EINVAL;3929goto exit;3930}39313932if (sme->ssid_len > IW_ESSID_MAX_SIZE) {3933ret = -E2BIG;3934goto exit;3935}39363937rtw_ps_deny(padapter, PS_DENY_JOIN);3938if (_FAIL == rtw_pwr_wakeup(padapter)) {3939ret = -EPERM;3940goto cancel_ps_deny;3941}39423943rtw_mi_scan_abort(padapter, _TRUE);39443945rtw_join_abort_timeout(padapter, 300);3946#ifdef CONFIG_CONCURRENT_MODE3947if (rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING)) {3948ret = -EINVAL;3949goto cancel_ps_deny;3950}3951#endif39523953_rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));3954ndis_ssid.SsidLength = sme->ssid_len;3955_rtw_memcpy(ndis_ssid.Ssid, (u8 *)sme->ssid, sme->ssid_len);39563957RTW_INFO("ssid=%s, len=%zu\n", ndis_ssid.Ssid, sme->ssid_len);395839593960if (sme->bssid)3961RTW_INFO("bssid="MAC_FMT"\n", MAC_ARG(sme->bssid));396239633964psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;3965psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;3966psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;3967psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */3968psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;3969psecuritypriv->auth_alg = WLAN_AUTH_OPEN;3970psecuritypriv->extauth_status = WLAN_STATUS_UNSPECIFIED_FAILURE;39713972#ifdef CONFIG_WAPI_SUPPORT3973padapter->wapiInfo.bWapiEnable = false;3974#endif39753976ret = rtw_cfg80211_set_wpa_version(psecuritypriv, sme->crypto.wpa_versions);3977if (ret < 0)3978goto cancel_ps_deny;39793980#ifdef CONFIG_WAPI_SUPPORT3981if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {3982padapter->wapiInfo.bWapiEnable = true;3983padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;3984padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;3985}3986#endif39873988ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);39893990#ifdef CONFIG_WAPI_SUPPORT3991if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_WAPI)3992padapter->mlmeextpriv.mlmext_info.auth_algo = psecuritypriv->dot11AuthAlgrthm;3993#endif399439953996if (ret < 0)3997goto cancel_ps_deny;39983999RTW_INFO("%s, ie_len=%zu\n", __func__, sme->ie_len);40004001ret = rtw_cfg80211_set_wpa_ie(padapter, (u8 *)sme->ie, sme->ie_len);4002if (ret < 0)4003goto cancel_ps_deny;40044005if (sme->crypto.n_ciphers_pairwise) {4006ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.ciphers_pairwise[0], _TRUE);4007if (ret < 0)4008goto cancel_ps_deny;4009}40104011/* For WEP Shared auth */4012if (sme->key_len > 0 && sme->key) {4013u32 wep_key_idx, wep_key_len, wep_total_len;4014NDIS_802_11_WEP *pwep = NULL;4015RTW_INFO("%s(): Shared/Auto WEP\n", __FUNCTION__);40164017wep_key_idx = sme->key_idx;4018wep_key_len = sme->key_len;40194020if (sme->key_idx > WEP_KEYS) {4021ret = -EINVAL;4022goto cancel_ps_deny;4023}40244025if (wep_key_len > 0) {4026wep_key_len = wep_key_len <= 5 ? 5 : 13;4027wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);4028pwep = (NDIS_802_11_WEP *) rtw_malloc(wep_total_len);4029if (pwep == NULL) {4030RTW_INFO(" wpa_set_encryption: pwep allocate fail !!!\n");4031ret = -ENOMEM;4032goto cancel_ps_deny;4033}40344035_rtw_memset(pwep, 0, wep_total_len);40364037pwep->KeyLength = wep_key_len;4038pwep->Length = wep_total_len;40394040if (wep_key_len == 13) {4041padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;4042padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;4043}4044} else {4045ret = -EINVAL;4046goto cancel_ps_deny;4047}40484049pwep->KeyIndex = wep_key_idx;4050pwep->KeyIndex |= 0x80000000;40514052_rtw_memcpy(pwep->KeyMaterial, (void *)sme->key, pwep->KeyLength);40534054if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)4055ret = -EOPNOTSUPP ;40564057if (pwep)4058rtw_mfree((u8 *)pwep, wep_total_len);40594060if (ret < 0)4061goto cancel_ps_deny;4062}40634064ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.cipher_group, _FALSE);4065if (ret < 0)4066return ret;40674068if (sme->crypto.n_akm_suites) {4069ret = rtw_cfg80211_set_key_mgt(psecuritypriv, sme->crypto.akm_suites[0]);4070if (ret < 0)4071goto cancel_ps_deny;4072}4073#ifdef CONFIG_8011R4074else {4075/*It could be a connection without RSN IEs*/4076psecuritypriv->rsn_akm_suite_type = 0;4077}4078#endif40794080#ifdef CONFIG_WAPI_SUPPORT4081if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_WAPI_PSK)4082padapter->wapiInfo.bWapiPSK = true;4083else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_WAPI_CERT)4084padapter->wapiInfo.bWapiPSK = false;4085#endif40864087authmode = psecuritypriv->ndisauthtype;4088rtw_set_802_11_authentication_mode(padapter, authmode);40894090/* rtw_set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */40914092if (rtw_set_802_11_connect(padapter, (u8 *)sme->bssid, &ndis_ssid) == _FALSE) {4093ret = -1;4094goto cancel_ps_deny;4095}409640974098_enter_critical_bh(&pwdev_priv->connect_req_lock, &irqL);40994100if (pwdev_priv->connect_req) {4101rtw_wdev_free_connect_req(pwdev_priv);4102RTW_INFO(FUNC_NDEV_FMT" free existing connect_req\n", FUNC_NDEV_ARG(ndev));4103}41044105pwdev_priv->connect_req = (struct cfg80211_connect_params *)rtw_malloc(sizeof(*pwdev_priv->connect_req));4106if (pwdev_priv->connect_req)4107_rtw_memcpy(pwdev_priv->connect_req, sme, sizeof(*pwdev_priv->connect_req));4108else4109RTW_WARN(FUNC_NDEV_FMT" alloc connect_req fail\n", FUNC_NDEV_ARG(ndev));41104111_exit_critical_bh(&pwdev_priv->connect_req_lock, &irqL);41124113RTW_INFO("set ssid:dot11AuthAlgrthm=%d, dot11PrivacyAlgrthm=%d, dot118021XGrpPrivacy=%d\n", psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,4114psecuritypriv->dot118021XGrpPrivacy);41154116cancel_ps_deny:4117rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);41184119exit:4120RTW_INFO("<=%s, ret %d\n", __FUNCTION__, ret);41214122#if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_CONNECT)4123rtw_wdev_set_not_indic_disco(pwdev_priv, 0);4124#endif41254126return ret;4127}41284129static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,4130u16 reason_code)4131{4132_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);41334134RTW_INFO(FUNC_NDEV_FMT" - Start to Disconnect\n", FUNC_NDEV_ARG(ndev));41354136#if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_DISCONNECT)4137#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))4138if (!wiphy->dev.power.is_prepared)4139#endif4140rtw_wdev_set_not_indic_disco(adapter_wdev_data(padapter), 1);4141#endif41424143rtw_set_to_roam(padapter, 0);41444145/* if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)) */4146{4147_rtw_disconnect(wiphy, ndev);4148}41494150#if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_DISCONNECT)4151rtw_wdev_set_not_indic_disco(adapter_wdev_data(padapter), 0);4152#endif41534154RTW_INFO(FUNC_NDEV_FMT" return 0\n", FUNC_NDEV_ARG(ndev));4155return 0;4156}41574158static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,4159#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))4160struct wireless_dev *wdev,4161#endif4162#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) || defined(COMPAT_KERNEL_RELEASE)4163enum nl80211_tx_power_setting type, int mbm)4164#else4165enum tx_power_setting type, int dbm)4166#endif4167{41684169// Set TXPower code from aircrack-ng 5.6.4.241704171_adapter *padapter = wiphy_to_adapter(wiphy);4172HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);4173int value;4174#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) || defined(COMPAT_KERNEL_RELEASE)4175value = mbm/100;4176#else4177value = dbm;4178#endif41794180// Limits to '4000mw'4181if(value < 0)4182value = 0;4183if(value > 40)4184value = 40;41854186if(type == NL80211_TX_POWER_FIXED) {4187pHalData->CurrentTxPwrIdx = value;4188rtw_hal_set_tx_power_level(padapter, pHalData->current_channel);4189} else4190return -EOPNOTSUPP;41914192#if 04193struct iwm_priv *iwm = wiphy_to_iwm(wiphy);4194int ret;41954196switch (type) {4197case NL80211_TX_POWER_AUTOMATIC:4198return 0;4199case NL80211_TX_POWER_FIXED:4200if (mbm < 0 || (mbm % 100))4201return -EOPNOTSUPP;42024203if (!test_bit(IWM_STATUS_READY, &iwm->status))4204return 0;42054206ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,4207CFG_TX_PWR_LIMIT_USR,4208MBM_TO_DBM(mbm) * 2);4209if (ret < 0)4210return ret;42114212return iwm_tx_power_trigger(iwm);4213default:4214IWM_ERR(iwm, "Unsupported power type: %d\n", type);4215return -EOPNOTSUPP;4216}4217#endif4218RTW_INFO("%s\n", __func__);4219return 0;4220}42214222static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,4223#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))4224struct wireless_dev *wdev,4225#endif4226int *dbm)4227{4228_adapter *padapter = wiphy_to_adapter(wiphy);4229HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);42304231RTW_INFO("%s\n", __func__);42324233*dbm = pHalData->CurrentTxPwrIdx;42344235return 0;4236}42374238inline bool rtw_cfg80211_pwr_mgmt(_adapter *adapter)4239{4240struct rtw_wdev_priv *rtw_wdev_priv = adapter_wdev_data(adapter);4241return rtw_wdev_priv->power_mgmt;4242}42434244static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,4245struct net_device *ndev,4246bool enabled, int timeout)4247{4248_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);4249struct rtw_wdev_priv *rtw_wdev_priv = adapter_wdev_data(padapter);42504251RTW_INFO(FUNC_NDEV_FMT" enabled:%u, timeout:%d\n", FUNC_NDEV_ARG(ndev),4252enabled, timeout);42534254rtw_wdev_priv->power_mgmt = enabled;42554256#ifdef CONFIG_LPS4257if (!enabled)4258rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE_CFG80211_PWRMGMT, 0);4259#endif42604261return 0;4262}42634264static void _rtw_set_pmksa(struct net_device *ndev,4265u8 *bssid, u8 *pmkid)4266{4267_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);4268struct security_priv *psecuritypriv = &padapter->securitypriv;4269u8 index, blInserted = _FALSE;42704271/* overwrite PMKID */4272for (index = 0 ; index < NUM_PMKID_CACHE; index++) {4273if (_rtw_memcmp(psecuritypriv->PMKIDList[index].Bssid, bssid, ETH_ALEN) == _TRUE) {4274/* BSSID is matched, the same AP => rewrite with new PMKID. */4275RTW_INFO("BSSID("MAC_FMT") exists in the PMKList.\n", MAC_ARG(bssid));42764277_rtw_memcpy(psecuritypriv->PMKIDList[index].PMKID, pmkid, WLAN_PMKID_LEN);4278psecuritypriv->PMKIDList[index].bUsed = _TRUE;4279psecuritypriv->PMKIDIndex = index + 1;4280blInserted = _TRUE;4281break;4282}4283}42844285if (!blInserted) {4286/* Find a new entry */4287RTW_INFO("Use the new entry index = %d for this PMKID.\n",4288psecuritypriv->PMKIDIndex);42894290_rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, bssid, ETH_ALEN);4291_rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pmkid, WLAN_PMKID_LEN);42924293psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = _TRUE;4294psecuritypriv->PMKIDIndex++ ;4295if (psecuritypriv->PMKIDIndex == 16)4296psecuritypriv->PMKIDIndex = 0;4297}4298}42994300static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,4301struct net_device *ndev,4302struct cfg80211_pmksa *pmksa)4303{4304u8 index, blInserted = _FALSE;4305_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);4306struct mlme_priv *mlme = &padapter->mlmepriv;4307struct security_priv *psecuritypriv = &padapter->securitypriv;4308u8 strZeroMacAddress[ETH_ALEN] = { 0x00 };4309bool sae_auth = rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE);43104311RTW_INFO(FUNC_NDEV_FMT" "MAC_FMT" "KEY_FMT"\n", FUNC_NDEV_ARG(ndev)4312, MAC_ARG(pmksa->bssid), KEY_ARG(pmksa->pmkid));43134314if (_rtw_memcmp((u8 *)pmksa->bssid, strZeroMacAddress, ETH_ALEN) == _TRUE)4315return -EINVAL;43164317if (check_fwstate(mlme, _FW_LINKED) == _FALSE && !sae_auth) {4318RTW_INFO(FUNC_NDEV_FMT" not set pmksa cause not in linked state\n", FUNC_NDEV_ARG(ndev));4319return -EINVAL;4320}43214322_rtw_set_pmksa(ndev, (u8 *)pmksa->bssid, (u8 *)pmksa->pmkid);43234324if (sae_auth &&4325(psecuritypriv->extauth_status == WLAN_STATUS_SUCCESS)) {4326RTW_PRINT("SAE: auth success, start assoc\n");4327start_clnt_assoc(padapter);4328}43294330return 0;4331}43324333static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,4334struct net_device *ndev,4335struct cfg80211_pmksa *pmksa)4336{4337u8 index, bMatched = _FALSE;4338_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);4339struct security_priv *psecuritypriv = &padapter->securitypriv;43404341RTW_INFO(FUNC_NDEV_FMT" "MAC_FMT" "KEY_FMT"\n", FUNC_NDEV_ARG(ndev)4342, MAC_ARG(pmksa->bssid), KEY_ARG(pmksa->pmkid));43434344for (index = 0 ; index < NUM_PMKID_CACHE; index++) {4345if (_rtw_memcmp(psecuritypriv->PMKIDList[index].Bssid, (u8 *)pmksa->bssid, ETH_ALEN) == _TRUE) {4346/* BSSID is matched, the same AP => Remove this PMKID information and reset it. */4347_rtw_memset(psecuritypriv->PMKIDList[index].Bssid, 0x00, ETH_ALEN);4348_rtw_memset(psecuritypriv->PMKIDList[index].PMKID, 0x00, WLAN_PMKID_LEN);4349psecuritypriv->PMKIDList[index].bUsed = _FALSE;4350bMatched = _TRUE;4351RTW_INFO(FUNC_NDEV_FMT" clear id:%hhu\n", FUNC_NDEV_ARG(ndev), index);4352break;4353}4354}43554356if (_FALSE == bMatched) {4357RTW_INFO(FUNC_NDEV_FMT" do not have matched BSSID\n"4358, FUNC_NDEV_ARG(ndev));4359return -EINVAL;4360}43614362return 0;4363}43644365static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,4366struct net_device *ndev)4367{4368_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);4369struct security_priv *psecuritypriv = &padapter->securitypriv;43704371RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));43724373_rtw_memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);4374psecuritypriv->PMKIDIndex = 0;43754376return 0;4377}43784379#ifdef CONFIG_AP_MODE4380void rtw_cfg80211_indicate_sta_assoc(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)4381{4382#if !defined(RTW_USE_CFG80211_STA_EVENT) && !defined(COMPAT_KERNEL_RELEASE)4383s32 freq;4384int channel;4385struct wireless_dev *pwdev = padapter->rtw_wdev;4386struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);4387#endif4388struct net_device *ndev = padapter->pnetdev;43894390RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));43914392#if defined(RTW_USE_CFG80211_STA_EVENT) || defined(COMPAT_KERNEL_RELEASE)4393{4394struct station_info sinfo;4395u8 ie_offset;4396if (get_frame_sub_type(pmgmt_frame) == WIFI_ASSOCREQ)4397ie_offset = _ASOCREQ_IE_OFFSET_;4398else /* WIFI_REASSOCREQ */4399ie_offset = _REASOCREQ_IE_OFFSET_;44004401memset(&sinfo, 0, sizeof(sinfo));4402sinfo.filled = STATION_INFO_ASSOC_REQ_IES;4403sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset;4404sinfo.assoc_req_ies_len = frame_len - WLAN_HDR_A3_LEN - ie_offset;4405cfg80211_new_sta(ndev, get_addr2_ptr(pmgmt_frame), &sinfo, GFP_ATOMIC);4406}4407#else /* defined(RTW_USE_CFG80211_STA_EVENT) */4408channel = pmlmeext->cur_channel;4409freq = rtw_ch2freq(channel);44104411#ifdef COMPAT_KERNEL_RELEASE4412rtw_cfg80211_rx_mgmt(pwdev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);4413#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)4414rtw_cfg80211_rx_mgmt(pwdev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);4415#else /* COMPAT_KERNEL_RELEASE */4416{4417/* to avoid WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION) when calling cfg80211_send_rx_assoc() */4418#ifndef CONFIG_PLATFORM_MSTAR4419pwdev->iftype = NL80211_IFTYPE_STATION;4420#endif /* CONFIG_PLATFORM_MSTAR */4421RTW_INFO("iftype=%d before call cfg80211_send_rx_assoc()\n", pwdev->iftype);4422rtw_cfg80211_send_rx_assoc(padapter, NULL, pmgmt_frame, frame_len);4423RTW_INFO("iftype=%d after call cfg80211_send_rx_assoc()\n", pwdev->iftype);4424pwdev->iftype = NL80211_IFTYPE_AP;4425/* cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC); */4426}4427#endif /* COMPAT_KERNEL_RELEASE */4428#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */44294430}44314432void rtw_cfg80211_indicate_sta_disassoc(_adapter *padapter, const u8 *da, unsigned short reason)4433{4434#if !defined(RTW_USE_CFG80211_STA_EVENT) && !defined(COMPAT_KERNEL_RELEASE)4435s32 freq;4436int channel;4437u8 *pmgmt_frame;4438uint frame_len;4439struct rtw_ieee80211_hdr *pwlanhdr;4440unsigned short *fctrl;4441u8 mgmt_buf[128] = {0};4442struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);4443struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);4444struct wireless_dev *wdev = padapter->rtw_wdev;4445#endif4446struct net_device *ndev = padapter->pnetdev;44474448RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));44494450#if defined(RTW_USE_CFG80211_STA_EVENT) || defined(COMPAT_KERNEL_RELEASE)4451cfg80211_del_sta(ndev, da, GFP_ATOMIC);4452#else /* defined(RTW_USE_CFG80211_STA_EVENT) */4453channel = pmlmeext->cur_channel;4454freq = rtw_ch2freq(channel);44554456pmgmt_frame = mgmt_buf;4457pwlanhdr = (struct rtw_ieee80211_hdr *)pmgmt_frame;44584459fctrl = &(pwlanhdr->frame_ctl);4460*(fctrl) = 0;44614462_rtw_memcpy(pwlanhdr->addr1, adapter_mac_addr(padapter), ETH_ALEN);4463_rtw_memcpy(pwlanhdr->addr2, da, ETH_ALEN);4464_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);44654466SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);4467pmlmeext->mgnt_seq++;4468set_frame_sub_type(pmgmt_frame, WIFI_DEAUTH);44694470pmgmt_frame += sizeof(struct rtw_ieee80211_hdr_3addr);4471frame_len = sizeof(struct rtw_ieee80211_hdr_3addr);44724473reason = cpu_to_le16(reason);4474pmgmt_frame = rtw_set_fixed_ie(pmgmt_frame, _RSON_CODE_ , (unsigned char *)&reason, &frame_len);44754476#ifdef COMPAT_KERNEL_RELEASE4477rtw_cfg80211_rx_mgmt(wdev, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);4478#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)4479rtw_cfg80211_rx_mgmt(wdev, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);4480#else /* COMPAT_KERNEL_RELEASE */4481cfg80211_send_disassoc(padapter->pnetdev, mgmt_buf, frame_len);4482/* cfg80211_rx_action(padapter->pnetdev, freq, mgmt_buf, frame_len, GFP_ATOMIC); */4483#endif /* COMPAT_KERNEL_RELEASE */4484#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */4485}44864487static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)4488{4489int ret = 0;44904491RTW_INFO("%s\n", __func__);44924493return ret;4494}44954496static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)4497{4498int ret = 0;44994500RTW_INFO("%s\n", __func__);45014502return ret;4503}45044505static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struct net_device *ndev)4506{4507int ret = 0;4508int rtap_len;4509int qos_len = 0;4510int dot11_hdr_len = 24;4511int snap_len = 6;4512unsigned char *pdata;4513u16 frame_ctl;4514unsigned char src_mac_addr[ETH_ALEN];4515unsigned char dst_mac_addr[ETH_ALEN];4516struct rtw_ieee80211_hdr *dot11_hdr;4517struct ieee80211_radiotap_header *rtap_hdr;4518_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);4519#ifdef CONFIG_DFS_MASTER4520struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);4521#endif45224523RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));45244525rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, skb->truesize);45264527if (IS_CH_WAITING(rfctl)) {4528#ifdef CONFIG_DFS_MASTER4529if (rtw_rfctl_overlap_radar_detect_ch(rfctl))4530goto fail;4531#endif4532}45334534if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))4535goto fail;45364537rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;4538if (unlikely(rtap_hdr->it_version))4539goto fail;45404541rtap_len = ieee80211_get_radiotap_len(skb->data);4542if (unlikely(skb->len < rtap_len))4543goto fail;45444545if (rtap_len != 14) {4546RTW_INFO("radiotap len (should be 14): %d\n", rtap_len);4547goto fail;4548}45494550/* Skip the ratio tap header */4551skb_pull(skb, rtap_len);45524553dot11_hdr = (struct rtw_ieee80211_hdr *)skb->data;4554frame_ctl = le16_to_cpu(dot11_hdr->frame_ctl);4555/* Check if the QoS bit is set */4556if ((frame_ctl & RTW_IEEE80211_FCTL_FTYPE) == RTW_IEEE80211_FTYPE_DATA) {4557/* Check if this ia a Wireless Distribution System (WDS) frame4558* which has 4 MAC addresses4559*/4560if (dot11_hdr->frame_ctl & 0x0080)4561qos_len = 2;4562if ((dot11_hdr->frame_ctl & 0x0300) == 0x0300)4563dot11_hdr_len += 6;45644565memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));4566memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));45674568/* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for4569* for two MAC addresses4570*/4571skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2);4572pdata = (unsigned char *)skb->data;4573memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));4574memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr));45754576RTW_INFO("should be eapol packet\n");45774578/* Use the real net device to transmit the packet */4579ret = _rtw_xmit_entry(skb, padapter->pnetdev);45804581return ret;45824583} else if ((frame_ctl & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE))4584== (RTW_IEEE80211_FTYPE_MGMT | RTW_IEEE80211_STYPE_ACTION)4585) {4586/* only for action frames */4587struct xmit_frame *pmgntframe;4588struct pkt_attrib *pattrib;4589unsigned char *pframe;4590/* u8 category, action, OUI_Subtype, dialogToken=0; */4591/* unsigned char *frame_body; */4592struct rtw_ieee80211_hdr *pwlanhdr;4593struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);4594struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);4595u8 *buf = skb->data;4596u32 len = skb->len;4597u8 category, action;4598int type = -1;45994600if (rtw_action_frame_parse(buf, len, &category, &action) == _FALSE) {4601RTW_INFO(FUNC_NDEV_FMT" frame_control:0x%x\n", FUNC_NDEV_ARG(ndev),4602le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl));4603goto fail;4604}46054606RTW_INFO("RTW_Tx:da="MAC_FMT" via "FUNC_NDEV_FMT"\n",4607MAC_ARG(GetAddr1Ptr(buf)), FUNC_NDEV_ARG(ndev));4608#ifdef CONFIG_P2P4609type = rtw_p2p_check_frames(padapter, buf, len, _TRUE);4610if (type >= 0)4611goto dump;4612#endif4613if (category == RTW_WLAN_CATEGORY_PUBLIC)4614RTW_INFO("RTW_Tx:%s\n", action_public_str(action));4615else4616RTW_INFO("RTW_Tx:category(%u), action(%u)\n", category, action);4617#ifdef CONFIG_P2P4618dump:4619#endif4620/* starting alloc mgmt frame to dump it */4621pmgntframe = alloc_mgtxmitframe(pxmitpriv);4622if (pmgntframe == NULL)4623goto fail;46244625/* update attribute */4626pattrib = &pmgntframe->attrib;4627update_mgntframe_attrib(padapter, pattrib);4628pattrib->retry_ctrl = _FALSE;46294630_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);46314632pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;46334634_rtw_memcpy(pframe, (void *)buf, len);4635pattrib->pktlen = len;46364637#ifdef CONFIG_P2P4638if (type >= 0)4639rtw_xframe_chk_wfd_ie(pmgntframe);4640#endif /* CONFIG_P2P */46414642pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;4643/* update seq number */4644pmlmeext->mgnt_seq = GetSequence(pwlanhdr);4645pattrib->seqnum = pmlmeext->mgnt_seq;4646pmlmeext->mgnt_seq++;464746484649pattrib->last_txcmdsz = pattrib->pktlen;46504651dump_mgntframe(padapter, pmgntframe);46524653} else4654RTW_INFO("frame_ctl=0x%x\n", frame_ctl & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE));465546564657fail:46584659rtw_skb_free(skb);46604661return 0;46624663}46644665#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))4666static void rtw_cfg80211_monitor_if_set_multicast_list(struct net_device *ndev)4667{4668RTW_INFO("%s\n", __func__);4669}4670#endif4671static int rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)4672{4673int ret = 0;46744675RTW_INFO("%s\n", __func__);46764677return ret;4678}46794680#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))4681static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {4682.ndo_open = rtw_cfg80211_monitor_if_open,4683.ndo_stop = rtw_cfg80211_monitor_if_close,4684.ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,4685#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))4686.ndo_set_multicast_list = rtw_cfg80211_monitor_if_set_multicast_list,4687#endif4688.ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,4689};4690#endif46914692static int rtw_cfg80211_add_monitor_if(_adapter *padapter, char *name, struct net_device **ndev)4693{4694int ret = 0;4695struct net_device *mon_ndev = NULL;4696struct wireless_dev *mon_wdev = NULL;4697struct rtw_netdev_priv_indicator *pnpi;4698struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);46994700if (!name) {4701RTW_INFO(FUNC_ADPT_FMT" without specific name\n", FUNC_ADPT_ARG(padapter));4702ret = -EINVAL;4703goto out;4704}47054706if (pwdev_priv->pmon_ndev) {4707RTW_INFO(FUNC_ADPT_FMT" monitor interface exist: "NDEV_FMT"\n",4708FUNC_ADPT_ARG(padapter), NDEV_ARG(pwdev_priv->pmon_ndev));4709ret = -EBUSY;4710goto out;4711}47124713mon_ndev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));4714if (!mon_ndev) {4715RTW_INFO(FUNC_ADPT_FMT" allocate ndev fail\n", FUNC_ADPT_ARG(padapter));4716ret = -ENOMEM;4717goto out;4718}47194720mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;4721strncpy(mon_ndev->name, name, IFNAMSIZ);4722mon_ndev->name[IFNAMSIZ - 1] = 0;4723#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 8))4724mon_ndev->priv_destructor = rtw_ndev_destructor;4725#else4726mon_ndev->destructor = rtw_ndev_destructor;4727#endif47284729#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))4730mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;4731#else4732mon_ndev->open = rtw_cfg80211_monitor_if_open;4733mon_ndev->stop = rtw_cfg80211_monitor_if_close;4734mon_ndev->hard_start_xmit = rtw_cfg80211_monitor_if_xmit_entry;4735mon_ndev->set_mac_address = rtw_cfg80211_monitor_if_set_mac_address;4736#endif47374738pnpi = netdev_priv(mon_ndev);4739pnpi->priv = padapter;4740pnpi->sizeof_priv = sizeof(_adapter);47414742/* wdev */4743mon_wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));4744if (!mon_wdev) {4745RTW_INFO(FUNC_ADPT_FMT" allocate mon_wdev fail\n", FUNC_ADPT_ARG(padapter));4746ret = -ENOMEM;4747goto out;4748}47494750mon_wdev->wiphy = padapter->rtw_wdev->wiphy;4751mon_wdev->netdev = mon_ndev;4752mon_wdev->iftype = NL80211_IFTYPE_MONITOR;4753mon_ndev->ieee80211_ptr = mon_wdev;47544755ret = register_netdevice(mon_ndev);4756if (ret)4757goto out;47584759*ndev = pwdev_priv->pmon_ndev = mon_ndev;4760_rtw_memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);47614762out:4763if (ret && mon_wdev) {4764rtw_mfree((u8 *)mon_wdev, sizeof(struct wireless_dev));4765mon_wdev = NULL;4766}47674768if (ret && mon_ndev) {4769free_netdev(mon_ndev);4770*ndev = mon_ndev = NULL;4771}47724773return ret;4774}47754776#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))4777static struct wireless_dev *4778#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)4779static struct net_device *4780#else4781static int4782#endif4783cfg80211_rtw_add_virtual_intf(4784struct wiphy *wiphy,4785#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))4786const char *name,4787#else4788char *name,4789#endif4790#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))4791unsigned char name_assign_type,4792#endif4793enum nl80211_iftype type,4794#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))4795u32 *flags,4796#endif4797struct vif_params *params)4798{4799int ret = 0;4800struct wireless_dev *wdev = NULL;4801struct net_device *ndev = NULL;4802_adapter *padapter;4803struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);48044805rtw_set_rtnl_lock_holder(dvobj, current);48064807RTW_INFO(FUNC_WIPHY_FMT" name:%s, type:%d\n", FUNC_WIPHY_ARG(wiphy), name, type);48084809switch (type) {4810case NL80211_IFTYPE_MONITOR:4811padapter = wiphy_to_adapter(wiphy); /* TODO: get ap iface ? */4812ret = rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);4813if (ret == 0)4814wdev = ndev->ieee80211_ptr;4815break;48164817#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))4818case NL80211_IFTYPE_P2P_CLIENT:4819case NL80211_IFTYPE_P2P_GO:4820#endif4821case NL80211_IFTYPE_STATION:4822case NL80211_IFTYPE_AP:4823#ifdef CONFIG_RTW_MESH4824case NL80211_IFTYPE_MESH_POINT:4825#endif4826padapter = dvobj_get_unregisterd_adapter(dvobj);4827if (!padapter) {4828RTW_WARN("adapter pool empty!\n");4829ret = -ENODEV;4830break;4831}4832if (rtw_os_ndev_init(padapter, name) != _SUCCESS) {4833RTW_WARN("ndev init fail!\n");4834ret = -ENODEV;4835break;4836}4837#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))4838if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO)4839rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);4840#endif4841ndev = padapter->pnetdev;4842wdev = ndev->ieee80211_ptr;4843break;48444845#if defined(CONFIG_P2P) && defined(RTW_DEDICATED_P2P_DEVICE)4846case NL80211_IFTYPE_P2P_DEVICE:4847ret = rtw_pd_iface_alloc(wiphy, name, &wdev);4848break;4849#endif48504851case NL80211_IFTYPE_ADHOC:4852case NL80211_IFTYPE_AP_VLAN:4853case NL80211_IFTYPE_WDS:4854default:4855ret = -ENODEV;4856RTW_INFO("Unsupported interface type\n");4857break;4858}48594860if (ndev)4861RTW_INFO(FUNC_WIPHY_FMT" ndev:%p, ret:%d\n", FUNC_WIPHY_ARG(wiphy), ndev, ret);4862else4863RTW_INFO(FUNC_WIPHY_FMT" wdev:%p, ret:%d\n", FUNC_WIPHY_ARG(wiphy), wdev, ret);48644865rtw_set_rtnl_lock_holder(dvobj, NULL);48664867#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))4868return wdev ? wdev : ERR_PTR(ret);4869#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)4870return ndev ? ndev : ERR_PTR(ret);4871#else4872return ret;4873#endif4874}48754876static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,4877#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))4878struct wireless_dev *wdev4879#else4880struct net_device *ndev4881#endif4882)4883{4884#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))4885struct net_device *ndev = wdev_to_ndev(wdev);4886#endif4887int ret = 0;4888struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);4889_adapter *adapter;4890struct rtw_wdev_priv *pwdev_priv;48914892rtw_set_rtnl_lock_holder(dvobj, current);48934894if (ndev) {4895adapter = (_adapter *)rtw_netdev_priv(ndev);4896pwdev_priv = adapter_wdev_data(adapter);48974898if (ndev == pwdev_priv->pmon_ndev) {4899unregister_netdevice(ndev);4900pwdev_priv->pmon_ndev = NULL;4901pwdev_priv->ifname_mon[0] = '\0';4902RTW_INFO(FUNC_NDEV_FMT" remove monitor ndev\n", FUNC_NDEV_ARG(ndev));4903} else {4904RTW_INFO(FUNC_NDEV_FMT" unregister ndev\n", FUNC_NDEV_ARG(ndev));4905rtw_os_ndev_unregister(adapter);4906}4907} else4908#if defined(CONFIG_P2P) && defined(RTW_DEDICATED_P2P_DEVICE)4909if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {4910if (wdev == wiphy_to_pd_wdev(wiphy))4911rtw_pd_iface_free(wiphy);4912else {4913RTW_ERR(FUNC_WIPHY_FMT" unknown P2P Device wdev:%p\n", FUNC_WIPHY_ARG(wiphy), wdev);4914rtw_warn_on(1);4915}4916} else4917#endif4918{4919ret = -EINVAL;4920goto exit;4921}49224923exit:4924rtw_set_rtnl_lock_holder(dvobj, NULL);4925return ret;4926}49274928static int rtw_add_beacon(_adapter *adapter, const u8 *head, size_t head_len, const u8 *tail, size_t tail_len)4929{4930int ret = 0;4931u8 *pbuf = NULL;4932uint len, wps_ielen = 0;4933uint p2p_ielen = 0;4934u8 got_p2p_ie = _FALSE;4935struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);4936/* struct sta_priv *pstapriv = &padapter->stapriv; */493749384939RTW_INFO("%s beacon_head_len=%zu, beacon_tail_len=%zu\n", __FUNCTION__, head_len, tail_len);494049414942if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)4943return -EINVAL;49444945if (head_len < 24)4946return -EINVAL;49474948#ifdef CONFIG_FW_HANDLE_TXBCN4949if (!rtw_ap_nums_check(adapter)) {4950RTW_ERR(FUNC_ADPT_FMT"failed, con't support over %d BCN\n", FUNC_ADPT_ARG(adapter), CONFIG_LIMITED_AP_NUM);4951return -EINVAL;4952}4953#endif /*CONFIG_FW_HANDLE_TXBCN*/49544955pbuf = rtw_zmalloc(head_len + tail_len);4956if (!pbuf)4957return -ENOMEM;495849594960/* _rtw_memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2); */49614962/* if((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<=0)) */4963/* pstapriv->max_num_sta = NUM_STA; */496449654966_rtw_memcpy(pbuf, (void *)head + 24, head_len - 24); /* 24=beacon header len. */4967_rtw_memcpy(pbuf + head_len - 24, (void *)tail, tail_len);49684969len = head_len + tail_len - 24;49704971/* check wps ie if inclued */4972if (rtw_get_wps_ie(pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL, &wps_ielen))4973RTW_INFO("add bcn, wps_ielen=%d\n", wps_ielen);49744975#ifdef CONFIG_P2P4976if (adapter->wdinfo.driver_interface == DRIVER_CFG80211) {4977/* check p2p if enable */4978if (rtw_get_p2p_ie(pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL, &p2p_ielen)) {4979struct wifidirect_info *pwdinfo = &(adapter->wdinfo);49804981RTW_INFO("got p2p_ie, len=%d\n", p2p_ielen);49824983got_p2p_ie = _TRUE;49844985if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {4986RTW_INFO("Enable P2P function for the first time\n");4987rtw_p2p_enable(adapter, P2P_ROLE_GO);49884989adapter->stapriv.expire_to = 3; /* 3x2 = 6 sec in p2p mode */4990} else {4991RTW_INFO("enter GO Mode, p2p_ielen=%d\n", p2p_ielen);49924993rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);4994rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);4995pwdinfo->intent = 15;4996}4997}4998}4999#endif /* CONFIG_P2P */50005001/* pbss_network->IEs will not include p2p_ie, wfd ie */5002rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, P2P_OUI, 4);5003rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, WFD_OUI, 4);50045005if (rtw_check_beacon_data(adapter, pbuf, len) == _SUCCESS) {5006#ifdef CONFIG_P2P5007/* check p2p if enable */5008if (got_p2p_ie == _TRUE) {5009struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;5010struct wifidirect_info *pwdinfo = &(adapter->wdinfo);5011pwdinfo->operating_channel = pmlmeext->cur_channel;5012}5013#endif /* CONFIG_P2P */5014ret = 0;5015} else5016ret = -EINVAL;501750185019rtw_mfree(pbuf, head_len + tail_len);50205021return ret;5022}50235024#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(COMPAT_KERNEL_RELEASE)5025static int cfg80211_rtw_add_beacon(struct wiphy *wiphy, struct net_device *ndev,5026struct beacon_parameters *info)5027{5028int ret = 0;5029_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);50305031RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));50325033if (rtw_cfg80211_sync_iftype(adapter) != _SUCCESS) {5034ret = -ENOTSUPP;5035goto exit;5036}5037rtw_mi_scan_abort(adapter, _TRUE);5038rtw_mi_buddy_set_scan_deny(adapter, 300);5039#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)5040ret = rtw_add_beacon(adapter, info->beacon.head, info->beacon.head_len, info->beacon.tail, info->beacon.tail_len);5041#else5042ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);5043#endif50445045exit:5046return ret;5047}50485049static int cfg80211_rtw_set_beacon(struct wiphy *wiphy, struct net_device *ndev,5050struct beacon_parameters *info)5051{5052_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);5053struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);50545055RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));50565057pmlmeext->bstart_bss = _TRUE;50585059cfg80211_rtw_add_beacon(wiphy, ndev, info);50605061return 0;5062}50635064static int cfg80211_rtw_del_beacon(struct wiphy *wiphy, struct net_device *ndev)5065{5066_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);50675068RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));50695070rtw_stop_ap_cmd(adapter, RTW_CMDF_WAIT_ACK);5071return 0;5072}5073#else5074static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,5075struct cfg80211_ap_settings *settings)5076{5077int ret = 0;5078_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);50795080RTW_INFO(FUNC_NDEV_FMT" hidden_ssid:%d, auth_type:%d\n", FUNC_NDEV_ARG(ndev),5081settings->hidden_ssid, settings->auth_type);50825083if (rtw_cfg80211_sync_iftype(adapter) != _SUCCESS) {5084ret = -ENOTSUPP;5085goto exit;5086}50875088/*5089Kernel < v5.1, the auth_type set as NL80211_AUTHTYPE_AUTOMATIC.5090if the AKM SAE in the RSN IE, we have to update the auth_type for SAE5091in rtw_check_beacon_data().5092*/5093rtw_cfg80211_set_auth_type(&adapter->securitypriv, settings->auth_type);50945095rtw_mi_scan_abort(adapter, _TRUE);5096rtw_mi_buddy_set_scan_deny(adapter, 300);50975098adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode = settings->hidden_ssid;5099ret = rtw_add_beacon(adapter, settings->beacon.head, settings->beacon.head_len,5100settings->beacon.tail, settings->beacon.tail_len);51015102// In cases like WPS, the proberesp and assocresp IEs vary from the beacon, and need to be explicitly set5103if(ret == 0) {5104if(settings->beacon.proberesp_ies && settings->beacon.proberesp_ies_len > 0) {5105rtw_cfg80211_set_mgnt_wpsp2pie(ndev, (char *)settings->beacon.proberesp_ies,5106settings->beacon.proberesp_ies_len, 0x2/*PROBE_RESP*/);5107}5108if(settings->beacon.assocresp_ies && settings->beacon.assocresp_ies_len < 0) {5109rtw_cfg80211_set_mgnt_wpsp2pie(ndev, (char *)settings->beacon.assocresp_ies,5110settings->beacon.assocresp_ies_len, 0x4/*ASSOC_RESP*/);5111}5112}51135114if (settings->ssid && settings->ssid_len) {5115WLAN_BSSID_EX *pbss_network = &adapter->mlmepriv.cur_network.network;5116WLAN_BSSID_EX *pbss_network_ext = &adapter->mlmeextpriv.mlmext_info.network;51175118if (0)5119RTW_INFO(FUNC_ADPT_FMT" ssid:(%s,%zu), from ie:(%s,%d)\n", FUNC_ADPT_ARG(adapter),5120settings->ssid, settings->ssid_len,5121pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength);51225123_rtw_memcpy(pbss_network->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);5124pbss_network->Ssid.SsidLength = settings->ssid_len;5125_rtw_memcpy(pbss_network_ext->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);5126pbss_network_ext->Ssid.SsidLength = settings->ssid_len;51275128if (0)5129RTW_INFO(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),5130pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,5131pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);5132}51335134exit:5135return ret;5136}51375138static int cfg80211_rtw_change_beacon(struct wiphy *wiphy, struct net_device *ndev,5139#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0))5140struct cfg80211_ap_update *info)5141#else5142struct cfg80211_beacon_data *info)5143#endif5144{5145int ret = 0;5146_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);51475148RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));51495150#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0))5151ret = rtw_add_beacon(adapter, info->beacon.head, info->beacon.head_len, info->beacon.tail, info->beacon.tail_len);5152#else5153ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);5154#endif51555156// In cases like WPS, the proberesp and assocresp IEs vary from the beacon, and need to be explicitly set5157if(ret == 0) {5158#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)5159if(info->beacon.proberesp_ies && info->beacon.proberesp_ies_len > 0) {5160rtw_cfg80211_set_mgnt_wpsp2pie(ndev, (char *)info->beacon.proberesp_ies, info->beacon.proberesp_ies_len, 0x2/*PROBE_RESP*/);5161#else5162if(info->proberesp_ies && info->proberesp_ies_len > 0) {5163rtw_cfg80211_set_mgnt_wpsp2pie(ndev, (char *)info->proberesp_ies, info->proberesp_ies_len, 0x2/*PROBE_RESP*/);5164#endif5165}5166#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)5167if(info->beacon.assocresp_ies && info->beacon.assocresp_ies_len > 0) {5168rtw_cfg80211_set_mgnt_wpsp2pie(ndev, (char *)info->beacon.assocresp_ies, info->beacon.assocresp_ies_len, 0x4/*ASSOC_RESP*/);5169#else5170if(info->assocresp_ies && info->assocresp_ies_len > 0) {5171rtw_cfg80211_set_mgnt_wpsp2pie(ndev, (char *)info->assocresp_ies, info->assocresp_ies_len, 0x4/*ASSOC_RESP*/);5172#endif5173}5174}51755176return ret;5177}51785179#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2))5180static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev,5181unsigned int link_id)5182#else5183static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)5184#endif5185{5186_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);51875188RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));51895190rtw_stop_ap_cmd(adapter, RTW_CMDF_WAIT_ACK);5191return 0;5192}5193#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) */51945195#if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))5196static int cfg80211_rtw_set_mac_acl(struct wiphy *wiphy, struct net_device *ndev,5197const struct cfg80211_acl_data *params)5198{5199_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);5200u8 acl_mode = RTW_ACL_MODE_DISABLED;5201int ret = -1;5202int i;52035204if (!params) {5205RTW_WARN(FUNC_ADPT_FMT" params NULL\n", FUNC_ADPT_ARG(adapter));5206rtw_macaddr_acl_clear(adapter, RTW_ACL_PERIOD_BSS);5207goto exit;5208}52095210RTW_INFO(FUNC_ADPT_FMT" acl_policy:%d, entry_num:%d\n"5211, FUNC_ADPT_ARG(adapter), params->acl_policy, params->n_acl_entries);52125213if (params->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED)5214acl_mode = RTW_ACL_MODE_ACCEPT_UNLESS_LISTED;5215else if (params->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED)5216acl_mode = RTW_ACL_MODE_DENY_UNLESS_LISTED;52175218rtw_macaddr_acl_clear(adapter, RTW_ACL_PERIOD_BSS);52195220rtw_set_macaddr_acl(adapter, RTW_ACL_PERIOD_BSS, acl_mode);52215222for (i = 0; i < params->n_acl_entries; i++)5223rtw_acl_add_sta(adapter, RTW_ACL_PERIOD_BSS, params->mac_addrs[i].addr);52245225ret = 0;52265227exit:5228return ret;5229}5230#endif /* CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) */52315232const char *_nl80211_sta_flags_str[] = {5233"INVALID",5234"AUTHORIZED",5235"SHORT_PREAMBLE",5236"WME",5237"MFP",5238"AUTHENTICATED",5239"TDLS_PEER",5240"ASSOCIATED",5241};52425243#define nl80211_sta_flags_str(_f) ((_f <= NL80211_STA_FLAG_MAX) ? _nl80211_sta_flags_str[_f] : _nl80211_sta_flags_str[0])52445245const char *_nl80211_plink_state_str[] = {5246"LISTEN",5247"OPN_SNT",5248"OPN_RCVD",5249"CNF_RCVD",5250"ESTAB",5251"HOLDING",5252"BLOCKED",5253"UNKNOWN",5254};52555256#define nl80211_plink_state_str(_s) ((_s < NUM_NL80211_PLINK_STATES) ? _nl80211_plink_state_str[_s] : _nl80211_plink_state_str[NUM_NL80211_PLINK_STATES])52575258#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))5259#define NL80211_PLINK_ACTION_NO_ACTION PLINK_ACTION_INVALID5260#define NL80211_PLINK_ACTION_OPEN PLINK_ACTION_OPEN5261#define NL80211_PLINK_ACTION_BLOCK PLINK_ACTION_BLOCK5262#define NUM_NL80211_PLINK_ACTIONS 35263#endif52645265const char *_nl80211_plink_actions_str[] = {5266"NO_ACTION",5267"OPEN",5268"BLOCK",5269"UNKNOWN",5270};52715272#define nl80211_plink_actions_str(_a) ((_a < NUM_NL80211_PLINK_ACTIONS) ? _nl80211_plink_actions_str[_a] : _nl80211_plink_actions_str[NUM_NL80211_PLINK_ACTIONS])52735274#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))5275const char *_nl80211_mesh_power_mode_str[] = {5276"UNKNOWN",5277"ACTIVE",5278"LIGHT_SLEEP",5279"DEEP_SLEEP",5280};52815282#define nl80211_mesh_power_mode_str(_p) ((_p <= NL80211_MESH_POWER_MAX) ? _nl80211_mesh_power_mode_str[_p] : _nl80211_mesh_power_mode_str[0])5283#endif52845285void dump_station_parameters(void *sel, struct wiphy *wiphy, const struct station_parameters *params)5286{5287#if DBG_RTW_CFG80211_STA_PARAM5288if (params->supported_rates_len) {5289#define SUPP_RATES_BUF_LEN (3 * RTW_G_RATES_NUM + 1)5290int i;5291char supp_rates_buf[SUPP_RATES_BUF_LEN] = {0};5292u8 cnt = 0;52935294rtw_warn_on(params->supported_rates_len > RTW_G_RATES_NUM);52955296for (i = 0; i < params->supported_rates_len; i++) {5297if (i >= RTW_G_RATES_NUM)5298break;5299cnt += snprintf(supp_rates_buf + cnt, SUPP_RATES_BUF_LEN - cnt -15300, "%02X ", params->supported_rates[i]);5301if (cnt >= SUPP_RATES_BUF_LEN - 1)5302break;5303}53045305RTW_PRINT_SEL(sel, "supported_rates:%s\n", supp_rates_buf);5306}53075308if (params->vlan)5309RTW_PRINT_SEL(sel, "vlan:"NDEV_FMT"\n", NDEV_ARG(params->vlan));53105311#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))5312if (params->sta_flags_mask) {5313#define STA_FLAGS_BUF_LEN 1285314int i = 0;5315char sta_flags_buf[STA_FLAGS_BUF_LEN] = {0};5316u8 cnt = 0;53175318for (i = 1; i <= NL80211_STA_FLAG_MAX; i++) {5319if (params->sta_flags_mask & BIT(i)) {5320cnt += snprintf(sta_flags_buf + cnt, STA_FLAGS_BUF_LEN - cnt -1, "%s=%u "5321, nl80211_sta_flags_str(i), (params->sta_flags_set & BIT(i)) ? 1 : 0);5322if (cnt >= STA_FLAGS_BUF_LEN - 1)5323break;5324}5325}53265327RTW_PRINT_SEL(sel, "sta_flags:%s\n", sta_flags_buf);5328}5329#else5330u32 station_flags;5331#error "TBD\n"5332#endif53335334if (params->listen_interval != -1)5335RTW_PRINT_SEL(sel, "listen_interval:%d\n", params->listen_interval);53365337if (params->aid)5338RTW_PRINT_SEL(sel, "aid:%u\n", params->aid);53395340#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))5341if (params->peer_aid)5342RTW_PRINT_SEL(sel, "peer_aid:%u\n", params->peer_aid);5343#endif53445345#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26))5346if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)5347RTW_PRINT_SEL(sel, "plink_action:%s\n", nl80211_plink_actions_str(params->plink_action));5348#endif53495350#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))5351#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))5352if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)5353#endif5354RTW_PRINT_SEL(sel, "plink_state:%s\n"5355, nl80211_plink_state_str(params->plink_state));5356#endif53575358#if 0 /* TODO */5359#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))5360const struct ieee80211_ht_cap *ht_capa;5361#endif5362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))5363const struct ieee80211_vht_cap *vht_capa;5364#endif5365#endif53665367#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))5368if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)5369RTW_PRINT_SEL(sel, "uapsd_queues:0x%02x\n", params->uapsd_queues);5370if (params->max_sp)5371RTW_PRINT_SEL(sel, "max_sp:%u\n", params->max_sp);5372#endif53735374#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))5375if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) {5376RTW_PRINT_SEL(sel, "local_pm:%s\n"5377, nl80211_mesh_power_mode_str(params->local_pm));5378}53795380if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)5381RTW_PRINT_SEL(sel, "capability:0x%04x\n", params->capability);53825383#if 0 /* TODO */5384const u8 *ext_capab;5385u8 ext_capab_len;5386#endif5387#endif53885389#if 0 /* TODO */5390#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))5391const u8 *supported_channels;5392u8 supported_channels_len;5393const u8 *supported_oper_classes;5394u8 supported_oper_classes_len;5395#endif53965397#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))5398u8 opmode_notif;5399bool opmode_notif_used;5400#endif54015402#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))5403int support_p2p_ps;5404#endif5405#endif5406#endif /* DBG_RTW_CFG80211_STA_PARAM */5407}54085409static int cfg80211_rtw_add_station(struct wiphy *wiphy, struct net_device *ndev,5410#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))5411u8 *mac,5412#else5413const u8 *mac,5414#endif5415struct station_parameters *params)5416{5417int ret = 0;5418_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);5419#if defined(CONFIG_TDLS) || defined(CONFIG_RTW_MESH)5420struct sta_priv *pstapriv = &padapter->stapriv;5421#endif5422#ifdef CONFIG_TDLS5423struct sta_info *psta;5424#endif /* CONFIG_TDLS */54255426RTW_INFO(FUNC_NDEV_FMT" mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(mac));54275428#if CONFIG_RTW_MACADDR_ACL5429if (rtw_access_ctrl(padapter, mac) == _FALSE) {5430RTW_INFO(FUNC_NDEV_FMT" deny by macaddr ACL\n", FUNC_NDEV_ARG(ndev));5431ret = -EINVAL;5432goto exit;5433}5434#endif54355436dump_station_parameters(RTW_DBGDUMP, wiphy, params);54375438#ifdef CONFIG_RTW_MESH5439if (MLME_IS_MESH(padapter)) {5440struct rtw_mesh_cfg *mcfg = &padapter->mesh_cfg;5441struct rtw_mesh_info *minfo = &padapter->mesh_info;5442struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;5443struct mesh_plink_ent *plink = NULL;5444struct wlan_network *scanned = NULL;5445bool acnode = 0;5446u8 add_new_sta = 0, probe_req = 0;5447_irqL irqL;54485449if (params->plink_state != NL80211_PLINK_LISTEN) {5450RTW_WARN(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(ndev), nl80211_plink_state_str(params->plink_state));5451rtw_warn_on(1);5452}5453if (!params->aid || params->aid > pstapriv->max_aid) {5454RTW_WARN(FUNC_NDEV_FMT" invalid aid:%u\n", FUNC_NDEV_ARG(ndev), params->aid);5455rtw_warn_on(1);5456ret = -EINVAL;5457goto exit;5458}54595460_enter_critical_bh(&(plink_ctl->lock), &irqL);54615462plink = _rtw_mesh_plink_get(padapter, mac);5463if (plink)5464goto release_plink_ctl;54655466#if CONFIG_RTW_MESH_PEER_BLACKLIST5467if (rtw_mesh_peer_blacklist_search(padapter, mac)) {5468RTW_INFO(FUNC_NDEV_FMT" deny by peer blacklist\n"5469, FUNC_NDEV_ARG(ndev));5470ret = -EINVAL;5471goto release_plink_ctl;5472}5473#endif54745475scanned = rtw_find_network(&padapter->mlmepriv.scanned_queue, mac);5476if (!scanned5477|| rtw_get_passing_time_ms(scanned->last_scanned) >= mcfg->peer_sel_policy.scanr_exp_ms5478) {5479if (!scanned)5480RTW_INFO(FUNC_NDEV_FMT" corresponding network not found\n", FUNC_NDEV_ARG(ndev));5481else5482RTW_INFO(FUNC_NDEV_FMT" corresponding network too old\n", FUNC_NDEV_ARG(ndev));54835484if (adapter_to_rfctl(padapter)->offch_state == OFFCHS_NONE)5485probe_req = 1;54865487ret = -EINVAL;5488goto release_plink_ctl;5489}54905491#if CONFIG_RTW_MESH_ACNODE_PREVENT5492if (plink_ctl->acnode_rsvd)5493acnode = rtw_mesh_scanned_is_acnode_confirmed(padapter, scanned);5494#endif54955496/* wpa_supplicant's auto peer will initiate peering when candidate peer is reported without max_peer_links consideration */5497if (plink_ctl->num >= mcfg->max_peer_links + acnode ? 1 : 0) {5498RTW_INFO(FUNC_NDEV_FMT" exceed max_peer_links:%u%s\n"5499, FUNC_NDEV_ARG(ndev), mcfg->max_peer_links, acnode ? " acn" : "");5500ret = -EINVAL;5501goto release_plink_ctl;5502}55035504if (!rtw_bss_is_candidate_mesh_peer(&padapter->mlmepriv.cur_network.network, &scanned->network, 1, 1)) {5505RTW_WARN(FUNC_NDEV_FMT" corresponding network is not candidate with same ch\n"5506, FUNC_NDEV_ARG(ndev));5507ret = -EINVAL;5508goto release_plink_ctl;5509}55105511#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST5512if (!rtw_mesh_cto_mgate_network_filter(padapter, scanned)) {5513RTW_INFO(FUNC_NDEV_FMT" peer filtered out by cto_mgate check\n"5514, FUNC_NDEV_ARG(ndev));5515ret = -EINVAL;5516goto release_plink_ctl;5517}5518#endif55195520if (_rtw_mesh_plink_add(padapter, mac) == _SUCCESS) {5521/* hook corresponding network in scan queue */5522plink = _rtw_mesh_plink_get(padapter, mac);5523plink->aid = params->aid;5524plink->scanned = scanned;55255526#if CONFIG_RTW_MESH_ACNODE_PREVENT5527if (acnode) {5528RTW_INFO(FUNC_ADPT_FMT" acnode "MAC_FMT"\n"5529, FUNC_ADPT_ARG(padapter), MAC_ARG(scanned->network.MacAddress));5530}5531#endif55325533add_new_sta = 1;5534} else {5535RTW_WARN(FUNC_NDEV_FMT" rtw_mesh_plink_add not success\n"5536, FUNC_NDEV_ARG(ndev));5537ret = -EINVAL;5538}5539release_plink_ctl:5540_exit_critical_bh(&(plink_ctl->lock), &irqL);55415542if (probe_req)5543issue_probereq(padapter, &padapter->mlmepriv.cur_network.network.mesh_id, mac);55445545if (add_new_sta) {5546struct station_info sinfo;55475548#ifdef CONFIG_DFS_MASTER5549if (IS_UNDER_CAC(adapter_to_rfctl(padapter)))5550rtw_force_stop_cac(adapter_to_rfctl(padapter), 300);5551#endif55525553/* indicate new sta */5554_rtw_memset(&sinfo, 0, sizeof(sinfo));5555cfg80211_new_sta(ndev, mac, &sinfo, GFP_ATOMIC);5556}5557goto exit;5558}5559#endif /* CONFIG_RTW_MESH */55605561#ifdef CONFIG_TDLS5562psta = rtw_get_stainfo(pstapriv, (u8 *)mac);5563if (psta == NULL) {5564psta = rtw_alloc_stainfo(pstapriv, (u8 *)mac);5565if (psta == NULL) {5566RTW_INFO("[%s] Alloc station for "MAC_FMT" fail\n", __FUNCTION__, MAC_ARG(mac));5567ret = -EOPNOTSUPP;5568goto exit;5569}5570}5571#endif /* CONFIG_TDLS */55725573exit:5574return ret;5575}55765577static int cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev,5578#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))5579u8 *mac5580#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))5581const u8 *mac5582#else5583struct station_del_parameters *params5584#endif5585)5586{5587int ret = 0;5588_irqL irqL;5589_list *phead, *plist;5590u8 updated = _FALSE;5591const u8 *target_mac;5592struct sta_info *psta = NULL;5593_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);5594struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);5595struct sta_priv *pstapriv = &padapter->stapriv;55965597#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))5598target_mac = mac;5599#else5600target_mac = params->mac;5601#endif56025603RTW_INFO("+"FUNC_NDEV_FMT" mac=%pM\n", FUNC_NDEV_ARG(ndev), target_mac);56045605if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE | WIFI_MESH_STATE)) != _TRUE) {5606RTW_INFO("%s, fw_state != FW_LINKED|WIFI_AP_STATE|WIFI_MESH_STATE\n", __func__);5607return -EINVAL;5608}560956105611if (!target_mac) {5612RTW_INFO("flush all sta, and cam_entry\n");56135614flush_all_cam_entry(padapter); /* clear CAM */56155616#ifdef CONFIG_AP_MODE5617ret = rtw_sta_flush(padapter, _TRUE);5618#endif5619return ret;5620}562156225623RTW_INFO("free sta macaddr =" MAC_FMT "\n", MAC_ARG(target_mac));56245625if (target_mac[0] == 0xff && target_mac[1] == 0xff &&5626target_mac[2] == 0xff && target_mac[3] == 0xff &&5627target_mac[4] == 0xff && target_mac[5] == 0xff)5628return -EINVAL;562956305631_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);56325633phead = &pstapriv->asoc_list;5634plist = get_next(phead);56355636/* check asoc_queue */5637while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {5638psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);56395640plist = get_next(plist);56415642if (_rtw_memcmp((u8 *)target_mac, psta->cmn.mac_addr, ETH_ALEN)) {5643if (psta->dot8021xalg == 1 && psta->bpairwise_key_installed == _FALSE)5644RTW_INFO("%s, sta's dot8021xalg = 1 and key_installed = _FALSE\n", __func__);5645else {5646RTW_INFO("free psta=%p, aid=%d\n", psta, psta->cmn.aid);56475648rtw_list_delete(&psta->asoc_list);5649pstapriv->asoc_list_cnt--;5650STA_SET_MESH_PLINK(psta, NULL);56515652/* _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); */5653if (MLME_IS_AP(padapter))5654updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_PREV_AUTH_NOT_VALID, _TRUE);5655else5656updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);5657/* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); */56585659psta = NULL;56605661break;5662}56635664}56655666}56675668_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);56695670associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);56715672#ifdef CONFIG_RTW_MESH5673if (MLME_IS_MESH(padapter))5674rtw_mesh_plink_del(padapter, target_mac);5675#endif56765677RTW_INFO("-"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));56785679return ret;56805681}56825683static int cfg80211_rtw_change_station(struct wiphy *wiphy, struct net_device *ndev,5684#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))5685u8 *mac,5686#else5687const u8 *mac,5688#endif5689struct station_parameters *params)5690{5691#ifdef CONFIG_RTW_MESH5692_adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);5693struct sta_priv *stapriv = &adapter->stapriv;5694struct sta_info *sta = NULL;5695_irqL irqL;5696#endif5697int ret = 0;56985699RTW_INFO(FUNC_NDEV_FMT" mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(mac));57005701dump_station_parameters(RTW_DBGDUMP, wiphy, params);57025703#ifdef CONFIG_RTW_MESH5704if (MLME_IS_MESH(adapter)) {5705enum cfg80211_station_type sta_type = CFG80211_STA_MESH_PEER_USER;5706struct rtw_mesh_info *minfo = &adapter->mesh_info;5707struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;5708struct mesh_plink_ent *plink = NULL;5709_irqL irqL2;5710struct sta_info *del_sta = NULL;57115712ret = cfg80211_check_station_change(wiphy, params, sta_type);5713if (ret) {5714RTW_INFO("cfg80211_check_station_change return %d\n", ret);5715goto exit;5716}57175718_enter_critical_bh(&(plink_ctl->lock), &irqL2);57195720plink = _rtw_mesh_plink_get(adapter, mac);5721if (!plink) {5722ret = -ENOENT;5723goto release_plink_ctl;5724}57255726plink->plink_state = nl80211_plink_state_to_rtw_plink_state(params->plink_state);57275728#if CONFIG_RTW_MESH_ACNODE_PREVENT5729if (params->plink_state == NL80211_PLINK_OPN_SNT5730#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))5731&& (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)5732#endif5733) {5734if (rtw_mesh_scanned_is_acnode_confirmed(adapter, plink->scanned)5735&& rtw_mesh_acnode_prevent_allow_sacrifice(adapter)5736) {5737struct sta_info *sac = rtw_mesh_acnode_prevent_pick_sacrifice(adapter);57385739if (sac) {5740del_sta = sac;5741_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);5742if (!rtw_is_list_empty(&del_sta->asoc_list)) {5743rtw_list_delete(&del_sta->asoc_list);5744stapriv->asoc_list_cnt--;5745STA_SET_MESH_PLINK(del_sta, NULL);5746}5747_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);5748RTW_INFO(FUNC_ADPT_FMT" sacrifice "MAC_FMT" for acnode\n"5749, FUNC_ADPT_ARG(adapter), MAC_ARG(del_sta->cmn.mac_addr));5750}5751}5752} else5753#endif5754if ((params->plink_state == NL80211_PLINK_OPN_RCVD5755|| params->plink_state == NL80211_PLINK_CNF_RCVD5756|| params->plink_state == NL80211_PLINK_ESTAB)5757#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))5758&& (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)5759#endif5760) {5761sta = rtw_get_stainfo(stapriv, mac);5762if (!sta) {5763sta = rtw_alloc_stainfo(stapriv, mac);5764if (!sta)5765goto release_plink_ctl;5766}57675768if (params->plink_state == NL80211_PLINK_ESTAB) {5769if (rtw_mesh_peer_establish(adapter, plink, sta) != _SUCCESS) {5770rtw_free_stainfo(adapter, sta);5771ret = -ENOENT;5772goto release_plink_ctl;5773}5774}5775}5776else if (params->plink_state == NL80211_PLINK_HOLDING5777#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))5778&& (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)5779#endif5780) {5781del_sta = rtw_get_stainfo(stapriv, mac);5782if (!del_sta)5783goto release_plink_ctl;57845785_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);5786if (!rtw_is_list_empty(&del_sta->asoc_list)) {5787rtw_list_delete(&del_sta->asoc_list);5788stapriv->asoc_list_cnt--;5789STA_SET_MESH_PLINK(del_sta, NULL);5790}5791_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);5792}57935794release_plink_ctl:5795_exit_critical_bh(&(plink_ctl->lock), &irqL2);57965797if (del_sta) {5798u8 sta_addr[ETH_ALEN];5799u8 updated = _FALSE;58005801_rtw_memcpy(sta_addr, del_sta->cmn.mac_addr, ETH_ALEN);5802updated = ap_free_sta(adapter, del_sta, 0, 0, 1);5803rtw_mesh_expire_peer(stapriv->padapter, sta_addr);58045805associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);5806}5807}58085809exit:5810#endif /* CONFIG_RTW_MESH */58115812return ret;5813}58145815struct sta_info *rtw_sta_info_get_by_idx(struct sta_priv *pstapriv, const int idx, u8 *asoc_list_num)5816{5817_list *phead, *plist;5818struct sta_info *psta = NULL;5819int i = 0;58205821phead = &pstapriv->asoc_list;5822plist = get_next(phead);58235824/* check asoc_queue */5825while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {5826if (idx == i)5827psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);5828plist = get_next(plist);5829i++;5830}58315832if (asoc_list_num)5833*asoc_list_num = i;58345835return psta;5836}58375838static int cfg80211_rtw_dump_station(struct wiphy *wiphy, struct net_device *ndev,5839int idx, u8 *mac, struct station_info *sinfo)5840{5841#define DBG_DUMP_STATION 058425843int ret = 0;5844_irqL irqL;5845_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);5846struct sta_priv *pstapriv = &padapter->stapriv;5847struct sta_info *psta = NULL;5848#ifdef CONFIG_RTW_MESH5849struct mesh_plink_ent *plink = NULL;5850#endif5851u8 asoc_list_num;58525853if (DBG_DUMP_STATION)5854RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));58555856_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);5857psta = rtw_sta_info_get_by_idx(pstapriv, idx, &asoc_list_num);5858_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);58595860#ifdef CONFIG_RTW_MESH5861if (MLME_IS_MESH(padapter)) {5862if (psta)5863plink = psta->plink;5864if (!plink)5865plink = rtw_mesh_plink_get_no_estab_by_idx(padapter, idx - asoc_list_num);5866}5867#endif /* CONFIG_RTW_MESH */58685869if ((!MLME_IS_MESH(padapter) && !psta)5870#ifdef CONFIG_RTW_MESH5871|| (MLME_IS_MESH(padapter) && !plink)5872#endif5873) {5874if (DBG_DUMP_STATION)5875RTW_INFO(FUNC_NDEV_FMT" end with idx:%d\n", FUNC_NDEV_ARG(ndev), idx);5876ret = -ENOENT;5877goto exit;5878}58795880if (psta)5881_rtw_memcpy(mac, psta->cmn.mac_addr, ETH_ALEN);5882#ifdef CONFIG_RTW_MESH5883else5884_rtw_memcpy(mac, plink->addr, ETH_ALEN);5885#endif58865887sinfo->filled = 0;58885889if (psta) {5890sinfo->filled |= STATION_INFO_SIGNAL;5891sinfo->signal = translate_percentage_to_dbm(psta->cmn.rssi_stat.rssi);5892sinfo->filled |= STATION_INFO_INACTIVE_TIME;5893sinfo->inactive_time = rtw_get_passing_time_ms(psta->sta_stats.last_rx_time);5894}58955896#ifdef CONFIG_RTW_MESH5897if (MLME_IS_MESH(padapter))5898rtw_cfg80211_fill_mesh_only_sta_info(plink, psta, sinfo);5899#endif59005901exit:5902return ret;5903}59045905static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,5906struct bss_parameters *params)5907{5908RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));5909/*5910RTW_INFO("use_cts_prot=%d\n", params->use_cts_prot);5911RTW_INFO("use_short_preamble=%d\n", params->use_short_preamble);5912RTW_INFO("use_short_slot_time=%d\n", params->use_short_slot_time);5913RTW_INFO("ap_isolate=%d\n", params->ap_isolate);59145915RTW_INFO("basic_rates_len=%d\n", params->basic_rates_len);5916for(i = 0; i < params->basic_rates_len; i++)5917RTW_INFO("basic_rates=%d\n", params->basic_rates[i]);5918*/5919return 0;59205921}59225923#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))5924static int cfg80211_rtw_set_txq_params(struct wiphy *wiphy5925#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))5926, struct net_device *ndev5927#endif5928, struct ieee80211_txq_params *params)5929{5930#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))5931_adapter *padapter = rtw_netdev_priv(ndev);5932#else5933_adapter *padapter = wiphy_to_adapter(wiphy);5934#endif5935struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;5936struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);5937u8 ac, AIFS, ECWMin, ECWMax, aSifsTime;5938u16 TXOP;5939u8 shift_count = 0;5940u32 acParm;59415942#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))5943ac = params->ac;5944#else5945ac = params->queue;5946#endif59475948switch (ac) {5949case NL80211_TXQ_Q_VO:5950ac = XMIT_VO_QUEUE;5951break;59525953case NL80211_TXQ_Q_VI:5954ac = XMIT_VI_QUEUE;5955break;59565957case NL80211_TXQ_Q_BE:5958ac = XMIT_BE_QUEUE;5959break;59605961case NL80211_TXQ_Q_BK:5962ac = XMIT_BK_QUEUE;5963break;59645965default:5966break;5967}59685969#if 05970RTW_INFO("ac=%d\n", ac);5971RTW_INFO("txop=%u\n", params->txop);5972RTW_INFO("cwmin=%u\n", params->cwmin);5973RTW_INFO("cwmax=%u\n", params->cwmax);5974RTW_INFO("aifs=%u\n", params->aifs);5975#endif59765977if (is_supported_5g(pmlmeext->cur_wireless_mode) ||5978(pmlmeext->cur_wireless_mode & WIRELESS_11_24N))5979aSifsTime = 16;5980else5981aSifsTime = 10;59825983AIFS = params->aifs * pmlmeinfo->slotTime + aSifsTime;59845985while ((params->cwmin + 1) >> shift_count != 1) {5986shift_count++;5987if (shift_count == 15)5988break;5989}59905991ECWMin = shift_count;59925993shift_count = 0;5994while ((params->cwmax + 1) >> shift_count != 1) {5995shift_count++;5996if (shift_count == 15)5997break;5998}59996000ECWMax = shift_count;60016002TXOP = le16_to_cpu(params->txop);60036004acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);60056006set_txq_params_cmd(padapter, acParm, ac);60076008return 0;6009}6010#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) */60116012#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))6013static int cfg80211_rtw_set_channel(struct wiphy *wiphy6014#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))6015, struct net_device *ndev6016#endif6017, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)6018{6019#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))6020_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);6021#else6022_adapter *padapter = wiphy_to_adapter(wiphy);6023#endif6024int chan_target = (u8) ieee80211_frequency_to_channel(chan->center_freq);6025int chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6026int chan_width = CHANNEL_WIDTH_20;60276028#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))6029RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));6030#endif60316032switch (channel_type) {6033case NL80211_CHAN_NO_HT:6034case NL80211_CHAN_HT20:6035chan_width = CHANNEL_WIDTH_20;6036chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6037break;6038case NL80211_CHAN_HT40MINUS:6039chan_width = CHANNEL_WIDTH_40;6040chan_offset = HAL_PRIME_CHNL_OFFSET_UPPER;6041break;6042case NL80211_CHAN_HT40PLUS:6043chan_width = CHANNEL_WIDTH_40;6044chan_offset = HAL_PRIME_CHNL_OFFSET_LOWER;6045break;6046default:6047chan_width = CHANNEL_WIDTH_20;6048chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6049break;6050}60516052RTW_INFO(FUNC_ADPT_FMT" ch:%d bw:%d, offset:%d\n"6053, FUNC_ADPT_ARG(padapter), chan_target, chan_width, chan_offset);60546055rtw_set_chbw_cmd(padapter, chan_target, chan_width, chan_offset, RTW_CMDF_WAIT_ACK);60566057return 0;6058}6059#endif /*#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))*/60606061static int cfg80211_rtw_set_monitor_channel(struct wiphy *wiphy6062#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))6063, struct cfg80211_chan_def *chandef6064#else6065, struct ieee80211_channel *chan6066, enum nl80211_channel_type channel_type6067#endif6068)6069{6070#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))6071struct ieee80211_channel *chan = chandef->chan;6072#endif60736074_adapter *padapter = wiphy_to_adapter(wiphy);6075int target_channal = chan->hw_value;6076int target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6077int target_width = CHANNEL_WIDTH_20;60786079#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))6080#ifdef CONFIG_DEBUG_CFG802116081RTW_INFO("center_freq %u Mhz ch %u width %u freq1 %u freq2 %u\n"6082, chan->center_freq6083, chan->hw_value6084, chandef->width6085, chandef->center_freq16086, chandef->center_freq2);6087#endif /* CONFIG_DEBUG_CFG80211 */60886089switch (chandef->width) {6090case NL80211_CHAN_WIDTH_20_NOHT:6091case NL80211_CHAN_WIDTH_20:6092target_width = CHANNEL_WIDTH_20;6093target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6094break;6095case NL80211_CHAN_WIDTH_40:6096target_width = CHANNEL_WIDTH_40;6097if (chandef->center_freq1 > chan->center_freq)6098target_offset = HAL_PRIME_CHNL_OFFSET_LOWER;6099else6100target_offset = HAL_PRIME_CHNL_OFFSET_UPPER;6101break;6102case NL80211_CHAN_WIDTH_80:6103target_width = CHANNEL_WIDTH_80;6104target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6105break;6106case NL80211_CHAN_WIDTH_80P80:6107target_width = CHANNEL_WIDTH_80_80;6108target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6109break;6110case NL80211_CHAN_WIDTH_160:6111target_width = CHANNEL_WIDTH_160;6112target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6113break;61146115#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))6116case NL80211_CHAN_WIDTH_5:6117case NL80211_CHAN_WIDTH_10:6118#endif6119default:6120target_width = CHANNEL_WIDTH_20;6121target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6122break;6123}6124#else6125#ifdef CONFIG_DEBUG_CFG802116126RTW_INFO("center_freq %u Mhz ch %u channel_type %u\n"6127, chan->center_freq6128, chan->hw_value6129, channel_type);6130#endif /* CONFIG_DEBUG_CFG80211 */61316132switch (channel_type) {6133case NL80211_CHAN_NO_HT:6134case NL80211_CHAN_HT20:6135target_width = CHANNEL_WIDTH_20;6136target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6137break;6138case NL80211_CHAN_HT40MINUS:6139target_width = CHANNEL_WIDTH_40;6140target_offset = HAL_PRIME_CHNL_OFFSET_UPPER;6141break;6142case NL80211_CHAN_HT40PLUS:6143target_width = CHANNEL_WIDTH_40;6144target_offset = HAL_PRIME_CHNL_OFFSET_LOWER;6145break;6146default:6147target_width = CHANNEL_WIDTH_20;6148target_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;6149break;6150}6151#endif6152RTW_INFO(FUNC_ADPT_FMT" ch:%d bw:%d, offset:%d\n"6153, FUNC_ADPT_ARG(padapter), target_channal, target_width, target_offset);61546155rtw_set_chbw_cmd(padapter, target_channal, target_width, target_offset, RTW_CMDF_WAIT_ACK);61566157return 0;6158}6159/*6160static int cfg80211_rtw_auth(struct wiphy *wiphy, struct net_device *ndev,6161struct cfg80211_auth_request *req)6162{6163RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));61646165return 0;6166}61676168static int cfg80211_rtw_assoc(struct wiphy *wiphy, struct net_device *ndev,6169struct cfg80211_assoc_request *req)6170{6171RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));61726173return 0;6174}6175*/6176#endif /* CONFIG_AP_MODE */61776178void rtw_cfg80211_external_auth_request(_adapter *padapter, union recv_frame *rframe)6179{6180struct rtw_external_auth_params params;6181struct wireless_dev *wdev = padapter->rtw_wdev;6182struct net_device *netdev = wdev_to_ndev(wdev);6183struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);6184struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);61856186u8 frame[256] = { 0 };6187uint frame_len = 24;6188s32 freq = 0;61896190/* rframe, in this case is null point */61916192freq = rtw_ch2freq(pmlmeext->cur_channel);61936194#ifdef CONFIG_DEBUG_CFG802116195RTW_INFO(FUNC_ADPT_FMT": freq(%d, %d)\n", FUNC_ADPT_ARG(padapter), freq);6196#endif61976198#if (KERNEL_VERSION(4, 17, 0) <= LINUX_VERSION_CODE)6199params.action = EXTERNAL_AUTH_START;6200_rtw_memcpy(params.bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);6201params.ssid.ssid_len = pmlmeinfo->network.Ssid.SsidLength;6202_rtw_memcpy(params.ssid.ssid, pmlmeinfo->network.Ssid.Ssid,6203pmlmeinfo->network.Ssid.SsidLength);6204params.key_mgmt_suite = 0x8ac0f00;62056206cfg80211_external_auth_request(netdev,6207(struct cfg80211_external_auth_params *)¶ms, GFP_ATOMIC);6208#elif (KERNEL_VERSION(2, 6, 37) <= LINUX_VERSION_CODE)6209set_frame_sub_type(frame, WIFI_AUTH);62106211_rtw_memcpy(frame + 4, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);6212_rtw_memcpy(frame + 10, adapter_mac_addr(padapter), ETH_ALEN);6213_rtw_memcpy(frame + 16, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);6214RTW_PUT_LE32((frame + 18), 0x8ac0f00);62156216if (pmlmeinfo->network.Ssid.SsidLength) {6217*(frame + 23) = pmlmeinfo->network.Ssid.SsidLength;6218_rtw_memcpy(frame + 24, pmlmeinfo->network.Ssid.Ssid,6219pmlmeinfo->network.Ssid.SsidLength);6220frame_len = 24 + pmlmeinfo->network.Ssid.SsidLength;6221}6222rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);6223#endif6224}62256226void rtw_cfg80211_rx_probe_request(_adapter *adapter, union recv_frame *rframe)6227{6228struct wireless_dev *wdev = adapter->rtw_wdev;6229u8 *frame = get_recvframe_data(rframe);6230uint frame_len = rframe->u.hdr.len;6231s32 freq;6232u8 ch, sch = rtw_get_oper_ch(adapter);62336234ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;6235freq = rtw_ch2freq(ch);62366237#ifdef CONFIG_DEBUG_CFG802116238RTW_INFO("RTW_Rx: probe request, ch=%d(%d), ta="MAC_FMT"\n"6239, ch, sch, MAC_ARG(get_addr2_ptr(frame)));6240#endif62416242#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)6243rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);6244#else6245cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);6246#endif6247}62486249void rtw_cfg80211_rx_action_p2p(_adapter *adapter, union recv_frame *rframe)6250{6251struct wireless_dev *wdev = adapter->rtw_wdev;6252u8 *frame = get_recvframe_data(rframe);6253uint frame_len = rframe->u.hdr.len;6254s32 freq;6255u8 ch, sch = rtw_get_oper_ch(adapter);6256u8 category, action;6257int type;62586259ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;6260freq = rtw_ch2freq(ch);62616262RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n"6263, ch, sch, MAC_ARG(get_addr2_ptr(frame)));6264#ifdef CONFIG_P2P6265type = rtw_p2p_check_frames(adapter, frame, frame_len, _FALSE);6266if (type >= 0)6267goto indicate;6268#endif6269rtw_action_frame_parse(frame, frame_len, &category, &action);6270RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);6271#ifdef CONFIG_P2P6272indicate:6273#endif6274#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)6275rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);6276#else6277cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);6278#endif6279}62806281void rtw_cfg80211_rx_p2p_action_public(_adapter *adapter, union recv_frame *rframe)6282{6283struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);6284struct wireless_dev *wdev = adapter->rtw_wdev;6285struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);6286u8 *frame = get_recvframe_data(rframe);6287uint frame_len = rframe->u.hdr.len;6288s32 freq;6289u8 ch, sch = rtw_get_oper_ch(adapter);6290u8 category, action;6291int type;62926293ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;6294freq = rtw_ch2freq(ch);62956296RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n"6297, ch, sch, MAC_ARG(get_addr2_ptr(frame)));6298#ifdef CONFIG_P2P6299type = rtw_p2p_check_frames(adapter, frame, frame_len, _FALSE);6300if (type >= 0) {6301switch (type) {6302case P2P_GO_NEGO_CONF:6303if (0) {6304RTW_INFO(FUNC_ADPT_FMT" Nego confirm. state=%u, status=%u, iaddr="MAC_FMT"\n"6305, FUNC_ADPT_ARG(adapter), pwdev_priv->nego_info.state, pwdev_priv->nego_info.status6306, MAC_ARG(pwdev_priv->nego_info.iface_addr));6307}6308if (pwdev_priv->nego_info.state == 26309&& pwdev_priv->nego_info.status == 06310&& rtw_check_invalid_mac_address(pwdev_priv->nego_info.iface_addr, _FALSE) == _FALSE6311) {6312_adapter *intended_iface = dvobj_get_adapter_by_addr(dvobj, pwdev_priv->nego_info.iface_addr);63136314if (intended_iface) {6315RTW_INFO(FUNC_ADPT_FMT" Nego confirm. Allow only "ADPT_FMT" to scan for 2000 ms\n"6316, FUNC_ADPT_ARG(adapter), ADPT_ARG(intended_iface));6317/* allow only intended_iface to do scan for 2000 ms */6318rtw_mi_set_scan_deny(adapter, 2000);6319rtw_clear_scan_deny(intended_iface);6320}6321}6322break;6323case P2P_PROVISION_DISC_RESP:6324case P2P_INVIT_RESP:6325rtw_clear_scan_deny(adapter);6326#if !RTW_P2P_GROUP_INTERFACE6327rtw_mi_buddy_set_scan_deny(adapter, 2000);6328#endif6329break;6330}6331goto indicate;6332}6333#endif6334rtw_action_frame_parse(frame, frame_len, &category, &action);6335RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);6336#ifdef CONFIG_P2P6337indicate:6338#endif6339#if defined(RTW_DEDICATED_P2P_DEVICE)6340if (rtw_cfg80211_redirect_pd_wdev(dvobj_to_wiphy(dvobj), get_ra(frame), &wdev))6341if (0)6342RTW_INFO("redirect to pd_wdev:%p\n", wdev);6343#endif63446345#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)6346rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);6347#else6348cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);6349#endif6350}63516352void rtw_cfg80211_rx_action(_adapter *adapter, union recv_frame *rframe, const char *msg)6353{6354struct wireless_dev *wdev = adapter->rtw_wdev;6355u8 *frame = get_recvframe_data(rframe);6356uint frame_len = rframe->u.hdr.len;6357s32 freq;6358u8 ch, sch = rtw_get_oper_ch(adapter);6359u8 category, action;6360int type = -1;63616362ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;6363freq = rtw_ch2freq(ch);63646365RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n"6366, ch, sch, MAC_ARG(get_addr2_ptr(frame)));63676368#ifdef CONFIG_RTW_MESH6369if (MLME_IS_MESH(adapter)) {6370type = rtw_mesh_check_frames_rx(adapter, frame, frame_len);6371if (type >= 0)6372goto indicate;6373}6374#endif6375rtw_action_frame_parse(frame, frame_len, &category, &action);6376if (category == RTW_WLAN_CATEGORY_PUBLIC) {6377if (action == ACT_PUBLIC_GAS_INITIAL_REQ) {6378rtw_mi_set_scan_deny(adapter, 200);6379rtw_mi_scan_abort(adapter, _FALSE); /*rtw_scan_abort_no_wait*/6380}6381}6382#ifdef CONFIG_RTW_MESH6383indicate:6384#endif63856386#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)6387rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);6388#else6389cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);6390#endif63916392if (type == -1) {6393if (msg)6394RTW_INFO("RTW_Rx:%s\n", msg);6395else6396RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);6397}6398}63996400#ifdef CONFIG_RTW_80211K6401void rtw_cfg80211_rx_rrm_action(_adapter *adapter, union recv_frame *rframe)6402{6403struct wireless_dev *wdev = adapter->rtw_wdev;6404u8 *frame = get_recvframe_data(rframe);6405uint frame_len = rframe->u.hdr.len;6406s32 freq;6407u8 ch, sch = rtw_get_oper_ch(adapter);64086409ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;6410freq = rtw_ch2freq(ch);64116412#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)6413rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);6414#else6415cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);6416#endif6417RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n"6418, ch, sch, MAC_ARG(get_addr2_ptr(frame)));6419}6420#endif /* CONFIG_RTW_80211K */64216422void rtw_cfg80211_rx_mframe(_adapter *adapter, union recv_frame *rframe, const char *msg)6423{6424struct wireless_dev *wdev = adapter->rtw_wdev;6425u8 *frame = get_recvframe_data(rframe);6426uint frame_len = rframe->u.hdr.len;6427s32 freq;6428u8 ch, sch = rtw_get_oper_ch(adapter);64296430ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;6431freq = rtw_ch2freq(ch);64326433#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)6434rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);6435#else6436cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);6437#endif64386439RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n", ch, sch, MAC_ARG(get_addr2_ptr(frame)));6440if (!rtw_sae_preprocess(adapter, frame, frame_len, _FALSE)) {6441if (msg)6442RTW_INFO("RTW_Rx:%s\n", msg);6443else6444RTW_INFO("RTW_Rx:frame_control:0x%02x\n", le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)rframe)->frame_ctl));6445}6446}64476448#ifdef CONFIG_P2P6449void rtw_cfg80211_issue_p2p_provision_request(_adapter *padapter, const u8 *buf, size_t len)6450{6451u16 wps_devicepassword_id = 0x0000;6452uint wps_devicepassword_id_len = 0;6453u8 wpsie[255] = { 0x00 }, p2p_ie[255] = { 0x00 };6454uint p2p_ielen = 0;6455uint wpsielen = 0;6456u32 devinfo_contentlen = 0;6457u8 devinfo_content[64] = { 0x00 };6458u16 capability = 0;6459uint capability_len = 0;64606461unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;6462u8 action = P2P_PUB_ACTION_ACTION;6463u8 dialogToken = 1;6464u32 p2poui = cpu_to_be32(P2POUI);6465u8 oui_subtype = P2P_PROVISION_DISC_REQ;6466u32 p2pielen = 0;6467#ifdef CONFIG_WFD6468u32 wfdielen = 0;6469#endif64706471struct xmit_frame *pmgntframe;6472struct pkt_attrib *pattrib;6473unsigned char *pframe;6474struct rtw_ieee80211_hdr *pwlanhdr;6475unsigned short *fctrl;6476struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);6477struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);64786479struct wifidirect_info *pwdinfo = &(padapter->wdinfo);6480u8 *frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));6481size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);648264836484RTW_INFO("[%s] In\n", __FUNCTION__);64856486/* prepare for building provision_request frame */6487_rtw_memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr1Ptr(buf), ETH_ALEN);6488_rtw_memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, GetAddr1Ptr(buf), ETH_ALEN);64896490pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;64916492rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);6493rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len);6494wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);64956496switch (wps_devicepassword_id) {6497case WPS_DPID_PIN:6498pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;6499break;6500case WPS_DPID_USER_SPEC:6501pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;6502break;6503case WPS_DPID_MACHINE_SPEC:6504break;6505case WPS_DPID_REKEY:6506break;6507case WPS_DPID_PBC:6508pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;6509break;6510case WPS_DPID_REGISTRAR_SPEC:6511pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;6512break;6513default:6514break;6515}651665176518if (rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, p2p_ie, &p2p_ielen)) {65196520rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, devinfo_content, &devinfo_contentlen);6521rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&capability, &capability_len);65226523}652465256526/* start to build provision_request frame */6527_rtw_memset(wpsie, 0, sizeof(wpsie));6528_rtw_memset(p2p_ie, 0, sizeof(p2p_ie));6529p2p_ielen = 0;65306531pmgntframe = alloc_mgtxmitframe(pxmitpriv);6532if (pmgntframe == NULL)6533return;653465356536/* update attribute */6537pattrib = &pmgntframe->attrib;6538update_mgntframe_attrib(padapter, pattrib);65396540_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);65416542pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;6543pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;65446545fctrl = &(pwlanhdr->frame_ctl);6546*(fctrl) = 0;65476548_rtw_memcpy(pwlanhdr->addr1, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);6549_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);6550_rtw_memcpy(pwlanhdr->addr3, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);65516552SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);6553pmlmeext->mgnt_seq++;6554set_frame_sub_type(pframe, WIFI_ACTION);65556556pframe += sizeof(struct rtw_ieee80211_hdr_3addr);6557pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);65586559pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));6560pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));6561pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));6562pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));6563pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));656465656566/* build_prov_disc_request_p2p_ie */6567/* P2P OUI */6568p2pielen = 0;6569p2p_ie[p2pielen++] = 0x50;6570p2p_ie[p2pielen++] = 0x6F;6571p2p_ie[p2pielen++] = 0x9A;6572p2p_ie[p2pielen++] = 0x09; /* WFA P2P v1.0 */65736574/* Commented by Albert 20110301 */6575/* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */6576/* 1. P2P Capability */6577/* 2. Device Info */6578/* 3. Group ID ( When joining an operating P2P Group ) */65796580/* P2P Capability ATTR */6581/* Type: */6582p2p_ie[p2pielen++] = P2P_ATTR_CAPABILITY;65836584/* Length: */6585/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */6586RTW_PUT_LE16(p2p_ie + p2pielen, 0x0002);6587p2pielen += 2;65886589/* Value: */6590/* Device Capability Bitmap, 1 byte */6591/* Group Capability Bitmap, 1 byte */6592_rtw_memcpy(p2p_ie + p2pielen, &capability, 2);6593p2pielen += 2;659465956596/* Device Info ATTR */6597/* Type: */6598p2p_ie[p2pielen++] = P2P_ATTR_DEVICE_INFO;65996600/* Length: */6601/* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */6602/* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */6603/* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); */6604RTW_PUT_LE16(p2p_ie + p2pielen, devinfo_contentlen);6605p2pielen += 2;66066607/* Value: */6608_rtw_memcpy(p2p_ie + p2pielen, devinfo_content, devinfo_contentlen);6609p2pielen += devinfo_contentlen;661066116612pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2p_ie, &p2p_ielen);6613/* p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, NULL, 0, pwdinfo->tx_prov_disc_info.peerDevAddr); */6614/* pframe += p2pielen; */6615pattrib->pktlen += p2p_ielen;66166617wpsielen = 0;6618/* WPS OUI */6619*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);6620wpsielen += 4;66216622/* WPS version */6623/* Type: */6624*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);6625wpsielen += 2;66266627/* Length: */6628*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);6629wpsielen += 2;66306631/* Value: */6632wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */66336634/* Config Method */6635/* Type: */6636*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);6637wpsielen += 2;66386639/* Length: */6640*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);6641wpsielen += 2;66426643/* Value: */6644*(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);6645wpsielen += 2;66466647pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);664866496650#ifdef CONFIG_WFD6651wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);6652pframe += wfdielen;6653pattrib->pktlen += wfdielen;6654#endif66556656pattrib->last_txcmdsz = pattrib->pktlen;66576658/* dump_mgntframe(padapter, pmgntframe); */6659if (dump_mgntframe_and_wait_ack(padapter, pmgntframe) != _SUCCESS)6660RTW_INFO("%s, ack to\n", __func__);66616662#if 06663if(wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) {6664RTW_INFO("waiting for p2p peer key-in PIN CODE\n");6665rtw_msleep_os(15000); /* 15 sec for key in PIN CODE, workaround for GS2 before issuing Nego Req. */6666}6667#endif66686669}66706671#ifdef CONFIG_RTW_80211R6672static s32 cfg80211_rtw_update_ft_ies(struct wiphy *wiphy,6673struct net_device *ndev,6674struct cfg80211_update_ft_ies_params *ftie)6675{6676_adapter *padapter = NULL;6677struct mlme_priv *pmlmepriv = NULL;6678struct ft_roam_info *pft_roam = NULL;6679_irqL irqL;6680u8 *p;6681u8 *pie = NULL;6682u32 ie_len = 0;66836684if (ndev == NULL)6685return -EINVAL;66866687padapter = (_adapter *)rtw_netdev_priv(ndev);6688pmlmepriv = &(padapter->mlmepriv);6689pft_roam = &(pmlmepriv->ft_roam);66906691p = (u8 *)ftie->ie;6692if (ftie->ie_len <= sizeof(pft_roam->updated_ft_ies)) {6693_enter_critical_bh(&pmlmepriv->lock, &irqL);6694_rtw_memcpy(pft_roam->updated_ft_ies, ftie->ie, ftie->ie_len);6695pft_roam->updated_ft_ies_len = ftie->ie_len;6696_exit_critical_bh(&pmlmepriv->lock, &irqL);6697} else {6698RTW_ERR("FTIEs parsing fail!\n");6699return -EINVAL;6700}67016702if (rtw_ft_roam_status(padapter, RTW_FT_AUTHENTICATED_STA)) {6703RTW_PRINT("auth success, start reassoc\n");6704rtw_ft_lock_set_status(padapter, RTW_FT_ASSOCIATING_STA, &irqL);6705start_clnt_assoc(padapter);6706}67076708return 0;6709}6710#endif67116712inline void rtw_cfg80211_set_is_roch(_adapter *adapter, bool val)6713{6714adapter->cfg80211_wdinfo.is_ro_ch = val;6715rtw_mi_update_iface_status(&(adapter->mlmepriv), 0);6716}67176718inline bool rtw_cfg80211_get_is_roch(_adapter *adapter)6719{6720return adapter->cfg80211_wdinfo.is_ro_ch;6721}67226723inline bool rtw_cfg80211_is_ro_ch_once(_adapter *adapter)6724{6725return adapter->cfg80211_wdinfo.last_ro_ch_time ? 1 : 0;6726}67276728inline void rtw_cfg80211_set_last_ro_ch_time(_adapter *adapter)6729{6730adapter->cfg80211_wdinfo.last_ro_ch_time = rtw_get_current_time();67316732if (!adapter->cfg80211_wdinfo.last_ro_ch_time)6733adapter->cfg80211_wdinfo.last_ro_ch_time++;6734}67356736inline s32 rtw_cfg80211_get_last_ro_ch_passing_ms(_adapter *adapter)6737{6738return rtw_get_passing_time_ms(adapter->cfg80211_wdinfo.last_ro_ch_time);6739}67406741static s32 cfg80211_rtw_remain_on_channel(struct wiphy *wiphy,6742#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))6743struct wireless_dev *wdev,6744#else6745struct net_device *ndev,6746#endif6747struct ieee80211_channel *channel,6748#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))6749enum nl80211_channel_type channel_type,6750#endif6751unsigned int duration, u64 *cookie)6752{6753s32 err = 0;6754u8 remain_ch = (u8) ieee80211_frequency_to_channel(channel->center_freq);6755_adapter *padapter = NULL;6756struct rtw_wdev_priv *pwdev_priv;6757struct wifidirect_info *pwdinfo;6758struct cfg80211_wifidirect_info *pcfg80211_wdinfo;6759#ifdef CONFIG_CONCURRENT_MODE6760u8 is_p2p_find = _FALSE;6761#endif67626763#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))6764#if defined(RTW_DEDICATED_P2P_DEVICE)6765if (wdev == wiphy_to_pd_wdev(wiphy))6766padapter = wiphy_to_adapter(wiphy);6767else6768#endif6769if (wdev_to_ndev(wdev))6770padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));6771else {6772err = -EINVAL;6773goto exit;6774}6775#else6776struct wireless_dev *wdev;67776778if (ndev == NULL) {6779err = -EINVAL;6780goto exit;6781}6782padapter = (_adapter *)rtw_netdev_priv(ndev);6783wdev = ndev_to_wdev(ndev);6784#endif67856786pwdev_priv = adapter_wdev_data(padapter);6787pwdinfo = &padapter->wdinfo;6788pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;6789#ifdef CONFIG_CONCURRENT_MODE6790is_p2p_find = (duration < (pwdinfo->ext_listen_interval)) ? _TRUE : _FALSE;6791#endif67926793*cookie = ATOMIC_INC_RETURN(&pcfg80211_wdinfo->ro_ch_cookie_gen);67946795RTW_INFO(FUNC_ADPT_FMT"%s ch:%u duration:%d, cookie:0x%llx\n"6796, FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""6797, remain_ch, duration, *cookie);67986799if (rtw_chset_search_ch(adapter_to_chset(padapter), remain_ch) < 0) {6800RTW_WARN(FUNC_ADPT_FMT" invalid ch:%u\n", FUNC_ADPT_ARG(padapter), remain_ch);6801err = -EFAULT;6802goto exit;6803}68046805#ifdef CONFIG_MP_INCLUDED6806if (rtw_mp_mode_check(padapter)) {6807RTW_INFO("MP mode block remain_on_channel request\n");6808err = -EFAULT;6809goto exit;6810}6811#endif68126813if (_FAIL == rtw_pwr_wakeup(padapter)) {6814err = -EFAULT;6815goto exit;6816}68176818rtw_scan_abort(padapter);6819#ifdef CONFIG_CONCURRENT_MODE6820/*don't scan_abort during p2p_listen.*/6821if (is_p2p_find)6822rtw_mi_buddy_scan_abort(padapter, _TRUE);6823#endif /*CONFIG_CONCURRENT_MODE*/68246825if (rtw_cfg80211_get_is_roch(padapter) == _TRUE) {6826_cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);6827p2p_cancel_roch_cmd(padapter, 0, NULL, RTW_CMDF_WAIT_ACK);6828}68296830/* if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) */6831if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)6832#if defined(CONFIG_ANDROID) && !defined(RTW_SINGLE_WIPHY)6833&& (!is_primary_adapter(padapter))6834/*wlan0 can't be p2p device in CONFIG_ANDROID */6835#endif6836){6837rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);6838padapter->wdinfo.listen_channel = remain_ch;6839RTW_INFO(FUNC_ADPT_FMT" init listen_channel %u\n"6840, FUNC_ADPT_ARG(padapter), padapter->wdinfo.listen_channel);6841} else if (rtw_p2p_chk_state(pwdinfo , P2P_STATE_LISTEN)6842&& (time_after_eq(rtw_get_current_time(), pwdev_priv->probe_resp_ie_update_time)6843&& rtw_get_passing_time_ms(pwdev_priv->probe_resp_ie_update_time) < 50)6844) {6845if (padapter->wdinfo.listen_channel != remain_ch) {6846padapter->wdinfo.listen_channel = remain_ch;6847RTW_INFO(FUNC_ADPT_FMT" update listen_channel %u\n"6848, FUNC_ADPT_ARG(padapter), padapter->wdinfo.listen_channel);6849}6850} else {6851rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));6852#ifdef CONFIG_DEBUG_CFG802116853RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));6854#endif6855}68566857rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);68586859#ifdef RTW_ROCH_DURATION_ENLARGE6860if (duration < 400)6861duration = duration * 3; /* extend from exper */6862#endif68636864#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE)6865if (rtw_mi_check_status(padapter, MI_LINKED)) {6866if (is_p2p_find) /* p2p_find , duration<1000 */6867duration = duration + pwdinfo->ext_listen_interval;6868else /* p2p_listen, duration=5000 */6869duration = pwdinfo->ext_listen_interval + (pwdinfo->ext_listen_interval / 4);6870}6871#endif /*defined (RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE) */68726873rtw_cfg80211_set_is_roch(padapter, _TRUE);6874pcfg80211_wdinfo->ro_ch_wdev = wdev;6875pcfg80211_wdinfo->remain_on_ch_cookie = *cookie;6876rtw_cfg80211_set_last_ro_ch_time(padapter);6877_rtw_memcpy(&pcfg80211_wdinfo->remain_on_ch_channel, channel, sizeof(struct ieee80211_channel));6878#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))6879pcfg80211_wdinfo->remain_on_ch_type = channel_type;6880#endif6881pcfg80211_wdinfo->restore_channel = rtw_get_oper_ch(padapter);68826883p2p_roch_cmd(padapter, *cookie, wdev, channel, pcfg80211_wdinfo->remain_on_ch_type,6884duration, RTW_CMDF_WAIT_ACK);68856886rtw_cfg80211_ready_on_channel(wdev, *cookie, channel, channel_type, duration, GFP_KERNEL);6887exit:6888return err;6889}68906891static s32 cfg80211_rtw_cancel_remain_on_channel(struct wiphy *wiphy,6892#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))6893struct wireless_dev *wdev,6894#else6895struct net_device *ndev,6896#endif6897u64 cookie)6898{6899s32 err = 0;6900_adapter *padapter;6901struct rtw_wdev_priv *pwdev_priv;6902struct wifidirect_info *pwdinfo;6903struct cfg80211_wifidirect_info *pcfg80211_wdinfo;69046905#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))6906#if defined(RTW_DEDICATED_P2P_DEVICE)6907if (wdev == wiphy_to_pd_wdev(wiphy))6908padapter = wiphy_to_adapter(wiphy);6909else6910#endif6911if (wdev_to_ndev(wdev))6912padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));6913else {6914err = -EINVAL;6915goto exit;6916}6917#else6918struct wireless_dev *wdev;69196920if (ndev == NULL) {6921err = -EINVAL;6922goto exit;6923}6924padapter = (_adapter *)rtw_netdev_priv(ndev);6925wdev = ndev_to_wdev(ndev);6926#endif69276928pwdev_priv = adapter_wdev_data(padapter);6929pwdinfo = &padapter->wdinfo;6930pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;69316932RTW_INFO(FUNC_ADPT_FMT"%s cookie:0x%llx\n"6933, FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""6934, cookie);69356936if (rtw_cfg80211_get_is_roch(padapter) == _TRUE) {6937_cancel_timer_ex(&padapter->cfg80211_wdinfo.remain_on_ch_timer);6938p2p_cancel_roch_cmd(padapter, cookie, wdev, RTW_CMDF_WAIT_ACK);6939}69406941exit:6942return err;6943}69446945inline int rtw_cfg80211_iface_has_p2p_group_cap(_adapter *adapter)6946{6947#if RTW_P2P_GROUP_INTERFACE6948if (is_primary_adapter(adapter))6949return 0;6950#endif6951return 1;6952}69536954inline int rtw_cfg80211_is_p2p_scan(_adapter *adapter)6955{6956#if RTW_P2P_GROUP_INTERFACE6957if (rtw_cfg80211_iface_has_p2p_group_cap(adapter))6958#endif6959{6960struct wifidirect_info *wdinfo = &adapter->wdinfo;69616962return rtw_p2p_chk_state(wdinfo, P2P_STATE_SCAN)6963|| rtw_p2p_chk_state(wdinfo, P2P_STATE_FIND_PHASE_SEARCH);6964}69656966#if RTW_P2P_GROUP_INTERFACE6967#if defined(RTW_DEDICATED_P2P_DEVICE)6968if (wiphy_to_pd_wdev(adapter_to_wiphy(adapter))) /* pd_wdev exist */6969return rtw_cfg80211_is_scan_by_pd_wdev(adapter);6970#endif6971{6972/*6973* For 2 RTW_P2P_GROUP_INTERFACE cases:6974* 1. RTW_DEDICATED_P2P_DEVICE defined but upper layer don't use pd_wdev or6975* 2. RTW_DEDICATED_P2P_DEVICE not defined6976*/6977struct rtw_wdev_priv *wdev_data = adapter_wdev_data(adapter);6978_irqL irqL;6979int is_p2p_scan = 0;69806981_enter_critical_bh(&wdev_data->scan_req_lock, &irqL);6982if (wdev_data->scan_request6983&& wdev_data->scan_request->n_ssids6984&& wdev_data->scan_request->ssids6985&& wdev_data->scan_request->ie6986) {6987if (_rtw_memcmp(wdev_data->scan_request->ssids[0].ssid, "DIRECT-", 7)6988&& rtw_get_p2p_ie((u8 *)wdev_data->scan_request->ie, wdev_data->scan_request->ie_len, NULL, NULL))6989is_p2p_scan = 1;6990}6991_exit_critical_bh(&wdev_data->scan_req_lock, &irqL);69926993return is_p2p_scan;6994}6995#endif6996}69976998#if defined(RTW_DEDICATED_P2P_DEVICE)6999int rtw_pd_iface_alloc(struct wiphy *wiphy, const char *name, struct wireless_dev **pd_wdev)7000{7001struct rtw_wiphy_data *wiphy_data = rtw_wiphy_priv(wiphy);7002struct wireless_dev *wdev = NULL;7003struct rtw_netdev_priv_indicator *npi;7004_adapter *primary_adpt = wiphy_to_adapter(wiphy);7005int ret = 0;70067007if (wiphy_data->pd_wdev) {7008RTW_WARN(FUNC_WIPHY_FMT" pd_wdev already exists\n", FUNC_WIPHY_ARG(wiphy));7009ret = -EBUSY;7010goto exit;7011}70127013wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));7014if (!wdev) {7015RTW_WARN(FUNC_WIPHY_FMT" allocate wdev fail\n", FUNC_WIPHY_ARG(wiphy));7016ret = -ENOMEM;7017goto exit;7018}70197020wdev->wiphy = wiphy;7021wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;7022_rtw_memcpy(wdev->address, adapter_mac_addr(primary_adpt), ETH_ALEN);70237024wiphy_data->pd_wdev = wdev;7025*pd_wdev = wdev;70267027RTW_INFO(FUNC_WIPHY_FMT" pd_wdev:%p, addr="MAC_FMT" added\n"7028, FUNC_WIPHY_ARG(wiphy), wdev, MAC_ARG(wdev_address(wdev)));70297030exit:7031if (ret && wdev) {7032rtw_mfree((u8 *)wdev, sizeof(struct wireless_dev));7033wdev = NULL;7034}70357036return ret;7037}70387039void rtw_pd_iface_free(struct wiphy *wiphy)7040{7041struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);7042struct rtw_wiphy_data *wiphy_data = rtw_wiphy_priv(wiphy);7043u8 rtnl_lock_needed;70447045if (!wiphy_data->pd_wdev)7046goto exit;70477048RTW_INFO(FUNC_WIPHY_FMT" pd_wdev:%p, addr="MAC_FMT"\n"7049, FUNC_WIPHY_ARG(wiphy), wiphy_data->pd_wdev7050, MAC_ARG(wdev_address(wiphy_data->pd_wdev)));70517052rtnl_lock_needed = rtw_rtnl_lock_needed(dvobj);7053if (rtnl_lock_needed)7054rtnl_lock();7055cfg80211_unregister_wdev(wiphy_data->pd_wdev);7056if (rtnl_lock_needed)7057rtnl_unlock();70587059rtw_mfree((u8 *)wiphy_data->pd_wdev, sizeof(struct wireless_dev));7060wiphy_data->pd_wdev = NULL;70617062exit:7063return;7064}70657066static int cfg80211_rtw_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)7067{7068_adapter *adapter = wiphy_to_adapter(wiphy);70697070RTW_INFO(FUNC_WIPHY_FMT" wdev=%p\n", FUNC_WIPHY_ARG(wiphy), wdev);70717072rtw_p2p_enable(adapter, P2P_ROLE_DEVICE);7073return 0;7074}70757076static void cfg80211_rtw_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)7077{7078_adapter *adapter = wiphy_to_adapter(wiphy);70797080RTW_INFO(FUNC_WIPHY_FMT" wdev=%p\n", FUNC_WIPHY_ARG(wiphy), wdev);70817082if (rtw_cfg80211_is_p2p_scan(adapter))7083rtw_scan_abort(adapter);70847085rtw_p2p_enable(adapter, P2P_ROLE_DISABLE);7086}70877088inline int rtw_cfg80211_redirect_pd_wdev(struct wiphy *wiphy, u8 *ra, struct wireless_dev **wdev)7089{7090struct wireless_dev *pd_wdev = wiphy_to_pd_wdev(wiphy);70917092if (pd_wdev && pd_wdev != *wdev7093&& _rtw_memcmp(wdev_address(pd_wdev), ra, ETH_ALEN) == _TRUE7094) {7095*wdev = pd_wdev;7096return 1;7097}7098return 0;7099}71007101inline int rtw_cfg80211_is_scan_by_pd_wdev(_adapter *adapter)7102{7103struct wiphy *wiphy = adapter_to_wiphy(adapter);7104struct rtw_wdev_priv *wdev_data = adapter_wdev_data(adapter);7105struct wireless_dev *wdev = NULL;7106_irqL irqL;71077108_enter_critical_bh(&wdev_data->scan_req_lock, &irqL);7109if (wdev_data->scan_request)7110wdev = wdev_data->scan_request->wdev;7111_exit_critical_bh(&wdev_data->scan_req_lock, &irqL);71127113if (wdev && wdev == wiphy_to_pd_wdev(wiphy))7114return 1;71157116return 0;7117}7118#endif /* RTW_DEDICATED_P2P_DEVICE */7119#endif /* CONFIG_P2P */71207121inline void rtw_cfg80211_set_is_mgmt_tx(_adapter *adapter, u8 val)7122{7123struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);71247125wdev_priv->is_mgmt_tx = val;7126rtw_mi_update_iface_status(&(adapter->mlmepriv), 0);7127}71287129inline u8 rtw_cfg80211_get_is_mgmt_tx(_adapter *adapter)7130{7131struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);71327133return wdev_priv->is_mgmt_tx;7134}71357136static int _cfg80211_rtw_mgmt_tx(_adapter *padapter, u8 tx_ch, u8 no_cck, const u8 *buf, size_t len, int wait_ack)7137{7138struct xmit_frame *pmgntframe;7139struct pkt_attrib *pattrib;7140unsigned char *pframe;7141int ret = _FAIL;7142bool ack = _TRUE;7143struct rtw_ieee80211_hdr *pwlanhdr;7144#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)7145struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);7146#endif7147struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);7148struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);7149u8 u_ch = rtw_mi_get_union_chan(padapter);7150u8 leave_op = 0;7151#ifdef CONFIG_P2P7152struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;7153#ifdef CONFIG_CONCURRENT_MODE7154struct wifidirect_info *pwdinfo = &padapter->wdinfo;7155#endif7156#endif71577158rtw_cfg80211_set_is_mgmt_tx(padapter, 1);71597160#ifdef CONFIG_BT_COEXIST7161rtw_btcoex_ScanNotify(padapter, _TRUE);7162#endif71637164#ifdef CONFIG_P2P7165if (rtw_cfg80211_get_is_roch(padapter) == _TRUE) {7166#ifdef CONFIG_CONCURRENT_MODE7167if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {7168RTW_INFO("%s, extend ro ch time\n", __func__);7169_set_timer(&padapter->cfg80211_wdinfo.remain_on_ch_timer, pwdinfo->ext_listen_period);7170}7171#endif /* CONFIG_CONCURRENT_MODE */7172}7173#endif /* CONFIG_P2P */71747175#ifdef CONFIG_MCC_MODE7176if (MCC_EN(padapter)) {7177if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))7178/* don't set channel, issue frame directly */7179goto issue_mgmt_frame;7180}7181#endif /* CONFIG_MCC_MODE */71827183if (rtw_mi_check_status(padapter, MI_LINKED)7184&& tx_ch != u_ch7185) {7186rtw_leave_opch(padapter);7187leave_op = 1;71887189#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)7190if (rtw_cfg80211_get_is_roch(padapter)7191&& ATOMIC_READ(&pwdev_priv->switch_ch_to) == 17192) {7193u16 ext_listen_period;71947195if (check_fwstate(&padapter->mlmepriv, _FW_LINKED))7196ext_listen_period = 500;7197else7198ext_listen_period = pwdinfo->ext_listen_period;7199ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);7200_set_timer(&pwdinfo->ap_p2p_switch_timer, ext_listen_period);7201RTW_INFO("%s, set switch ch timer, period=%d\n", __func__, ext_listen_period);7202}7203#endif /* RTW_ROCH_BACK_OP && CONFIG_P2P && CONFIG_CONCURRENT_MODE */7204}72057206if (tx_ch != rtw_get_oper_ch(padapter))7207set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);7208#ifdef CONFIG_MCC_MODE7209issue_mgmt_frame:7210#endif7211/* starting alloc mgmt frame to dump it */7212pmgntframe = alloc_mgtxmitframe(pxmitpriv);7213if (pmgntframe == NULL) {7214/* ret = -ENOMEM; */7215ret = _FAIL;7216goto exit;7217}72187219/* update attribute */7220pattrib = &pmgntframe->attrib;7221update_mgntframe_attrib(padapter, pattrib);72227223if (no_cck && IS_CCK_RATE(pattrib->rate)) {7224/* force OFDM 6M rate*/7225pattrib->rate = MGN_6M;7226pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G);7227}72287229pattrib->retry_ctrl = _FALSE;72307231_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);72327233pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;72347235_rtw_memcpy(pframe, (void *)buf, len);7236pattrib->pktlen = len;72377238pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;7239/* update seq number */7240pmlmeext->mgnt_seq = GetSequence(pwlanhdr);7241pattrib->seqnum = pmlmeext->mgnt_seq;7242pmlmeext->mgnt_seq++;72437244#ifdef CONFIG_P2P7245rtw_xframe_chk_wfd_ie(pmgntframe);7246#endif /* CONFIG_P2P */72477248pattrib->last_txcmdsz = pattrib->pktlen;72497250if (wait_ack) {7251if (dump_mgntframe_and_wait_ack(padapter, pmgntframe) != _SUCCESS) {7252ack = _FALSE;7253ret = _FAIL;72547255#ifdef CONFIG_DEBUG_CFG802117256RTW_INFO("%s, ack == _FAIL\n", __func__);7257#endif7258} else {72597260#ifdef CONFIG_XMIT_ACK7261if (!MLME_IS_MESH(padapter)) /* TODO: remove this sleep for all mode */7262rtw_msleep_os(50);7263#endif7264#ifdef CONFIG_DEBUG_CFG802117265RTW_INFO("%s, ack=%d, ok!\n", __func__, ack);7266#endif7267ret = _SUCCESS;7268}7269} else {7270dump_mgntframe(padapter, pmgntframe);7271ret = _SUCCESS;7272}72737274exit:7275#ifdef CONFIG_P2P7276if (rtw_cfg80211_get_is_roch(padapter)7277&& !roch_stay_in_cur_chan(padapter)7278&& pcfg80211_wdinfo->remain_on_ch_channel.hw_value != u_ch7279) {7280/* roch is ongoing, switch back to rch */7281if (pcfg80211_wdinfo->remain_on_ch_channel.hw_value != tx_ch)7282set_channel_bwmode(padapter, pcfg80211_wdinfo->remain_on_ch_channel.hw_value7283, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);7284} else7285#endif7286if (leave_op) {7287if (rtw_mi_check_status(padapter, MI_LINKED)) {7288u8 u_bw = rtw_mi_get_union_bw(padapter);7289u8 u_offset = rtw_mi_get_union_offset(padapter);72907291set_channel_bwmode(padapter, u_ch, u_offset, u_bw);7292}7293rtw_back_opch(padapter);7294}72957296rtw_cfg80211_set_is_mgmt_tx(padapter, 0);72977298#ifdef CONFIG_BT_COEXIST7299rtw_btcoex_ScanNotify(padapter, _FALSE);7300#endif73017302#ifdef CONFIG_DEBUG_CFG802117303RTW_INFO("%s, ret=%d\n", __func__, ret);7304#endif73057306return ret;73077308}73097310u8 rtw_mgnt_tx_handler(_adapter *adapter, u8 *buf)7311{7312u8 rst = H2C_CMD_FAIL;7313struct mgnt_tx_parm *mgnt_parm = (struct mgnt_tx_parm *)buf;73147315if (_cfg80211_rtw_mgmt_tx(adapter, mgnt_parm->tx_ch, mgnt_parm->no_cck,7316mgnt_parm->buf, mgnt_parm->len, mgnt_parm->wait_ack) == _SUCCESS)7317rst = H2C_SUCCESS;73187319return rst;7320}73217322static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy,7323#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))7324struct wireless_dev *wdev,7325#else7326struct net_device *ndev,7327#endif7328#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) || defined(COMPAT_KERNEL_RELEASE)7329struct ieee80211_channel *chan,7330#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)7331bool offchan,7332#endif7333#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))7334enum nl80211_channel_type channel_type,7335#endif7336#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))7337bool channel_type_valid,7338#endif7339#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)7340unsigned int wait,7341#endif7342const u8 *buf, size_t len,7343#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))7344bool no_cck,7345#endif7346#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))7347bool dont_wait_for_ack,7348#endif7349#else7350struct cfg80211_mgmt_tx_params *params,7351#endif7352u64 *cookie)7353{7354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(COMPAT_KERNEL_RELEASE)7355struct ieee80211_channel *chan = params->chan;7356const u8 *buf = params->buf;7357size_t len = params->len;7358bool no_cck = params->no_cck;7359#endif7360#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))7361bool no_cck = 0;7362#endif7363int ret = 0;7364u8 tx_ret;7365int wait_ack = 1;7366const u8 *dump_buf = buf;7367size_t dump_len = len;7368u32 dump_limit = RTW_MAX_MGMT_TX_CNT;7369u32 dump_cnt = 0;7370u32 sleep_ms = 0;7371u32 retry_guarantee_ms = 0;7372bool ack = _TRUE;7373u8 tx_ch;7374u8 category, action;7375u8 frame_styp;7376#ifdef CONFIG_P2P7377u8 is_p2p = 0;7378#endif7379int type = (-1);7380systime start = rtw_get_current_time();7381_adapter *padapter;7382struct dvobj_priv *dvobj;7383struct rtw_wdev_priv *pwdev_priv;7384struct rf_ctl_t *rfctl;73857386#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))7387#if defined(RTW_DEDICATED_P2P_DEVICE)7388if (wdev == wiphy_to_pd_wdev(wiphy))7389padapter = wiphy_to_adapter(wiphy);7390else7391#endif7392if (wdev_to_ndev(wdev))7393padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));7394else {7395ret = -EINVAL;7396goto exit;7397}7398#else7399struct wireless_dev *wdev;74007401if (ndev == NULL) {7402ret = -EINVAL;7403goto exit;7404}7405padapter = (_adapter *)rtw_netdev_priv(ndev);7406wdev = ndev_to_wdev(ndev);7407#endif74087409if (chan == NULL) {7410ret = -EINVAL;7411goto exit;7412}74137414rfctl = adapter_to_rfctl(padapter);7415tx_ch = (u8)ieee80211_frequency_to_channel(chan->center_freq);7416if (IS_CH_WAITING(rfctl)) {7417#ifdef CONFIG_DFS_MASTER7418if (_rtw_rfctl_overlap_radar_detect_ch(rfctl, tx_ch, CHANNEL_WIDTH_20, HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {7419ret = -EINVAL;7420goto exit;7421}7422#endif7423}74247425dvobj = adapter_to_dvobj(padapter);7426pwdev_priv = adapter_wdev_data(padapter);74277428/* cookie generation */7429*cookie = pwdev_priv->mgmt_tx_cookie++;74307431#ifdef CONFIG_DEBUG_CFG802117432RTW_INFO(FUNC_ADPT_FMT"%s len=%zu, ch=%d"7433#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))7434", ch_type=%d"7435#endif7436#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))7437", channel_type_valid=%d"7438#endif7439"\n", FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""7440, len, tx_ch7441#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))7442, channel_type7443#endif7444#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))7445, channel_type_valid7446#endif7447);7448#endif /* CONFIG_DEBUG_CFG80211 */74497450/* indicate ack before issue frame to avoid racing with rsp frame */7451#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)7452rtw_cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, GFP_KERNEL);7453#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 36))7454cfg80211_action_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);7455#endif74567457frame_styp = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl) & IEEE80211_FCTL_STYPE;7458if (IEEE80211_STYPE_PROBE_RESP == frame_styp) {7459#ifdef CONFIG_DEBUG_CFG802117460RTW_INFO("RTW_Tx: probe_resp tx_ch=%d, no_cck=%u, da="MAC_FMT"\n", tx_ch, no_cck, MAC_ARG(GetAddr1Ptr(buf)));7461#endif /* CONFIG_DEBUG_CFG80211 */7462wait_ack = 0;7463goto dump;7464}7465else if (frame_styp == RTW_IEEE80211_STYPE_AUTH) {7466int retval = 0;74677468RTW_INFO("RTW_Tx:tx_ch=%d, no_cck=%u, da="MAC_FMT"\n", tx_ch, no_cck, MAC_ARG(GetAddr1Ptr(buf)));74697470retval = rtw_sae_preprocess(padapter, buf, len, _TRUE);7471if (retval == 2)7472goto exit;7473if (retval == 0)7474RTW_INFO("RTW_Tx:AUTH\n");7475dump_limit = 1;7476goto dump;7477}74787479if (rtw_action_frame_parse(buf, len, &category, &action) == _FALSE) {7480RTW_INFO(FUNC_ADPT_FMT" frame_control:0x%02x\n", FUNC_ADPT_ARG(padapter),7481le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl));7482goto exit;7483}74847485RTW_INFO("RTW_Tx:tx_ch=%d, no_cck=%u, da="MAC_FMT"\n", tx_ch, no_cck, MAC_ARG(GetAddr1Ptr(buf)));7486#ifdef CONFIG_P2P7487type = rtw_p2p_check_frames(padapter, buf, len, _TRUE);7488if (type >= 0) {7489is_p2p = 1;7490no_cck = 1; /* force no CCK for P2P frames */7491goto dump;7492}7493#endif7494#ifdef CONFIG_RTW_MESH7495if (MLME_IS_MESH(padapter)) {7496type = rtw_mesh_check_frames_tx(padapter, &dump_buf, &dump_len);7497if (type >= 0) {7498dump_limit = 1;7499goto dump;7500}7501}7502#endif7503if (category == RTW_WLAN_CATEGORY_PUBLIC) {7504RTW_INFO("RTW_Tx:%s\n", action_public_str(action));7505switch (action) {7506case ACT_PUBLIC_GAS_INITIAL_REQ:7507case ACT_PUBLIC_GAS_INITIAL_RSP:7508sleep_ms = 50;7509retry_guarantee_ms = RTW_MAX_MGMT_TX_MS_GAS;7510break;7511}7512}7513#ifdef CONFIG_RTW_80211K7514else if (category == RTW_WLAN_CATEGORY_RADIO_MEAS)7515RTW_INFO("RTW_Tx: RRM Action\n");7516#endif7517else7518RTW_INFO("RTW_Tx:category(%u), action(%u)\n", category, action);75197520dump:75217522rtw_ps_deny(padapter, PS_DENY_MGNT_TX);7523if (_FAIL == rtw_pwr_wakeup(padapter)) {7524ret = -EFAULT;7525goto cancel_ps_deny;7526}75277528while (1) {7529dump_cnt++;75307531rtw_mi_set_scan_deny(padapter, 1000);7532rtw_mi_scan_abort(padapter, _TRUE);7533tx_ret = rtw_mgnt_tx_cmd(padapter, tx_ch, no_cck, dump_buf, dump_len, wait_ack, RTW_CMDF_WAIT_ACK);7534if (tx_ret == _SUCCESS7535|| (dump_cnt >= dump_limit && rtw_get_passing_time_ms(start) >= retry_guarantee_ms))7536break;75377538if (sleep_ms > 0)7539rtw_msleep_os(sleep_ms);7540}75417542if (tx_ret != _SUCCESS || dump_cnt > 1) {7543RTW_INFO(FUNC_ADPT_FMT" %s (%d/%d) in %d ms\n", FUNC_ADPT_ARG(padapter),7544tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt, dump_limit, rtw_get_passing_time_ms(start));7545}75467547#ifdef CONFIG_P2P7548if (is_p2p) {7549switch (type) {7550case P2P_GO_NEGO_CONF:7551if (0) {7552RTW_INFO(FUNC_ADPT_FMT" Nego confirm. state=%u, status=%u, iaddr="MAC_FMT"\n"7553, FUNC_ADPT_ARG(padapter), pwdev_priv->nego_info.state, pwdev_priv->nego_info.status7554, MAC_ARG(pwdev_priv->nego_info.iface_addr));7555}7556if (pwdev_priv->nego_info.state == 27557&& pwdev_priv->nego_info.status == 07558&& rtw_check_invalid_mac_address(pwdev_priv->nego_info.iface_addr, _FALSE) == _FALSE7559) {7560_adapter *intended_iface = dvobj_get_adapter_by_addr(dvobj, pwdev_priv->nego_info.iface_addr);75617562if (intended_iface) {7563RTW_INFO(FUNC_ADPT_FMT" Nego confirm. Allow only "ADPT_FMT" to scan for 2000 ms\n"7564, FUNC_ADPT_ARG(padapter), ADPT_ARG(intended_iface));7565/* allow only intended_iface to do scan for 2000 ms */7566rtw_mi_set_scan_deny(padapter, 2000);7567rtw_clear_scan_deny(intended_iface);7568}7569}7570break;7571case P2P_INVIT_RESP:7572if (pwdev_priv->invit_info.flags & BIT(0)7573&& pwdev_priv->invit_info.status == 07574) {7575rtw_clear_scan_deny(padapter);7576RTW_INFO(FUNC_ADPT_FMT" agree with invitation of persistent group\n",7577FUNC_ADPT_ARG(padapter));7578#if !RTW_P2P_GROUP_INTERFACE7579rtw_mi_buddy_set_scan_deny(padapter, 5000);7580#endif7581rtw_pwr_wakeup_ex(padapter, 5000);7582}7583break;7584}7585}7586#endif /* CONFIG_P2P */75877588cancel_ps_deny:7589rtw_ps_deny_cancel(padapter, PS_DENY_MGNT_TX);75907591if (dump_buf != buf)7592rtw_mfree((u8 *)dump_buf, dump_len);7593exit:7594return ret;7595}75967597#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))7598static void cfg80211_rtw_update_mgmt_frame_register(struct wiphy *wiphy,7599struct wireless_dev *wdev,7600struct mgmt_frame_regs *upd)7601#else7602static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,7603#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))7604struct wireless_dev *wdev,7605#else7606struct net_device *ndev,7607#endif7608u16 frame_type, bool reg)7609#endif7610{7611#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))7612struct net_device *ndev = wdev_to_ndev(wdev);7613#endif7614_adapter *adapter;76157616struct rtw_wdev_priv *pwdev_priv;76177618if (ndev == NULL)7619goto exit;76207621adapter = (_adapter *)rtw_netdev_priv(ndev);7622pwdev_priv = adapter_wdev_data(adapter);76237624#ifdef CONFIG_DEBUG_CFG802117625RTW_INFO(FUNC_ADPT_FMT" frame_type:%x, reg:%d\n", FUNC_ADPT_ARG(adapter),7626frame_type, reg);7627#endif76287629exit:7630return;7631}76327633#if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))7634static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy,7635struct net_device *ndev,7636#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))7637const u8 *peer,7638#else7639u8 *peer,7640#endif7641#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))7642int link_id,7643#endif7644u8 action_code,7645u8 dialog_token,7646u16 status_code,7647#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))7648u32 peer_capability,7649#endif7650#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))7651bool initiator,7652#endif7653const u8 *buf,7654size_t len)7655{7656_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);7657struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;7658struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;7659int ret = 0;7660struct tdls_txmgmt txmgmt;76617662if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _FALSE) {7663RTW_INFO("Discard tdls action:%d, since hal doesn't support tdls\n", action_code);7664goto discard;7665}76667667if (rtw_is_tdls_enabled(padapter) == _FALSE) {7668RTW_INFO("TDLS is not enabled\n");7669goto discard;7670}76717672if (rtw_tdls_is_driver_setup(padapter)) {7673RTW_INFO("Discard tdls action:%d, let driver to set up direct link\n", action_code);7674goto discard;7675}76767677_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));7678_rtw_memcpy(txmgmt.peer, peer, ETH_ALEN);7679txmgmt.action_code = action_code;7680txmgmt.dialog_token = dialog_token;7681txmgmt.status_code = status_code;7682txmgmt.len = len;7683txmgmt.buf = (u8 *)rtw_malloc(txmgmt.len);7684if (txmgmt.buf == NULL) {7685ret = -ENOMEM;7686goto bad;7687}7688_rtw_memcpy(txmgmt.buf, (void *)buf, txmgmt.len);76897690/* Debug purpose */7691#if 17692RTW_INFO("%s %d\n", __FUNCTION__, __LINE__);7693RTW_INFO("peer:"MAC_FMT", action code:%d, dialog:%d, status code:%d\n",7694MAC_ARG(txmgmt.peer), txmgmt.action_code,7695txmgmt.dialog_token, txmgmt.status_code);7696if (txmgmt.len > 0) {7697int i = 0;7698for (; i < len; i++)7699printk("%02x ", *(txmgmt.buf + i));7700RTW_INFO("len:%d\n", (u32)txmgmt.len);7701}7702#endif77037704switch (txmgmt.action_code) {7705case TDLS_SETUP_REQUEST:7706issue_tdls_setup_req(padapter, &txmgmt, _TRUE);7707break;7708case TDLS_SETUP_RESPONSE:7709issue_tdls_setup_rsp(padapter, &txmgmt);7710break;7711case TDLS_SETUP_CONFIRM:7712issue_tdls_setup_cfm(padapter, &txmgmt);7713break;7714case TDLS_TEARDOWN:7715issue_tdls_teardown(padapter, &txmgmt, _TRUE);7716break;7717case TDLS_DISCOVERY_REQUEST:7718issue_tdls_dis_req(padapter, &txmgmt);7719break;7720case TDLS_DISCOVERY_RESPONSE:7721issue_tdls_dis_rsp(padapter, &txmgmt, pmlmeinfo->enc_algo ? _TRUE : _FALSE);7722break;7723}77247725bad:7726if (txmgmt.buf)7727rtw_mfree(txmgmt.buf, txmgmt.len);77287729discard:7730return ret;7731}77327733static int cfg80211_rtw_tdls_oper(struct wiphy *wiphy,7734struct net_device *ndev,7735#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))7736const u8 *peer,7737#else7738u8 *peer,7739#endif7740enum nl80211_tdls_operation oper)7741{7742_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);7743struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;7744struct tdls_txmgmt txmgmt;7745struct sta_info *ptdls_sta = NULL;77467747RTW_INFO(FUNC_NDEV_FMT", nl80211_tdls_operation:%d\n", FUNC_NDEV_ARG(ndev), oper);77487749if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _FALSE) {7750RTW_INFO("Discard tdls oper:%d, since hal doesn't support tdls\n", oper);7751return 0;7752}77537754if (rtw_is_tdls_enabled(padapter) == _FALSE) {7755RTW_INFO("TDLS is not enabled\n");7756return 0;7757}77587759#ifdef CONFIG_LPS7760rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 0);7761#endif /* CONFIG_LPS */77627763_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));7764if (peer)7765_rtw_memcpy(txmgmt.peer, peer, ETH_ALEN);77667767if (rtw_tdls_is_driver_setup(padapter)) {7768/* these two cases are done by driver itself */7769if (oper == NL80211_TDLS_ENABLE_LINK || oper == NL80211_TDLS_DISABLE_LINK)7770return 0;7771}77727773switch (oper) {7774case NL80211_TDLS_DISCOVERY_REQ:7775issue_tdls_dis_req(padapter, &txmgmt);7776break;7777case NL80211_TDLS_SETUP:7778#ifdef CONFIG_WFD7779if (_AES_ != padapter->securitypriv.dot11PrivacyAlgrthm) {7780if (padapter->wdinfo.wfd_tdls_weaksec == _TRUE)7781issue_tdls_setup_req(padapter, &txmgmt, _TRUE);7782else7783RTW_INFO("[%s] Current link is not AES, SKIP sending the tdls setup request!!\n", __FUNCTION__);7784} else7785#endif /* CONFIG_WFD */7786{7787issue_tdls_setup_req(padapter, &txmgmt, _TRUE);7788}7789break;7790case NL80211_TDLS_TEARDOWN:7791ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), txmgmt.peer);7792if (ptdls_sta != NULL) {7793txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;7794issue_tdls_teardown(padapter, &txmgmt, _TRUE);7795} else7796RTW_INFO("TDLS peer not found\n");7797break;7798case NL80211_TDLS_ENABLE_LINK:7799RTW_INFO(FUNC_NDEV_FMT", NL80211_TDLS_ENABLE_LINK;mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(peer));7800ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), (u8 *)peer);7801if (ptdls_sta != NULL) {7802rtw_tdls_set_link_established(padapter, _TRUE);7803ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;7804ptdls_sta->state |= _FW_LINKED;7805rtw_tdls_cmd(padapter, txmgmt.peer, TDLS_ESTABLISHED);7806}7807break;7808case NL80211_TDLS_DISABLE_LINK:7809RTW_INFO(FUNC_NDEV_FMT", NL80211_TDLS_DISABLE_LINK;mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(peer));7810ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), (u8 *)peer);7811if (ptdls_sta != NULL) {7812rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);7813rtw_tdls_cmd(padapter, (u8 *)peer, TDLS_TEARDOWN_STA_LOCALLY_POST);7814}7815break;7816}7817return 0;7818}7819#endif /* CONFIG_TDLS */78207821#if defined(CONFIG_RTW_MESH) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))78227823#if DBG_RTW_CFG80211_MESH_CONF7824#define LEGACY_RATES_STR_LEN (RTW_G_RATES_NUM * 5 + 1)7825int get_legacy_rates_str(struct wiphy *wiphy, enum nl80211_band band, u32 mask, char *buf)7826{7827int i;7828int cnt = 0;78297830for (i = 0; i < wiphy->bands[band]->n_bitrates; i++) {7831if (mask & BIT(i)) {7832cnt += snprintf(buf + cnt, LEGACY_RATES_STR_LEN - cnt -1, "%d.%d "7833, wiphy->bands[band]->bitrates[i].bitrate / 107834, wiphy->bands[band]->bitrates[i].bitrate % 10);7835if (cnt >= LEGACY_RATES_STR_LEN - 1)7836break;7837}7838}78397840return cnt;7841}78427843void dump_mesh_setup(void *sel, struct wiphy *wiphy, const struct mesh_setup *setup)7844{7845#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))7846#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))7847struct cfg80211_chan_def *chdef = (struct cfg80211_chan_def *)(&setup->chandef);7848#endif7849struct ieee80211_channel *chan;7850#endif78517852#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))7853chan = (struct ieee80211_channel *)chdef->chan;7854#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))7855chan = (struct ieee80211_channel *)setup->channel;7856#endif78577858RTW_PRINT_SEL(sel, "mesh_id:\"%s\", len:%u\n", setup->mesh_id, setup->mesh_id_len);7859#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))7860RTW_PRINT_SEL(sel, "sync_method:%u\n", setup->sync_method);7861#endif7862RTW_PRINT_SEL(sel, "path_sel_proto:%u, path_metric:%u\n", setup->path_sel_proto, setup->path_metric);7863#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))7864RTW_PRINT_SEL(sel, "auth_id:%u\n", setup->auth_id);7865#endif7866#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))7867if (setup->ie && setup->ie_len) {7868RTW_PRINT_SEL(sel, "ie:%p, len:%u\n", setup->ie, setup->ie_len);7869dump_ies(RTW_DBGDUMP, setup->ie, setup->ie_len);7870}7871#else7872if (setup->vendor_ie && setup->vendor_ie_len) {7873RTW_PRINT_SEL(sel, "ie:%p, len:%u\n", setup->vendor_ie, setup->vendor_ie_len);7874dump_ies(RTW_DBGDUMP, setup->vendor_ie, setup->vendor_ie_len);7875}7876#endif7877#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))7878RTW_PRINT_SEL(sel, "is_authenticated:%d, is_secure:%d\n", setup->is_authenticated, setup->is_secure);7879#endif7880#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))7881RTW_PRINT_SEL(sel, "user_mpm:%d\n", setup->user_mpm);7882#endif7883#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))7884RTW_PRINT_SEL(sel, "dtim_period:%u, beacon_interval:%u\n", setup->dtim_period, setup->beacon_interval);7885#endif78867887#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))7888#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))7889RTW_PRINT_SEL(sel, "center_freq:%u, ch:%u, width:%s, cfreq1:%u, cfreq2:%u\n"7890, chan->center_freq, chan->hw_value, nl80211_chan_width_str(chdef->width), chdef->center_freq1, chdef->center_freq2);7891#else7892RTW_PRINT_SEL(sel, "center_freq:%u, ch:%u, channel_type:%s\n"7893, chan->center_freq, chan->hw_value, nl80211_channel_type_str(setup->channel_type));7894#endif7895#endif78967897#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))7898if (setup->mcast_rate[chan->band]) {7899RTW_PRINT_SEL(sel, "mcast_rate:%d.%d\n"7900, wiphy->bands[chan->band]->bitrates[setup->mcast_rate[chan->band] - 1].bitrate / 107901, wiphy->bands[chan->band]->bitrates[setup->mcast_rate[chan->band] - 1].bitrate % 107902);7903}7904#endif79057906#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))7907if (setup->basic_rates) {7908char buf[LEGACY_RATES_STR_LEN] = {0};79097910get_legacy_rates_str(wiphy, chan->band, setup->basic_rates, buf);7911RTW_PRINT_SEL(sel, "basic_rates:%s\n", buf);7912}7913#endif79147915#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))7916if (setup->beacon_rate.control[chan->band].legacy) {7917char buf[LEGACY_RATES_STR_LEN] = {0};79187919get_legacy_rates_str(wiphy, chan->band, setup->beacon_rate.control[chan->band].legacy, buf);7920RTW_PRINT_SEL(sel, "beacon_rate.legacy:%s\n", buf);7921}7922if (*((u32 *)&(setup->beacon_rate.control[chan->band].ht_mcs[0]))7923|| *((u32 *)&(setup->beacon_rate.control[chan->band].ht_mcs[4]))7924|| *((u16 *)&(setup->beacon_rate.control[chan->band].ht_mcs[8]))7925) {7926RTW_PRINT_SEL(sel, "beacon_rate.ht_mcs:"HT_RX_MCS_BMP_FMT"\n"7927, HT_RX_MCS_BMP_ARG(setup->beacon_rate.control[chan->band].ht_mcs));7928}79297930if (setup->beacon_rate.control[chan->band].vht_mcs[0]7931|| setup->beacon_rate.control[chan->band].vht_mcs[1]7932|| setup->beacon_rate.control[chan->band].vht_mcs[2]7933|| setup->beacon_rate.control[chan->band].vht_mcs[3]7934) {7935int i;79367937for (i = 0; i < 4; i++) {/* parsing up to 4SS */7938u16 mcs_mask = setup->beacon_rate.control[chan->band].vht_mcs[i];79397940RTW_PRINT_SEL(sel, "beacon_rate.vht_mcs[%d]:%s\n", i7941, mcs_mask == 0x00FF ? "0~7" : mcs_mask == 0x01FF ? "0~8" : mcs_mask == 0x03FF ? "0~9" : "invalid");7942}7943}79447945if (setup->beacon_rate.control[chan->band].gi) {7946RTW_PRINT_SEL(sel, "beacon_rate.gi:%s\n"7947, setup->beacon_rate.control[chan->band].gi == NL80211_TXRATE_FORCE_SGI ? "SGI" :7948setup->beacon_rate.control[chan->band].gi == NL80211_TXRATE_FORCE_LGI ? "LGI" : "invalid"7949);7950}7951#endif7952}79537954void dump_mesh_config(void *sel, const struct mesh_config *conf)7955{7956RTW_PRINT_SEL(sel, "dot11MeshRetryTimeout:%u\n", conf->dot11MeshRetryTimeout);7957RTW_PRINT_SEL(sel, "dot11MeshConfirmTimeout:%u\n", conf->dot11MeshConfirmTimeout);7958RTW_PRINT_SEL(sel, "dot11MeshHoldingTimeout:%u\n", conf->dot11MeshHoldingTimeout);7959RTW_PRINT_SEL(sel, "dot11MeshMaxPeerLinks:%u\n", conf->dot11MeshMaxPeerLinks);7960RTW_PRINT_SEL(sel, "dot11MeshMaxRetries:%u\n", conf->dot11MeshMaxRetries);7961RTW_PRINT_SEL(sel, "dot11MeshTTL:%u\n", conf->dot11MeshTTL);7962RTW_PRINT_SEL(sel, "element_ttl:%u\n", conf->element_ttl);7963RTW_PRINT_SEL(sel, "auto_open_plinks:%d\n", conf->auto_open_plinks);79647965#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))7966RTW_PRINT_SEL(sel, "dot11MeshNbrOffsetMaxNeighbor:%u\n", conf->dot11MeshNbrOffsetMaxNeighbor);7967#endif79687969RTW_PRINT_SEL(sel, "dot11MeshHWMPmaxPREQretries:%u\n", conf->dot11MeshHWMPmaxPREQretries);7970RTW_PRINT_SEL(sel, "path_refresh_time:%u\n", conf->path_refresh_time);7971RTW_PRINT_SEL(sel, "min_discovery_timeout:%u\n", conf->min_discovery_timeout);7972RTW_PRINT_SEL(sel, "dot11MeshHWMPactivePathTimeout:%u\n", conf->dot11MeshHWMPactivePathTimeout);7973RTW_PRINT_SEL(sel, "dot11MeshHWMPpreqMinInterval:%u\n", conf->dot11MeshHWMPpreqMinInterval);7974#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))7975RTW_PRINT_SEL(sel, "dot11MeshHWMPperrMinInterval:%u\n", conf->dot11MeshHWMPperrMinInterval);7976#endif7977RTW_PRINT_SEL(sel, "dot11MeshHWMPnetDiameterTraversalTime:%u\n", conf->dot11MeshHWMPnetDiameterTraversalTime);7978RTW_PRINT_SEL(sel, "dot11MeshHWMPRootMode:%u\n", conf->dot11MeshHWMPRootMode);7979#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))7980RTW_PRINT_SEL(sel, "dot11MeshHWMPRannInterval:%u\n", conf->dot11MeshHWMPRannInterval);7981RTW_PRINT_SEL(sel, "dot11MeshGateAnnouncementProtocol:%d\n", conf->dot11MeshGateAnnouncementProtocol);7982#endif79837984#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))7985RTW_PRINT_SEL(sel, "dot11MeshForwarding:%d\n", conf->dot11MeshForwarding);7986RTW_PRINT_SEL(sel, "rssi_threshold:%d\n", conf->rssi_threshold);7987#endif79887989#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))7990RTW_PRINT_SEL(sel, "ht_opmode:0x%04x\n", conf->ht_opmode);7991#endif79927993#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))7994RTW_PRINT_SEL(sel, "dot11MeshHWMPactivePathToRootTimeout:%u\n", conf->dot11MeshHWMPactivePathToRootTimeout);7995RTW_PRINT_SEL(sel, "dot11MeshHWMProotInterval:%u\n", conf->dot11MeshHWMProotInterval);7996RTW_PRINT_SEL(sel, "dot11MeshHWMPconfirmationInterval:%u\n", conf->dot11MeshHWMPconfirmationInterval);7997#endif79987999#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))8000RTW_PRINT_SEL(sel, "power_mode:%s\n", nl80211_mesh_power_mode_str(conf->power_mode));8001RTW_PRINT_SEL(sel, "dot11MeshAwakeWindowDuration:%u\n", conf->dot11MeshAwakeWindowDuration);8002#endif80038004#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))8005RTW_PRINT_SEL(sel, "plink_timeout:%u\n", conf->plink_timeout);8006#endif8007}8008#endif /* DBG_RTW_CFG80211_MESH_CONF */80098010static void rtw_cfg80211_mesh_info_set_profile(struct rtw_mesh_info *minfo, const struct mesh_setup *setup)8011{8012_rtw_memcpy(minfo->mesh_id, setup->mesh_id, setup->mesh_id_len);8013minfo->mesh_id_len = setup->mesh_id_len;8014minfo->mesh_pp_id = setup->path_sel_proto;8015minfo->mesh_pm_id = setup->path_metric;8016minfo->mesh_cc_id = 0;8017#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))8018minfo->mesh_sp_id = setup->sync_method;8019#endif8020#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))8021minfo->mesh_auth_id = setup->auth_id;8022#else8023if (setup->is_authenticated) {8024u8 *rsn_ie;8025sint rsn_ie_len;8026struct rsne_info info;8027u8 *akm;8028u8 AKM_SUITE_SAE[4] = {0x00, 0x0F, 0xAC, 0x08};80298030rsn_ie = rtw_get_ie(setup->ie, WLAN_EID_RSN, &rsn_ie_len, setup->ie_len);8031if (!rsn_ie || !rsn_ie_len) {8032rtw_warn_on(1);8033return;8034}80358036if (rtw_rsne_info_parse(rsn_ie, rsn_ie_len + 2, &info) != _SUCCESS) {8037rtw_warn_on(1);8038return;8039}80408041if (!info.akm_list || !info.akm_cnt) {8042rtw_warn_on(1);8043return;8044}80458046akm = info.akm_list;8047while (akm < info.akm_list + info.akm_cnt * 4) {8048if (_rtw_memcmp(akm, AKM_SUITE_SAE, 4) == _TRUE) {8049minfo->mesh_auth_id = 0x01;8050break;8051}8052}80538054if (!minfo->mesh_auth_id) {8055rtw_warn_on(1);8056return;8057}8058}8059#endif8060}80618062static inline bool chk_mesh_attr(enum nl80211_meshconf_params parm, u32 mask)8063{8064return (mask >> (parm - 1)) & 0x1;8065}80668067static void rtw_cfg80211_mesh_cfg_set(_adapter *adapter, const struct mesh_config *conf, u32 mask)8068{8069struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;80708071#if 0 /* driver MPM */8072if (chk_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask));8073if (chk_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask));8074if (chk_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask));8075if (chk_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask));8076if (chk_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask));8077#endif80788079if (chk_mesh_attr(NL80211_MESHCONF_TTL, mask))8080mcfg->dot11MeshTTL = conf->dot11MeshTTL;8081if (chk_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))8082mcfg->element_ttl = conf->element_ttl;80838084#if 0 /* driver MPM */8085if (chk_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask));8086#endif80878088#if 0 /* TBD: synchronization */8089#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))8090if (chk_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask));8091#endif8092#endif80938094if (chk_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask))8095mcfg->dot11MeshHWMPmaxPREQretries = conf->dot11MeshHWMPmaxPREQretries;8096if (chk_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask))8097mcfg->path_refresh_time = conf->path_refresh_time;8098if (chk_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask))8099mcfg->min_discovery_timeout = conf->min_discovery_timeout;8100if (chk_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask))8101mcfg->dot11MeshHWMPactivePathTimeout = conf->dot11MeshHWMPactivePathTimeout;8102if (chk_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask))8103mcfg->dot11MeshHWMPpreqMinInterval = conf->dot11MeshHWMPpreqMinInterval;8104#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))8105if (chk_mesh_attr(NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, mask))8106mcfg->dot11MeshHWMPperrMinInterval = conf->dot11MeshHWMPperrMinInterval;8107#endif8108if (chk_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, mask))8109mcfg->dot11MeshHWMPnetDiameterTraversalTime = conf->dot11MeshHWMPnetDiameterTraversalTime;81108111if (chk_mesh_attr(NL80211_MESHCONF_HWMP_ROOTMODE, mask))8112mcfg->dot11MeshHWMPRootMode = conf->dot11MeshHWMPRootMode;8113#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))8114if (chk_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask))8115mcfg->dot11MeshGateAnnouncementProtocol = conf->dot11MeshGateAnnouncementProtocol;8116/* our current gate annc implementation rides on root annc with gate annc bit in PREQ flags */8117if (mcfg->dot11MeshGateAnnouncementProtocol8118&& mcfg->dot11MeshHWMPRootMode <= RTW_IEEE80211_ROOTMODE_ROOT8119) {8120mcfg->dot11MeshHWMPRootMode = RTW_IEEE80211_PROACTIVE_RANN;8121RTW_INFO(ADPT_FMT" enable PROACTIVE_RANN becaue gate annc is needed\n", ADPT_ARG(adapter));8122}8123if (chk_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask))8124mcfg->dot11MeshHWMPRannInterval = conf->dot11MeshHWMPRannInterval;8125#endif8126#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))8127if (chk_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))8128mcfg->dot11MeshForwarding = conf->dot11MeshForwarding;81298130if (chk_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask))8131mcfg->rssi_threshold = conf->rssi_threshold;8132#endif81338134#if 0 /* controlled by driver */8135#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))8136if (chk_mesh_attr(NL80211_MESHCONF_HT_OPMODE, mask));8137#endif8138#endif81398140#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))8141if (chk_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask))8142mcfg->dot11MeshHWMPactivePathToRootTimeout = conf->dot11MeshHWMPactivePathToRootTimeout;8143if (chk_mesh_attr(NL80211_MESHCONF_HWMP_ROOT_INTERVAL, mask))8144mcfg->dot11MeshHWMProotInterval = conf->dot11MeshHWMProotInterval;8145if (chk_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask))8146mcfg->dot11MeshHWMPconfirmationInterval = conf->dot11MeshHWMPconfirmationInterval;8147#endif81488149#if 0 /* TBD */8150#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))8151if (chk_mesh_attr(NL80211_MESHCONF_POWER_MODE, mask));8152if (chk_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask));8153#endif8154#endif81558156#if 0 /* driver MPM */8157#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))8158if (chk_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask));8159#endif8160#endif8161}81628163u8 *rtw_cfg80211_construct_mesh_beacon_ies(struct wiphy *wiphy, _adapter *adapter8164, const struct mesh_config *conf, const struct mesh_setup *setup8165, uint *ies_len)8166{8167struct rtw_mesh_info *minfo = &adapter->mesh_info;8168struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;8169#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))8170#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))8171struct cfg80211_chan_def *chdef = (struct cfg80211_chan_def *)(&setup->chandef);8172#endif8173struct ieee80211_channel *chan;8174u8 ch, bw, offset;8175#endif8176uint len;8177u8 n_bitrates;8178u8 ht = 0;8179u8 vht = 0;8180u8 *rsn_ie = NULL;8181sint rsn_ie_len = 0;8182u8 *ies = NULL, *c;8183u8 supported_rates[RTW_G_RATES_NUM] = {0};8184int i;81858186*ies_len = 0;81878188#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))8189chan = (struct ieee80211_channel *)chdef->chan;8190#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))8191chan = (struct ieee80211_channel *)setup->channel;8192#endif81938194n_bitrates = wiphy->bands[chan->band]->n_bitrates;81958196#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))8197#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))8198rtw_get_chbw_from_cfg80211_chan_def(chdef, &ht, &ch, &bw, &offset);8199#else8200rtw_get_chbw_from_nl80211_channel_type(chan, setup->channel_type, &ht, &ch, &bw, &offset);8201#endif8202if (!ch)8203goto exit;82048205#if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))8206vht = ht && ch > 14 && bw >= CHANNEL_WIDTH_80; /* VHT40/VHT20? */8207#endif82088209RTW_INFO(FUNC_ADPT_FMT" => ch:%u,%u,%u, ht:%u, vht:%u\n"8210, FUNC_ADPT_ARG(adapter), ch, bw, offset, ht, vht);8211#endif82128213rsn_ie = rtw_get_ie(setup->ie, WLAN_EID_RSN, &rsn_ie_len, setup->ie_len);8214if (rsn_ie && !rsn_ie_len) {8215rtw_warn_on(1);8216rsn_ie = NULL;8217}82188219len = _BEACON_IE_OFFSET_8220+ 2 /* 0-length SSID */8221+ (n_bitrates >= 8 ? 8 : n_bitrates) + 2 /* Supported Rates */8222+ 3 /* DS parameter set */8223+ 6 /* TIM */8224+ (n_bitrates > 8 ? n_bitrates - 8 + 2 : 0) /* Extended Supported Rates */8225+ (rsn_ie ? rsn_ie_len + 2 : 0) /* RSN */8226#if defined(CONFIG_80211N_HT)8227+ (ht ? HT_CAP_IE_LEN + 2 + HT_OP_IE_LEN + 2 : 0) /* HT */8228#endif8229#if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))8230+ (vht ? VHT_CAP_IE_LEN + 2 + VHT_OP_IE_LEN + 2 : 0) /* VHT */8231#endif8232+ minfo->mesh_id_len + 2 /* Mesh ID */8233+ 9 /* Mesh configuration */8234;82358236ies = rtw_zmalloc(len);8237if (!ies)8238goto exit;82398240/* timestamp */8241c = ies + 8;82428243/* beacon interval */8244RTW_PUT_LE16(c , setup->beacon_interval);8245c += 2;82468247/* capability */8248if (rsn_ie)8249*((u16 *)c) |= cpu_to_le16(cap_Privacy);8250c += 2;82518252/* SSID */8253c = rtw_set_ie(c, WLAN_EID_SSID, 0, NULL, NULL);82548255/* Supported Rates */8256for (i = 0; i < n_bitrates; i++) {8257supported_rates[i] = wiphy->bands[chan->band]->bitrates[i].bitrate / 5;8258#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))8259if (setup->basic_rates & BIT(i))8260#else8261if (rtw_is_basic_rate_mix(supported_rates[i]))8262#endif8263supported_rates[i] |= IEEE80211_BASIC_RATE_MASK;8264}8265c = rtw_set_ie(c, WLAN_EID_SUPP_RATES, (n_bitrates >= 8 ? 8 : n_bitrates), supported_rates, NULL);82668267/* DS parameter set */8268c = rtw_set_ie(c, WLAN_EID_DS_PARAMS, 1, &ch, NULL);82698270/* TIM */8271*c = WLAN_EID_TIM;8272*(c + 1) = 4;8273c += 6;8274//c = rtw_set_ie(c, _TIM_IE_, 4, NULL, NULL);82758276/* Extended Supported Rates */8277if (n_bitrates > 8)8278c = rtw_set_ie(c, WLAN_EID_EXT_SUPP_RATES, n_bitrates - 8, supported_rates + 8, NULL);82798280/* RSN */8281if (rsn_ie)8282c = rtw_set_ie(c, WLAN_EID_RSN, rsn_ie_len, rsn_ie + 2, NULL);82838284#if defined(CONFIG_80211N_HT)8285if (ht) {8286struct ieee80211_sta_ht_cap *sta_ht_cap = &wiphy->bands[chan->band]->ht_cap;8287u8 ht_cap[HT_CAP_IE_LEN];8288u8 ht_op[HT_OP_IE_LEN];82898290_rtw_memset(ht_cap, 0, HT_CAP_IE_LEN);8291_rtw_memset(ht_op, 0, HT_OP_IE_LEN);82928293/* WLAN_EID_HT_CAP */8294RTW_PUT_LE16(HT_CAP_ELE_CAP_INFO(ht_cap), sta_ht_cap->cap);8295SET_HT_CAP_ELE_MAX_AMPDU_LEN_EXP(ht_cap, sta_ht_cap->ampdu_factor);8296SET_HT_CAP_ELE_MIN_MPDU_S_SPACE(ht_cap, sta_ht_cap->ampdu_density);8297_rtw_memcpy(HT_CAP_ELE_SUP_MCS_SET(ht_cap), &sta_ht_cap->mcs, 16);8298c = rtw_set_ie(c, WLAN_EID_HT_CAP, HT_CAP_IE_LEN, ht_cap, NULL);82998300/* WLAN_EID_HT_OPERATION */8301SET_HT_OP_ELE_PRI_CHL(ht_op, ch);8302switch (offset) {8303case HAL_PRIME_CHNL_OFFSET_LOWER:8304SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op, SCA);8305break;8306case HAL_PRIME_CHNL_OFFSET_UPPER:8307SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op, SCB);8308break;8309case HAL_PRIME_CHNL_OFFSET_DONT_CARE:8310default:8311SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op, SCN);8312break;8313}8314if (bw >= CHANNEL_WIDTH_40)8315SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op, 1);8316else8317SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op, 0);8318c = rtw_set_ie(c, WLAN_EID_HT_OPERATION, HT_OP_IE_LEN, ht_op, NULL);8319}8320#endif /* defined(CONFIG_80211N_HT) */83218322#if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))8323if (vht) {8324struct ieee80211_sta_vht_cap *sta_vht_cap = &wiphy->bands[chan->band]->vht_cap;8325u8 vht_cap[VHT_CAP_IE_LEN];8326u8 vht_op[VHT_OP_IE_LEN];8327u8 cch = rtw_get_center_ch(ch, bw, offset);83288329_rtw_memset(vht_op, 0, VHT_OP_IE_LEN);83308331/* WLAN_EID_VHT_CAPABILITY */8332_rtw_memcpy(vht_cap, &sta_vht_cap->cap, 4);8333_rtw_memcpy(vht_cap + 4, &sta_vht_cap->vht_mcs, 8);8334c = rtw_set_ie(c, WLAN_EID_VHT_CAPABILITY, VHT_CAP_IE_LEN, vht_cap, NULL);83358336/* WLAN_EID_VHT_OPERATION */8337if (bw < CHANNEL_WIDTH_80) {8338SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op, 0);8339SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op, 0);8340SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op, 0);8341} else if (bw == CHANNEL_WIDTH_80) {8342SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op, 1);8343SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op, cch);8344SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op, 0);8345} else {8346RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), bw);8347rtw_warn_on(1);8348rtw_mfree(ies, len);8349goto exit;8350}83518352/* Hard code 1 stream, MCS0-7 is a min Basic VHT MCS rates */8353vht_op[3] = 0xfc;8354vht_op[4] = 0xff;8355c = rtw_set_ie(c, WLAN_EID_VHT_OPERATION, VHT_OP_IE_LEN, vht_op, NULL);8356}8357#endif /* defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */83588359/* Mesh ID */8360c = rtw_set_ie_mesh_id(c, NULL, minfo->mesh_id, minfo->mesh_id_len);83618362/* Mesh configuration */8363c = rtw_set_ie_mesh_config(c, NULL8364, minfo->mesh_pp_id8365, minfo->mesh_pm_id8366, minfo->mesh_cc_id8367, minfo->mesh_sp_id8368, minfo->mesh_auth_id8369, 0, 0, 08370, 18371, 0, 08372, mcfg->dot11MeshForwarding8373, 0, 0, 08374);83758376#if DBG_RTW_CFG80211_MESH_CONF8377RTW_INFO(FUNC_ADPT_FMT" ies_len:%u\n", FUNC_ADPT_ARG(adapter), len);8378dump_ies(RTW_DBGDUMP, ies + _BEACON_IE_OFFSET_, len - _BEACON_IE_OFFSET_);8379#endif83808381exit:8382if (ies)8383*ies_len = len;8384return ies;8385}83868387static int cfg80211_rtw_get_mesh_config(struct wiphy *wiphy, struct net_device *dev8388, struct mesh_config *conf)8389{8390_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8391struct rtw_mesh_cfg *mesh_cfg = &adapter->mesh_cfg;8392int ret = 0;83938394RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));83958396/* driver MPM */8397conf->dot11MeshRetryTimeout = 0;8398conf->dot11MeshConfirmTimeout = 0;8399conf->dot11MeshHoldingTimeout = 0;8400conf->dot11MeshMaxPeerLinks = mesh_cfg->max_peer_links;8401conf->dot11MeshMaxRetries = 0;84028403conf->dot11MeshTTL = mesh_cfg->dot11MeshTTL;8404conf->element_ttl = mesh_cfg->element_ttl;84058406/* driver MPM */8407conf->auto_open_plinks = 0;84088409/* TBD: synchronization */8410#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))8411conf->dot11MeshNbrOffsetMaxNeighbor = 0;8412#endif84138414conf->dot11MeshHWMPmaxPREQretries = mesh_cfg->dot11MeshHWMPmaxPREQretries;8415conf->path_refresh_time = mesh_cfg->path_refresh_time;8416conf->min_discovery_timeout = mesh_cfg->min_discovery_timeout;8417conf->dot11MeshHWMPactivePathTimeout = mesh_cfg->dot11MeshHWMPactivePathTimeout;8418conf->dot11MeshHWMPpreqMinInterval = mesh_cfg->dot11MeshHWMPpreqMinInterval;8419#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))8420conf->dot11MeshHWMPperrMinInterval = mesh_cfg->dot11MeshHWMPperrMinInterval;8421#endif8422conf->dot11MeshHWMPnetDiameterTraversalTime = mesh_cfg->dot11MeshHWMPnetDiameterTraversalTime;8423conf->dot11MeshHWMPRootMode = mesh_cfg->dot11MeshHWMPRootMode;8424#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))8425conf->dot11MeshHWMPRannInterval = mesh_cfg->dot11MeshHWMPRannInterval;8426#endif8427conf->dot11MeshGateAnnouncementProtocol = mesh_cfg->dot11MeshGateAnnouncementProtocol;8428#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))8429conf->dot11MeshForwarding = mesh_cfg->dot11MeshForwarding;8430conf->rssi_threshold = mesh_cfg->rssi_threshold;8431#endif84328433/* TBD */8434#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))8435conf->ht_opmode = 0xffff;8436#endif84378438#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))8439conf->dot11MeshHWMPactivePathToRootTimeout = mesh_cfg->dot11MeshHWMPactivePathToRootTimeout;8440conf->dot11MeshHWMProotInterval = mesh_cfg->dot11MeshHWMProotInterval;8441conf->dot11MeshHWMPconfirmationInterval = mesh_cfg->dot11MeshHWMPconfirmationInterval;8442#endif84438444/* TBD: power save */8445#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))8446conf->power_mode = NL80211_MESH_POWER_ACTIVE;8447conf->dot11MeshAwakeWindowDuration = 0;8448#endif84498450#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))8451conf->plink_timeout = mesh_cfg->plink_timeout;8452#endif84538454return ret;8455}84568457static void rtw_mbss_info_change_notify(_adapter *adapter, bool minfo_changed, bool need_work)8458{8459if (need_work)8460rtw_mesh_work(&adapter->mesh_work);8461}84628463static int cfg80211_rtw_update_mesh_config(struct wiphy *wiphy, struct net_device *dev8464, u32 mask, const struct mesh_config *nconf)8465{8466_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8467int ret = 0;8468bool minfo_changed = _FALSE, need_work = _FALSE;84698470RTW_INFO(FUNC_ADPT_FMT" mask:0x%08x\n", FUNC_ADPT_ARG(adapter), mask);84718472rtw_cfg80211_mesh_cfg_set(adapter, nconf, mask);8473update_beacon(adapter, WLAN_EID_MESH_CONFIG, NULL, _TRUE, 0);8474#if CONFIG_RTW_MESH_CTO_MGATE_CARRIER8475if (rtw_mesh_cto_mgate_required(adapter))8476rtw_netif_carrier_off(adapter->pnetdev);8477else8478rtw_netif_carrier_on(adapter->pnetdev);8479#endif8480need_work = rtw_ieee80211_mesh_root_setup(adapter);84818482rtw_mbss_info_change_notify(adapter, minfo_changed, need_work);84838484return ret;8485}84868487static int cfg80211_rtw_join_mesh(struct wiphy *wiphy, struct net_device *dev,8488const struct mesh_config *conf, const struct mesh_setup *setup)8489{8490_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8491u8 *ies = NULL;8492uint ies_len;8493int ret = 0;84948495RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));84968497#if DBG_RTW_CFG80211_MESH_CONF8498RTW_INFO(FUNC_ADPT_FMT" mesh_setup:\n", FUNC_ADPT_ARG(adapter));8499dump_mesh_setup(RTW_DBGDUMP, wiphy, setup);8500RTW_INFO(FUNC_ADPT_FMT" mesh_config:\n", FUNC_ADPT_ARG(adapter));8501dump_mesh_config(RTW_DBGDUMP, conf);8502#endif85038504if (rtw_cfg80211_sync_iftype(adapter) != _SUCCESS) {8505ret = -ENOTSUPP;8506goto exit;8507}85088509/* initialization */8510rtw_mesh_init_mesh_info(adapter);85118512/* apply cfg80211 settings*/8513rtw_cfg80211_mesh_info_set_profile(&adapter->mesh_info, setup);8514rtw_cfg80211_mesh_cfg_set(adapter, conf, 0xFFFFFFFF);85158516/* apply cfg80211 settings (join only) */8517rtw_mesh_cfg_init_max_peer_links(adapter, conf->dot11MeshMaxPeerLinks);8518#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))8519rtw_mesh_cfg_init_plink_timeout(adapter, conf->plink_timeout);8520#endif85218522rtw_ieee80211_mesh_root_setup(adapter);85238524ies = rtw_cfg80211_construct_mesh_beacon_ies(wiphy, adapter, conf, setup, &ies_len);8525if (!ies) {8526ret = -EINVAL;8527goto exit;8528}85298530/* start mbss */8531if (rtw_check_beacon_data(adapter, ies, ies_len) != _SUCCESS) {8532ret = -EINVAL;8533goto exit;8534}85358536rtw_mesh_work(&adapter->mesh_work);85378538exit:8539if (ies)8540rtw_mfree(ies, ies_len);8541if (ret)8542rtw_mesh_deinit_mesh_info(adapter);85438544return ret;8545}85468547static int cfg80211_rtw_leave_mesh(struct wiphy *wiphy, struct net_device *dev)8548{8549_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8550int ret = 0;85518552RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));85538554rtw_mesh_deinit_mesh_info(adapter);85558556rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11Infrastructure, 0);8557rtw_setopmode_cmd(adapter, Ndis802_11Infrastructure, RTW_CMDF_WAIT_ACK);85588559return ret;8560}85618562static int cfg80211_rtw_add_mpath(struct wiphy *wiphy, struct net_device *dev8563#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))8564, const u8 *dst, const u8 *next_hop8565#else8566, u8 *dst, u8 *next_hop8567#endif8568)8569{8570_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8571struct sta_priv *stapriv = &adapter->stapriv;8572struct sta_info *sta;8573struct rtw_mesh_path *mpath;8574int ret = 0;85758576rtw_rcu_read_lock();85778578sta = rtw_get_stainfo(stapriv, next_hop);8579if (!sta) {8580ret = -ENOENT;8581goto exit;8582}85838584mpath = rtw_mesh_path_add(adapter, dst);8585if (!mpath) {8586ret = -ENOENT;8587goto exit;8588}85898590rtw_mesh_path_fix_nexthop(mpath, sta);85918592exit:8593rtw_rcu_read_unlock();85948595return ret;8596}85978598static int cfg80211_rtw_del_mpath(struct wiphy *wiphy, struct net_device *dev8599#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))8600, const u8 *dst8601#else8602, u8 *dst8603#endif8604)8605{8606_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8607int ret = 0;86088609if (dst) {8610if (rtw_mesh_path_del(adapter, dst)) {8611ret = -ENOENT;8612goto exit;8613}8614} else {8615rtw_mesh_path_flush_by_iface(adapter);8616}86178618exit:8619return ret;8620}86218622static int cfg80211_rtw_change_mpath(struct wiphy *wiphy, struct net_device *dev8623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))8624, const u8 *dst, const u8 *next_hop8625#else8626, u8 *dst, u8 *next_hop8627#endif8628)8629{8630_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8631struct sta_priv *stapriv = &adapter->stapriv;8632struct sta_info *sta;8633struct rtw_mesh_path *mpath;8634int ret = 0;86358636rtw_rcu_read_lock();86378638sta = rtw_get_stainfo(stapriv, next_hop);8639if (!sta) {8640ret = -ENOENT;8641goto exit;8642}86438644mpath = rtw_mesh_path_lookup(adapter, dst);8645if (!mpath) {8646ret = -ENOENT;8647goto exit;8648}86498650rtw_mesh_path_fix_nexthop(mpath, sta);86518652exit:8653rtw_rcu_read_unlock();86548655return ret;8656}86578658static void rtw_cfg80211_mpath_set_pinfo(struct rtw_mesh_path *mpath, u8 *next_hop, struct mpath_info *pinfo)8659{8660struct sta_info *next_hop_sta = rtw_rcu_dereference(mpath->next_hop);86618662if (next_hop_sta)8663_rtw_memcpy(next_hop, next_hop_sta->cmn.mac_addr, ETH_ALEN);8664else8665_rtw_memset(next_hop, 0, ETH_ALEN);86668667_rtw_memset(pinfo, 0, sizeof(*pinfo));86688669pinfo->generation = mpath->adapter->mesh_info.mesh_paths_generation;86708671pinfo->filled = 08672| MPATH_INFO_FRAME_QLEN8673| MPATH_INFO_SN8674| MPATH_INFO_METRIC8675| MPATH_INFO_EXPTIME8676| MPATH_INFO_DISCOVERY_TIMEOUT8677| MPATH_INFO_DISCOVERY_RETRIES8678| MPATH_INFO_FLAGS8679;86808681pinfo->frame_qlen = mpath->frame_queue_len;8682pinfo->sn = mpath->sn;8683pinfo->metric = mpath->metric;8684if (rtw_time_after(mpath->exp_time, rtw_get_current_time()))8685pinfo->exptime = rtw_get_remaining_time_ms(mpath->exp_time);8686pinfo->discovery_timeout = rtw_systime_to_ms(mpath->discovery_timeout);8687pinfo->discovery_retries = mpath->discovery_retries;8688if (mpath->flags & RTW_MESH_PATH_ACTIVE)8689pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;8690if (mpath->flags & RTW_MESH_PATH_RESOLVING)8691pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;8692if (mpath->flags & RTW_MESH_PATH_SN_VALID)8693pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;8694if (mpath->flags & RTW_MESH_PATH_FIXED)8695pinfo->flags |= NL80211_MPATH_FLAG_FIXED;8696if (mpath->flags & RTW_MESH_PATH_RESOLVED)8697pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED;8698}86998700static int cfg80211_rtw_get_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop, struct mpath_info *pinfo)8701{8702_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8703struct rtw_mesh_path *mpath;8704int ret = 0;87058706rtw_rcu_read_lock();87078708mpath = rtw_mesh_path_lookup(adapter, dst);8709if (!mpath) {8710ret = -ENOENT;8711goto exit;8712}87138714rtw_cfg80211_mpath_set_pinfo(mpath, next_hop, pinfo);87158716exit:8717rtw_rcu_read_unlock();87188719return ret;8720}87218722static int cfg80211_rtw_dump_mpath(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *next_hop, struct mpath_info *pinfo)8723{8724_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8725struct rtw_mesh_path *mpath;8726int ret = 0;87278728rtw_rcu_read_lock();87298730mpath = rtw_mesh_path_lookup_by_idx(adapter, idx);8731if (!mpath) {8732ret = -ENOENT;8733goto exit;8734}87358736_rtw_memcpy(dst, mpath->dst, ETH_ALEN);8737rtw_cfg80211_mpath_set_pinfo(mpath, next_hop, pinfo);87388739exit:8740rtw_rcu_read_unlock();87418742return ret;8743}87448745#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))8746static void rtw_cfg80211_mpp_set_pinfo(struct rtw_mesh_path *mpath, u8 *mpp, struct mpath_info *pinfo)8747{8748_rtw_memcpy(mpp, mpath->mpp, ETH_ALEN);87498750_rtw_memset(pinfo, 0, sizeof(*pinfo));8751pinfo->generation = mpath->adapter->mesh_info.mpp_paths_generation;8752}87538754static int cfg80211_rtw_get_mpp(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *mpp, struct mpath_info *pinfo)8755{8756_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8757struct rtw_mesh_path *mpath;8758int ret = 0;87598760rtw_rcu_read_lock();87618762mpath = rtw_mpp_path_lookup(adapter, dst);8763if (!mpath) {8764ret = -ENOENT;8765goto exit;8766}87678768rtw_cfg80211_mpp_set_pinfo(mpath, mpp, pinfo);87698770exit:8771rtw_rcu_read_unlock();87728773return ret;8774}87758776static int cfg80211_rtw_dump_mpp(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *mpp, struct mpath_info *pinfo)8777{8778_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);8779struct rtw_mesh_path *mpath;8780int ret = 0;87818782rtw_rcu_read_lock();87838784mpath = rtw_mpp_path_lookup_by_idx(adapter, idx);8785if (!mpath) {8786ret = -ENOENT;8787goto exit;8788}87898790_rtw_memcpy(dst, mpath->dst, ETH_ALEN);8791rtw_cfg80211_mpp_set_pinfo(mpath, mpp, pinfo);87928793exit:8794rtw_rcu_read_unlock();87958796return ret;8797}8798#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */87998800#endif /* defined(CONFIG_RTW_MESH) */88018802#if defined(CONFIG_PNO_SUPPORT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))8803static int cfg80211_rtw_sched_scan_start(struct wiphy *wiphy,8804struct net_device *dev,8805struct cfg80211_sched_scan_request *request)8806{88078808_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);8809struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);8810struct cfg80211_ssid *ssids;8811int n_ssids = 0;8812int interval = 0;8813int i = 0;8814u8 ret;88158816if (padapter->bup == _FALSE) {8817RTW_INFO("%s: net device is down.\n", __func__);8818return -EIO;8819}88208821if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE ||8822check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE ||8823check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) {8824RTW_INFO("%s: device is busy.\n", __func__);8825rtw_scan_abort(padapter);8826}88278828if (request == NULL) {8829RTW_INFO("%s: invalid cfg80211_requests parameters.\n", __func__);8830return -EINVAL;8831}8832#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)88338834#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)8835interval = request->scan_plans->interval;8836#else8837interval = request->interval;8838#endif8839n_ssids = request->n_match_sets;8840ssids = (struct cfg80211_ssid *)rtw_zmalloc(n_ssids * sizeof(struct cfg80211_ssid));8841if(ssids == NULL) {8842RTW_ERR("Fail to allocate ssids for PNO\n");8843return -ENOMEM;8844}8845for (i=0;i<request->n_match_sets;i++) {8846ssids[i].ssid_len = request->match_sets[i].ssid.ssid_len;8847memcpy(ssids[i].ssid, request->match_sets[i].ssid.ssid,8848request->match_sets[i].ssid.ssid_len);8849}8850#else8851interval = request->interval;8852n_ssids = request->n_ssids;8853ssids = request->ssids;8854#endif8855ret = rtw_android_cfg80211_pno_setup(dev, ssids,8856n_ssids, interval);8857if (ret < 0) {8858RTW_INFO("%s ret: %d\n", __func__, ret);8859goto exit;8860}88618862ret = rtw_android_pno_enable(dev, _TRUE);8863if (ret < 0) {8864RTW_INFO("%s ret: %d\n", __func__, ret);8865goto exit;8866}8867exit:8868return ret;8869}88708871static int cfg80211_rtw_sched_scan_stop(struct wiphy *wiphy,8872struct net_device *dev)8873{8874return rtw_android_pno_enable(dev, _FALSE);8875}88768877int cfg80211_rtw_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) {8878RTW_DBG("==> %s\n",__func__);8879RTW_DBG("<== %s\n",__func__);8880return 0;8881}88828883int cfg80211_rtw_resume(struct wiphy *wiphy) {88848885_adapter *padapter;8886struct pwrctrl_priv *pwrpriv;8887struct mlme_priv *pmlmepriv;8888padapter = wiphy_to_adapter(wiphy);8889pwrpriv = adapter_to_pwrctl(padapter);8890pmlmepriv = &padapter->mlmepriv;8891struct sitesurvey_parm parm;8892int i, len;889388948895RTW_DBG("==> %s\n",__func__);8896if (pwrpriv->wowlan_last_wake_reason == RX_PNO) {88978898struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);8899_irqL irqL;8900int PNOWakeupScanWaitCnt = 0;89018902rtw_cfg80211_disconnected(padapter->rtw_wdev, 0, NULL, 0, 1, GFP_ATOMIC);89038904rtw_init_sitesurvey_parm(padapter, &parm);8905for (i=0;i<pwrpriv->pnlo_info->ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {8906len = pwrpriv->pno_ssid_list->node[i].SSID_len;8907_rtw_memcpy(&parm.ssid[i].Ssid, pwrpriv->pno_ssid_list->node[i].SSID, len);8908parm.ssid[i].SsidLength = len;8909}8910parm.ssid_num = pwrpriv->pnlo_info->ssid_num;89118912_enter_critical_bh(&pmlmepriv->lock, &irqL);8913//This modification fix PNO wakeup reconnect issue with hidden SSID AP.8914//rtw_sitesurvey_cmd(padapter, NULL);8915rtw_sitesurvey_cmd(padapter, &parm);8916_exit_critical_bh(&pmlmepriv->lock, &irqL);89178918for (PNOWakeupScanWaitCnt = 0; PNOWakeupScanWaitCnt < 10; PNOWakeupScanWaitCnt++) {8919if(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _FALSE)8920break;8921rtw_msleep_os(1000);8922}89238924_enter_critical_bh(&pmlmepriv->lock, &irqL);8925cfg80211_sched_scan_results(padapter->rtw_wdev->wiphy);8926_exit_critical_bh(&pmlmepriv->lock, &irqL);89278928}8929RTW_DBG("<== %s\n",__func__);8930return 0;89318932}8933#endif /* CONFIG_PNO_SUPPORT */89348935static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf, int len)8936{8937int ret = 0;8938uint wps_ielen = 0;8939u8 *wps_ie;8940u32 p2p_ielen = 0;8941u8 wps_oui[8] = {0x0, 0x50, 0xf2, 0x04};8942u8 *p2p_ie;8943u32 wfd_ielen = 0;8944u8 *wfd_ie;8945_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);8946struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);8947struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);89488949RTW_INFO(FUNC_NDEV_FMT" ielen=%d\n", FUNC_NDEV_ARG(ndev), len);89508951if (len > 0) {8952wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);8953if (wps_ie) {8954#ifdef CONFIG_DEBUG_CFG802118955RTW_INFO("bcn_wps_ielen=%d\n", wps_ielen);8956#endif89578958if (pmlmepriv->wps_beacon_ie) {8959u32 free_len = pmlmepriv->wps_beacon_ie_len;8960pmlmepriv->wps_beacon_ie_len = 0;8961rtw_mfree(pmlmepriv->wps_beacon_ie, free_len);8962pmlmepriv->wps_beacon_ie = NULL;8963}89648965pmlmepriv->wps_beacon_ie = rtw_malloc(wps_ielen);8966if (pmlmepriv->wps_beacon_ie == NULL) {8967RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);8968return -EINVAL;89698970}89718972_rtw_memcpy(pmlmepriv->wps_beacon_ie, wps_ie, wps_ielen);8973pmlmepriv->wps_beacon_ie_len = wps_ielen;89748975update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE, RTW_CMDF_WAIT_ACK);89768977}89788979/* buf += wps_ielen; */8980/* len -= wps_ielen; */89818982#ifdef CONFIG_P2P8983p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);8984if (p2p_ie) {8985#ifdef CONFIG_DEBUG_CFG802118986RTW_INFO("bcn_p2p_ielen=%d\n", p2p_ielen);8987#endif89888989if (pmlmepriv->p2p_beacon_ie) {8990u32 free_len = pmlmepriv->p2p_beacon_ie_len;8991pmlmepriv->p2p_beacon_ie_len = 0;8992rtw_mfree(pmlmepriv->p2p_beacon_ie, free_len);8993pmlmepriv->p2p_beacon_ie = NULL;8994}89958996pmlmepriv->p2p_beacon_ie = rtw_malloc(p2p_ielen);8997if (pmlmepriv->p2p_beacon_ie == NULL) {8998RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);8999return -EINVAL;90009001}90029003_rtw_memcpy(pmlmepriv->p2p_beacon_ie, p2p_ie, p2p_ielen);9004pmlmepriv->p2p_beacon_ie_len = p2p_ielen;90059006}9007#endif /* CONFIG_P2P */900890099010#ifdef CONFIG_WFD9011wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);9012if (wfd_ie) {9013#ifdef CONFIG_DEBUG_CFG802119014RTW_INFO("bcn_wfd_ielen=%d\n", wfd_ielen);9015#endif90169017if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_BEACON_IE, wfd_ie, wfd_ielen) != _SUCCESS)9018return -EINVAL;9019}9020#endif /* CONFIG_WFD */90219022pmlmeext->bstart_bss = _TRUE;90239024}90259026return ret;90279028}90299030static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net, char *buf, int len)9031{9032int ret = 0;9033uint wps_ielen = 0;9034u8 *wps_ie;9035u32 p2p_ielen = 0;9036u8 *p2p_ie;9037u32 wfd_ielen = 0;9038u8 *wfd_ie;9039_adapter *padapter = (_adapter *)rtw_netdev_priv(net);9040struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);90419042#ifdef CONFIG_DEBUG_CFG802119043RTW_INFO("%s, ielen=%d\n", __func__, len);9044#endif90459046if (len > 0) {9047wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);9048if (wps_ie) {9049uint attr_contentlen = 0;9050u16 uconfig_method, *puconfig_method = NULL;90519052#ifdef CONFIG_DEBUG_CFG802119053RTW_INFO("probe_resp_wps_ielen=%d\n", wps_ielen);9054#endif90559056if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {9057u8 sr = 0;9058rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);90599060if (sr != 0)9061RTW_INFO("%s, got sr\n", __func__);9062else {9063RTW_INFO("GO mode process WPS under site-survey, sr no set\n");9064return ret;9065}9066}90679068if (pmlmepriv->wps_probe_resp_ie) {9069u32 free_len = pmlmepriv->wps_probe_resp_ie_len;9070pmlmepriv->wps_probe_resp_ie_len = 0;9071rtw_mfree(pmlmepriv->wps_probe_resp_ie, free_len);9072pmlmepriv->wps_probe_resp_ie = NULL;9073}90749075pmlmepriv->wps_probe_resp_ie = rtw_malloc(wps_ielen);9076if (pmlmepriv->wps_probe_resp_ie == NULL) {9077RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);9078return -EINVAL;90799080}90819082/* add PUSH_BUTTON config_method by driver self in wpsie of probe_resp at GO Mode */9083puconfig_method = (u16 *)rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_CONF_METHOD , NULL, &attr_contentlen);9084if (puconfig_method != NULL) {9085/* struct registry_priv *pregistrypriv = &padapter->registrypriv; */9086struct wireless_dev *wdev = padapter->rtw_wdev;90879088#ifdef CONFIG_DEBUG_CFG802119089/* printk("config_method in wpsie of probe_resp = 0x%x\n", be16_to_cpu(*puconfig_method)); */9090#endif90919092#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)9093/* for WIFI-DIRECT LOGO 4.2.2, AUTO GO can't set PUSH_BUTTON flags */9094if (wdev->iftype == NL80211_IFTYPE_P2P_GO) {9095uconfig_method = WPS_CM_PUSH_BUTTON;9096uconfig_method = cpu_to_be16(uconfig_method);90979098*puconfig_method &= ~uconfig_method;9099}9100#endif9101}91029103_rtw_memcpy(pmlmepriv->wps_probe_resp_ie, wps_ie, wps_ielen);9104pmlmepriv->wps_probe_resp_ie_len = wps_ielen;91059106}91079108/* buf += wps_ielen; */9109/* len -= wps_ielen; */91109111#ifdef CONFIG_P2P9112p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);9113if (p2p_ie) {9114u8 is_GO = _FALSE;9115u32 attr_contentlen = 0;9116u16 cap_attr = 0;91179118#ifdef CONFIG_DEBUG_CFG802119119RTW_INFO("probe_resp_p2p_ielen=%d\n", p2p_ielen);9120#endif91219122/* Check P2P Capability ATTR */9123if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *) &attr_contentlen)) {9124u8 grp_cap = 0;9125/* RTW_INFO( "[%s] Got P2P Capability Attr!!\n", __FUNCTION__ ); */9126cap_attr = le16_to_cpu(cap_attr);9127grp_cap = (u8)((cap_attr >> 8) & 0xff);91289129is_GO = (grp_cap & BIT(0)) ? _TRUE : _FALSE;91309131if (is_GO)9132RTW_INFO("Got P2P Capability Attr, grp_cap=0x%x, is_GO\n", grp_cap);9133}913491359136if (is_GO == _FALSE) {9137if (pmlmepriv->p2p_probe_resp_ie) {9138u32 free_len = pmlmepriv->p2p_probe_resp_ie_len;9139pmlmepriv->p2p_probe_resp_ie_len = 0;9140rtw_mfree(pmlmepriv->p2p_probe_resp_ie, free_len);9141pmlmepriv->p2p_probe_resp_ie = NULL;9142}91439144pmlmepriv->p2p_probe_resp_ie = rtw_malloc(p2p_ielen);9145if (pmlmepriv->p2p_probe_resp_ie == NULL) {9146RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);9147return -EINVAL;91489149}9150_rtw_memcpy(pmlmepriv->p2p_probe_resp_ie, p2p_ie, p2p_ielen);9151pmlmepriv->p2p_probe_resp_ie_len = p2p_ielen;9152} else {9153if (pmlmepriv->p2p_go_probe_resp_ie) {9154u32 free_len = pmlmepriv->p2p_go_probe_resp_ie_len;9155pmlmepriv->p2p_go_probe_resp_ie_len = 0;9156rtw_mfree(pmlmepriv->p2p_go_probe_resp_ie, free_len);9157pmlmepriv->p2p_go_probe_resp_ie = NULL;9158}91599160pmlmepriv->p2p_go_probe_resp_ie = rtw_malloc(p2p_ielen);9161if (pmlmepriv->p2p_go_probe_resp_ie == NULL) {9162RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);9163return -EINVAL;91649165}9166_rtw_memcpy(pmlmepriv->p2p_go_probe_resp_ie, p2p_ie, p2p_ielen);9167pmlmepriv->p2p_go_probe_resp_ie_len = p2p_ielen;9168}91699170}9171#endif /* CONFIG_P2P */917291739174#ifdef CONFIG_WFD9175wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);9176if (wfd_ie) {9177#ifdef CONFIG_DEBUG_CFG802119178RTW_INFO("probe_resp_wfd_ielen=%d\n", wfd_ielen);9179#endif91809181if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_PROBE_RESP_IE, wfd_ie, wfd_ielen) != _SUCCESS)9182return -EINVAL;9183}9184#endif /* CONFIG_WFD */91859186}91879188return ret;91899190}91919192static int rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device *net, char *buf, int len)9193{9194int ret = 0;9195_adapter *padapter = (_adapter *)rtw_netdev_priv(net);9196struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);9197u8 *ie;9198u32 ie_len;91999200RTW_INFO("%s, ielen=%d\n", __func__, len);92019202if (len <= 0)9203goto exit;92049205ie = rtw_get_wps_ie(buf, len, NULL, &ie_len);9206if (ie && ie_len) {9207if (pmlmepriv->wps_assoc_resp_ie) {9208u32 free_len = pmlmepriv->wps_assoc_resp_ie_len;92099210pmlmepriv->wps_assoc_resp_ie_len = 0;9211rtw_mfree(pmlmepriv->wps_assoc_resp_ie, free_len);9212pmlmepriv->wps_assoc_resp_ie = NULL;9213}92149215pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);9216if (pmlmepriv->wps_assoc_resp_ie == NULL) {9217RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);9218return -EINVAL;9219}9220_rtw_memcpy(pmlmepriv->wps_assoc_resp_ie, ie, ie_len);9221pmlmepriv->wps_assoc_resp_ie_len = ie_len;9222}92239224ie = rtw_get_p2p_ie(buf, len, NULL, &ie_len);9225if (ie && ie_len) {9226if (pmlmepriv->p2p_assoc_resp_ie) {9227u32 free_len = pmlmepriv->p2p_assoc_resp_ie_len;92289229pmlmepriv->p2p_assoc_resp_ie_len = 0;9230rtw_mfree(pmlmepriv->p2p_assoc_resp_ie, free_len);9231pmlmepriv->p2p_assoc_resp_ie = NULL;9232}92339234pmlmepriv->p2p_assoc_resp_ie = rtw_malloc(ie_len);9235if (pmlmepriv->p2p_assoc_resp_ie == NULL) {9236RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);9237return -EINVAL;9238}9239_rtw_memcpy(pmlmepriv->p2p_assoc_resp_ie, ie, ie_len);9240pmlmepriv->p2p_assoc_resp_ie_len = ie_len;9241}92429243#ifdef CONFIG_WFD9244ie = rtw_get_wfd_ie(buf, len, NULL, &ie_len);9245if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_ASSOC_RESP_IE, ie, ie_len) != _SUCCESS)9246return -EINVAL;9247#endif92489249exit:9250return ret;9251}92529253int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,9254int type)9255{9256int ret = 0;9257uint wps_ielen = 0;9258u32 p2p_ielen = 0;92599260#ifdef CONFIG_DEBUG_CFG802119261RTW_INFO("%s, ielen=%d\n", __func__, len);9262#endif92639264if ((rtw_get_wps_ie(buf, len, NULL, &wps_ielen) && (wps_ielen > 0))9265#ifdef CONFIG_P2P9266|| (rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen) && (p2p_ielen > 0))9267#endif9268) {9269if (net != NULL) {9270switch (type) {9271case 0x1: /* BEACON */9272ret = rtw_cfg80211_set_beacon_wpsp2pie(net, buf, len);9273break;9274case 0x2: /* PROBE_RESP */9275ret = rtw_cfg80211_set_probe_resp_wpsp2pie(net, buf, len);9276#ifdef CONFIG_P2P9277if (ret == 0)9278adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->probe_resp_ie_update_time = rtw_get_current_time();9279#endif9280break;9281case 0x4: /* ASSOC_RESP */9282ret = rtw_cfg80211_set_assoc_resp_wpsp2pie(net, buf, len);9283break;9284}9285}9286}92879288return ret;92899290}92919292#ifdef CONFIG_80211N_HT9293static void rtw_cfg80211_init_ht_capab_ex(_adapter *padapter9294, struct ieee80211_sta_ht_cap *ht_cap, BAND_TYPE band, u8 rf_type)9295{9296struct registry_priv *pregistrypriv = &padapter->registrypriv;9297struct mlme_priv *pmlmepriv = &padapter->mlmepriv;9298struct ht_priv *phtpriv = &pmlmepriv->htpriv;9299u8 stbc_rx_enable = _FALSE;93009301rtw_ht_use_default_setting(padapter);93029303/* RX LDPC */9304if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX))9305ht_cap->cap |= IEEE80211_HT_CAP_LDPC_CODING;93069307/* TX STBC */9308if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX))9309ht_cap->cap |= IEEE80211_HT_CAP_TX_STBC;93109311/* RX STBC */9312if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) {9313/*rtw_rx_stbc 0: disable, bit(0):enable 2.4g, bit(1):enable 5g*/9314if (band == BAND_ON_2_4G)9315stbc_rx_enable = (pregistrypriv->rx_stbc & BIT(0)) ? _TRUE : _FALSE;9316if (band == BAND_ON_5G)9317stbc_rx_enable = (pregistrypriv->rx_stbc & BIT(1)) ? _TRUE : _FALSE;93189319if (stbc_rx_enable) {9320switch (rf_type) {9321case RF_1T1R:9322ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/*RX STBC One spatial stream*/9323break;93249325case RF_2T2R:9326case RF_1T2R:9327ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/* Only one spatial-stream STBC RX is supported */9328break;9329case RF_3T3R:9330case RF_3T4R:9331case RF_4T4R:9332ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/* Only one spatial-stream STBC RX is supported */9333break;9334default:9335RTW_INFO("[warning] rf_type %d is not expected\n", rf_type);9336break;9337}9338}9339}9340}93419342static void rtw_cfg80211_init_ht_capab(_adapter *padapter9343, struct ieee80211_sta_ht_cap *ht_cap, BAND_TYPE band, u8 rf_type)9344{9345struct registry_priv *regsty = &padapter->registrypriv;9346u8 rx_nss = 0;93479348if (!regsty->ht_enable || !is_supported_ht(regsty->wireless_mode))9349return;93509351ht_cap->ht_supported = 1;93529353ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |9354IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |9355IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;9356rtw_cfg80211_init_ht_capab_ex(padapter, ht_cap, band, rf_type);93579358/*9359*Maximum length of AMPDU that the STA can receive.9360*Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)9361*/9362ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;93639364/*Minimum MPDU start spacing , */9365ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;93669367ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;93689369rx_nss = GET_HAL_RX_NSS(padapter);9370switch (rx_nss) {9371case 1:9372ht_cap->mcs.rx_mask[0] = 0xFF;9373break;9374case 2:9375ht_cap->mcs.rx_mask[0] = 0xFF;9376ht_cap->mcs.rx_mask[1] = 0xFF;9377break;9378case 3:9379ht_cap->mcs.rx_mask[0] = 0xFF;9380ht_cap->mcs.rx_mask[1] = 0xFF;9381ht_cap->mcs.rx_mask[2] = 0xFF;9382break;9383case 4:9384ht_cap->mcs.rx_mask[0] = 0xFF;9385ht_cap->mcs.rx_mask[1] = 0xFF;9386ht_cap->mcs.rx_mask[2] = 0xFF;9387ht_cap->mcs.rx_mask[3] = 0xFF;9388break;9389default:9390rtw_warn_on(1);9391RTW_INFO("%s, error rf_type=%d, rx_nss=%d\n", __func__, rf_type, rx_nss);9392};93939394ht_cap->mcs.rx_highest = cpu_to_le16(9395rtw_ht_mcs_rate(hal_is_bw_support(padapter, CHANNEL_WIDTH_40)9396, hal_is_bw_support(padapter, CHANNEL_WIDTH_40) ? ht_cap->cap & IEEE80211_HT_CAP_SGI_40 : ht_cap->cap & IEEE80211_HT_CAP_SGI_209397, ht_cap->mcs.rx_mask) / 10);9398}9399#endif /* CONFIG_80211N_HT */94009401#if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))9402static void rtw_cfg80211_init_vht_capab(_adapter *padapter9403, struct ieee80211_sta_vht_cap *sta_vht_cap, BAND_TYPE band, u8 rf_type)9404{9405struct registry_priv *regsty = &padapter->registrypriv;9406u8 vht_cap_ie[2 + 12] = {0};94079408if (!REGSTY_IS_11AC_ENABLE(regsty) || !is_supported_vht(regsty->wireless_mode))9409return;94109411rtw_vht_use_default_setting(padapter);9412rtw_build_vht_cap_ie(padapter, vht_cap_ie);94139414sta_vht_cap->vht_supported = 1;94159416_rtw_memcpy(&sta_vht_cap->cap, vht_cap_ie + 2, 4);9417_rtw_memcpy(&sta_vht_cap->vht_mcs, vht_cap_ie + 2 + 4, 8);9418}9419#endif /* defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */94209421void rtw_cfg80211_init_wdev_data(_adapter *padapter)9422{9423#ifdef CONFIG_CONCURRENT_MODE9424struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);94259426ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);9427#endif9428}94299430void rtw_cfg80211_init_wiphy(_adapter *padapter)9431{9432u8 rf_type;9433struct ieee80211_supported_band *band;9434struct wireless_dev *pwdev = padapter->rtw_wdev;9435struct wiphy *wiphy = pwdev->wiphy;94369437rf_type = GET_HAL_RFPATH(padapter);9438RTW_INFO("%s:rf_type=%d\n", __func__, rf_type);94399440if (IsSupported24G(padapter->registrypriv.wireless_mode)) {9441band = wiphy->bands[NL80211_BAND_2GHZ];9442if (band) {9443#if defined(CONFIG_80211N_HT)9444rtw_cfg80211_init_ht_capab(padapter, &band->ht_cap, BAND_ON_2_4G, rf_type);9445#endif9446}9447}9448#ifdef CONFIG_IEEE80211_BAND_5GHZ9449if (is_supported_5g(padapter->registrypriv.wireless_mode)) {9450band = wiphy->bands[NL80211_BAND_5GHZ];9451if (band) {9452#if defined(CONFIG_80211N_HT)9453rtw_cfg80211_init_ht_capab(padapter, &band->ht_cap, BAND_ON_5G, rf_type);9454#endif9455#if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))9456rtw_cfg80211_init_vht_capab(padapter, &band->vht_cap, BAND_ON_5G, rf_type);9457#endif9458}9459}9460#endif94619462/* copy mac_addr to wiphy */9463_rtw_memcpy(wiphy->perm_addr, adapter_mac_addr(padapter), ETH_ALEN);94649465}94669467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))9468struct ieee80211_iface_limit rtw_limits[] = {9469{9470.max = 2,9471.types = BIT(NL80211_IFTYPE_STATION)9472#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))9473| BIT(NL80211_IFTYPE_P2P_CLIENT)9474#endif9475},9476#ifdef CONFIG_AP_MODE9477{9478.max = 1,9479.types = BIT(NL80211_IFTYPE_AP)9480#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))9481| BIT(NL80211_IFTYPE_P2P_GO)9482#endif9483},9484#endif9485#if defined(RTW_DEDICATED_P2P_DEVICE)9486{9487.max = 1,9488.types = BIT(NL80211_IFTYPE_P2P_DEVICE)9489},9490#endif9491#if defined(CONFIG_RTW_MESH)9492{9493.max = 1,9494.types = BIT(NL80211_IFTYPE_MESH_POINT)9495},9496#endif9497};94989499struct ieee80211_iface_combination rtw_combinations[] = {9500{9501.limits = rtw_limits,9502.n_limits = ARRAY_SIZE(rtw_limits),9503#if defined(RTW_DEDICATED_P2P_DEVICE)9504.max_interfaces = 3,9505#else9506.max_interfaces = 2,9507#endif9508.num_different_channels = 1,9509},9510};9511#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) */95129513static void rtw_cfg80211_preinit_wiphy(_adapter *adapter, struct wiphy *wiphy)9514{9515struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);9516struct registry_priv *regsty = dvobj_to_regsty(dvobj);95179518wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;95199520wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;9521wiphy->max_scan_ie_len = RTW_SCAN_IE_LEN_MAX;9522wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;95239524#if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))9525wiphy->max_acl_mac_addrs = NUM_ACL;9526#endif95279528#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)9529wiphy->max_remain_on_channel_duration = RTW_MAX_REMAIN_ON_CHANNEL_DURATION;9530#endif95319532wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)9533| BIT(NL80211_IFTYPE_ADHOC)9534#ifdef CONFIG_AP_MODE9535| BIT(NL80211_IFTYPE_AP)9536#ifdef CONFIG_WIFI_MONITOR9537| BIT(NL80211_IFTYPE_MONITOR)9538#endif9539#endif9540#if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))9541| BIT(NL80211_IFTYPE_P2P_CLIENT)9542| BIT(NL80211_IFTYPE_P2P_GO)9543#if defined(RTW_DEDICATED_P2P_DEVICE)9544| BIT(NL80211_IFTYPE_P2P_DEVICE)9545#endif9546#endif9547#ifdef CONFIG_RTW_MESH9548| BIT(NL80211_IFTYPE_MESH_POINT) /* 2.6.26 */9549#endif9550;95519552#if defined(CONFIG_ANDROID) && !defined(RTW_SINGLE_WIPHY)9553if (is_primary_adapter(adapter)) {9554wiphy->interface_modes &= ~(BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT));9555RTW_INFO("%s primary- don't set p2p capability\n", __func__);9556}9557#endif95589559#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)9560#ifdef CONFIG_AP_MODE9561wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;9562#endif /* CONFIG_AP_MODE */9563#endif95649565#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))9566#ifdef CONFIG_WIFI_MONITOR9567wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);9568#endif9569#endif95709571#if defined(RTW_SINGLE_WIPHY) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))9572wiphy->iface_combinations = rtw_combinations;9573wiphy->n_iface_combinations = ARRAY_SIZE(rtw_combinations);9574#endif95759576wiphy->cipher_suites = rtw_cipher_suites;9577wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);95789579if (IsSupported24G(adapter->registrypriv.wireless_mode))9580wiphy->bands[NL80211_BAND_2GHZ] = rtw_spt_band_alloc(BAND_ON_2_4G);95819582#ifdef CONFIG_IEEE80211_BAND_5GHZ9583if (is_supported_5g(adapter->registrypriv.wireless_mode))9584wiphy->bands[NL80211_BAND_5GHZ] = rtw_spt_band_alloc(BAND_ON_5G);9585#endif95869587#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))9588wiphy->flags |= WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;9589#endif95909591#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))9592wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;9593wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;9594/* remove WIPHY_FLAG_OFFCHAN_TX, because we not support this feature */9595/* wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME; */9596#endif95979598#if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) && \9599LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))9600wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;9601#ifdef CONFIG_PNO_SUPPORT9602wiphy->max_sched_scan_ssids = MAX_PNO_LIST_COUNT;9603#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)9604wiphy->max_match_sets = MAX_PNO_LIST_COUNT;9605#endif9606#endif9607#endif96089609#if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))9610#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))9611wiphy->wowlan = wowlan_stub;9612#else9613wiphy->wowlan = &wowlan_stub;9614#endif9615#endif96169617#if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))9618wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;9619#ifndef CONFIG_TDLS_DRIVER_SETUP9620wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; /* Driver handles key exchange */9621wiphy->flags |= NL80211_ATTR_HT_CAPABILITY;9622#endif /* CONFIG_TDLS_DRIVER_SETUP */9623#endif /* CONFIG_TDLS */96249625if (regsty->power_mgnt != PS_MODE_ACTIVE)9626wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;9627else9628wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;96299630#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))9631/* wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */9632#endif96339634#ifdef CONFIG_RTW_MESH9635wiphy->flags |= 09636#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))9637| WIPHY_FLAG_IBSS_RSN9638#endif9639#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))9640| WIPHY_FLAG_MESH_AUTH9641#endif9642;96439644#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))9645wiphy->features |= 09646#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))9647| NL80211_FEATURE_USERSPACE_MPM9648#endif9649;9650#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) */9651#endif /* CONFIG_RTW_MESH */96529653#if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE)9654wiphy->features |= NL80211_FEATURE_SAE;9655#endif9656}96579658#ifdef CONFIG_RFKILL_POLL9659void rtw_cfg80211_init_rfkill(struct wiphy *wiphy)9660{9661wiphy_rfkill_set_hw_state(wiphy, 0);9662wiphy_rfkill_start_polling(wiphy);9663}96649665void rtw_cfg80211_deinit_rfkill(struct wiphy *wiphy)9666{9667wiphy_rfkill_stop_polling(wiphy);9668}96699670static void cfg80211_rtw_rfkill_poll(struct wiphy *wiphy)9671{9672_adapter *padapter = NULL;9673bool blocked = _FALSE;9674u8 valid = 0;96759676padapter = wiphy_to_adapter(wiphy);96779678if (adapter_to_dvobj(padapter)->processing_dev_remove == _TRUE) {9679/*RTW_INFO("cfg80211_rtw_rfkill_poll: device is removed!\n");*/9680return;9681}96829683blocked = rtw_hal_rfkill_poll(padapter, &valid);9684/*RTW_INFO("cfg80211_rtw_rfkill_poll: valid=%d, blocked=%d\n",9685valid, blocked);*/96869687if (valid)9688wiphy_rfkill_set_hw_state(wiphy, blocked);9689}9690#endif96919692#if defined(CONFIG_RTW_HOSTAPD_ACS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))96939694#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))9695#define SURVEY_INFO_TIME SURVEY_INFO_CHANNEL_TIME9696#define SURVEY_INFO_TIME_BUSY SURVEY_INFO_CHANNEL_TIME_BUSY9697#define SURVEY_INFO_TIME_EXT_BUSY SURVEY_INFO_CHANNEL_TIME_EXT_BUSY9698#define SURVEY_INFO_TIME_RX SURVEY_INFO_CHANNEL_TIME_RX9699#define SURVEY_INFO_TIME_TX SURVEY_INFO_CHANNEL_TIME_TX9700#endif97019702#ifdef CONFIG_FIND_BEST_CHANNEL9703static void rtw_cfg80211_set_survey_info_with_find_best_channel(struct wiphy *wiphy9704, struct net_device *netdev, int idx, struct survey_info *info)9705{9706_adapter *adapter = (_adapter *)rtw_netdev_priv(netdev);9707struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);9708RT_CHANNEL_INFO *ch_set = rfctl->channel_set;9709u8 ch_num = rfctl->max_chan_nums;9710u32 total_rx_cnt = 0;9711int i;97129713s8 noise = -50; /*channel noise in dBm. This and all following fields are optional */9714u64 time = 100; /*amount of time in ms the radio was turn on (on the channel)*/9715u64 time_busy = 0; /*amount of time the primary channel was sensed busy*/97169717info->filled = SURVEY_INFO_NOISE_DBM9718#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))9719| SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY9720#endif9721;97229723for (i = 0; i < ch_num; i++)9724total_rx_cnt += ch_set[i].rx_count;97259726time_busy = ch_set[idx].rx_count * time / total_rx_cnt;9727noise += ch_set[idx].rx_count * 50 / total_rx_cnt;97289729#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))9730#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))9731info->channel_time = time;9732info->channel_time_busy = time_busy;9733#else9734info->time = time;9735info->time_busy = time_busy;9736#endif9737#endif9738info->noise = noise;97399740/* reset if final channel is got */9741if (idx == ch_num - 1) {9742for (i = 0; i < ch_num; i++)9743ch_set[i].rx_count = 0;9744}9745}9746#endif /* CONFIG_FIND_BEST_CHANNEL */97479748#if defined(CONFIG_RTW_ACS) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)9749static void rtw_cfg80211_set_survey_info_with_clm(PADAPTER padapter, int idx, struct survey_info *pinfo)9750{9751s8 noise = -50; /*channel noise in dBm. This and all following fields are optional */9752u64 time = SURVEY_TO; /*amount of time in ms the radio was turn on (on the channel)*/9753u64 time_busy = 0; /*amount of time the primary channel was sensed busy*/9754u8 chan = (u8)idx;97559756if ((idx < 0) || (pinfo == NULL))9757return;97589759pinfo->filled = SURVEY_INFO_NOISE_DBM9760#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))9761| SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY9762#endif9763;97649765time_busy = rtw_acs_get_clm_ratio_by_ch_idx(padapter, chan);9766noise = rtw_noise_query_by_chan_idx(padapter, chan);9767/* RTW_INFO("%s: ch-idx:%d time=%llu(ms), time_busy=%llu(ms), noise=%d(dbm)\n", __func__, idx, time, time_busy, noise); */97689769#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))9770#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))9771pinfo->channel_time = time;9772pinfo->channel_time_busy = time_busy;9773#else9774pinfo->time = time;9775pinfo->time_busy = time_busy;9776#endif9777#endif9778pinfo->noise = noise;9779}9780#endif97819782int rtw_hostapd_acs_dump_survey(struct wiphy *wiphy, struct net_device *netdev, int idx, struct survey_info *info)9783{9784PADAPTER padapter = (_adapter *)rtw_netdev_priv(netdev);9785struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);9786RT_CHANNEL_INFO *pch_set = rfctl->channel_set;9787u8 max_chan_nums = rfctl->max_chan_nums;9788u32 freq = 0;9789u8 ret = 0;9790u16 channel = 0;97919792if (!netdev || !info) {9793RTW_INFO("%s: invial parameters.\n", __func__);9794return -EINVAL;9795}97969797_rtw_memset(info, 0, sizeof(struct survey_info));9798if (padapter->bup == _FALSE) {9799RTW_INFO("%s: net device is down.\n", __func__);9800return -EIO;9801}98029803if (idx >= max_chan_nums)9804return -ENOENT;98059806channel = pch_set[idx].ChannelNum;9807freq = rtw_ch2freq(channel);9808info->channel = ieee80211_get_channel(wiphy, freq);9809/* RTW_INFO("%s: channel %d, freq %d\n", __func__, channel, freq); */98109811if (!info->channel)9812return -EINVAL;98139814if (info->channel->flags == IEEE80211_CHAN_DISABLED)9815return ret;98169817#ifdef CONFIG_FIND_BEST_CHANNEL9818rtw_cfg80211_set_survey_info_with_find_best_channel(wiphy, netdev, idx, info);9819#elif defined(CONFIG_RTW_ACS) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)9820rtw_cfg80211_set_survey_info_with_clm(padapter, idx, info);9821#else9822RTW_ERR("%s: unknown acs operation!\n", __func__);9823#endif98249825return ret;9826}9827#endif /* defined(CONFIG_RTW_HOSTAPD_ACS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) */98289829#if (KERNEL_VERSION(4, 17, 0) <= LINUX_VERSION_CODE)9830int cfg80211_rtw_external_auth(struct wiphy *wiphy, struct net_device *dev,9831struct cfg80211_external_auth_params *params)9832{9833PADAPTER padapter = (_adapter *)rtw_netdev_priv(dev);98349835RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(dev));98369837rtw_cfg80211_external_auth_status(wiphy, dev,9838(struct rtw_external_auth_params *)params);98399840return 0;9841}9842#endif98439844void rtw_cfg80211_external_auth_status(struct wiphy *wiphy, struct net_device *dev,9845struct rtw_external_auth_params *params)9846{9847PADAPTER padapter = (_adapter *)rtw_netdev_priv(dev);9848struct security_priv *psecuritypriv = &padapter->securitypriv;9849struct sta_priv *pstapriv = &padapter->stapriv;9850struct sta_info *psta = NULL;9851u8 *buf = NULL;9852u32 len = 0;9853_irqL irqL;98549855RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(dev));98569857RTW_INFO("SAE: action: %u, status: %u\n", params->action, params->status);9858if (params->status == WLAN_STATUS_SUCCESS) {9859RTW_INFO("bssid: "MAC_FMT"\n", MAC_ARG(params->bssid));9860RTW_INFO("SSID: [%s]\n",9861((params->ssid.ssid_len == 0) ? "" : (char *)params->ssid.ssid));9862RTW_INFO("suite: 0x%08x\n", params->key_mgmt_suite);9863}98649865psta = rtw_get_stainfo(pstapriv, params->bssid);9866if (psta && (params->status == WLAN_STATUS_SUCCESS)) {9867/* AP mode */9868RTW_INFO("station match\n");98699870psta->state &= ~WIFI_FW_AUTH_NULL;9871psta->state |= WIFI_FW_AUTH_SUCCESS;9872psta->expire_to = padapter->stapriv.assoc_to;98739874/* ToDo: Kernel v5.1 pmkid is pointer */9875/* RTW_INFO_DUMP("PMKID:", params->pmkid, PMKID_LEN); */9876_rtw_set_pmksa(dev, params->bssid, params->pmkid);98779878_enter_critical_bh(&psta->lock, &irqL);9879if ((psta->auth_len != 0) && (psta->pauth_frame != NULL)) {9880buf = rtw_zmalloc(psta->auth_len);9881if (buf) {9882_rtw_memcpy(buf, psta->pauth_frame, psta->auth_len);9883len = psta->auth_len;9884}98859886rtw_mfree(psta->pauth_frame, psta->auth_len);9887psta->pauth_frame = NULL;9888psta->auth_len = 0;9889}9890_exit_critical_bh(&psta->lock, &irqL);98919892if (buf) {9893struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);9894/* send the SAE auth Confirm */98959896rtw_ps_deny(padapter, PS_DENY_MGNT_TX);9897if (_SUCCESS == rtw_pwr_wakeup(padapter)) {9898rtw_mi_set_scan_deny(padapter, 1000);9899rtw_mi_scan_abort(padapter, _TRUE);99009901RTW_INFO("SAE: Tx auth Confirm\n");9902rtw_mgnt_tx_cmd(padapter, pmlmeext->cur_channel, 1, buf, len, 0, RTW_CMDF_DIRECTLY);99039904}9905rtw_ps_deny_cancel(padapter, PS_DENY_MGNT_TX);99069907rtw_mfree(buf, len);9908buf = NULL;9909len = 0;9910}9911} else {9912/* STA mode */9913psecuritypriv->extauth_status = params->status;9914}9915}99169917static struct cfg80211_ops rtw_cfg80211_ops = {9918.change_virtual_intf = cfg80211_rtw_change_iface,9919.add_key = cfg80211_rtw_add_key,9920.get_key = cfg80211_rtw_get_key,9921.del_key = cfg80211_rtw_del_key,9922.set_default_key = cfg80211_rtw_set_default_key,9923#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))9924.set_default_mgmt_key = cfg80211_rtw_set_default_mgmt_key,9925#endif9926#if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))9927.set_rekey_data = cfg80211_rtw_set_rekey_data,9928#endif /*CONFIG_GTK_OL*/9929.get_station = cfg80211_rtw_get_station,9930.scan = cfg80211_rtw_scan,9931.set_wiphy_params = cfg80211_rtw_set_wiphy_params,9932.connect = cfg80211_rtw_connect,9933.disconnect = cfg80211_rtw_disconnect,9934.join_ibss = cfg80211_rtw_join_ibss,9935.leave_ibss = cfg80211_rtw_leave_ibss,9936.set_tx_power = cfg80211_rtw_set_txpower,9937.get_tx_power = cfg80211_rtw_get_txpower,9938.set_power_mgmt = cfg80211_rtw_set_power_mgmt,9939.set_pmksa = cfg80211_rtw_set_pmksa,9940.del_pmksa = cfg80211_rtw_del_pmksa,9941.flush_pmksa = cfg80211_rtw_flush_pmksa,99429943#ifdef CONFIG_AP_MODE9944.add_virtual_intf = cfg80211_rtw_add_virtual_intf,9945.del_virtual_intf = cfg80211_rtw_del_virtual_intf,99469947#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(COMPAT_KERNEL_RELEASE)9948.add_beacon = cfg80211_rtw_add_beacon,9949.set_beacon = cfg80211_rtw_set_beacon,9950.del_beacon = cfg80211_rtw_del_beacon,9951#else9952.start_ap = cfg80211_rtw_start_ap,9953.change_beacon = cfg80211_rtw_change_beacon,9954.stop_ap = cfg80211_rtw_stop_ap,9955#endif99569957#if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))9958.set_mac_acl = cfg80211_rtw_set_mac_acl,9959#endif99609961.add_station = cfg80211_rtw_add_station,9962.del_station = cfg80211_rtw_del_station,9963.change_station = cfg80211_rtw_change_station,9964.dump_station = cfg80211_rtw_dump_station,9965.change_bss = cfg80211_rtw_change_bss,9966#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))9967.set_txq_params = cfg80211_rtw_set_txq_params,9968#endif9969#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))9970.set_channel = cfg80211_rtw_set_channel,9971#endif9972/* .auth = cfg80211_rtw_auth, */9973/* .assoc = cfg80211_rtw_assoc, */9974#endif /* CONFIG_AP_MODE */99759976#if defined(CONFIG_RTW_MESH) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))9977.get_mesh_config = cfg80211_rtw_get_mesh_config,9978.update_mesh_config = cfg80211_rtw_update_mesh_config,9979.join_mesh = cfg80211_rtw_join_mesh,9980.leave_mesh = cfg80211_rtw_leave_mesh,9981.add_mpath = cfg80211_rtw_add_mpath,9982.del_mpath = cfg80211_rtw_del_mpath,9983.change_mpath = cfg80211_rtw_change_mpath,9984.get_mpath = cfg80211_rtw_get_mpath,9985.dump_mpath = cfg80211_rtw_dump_mpath,9986#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))9987.get_mpp = cfg80211_rtw_get_mpp,9988.dump_mpp = cfg80211_rtw_dump_mpp,9989#endif9990#endif99919992#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))9993.set_monitor_channel = cfg80211_rtw_set_monitor_channel,9994#endif99959996#ifdef CONFIG_P2P9997.remain_on_channel = cfg80211_rtw_remain_on_channel,9998.cancel_remain_on_channel = cfg80211_rtw_cancel_remain_on_channel,9999#if defined(RTW_DEDICATED_P2P_DEVICE)10000.start_p2p_device = cfg80211_rtw_start_p2p_device,10001.stop_p2p_device = cfg80211_rtw_stop_p2p_device,10002#endif10003#endif /* CONFIG_P2P */1000410005#ifdef CONFIG_RTW_80211R10006.update_ft_ies = cfg80211_rtw_update_ft_ies,10007#endif1000810009#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)10010.mgmt_tx = cfg80211_rtw_mgmt_tx,10011#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))10012.update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_register,10013#else10014.mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,10015#endif10016#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))10017.action = cfg80211_rtw_mgmt_tx,10018#endif1001910020#if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))10021.tdls_mgmt = cfg80211_rtw_tdls_mgmt,10022.tdls_oper = cfg80211_rtw_tdls_oper,10023#endif /* CONFIG_TDLS */1002410025#if defined(CONFIG_PNO_SUPPORT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))10026.sched_scan_start = cfg80211_rtw_sched_scan_start,10027.sched_scan_stop = cfg80211_rtw_sched_scan_stop,10028.suspend = cfg80211_rtw_suspend,10029.resume = cfg80211_rtw_resume,10030#endif /* CONFIG_PNO_SUPPORT */10031#ifdef CONFIG_RFKILL_POLL10032.rfkill_poll = cfg80211_rtw_rfkill_poll,10033#endif10034#if defined(CONFIG_RTW_HOSTAPD_ACS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))10035.dump_survey = rtw_hostapd_acs_dump_survey,10036#endif10037#if (KERNEL_VERSION(4, 17, 0) <= LINUX_VERSION_CODE)10038.external_auth = cfg80211_rtw_external_auth,10039#endif10040};1004110042struct wiphy *rtw_wiphy_alloc(_adapter *padapter, struct device *dev)10043{10044struct wiphy *wiphy;10045struct rtw_wiphy_data *wiphy_data;1004610047/* wiphy */10048wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wiphy_data));10049if (!wiphy) {10050RTW_INFO("Couldn't allocate wiphy device\n");10051goto exit;10052}10053set_wiphy_dev(wiphy, dev);1005410055/* wiphy_data */10056wiphy_data = rtw_wiphy_priv(wiphy);10057wiphy_data->dvobj = adapter_to_dvobj(padapter);10058#ifndef RTW_SINGLE_WIPHY10059wiphy_data->adapter = padapter;10060#endif1006110062rtw_cfg80211_preinit_wiphy(padapter, wiphy);1006310064RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));1006510066exit:10067return wiphy;10068}1006910070void rtw_wiphy_free(struct wiphy *wiphy)10071{10072if (!wiphy)10073return;1007410075RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));1007610077if (wiphy->bands[NL80211_BAND_2GHZ]) {10078rtw_spt_band_free(wiphy->bands[NL80211_BAND_2GHZ]);10079wiphy->bands[NL80211_BAND_2GHZ] = NULL;10080}10081if (wiphy->bands[NL80211_BAND_5GHZ]) {10082rtw_spt_band_free(wiphy->bands[NL80211_BAND_5GHZ]);10083wiphy->bands[NL80211_BAND_5GHZ] = NULL;10084}1008510086wiphy_free(wiphy);10087}1008810089int rtw_wiphy_register(struct wiphy *wiphy)10090{10091RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));1009210093#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)10094rtw_cfgvendor_attach(wiphy);10095#endif1009610097rtw_regd_init(wiphy);1009810099return wiphy_register(wiphy);10100}1010110102void rtw_wiphy_unregister(struct wiphy *wiphy)10103{10104RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));1010510106#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)10107rtw_cfgvendor_detach(wiphy);10108#endif1010910110#if defined(RTW_DEDICATED_P2P_DEVICE)10111rtw_pd_iface_free(wiphy);10112#endif1011310114return wiphy_unregister(wiphy);10115}1011610117int rtw_wdev_alloc(_adapter *padapter, struct wiphy *wiphy)10118{10119int ret = 0;10120struct net_device *pnetdev = padapter->pnetdev;10121struct wireless_dev *wdev;10122struct rtw_wdev_priv *pwdev_priv;1012310124RTW_INFO("%s(padapter=%p)\n", __func__, padapter);1012510126/* wdev */10127wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));10128if (!wdev) {10129RTW_INFO("Couldn't allocate wireless device\n");10130ret = -ENOMEM;10131goto exit;10132}10133wdev->wiphy = wiphy;10134wdev->netdev = pnetdev;10135wdev->iftype = NL80211_IFTYPE_STATION;10136padapter->rtw_wdev = wdev;10137pnetdev->ieee80211_ptr = wdev;1013810139/* init pwdev_priv */10140pwdev_priv = adapter_wdev_data(padapter);10141pwdev_priv->rtw_wdev = wdev;10142pwdev_priv->pmon_ndev = NULL;10143pwdev_priv->ifname_mon[0] = '\0';10144pwdev_priv->padapter = padapter;10145pwdev_priv->scan_request = NULL;10146_rtw_spinlock_init(&pwdev_priv->scan_req_lock);10147pwdev_priv->connect_req = NULL;10148_rtw_spinlock_init(&pwdev_priv->connect_req_lock);1014910150pwdev_priv->p2p_enabled = _FALSE;10151pwdev_priv->probe_resp_ie_update_time = rtw_get_current_time();10152pwdev_priv->provdisc_req_issued = _FALSE;10153rtw_wdev_invit_info_init(&pwdev_priv->invit_info);10154rtw_wdev_nego_info_init(&pwdev_priv->nego_info);1015510156pwdev_priv->bandroid_scan = _FALSE;1015710158if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)10159pwdev_priv->power_mgmt = _TRUE;10160else10161pwdev_priv->power_mgmt = _FALSE;1016210163_rtw_mutex_init(&pwdev_priv->roch_mutex);1016410165#ifdef CONFIG_CONCURRENT_MODE10166ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);10167#endif1016810169#ifdef CONFIG_RTW_CFGVEDNOR_RSSIMONITOR10170pwdev_priv->rssi_monitor_enable = 0;10171pwdev_priv->rssi_monitor_max = 0;10172pwdev_priv->rssi_monitor_min = 0;10173#endif101741017510176exit:10177return ret;10178}1017910180void rtw_wdev_free(struct wireless_dev *wdev)10181{10182if (!wdev)10183return;1018410185RTW_INFO("%s(wdev=%p)\n", __func__, wdev);1018610187if (wdev_to_ndev(wdev)) {10188_adapter *adapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));10189struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);10190_irqL irqL;1019110192_rtw_spinlock_free(&wdev_priv->scan_req_lock);1019310194_enter_critical_bh(&wdev_priv->connect_req_lock, &irqL);10195rtw_wdev_free_connect_req(wdev_priv);10196_exit_critical_bh(&wdev_priv->connect_req_lock, &irqL);10197_rtw_spinlock_free(&wdev_priv->connect_req_lock);1019810199_rtw_mutex_free(&wdev_priv->roch_mutex);10200}1020110202rtw_mfree((u8 *)wdev, sizeof(struct wireless_dev));10203}1020410205void rtw_wdev_unregister(struct wireless_dev *wdev)10206{10207struct net_device *ndev;10208_adapter *adapter;10209struct rtw_wdev_priv *pwdev_priv;1021010211if (!wdev)10212return;1021310214RTW_INFO("%s(wdev=%p)\n", __func__, wdev);1021510216ndev = wdev_to_ndev(wdev);10217if (!ndev)10218return;1021910220adapter = (_adapter *)rtw_netdev_priv(ndev);10221pwdev_priv = adapter_wdev_data(adapter);1022210223rtw_cfg80211_indicate_scan_done(adapter, _TRUE);1022410225#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) || defined(COMPAT_KERNEL_RELEASE)10226#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2))10227if (wdev->links[0].client.current_bss) {10228#else10229if (wdev->current_bss) {10230#endif10231RTW_INFO(FUNC_ADPT_FMT" clear current_bss by cfg80211_disconnected\n", FUNC_ADPT_ARG(adapter));10232rtw_cfg80211_indicate_disconnect(adapter, 0, 1);10233}10234#endif1023510236if (pwdev_priv->pmon_ndev) {10237RTW_INFO("%s, unregister monitor interface\n", __func__);10238unregister_netdev(pwdev_priv->pmon_ndev);10239}10240}1024110242int rtw_cfg80211_ndev_res_alloc(_adapter *adapter)10243{10244int ret = _FAIL;1024510246#if !defined(RTW_SINGLE_WIPHY)10247struct wiphy *wiphy;10248struct device *dev = dvobj_to_dev(adapter_to_dvobj(adapter));1024910250wiphy = rtw_wiphy_alloc(adapter, dev);10251if (wiphy == NULL)10252goto exit;1025310254adapter->wiphy = wiphy;10255#endif1025610257if (rtw_wdev_alloc(adapter, adapter_to_wiphy(adapter)) == 0)10258ret = _SUCCESS;1025910260#if !defined(RTW_SINGLE_WIPHY)10261if (ret != _SUCCESS) {10262rtw_wiphy_free(wiphy);10263adapter->wiphy = NULL;10264}10265#endif1026610267exit:10268return ret;10269}1027010271void rtw_cfg80211_ndev_res_free(_adapter *adapter)10272{10273rtw_wdev_free(adapter->rtw_wdev);10274adapter->rtw_wdev = NULL;10275#if !defined(RTW_SINGLE_WIPHY)10276rtw_wiphy_free(adapter_to_wiphy(adapter));10277adapter->wiphy = NULL;10278#endif10279}1028010281int rtw_cfg80211_ndev_res_register(_adapter *adapter)10282{10283int ret = _FAIL;1028410285#if !defined(RTW_SINGLE_WIPHY)10286if (rtw_wiphy_register(adapter_to_wiphy(adapter)) < 0) {10287RTW_INFO("%s rtw_wiphy_register fail for if%d\n", __func__, (adapter->iface_id + 1));10288goto exit;10289}1029010291#ifdef CONFIG_RFKILL_POLL10292rtw_cfg80211_init_rfkill(adapter_to_wiphy(adapter));10293#endif10294#endif1029510296ret = _SUCCESS;1029710298exit:10299return ret;10300}1030110302void rtw_cfg80211_ndev_res_unregister(_adapter *adapter)10303{10304rtw_wdev_unregister(adapter->rtw_wdev);10305}1030610307int rtw_cfg80211_dev_res_alloc(struct dvobj_priv *dvobj)10308{10309int ret = _FAIL;1031010311#if defined(RTW_SINGLE_WIPHY)10312struct wiphy *wiphy;10313struct device *dev = dvobj_to_dev(dvobj);1031410315wiphy = rtw_wiphy_alloc(dvobj_get_primary_adapter(dvobj), dev);10316if (wiphy == NULL)10317return ret;1031810319dvobj->wiphy = wiphy;10320#endif1032110322ret = _SUCCESS;10323return ret;10324}1032510326void rtw_cfg80211_dev_res_free(struct dvobj_priv *dvobj)10327{10328#if defined(RTW_SINGLE_WIPHY)10329rtw_wiphy_free(dvobj_to_wiphy(dvobj));10330dvobj->wiphy = NULL;10331#endif10332}1033310334int rtw_cfg80211_dev_res_register(struct dvobj_priv *dvobj)10335{10336int ret = _FAIL;1033710338#if defined(RTW_SINGLE_WIPHY)10339if (rtw_wiphy_register(dvobj_to_wiphy(dvobj)) != 0)10340return ret;1034110342#ifdef CONFIG_RFKILL_POLL10343rtw_cfg80211_init_rfkill(dvobj_to_wiphy(dvobj));10344#endif10345#endif1034610347ret = _SUCCESS;1034810349return ret;10350}1035110352void rtw_cfg80211_dev_res_unregister(struct dvobj_priv *dvobj)10353{10354#if defined(RTW_SINGLE_WIPHY)10355#ifdef CONFIG_RFKILL_POLL10356rtw_cfg80211_deinit_rfkill(dvobj_to_wiphy(dvobj));10357#endif10358rtw_wiphy_unregister(dvobj_to_wiphy(dvobj));10359#endif10360}1036110362#endif /* CONFIG_IOCTL_CFG80211 */103631036410365