158391efdSNathan Chancellor // SPDX-License-Identifier: GPL-2.0 2554c0a3aSHans de Goede /****************************************************************************** 3554c0a3aSHans de Goede * 4554c0a3aSHans de Goede * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 5554c0a3aSHans de Goede * 6554c0a3aSHans de Goede ******************************************************************************/ 7554c0a3aSHans de Goede #define _RTW_MLME_EXT_C_ 8554c0a3aSHans de Goede 9554c0a3aSHans de Goede #include <drv_types.h> 10554c0a3aSHans de Goede #include <rtw_debug.h> 11554c0a3aSHans de Goede #include <rtw_wifi_regd.h> 12d312a47fSNishka Dasgupta #include <hal_btcoex.h> 1360db8d10SJérémy Lefaure #include <linux/kernel.h> 14d48603afSRoss Schmidt #include <asm/unaligned.h> 15554c0a3aSHans de Goede 16554c0a3aSHans de Goede static struct mlme_handler mlme_sta_tbl[] = { 17554c0a3aSHans de Goede {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq}, 18554c0a3aSHans de Goede {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp}, 19554c0a3aSHans de Goede {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq}, 20554c0a3aSHans de Goede {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp}, 21554c0a3aSHans de Goede {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, 22554c0a3aSHans de Goede {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, 23554c0a3aSHans de Goede 24554c0a3aSHans de Goede /*---------------------------------------------------------- 25554c0a3aSHans de Goede below 2 are reserved 26554c0a3aSHans de Goede -----------------------------------------------------------*/ 27554c0a3aSHans de Goede {0, "DoReserved", &DoReserved}, 28554c0a3aSHans de Goede {0, "DoReserved", &DoReserved}, 29554c0a3aSHans de Goede {WIFI_BEACON, "OnBeacon", &OnBeacon}, 30554c0a3aSHans de Goede {WIFI_ATIM, "OnATIM", &OnAtim}, 31554c0a3aSHans de Goede {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc}, 32554c0a3aSHans de Goede {WIFI_AUTH, "OnAuth", &OnAuthClient}, 33554c0a3aSHans de Goede {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth}, 34554c0a3aSHans de Goede {WIFI_ACTION, "OnAction", &OnAction}, 35554c0a3aSHans de Goede {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction}, 36554c0a3aSHans de Goede }; 37554c0a3aSHans de Goede 38554c0a3aSHans de Goede static struct action_handler OnAction_tbl[] = { 39554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct}, 40554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved}, 41554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved}, 42554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back}, 43554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public}, 44554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved}, 45554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved}, 46554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht}, 47554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query}, 48554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved}, 49554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved}, 50554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved}, 51554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &DoReserved}, 52554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved}, 53554c0a3aSHans de Goede }; 54554c0a3aSHans de Goede 55554c0a3aSHans de Goede static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; 56554c0a3aSHans de Goede 57554c0a3aSHans de Goede /************************************************** 58554c0a3aSHans de Goede OUI definitions for the vendor specific IE 59554c0a3aSHans de Goede ***************************************************/ 60554c0a3aSHans de Goede unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; 61554c0a3aSHans de Goede unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02}; 62554c0a3aSHans de Goede unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; 63554c0a3aSHans de Goede unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09}; 64554c0a3aSHans de Goede unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A}; 65554c0a3aSHans de Goede 66554c0a3aSHans de Goede unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; 67554c0a3aSHans de Goede unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; 68554c0a3aSHans de Goede 69554c0a3aSHans de Goede static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20}; 70554c0a3aSHans de Goede 71554c0a3aSHans de Goede /******************************************************** 72554c0a3aSHans de Goede ChannelPlan definitions 73554c0a3aSHans de Goede *********************************************************/ 74554c0a3aSHans de Goede static RT_CHANNEL_PLAN_2G RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { 75554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */ 76554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */ 77554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */ 78554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */ 79554c0a3aSHans de Goede {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */ 80554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x05, RT_CHANNEL_DOMAIN_2G_GLOBAL , Passive scan CH 12, 13, 14 */ 81554c0a3aSHans de Goede {{}, 0}, /* 0x06, RT_CHANNEL_DOMAIN_2G_NULL */ 82554c0a3aSHans de Goede }; 83554c0a3aSHans de Goede 84554c0a3aSHans de Goede static RT_CHANNEL_PLAN_5G RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = { 85554c0a3aSHans de Goede {{}, 0}, /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */ 86554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */ 87554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */ 88554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22}, /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */ 89554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */ 90554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */ 91554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */ 92554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */ 93554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */ 94554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */ 95554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20}, /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */ 96554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20}, /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */ 97554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */ 98554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */ 99554c0a3aSHans de Goede {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */ 100554c0a3aSHans de Goede {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15}, /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */ 101554c0a3aSHans de Goede {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */ 102554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x11, RT_CHANNEL_DOMAIN_5G_NCC3 */ 103554c0a3aSHans de Goede {{36, 40, 44, 48}, 4}, /* 0x12, RT_CHANNEL_DOMAIN_5G_ETSI4 */ 104554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20}, /* 0x13, RT_CHANNEL_DOMAIN_5G_ETSI5 */ 105554c0a3aSHans de Goede {{149, 153, 157, 161}, 4}, /* 0x14, RT_CHANNEL_DOMAIN_5G_FCC8 */ 106554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x15, RT_CHANNEL_DOMAIN_5G_ETSI6 */ 107554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x16, RT_CHANNEL_DOMAIN_5G_ETSI7 */ 108554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x17, RT_CHANNEL_DOMAIN_5G_ETSI8 */ 109554c0a3aSHans de Goede {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x18, RT_CHANNEL_DOMAIN_5G_ETSI9 */ 110554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x19, RT_CHANNEL_DOMAIN_5G_ETSI10 */ 111554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165}, 16}, /* 0x1A, RT_CHANNEL_DOMAIN_5G_ETSI11 */ 112554c0a3aSHans de Goede {{52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17}, /* 0x1B, RT_CHANNEL_DOMAIN_5G_NCC4 */ 113554c0a3aSHans de Goede {{149, 153, 157, 161}, 4}, /* 0x1C, RT_CHANNEL_DOMAIN_5G_ETSI12 */ 114554c0a3aSHans de Goede {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17}, /* 0x1D, RT_CHANNEL_DOMAIN_5G_FCC9 */ 115554c0a3aSHans de Goede {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140}, 12}, /* 0x1E, RT_CHANNEL_DOMAIN_5G_ETSI13 */ 116554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161}, 20}, /* 0x1F, RT_CHANNEL_DOMAIN_5G_FCC10 */ 117554c0a3aSHans de Goede 118554c0a3aSHans de Goede /* Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */ 119554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21}, /* 0x20, RT_CHANNEL_DOMAIN_5G_FCC */ 120554c0a3aSHans de Goede {{36, 40, 44, 48}, 4}, /* 0x21, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */ 121554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, /* 0x22, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */ 122554c0a3aSHans de Goede }; 123554c0a3aSHans de Goede 124554c0a3aSHans de Goede static RT_CHANNEL_PLAN_MAP RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { 125554c0a3aSHans de Goede /* 0x00 ~ 0x1F , Old Define ===== */ 126554c0a3aSHans de Goede {0x02, 0x20}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ 127554c0a3aSHans de Goede {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ 128554c0a3aSHans de Goede {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ 129554c0a3aSHans de Goede {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ 130554c0a3aSHans de Goede {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ 131554c0a3aSHans de Goede {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ 132554c0a3aSHans de Goede {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ 133554c0a3aSHans de Goede {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ 134554c0a3aSHans de Goede {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ 135554c0a3aSHans de Goede {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ 136554c0a3aSHans de Goede {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ 137554c0a3aSHans de Goede {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ 138554c0a3aSHans de Goede {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ 139554c0a3aSHans de Goede {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ 140554c0a3aSHans de Goede {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ 141554c0a3aSHans de Goede {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ 142554c0a3aSHans de Goede {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ 143554c0a3aSHans de Goede {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ 144554c0a3aSHans de Goede {0x01, 0x21}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ 145554c0a3aSHans de Goede {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ 146554c0a3aSHans de Goede {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ 147554c0a3aSHans de Goede {0x00, 0x21}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ 148554c0a3aSHans de Goede {0x00, 0x22}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ 149554c0a3aSHans de Goede {0x03, 0x21}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ 150554c0a3aSHans de Goede {0x06, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ 151554c0a3aSHans de Goede {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ 152554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1A, */ 153554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1B, */ 154554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1C, */ 155554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1D, */ 156554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1E, */ 157554c0a3aSHans de Goede {0x06, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ 158554c0a3aSHans de Goede /* 0x20 ~ 0x7F , New Define ===== */ 159554c0a3aSHans de Goede {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ 160554c0a3aSHans de Goede {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ 161554c0a3aSHans de Goede {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ 162554c0a3aSHans de Goede {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ 163554c0a3aSHans de Goede {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ 164554c0a3aSHans de Goede {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ 165554c0a3aSHans de Goede {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ 166554c0a3aSHans de Goede {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ 167554c0a3aSHans de Goede {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ 168554c0a3aSHans de Goede {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ 169554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2A, */ 170554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2B, */ 171554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2C, */ 172554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2D, */ 173554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2E, */ 174554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2F, */ 175554c0a3aSHans de Goede {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ 176554c0a3aSHans de Goede {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ 177554c0a3aSHans de Goede {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ 178554c0a3aSHans de Goede {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ 179554c0a3aSHans de Goede {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ 180554c0a3aSHans de Goede {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ 181554c0a3aSHans de Goede {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ 182554c0a3aSHans de Goede {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ 183554c0a3aSHans de Goede {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ 184554c0a3aSHans de Goede {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ 185554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3A, */ 186554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3B, */ 187554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3C, */ 188554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3D, */ 189554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3E, */ 190554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3F, */ 191554c0a3aSHans de Goede {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ 192554c0a3aSHans de Goede {0x05, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */ 193554c0a3aSHans de Goede {0x01, 0x12}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */ 194554c0a3aSHans de Goede {0x02, 0x05}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */ 195554c0a3aSHans de Goede {0x02, 0x11}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */ 196554c0a3aSHans de Goede {0x00, 0x13}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */ 197554c0a3aSHans de Goede {0x02, 0x14}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */ 198554c0a3aSHans de Goede {0x00, 0x15}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */ 199554c0a3aSHans de Goede {0x00, 0x16}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */ 200554c0a3aSHans de Goede {0x00, 0x17}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */ 201554c0a3aSHans de Goede {0x00, 0x18}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */ 202554c0a3aSHans de Goede {0x00, 0x19}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */ 203554c0a3aSHans de Goede {0x00, 0x1A}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */ 204554c0a3aSHans de Goede {0x02, 0x1B}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */ 205554c0a3aSHans de Goede {0x00, 0x1C}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */ 206554c0a3aSHans de Goede {0x02, 0x1D}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */ 207554c0a3aSHans de Goede {0x00, 0x1E}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */ 208554c0a3aSHans de Goede {0x02, 0x1F}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ 209554c0a3aSHans de Goede }; 210554c0a3aSHans de Goede 2114d17363dSAndreas Hellmich /* use the combination for max channel numbers */ 2124d17363dSAndreas Hellmich static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; 213554c0a3aSHans de Goede 2144d17363dSAndreas Hellmich /* Search the @param ch in given @param ch_set 215554c0a3aSHans de Goede * @ch_set: the given channel set 216554c0a3aSHans de Goede * @ch: the given channel number 217554c0a3aSHans de Goede * 218554c0a3aSHans de Goede * return the index of channel_num in channel_set, -1 if not found 219554c0a3aSHans de Goede */ 220554c0a3aSHans de Goede int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch) 221554c0a3aSHans de Goede { 222554c0a3aSHans de Goede int i; 223c926f022SSimran Singhal 224554c0a3aSHans de Goede for (i = 0; ch_set[i].ChannelNum != 0; i++) { 225554c0a3aSHans de Goede if (ch == ch_set[i].ChannelNum) 226554c0a3aSHans de Goede break; 227554c0a3aSHans de Goede } 228554c0a3aSHans de Goede 229554c0a3aSHans de Goede if (i >= ch_set[i].ChannelNum) 230554c0a3aSHans de Goede return -1; 231554c0a3aSHans de Goede return i; 232554c0a3aSHans de Goede } 233554c0a3aSHans de Goede 2344d17363dSAndreas Hellmich /* Check the @param ch is fit with setband setting of @param adapter 235554c0a3aSHans de Goede * @adapter: the given adapter 236554c0a3aSHans de Goede * @ch: the given channel number 237554c0a3aSHans de Goede * 238554c0a3aSHans de Goede * return true when check valid, false not valid 239554c0a3aSHans de Goede */ 240554c0a3aSHans de Goede bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch) 241554c0a3aSHans de Goede { 242554c0a3aSHans de Goede if (adapter->setband == GHZ24_50 /* 2.4G and 5G */ 243554c0a3aSHans de Goede || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */ 244554c0a3aSHans de Goede || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */ 245554c0a3aSHans de Goede ) { 246554c0a3aSHans de Goede return true; 247554c0a3aSHans de Goede } 248554c0a3aSHans de Goede return false; 249554c0a3aSHans de Goede } 250554c0a3aSHans de Goede 251554c0a3aSHans de Goede /**************************************************************************** 252554c0a3aSHans de Goede 253554c0a3aSHans de Goede Following are the initialization functions for WiFi MLME 254554c0a3aSHans de Goede 255554c0a3aSHans de Goede *****************************************************************************/ 256554c0a3aSHans de Goede 257554c0a3aSHans de Goede int init_hw_mlme_ext(struct adapter *padapter) 258554c0a3aSHans de Goede { 259554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 260554c0a3aSHans de Goede 261554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 262554c0a3aSHans de Goede return _SUCCESS; 263554c0a3aSHans de Goede } 264554c0a3aSHans de Goede 265554c0a3aSHans de Goede void init_mlme_default_rate_set(struct adapter *padapter) 266554c0a3aSHans de Goede { 267554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 268554c0a3aSHans de Goede 269554c0a3aSHans de Goede unsigned char mixed_datarate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_, 0xff}; 270554c0a3aSHans de Goede unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,}; 271554c0a3aSHans de Goede unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; 272554c0a3aSHans de Goede 273554c0a3aSHans de Goede memcpy(pmlmeext->datarate, mixed_datarate, NumRates); 274554c0a3aSHans de Goede memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); 275554c0a3aSHans de Goede 276554c0a3aSHans de Goede memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set)); 277554c0a3aSHans de Goede } 278554c0a3aSHans de Goede 279554c0a3aSHans de Goede static void init_mlme_ext_priv_value(struct adapter *padapter) 280554c0a3aSHans de Goede { 281554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 282c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 283554c0a3aSHans de Goede 284554c0a3aSHans de Goede atomic_set(&pmlmeext->event_seq, 0); 285554c0a3aSHans de Goede pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */ 286554c0a3aSHans de Goede pmlmeext->sa_query_seq = 0; 287554c0a3aSHans de Goede pmlmeext->mgnt_80211w_IPN = 0; 288554c0a3aSHans de Goede pmlmeext->mgnt_80211w_IPN_rx = 0; 289554c0a3aSHans de Goede pmlmeext->cur_channel = padapter->registrypriv.channel; 290554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 291554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 292554c0a3aSHans de Goede 293554c0a3aSHans de Goede pmlmeext->retry = 0; 294554c0a3aSHans de Goede 295554c0a3aSHans de Goede pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; 296554c0a3aSHans de Goede 297554c0a3aSHans de Goede init_mlme_default_rate_set(padapter); 298554c0a3aSHans de Goede 299554c0a3aSHans de Goede pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; 300554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_DISABLE; 301554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = 0; 302554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt = 0; 303554c0a3aSHans de Goede pmlmeext->scan_abort = false; 304554c0a3aSHans de Goede 305554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 306554c0a3aSHans de Goede pmlmeinfo->reauth_count = 0; 307554c0a3aSHans de Goede pmlmeinfo->reassoc_count = 0; 308554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 309554c0a3aSHans de Goede pmlmeinfo->auth_seq = 0; 310554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; 311554c0a3aSHans de Goede pmlmeinfo->key_index = 0; 312554c0a3aSHans de Goede pmlmeinfo->iv = 0; 313554c0a3aSHans de Goede 314554c0a3aSHans de Goede pmlmeinfo->enc_algo = _NO_PRIVACY_; 315554c0a3aSHans de Goede pmlmeinfo->authModeToggle = 0; 316554c0a3aSHans de Goede 317554c0a3aSHans de Goede memset(pmlmeinfo->chg_txt, 0, 128); 318554c0a3aSHans de Goede 319554c0a3aSHans de Goede pmlmeinfo->slotTime = SHORT_SLOT_TIME; 320554c0a3aSHans de Goede pmlmeinfo->preamble_mode = PREAMBLE_AUTO; 321554c0a3aSHans de Goede 322554c0a3aSHans de Goede pmlmeinfo->dialogToken = 0; 323554c0a3aSHans de Goede 324554c0a3aSHans de Goede pmlmeext->action_public_rxseq = 0xffff; 325554c0a3aSHans de Goede pmlmeext->action_public_dialog_token = 0xff; 326554c0a3aSHans de Goede } 327554c0a3aSHans de Goede 328554c0a3aSHans de Goede static int has_channel(RT_CHANNEL_INFO *channel_set, 329554c0a3aSHans de Goede u8 chanset_size, 3303520c7a4SHenriette Hofmeier u8 chan) 3313520c7a4SHenriette Hofmeier { 332554c0a3aSHans de Goede int i; 333554c0a3aSHans de Goede 334554c0a3aSHans de Goede for (i = 0; i < chanset_size; i++) { 335554c0a3aSHans de Goede if (channel_set[i].ChannelNum == chan) { 336554c0a3aSHans de Goede return 1; 337554c0a3aSHans de Goede } 338554c0a3aSHans de Goede } 339554c0a3aSHans de Goede 340554c0a3aSHans de Goede return 0; 341554c0a3aSHans de Goede } 342554c0a3aSHans de Goede 343554c0a3aSHans de Goede static void init_channel_list(struct adapter *padapter, RT_CHANNEL_INFO *channel_set, 344554c0a3aSHans de Goede u8 chanset_size, 3453520c7a4SHenriette Hofmeier struct p2p_channels *channel_list) 3463520c7a4SHenriette Hofmeier { 347554c0a3aSHans de Goede 34853e3a7e1SColin Ian King static const struct p2p_oper_class_map op_class[] = { 349554c0a3aSHans de Goede { IEEE80211G, 81, 1, 13, 1, BW20 }, 350554c0a3aSHans de Goede { IEEE80211G, 82, 14, 14, 1, BW20 }, 351554c0a3aSHans de Goede { IEEE80211A, 115, 36, 48, 4, BW20 }, 352554c0a3aSHans de Goede { IEEE80211A, 116, 36, 44, 8, BW40PLUS }, 353554c0a3aSHans de Goede { IEEE80211A, 117, 40, 48, 8, BW40MINUS }, 354554c0a3aSHans de Goede { IEEE80211A, 124, 149, 161, 4, BW20 }, 355554c0a3aSHans de Goede { IEEE80211A, 125, 149, 169, 4, BW20 }, 356554c0a3aSHans de Goede { IEEE80211A, 126, 149, 157, 8, BW40PLUS }, 357554c0a3aSHans de Goede { IEEE80211A, 127, 153, 161, 8, BW40MINUS }, 358554c0a3aSHans de Goede { -1, 0, 0, 0, 0, BW20 } 359554c0a3aSHans de Goede }; 360554c0a3aSHans de Goede 361554c0a3aSHans de Goede int cla, op; 362554c0a3aSHans de Goede 363554c0a3aSHans de Goede cla = 0; 364554c0a3aSHans de Goede 365554c0a3aSHans de Goede for (op = 0; op_class[op].op_class; op++) { 366554c0a3aSHans de Goede u8 ch; 36753e3a7e1SColin Ian King const struct p2p_oper_class_map *o = &op_class[op]; 368554c0a3aSHans de Goede struct p2p_reg_class *reg = NULL; 369554c0a3aSHans de Goede 370554c0a3aSHans de Goede for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { 371a65f0d18SVatsala Narang if (!has_channel(channel_set, chanset_size, ch)) 372554c0a3aSHans de Goede continue; 373554c0a3aSHans de Goede 374554c0a3aSHans de Goede if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc)) 375554c0a3aSHans de Goede continue; 376554c0a3aSHans de Goede 377554c0a3aSHans de Goede if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) && 378554c0a3aSHans de Goede ((BW40MINUS == o->bw) || (BW40PLUS == o->bw))) 379554c0a3aSHans de Goede continue; 380554c0a3aSHans de Goede 38141452327SVatsala Narang if (!reg) { 382554c0a3aSHans de Goede reg = &channel_list->reg_class[cla]; 383554c0a3aSHans de Goede cla++; 384554c0a3aSHans de Goede reg->reg_class = o->op_class; 385554c0a3aSHans de Goede reg->channels = 0; 386554c0a3aSHans de Goede } 387554c0a3aSHans de Goede reg->channel[reg->channels] = ch; 388554c0a3aSHans de Goede reg->channels++; 389554c0a3aSHans de Goede } 390554c0a3aSHans de Goede } 391554c0a3aSHans de Goede channel_list->reg_classes = cla; 392554c0a3aSHans de Goede 393554c0a3aSHans de Goede } 394554c0a3aSHans de Goede 395554c0a3aSHans de Goede static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, RT_CHANNEL_INFO *channel_set) 396554c0a3aSHans de Goede { 397554c0a3aSHans de Goede u8 index, chanset_size = 0; 398554c0a3aSHans de Goede u8 b5GBand = false, b2_4GBand = false; 399554c0a3aSHans de Goede u8 Index2G = 0, Index5G = 0; 400554c0a3aSHans de Goede 401554c0a3aSHans de Goede memset(channel_set, 0, sizeof(RT_CHANNEL_INFO)*MAX_CHANNEL_NUM); 402554c0a3aSHans de Goede 403554c0a3aSHans de Goede if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) { 404554c0a3aSHans de Goede DBG_871X("ChannelPlan ID %x error !!!!!\n", ChannelPlan); 405554c0a3aSHans de Goede return chanset_size; 406554c0a3aSHans de Goede } 407554c0a3aSHans de Goede 408554c0a3aSHans de Goede if (IsSupported24G(padapter->registrypriv.wireless_mode)) { 409554c0a3aSHans de Goede b2_4GBand = true; 410554c0a3aSHans de Goede if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan) 411554c0a3aSHans de Goede Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; 412554c0a3aSHans de Goede else 413554c0a3aSHans de Goede Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G; 414554c0a3aSHans de Goede } 415554c0a3aSHans de Goede 416554c0a3aSHans de Goede if (b2_4GBand) { 417554c0a3aSHans de Goede for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) { 418554c0a3aSHans de Goede channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index]; 419554c0a3aSHans de Goede 420554c0a3aSHans de Goede if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */ 421554c0a3aSHans de Goede (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)) { 422554c0a3aSHans de Goede if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11) 423554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 424554c0a3aSHans de Goede else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) 425554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 426554c0a3aSHans de Goede } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan || 427554c0a3aSHans de Goede RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan || 428554c0a3aSHans de Goede RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /* channel 12~13, passive scan */ 429554c0a3aSHans de Goede if (channel_set[chanset_size].ChannelNum <= 11) 430554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 431554c0a3aSHans de Goede else 432554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 433554c0a3aSHans de Goede } else 434554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 435554c0a3aSHans de Goede 436554c0a3aSHans de Goede chanset_size++; 437554c0a3aSHans de Goede } 438554c0a3aSHans de Goede } 439554c0a3aSHans de Goede 440554c0a3aSHans de Goede if (b5GBand) { 441554c0a3aSHans de Goede for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) { 442554c0a3aSHans de Goede if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 443554c0a3aSHans de Goede || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) { 444554c0a3aSHans de Goede channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index]; 445554c0a3aSHans de Goede if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */ 446554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 447554c0a3aSHans de Goede else 448554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 449554c0a3aSHans de Goede DBG_871X("%s(): channel_set[%d].ChannelNum = %d\n", __func__, chanset_size, channel_set[chanset_size].ChannelNum); 450554c0a3aSHans de Goede chanset_size++; 451554c0a3aSHans de Goede } 452554c0a3aSHans de Goede } 453554c0a3aSHans de Goede } 454554c0a3aSHans de Goede 455554c0a3aSHans de Goede DBG_871X("%s ChannelPlan ID %x Chan num:%d \n", __func__, ChannelPlan, chanset_size); 456554c0a3aSHans de Goede return chanset_size; 457554c0a3aSHans de Goede } 458554c0a3aSHans de Goede 459067756acSHariprasad Kelam void init_mlme_ext_priv(struct adapter *padapter) 460554c0a3aSHans de Goede { 461554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 462554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 463c872ed07SVatsala Narang struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 464c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 465554c0a3aSHans de Goede 466554c0a3aSHans de Goede pmlmeext->padapter = padapter; 467554c0a3aSHans de Goede 468554c0a3aSHans de Goede /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */ 469554c0a3aSHans de Goede 470554c0a3aSHans de Goede init_mlme_ext_priv_value(padapter); 4712646633fSAastha Gupta pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req; 472554c0a3aSHans de Goede 473554c0a3aSHans de Goede init_mlme_ext_timer(padapter); 474554c0a3aSHans de Goede 475554c0a3aSHans de Goede init_mlme_ap_info(padapter); 476554c0a3aSHans de Goede 477554c0a3aSHans de Goede pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set); 478554c0a3aSHans de Goede init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); 479554c0a3aSHans de Goede pmlmeext->last_scan_time = 0; 480554c0a3aSHans de Goede pmlmeext->chan_scan_time = SURVEY_TO; 481554c0a3aSHans de Goede pmlmeext->mlmeext_init = true; 482554c0a3aSHans de Goede pmlmeext->active_keep_alive_check = true; 483554c0a3aSHans de Goede 484554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 485554c0a3aSHans de Goede pmlmeext->fixed_chan = 0xFF; 486554c0a3aSHans de Goede #endif 487554c0a3aSHans de Goede } 488554c0a3aSHans de Goede 489554c0a3aSHans de Goede void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) 490554c0a3aSHans de Goede { 491554c0a3aSHans de Goede struct adapter *padapter = pmlmeext->padapter; 492554c0a3aSHans de Goede 493554c0a3aSHans de Goede if (!padapter) 494554c0a3aSHans de Goede return; 495554c0a3aSHans de Goede 4960ad02fa8SGeorgiana Chelu if (padapter->bDriverStopped) { 497554c0a3aSHans de Goede del_timer_sync(&pmlmeext->survey_timer); 498554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 499554c0a3aSHans de Goede /* del_timer_sync(&pmlmeext->ADDBA_timer); */ 500554c0a3aSHans de Goede } 501554c0a3aSHans de Goede } 502554c0a3aSHans de Goede 503554c0a3aSHans de Goede static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame) 504554c0a3aSHans de Goede { 505554c0a3aSHans de Goede u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 506554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 507554c0a3aSHans de Goede 508554c0a3aSHans de Goede if (ptable->func) { 509554c0a3aSHans de Goede /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ 510554c0a3aSHans de Goede if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && 511554c0a3aSHans de Goede memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) 512554c0a3aSHans de Goede return; 513554c0a3aSHans de Goede 514554c0a3aSHans de Goede ptable->func(padapter, precv_frame); 515554c0a3aSHans de Goede } 516554c0a3aSHans de Goede } 517554c0a3aSHans de Goede 518554c0a3aSHans de Goede void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame) 519554c0a3aSHans de Goede { 520554c0a3aSHans de Goede int index; 521554c0a3aSHans de Goede struct mlme_handler *ptable; 522554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 523554c0a3aSHans de Goede u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 524554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 525554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe)); 526554c0a3aSHans de Goede struct dvobj_priv *psdpriv = padapter->dvobj; 527554c0a3aSHans de Goede struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; 528554c0a3aSHans de Goede 529554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 530554c0a3aSHans de Goede ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n", 531554c0a3aSHans de Goede GetFrameType(pframe), GetFrameSubType(pframe))); 532554c0a3aSHans de Goede 533554c0a3aSHans de Goede if (GetFrameType(pframe) != WIFI_MGT_TYPE) { 534554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe))); 535554c0a3aSHans de Goede return; 536554c0a3aSHans de Goede } 537554c0a3aSHans de Goede 538554c0a3aSHans de Goede /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ 539554c0a3aSHans de Goede if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && 540554c0a3aSHans de Goede memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) { 541554c0a3aSHans de Goede return; 542554c0a3aSHans de Goede } 543554c0a3aSHans de Goede 544554c0a3aSHans de Goede ptable = mlme_sta_tbl; 545554c0a3aSHans de Goede 546554c0a3aSHans de Goede index = GetFrameSubType(pframe) >> 4; 547554c0a3aSHans de Goede 54860db8d10SJérémy Lefaure if (index >= ARRAY_SIZE(mlme_sta_tbl)) { 549554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type =%d\n", index)); 550554c0a3aSHans de Goede return; 551554c0a3aSHans de Goede } 552554c0a3aSHans de Goede ptable += index; 553554c0a3aSHans de Goede 55434557e23SIzabela Bakollari if (psta) { 555554c0a3aSHans de Goede if (GetRetry(pframe)) { 556554c0a3aSHans de Goede if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) { 557554c0a3aSHans de Goede /* drop the duplicate management frame */ 558554c0a3aSHans de Goede pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++; 559554c0a3aSHans de Goede DBG_871X("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num); 560554c0a3aSHans de Goede return; 561554c0a3aSHans de Goede } 562554c0a3aSHans de Goede } 563554c0a3aSHans de Goede psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num; 564554c0a3aSHans de Goede } 565554c0a3aSHans de Goede 566554c0a3aSHans de Goede switch (GetFrameSubType(pframe)) { 567554c0a3aSHans de Goede case WIFI_AUTH: 5680ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) 569554c0a3aSHans de Goede ptable->func = &OnAuth; 570554c0a3aSHans de Goede else 571554c0a3aSHans de Goede ptable->func = &OnAuthClient; 57252a1d9d4SGustavo A. R. Silva fallthrough; 573554c0a3aSHans de Goede case WIFI_ASSOCREQ: 574554c0a3aSHans de Goede case WIFI_REASSOCREQ: 575554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 576554c0a3aSHans de Goede break; 577554c0a3aSHans de Goede case WIFI_PROBEREQ: 578554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 579554c0a3aSHans de Goede break; 580554c0a3aSHans de Goede case WIFI_BEACON: 581554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 582554c0a3aSHans de Goede break; 583554c0a3aSHans de Goede case WIFI_ACTION: 584554c0a3aSHans de Goede /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */ 585554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 586554c0a3aSHans de Goede break; 587554c0a3aSHans de Goede default: 588554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 589554c0a3aSHans de Goede break; 590554c0a3aSHans de Goede } 591554c0a3aSHans de Goede } 592554c0a3aSHans de Goede 593554c0a3aSHans de Goede /**************************************************************************** 594554c0a3aSHans de Goede 595554c0a3aSHans de Goede Following are the callback functions for each subtype of the management frames 596554c0a3aSHans de Goede 597554c0a3aSHans de Goede *****************************************************************************/ 598554c0a3aSHans de Goede 599554c0a3aSHans de Goede unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame) 600554c0a3aSHans de Goede { 601554c0a3aSHans de Goede unsigned int ielen; 602554c0a3aSHans de Goede unsigned char *p; 603554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 604554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 605c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 606c872ed07SVatsala Narang struct wlan_bssid_ex *cur = &pmlmeinfo->network; 607554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 608554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 609554c0a3aSHans de Goede u8 is_valid_p2p_probereq = false; 610554c0a3aSHans de Goede 611554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 612554c0a3aSHans de Goede return _SUCCESS; 613554c0a3aSHans de Goede 614554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == false && 615554c0a3aSHans de Goede check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) { 616554c0a3aSHans de Goede return _SUCCESS; 617554c0a3aSHans de Goede } 618554c0a3aSHans de Goede 619554c0a3aSHans de Goede 620554c0a3aSHans de Goede /* DBG_871X("+OnProbeReq\n"); */ 621554c0a3aSHans de Goede 622554c0a3aSHans de Goede #ifdef CONFIG_AUTO_AP_MODE 6230ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, _FW_LINKED) && 6240ad02fa8SGeorgiana Chelu pmlmepriv->cur_network.join_res) { 625554c0a3aSHans de Goede struct sta_info *psta; 626554c0a3aSHans de Goede u8 *mac_addr, *peer_addr; 627554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 628554c0a3aSHans de Goede u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A}; 629554c0a3aSHans de Goede /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */ 630554c0a3aSHans de Goede 631554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen, 632554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); 633554c0a3aSHans de Goede 634554c0a3aSHans de Goede if (!p || ielen != 14) 635554c0a3aSHans de Goede goto _non_rc_device; 636554c0a3aSHans de Goede 637554c0a3aSHans de Goede if (memcmp(p+2, RC_OUI, sizeof(RC_OUI))) 638554c0a3aSHans de Goede goto _non_rc_device; 639554c0a3aSHans de Goede 640554c0a3aSHans de Goede if (memcmp(p+6, get_sa(pframe), ETH_ALEN)) { 641bbda3ac4SRoss Schmidt DBG_871X("%s, do rc pairing (%pM), but mac addr mismatch!(%pM)\n", __func__, 642554c0a3aSHans de Goede MAC_ARG(get_sa(pframe)), MAC_ARG(p+6)); 643554c0a3aSHans de Goede 644554c0a3aSHans de Goede goto _non_rc_device; 645554c0a3aSHans de Goede } 646554c0a3aSHans de Goede 647bbda3ac4SRoss Schmidt DBG_871X("%s, got the pairing device(%pM)\n", __func__, MAC_ARG(get_sa(pframe))); 648554c0a3aSHans de Goede 649554c0a3aSHans de Goede /* new a station */ 650554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, get_sa(pframe)); 651554c0a3aSHans de Goede if (psta == NULL) { 652554c0a3aSHans de Goede /* allocate a new one */ 653bbda3ac4SRoss Schmidt DBG_871X("going to alloc stainfo for rc =%pM\n", MAC_ARG(get_sa(pframe))); 654554c0a3aSHans de Goede psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe)); 65541452327SVatsala Narang if (!psta) { 656554c0a3aSHans de Goede /* TODO: */ 657554c0a3aSHans de Goede DBG_871X(" Exceed the upper limit of supported clients...\n"); 658554c0a3aSHans de Goede return _SUCCESS; 659554c0a3aSHans de Goede } 660554c0a3aSHans de Goede 661554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 662554c0a3aSHans de Goede if (list_empty(&psta->asoc_list)) { 663554c0a3aSHans de Goede psta->expire_to = pstapriv->expire_to; 664554c0a3aSHans de Goede list_add_tail(&psta->asoc_list, &pstapriv->asoc_list); 665554c0a3aSHans de Goede pstapriv->asoc_list_cnt++; 666554c0a3aSHans de Goede } 667554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 668554c0a3aSHans de Goede 669554c0a3aSHans de Goede /* generate pairing ID */ 670554c0a3aSHans de Goede mac_addr = myid(&(padapter->eeprompriv)); 671554c0a3aSHans de Goede peer_addr = psta->hwaddr; 672554c0a3aSHans de Goede psta->pid = (u16)(((mac_addr[4]<<8) + mac_addr[5]) + ((peer_addr[4]<<8) + peer_addr[5])); 673554c0a3aSHans de Goede 674554c0a3aSHans de Goede /* update peer stainfo */ 675554c0a3aSHans de Goede psta->isrc = true; 676554c0a3aSHans de Goede /* psta->aid = 0; */ 677554c0a3aSHans de Goede /* psta->mac_id = 2; */ 678554c0a3aSHans de Goede 679554c0a3aSHans de Goede /* get a unique AID */ 680554c0a3aSHans de Goede if (psta->aid > 0) { 681554c0a3aSHans de Goede DBG_871X("old AID %d\n", psta->aid); 682554c0a3aSHans de Goede } else { 683554c0a3aSHans de Goede for (psta->aid = 1; psta->aid <= NUM_STA; psta->aid++) 684554c0a3aSHans de Goede if (pstapriv->sta_aid[psta->aid - 1] == NULL) 685554c0a3aSHans de Goede break; 686554c0a3aSHans de Goede 687554c0a3aSHans de Goede if (psta->aid > pstapriv->max_num_sta) { 688554c0a3aSHans de Goede psta->aid = 0; 689554c0a3aSHans de Goede DBG_871X("no room for more AIDs\n"); 690554c0a3aSHans de Goede return _SUCCESS; 6919358bd52SVatsala Narang } 692554c0a3aSHans de Goede pstapriv->sta_aid[psta->aid - 1] = psta; 693554c0a3aSHans de Goede DBG_871X("allocate new AID = (%d)\n", psta->aid); 694554c0a3aSHans de Goede } 695554c0a3aSHans de Goede 696554c0a3aSHans de Goede psta->qos_option = 1; 697554c0a3aSHans de Goede psta->bw_mode = CHANNEL_WIDTH_20; 698554c0a3aSHans de Goede psta->ieee8021x_blocked = false; 699554c0a3aSHans de Goede psta->htpriv.ht_option = true; 700554c0a3aSHans de Goede psta->htpriv.ampdu_enable = false; 701554c0a3aSHans de Goede psta->htpriv.sgi_20m = false; 702554c0a3aSHans de Goede psta->htpriv.sgi_40m = false; 703554c0a3aSHans de Goede psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 704554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ 705554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ 706554c0a3aSHans de Goede 707554c0a3aSHans de Goede rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true); 708554c0a3aSHans de Goede 709554c0a3aSHans de Goede memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); 710554c0a3aSHans de Goede 711554c0a3aSHans de Goede spin_lock_bh(&psta->lock); 712554c0a3aSHans de Goede psta->state |= _FW_LINKED; 713554c0a3aSHans de Goede spin_unlock_bh(&psta->lock); 714554c0a3aSHans de Goede 715554c0a3aSHans de Goede report_add_sta_event(padapter, psta->hwaddr, psta->aid); 716554c0a3aSHans de Goede 717554c0a3aSHans de Goede } 718554c0a3aSHans de Goede 719554c0a3aSHans de Goede issue_probersp(padapter, get_sa(pframe), false); 720554c0a3aSHans de Goede 721554c0a3aSHans de Goede return _SUCCESS; 722554c0a3aSHans de Goede 723554c0a3aSHans de Goede } 724554c0a3aSHans de Goede 725554c0a3aSHans de Goede _non_rc_device: 726554c0a3aSHans de Goede 727554c0a3aSHans de Goede return _SUCCESS; 728554c0a3aSHans de Goede 729554c0a3aSHans de Goede #endif /* CONFIG_AUTO_AP_MODE */ 730554c0a3aSHans de Goede 731554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen, 732554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); 733554c0a3aSHans de Goede 734554c0a3aSHans de Goede 735554c0a3aSHans de Goede /* check (wildcard) SSID */ 73634557e23SIzabela Bakollari if (p) { 7370ad02fa8SGeorgiana Chelu if (is_valid_p2p_probereq) 738554c0a3aSHans de Goede goto _issue_probersp; 739554c0a3aSHans de Goede 740554c0a3aSHans de Goede if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) 741554c0a3aSHans de Goede || (ielen == 0 && pmlmeinfo->hidden_ssid_mode) 742554c0a3aSHans de Goede ) 743554c0a3aSHans de Goede return _SUCCESS; 744554c0a3aSHans de Goede 745554c0a3aSHans de Goede _issue_probersp: 7460ad02fa8SGeorgiana Chelu if ((check_fwstate(pmlmepriv, _FW_LINKED) && 7470ad02fa8SGeorgiana Chelu pmlmepriv->cur_network.join_res) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { 748554c0a3aSHans de Goede /* DBG_871X("+issue_probersp during ap mode\n"); */ 749554c0a3aSHans de Goede issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); 750554c0a3aSHans de Goede } 751554c0a3aSHans de Goede 752554c0a3aSHans de Goede } 753554c0a3aSHans de Goede 754554c0a3aSHans de Goede return _SUCCESS; 755554c0a3aSHans de Goede 756554c0a3aSHans de Goede } 757554c0a3aSHans de Goede 758554c0a3aSHans de Goede unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame) 759554c0a3aSHans de Goede { 760554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 761554c0a3aSHans de Goede 762554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 763554c0a3aSHans de Goede report_survey_event(padapter, precv_frame); 764554c0a3aSHans de Goede return _SUCCESS; 765554c0a3aSHans de Goede } 766554c0a3aSHans de Goede 767554c0a3aSHans de Goede return _SUCCESS; 768554c0a3aSHans de Goede 769554c0a3aSHans de Goede } 770554c0a3aSHans de Goede 771554c0a3aSHans de Goede unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame) 772554c0a3aSHans de Goede { 773554c0a3aSHans de Goede int cam_idx; 774554c0a3aSHans de Goede struct sta_info *psta; 775554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 776554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 777554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 778554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 779554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 780554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 781554c0a3aSHans de Goede struct wlan_bssid_ex *pbss; 782554c0a3aSHans de Goede int ret = _SUCCESS; 783554c0a3aSHans de Goede u8 *p = NULL; 784554c0a3aSHans de Goede u32 ielen = 0; 785554c0a3aSHans de Goede 786554c0a3aSHans de Goede p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_); 78734557e23SIzabela Bakollari if (p && ielen > 0) { 788554c0a3aSHans de Goede if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) { 789554c0a3aSHans de Goede /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */ 790bbda3ac4SRoss Schmidt DBG_871X("[WIFIDBG] Error in ESR IE is detected in Beacon of BSSID:%pM. Fix the length of ESR IE to avoid failed Beacon parsing.\n", MAC_ARG(GetAddr3Ptr(pframe))); 791554c0a3aSHans de Goede *(p + 1) = ielen - 1; 792554c0a3aSHans de Goede } 793554c0a3aSHans de Goede } 794554c0a3aSHans de Goede 795554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 796554c0a3aSHans de Goede report_survey_event(padapter, precv_frame); 797554c0a3aSHans de Goede return _SUCCESS; 798554c0a3aSHans de Goede } 799554c0a3aSHans de Goede 800554c0a3aSHans de Goede if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) { 801554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { 802554c0a3aSHans de Goede /* we should update current network before auth, or some IE is wrong */ 8032ef2b7c2SJoe Perches pbss = rtw_malloc(sizeof(struct wlan_bssid_ex)); 804554c0a3aSHans de Goede if (pbss) { 805554c0a3aSHans de Goede if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { 806554c0a3aSHans de Goede update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true); 807554c0a3aSHans de Goede rtw_get_bcn_info(&(pmlmepriv->cur_network)); 808554c0a3aSHans de Goede } 8098f24f505SMadhumitha Prabakaran kfree(pbss); 810554c0a3aSHans de Goede } 811554c0a3aSHans de Goede 812554c0a3aSHans de Goede /* check the vendor of the assoc AP */ 813554c0a3aSHans de Goede pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr)); 814554c0a3aSHans de Goede 815554c0a3aSHans de Goede /* update TSF Value */ 816554c0a3aSHans de Goede update_TSF(pmlmeext, pframe, len); 817554c0a3aSHans de Goede 818554c0a3aSHans de Goede /* reset for adaptive_early_32k */ 819554c0a3aSHans de Goede pmlmeext->adaptive_tsf_done = false; 820554c0a3aSHans de Goede pmlmeext->DrvBcnEarly = 0xff; 821554c0a3aSHans de Goede pmlmeext->DrvBcnTimeOut = 0xff; 822554c0a3aSHans de Goede pmlmeext->bcn_cnt = 0; 823554c0a3aSHans de Goede memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt)); 824554c0a3aSHans de Goede memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio)); 825554c0a3aSHans de Goede 826554c0a3aSHans de Goede /* start auth */ 827554c0a3aSHans de Goede start_clnt_auth(padapter); 828554c0a3aSHans de Goede 829554c0a3aSHans de Goede return _SUCCESS; 830554c0a3aSHans de Goede } 831554c0a3aSHans de Goede 832554c0a3aSHans de Goede if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { 833554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 83434557e23SIzabela Bakollari if (psta) { 835554c0a3aSHans de Goede ret = rtw_check_bcn_info(padapter, pframe, len); 836554c0a3aSHans de Goede if (!ret) { 837554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n "); 838554c0a3aSHans de Goede receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0); 839554c0a3aSHans de Goede return _SUCCESS; 840554c0a3aSHans de Goede } 841554c0a3aSHans de Goede /* update WMM, ERP in the beacon */ 842554c0a3aSHans de Goede /* todo: the timer is used instead of the number of the beacon received */ 843554c0a3aSHans de Goede if ((sta_rx_pkts(psta) & 0xf) == 0) 844554c0a3aSHans de Goede /* DBG_871X("update_bcn_info\n"); */ 845554c0a3aSHans de Goede update_beacon_info(padapter, pframe, len, psta); 846554c0a3aSHans de Goede 847554c0a3aSHans de Goede adaptive_early_32k(pmlmeext, pframe, len); 848554c0a3aSHans de Goede } 849554c0a3aSHans de Goede } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 850554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 85134557e23SIzabela Bakollari if (psta) { 852554c0a3aSHans de Goede /* update WMM, ERP in the beacon */ 853554c0a3aSHans de Goede /* todo: the timer is used instead of the number of the beacon received */ 854554c0a3aSHans de Goede if ((sta_rx_pkts(psta) & 0xf) == 0) { 855554c0a3aSHans de Goede /* DBG_871X("update_bcn_info\n"); */ 856554c0a3aSHans de Goede update_beacon_info(padapter, pframe, len, psta); 857554c0a3aSHans de Goede } 858554c0a3aSHans de Goede } else { 859554c0a3aSHans de Goede /* allocate a new CAM entry for IBSS station */ 860554c0a3aSHans de Goede cam_idx = allocate_fw_sta_entry(padapter); 861554c0a3aSHans de Goede if (cam_idx == NUM_STA) 862554c0a3aSHans de Goede goto _END_ONBEACON_; 863554c0a3aSHans de Goede 864554c0a3aSHans de Goede /* get supported rate */ 865554c0a3aSHans de Goede if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) { 866554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[cam_idx].status = 0; 867554c0a3aSHans de Goede goto _END_ONBEACON_; 868554c0a3aSHans de Goede } 869554c0a3aSHans de Goede 870554c0a3aSHans de Goede /* update TSF Value */ 871554c0a3aSHans de Goede update_TSF(pmlmeext, pframe, len); 872554c0a3aSHans de Goede 873554c0a3aSHans de Goede /* report sta add event */ 874554c0a3aSHans de Goede report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx); 875554c0a3aSHans de Goede } 876554c0a3aSHans de Goede } 877554c0a3aSHans de Goede } 878554c0a3aSHans de Goede 879554c0a3aSHans de Goede _END_ONBEACON_: 880554c0a3aSHans de Goede 881554c0a3aSHans de Goede return _SUCCESS; 882554c0a3aSHans de Goede 883554c0a3aSHans de Goede } 884554c0a3aSHans de Goede 885554c0a3aSHans de Goede unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame) 886554c0a3aSHans de Goede { 887554c0a3aSHans de Goede unsigned int auth_mode, seq, ie_len; 888554c0a3aSHans de Goede unsigned char *sa, *p; 889554c0a3aSHans de Goede u16 algorithm; 890554c0a3aSHans de Goede int status; 891554c0a3aSHans de Goede static struct sta_info stat; 892554c0a3aSHans de Goede struct sta_info *pstat = NULL; 893554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 894554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 895554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 896554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 897554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 898554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 899554c0a3aSHans de Goede u8 offset = 0; 900554c0a3aSHans de Goede 901554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 902554c0a3aSHans de Goede return _FAIL; 903554c0a3aSHans de Goede 904554c0a3aSHans de Goede DBG_871X("+OnAuth\n"); 905554c0a3aSHans de Goede 906554c0a3aSHans de Goede sa = GetAddr2Ptr(pframe); 907554c0a3aSHans de Goede 908554c0a3aSHans de Goede auth_mode = psecuritypriv->dot11AuthAlgrthm; 909554c0a3aSHans de Goede 910554c0a3aSHans de Goede if (GetPrivacy(pframe)) { 911554c0a3aSHans de Goede u8 *iv; 912554c0a3aSHans de Goede struct rx_pkt_attrib *prxattrib = &(precv_frame->u.hdr.attrib); 913554c0a3aSHans de Goede 914554c0a3aSHans de Goede prxattrib->hdrlen = WLAN_HDR_A3_LEN; 915554c0a3aSHans de Goede prxattrib->encrypt = _WEP40_; 916554c0a3aSHans de Goede 917554c0a3aSHans de Goede iv = pframe+prxattrib->hdrlen; 918554c0a3aSHans de Goede prxattrib->key_index = ((iv[3]>>6)&0x3); 919554c0a3aSHans de Goede 920554c0a3aSHans de Goede prxattrib->iv_len = 4; 921554c0a3aSHans de Goede prxattrib->icv_len = 4; 922554c0a3aSHans de Goede 923554c0a3aSHans de Goede rtw_wep_decrypt(padapter, (u8 *)precv_frame); 924554c0a3aSHans de Goede 925554c0a3aSHans de Goede offset = 4; 926554c0a3aSHans de Goede } 927554c0a3aSHans de Goede 928554c0a3aSHans de Goede algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset)); 929554c0a3aSHans de Goede seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2)); 930554c0a3aSHans de Goede 931554c0a3aSHans de Goede DBG_871X("auth alg =%x, seq =%X\n", algorithm, seq); 932554c0a3aSHans de Goede 933554c0a3aSHans de Goede if (auth_mode == 2 && 934554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ && 935554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm != _WEP104_) 936554c0a3aSHans de Goede auth_mode = 0; 937554c0a3aSHans de Goede 938554c0a3aSHans de Goede if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */ 939554c0a3aSHans de Goede (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */ 940554c0a3aSHans de Goede DBG_871X("auth rejected due to bad alg [alg =%d, auth_mib =%d] %02X%02X%02X%02X%02X%02X\n", 941554c0a3aSHans de Goede algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); 942554c0a3aSHans de Goede 943554c0a3aSHans de Goede status = _STATS_NO_SUPP_ALG_; 944554c0a3aSHans de Goede 945554c0a3aSHans de Goede goto auth_fail; 946554c0a3aSHans de Goede } 947554c0a3aSHans de Goede 948554c0a3aSHans de Goede if (rtw_access_ctrl(padapter, sa) == false) { 949554c0a3aSHans de Goede status = _STATS_UNABLE_HANDLE_STA_; 950554c0a3aSHans de Goede goto auth_fail; 951554c0a3aSHans de Goede } 952554c0a3aSHans de Goede 953554c0a3aSHans de Goede pstat = rtw_get_stainfo(pstapriv, sa); 954554c0a3aSHans de Goede if (pstat == NULL) { 955554c0a3aSHans de Goede 956554c0a3aSHans de Goede /* allocate a new one */ 957bbda3ac4SRoss Schmidt DBG_871X("going to alloc stainfo for sa =%pM\n", MAC_ARG(sa)); 958554c0a3aSHans de Goede pstat = rtw_alloc_stainfo(pstapriv, sa); 959554c0a3aSHans de Goede if (pstat == NULL) { 960554c0a3aSHans de Goede DBG_871X(" Exceed the upper limit of supported clients...\n"); 961554c0a3aSHans de Goede status = _STATS_UNABLE_HANDLE_STA_; 962554c0a3aSHans de Goede goto auth_fail; 963554c0a3aSHans de Goede } 964554c0a3aSHans de Goede 965554c0a3aSHans de Goede pstat->state = WIFI_FW_AUTH_NULL; 966554c0a3aSHans de Goede pstat->auth_seq = 0; 967554c0a3aSHans de Goede 968554c0a3aSHans de Goede /* pstat->flags = 0; */ 969554c0a3aSHans de Goede /* pstat->capability = 0; */ 970554c0a3aSHans de Goede } else { 971554c0a3aSHans de Goede 972554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 973554c0a3aSHans de Goede if (list_empty(&pstat->asoc_list) == false) { 974554c0a3aSHans de Goede list_del_init(&pstat->asoc_list); 975554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 976554c0a3aSHans de Goede if (pstat->expire_to > 0) { 977554c0a3aSHans de Goede /* TODO: STA re_auth within expire_to */ 978554c0a3aSHans de Goede } 979554c0a3aSHans de Goede } 980554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 981554c0a3aSHans de Goede 982554c0a3aSHans de Goede if (seq == 1) { 983554c0a3aSHans de Goede /* TODO: STA re_auth and auth timeout */ 984554c0a3aSHans de Goede } 985554c0a3aSHans de Goede } 986554c0a3aSHans de Goede 987554c0a3aSHans de Goede spin_lock_bh(&pstapriv->auth_list_lock); 988554c0a3aSHans de Goede if (list_empty(&pstat->auth_list)) { 989554c0a3aSHans de Goede 990554c0a3aSHans de Goede list_add_tail(&pstat->auth_list, &pstapriv->auth_list); 991554c0a3aSHans de Goede pstapriv->auth_list_cnt++; 992554c0a3aSHans de Goede } 993554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->auth_list_lock); 994554c0a3aSHans de Goede 995554c0a3aSHans de Goede if (pstat->auth_seq == 0) 996554c0a3aSHans de Goede pstat->expire_to = pstapriv->auth_to; 997554c0a3aSHans de Goede 998554c0a3aSHans de Goede 999554c0a3aSHans de Goede if ((pstat->auth_seq + 1) != seq) { 1000554c0a3aSHans de Goede DBG_871X("(1)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n", 1001554c0a3aSHans de Goede seq, pstat->auth_seq+1); 1002554c0a3aSHans de Goede status = _STATS_OUT_OF_AUTH_SEQ_; 1003554c0a3aSHans de Goede goto auth_fail; 1004554c0a3aSHans de Goede } 1005554c0a3aSHans de Goede 1006554c0a3aSHans de Goede if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) { 1007554c0a3aSHans de Goede if (seq == 1) { 1008554c0a3aSHans de Goede pstat->state &= ~WIFI_FW_AUTH_NULL; 1009554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_SUCCESS; 1010554c0a3aSHans de Goede pstat->expire_to = pstapriv->assoc_to; 1011554c0a3aSHans de Goede pstat->authalg = algorithm; 1012554c0a3aSHans de Goede } else { 1013554c0a3aSHans de Goede DBG_871X("(2)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n", 1014554c0a3aSHans de Goede seq, pstat->auth_seq+1); 1015554c0a3aSHans de Goede status = _STATS_OUT_OF_AUTH_SEQ_; 1016554c0a3aSHans de Goede goto auth_fail; 1017554c0a3aSHans de Goede } 1018554c0a3aSHans de Goede } else { /* shared system or auto authentication */ 1019554c0a3aSHans de Goede if (seq == 1) { 1020554c0a3aSHans de Goede /* prepare for the challenging txt... */ 1021554c0a3aSHans de Goede memset((void *)pstat->chg_txt, 78, 128); 1022554c0a3aSHans de Goede 1023554c0a3aSHans de Goede pstat->state &= ~WIFI_FW_AUTH_NULL; 1024554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_STATE; 1025554c0a3aSHans de Goede pstat->authalg = algorithm; 1026554c0a3aSHans de Goede pstat->auth_seq = 2; 1027554c0a3aSHans de Goede } else if (seq == 3) { 1028554c0a3aSHans de Goede /* checking for challenging txt... */ 1029554c0a3aSHans de Goede DBG_871X("checking for challenging txt...\n"); 1030554c0a3aSHans de Goede 1031554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len, 1032554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); 1033554c0a3aSHans de Goede 1034554c0a3aSHans de Goede if ((p == NULL) || (ie_len <= 0)) { 1035554c0a3aSHans de Goede DBG_871X("auth rejected because challenge failure!(1)\n"); 1036554c0a3aSHans de Goede status = _STATS_CHALLENGE_FAIL_; 1037554c0a3aSHans de Goede goto auth_fail; 1038554c0a3aSHans de Goede } 1039554c0a3aSHans de Goede 1040554c0a3aSHans de Goede if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) { 1041554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_AUTH_STATE); 1042554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_SUCCESS; 1043554c0a3aSHans de Goede /* challenging txt is correct... */ 1044554c0a3aSHans de Goede pstat->expire_to = pstapriv->assoc_to; 1045554c0a3aSHans de Goede } else { 1046554c0a3aSHans de Goede DBG_871X("auth rejected because challenge failure!\n"); 1047554c0a3aSHans de Goede status = _STATS_CHALLENGE_FAIL_; 1048554c0a3aSHans de Goede goto auth_fail; 1049554c0a3aSHans de Goede } 1050554c0a3aSHans de Goede } else { 1051554c0a3aSHans de Goede DBG_871X("(3)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n", 1052554c0a3aSHans de Goede seq, pstat->auth_seq+1); 1053554c0a3aSHans de Goede status = _STATS_OUT_OF_AUTH_SEQ_; 1054554c0a3aSHans de Goede goto auth_fail; 1055554c0a3aSHans de Goede } 1056554c0a3aSHans de Goede } 1057554c0a3aSHans de Goede 1058554c0a3aSHans de Goede 1059554c0a3aSHans de Goede /* Now, we are going to issue_auth... */ 1060554c0a3aSHans de Goede pstat->auth_seq = seq + 1; 1061554c0a3aSHans de Goede 1062554c0a3aSHans de Goede issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_)); 1063554c0a3aSHans de Goede 1064554c0a3aSHans de Goede if (pstat->state & WIFI_FW_AUTH_SUCCESS) 1065554c0a3aSHans de Goede pstat->auth_seq = 0; 1066554c0a3aSHans de Goede 1067554c0a3aSHans de Goede 1068554c0a3aSHans de Goede return _SUCCESS; 1069554c0a3aSHans de Goede 1070554c0a3aSHans de Goede auth_fail: 1071554c0a3aSHans de Goede 1072554c0a3aSHans de Goede if (pstat) 1073554c0a3aSHans de Goede rtw_free_stainfo(padapter, pstat); 1074554c0a3aSHans de Goede 1075554c0a3aSHans de Goede pstat = &stat; 1076554c0a3aSHans de Goede memset((char *)pstat, '\0', sizeof(stat)); 1077554c0a3aSHans de Goede pstat->auth_seq = 2; 1078554c0a3aSHans de Goede memcpy(pstat->hwaddr, sa, 6); 1079554c0a3aSHans de Goede 1080554c0a3aSHans de Goede issue_auth(padapter, pstat, (unsigned short)status); 1081554c0a3aSHans de Goede 1082554c0a3aSHans de Goede return _FAIL; 1083554c0a3aSHans de Goede 1084554c0a3aSHans de Goede } 1085554c0a3aSHans de Goede 1086554c0a3aSHans de Goede unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame) 1087554c0a3aSHans de Goede { 10883a0514a9SJason Yan unsigned int seq, len, status, offset; 1089554c0a3aSHans de Goede unsigned char *p; 1090554c0a3aSHans de Goede unsigned int go2asoc = 0; 1091554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1092554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1093554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1094554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1095554c0a3aSHans de Goede 1096554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1097554c0a3aSHans de Goede 1098554c0a3aSHans de Goede /* check A1 matches or not */ 1099554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) 1100554c0a3aSHans de Goede return _SUCCESS; 1101554c0a3aSHans de Goede 1102554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) 1103554c0a3aSHans de Goede return _SUCCESS; 1104554c0a3aSHans de Goede 1105554c0a3aSHans de Goede offset = (GetPrivacy(pframe)) ? 4 : 0; 1106554c0a3aSHans de Goede 1107554c0a3aSHans de Goede seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2)); 1108554c0a3aSHans de Goede status = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4)); 1109554c0a3aSHans de Goede 1110554c0a3aSHans de Goede if (status != 0) { 1111554c0a3aSHans de Goede DBG_871X("clnt auth fail, status: %d\n", status); 1112554c0a3aSHans de Goede if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ 1113554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) 1114554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; 1115554c0a3aSHans de Goede else 1116554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; 1117554c0a3aSHans de Goede /* pmlmeinfo->reauth_count = 0; */ 1118554c0a3aSHans de Goede } 1119554c0a3aSHans de Goede 1120554c0a3aSHans de Goede set_link_timer(pmlmeext, 1); 1121554c0a3aSHans de Goede goto authclnt_fail; 1122554c0a3aSHans de Goede } 1123554c0a3aSHans de Goede 1124554c0a3aSHans de Goede if (seq == 2) { 1125554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { 1126554c0a3aSHans de Goede /* legendary shared system */ 1127554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, 1128554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); 1129554c0a3aSHans de Goede 1130554c0a3aSHans de Goede if (p == NULL) { 1131554c0a3aSHans de Goede /* DBG_871X("marc: no challenge text?\n"); */ 1132554c0a3aSHans de Goede goto authclnt_fail; 1133554c0a3aSHans de Goede } 1134554c0a3aSHans de Goede 1135554c0a3aSHans de Goede memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len); 1136554c0a3aSHans de Goede pmlmeinfo->auth_seq = 3; 1137554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 1138554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 1139554c0a3aSHans de Goede 1140554c0a3aSHans de Goede return _SUCCESS; 1141554c0a3aSHans de Goede } else { 1142554c0a3aSHans de Goede /* open system */ 1143554c0a3aSHans de Goede go2asoc = 1; 1144554c0a3aSHans de Goede } 1145554c0a3aSHans de Goede } else if (seq == 4) { 1146554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { 1147554c0a3aSHans de Goede go2asoc = 1; 1148554c0a3aSHans de Goede } else { 1149554c0a3aSHans de Goede goto authclnt_fail; 1150554c0a3aSHans de Goede } 1151554c0a3aSHans de Goede } else { 1152554c0a3aSHans de Goede /* this is also illegal */ 1153554c0a3aSHans de Goede /* DBG_871X("marc: clnt auth failed due to illegal seq =%x\n", seq); */ 1154554c0a3aSHans de Goede goto authclnt_fail; 1155554c0a3aSHans de Goede } 1156554c0a3aSHans de Goede 1157554c0a3aSHans de Goede if (go2asoc) { 1158554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "auth success, start assoc\n"); 1159554c0a3aSHans de Goede start_clnt_assoc(padapter); 1160554c0a3aSHans de Goede return _SUCCESS; 1161554c0a3aSHans de Goede } 1162554c0a3aSHans de Goede 1163554c0a3aSHans de Goede authclnt_fail: 1164554c0a3aSHans de Goede 1165554c0a3aSHans de Goede /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */ 1166554c0a3aSHans de Goede 1167554c0a3aSHans de Goede return _FAIL; 1168554c0a3aSHans de Goede 1169554c0a3aSHans de Goede } 1170554c0a3aSHans de Goede 1171554c0a3aSHans de Goede unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame) 1172554c0a3aSHans de Goede { 117347548aa9SJason Yan u16 capab_info; 1174554c0a3aSHans de Goede struct rtw_ieee802_11_elems elems; 1175554c0a3aSHans de Goede struct sta_info *pstat; 1176554c0a3aSHans de Goede unsigned char reassoc, *p, *pos, *wpa_ie; 1177554c0a3aSHans de Goede unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; 1178554c0a3aSHans de Goede int i, ie_len, wpa_ie_len, left; 1179554c0a3aSHans de Goede unsigned char supportRate[16]; 1180554c0a3aSHans de Goede int supportRateNum; 1181554c0a3aSHans de Goede unsigned short status = _STATS_SUCCESSFUL_; 1182554c0a3aSHans de Goede unsigned short frame_type, ie_offset = 0; 1183554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1184554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 1185554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1186554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1187554c0a3aSHans de Goede struct wlan_bssid_ex *cur = &(pmlmeinfo->network); 1188554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1189554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1190554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1191554c0a3aSHans de Goede 1192554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 1193554c0a3aSHans de Goede return _FAIL; 1194554c0a3aSHans de Goede 1195554c0a3aSHans de Goede frame_type = GetFrameSubType(pframe); 1196554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) { 1197554c0a3aSHans de Goede reassoc = 0; 1198554c0a3aSHans de Goede ie_offset = _ASOCREQ_IE_OFFSET_; 1199554c0a3aSHans de Goede } else { /* WIFI_REASSOCREQ */ 1200554c0a3aSHans de Goede reassoc = 1; 1201554c0a3aSHans de Goede ie_offset = _REASOCREQ_IE_OFFSET_; 1202554c0a3aSHans de Goede } 1203554c0a3aSHans de Goede 1204554c0a3aSHans de Goede 12057d0b4f3cSQuytelda Kahja if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) { 1206554c0a3aSHans de Goede DBG_871X("handle_assoc(reassoc =%d) - too short payload (len =%lu)" 1207554c0a3aSHans de Goede "\n", reassoc, (unsigned long)pkt_len); 1208554c0a3aSHans de Goede return _FAIL; 1209554c0a3aSHans de Goede } 1210554c0a3aSHans de Goede 1211554c0a3aSHans de Goede pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 121241452327SVatsala Narang if (!pstat) { 1213554c0a3aSHans de Goede status = _RSON_CLS2_; 1214554c0a3aSHans de Goede goto asoc_class2_error; 1215554c0a3aSHans de Goede } 1216554c0a3aSHans de Goede 1217d48603afSRoss Schmidt capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN); 1218554c0a3aSHans de Goede /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */ 1219554c0a3aSHans de Goede 12207d0b4f3cSQuytelda Kahja left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset); 12217d0b4f3cSQuytelda Kahja pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset); 1222554c0a3aSHans de Goede 1223554c0a3aSHans de Goede 1224554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1225554c0a3aSHans de Goede 1226554c0a3aSHans de Goede /* check if this stat has been successfully authenticated/assocated */ 1227554c0a3aSHans de Goede if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { 1228554c0a3aSHans de Goede if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { 1229554c0a3aSHans de Goede status = _RSON_CLS2_; 1230554c0a3aSHans de Goede goto asoc_class2_error; 1231554c0a3aSHans de Goede } else { 1232554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); 1233554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_STATE; 1234554c0a3aSHans de Goede } 1235554c0a3aSHans de Goede } else { 1236554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_AUTH_SUCCESS); 1237554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_STATE; 1238554c0a3aSHans de Goede } 1239554c0a3aSHans de Goede 1240554c0a3aSHans de Goede 1241554c0a3aSHans de Goede pstat->capability = capab_info; 1242554c0a3aSHans de Goede 1243554c0a3aSHans de Goede /* now parse all ieee802_11 ie to point to elems */ 1244554c0a3aSHans de Goede if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || 1245554c0a3aSHans de Goede !elems.ssid) { 1246bbda3ac4SRoss Schmidt DBG_871X("STA %pM sent invalid association request\n", 1247554c0a3aSHans de Goede MAC_ARG(pstat->hwaddr)); 1248554c0a3aSHans de Goede status = _STATS_FAILURE_; 1249554c0a3aSHans de Goede goto OnAssocReqFail; 1250554c0a3aSHans de Goede } 1251554c0a3aSHans de Goede 1252554c0a3aSHans de Goede /* now we should check all the fields... */ 1253554c0a3aSHans de Goede /* checking SSID */ 1254554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len, 1255554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1256554c0a3aSHans de Goede 12576493a78fSAymen Qader if (!p || ie_len == 0) { 12586493a78fSAymen Qader /* broadcast ssid, however it is not allowed in assocreq */ 1259554c0a3aSHans de Goede status = _STATS_FAILURE_; 12606493a78fSAymen Qader goto OnAssocReqFail; 12616493a78fSAymen Qader } else { 1262554c0a3aSHans de Goede /* check if ssid match */ 1263554c0a3aSHans de Goede if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength)) 1264554c0a3aSHans de Goede status = _STATS_FAILURE_; 1265554c0a3aSHans de Goede 1266554c0a3aSHans de Goede if (ie_len != cur->Ssid.SsidLength) 1267554c0a3aSHans de Goede status = _STATS_FAILURE_; 1268554c0a3aSHans de Goede } 1269554c0a3aSHans de Goede 12705706396fSVatsala Narang if (status != _STATS_SUCCESSFUL_) 1271554c0a3aSHans de Goede goto OnAssocReqFail; 1272554c0a3aSHans de Goede 1273554c0a3aSHans de Goede /* check if the supported rate is ok */ 1274554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1275554c0a3aSHans de Goede if (p == NULL) { 1276554c0a3aSHans de Goede DBG_871X("Rx a sta assoc-req which supported rate is empty!\n"); 1277554c0a3aSHans de Goede /* use our own rate set as statoin used */ 1278554c0a3aSHans de Goede /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ 1279554c0a3aSHans de Goede /* supportRateNum = AP_BSSRATE_LEN; */ 1280554c0a3aSHans de Goede 1281554c0a3aSHans de Goede status = _STATS_FAILURE_; 1282554c0a3aSHans de Goede goto OnAssocReqFail; 1283554c0a3aSHans de Goede } else { 1284554c0a3aSHans de Goede memcpy(supportRate, p+2, ie_len); 1285554c0a3aSHans de Goede supportRateNum = ie_len; 1286554c0a3aSHans de Goede 1287554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len, 1288554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1289554c0a3aSHans de Goede if (p != NULL) { 1290554c0a3aSHans de Goede 1291554c0a3aSHans de Goede if (supportRateNum <= sizeof(supportRate)) { 1292554c0a3aSHans de Goede memcpy(supportRate+supportRateNum, p+2, ie_len); 1293554c0a3aSHans de Goede supportRateNum += ie_len; 1294554c0a3aSHans de Goede } 1295554c0a3aSHans de Goede } 1296554c0a3aSHans de Goede } 1297554c0a3aSHans de Goede 1298554c0a3aSHans de Goede /* todo: mask supportRate between AP & STA -> move to update raid */ 1299554c0a3aSHans de Goede /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ 1300554c0a3aSHans de Goede 1301554c0a3aSHans de Goede /* update station supportRate */ 1302554c0a3aSHans de Goede pstat->bssratelen = supportRateNum; 1303554c0a3aSHans de Goede memcpy(pstat->bssrateset, supportRate, supportRateNum); 1304554c0a3aSHans de Goede UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen); 1305554c0a3aSHans de Goede 1306554c0a3aSHans de Goede /* check RSN/WPA/WPS */ 1307554c0a3aSHans de Goede pstat->dot8021xalg = 0; 1308554c0a3aSHans de Goede pstat->wpa_psk = 0; 1309554c0a3aSHans de Goede pstat->wpa_group_cipher = 0; 1310554c0a3aSHans de Goede pstat->wpa2_group_cipher = 0; 1311554c0a3aSHans de Goede pstat->wpa_pairwise_cipher = 0; 1312554c0a3aSHans de Goede pstat->wpa2_pairwise_cipher = 0; 1313554c0a3aSHans de Goede memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); 1314554c0a3aSHans de Goede if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) { 1315554c0a3aSHans de Goede 1316554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 1317554c0a3aSHans de Goede 1318554c0a3aSHans de Goede wpa_ie = elems.rsn_ie; 1319554c0a3aSHans de Goede wpa_ie_len = elems.rsn_ie_len; 1320554c0a3aSHans de Goede 1321554c0a3aSHans de Goede if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 1322554c0a3aSHans de Goede pstat->dot8021xalg = 1;/* psk, todo:802.1x */ 1323554c0a3aSHans de Goede pstat->wpa_psk |= BIT(1); 1324554c0a3aSHans de Goede 1325554c0a3aSHans de Goede pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher; 1326554c0a3aSHans de Goede pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher; 1327554c0a3aSHans de Goede 1328554c0a3aSHans de Goede if (!pstat->wpa2_group_cipher) 1329554c0a3aSHans de Goede status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; 1330554c0a3aSHans de Goede 1331554c0a3aSHans de Goede if (!pstat->wpa2_pairwise_cipher) 1332554c0a3aSHans de Goede status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 1333554c0a3aSHans de Goede } else { 1334554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1335554c0a3aSHans de Goede } 1336554c0a3aSHans de Goede 1337554c0a3aSHans de Goede } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) { 1338554c0a3aSHans de Goede 1339554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 1340554c0a3aSHans de Goede 1341554c0a3aSHans de Goede wpa_ie = elems.wpa_ie; 1342554c0a3aSHans de Goede wpa_ie_len = elems.wpa_ie_len; 1343554c0a3aSHans de Goede 1344554c0a3aSHans de Goede if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 1345554c0a3aSHans de Goede pstat->dot8021xalg = 1;/* psk, todo:802.1x */ 1346554c0a3aSHans de Goede pstat->wpa_psk |= BIT(0); 1347554c0a3aSHans de Goede 1348554c0a3aSHans de Goede pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher; 1349554c0a3aSHans de Goede pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher; 1350554c0a3aSHans de Goede 1351554c0a3aSHans de Goede if (!pstat->wpa_group_cipher) 1352554c0a3aSHans de Goede status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; 1353554c0a3aSHans de Goede 1354554c0a3aSHans de Goede if (!pstat->wpa_pairwise_cipher) 1355554c0a3aSHans de Goede status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 1356554c0a3aSHans de Goede 1357554c0a3aSHans de Goede } else { 1358554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1359554c0a3aSHans de Goede } 1360554c0a3aSHans de Goede 1361554c0a3aSHans de Goede } else { 1362554c0a3aSHans de Goede wpa_ie = NULL; 1363554c0a3aSHans de Goede wpa_ie_len = 0; 1364554c0a3aSHans de Goede } 1365554c0a3aSHans de Goede 13665706396fSVatsala Narang if (status != _STATS_SUCCESSFUL_) 1367554c0a3aSHans de Goede goto OnAssocReqFail; 1368554c0a3aSHans de Goede 1369554c0a3aSHans de Goede pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); 137041452327SVatsala Narang if (!wpa_ie) { 1371554c0a3aSHans de Goede if (elems.wps_ie) { 1372554c0a3aSHans de Goede DBG_871X("STA included WPS IE in " 1373554c0a3aSHans de Goede "(Re)Association Request - assume WPS is " 1374554c0a3aSHans de Goede "used\n"); 1375554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WPS; 1376554c0a3aSHans de Goede /* wpabuf_free(sta->wps_ie); */ 1377554c0a3aSHans de Goede /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ 1378554c0a3aSHans de Goede /* elems.wps_ie_len - 4); */ 1379554c0a3aSHans de Goede } else { 1380554c0a3aSHans de Goede DBG_871X("STA did not include WPA/RSN IE " 1381554c0a3aSHans de Goede "in (Re)Association Request - possible WPS " 1382554c0a3aSHans de Goede "use\n"); 1383554c0a3aSHans de Goede pstat->flags |= WLAN_STA_MAYBE_WPS; 1384554c0a3aSHans de Goede } 1385554c0a3aSHans de Goede 1386554c0a3aSHans de Goede 1387554c0a3aSHans de Goede /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ 1388554c0a3aSHans de Goede /* that the selected registrar of AP is _FLASE */ 1389554c0a3aSHans de Goede if ((psecuritypriv->wpa_psk > 0) 1390554c0a3aSHans de Goede && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) { 1391554c0a3aSHans de Goede if (pmlmepriv->wps_beacon_ie) { 1392554c0a3aSHans de Goede u8 selected_registrar = 0; 1393554c0a3aSHans de Goede 1394554c0a3aSHans de Goede rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); 1395554c0a3aSHans de Goede 1396554c0a3aSHans de Goede if (!selected_registrar) { 1397554c0a3aSHans de Goede DBG_871X("selected_registrar is false , or AP is not ready to do WPS\n"); 1398554c0a3aSHans de Goede 1399554c0a3aSHans de Goede status = _STATS_UNABLE_HANDLE_STA_; 1400554c0a3aSHans de Goede 1401554c0a3aSHans de Goede goto OnAssocReqFail; 1402554c0a3aSHans de Goede } 1403554c0a3aSHans de Goede } 1404554c0a3aSHans de Goede } 1405554c0a3aSHans de Goede 1406554c0a3aSHans de Goede } else { 1407554c0a3aSHans de Goede int copy_len; 1408554c0a3aSHans de Goede 1409554c0a3aSHans de Goede if (psecuritypriv->wpa_psk == 0) { 1410bbda3ac4SRoss Schmidt DBG_871X("STA %pM: WPA/RSN IE in association " 1411554c0a3aSHans de Goede "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr)); 1412554c0a3aSHans de Goede 1413554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1414554c0a3aSHans de Goede 1415554c0a3aSHans de Goede goto OnAssocReqFail; 1416554c0a3aSHans de Goede 1417554c0a3aSHans de Goede } 1418554c0a3aSHans de Goede 1419554c0a3aSHans de Goede if (elems.wps_ie) { 1420554c0a3aSHans de Goede DBG_871X("STA included WPS IE in " 1421554c0a3aSHans de Goede "(Re)Association Request - WPS is " 1422554c0a3aSHans de Goede "used\n"); 1423554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WPS; 1424554c0a3aSHans de Goede copy_len = 0; 1425554c0a3aSHans de Goede } else { 1426554c0a3aSHans de Goede copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2); 1427554c0a3aSHans de Goede } 1428554c0a3aSHans de Goede 1429554c0a3aSHans de Goede 1430554c0a3aSHans de Goede if (copy_len > 0) 1431554c0a3aSHans de Goede memcpy(pstat->wpa_ie, wpa_ie-2, copy_len); 1432554c0a3aSHans de Goede 1433554c0a3aSHans de Goede } 1434554c0a3aSHans de Goede 1435554c0a3aSHans de Goede 1436554c0a3aSHans de Goede /* check if there is WMM IE & support WWM-PS */ 1437554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_WME; 1438554c0a3aSHans de Goede pstat->qos_option = 0; 1439554c0a3aSHans de Goede pstat->qos_info = 0; 1440554c0a3aSHans de Goede pstat->has_legacy_ac = true; 1441554c0a3aSHans de Goede pstat->uapsd_vo = 0; 1442554c0a3aSHans de Goede pstat->uapsd_vi = 0; 1443554c0a3aSHans de Goede pstat->uapsd_be = 0; 1444554c0a3aSHans de Goede pstat->uapsd_bk = 0; 1445554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option) { 1446554c0a3aSHans de Goede p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0; 1447554c0a3aSHans de Goede for (;;) { 1448554c0a3aSHans de Goede p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); 144934557e23SIzabela Bakollari if (p) { 1450554c0a3aSHans de Goede if (!memcmp(p+2, WMM_IE, 6)) { 1451554c0a3aSHans de Goede 1452554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WME; 1453554c0a3aSHans de Goede 1454554c0a3aSHans de Goede pstat->qos_option = 1; 1455554c0a3aSHans de Goede pstat->qos_info = *(p+8); 1456554c0a3aSHans de Goede 1457554c0a3aSHans de Goede pstat->max_sp_len = (pstat->qos_info>>5)&0x3; 1458554c0a3aSHans de Goede 1459554c0a3aSHans de Goede if ((pstat->qos_info&0xf) != 0xf) 1460554c0a3aSHans de Goede pstat->has_legacy_ac = true; 1461554c0a3aSHans de Goede else 1462554c0a3aSHans de Goede pstat->has_legacy_ac = false; 1463554c0a3aSHans de Goede 1464554c0a3aSHans de Goede if (pstat->qos_info&0xf) { 1465554c0a3aSHans de Goede if (pstat->qos_info&BIT(0)) 1466554c0a3aSHans de Goede pstat->uapsd_vo = BIT(0)|BIT(1); 1467554c0a3aSHans de Goede else 1468554c0a3aSHans de Goede pstat->uapsd_vo = 0; 1469554c0a3aSHans de Goede 1470554c0a3aSHans de Goede if (pstat->qos_info&BIT(1)) 1471554c0a3aSHans de Goede pstat->uapsd_vi = BIT(0)|BIT(1); 1472554c0a3aSHans de Goede else 1473554c0a3aSHans de Goede pstat->uapsd_vi = 0; 1474554c0a3aSHans de Goede 1475554c0a3aSHans de Goede if (pstat->qos_info&BIT(2)) 1476554c0a3aSHans de Goede pstat->uapsd_bk = BIT(0)|BIT(1); 1477554c0a3aSHans de Goede else 1478554c0a3aSHans de Goede pstat->uapsd_bk = 0; 1479554c0a3aSHans de Goede 1480554c0a3aSHans de Goede if (pstat->qos_info&BIT(3)) 1481554c0a3aSHans de Goede pstat->uapsd_be = BIT(0)|BIT(1); 1482554c0a3aSHans de Goede else 1483554c0a3aSHans de Goede pstat->uapsd_be = 0; 1484554c0a3aSHans de Goede 1485554c0a3aSHans de Goede } 1486554c0a3aSHans de Goede 1487554c0a3aSHans de Goede break; 1488554c0a3aSHans de Goede } 1489554c0a3aSHans de Goede } else { 1490554c0a3aSHans de Goede break; 1491554c0a3aSHans de Goede } 1492554c0a3aSHans de Goede p = p + ie_len + 2; 1493554c0a3aSHans de Goede } 1494554c0a3aSHans de Goede } 1495554c0a3aSHans de Goede 1496554c0a3aSHans de Goede /* save HT capabilities in the sta object */ 1497c25d8a7dSRoss Schmidt memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); 1498c25d8a7dSRoss Schmidt if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) { 1499554c0a3aSHans de Goede pstat->flags |= WLAN_STA_HT; 1500554c0a3aSHans de Goede 1501554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WME; 1502554c0a3aSHans de Goede 1503c25d8a7dSRoss Schmidt memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap)); 1504554c0a3aSHans de Goede 1505554c0a3aSHans de Goede } else 1506554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_HT; 1507554c0a3aSHans de Goede 1508554c0a3aSHans de Goede 1509554c0a3aSHans de Goede if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) { 1510554c0a3aSHans de Goede status = _STATS_FAILURE_; 1511554c0a3aSHans de Goede goto OnAssocReqFail; 1512554c0a3aSHans de Goede } 1513554c0a3aSHans de Goede 1514554c0a3aSHans de Goede 1515554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_HT) && 1516554c0a3aSHans de Goede ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || 1517554c0a3aSHans de Goede (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) { 1518bbda3ac4SRoss Schmidt DBG_871X("HT: %pM tried to use TKIP with HT association\n", MAC_ARG(pstat->hwaddr)); 1519554c0a3aSHans de Goede 1520554c0a3aSHans de Goede /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */ 1521554c0a3aSHans de Goede /* goto OnAssocReqFail; */ 1522554c0a3aSHans de Goede } 1523554c0a3aSHans de Goede pstat->flags |= WLAN_STA_NONERP; 1524554c0a3aSHans de Goede for (i = 0; i < pstat->bssratelen; i++) { 1525554c0a3aSHans de Goede if ((pstat->bssrateset[i] & 0x7f) > 22) { 1526554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_NONERP; 1527554c0a3aSHans de Goede break; 1528554c0a3aSHans de Goede } 1529554c0a3aSHans de Goede } 1530554c0a3aSHans de Goede 1531554c0a3aSHans de Goede if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) 1532554c0a3aSHans de Goede pstat->flags |= WLAN_STA_SHORT_PREAMBLE; 1533554c0a3aSHans de Goede else 1534554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; 1535554c0a3aSHans de Goede 1536554c0a3aSHans de Goede 1537554c0a3aSHans de Goede 1538554c0a3aSHans de Goede if (status != _STATS_SUCCESSFUL_) 1539554c0a3aSHans de Goede goto OnAssocReqFail; 1540554c0a3aSHans de Goede 1541554c0a3aSHans de Goede /* TODO: identify_proprietary_vendor_ie(); */ 1542554c0a3aSHans de Goede /* Realtek proprietary IE */ 1543554c0a3aSHans de Goede /* identify if this is Broadcom sta */ 1544554c0a3aSHans de Goede /* identify if this is ralink sta */ 1545554c0a3aSHans de Goede /* Customer proprietary IE */ 1546554c0a3aSHans de Goede 1547554c0a3aSHans de Goede 1548554c0a3aSHans de Goede 1549554c0a3aSHans de Goede /* get a unique AID */ 1550554c0a3aSHans de Goede if (pstat->aid > 0) { 1551554c0a3aSHans de Goede DBG_871X(" old AID %d\n", pstat->aid); 1552554c0a3aSHans de Goede } else { 155387e4a540SYoung Xiao for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) 1554554c0a3aSHans de Goede if (pstapriv->sta_aid[pstat->aid - 1] == NULL) 1555554c0a3aSHans de Goede break; 1556554c0a3aSHans de Goede 1557554c0a3aSHans de Goede /* if (pstat->aid > NUM_STA) { */ 1558554c0a3aSHans de Goede if (pstat->aid > pstapriv->max_num_sta) { 1559554c0a3aSHans de Goede 1560554c0a3aSHans de Goede pstat->aid = 0; 1561554c0a3aSHans de Goede 1562554c0a3aSHans de Goede DBG_871X(" no room for more AIDs\n"); 1563554c0a3aSHans de Goede 1564554c0a3aSHans de Goede status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 1565554c0a3aSHans de Goede 1566554c0a3aSHans de Goede goto OnAssocReqFail; 1567554c0a3aSHans de Goede 1568554c0a3aSHans de Goede 1569554c0a3aSHans de Goede } else { 1570554c0a3aSHans de Goede pstapriv->sta_aid[pstat->aid - 1] = pstat; 1571554c0a3aSHans de Goede DBG_871X("allocate new AID = (%d)\n", pstat->aid); 1572554c0a3aSHans de Goede } 1573554c0a3aSHans de Goede } 1574554c0a3aSHans de Goede 1575554c0a3aSHans de Goede 1576554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_ASSOC_STATE); 1577554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_SUCCESS; 1578554c0a3aSHans de Goede 1579554c0a3aSHans de Goede spin_lock_bh(&pstapriv->auth_list_lock); 1580554c0a3aSHans de Goede if (!list_empty(&pstat->auth_list)) { 1581554c0a3aSHans de Goede list_del_init(&pstat->auth_list); 1582554c0a3aSHans de Goede pstapriv->auth_list_cnt--; 1583554c0a3aSHans de Goede } 1584554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->auth_list_lock); 1585554c0a3aSHans de Goede 1586554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1587554c0a3aSHans de Goede if (list_empty(&pstat->asoc_list)) { 1588554c0a3aSHans de Goede pstat->expire_to = pstapriv->expire_to; 1589554c0a3aSHans de Goede list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); 1590554c0a3aSHans de Goede pstapriv->asoc_list_cnt++; 1591554c0a3aSHans de Goede } 1592554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1593554c0a3aSHans de Goede 1594554c0a3aSHans de Goede /* now the station is qualified to join our BSS... */ 1595554c0a3aSHans de Goede if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) { 1596554c0a3aSHans de Goede /* 1 bss_cap_update & sta_info_update */ 1597554c0a3aSHans de Goede bss_cap_update_on_sta_join(padapter, pstat); 1598554c0a3aSHans de Goede sta_info_update(padapter, pstat); 1599554c0a3aSHans de Goede 1600554c0a3aSHans de Goede /* 2 issue assoc rsp before notify station join event. */ 1601554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) 1602554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); 1603554c0a3aSHans de Goede else 1604554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); 1605554c0a3aSHans de Goede 1606554c0a3aSHans de Goede spin_lock_bh(&pstat->lock); 1607554c0a3aSHans de Goede if (pstat->passoc_req) { 1608554c0a3aSHans de Goede kfree(pstat->passoc_req); 1609554c0a3aSHans de Goede pstat->passoc_req = NULL; 1610554c0a3aSHans de Goede pstat->assoc_req_len = 0; 1611554c0a3aSHans de Goede } 1612554c0a3aSHans de Goede 1613554c0a3aSHans de Goede pstat->passoc_req = rtw_zmalloc(pkt_len); 1614554c0a3aSHans de Goede if (pstat->passoc_req) { 1615554c0a3aSHans de Goede memcpy(pstat->passoc_req, pframe, pkt_len); 1616554c0a3aSHans de Goede pstat->assoc_req_len = pkt_len; 1617554c0a3aSHans de Goede } 1618554c0a3aSHans de Goede spin_unlock_bh(&pstat->lock); 1619554c0a3aSHans de Goede 1620554c0a3aSHans de Goede /* 3-(1) report sta add event */ 1621554c0a3aSHans de Goede report_add_sta_event(padapter, pstat->hwaddr, pstat->aid); 1622554c0a3aSHans de Goede } 1623554c0a3aSHans de Goede 1624554c0a3aSHans de Goede return _SUCCESS; 1625554c0a3aSHans de Goede 1626554c0a3aSHans de Goede asoc_class2_error: 1627554c0a3aSHans de Goede 1628554c0a3aSHans de Goede issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status); 1629554c0a3aSHans de Goede 1630554c0a3aSHans de Goede return _FAIL; 1631554c0a3aSHans de Goede 1632554c0a3aSHans de Goede OnAssocReqFail: 1633554c0a3aSHans de Goede 1634554c0a3aSHans de Goede pstat->aid = 0; 1635554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) 1636554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); 1637554c0a3aSHans de Goede else 1638554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); 1639554c0a3aSHans de Goede 1640554c0a3aSHans de Goede return _FAIL; 1641554c0a3aSHans de Goede } 1642554c0a3aSHans de Goede 1643554c0a3aSHans de Goede unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame) 1644554c0a3aSHans de Goede { 1645554c0a3aSHans de Goede uint i; 1646554c0a3aSHans de Goede int res; 1647554c0a3aSHans de Goede unsigned short status; 1648554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 1649554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1650554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1651554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1652554c0a3aSHans de Goede /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */ 1653554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1654554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1655554c0a3aSHans de Goede 1656554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1657554c0a3aSHans de Goede 1658554c0a3aSHans de Goede /* check A1 matches or not */ 1659554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) 1660554c0a3aSHans de Goede return _SUCCESS; 1661554c0a3aSHans de Goede 1662554c0a3aSHans de Goede if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) 1663554c0a3aSHans de Goede return _SUCCESS; 1664554c0a3aSHans de Goede 1665554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) 1666554c0a3aSHans de Goede return _SUCCESS; 1667554c0a3aSHans de Goede 1668554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 1669554c0a3aSHans de Goede 1670554c0a3aSHans de Goede /* status */ 1671554c0a3aSHans de Goede status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2)); 1672554c0a3aSHans de Goede if (status > 0) { 1673554c0a3aSHans de Goede DBG_871X("assoc reject, status code: %d\n", status); 1674554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 1675554c0a3aSHans de Goede res = -4; 1676554c0a3aSHans de Goede goto report_assoc_result; 1677554c0a3aSHans de Goede } 1678554c0a3aSHans de Goede 1679554c0a3aSHans de Goede /* get capabilities */ 1680554c0a3aSHans de Goede pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1681554c0a3aSHans de Goede 1682554c0a3aSHans de Goede /* set slot time */ 1683554c0a3aSHans de Goede pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20; 1684554c0a3aSHans de Goede 1685554c0a3aSHans de Goede /* AID */ 1686554c0a3aSHans de Goede res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff); 1687554c0a3aSHans de Goede 1688554c0a3aSHans de Goede /* following are moved to join event callback function */ 1689554c0a3aSHans de Goede /* to handle HT, WMM, rate adaptive, update MAC reg */ 1690554c0a3aSHans de Goede /* for not to handle the synchronous IO in the tasklet */ 1691554c0a3aSHans de Goede for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) { 1692554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pframe + i); 1693554c0a3aSHans de Goede 1694554c0a3aSHans de Goede switch (pIE->ElementID) { 1695554c0a3aSHans de Goede case _VENDOR_SPECIFIC_IE_: 1696554c0a3aSHans de Goede if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */ 1697554c0a3aSHans de Goede WMM_param_handler(padapter, pIE); 1698554c0a3aSHans de Goede break; 1699554c0a3aSHans de Goede 1700554c0a3aSHans de Goede case _HT_CAPABILITY_IE_: /* HT caps */ 1701554c0a3aSHans de Goede HT_caps_handler(padapter, pIE); 1702554c0a3aSHans de Goede break; 1703554c0a3aSHans de Goede 1704554c0a3aSHans de Goede case _HT_EXTRA_INFO_IE_: /* HT info */ 1705554c0a3aSHans de Goede HT_info_handler(padapter, pIE); 1706554c0a3aSHans de Goede break; 1707554c0a3aSHans de Goede 1708554c0a3aSHans de Goede case _ERPINFO_IE_: 1709554c0a3aSHans de Goede ERP_IE_handler(padapter, pIE); 1710554c0a3aSHans de Goede 1711554c0a3aSHans de Goede default: 1712554c0a3aSHans de Goede break; 1713554c0a3aSHans de Goede } 1714554c0a3aSHans de Goede 1715554c0a3aSHans de Goede i += (pIE->Length + 2); 1716554c0a3aSHans de Goede } 1717554c0a3aSHans de Goede 1718554c0a3aSHans de Goede pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE); 1719554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 1720554c0a3aSHans de Goede 1721554c0a3aSHans de Goede /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ 1722554c0a3aSHans de Goede UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates); 1723554c0a3aSHans de Goede 1724554c0a3aSHans de Goede report_assoc_result: 1725554c0a3aSHans de Goede if (res > 0) { 1726554c0a3aSHans de Goede rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len); 1727554c0a3aSHans de Goede } else { 1728554c0a3aSHans de Goede rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len); 1729554c0a3aSHans de Goede } 1730554c0a3aSHans de Goede 1731554c0a3aSHans de Goede report_join_res(padapter, res); 1732554c0a3aSHans de Goede 1733554c0a3aSHans de Goede return _SUCCESS; 1734554c0a3aSHans de Goede } 1735554c0a3aSHans de Goede 1736554c0a3aSHans de Goede unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame) 1737554c0a3aSHans de Goede { 1738554c0a3aSHans de Goede unsigned short reason; 1739554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1740554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1741554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1742554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1743554c0a3aSHans de Goede 1744554c0a3aSHans de Goede /* check A3 */ 1745554c0a3aSHans de Goede if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) 1746554c0a3aSHans de Goede return _SUCCESS; 1747554c0a3aSHans de Goede 1748554c0a3aSHans de Goede reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1749554c0a3aSHans de Goede 1750554c0a3aSHans de Goede DBG_871X("%s Reason code(%d)\n", __func__, reason); 1751554c0a3aSHans de Goede 17520ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1753554c0a3aSHans de Goede struct sta_info *psta; 1754554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1755554c0a3aSHans de Goede 1756554c0a3aSHans de Goede /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ 1757554c0a3aSHans de Goede /* rtw_free_stainfo(padapter, psta); */ 1758554c0a3aSHans de Goede /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ 1759554c0a3aSHans de Goede 1760554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n", 1761554c0a3aSHans de Goede reason, GetAddr2Ptr(pframe)); 1762554c0a3aSHans de Goede 1763554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1764554c0a3aSHans de Goede if (psta) { 1765554c0a3aSHans de Goede u8 updated = false; 1766554c0a3aSHans de Goede 1767554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1768554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) == false) { 1769554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 1770554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 1771554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, false, reason); 1772554c0a3aSHans de Goede 1773554c0a3aSHans de Goede } 1774554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1775554c0a3aSHans de Goede 1776554c0a3aSHans de Goede associated_clients_update(padapter, updated); 1777554c0a3aSHans de Goede } 1778554c0a3aSHans de Goede 1779554c0a3aSHans de Goede 1780554c0a3aSHans de Goede return _SUCCESS; 1781554c0a3aSHans de Goede } else { 1782554c0a3aSHans de Goede int ignore_received_deauth = 0; 1783554c0a3aSHans de Goede 1784554c0a3aSHans de Goede /* Commented by Albert 20130604 */ 1785554c0a3aSHans de Goede /* Before sending the auth frame to start the STA/GC mode connection with AP/GO, */ 1786554c0a3aSHans de Goede /* we will send the deauth first. */ 1787554c0a3aSHans de Goede /* However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */ 1788554c0a3aSHans de Goede /* Added the following code to avoid this case. */ 1789554c0a3aSHans de Goede if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) || 1790554c0a3aSHans de Goede (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) { 1791554c0a3aSHans de Goede if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) { 1792554c0a3aSHans de Goede ignore_received_deauth = 1; 1793554c0a3aSHans de Goede } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) { 1794554c0a3aSHans de Goede /* TODO: 802.11r */ 1795554c0a3aSHans de Goede ignore_received_deauth = 1; 1796554c0a3aSHans de Goede } 1797554c0a3aSHans de Goede } 1798554c0a3aSHans de Goede 1799554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n", 1800554c0a3aSHans de Goede reason, GetAddr3Ptr(pframe), ignore_received_deauth); 1801554c0a3aSHans de Goede 1802554c0a3aSHans de Goede if (0 == ignore_received_deauth) { 1803554c0a3aSHans de Goede receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); 1804554c0a3aSHans de Goede } 1805554c0a3aSHans de Goede } 1806554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = false; 1807554c0a3aSHans de Goede return _SUCCESS; 1808554c0a3aSHans de Goede 1809554c0a3aSHans de Goede } 1810554c0a3aSHans de Goede 1811554c0a3aSHans de Goede unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame) 1812554c0a3aSHans de Goede { 1813554c0a3aSHans de Goede unsigned short reason; 1814554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1815554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1816554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1817554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1818554c0a3aSHans de Goede 1819554c0a3aSHans de Goede /* check A3 */ 1820554c0a3aSHans de Goede if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) 1821554c0a3aSHans de Goede return _SUCCESS; 1822554c0a3aSHans de Goede 1823554c0a3aSHans de Goede reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1824554c0a3aSHans de Goede 1825554c0a3aSHans de Goede DBG_871X("%s Reason code(%d)\n", __func__, reason); 1826554c0a3aSHans de Goede 18270ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1828554c0a3aSHans de Goede struct sta_info *psta; 1829554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1830554c0a3aSHans de Goede 1831554c0a3aSHans de Goede /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ 1832554c0a3aSHans de Goede /* rtw_free_stainfo(padapter, psta); */ 1833554c0a3aSHans de Goede /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ 1834554c0a3aSHans de Goede 1835554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", 1836554c0a3aSHans de Goede reason, GetAddr2Ptr(pframe)); 1837554c0a3aSHans de Goede 1838554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1839554c0a3aSHans de Goede if (psta) { 1840554c0a3aSHans de Goede u8 updated = false; 1841554c0a3aSHans de Goede 1842554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1843554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) == false) { 1844554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 1845554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 1846554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, false, reason); 1847554c0a3aSHans de Goede 1848554c0a3aSHans de Goede } 1849554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1850554c0a3aSHans de Goede 1851554c0a3aSHans de Goede associated_clients_update(padapter, updated); 1852554c0a3aSHans de Goede } 1853554c0a3aSHans de Goede 1854554c0a3aSHans de Goede return _SUCCESS; 1855554c0a3aSHans de Goede } else { 1856554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "sta recv disassoc reason code(%d) sta:%pM\n", 1857554c0a3aSHans de Goede reason, GetAddr3Ptr(pframe)); 1858554c0a3aSHans de Goede 1859554c0a3aSHans de Goede receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); 1860554c0a3aSHans de Goede } 1861554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = false; 1862554c0a3aSHans de Goede return _SUCCESS; 1863554c0a3aSHans de Goede 1864554c0a3aSHans de Goede } 1865554c0a3aSHans de Goede 1866554c0a3aSHans de Goede unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame) 1867554c0a3aSHans de Goede { 1868554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1869554c0a3aSHans de Goede return _SUCCESS; 1870554c0a3aSHans de Goede } 1871554c0a3aSHans de Goede 1872554c0a3aSHans de Goede unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame) 1873554c0a3aSHans de Goede { 1874554c0a3aSHans de Goede struct sta_info *psta = NULL; 1875554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1876554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1877554c0a3aSHans de Goede u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1878554c0a3aSHans de Goede u8 category; 1879554c0a3aSHans de Goede u8 action; 1880554c0a3aSHans de Goede 1881554c0a3aSHans de Goede DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); 1882554c0a3aSHans de Goede 1883554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1884554c0a3aSHans de Goede 1885554c0a3aSHans de Goede if (!psta) 1886554c0a3aSHans de Goede goto exit; 1887554c0a3aSHans de Goede 1888554c0a3aSHans de Goede category = frame_body[0]; 1889554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT) 1890554c0a3aSHans de Goede goto exit; 1891554c0a3aSHans de Goede 1892554c0a3aSHans de Goede action = frame_body[1]; 1893554c0a3aSHans de Goede switch (action) { 189472cac683SRoss Schmidt case WLAN_ACTION_SPCT_MSR_REQ: 189572cac683SRoss Schmidt case WLAN_ACTION_SPCT_MSR_RPRT: 189672cac683SRoss Schmidt case WLAN_ACTION_SPCT_TPC_REQ: 189772cac683SRoss Schmidt case WLAN_ACTION_SPCT_TPC_RPRT: 189872cac683SRoss Schmidt case WLAN_ACTION_SPCT_CHL_SWITCH: 1899554c0a3aSHans de Goede break; 1900554c0a3aSHans de Goede default: 1901554c0a3aSHans de Goede break; 1902554c0a3aSHans de Goede } 1903554c0a3aSHans de Goede 1904554c0a3aSHans de Goede exit: 19051c4bfacfSHariprasad Kelam return _FAIL; 1906554c0a3aSHans de Goede } 1907554c0a3aSHans de Goede 1908554c0a3aSHans de Goede unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame) 1909554c0a3aSHans de Goede { 1910554c0a3aSHans de Goede u8 *addr; 1911554c0a3aSHans de Goede struct sta_info *psta = NULL; 1912554c0a3aSHans de Goede struct recv_reorder_ctrl *preorder_ctrl; 1913554c0a3aSHans de Goede unsigned char *frame_body; 1914554c0a3aSHans de Goede unsigned char category, action; 1915554c0a3aSHans de Goede unsigned short tid, status, reason_code = 0; 1916554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1917554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1918554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1919554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1920554c0a3aSHans de Goede 1921554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1922554c0a3aSHans de Goede 1923554c0a3aSHans de Goede /* check RA matches or not */ 1924554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */ 1925554c0a3aSHans de Goede return _SUCCESS; 1926554c0a3aSHans de Goede 1927554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 1928554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) 1929554c0a3aSHans de Goede return _SUCCESS; 1930554c0a3aSHans de Goede 1931554c0a3aSHans de Goede addr = GetAddr2Ptr(pframe); 1932554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, addr); 1933554c0a3aSHans de Goede 193441452327SVatsala Narang if (!psta) 1935554c0a3aSHans de Goede return _SUCCESS; 1936554c0a3aSHans de Goede 1937554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1938554c0a3aSHans de Goede 1939554c0a3aSHans de Goede category = frame_body[0]; 1940554c0a3aSHans de Goede if (category == RTW_WLAN_CATEGORY_BACK) {/* representing Block Ack */ 1941a65f0d18SVatsala Narang if (!pmlmeinfo->HT_enable) 1942554c0a3aSHans de Goede return _SUCCESS; 1943554c0a3aSHans de Goede 1944554c0a3aSHans de Goede action = frame_body[1]; 1945554c0a3aSHans de Goede DBG_871X("%s, action =%d\n", __func__, action); 1946554c0a3aSHans de Goede switch (action) { 1947*f4acd33cSRoss Schmidt case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ 1948554c0a3aSHans de Goede 1949554c0a3aSHans de Goede memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); 1950554c0a3aSHans de Goede /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */ 1951554c0a3aSHans de Goede process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); 1952554c0a3aSHans de Goede 19532646633fSAastha Gupta if (pmlmeinfo->accept_addba_req) { 1954*f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 0); 1955554c0a3aSHans de Goede } else { 1956*f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ 1957554c0a3aSHans de Goede } 1958554c0a3aSHans de Goede 1959554c0a3aSHans de Goede break; 1960554c0a3aSHans de Goede 1961*f4acd33cSRoss Schmidt case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ 1962d48603afSRoss Schmidt status = get_unaligned_le16(&frame_body[3]); 1963554c0a3aSHans de Goede tid = ((frame_body[5] >> 2) & 0x7); 1964554c0a3aSHans de Goede 1965554c0a3aSHans de Goede if (status == 0) { 1966554c0a3aSHans de Goede /* successful */ 1967554c0a3aSHans de Goede DBG_871X("agg_enable for TID =%d\n", tid); 1968e52d8d0dSVatsala Narang psta->htpriv.agg_enable_bitmap |= BIT(tid); 1969554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); 1970554c0a3aSHans de Goede } else { 1971554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 1972554c0a3aSHans de Goede } 1973554c0a3aSHans de Goede 1974554c0a3aSHans de Goede if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { 1975554c0a3aSHans de Goede DBG_871X("%s alive check - rx ADDBA response\n", __func__); 1976554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 1977554c0a3aSHans de Goede psta->expire_to = pstapriv->expire_to; 1978554c0a3aSHans de Goede psta->state ^= WIFI_STA_ALIVE_CHK_STATE; 1979554c0a3aSHans de Goede } 1980554c0a3aSHans de Goede 1981554c0a3aSHans de Goede /* DBG_871X("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap); */ 1982554c0a3aSHans de Goede break; 1983554c0a3aSHans de Goede 1984*f4acd33cSRoss Schmidt case WLAN_ACTION_DELBA: /* DELBA */ 1985554c0a3aSHans de Goede if ((frame_body[3] & BIT(3)) == 0) { 1986e52d8d0dSVatsala Narang psta->htpriv.agg_enable_bitmap &= 1987e52d8d0dSVatsala Narang ~BIT((frame_body[3] >> 4) & 0xf); 1988e52d8d0dSVatsala Narang psta->htpriv.candidate_tid_bitmap &= 1989e52d8d0dSVatsala Narang ~BIT((frame_body[3] >> 4) & 0xf); 1990554c0a3aSHans de Goede 1991554c0a3aSHans de Goede /* reason_code = frame_body[4] | (frame_body[5] << 8); */ 1992d48603afSRoss Schmidt reason_code = get_unaligned_le16(&frame_body[4]); 1993554c0a3aSHans de Goede } else if ((frame_body[3] & BIT(3)) == BIT(3)) { 1994554c0a3aSHans de Goede tid = (frame_body[3] >> 4) & 0x0F; 1995554c0a3aSHans de Goede 1996554c0a3aSHans de Goede preorder_ctrl = &psta->recvreorder_ctrl[tid]; 1997554c0a3aSHans de Goede preorder_ctrl->enable = false; 1998554c0a3aSHans de Goede preorder_ctrl->indicate_seq = 0xffff; 1999554c0a3aSHans de Goede #ifdef DBG_RX_SEQ 2000554c0a3aSHans de Goede DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__, 2001554c0a3aSHans de Goede preorder_ctrl->indicate_seq); 2002554c0a3aSHans de Goede #endif 2003554c0a3aSHans de Goede } 2004554c0a3aSHans de Goede 2005554c0a3aSHans de Goede DBG_871X("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code); 2006554c0a3aSHans de Goede /* todo: how to notify the host while receiving DELETE BA */ 2007554c0a3aSHans de Goede break; 2008554c0a3aSHans de Goede 2009554c0a3aSHans de Goede default: 2010554c0a3aSHans de Goede break; 2011554c0a3aSHans de Goede } 2012554c0a3aSHans de Goede } 2013554c0a3aSHans de Goede return _SUCCESS; 2014554c0a3aSHans de Goede } 2015554c0a3aSHans de Goede 2016554c0a3aSHans de Goede static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token) 2017554c0a3aSHans de Goede { 2018554c0a3aSHans de Goede struct adapter *adapter = recv_frame->u.hdr.adapter; 2019554c0a3aSHans de Goede struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv); 2020554c0a3aSHans de Goede u8 *frame = recv_frame->u.hdr.rx_data; 2021554c0a3aSHans de Goede u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) | 2022554c0a3aSHans de Goede (recv_frame->u.hdr.attrib.frag_num & 0xf); 2023554c0a3aSHans de Goede 2024554c0a3aSHans de Goede if (GetRetry(frame)) { 2025554c0a3aSHans de Goede if (token >= 0) { 2026554c0a3aSHans de Goede if ((seq_ctrl == mlmeext->action_public_rxseq) 2027554c0a3aSHans de Goede && (token == mlmeext->action_public_dialog_token)) { 2028554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n", 2029554c0a3aSHans de Goede FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token); 2030554c0a3aSHans de Goede return _FAIL; 2031554c0a3aSHans de Goede } 2032554c0a3aSHans de Goede } else { 2033554c0a3aSHans de Goede if (seq_ctrl == mlmeext->action_public_rxseq) { 2034554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n", 2035554c0a3aSHans de Goede FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq); 2036554c0a3aSHans de Goede return _FAIL; 2037554c0a3aSHans de Goede } 2038554c0a3aSHans de Goede } 2039554c0a3aSHans de Goede } 2040554c0a3aSHans de Goede 2041554c0a3aSHans de Goede mlmeext->action_public_rxseq = seq_ctrl; 2042554c0a3aSHans de Goede 2043554c0a3aSHans de Goede if (token >= 0) 2044554c0a3aSHans de Goede mlmeext->action_public_dialog_token = token; 2045554c0a3aSHans de Goede 2046554c0a3aSHans de Goede return _SUCCESS; 2047554c0a3aSHans de Goede } 2048554c0a3aSHans de Goede 2049554c0a3aSHans de Goede static unsigned int on_action_public_p2p(union recv_frame *precv_frame) 2050554c0a3aSHans de Goede { 2051554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2052554c0a3aSHans de Goede u8 *frame_body; 2053554c0a3aSHans de Goede u8 dialogToken = 0; 2054554c0a3aSHans de Goede 2055554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 2056554c0a3aSHans de Goede 2057554c0a3aSHans de Goede dialogToken = frame_body[7]; 2058554c0a3aSHans de Goede 2059554c0a3aSHans de Goede if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL) 2060554c0a3aSHans de Goede return _FAIL; 2061554c0a3aSHans de Goede 2062554c0a3aSHans de Goede return _SUCCESS; 2063554c0a3aSHans de Goede } 2064554c0a3aSHans de Goede 2065554c0a3aSHans de Goede static unsigned int on_action_public_vendor(union recv_frame *precv_frame) 2066554c0a3aSHans de Goede { 2067554c0a3aSHans de Goede unsigned int ret = _FAIL; 2068554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2069554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 2070554c0a3aSHans de Goede 2071554c0a3aSHans de Goede if (!memcmp(frame_body + 2, P2P_OUI, 4)) { 2072554c0a3aSHans de Goede ret = on_action_public_p2p(precv_frame); 2073554c0a3aSHans de Goede } 2074554c0a3aSHans de Goede 2075554c0a3aSHans de Goede return ret; 2076554c0a3aSHans de Goede } 2077554c0a3aSHans de Goede 2078554c0a3aSHans de Goede static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action) 2079554c0a3aSHans de Goede { 2080554c0a3aSHans de Goede unsigned int ret = _FAIL; 2081554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2082554c0a3aSHans de Goede uint frame_len = precv_frame->u.hdr.len; 2083554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 2084554c0a3aSHans de Goede u8 token; 2085554c0a3aSHans de Goede struct adapter *adapter = precv_frame->u.hdr.adapter; 2086554c0a3aSHans de Goede int cnt = 0; 2087554c0a3aSHans de Goede char msg[64]; 2088554c0a3aSHans de Goede 2089554c0a3aSHans de Goede token = frame_body[2]; 2090554c0a3aSHans de Goede 2091554c0a3aSHans de Goede if (rtw_action_public_decache(precv_frame, token) == _FAIL) 2092554c0a3aSHans de Goede goto exit; 2093554c0a3aSHans de Goede 2094554c0a3aSHans de Goede cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token); 2095554c0a3aSHans de Goede rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg); 2096554c0a3aSHans de Goede 2097554c0a3aSHans de Goede ret = _SUCCESS; 2098554c0a3aSHans de Goede 2099554c0a3aSHans de Goede exit: 2100554c0a3aSHans de Goede return ret; 2101554c0a3aSHans de Goede } 2102554c0a3aSHans de Goede 2103554c0a3aSHans de Goede unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame) 2104554c0a3aSHans de Goede { 2105554c0a3aSHans de Goede unsigned int ret = _FAIL; 2106554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2107554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 2108554c0a3aSHans de Goede u8 category, action; 2109554c0a3aSHans de Goede 2110554c0a3aSHans de Goede /* check RA matches or not */ 2111554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) 2112554c0a3aSHans de Goede goto exit; 2113554c0a3aSHans de Goede 2114554c0a3aSHans de Goede category = frame_body[0]; 2115554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_PUBLIC) 2116554c0a3aSHans de Goede goto exit; 2117554c0a3aSHans de Goede 2118554c0a3aSHans de Goede action = frame_body[1]; 2119554c0a3aSHans de Goede switch (action) { 2120554c0a3aSHans de Goede case ACT_PUBLIC_VENDOR: 2121554c0a3aSHans de Goede ret = on_action_public_vendor(precv_frame); 2122554c0a3aSHans de Goede break; 2123554c0a3aSHans de Goede default: 2124554c0a3aSHans de Goede ret = on_action_public_default(precv_frame, action); 2125554c0a3aSHans de Goede break; 2126554c0a3aSHans de Goede } 2127554c0a3aSHans de Goede 2128554c0a3aSHans de Goede exit: 2129554c0a3aSHans de Goede return ret; 2130554c0a3aSHans de Goede } 2131554c0a3aSHans de Goede 2132554c0a3aSHans de Goede unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame) 2133554c0a3aSHans de Goede { 2134554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2135554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 2136554c0a3aSHans de Goede u8 category, action; 2137554c0a3aSHans de Goede 2138554c0a3aSHans de Goede /* check RA matches or not */ 2139554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) 2140554c0a3aSHans de Goede goto exit; 2141554c0a3aSHans de Goede 2142554c0a3aSHans de Goede category = frame_body[0]; 2143554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_HT) 2144554c0a3aSHans de Goede goto exit; 2145554c0a3aSHans de Goede 2146554c0a3aSHans de Goede action = frame_body[1]; 2147554c0a3aSHans de Goede switch (action) { 2148a9d87638SRoss Schmidt case WLAN_HT_ACTION_COMPRESSED_BF: 2149554c0a3aSHans de Goede break; 2150554c0a3aSHans de Goede default: 2151554c0a3aSHans de Goede break; 2152554c0a3aSHans de Goede } 2153554c0a3aSHans de Goede 2154554c0a3aSHans de Goede exit: 2155554c0a3aSHans de Goede 2156554c0a3aSHans de Goede return _SUCCESS; 2157554c0a3aSHans de Goede } 2158554c0a3aSHans de Goede 2159554c0a3aSHans de Goede unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame) 2160554c0a3aSHans de Goede { 2161554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2162554c0a3aSHans de Goede struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; 2163554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2164554c0a3aSHans de Goede unsigned short tid; 2165554c0a3aSHans de Goede /* Baron */ 2166554c0a3aSHans de Goede 2167554c0a3aSHans de Goede DBG_871X("OnAction_sa_query\n"); 2168554c0a3aSHans de Goede 2169554c0a3aSHans de Goede switch (pframe[WLAN_HDR_A3_LEN+1]) { 2170554c0a3aSHans de Goede case 0: /* SA Query req */ 2171554c0a3aSHans de Goede memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short)); 2172554c0a3aSHans de Goede DBG_871X("OnAction_sa_query request, action =%d, tid =%04x\n", pframe[WLAN_HDR_A3_LEN+1], tid); 2173554c0a3aSHans de Goede issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid); 2174554c0a3aSHans de Goede break; 2175554c0a3aSHans de Goede 2176554c0a3aSHans de Goede case 1: /* SA Query rsp */ 2177554c0a3aSHans de Goede del_timer_sync(&pmlmeext->sa_query_timer); 2178554c0a3aSHans de Goede DBG_871X("OnAction_sa_query response, action =%d, tid =%04x, cancel timer\n", pframe[WLAN_HDR_A3_LEN+1], pframe[WLAN_HDR_A3_LEN+2]); 2179554c0a3aSHans de Goede break; 2180554c0a3aSHans de Goede default: 2181554c0a3aSHans de Goede break; 2182554c0a3aSHans de Goede } 2183554c0a3aSHans de Goede if (0) { 2184554c0a3aSHans de Goede int pp; 2185c926f022SSimran Singhal 2186554c0a3aSHans de Goede printk("pattrib->pktlen = %d =>", pattrib->pkt_len); 2187554c0a3aSHans de Goede for (pp = 0; pp < pattrib->pkt_len; pp++) 2188554c0a3aSHans de Goede printk(" %02x ", pframe[pp]); 2189554c0a3aSHans de Goede printk("\n"); 2190554c0a3aSHans de Goede } 2191554c0a3aSHans de Goede 2192554c0a3aSHans de Goede return _SUCCESS; 2193554c0a3aSHans de Goede } 2194554c0a3aSHans de Goede 2195554c0a3aSHans de Goede unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame) 2196554c0a3aSHans de Goede { 2197554c0a3aSHans de Goede int i; 2198554c0a3aSHans de Goede unsigned char category; 2199554c0a3aSHans de Goede struct action_handler *ptable; 2200554c0a3aSHans de Goede unsigned char *frame_body; 2201554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2202554c0a3aSHans de Goede 2203554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 2204554c0a3aSHans de Goede 2205554c0a3aSHans de Goede category = frame_body[0]; 2206554c0a3aSHans de Goede 220760db8d10SJérémy Lefaure for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) { 2208554c0a3aSHans de Goede ptable = &OnAction_tbl[i]; 2209554c0a3aSHans de Goede 2210554c0a3aSHans de Goede if (category == ptable->num) 2211554c0a3aSHans de Goede ptable->func(padapter, precv_frame); 2212554c0a3aSHans de Goede 2213554c0a3aSHans de Goede } 2214554c0a3aSHans de Goede 2215554c0a3aSHans de Goede return _SUCCESS; 2216554c0a3aSHans de Goede 2217554c0a3aSHans de Goede } 2218554c0a3aSHans de Goede 2219554c0a3aSHans de Goede unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame) 2220554c0a3aSHans de Goede { 2221554c0a3aSHans de Goede 2222554c0a3aSHans de Goede /* DBG_871X("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */ 2223554c0a3aSHans de Goede return _SUCCESS; 2224554c0a3aSHans de Goede } 2225554c0a3aSHans de Goede 2226554c0a3aSHans de Goede static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once) 2227554c0a3aSHans de Goede { 2228554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2229554c0a3aSHans de Goede struct xmit_buf *pxmitbuf; 2230554c0a3aSHans de Goede 2231554c0a3aSHans de Goede if (once) 2232554c0a3aSHans de Goede pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv); 2233554c0a3aSHans de Goede else 2234554c0a3aSHans de Goede pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv); 2235554c0a3aSHans de Goede 2236554c0a3aSHans de Goede if (pmgntframe == NULL) { 2237554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once); 2238554c0a3aSHans de Goede goto exit; 2239554c0a3aSHans de Goede } 2240554c0a3aSHans de Goede 2241554c0a3aSHans de Goede pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv); 2242554c0a3aSHans de Goede if (pxmitbuf == NULL) { 2243554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter)); 2244554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pmgntframe); 2245554c0a3aSHans de Goede pmgntframe = NULL; 2246554c0a3aSHans de Goede goto exit; 2247554c0a3aSHans de Goede } 2248554c0a3aSHans de Goede 2249554c0a3aSHans de Goede pmgntframe->frame_tag = MGNT_FRAMETAG; 2250554c0a3aSHans de Goede pmgntframe->pxmitbuf = pxmitbuf; 2251554c0a3aSHans de Goede pmgntframe->buf_addr = pxmitbuf->pbuf; 2252554c0a3aSHans de Goede pxmitbuf->priv_data = pmgntframe; 2253554c0a3aSHans de Goede 2254554c0a3aSHans de Goede exit: 2255554c0a3aSHans de Goede return pmgntframe; 2256554c0a3aSHans de Goede 2257554c0a3aSHans de Goede } 2258554c0a3aSHans de Goede 2259554c0a3aSHans de Goede inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) 2260554c0a3aSHans de Goede { 2261554c0a3aSHans de Goede return _alloc_mgtxmitframe(pxmitpriv, false); 2262554c0a3aSHans de Goede } 2263554c0a3aSHans de Goede 2264554c0a3aSHans de Goede /**************************************************************************** 2265554c0a3aSHans de Goede 226668468503SAndreas Hellmich Following are some TX functions for WiFi MLME 2267554c0a3aSHans de Goede 2268554c0a3aSHans de Goede *****************************************************************************/ 2269554c0a3aSHans de Goede 2270554c0a3aSHans de Goede void update_mgnt_tx_rate(struct adapter *padapter, u8 rate) 2271554c0a3aSHans de Goede { 2272554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2273554c0a3aSHans de Goede 2274554c0a3aSHans de Goede pmlmeext->tx_rate = rate; 2275554c0a3aSHans de Goede /* DBG_871X("%s(): rate = %x\n", __func__, rate); */ 2276554c0a3aSHans de Goede } 2277554c0a3aSHans de Goede 2278554c0a3aSHans de Goede void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib) 2279554c0a3aSHans de Goede { 2280554c0a3aSHans de Goede u8 wireless_mode; 2281554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2282554c0a3aSHans de Goede 2283554c0a3aSHans de Goede /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */ 2284554c0a3aSHans de Goede 2285554c0a3aSHans de Goede pattrib->hdrlen = 24; 2286554c0a3aSHans de Goede pattrib->nr_frags = 1; 2287554c0a3aSHans de Goede pattrib->priority = 7; 2288554c0a3aSHans de Goede pattrib->mac_id = 0; 2289554c0a3aSHans de Goede pattrib->qsel = 0x12; 2290554c0a3aSHans de Goede 2291554c0a3aSHans de Goede pattrib->pktlen = 0; 2292554c0a3aSHans de Goede 2293554c0a3aSHans de Goede if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB) 2294554c0a3aSHans de Goede wireless_mode = WIRELESS_11B; 2295554c0a3aSHans de Goede else 2296554c0a3aSHans de Goede wireless_mode = WIRELESS_11G; 2297554c0a3aSHans de Goede pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode); 2298554c0a3aSHans de Goede pattrib->rate = pmlmeext->tx_rate; 2299554c0a3aSHans de Goede 2300554c0a3aSHans de Goede pattrib->encrypt = _NO_PRIVACY_; 2301554c0a3aSHans de Goede pattrib->bswenc = false; 2302554c0a3aSHans de Goede 2303554c0a3aSHans de Goede pattrib->qos_en = false; 2304554c0a3aSHans de Goede pattrib->ht_en = false; 2305554c0a3aSHans de Goede pattrib->bwmode = CHANNEL_WIDTH_20; 2306554c0a3aSHans de Goede pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 2307554c0a3aSHans de Goede pattrib->sgi = false; 2308554c0a3aSHans de Goede 2309554c0a3aSHans de Goede pattrib->seqnum = pmlmeext->mgnt_seq; 2310554c0a3aSHans de Goede 2311554c0a3aSHans de Goede pattrib->retry_ctrl = true; 2312554c0a3aSHans de Goede 2313554c0a3aSHans de Goede pattrib->mbssid = 0; 2314554c0a3aSHans de Goede 2315554c0a3aSHans de Goede } 2316554c0a3aSHans de Goede 2317554c0a3aSHans de Goede void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe) 2318554c0a3aSHans de Goede { 2319554c0a3aSHans de Goede u8 *pframe; 2320554c0a3aSHans de Goede struct pkt_attrib *pattrib = &pmgntframe->attrib; 2321554c0a3aSHans de Goede 2322554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2323554c0a3aSHans de Goede 2324554c0a3aSHans de Goede memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN); 2325554c0a3aSHans de Goede memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN); 2326554c0a3aSHans de Goede } 2327554c0a3aSHans de Goede 2328554c0a3aSHans de Goede void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe) 2329554c0a3aSHans de Goede { 23300ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 23310ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2332554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2333554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2334554c0a3aSHans de Goede return; 2335554c0a3aSHans de Goede } 2336554c0a3aSHans de Goede 2337554c0a3aSHans de Goede rtw_hal_mgnt_xmit(padapter, pmgntframe); 2338554c0a3aSHans de Goede } 2339554c0a3aSHans de Goede 2340554c0a3aSHans de Goede s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms) 2341554c0a3aSHans de Goede { 2342554c0a3aSHans de Goede s32 ret = _FAIL; 2343554c0a3aSHans de Goede _irqL irqL; 2344554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 2345554c0a3aSHans de Goede struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; 2346554c0a3aSHans de Goede struct submit_ctx sctx; 2347554c0a3aSHans de Goede 23480ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 23490ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2350554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2351554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2352554c0a3aSHans de Goede return ret; 2353554c0a3aSHans de Goede } 2354554c0a3aSHans de Goede 2355554c0a3aSHans de Goede rtw_sctx_init(&sctx, timeout_ms); 2356554c0a3aSHans de Goede pxmitbuf->sctx = &sctx; 2357554c0a3aSHans de Goede 2358554c0a3aSHans de Goede ret = rtw_hal_mgnt_xmit(padapter, pmgntframe); 2359554c0a3aSHans de Goede 2360554c0a3aSHans de Goede if (ret == _SUCCESS) 2361554c0a3aSHans de Goede ret = rtw_sctx_wait(&sctx, __func__); 2362554c0a3aSHans de Goede 2363554c0a3aSHans de Goede spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); 2364554c0a3aSHans de Goede pxmitbuf->sctx = NULL; 2365554c0a3aSHans de Goede spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); 2366554c0a3aSHans de Goede 2367554c0a3aSHans de Goede return ret; 2368554c0a3aSHans de Goede } 2369554c0a3aSHans de Goede 2370554c0a3aSHans de Goede s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe) 2371554c0a3aSHans de Goede { 237240d4aa0fSShreeya Patel static u8 seq_no; 2373554c0a3aSHans de Goede s32 ret = _FAIL; 2374554c0a3aSHans de Goede u32 timeout_ms = 500;/* 500ms */ 2375554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 2376554c0a3aSHans de Goede 23770ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 23780ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2379554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2380554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2381554c0a3aSHans de Goede return -1; 2382554c0a3aSHans de Goede } 2383554c0a3aSHans de Goede 2384554c0a3aSHans de Goede if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) { 2385554c0a3aSHans de Goede pxmitpriv->ack_tx = true; 2386554c0a3aSHans de Goede pxmitpriv->seq_no = seq_no++; 2387554c0a3aSHans de Goede pmgntframe->ack_report = 1; 2388a65f0d18SVatsala Narang if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) 2389554c0a3aSHans de Goede ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms); 2390554c0a3aSHans de Goede 2391554c0a3aSHans de Goede pxmitpriv->ack_tx = false; 2392554c0a3aSHans de Goede mutex_unlock(&pxmitpriv->ack_tx_mutex); 2393554c0a3aSHans de Goede } 2394554c0a3aSHans de Goede 2395554c0a3aSHans de Goede return ret; 2396554c0a3aSHans de Goede } 2397554c0a3aSHans de Goede 2398554c0a3aSHans de Goede static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) 2399554c0a3aSHans de Goede { 2400554c0a3aSHans de Goede u8 *ssid_ie; 2401554c0a3aSHans de Goede sint ssid_len_ori; 2402554c0a3aSHans de Goede int len_diff = 0; 2403554c0a3aSHans de Goede 2404554c0a3aSHans de Goede ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); 2405554c0a3aSHans de Goede 2406554c0a3aSHans de Goede /* DBG_871X("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */ 2407554c0a3aSHans de Goede 2408554c0a3aSHans de Goede if (ssid_ie && ssid_len_ori > 0) { 2409554c0a3aSHans de Goede switch (hidden_ssid_mode) { 2410554c0a3aSHans de Goede case 1: 2411554c0a3aSHans de Goede { 2412554c0a3aSHans de Goede u8 *next_ie = ssid_ie + 2 + ssid_len_ori; 2413554c0a3aSHans de Goede u32 remain_len = 0; 2414554c0a3aSHans de Goede 2415554c0a3aSHans de Goede remain_len = ies_len - (next_ie-ies); 2416554c0a3aSHans de Goede 2417554c0a3aSHans de Goede ssid_ie[1] = 0; 2418554c0a3aSHans de Goede memcpy(ssid_ie+2, next_ie, remain_len); 2419554c0a3aSHans de Goede len_diff -= ssid_len_ori; 2420554c0a3aSHans de Goede 2421554c0a3aSHans de Goede break; 2422554c0a3aSHans de Goede } 2423554c0a3aSHans de Goede case 2: 2424554c0a3aSHans de Goede memset(&ssid_ie[2], 0, ssid_len_ori); 2425554c0a3aSHans de Goede break; 2426554c0a3aSHans de Goede default: 2427554c0a3aSHans de Goede break; 2428554c0a3aSHans de Goede } 2429554c0a3aSHans de Goede } 2430554c0a3aSHans de Goede 2431554c0a3aSHans de Goede return len_diff; 2432554c0a3aSHans de Goede } 2433554c0a3aSHans de Goede 2434554c0a3aSHans de Goede void issue_beacon(struct adapter *padapter, int timeout_ms) 2435554c0a3aSHans de Goede { 2436554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2437554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2438554c0a3aSHans de Goede unsigned char *pframe; 2439554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2440554c0a3aSHans de Goede __le16 *fctrl; 2441554c0a3aSHans de Goede unsigned int rate_len; 2442554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2443554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2444554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2445554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2446554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 2447554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2448554c0a3aSHans de Goede 2449554c0a3aSHans de Goede /* DBG_871X("%s\n", __func__); */ 2450554c0a3aSHans de Goede 2451554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 245241452327SVatsala Narang if (!pmgntframe) { 2453554c0a3aSHans de Goede DBG_871X("%s, alloc mgnt frame fail\n", __func__); 2454554c0a3aSHans de Goede return; 2455554c0a3aSHans de Goede } 2456554c0a3aSHans de Goede 2457554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->bcn_update_lock); 2458554c0a3aSHans de Goede 2459554c0a3aSHans de Goede /* update attribute */ 2460554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2461554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2462554c0a3aSHans de Goede pattrib->qsel = 0x10; 2463554c0a3aSHans de Goede 2464554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2465554c0a3aSHans de Goede 2466554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2467554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2468554c0a3aSHans de Goede 2469554c0a3aSHans de Goede 2470554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2471554c0a3aSHans de Goede *(fctrl) = 0; 2472554c0a3aSHans de Goede 2473554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 2474554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 2475554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); 2476554c0a3aSHans de Goede 2477554c0a3aSHans de Goede SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); 2478554c0a3aSHans de Goede /* pmlmeext->mgnt_seq++; */ 2479554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_BEACON); 2480554c0a3aSHans de Goede 2481554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2482554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2483554c0a3aSHans de Goede 2484554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 2485554c0a3aSHans de Goede /* DBG_871X("ie len =%d\n", cur_network->IELength); */ 2486554c0a3aSHans de Goede { 2487554c0a3aSHans de Goede int len_diff; 2488c926f022SSimran Singhal 2489554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, cur_network->IELength); 2490554c0a3aSHans de Goede len_diff = update_hidden_ssid( 2491554c0a3aSHans de Goede pframe+_BEACON_IE_OFFSET_ 2492554c0a3aSHans de Goede , cur_network->IELength-_BEACON_IE_OFFSET_ 2493554c0a3aSHans de Goede , pmlmeinfo->hidden_ssid_mode 2494554c0a3aSHans de Goede ); 2495554c0a3aSHans de Goede pframe += (cur_network->IELength+len_diff); 2496554c0a3aSHans de Goede pattrib->pktlen += (cur_network->IELength+len_diff); 2497554c0a3aSHans de Goede } 2498554c0a3aSHans de Goede 2499554c0a3aSHans de Goede { 2500554c0a3aSHans de Goede u8 *wps_ie; 2501554c0a3aSHans de Goede uint wps_ielen; 2502554c0a3aSHans de Goede u8 sr = 0; 2503c926f022SSimran Singhal 2504554c0a3aSHans de Goede wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, 2505554c0a3aSHans de Goede pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); 2506554c0a3aSHans de Goede if (wps_ie && wps_ielen > 0) { 2507554c0a3aSHans de Goede rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); 2508554c0a3aSHans de Goede } 2509554c0a3aSHans de Goede if (sr != 0) 2510554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_UNDER_WPS); 2511554c0a3aSHans de Goede else 2512554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); 2513554c0a3aSHans de Goede } 2514554c0a3aSHans de Goede 2515554c0a3aSHans de Goede goto _issue_bcn; 2516554c0a3aSHans de Goede 2517554c0a3aSHans de Goede } 2518554c0a3aSHans de Goede 2519554c0a3aSHans de Goede /* below for ad-hoc mode */ 2520554c0a3aSHans de Goede 2521554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 2522554c0a3aSHans de Goede pframe += 8; 2523554c0a3aSHans de Goede pattrib->pktlen += 8; 2524554c0a3aSHans de Goede 2525554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 2526554c0a3aSHans de Goede 2527554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 2528554c0a3aSHans de Goede 2529554c0a3aSHans de Goede pframe += 2; 2530554c0a3aSHans de Goede pattrib->pktlen += 2; 2531554c0a3aSHans de Goede 2532554c0a3aSHans de Goede /* capability info: 2 bytes */ 2533554c0a3aSHans de Goede 2534554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 2535554c0a3aSHans de Goede 2536554c0a3aSHans de Goede pframe += 2; 2537554c0a3aSHans de Goede pattrib->pktlen += 2; 2538554c0a3aSHans de Goede 2539554c0a3aSHans de Goede /* SSID */ 2540554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); 2541554c0a3aSHans de Goede 2542554c0a3aSHans de Goede /* supported rates... */ 2543554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 2544554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); 2545554c0a3aSHans de Goede 2546554c0a3aSHans de Goede /* DS parameter set */ 2547554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); 2548554c0a3aSHans de Goede 2549554c0a3aSHans de Goede /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */ 2550554c0a3aSHans de Goede { 2551554c0a3aSHans de Goede u8 erpinfo = 0; 2552554c0a3aSHans de Goede u32 ATIMWindow; 2553554c0a3aSHans de Goede /* IBSS Parameter Set... */ 2554554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 2555554c0a3aSHans de Goede ATIMWindow = 0; 2556554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); 2557554c0a3aSHans de Goede 2558554c0a3aSHans de Goede /* ERP IE */ 2559554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen); 2560554c0a3aSHans de Goede } 2561554c0a3aSHans de Goede 2562554c0a3aSHans de Goede 2563554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 2564554c0a3aSHans de Goede if (rate_len > 8) { 2565554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); 2566554c0a3aSHans de Goede } 2567554c0a3aSHans de Goede 2568554c0a3aSHans de Goede 2569554c0a3aSHans de Goede /* todo:HT for adhoc */ 2570554c0a3aSHans de Goede 2571554c0a3aSHans de Goede _issue_bcn: 2572554c0a3aSHans de Goede 2573554c0a3aSHans de Goede pmlmepriv->update_bcn = false; 2574554c0a3aSHans de Goede 2575554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->bcn_update_lock); 2576554c0a3aSHans de Goede 2577554c0a3aSHans de Goede if ((pattrib->pktlen + TXDESC_SIZE) > 512) { 2578554c0a3aSHans de Goede DBG_871X("beacon frame too large\n"); 2579554c0a3aSHans de Goede return; 2580554c0a3aSHans de Goede } 2581554c0a3aSHans de Goede 2582554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2583554c0a3aSHans de Goede 2584554c0a3aSHans de Goede /* DBG_871X("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */ 2585554c0a3aSHans de Goede if (timeout_ms > 0) 2586554c0a3aSHans de Goede dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms); 2587554c0a3aSHans de Goede else 2588554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2589554c0a3aSHans de Goede 2590554c0a3aSHans de Goede } 2591554c0a3aSHans de Goede 2592554c0a3aSHans de Goede void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq) 2593554c0a3aSHans de Goede { 2594554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2595554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2596554c0a3aSHans de Goede unsigned char *pframe; 2597554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2598554c0a3aSHans de Goede __le16 *fctrl; 2599554c0a3aSHans de Goede unsigned char *mac, *bssid; 2600554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2601554c0a3aSHans de Goede 2602554c0a3aSHans de Goede u8 *pwps_ie; 2603554c0a3aSHans de Goede uint wps_ielen; 2604554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2605554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2606554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2607554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 2608554c0a3aSHans de Goede unsigned int rate_len; 2609554c0a3aSHans de Goede 2610554c0a3aSHans de Goede /* DBG_871X("%s\n", __func__); */ 2611554c0a3aSHans de Goede 2612554c0a3aSHans de Goede if (da == NULL) 2613554c0a3aSHans de Goede return; 2614554c0a3aSHans de Goede 2615554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2616554c0a3aSHans de Goede if (pmgntframe == NULL) { 2617554c0a3aSHans de Goede DBG_871X("%s, alloc mgnt frame fail\n", __func__); 2618554c0a3aSHans de Goede return; 2619554c0a3aSHans de Goede } 2620554c0a3aSHans de Goede 2621554c0a3aSHans de Goede 2622554c0a3aSHans de Goede /* update attribute */ 2623554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2624554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2625554c0a3aSHans de Goede 2626554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2627554c0a3aSHans de Goede 2628554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2629554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2630554c0a3aSHans de Goede 2631554c0a3aSHans de Goede mac = myid(&(padapter->eeprompriv)); 2632554c0a3aSHans de Goede bssid = cur_network->MacAddress; 2633554c0a3aSHans de Goede 2634554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2635554c0a3aSHans de Goede *(fctrl) = 0; 2636554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 2637554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, mac, ETH_ALEN); 2638554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); 2639554c0a3aSHans de Goede 2640554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2641554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2642554c0a3aSHans de Goede SetFrameSubType(fctrl, WIFI_PROBERSP); 2643554c0a3aSHans de Goede 2644554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 2645554c0a3aSHans de Goede pattrib->pktlen = pattrib->hdrlen; 2646554c0a3aSHans de Goede pframe += pattrib->hdrlen; 2647554c0a3aSHans de Goede 2648554c0a3aSHans de Goede 2649554c0a3aSHans de Goede if (cur_network->IELength > MAX_IE_SZ) 2650554c0a3aSHans de Goede return; 2651554c0a3aSHans de Goede 2652554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 2653554c0a3aSHans de Goede pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen); 2654554c0a3aSHans de Goede 2655554c0a3aSHans de Goede /* inerset & update wps_probe_resp_ie */ 265634557e23SIzabela Bakollari if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) { 2657554c0a3aSHans de Goede uint wps_offset, remainder_ielen; 2658554c0a3aSHans de Goede u8 *premainder_ie; 2659554c0a3aSHans de Goede 2660554c0a3aSHans de Goede wps_offset = (uint)(pwps_ie - cur_network->IEs); 2661554c0a3aSHans de Goede 2662554c0a3aSHans de Goede premainder_ie = pwps_ie + wps_ielen; 2663554c0a3aSHans de Goede 2664554c0a3aSHans de Goede remainder_ielen = cur_network->IELength - wps_offset - wps_ielen; 2665554c0a3aSHans de Goede 2666554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, wps_offset); 2667554c0a3aSHans de Goede pframe += wps_offset; 2668554c0a3aSHans de Goede pattrib->pktlen += wps_offset; 2669554c0a3aSHans de Goede 2670554c0a3aSHans de Goede wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */ 2671554c0a3aSHans de Goede if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) { 2672554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2); 2673554c0a3aSHans de Goede pframe += wps_ielen+2; 2674554c0a3aSHans de Goede pattrib->pktlen += wps_ielen+2; 2675554c0a3aSHans de Goede } 2676554c0a3aSHans de Goede 2677554c0a3aSHans de Goede if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) { 2678554c0a3aSHans de Goede memcpy(pframe, premainder_ie, remainder_ielen); 2679554c0a3aSHans de Goede pframe += remainder_ielen; 2680554c0a3aSHans de Goede pattrib->pktlen += remainder_ielen; 2681554c0a3aSHans de Goede } 2682554c0a3aSHans de Goede } else { 2683554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, cur_network->IELength); 2684554c0a3aSHans de Goede pframe += cur_network->IELength; 2685554c0a3aSHans de Goede pattrib->pktlen += cur_network->IELength; 2686554c0a3aSHans de Goede } 2687554c0a3aSHans de Goede 2688554c0a3aSHans de Goede /* retrieve SSID IE from cur_network->Ssid */ 2689554c0a3aSHans de Goede { 2690554c0a3aSHans de Goede u8 *ssid_ie; 2691554c0a3aSHans de Goede sint ssid_ielen; 2692554c0a3aSHans de Goede sint ssid_ielen_diff; 2693554c0a3aSHans de Goede u8 buf[MAX_IE_SZ]; 2694554c0a3aSHans de Goede u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr); 2695554c0a3aSHans de Goede 2696554c0a3aSHans de Goede ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen, 2697554c0a3aSHans de Goede (pframe-ies)-_FIXED_IE_LENGTH_); 2698554c0a3aSHans de Goede 2699554c0a3aSHans de Goede ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen; 2700554c0a3aSHans de Goede 2701554c0a3aSHans de Goede if (ssid_ie && cur_network->Ssid.SsidLength) { 2702554c0a3aSHans de Goede uint remainder_ielen; 2703554c0a3aSHans de Goede u8 *remainder_ie; 2704c926f022SSimran Singhal 2705554c0a3aSHans de Goede remainder_ie = ssid_ie+2; 2706554c0a3aSHans de Goede remainder_ielen = (pframe-remainder_ie); 2707554c0a3aSHans de Goede 2708554c0a3aSHans de Goede if (remainder_ielen > MAX_IE_SZ) { 2709554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter)); 2710554c0a3aSHans de Goede remainder_ielen = MAX_IE_SZ; 2711554c0a3aSHans de Goede } 2712554c0a3aSHans de Goede 2713554c0a3aSHans de Goede memcpy(buf, remainder_ie, remainder_ielen); 2714554c0a3aSHans de Goede memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen); 2715554c0a3aSHans de Goede *(ssid_ie+1) = cur_network->Ssid.SsidLength; 2716554c0a3aSHans de Goede memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength); 2717554c0a3aSHans de Goede 2718554c0a3aSHans de Goede pframe += ssid_ielen_diff; 2719554c0a3aSHans de Goede pattrib->pktlen += ssid_ielen_diff; 2720554c0a3aSHans de Goede } 2721554c0a3aSHans de Goede } 2722554c0a3aSHans de Goede } else { 2723554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 2724554c0a3aSHans de Goede pframe += 8; 2725554c0a3aSHans de Goede pattrib->pktlen += 8; 2726554c0a3aSHans de Goede 2727554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 2728554c0a3aSHans de Goede 2729554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 2730554c0a3aSHans de Goede 2731554c0a3aSHans de Goede pframe += 2; 2732554c0a3aSHans de Goede pattrib->pktlen += 2; 2733554c0a3aSHans de Goede 2734554c0a3aSHans de Goede /* capability info: 2 bytes */ 2735554c0a3aSHans de Goede 2736554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 2737554c0a3aSHans de Goede 2738554c0a3aSHans de Goede pframe += 2; 2739554c0a3aSHans de Goede pattrib->pktlen += 2; 2740554c0a3aSHans de Goede 2741554c0a3aSHans de Goede /* below for ad-hoc mode */ 2742554c0a3aSHans de Goede 2743554c0a3aSHans de Goede /* SSID */ 2744554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); 2745554c0a3aSHans de Goede 2746554c0a3aSHans de Goede /* supported rates... */ 2747554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 2748554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); 2749554c0a3aSHans de Goede 2750554c0a3aSHans de Goede /* DS parameter set */ 2751554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); 2752554c0a3aSHans de Goede 2753554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 2754554c0a3aSHans de Goede u8 erpinfo = 0; 2755554c0a3aSHans de Goede u32 ATIMWindow; 2756554c0a3aSHans de Goede /* IBSS Parameter Set... */ 2757554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 2758554c0a3aSHans de Goede ATIMWindow = 0; 2759554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); 2760554c0a3aSHans de Goede 2761554c0a3aSHans de Goede /* ERP IE */ 2762554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen); 2763554c0a3aSHans de Goede } 2764554c0a3aSHans de Goede 2765554c0a3aSHans de Goede 2766554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 2767554c0a3aSHans de Goede if (rate_len > 8) { 2768554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); 2769554c0a3aSHans de Goede } 2770554c0a3aSHans de Goede 2771554c0a3aSHans de Goede 2772554c0a3aSHans de Goede /* todo:HT for adhoc */ 2773554c0a3aSHans de Goede 2774554c0a3aSHans de Goede } 2775554c0a3aSHans de Goede 2776554c0a3aSHans de Goede #ifdef CONFIG_AUTO_AP_MODE 2777554c0a3aSHans de Goede { 2778554c0a3aSHans de Goede struct sta_info *psta; 2779554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 2780554c0a3aSHans de Goede 2781554c0a3aSHans de Goede DBG_871X("(%s)\n", __func__); 2782554c0a3aSHans de Goede 2783554c0a3aSHans de Goede /* check rc station */ 2784554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, da); 2785554c0a3aSHans de Goede if (psta && psta->isrc && psta->pid > 0) { 2786554c0a3aSHans de Goede u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A}; 2787554c0a3aSHans de Goede u8 RC_INFO[14] = {0}; 2788554c0a3aSHans de Goede /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */ 2789554c0a3aSHans de Goede u16 cu_ch = (u16)cur_network->Configuration.DSConfig; 2790554c0a3aSHans de Goede 2791bbda3ac4SRoss Schmidt DBG_871X("%s, reply rc(pid = 0x%x) device %pM in ch =%d\n", __func__, 2792554c0a3aSHans de Goede psta->pid, MAC_ARG(psta->hwaddr), cu_ch); 2793554c0a3aSHans de Goede 2794554c0a3aSHans de Goede /* append vendor specific ie */ 2795554c0a3aSHans de Goede memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI)); 2796554c0a3aSHans de Goede memcpy(&RC_INFO[4], mac, ETH_ALEN); 2797554c0a3aSHans de Goede memcpy(&RC_INFO[10], (u8 *)&psta->pid, 2); 2798554c0a3aSHans de Goede memcpy(&RC_INFO[12], (u8 *)&cu_ch, 2); 2799554c0a3aSHans de Goede 2800554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen); 2801554c0a3aSHans de Goede } 2802554c0a3aSHans de Goede } 2803554c0a3aSHans de Goede #endif /* CONFIG_AUTO_AP_MODE */ 2804554c0a3aSHans de Goede 2805554c0a3aSHans de Goede 2806554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2807554c0a3aSHans de Goede 2808554c0a3aSHans de Goede 2809554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2810554c0a3aSHans de Goede 2811554c0a3aSHans de Goede return; 2812554c0a3aSHans de Goede 2813554c0a3aSHans de Goede } 2814554c0a3aSHans de Goede 281542b3b621SAishwarya Pant static int _issue_probereq(struct adapter *padapter, 281642b3b621SAishwarya Pant struct ndis_802_11_ssid *pssid, 281742b3b621SAishwarya Pant u8 *da, u8 ch, bool append_wps, bool wait_ack) 2818554c0a3aSHans de Goede { 2819554c0a3aSHans de Goede int ret = _FAIL; 2820554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2821554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2822554c0a3aSHans de Goede unsigned char *pframe; 2823554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2824554c0a3aSHans de Goede __le16 *fctrl; 2825554c0a3aSHans de Goede unsigned char *mac; 2826554c0a3aSHans de Goede unsigned char bssrate[NumRates]; 2827554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2828554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2829554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2830554c0a3aSHans de Goede int bssrate_len = 0; 2831554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2832554c0a3aSHans de Goede 2833554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n")); 2834554c0a3aSHans de Goede 2835554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 283641452327SVatsala Narang if (!pmgntframe) 2837554c0a3aSHans de Goede goto exit; 2838554c0a3aSHans de Goede 2839554c0a3aSHans de Goede /* update attribute */ 2840554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2841554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2842554c0a3aSHans de Goede 2843554c0a3aSHans de Goede 2844554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2845554c0a3aSHans de Goede 2846554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2847554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2848554c0a3aSHans de Goede 2849554c0a3aSHans de Goede mac = myid(&(padapter->eeprompriv)); 2850554c0a3aSHans de Goede 2851554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2852554c0a3aSHans de Goede *(fctrl) = 0; 2853554c0a3aSHans de Goede 2854554c0a3aSHans de Goede if (da) { 2855554c0a3aSHans de Goede /* unicast probe request frame */ 2856554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 2857554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, da, ETH_ALEN); 2858554c0a3aSHans de Goede } else { 2859554c0a3aSHans de Goede /* broadcast probe request frame */ 2860554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 2861554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); 2862554c0a3aSHans de Goede } 2863554c0a3aSHans de Goede 2864554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, mac, ETH_ALEN); 2865554c0a3aSHans de Goede 2866554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2867554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2868554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_PROBEREQ); 2869554c0a3aSHans de Goede 2870554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2871554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2872554c0a3aSHans de Goede 2873554c0a3aSHans de Goede if (pssid) 2874554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen)); 2875554c0a3aSHans de Goede else 2876554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen)); 2877554c0a3aSHans de Goede 2878554c0a3aSHans de Goede get_rate_set(padapter, bssrate, &bssrate_len); 2879554c0a3aSHans de Goede 2880554c0a3aSHans de Goede if (bssrate_len > 8) { 2881554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen)); 2882554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); 2883554c0a3aSHans de Goede } else { 2884554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen)); 2885554c0a3aSHans de Goede } 2886554c0a3aSHans de Goede 2887554c0a3aSHans de Goede if (ch) 2888554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen); 2889554c0a3aSHans de Goede 2890554c0a3aSHans de Goede if (append_wps) { 2891554c0a3aSHans de Goede /* add wps_ie for wps2.0 */ 2892554c0a3aSHans de Goede if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) { 2893554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len); 2894554c0a3aSHans de Goede pframe += pmlmepriv->wps_probe_req_ie_len; 2895554c0a3aSHans de Goede pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; 2896554c0a3aSHans de Goede } 2897554c0a3aSHans de Goede } 2898554c0a3aSHans de Goede 2899554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2900554c0a3aSHans de Goede 2901554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz)); 2902554c0a3aSHans de Goede 2903554c0a3aSHans de Goede if (wait_ack) { 2904554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 2905554c0a3aSHans de Goede } else { 2906554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2907554c0a3aSHans de Goede ret = _SUCCESS; 2908554c0a3aSHans de Goede } 2909554c0a3aSHans de Goede 2910554c0a3aSHans de Goede exit: 2911554c0a3aSHans de Goede return ret; 2912554c0a3aSHans de Goede } 2913554c0a3aSHans de Goede 2914554c0a3aSHans de Goede inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da) 2915554c0a3aSHans de Goede { 2916554c0a3aSHans de Goede _issue_probereq(padapter, pssid, da, 0, 1, false); 2917554c0a3aSHans de Goede } 2918554c0a3aSHans de Goede 2919554c0a3aSHans de Goede int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps, 2920554c0a3aSHans de Goede int try_cnt, int wait_ms) 2921554c0a3aSHans de Goede { 2922554c0a3aSHans de Goede int ret; 2923554c0a3aSHans de Goede int i = 0; 2924554c0a3aSHans de Goede 2925554c0a3aSHans de Goede do { 29269cdb1928SSaiyam Doshi ret = _issue_probereq(padapter, pssid, da, ch, append_wps, 29279cdb1928SSaiyam Doshi wait_ms > 0); 2928554c0a3aSHans de Goede 2929554c0a3aSHans de Goede i++; 2930554c0a3aSHans de Goede 2931554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 2932554c0a3aSHans de Goede break; 2933554c0a3aSHans de Goede 2934554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 2935554c0a3aSHans de Goede msleep(wait_ms); 2936554c0a3aSHans de Goede 2937554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 2938554c0a3aSHans de Goede 2939554c0a3aSHans de Goede if (ret != _FAIL) { 2940554c0a3aSHans de Goede ret = _SUCCESS; 2941554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 2942554c0a3aSHans de Goede goto exit; 2943554c0a3aSHans de Goede #endif 2944554c0a3aSHans de Goede } 2945554c0a3aSHans de Goede 2946554c0a3aSHans de Goede if (try_cnt && wait_ms) { 2947554c0a3aSHans de Goede if (da) 2948bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", 2949554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), 2950554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 2951554c0a3aSHans de Goede else 2952554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", 2953554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), 2954554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 2955554c0a3aSHans de Goede } 2956554c0a3aSHans de Goede exit: 2957554c0a3aSHans de Goede return ret; 2958554c0a3aSHans de Goede } 2959554c0a3aSHans de Goede 296068468503SAndreas Hellmich /* if psta == NULL, indicate we are station(client) now... */ 2961554c0a3aSHans de Goede void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status) 2962554c0a3aSHans de Goede { 2963554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2964554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2965554c0a3aSHans de Goede unsigned char *pframe; 2966554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2967554c0a3aSHans de Goede __le16 *fctrl; 2968554c0a3aSHans de Goede unsigned int val32; 2969554c0a3aSHans de Goede unsigned short val16; 2970554c0a3aSHans de Goede int use_shared_key = 0; 2971554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2972554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2973554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2974554c0a3aSHans de Goede __le16 le_tmp; 2975554c0a3aSHans de Goede 2976554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2977554c0a3aSHans de Goede if (pmgntframe == NULL) 2978554c0a3aSHans de Goede return; 2979554c0a3aSHans de Goede 2980554c0a3aSHans de Goede /* update attribute */ 2981554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2982554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2983554c0a3aSHans de Goede 2984554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2985554c0a3aSHans de Goede 2986554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2987554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2988554c0a3aSHans de Goede 2989554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2990554c0a3aSHans de Goede *(fctrl) = 0; 2991554c0a3aSHans de Goede 2992554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2993554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2994554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_AUTH); 2995554c0a3aSHans de Goede 2996554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2997554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2998554c0a3aSHans de Goede 2999554c0a3aSHans de Goede 3000554c0a3aSHans de Goede if (psta) { /* for AP mode */ 3001554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN); 3002554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3003554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); 3004554c0a3aSHans de Goede 3005554c0a3aSHans de Goede /* setting auth algo number */ 3006554c0a3aSHans de Goede val16 = (u16)psta->authalg; 3007554c0a3aSHans de Goede 3008554c0a3aSHans de Goede if (status != _STATS_SUCCESSFUL_) 3009554c0a3aSHans de Goede val16 = 0; 3010554c0a3aSHans de Goede 3011554c0a3aSHans de Goede if (val16) 3012554c0a3aSHans de Goede use_shared_key = 1; 3013554c0a3aSHans de Goede 3014554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 3015554c0a3aSHans de Goede 3016554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3017554c0a3aSHans de Goede 3018554c0a3aSHans de Goede /* setting auth seq number */ 3019554c0a3aSHans de Goede val16 = (u16)psta->auth_seq; 3020554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 3021554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3022554c0a3aSHans de Goede 3023554c0a3aSHans de Goede /* setting status code... */ 3024554c0a3aSHans de Goede val16 = status; 3025554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 3026554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3027554c0a3aSHans de Goede 3028554c0a3aSHans de Goede /* added challenging text... */ 3029554c0a3aSHans de Goede if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) 3030554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen)); 3031554c0a3aSHans de Goede 3032554c0a3aSHans de Goede } else { 3033554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); 3034554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); 3035554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); 3036554c0a3aSHans de Goede 3037554c0a3aSHans de Goede /* setting auth algo number */ 3038554c0a3aSHans de Goede val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ 3039554c0a3aSHans de Goede if (val16) { 3040554c0a3aSHans de Goede use_shared_key = 1; 3041554c0a3aSHans de Goede } 3042554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 3043554c0a3aSHans de Goede /* DBG_871X("%s auth_algo = %s auth_seq =%d\n", __func__, (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED", pmlmeinfo->auth_seq); */ 3044554c0a3aSHans de Goede 3045554c0a3aSHans de Goede /* setting IV for auth seq #3 */ 3046554c0a3aSHans de Goede if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { 3047554c0a3aSHans de Goede __le32 le_tmp32; 3048554c0a3aSHans de Goede 3049554c0a3aSHans de Goede /* DBG_871X("==> iv(%d), key_index(%d)\n", pmlmeinfo->iv, pmlmeinfo->key_index); */ 3050554c0a3aSHans de Goede val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30)); 3051554c0a3aSHans de Goede le_tmp32 = cpu_to_le32(val32); 3052554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen)); 3053554c0a3aSHans de Goede 3054554c0a3aSHans de Goede pattrib->iv_len = 4; 3055554c0a3aSHans de Goede } 3056554c0a3aSHans de Goede 3057554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3058554c0a3aSHans de Goede 3059554c0a3aSHans de Goede /* setting auth seq number */ 3060554c0a3aSHans de Goede le_tmp = cpu_to_le16(pmlmeinfo->auth_seq); 3061554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3062554c0a3aSHans de Goede 3063554c0a3aSHans de Goede 3064554c0a3aSHans de Goede /* setting status code... */ 3065554c0a3aSHans de Goede le_tmp = cpu_to_le16(status); 3066554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3067554c0a3aSHans de Goede 3068554c0a3aSHans de Goede /* then checking to see if sending challenging text... */ 3069554c0a3aSHans de Goede if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { 3070554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen)); 3071554c0a3aSHans de Goede 3072554c0a3aSHans de Goede SetPrivacy(fctrl); 3073554c0a3aSHans de Goede 3074554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 3075554c0a3aSHans de Goede 3076554c0a3aSHans de Goede pattrib->encrypt = _WEP40_; 3077554c0a3aSHans de Goede 3078554c0a3aSHans de Goede pattrib->icv_len = 4; 3079554c0a3aSHans de Goede 3080554c0a3aSHans de Goede pattrib->pktlen += pattrib->icv_len; 3081554c0a3aSHans de Goede 3082554c0a3aSHans de Goede } 3083554c0a3aSHans de Goede 3084554c0a3aSHans de Goede } 3085554c0a3aSHans de Goede 3086554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3087554c0a3aSHans de Goede 3088554c0a3aSHans de Goede rtw_wep_encrypt(padapter, (u8 *)pmgntframe); 3089554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3090554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3091554c0a3aSHans de Goede } 3092554c0a3aSHans de Goede 3093554c0a3aSHans de Goede 3094554c0a3aSHans de Goede void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type) 3095554c0a3aSHans de Goede { 3096554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3097554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3098554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3099554c0a3aSHans de Goede unsigned char *pbuf, *pframe; 3100554c0a3aSHans de Goede unsigned short val; 3101554c0a3aSHans de Goede __le16 *fctrl; 3102554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3103554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 3104554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 3105554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3106554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); 3107554c0a3aSHans de Goede u8 *ie = pnetwork->IEs; 3108554c0a3aSHans de Goede __le16 lestatus, le_tmp; 3109554c0a3aSHans de Goede 3110554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3111554c0a3aSHans de Goede 3112554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3113554c0a3aSHans de Goede if (pmgntframe == NULL) 3114554c0a3aSHans de Goede return; 3115554c0a3aSHans de Goede 3116554c0a3aSHans de Goede /* update attribute */ 3117554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3118554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3119554c0a3aSHans de Goede 3120554c0a3aSHans de Goede 3121554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3122554c0a3aSHans de Goede 3123554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3124554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3125554c0a3aSHans de Goede 3126554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3127554c0a3aSHans de Goede *(fctrl) = 0; 3128554c0a3aSHans de Goede 3129554c0a3aSHans de Goede memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); 3130554c0a3aSHans de Goede memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN); 3131554c0a3aSHans de Goede memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3132554c0a3aSHans de Goede 3133554c0a3aSHans de Goede 3134554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3135554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3136554c0a3aSHans de Goede if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP)) 3137554c0a3aSHans de Goede SetFrameSubType(pwlanhdr, pkt_type); 3138554c0a3aSHans de Goede else 3139554c0a3aSHans de Goede return; 3140554c0a3aSHans de Goede 3141554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 3142554c0a3aSHans de Goede pattrib->pktlen += pattrib->hdrlen; 3143554c0a3aSHans de Goede pframe += pattrib->hdrlen; 3144554c0a3aSHans de Goede 3145554c0a3aSHans de Goede /* capability */ 3146554c0a3aSHans de Goede val = *(unsigned short *)rtw_get_capability_from_ie(ie); 3147554c0a3aSHans de Goede 3148554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen)); 3149554c0a3aSHans de Goede 3150554c0a3aSHans de Goede lestatus = cpu_to_le16(status); 3151554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen)); 3152554c0a3aSHans de Goede 3153554c0a3aSHans de Goede le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15)); 3154554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3155554c0a3aSHans de Goede 3156554c0a3aSHans de Goede if (pstat->bssratelen <= 8) { 3157554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen)); 3158554c0a3aSHans de Goede } else { 3159554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen)); 3160554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen)); 3161554c0a3aSHans de Goede } 3162554c0a3aSHans de Goede 3163554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) { 3164554c0a3aSHans de Goede uint ie_len = 0; 3165554c0a3aSHans de Goede 3166554c0a3aSHans de Goede /* FILL HT CAP INFO IE */ 3167554c0a3aSHans de Goede /* p = hostapd_eid_ht_capabilities_info(hapd, p); */ 3168554c0a3aSHans de Goede pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); 3169554c0a3aSHans de Goede if (pbuf && ie_len > 0) { 3170554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 3171554c0a3aSHans de Goede pframe += (ie_len+2); 3172554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 3173554c0a3aSHans de Goede } 3174554c0a3aSHans de Goede 3175554c0a3aSHans de Goede /* FILL HT ADD INFO IE */ 3176554c0a3aSHans de Goede /* p = hostapd_eid_ht_operation(hapd, p); */ 3177554c0a3aSHans de Goede pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); 3178554c0a3aSHans de Goede if (pbuf && ie_len > 0) { 3179554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 3180554c0a3aSHans de Goede pframe += (ie_len+2); 3181554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 3182554c0a3aSHans de Goede } 3183554c0a3aSHans de Goede 3184554c0a3aSHans de Goede } 3185554c0a3aSHans de Goede 3186554c0a3aSHans de Goede /* FILL WMM IE */ 3187554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) { 3188554c0a3aSHans de Goede uint ie_len = 0; 3189554c0a3aSHans de Goede unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; 3190554c0a3aSHans de Goede 3191554c0a3aSHans de Goede for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) { 3192554c0a3aSHans de Goede pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); 3193554c0a3aSHans de Goede if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) { 3194554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 3195554c0a3aSHans de Goede pframe += (ie_len+2); 3196554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 3197554c0a3aSHans de Goede 3198554c0a3aSHans de Goede break; 3199554c0a3aSHans de Goede } 3200554c0a3aSHans de Goede 3201554c0a3aSHans de Goede if ((pbuf == NULL) || (ie_len == 0)) { 3202554c0a3aSHans de Goede break; 3203554c0a3aSHans de Goede } 3204554c0a3aSHans de Goede } 3205554c0a3aSHans de Goede 3206554c0a3aSHans de Goede } 3207554c0a3aSHans de Goede 3208554c0a3aSHans de Goede if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) { 3209554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen)); 3210554c0a3aSHans de Goede } 3211554c0a3aSHans de Goede 3212554c0a3aSHans de Goede /* add WPS IE ie for wps 2.0 */ 3213554c0a3aSHans de Goede if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) { 3214554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len); 3215554c0a3aSHans de Goede 3216554c0a3aSHans de Goede pframe += pmlmepriv->wps_assoc_resp_ie_len; 3217554c0a3aSHans de Goede pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len; 3218554c0a3aSHans de Goede } 3219554c0a3aSHans de Goede 3220554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3221554c0a3aSHans de Goede 3222554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3223554c0a3aSHans de Goede } 3224554c0a3aSHans de Goede 3225554c0a3aSHans de Goede void issue_assocreq(struct adapter *padapter) 3226554c0a3aSHans de Goede { 3227554c0a3aSHans de Goede int ret = _FAIL; 3228554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3229554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3230554c0a3aSHans de Goede unsigned char *pframe; 3231554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3232554c0a3aSHans de Goede __le16 *fctrl; 3233554c0a3aSHans de Goede __le16 val16; 3234554c0a3aSHans de Goede unsigned int i, j, index = 0; 3235554c0a3aSHans de Goede unsigned char bssrate[NumRates], sta_bssrate[NumRates]; 3236554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 3237554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3238554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 3239554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3240554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3241554c0a3aSHans de Goede int bssrate_len = 0, sta_bssrate_len = 0; 3242554c0a3aSHans de Goede u8 vs_ie_length = 0; 3243554c0a3aSHans de Goede 3244554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3245554c0a3aSHans de Goede if (pmgntframe == NULL) 3246554c0a3aSHans de Goede goto exit; 3247554c0a3aSHans de Goede 3248554c0a3aSHans de Goede /* update attribute */ 3249554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3250554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3251554c0a3aSHans de Goede 3252554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3253554c0a3aSHans de Goede 3254554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3255554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3256554c0a3aSHans de Goede 3257554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3258554c0a3aSHans de Goede *(fctrl) = 0; 3259554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3260554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3261554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3262554c0a3aSHans de Goede 3263554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3264554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3265554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ASSOCREQ); 3266554c0a3aSHans de Goede 3267554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3268554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3269554c0a3aSHans de Goede 3270554c0a3aSHans de Goede /* caps */ 3271554c0a3aSHans de Goede memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); 3272554c0a3aSHans de Goede 3273554c0a3aSHans de Goede pframe += 2; 3274554c0a3aSHans de Goede pattrib->pktlen += 2; 3275554c0a3aSHans de Goede 3276554c0a3aSHans de Goede /* listen interval */ 3277554c0a3aSHans de Goede /* todo: listen interval for power saving */ 3278554c0a3aSHans de Goede val16 = cpu_to_le16(3); 3279554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)&val16, 2); 3280554c0a3aSHans de Goede pframe += 2; 3281554c0a3aSHans de Goede pattrib->pktlen += 2; 3282554c0a3aSHans de Goede 3283554c0a3aSHans de Goede /* SSID */ 3284554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen)); 3285554c0a3aSHans de Goede 3286554c0a3aSHans de Goede /* supported rate & extended supported rate */ 3287554c0a3aSHans de Goede 3288554c0a3aSHans de Goede /* Check if the AP's supported rates are also supported by STA. */ 3289554c0a3aSHans de Goede get_rate_set(padapter, sta_bssrate, &sta_bssrate_len); 3290554c0a3aSHans de Goede /* DBG_871X("sta_bssrate_len =%d\n", sta_bssrate_len); */ 3291554c0a3aSHans de Goede 3292554c0a3aSHans de Goede if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */ 3293554c0a3aSHans de Goede sta_bssrate_len = 4; 3294554c0a3aSHans de Goede 3295554c0a3aSHans de Goede 3296554c0a3aSHans de Goede /* for (i = 0; i < sta_bssrate_len; i++) { */ 3297554c0a3aSHans de Goede /* DBG_871X("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */ 3298554c0a3aSHans de Goede /* */ 3299554c0a3aSHans de Goede 3300554c0a3aSHans de Goede for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 3301554c0a3aSHans de Goede if (pmlmeinfo->network.SupportedRates[i] == 0) 3302554c0a3aSHans de Goede break; 3303554c0a3aSHans de Goede DBG_871X("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]); 3304554c0a3aSHans de Goede } 3305554c0a3aSHans de Goede 3306554c0a3aSHans de Goede 3307554c0a3aSHans de Goede for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 3308554c0a3aSHans de Goede if (pmlmeinfo->network.SupportedRates[i] == 0) 3309554c0a3aSHans de Goede break; 3310554c0a3aSHans de Goede 3311554c0a3aSHans de Goede 3312554c0a3aSHans de Goede /* Check if the AP's supported rates are also supported by STA. */ 3313554c0a3aSHans de Goede for (j = 0; j < sta_bssrate_len; j++) { 3314554c0a3aSHans de Goede /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ 3315554c0a3aSHans de Goede if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK) 3316554c0a3aSHans de Goede == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) { 3317554c0a3aSHans de Goede /* DBG_871X("match i = %d, j =%d\n", i, j); */ 3318554c0a3aSHans de Goede break; 3319554c0a3aSHans de Goede } else { 3320554c0a3aSHans de Goede /* DBG_871X("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */ 3321554c0a3aSHans de Goede } 3322554c0a3aSHans de Goede } 3323554c0a3aSHans de Goede 3324554c0a3aSHans de Goede if (j == sta_bssrate_len) { 3325554c0a3aSHans de Goede /* the rate is not supported by STA */ 3326554c0a3aSHans de Goede DBG_871X("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]); 3327554c0a3aSHans de Goede } else { 3328554c0a3aSHans de Goede /* the rate is supported by STA */ 3329554c0a3aSHans de Goede bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; 3330554c0a3aSHans de Goede } 3331554c0a3aSHans de Goede } 3332554c0a3aSHans de Goede 3333554c0a3aSHans de Goede bssrate_len = index; 3334554c0a3aSHans de Goede DBG_871X("bssrate_len = %d\n", bssrate_len); 3335554c0a3aSHans de Goede 3336554c0a3aSHans de Goede if (bssrate_len == 0) { 3337554c0a3aSHans de Goede rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); 3338554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pmgntframe); 3339554c0a3aSHans de Goede goto exit; /* don't connect to AP if no joint supported rate */ 3340554c0a3aSHans de Goede } 3341554c0a3aSHans de Goede 3342554c0a3aSHans de Goede 3343554c0a3aSHans de Goede if (bssrate_len > 8) { 3344554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen)); 3345554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); 3346554c0a3aSHans de Goede } else 3347554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen)); 3348554c0a3aSHans de Goede 3349554c0a3aSHans de Goede /* vendor specific IE, such as WPA, WMM, WPS */ 3350554c0a3aSHans de Goede for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) { 3351554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i); 3352554c0a3aSHans de Goede 3353554c0a3aSHans de Goede switch (pIE->ElementID) { 3354554c0a3aSHans de Goede case _VENDOR_SPECIFIC_IE_: 3355554c0a3aSHans de Goede if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) || 3356554c0a3aSHans de Goede (!memcmp(pIE->data, WMM_OUI, 4)) || 3357554c0a3aSHans de Goede (!memcmp(pIE->data, WPS_OUI, 4))) { 3358554c0a3aSHans de Goede vs_ie_length = pIE->Length; 3359554c0a3aSHans de Goede if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) { 33604d17363dSAndreas Hellmich /* Commented by Kurt 20110629 33614d17363dSAndreas Hellmich * In some older APs, WPS handshake 33624d17363dSAndreas Hellmich * would be fail if we append vendor 33634d17363dSAndreas Hellmich * extensions information to AP 33644d17363dSAndreas Hellmich */ 3365554c0a3aSHans de Goede 3366554c0a3aSHans de Goede vs_ie_length = 14; 3367554c0a3aSHans de Goede } 3368554c0a3aSHans de Goede 3369554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen)); 3370554c0a3aSHans de Goede } 3371554c0a3aSHans de Goede break; 3372554c0a3aSHans de Goede 3373554c0a3aSHans de Goede case EID_WPA2: 3374554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen)); 3375554c0a3aSHans de Goede break; 3376554c0a3aSHans de Goede case EID_HTCapability: 33770ad02fa8SGeorgiana Chelu if (padapter->mlmepriv.htpriv.ht_option) { 3378554c0a3aSHans de Goede if (!(is_ap_in_tkip(padapter))) { 3379554c0a3aSHans de Goede memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element)); 3380554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); 3381554c0a3aSHans de Goede } 3382554c0a3aSHans de Goede } 3383554c0a3aSHans de Goede break; 3384554c0a3aSHans de Goede 3385554c0a3aSHans de Goede case EID_EXTCapability: 33860ad02fa8SGeorgiana Chelu if (padapter->mlmepriv.htpriv.ht_option) 3387554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen)); 3388554c0a3aSHans de Goede break; 3389554c0a3aSHans de Goede default: 3390554c0a3aSHans de Goede break; 3391554c0a3aSHans de Goede } 3392554c0a3aSHans de Goede 3393554c0a3aSHans de Goede i += (pIE->Length + 2); 3394554c0a3aSHans de Goede } 3395554c0a3aSHans de Goede 3396554c0a3aSHans de Goede if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) 3397554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen)); 3398554c0a3aSHans de Goede 3399554c0a3aSHans de Goede 3400554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3401554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3402554c0a3aSHans de Goede 3403554c0a3aSHans de Goede ret = _SUCCESS; 3404554c0a3aSHans de Goede 3405554c0a3aSHans de Goede exit: 3406554c0a3aSHans de Goede if (ret == _SUCCESS) 3407554c0a3aSHans de Goede rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen); 3408554c0a3aSHans de Goede else 3409554c0a3aSHans de Goede rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len); 3410554c0a3aSHans de Goede } 3411554c0a3aSHans de Goede 341268468503SAndreas Hellmich /* when wait_ack is true, this function should be called at process context */ 341342b3b621SAishwarya Pant static int _issue_nulldata(struct adapter *padapter, unsigned char *da, 341442b3b621SAishwarya Pant unsigned int power_mode, bool wait_ack) 3415554c0a3aSHans de Goede { 3416554c0a3aSHans de Goede int ret = _FAIL; 3417554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3418554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3419554c0a3aSHans de Goede unsigned char *pframe; 3420554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3421554c0a3aSHans de Goede __le16 *fctrl; 3422554c0a3aSHans de Goede struct xmit_priv *pxmitpriv; 3423554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 3424554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 3425554c0a3aSHans de Goede 3426554c0a3aSHans de Goede /* DBG_871X("%s:%d\n", __func__, power_mode); */ 3427554c0a3aSHans de Goede 3428554c0a3aSHans de Goede if (!padapter) 3429554c0a3aSHans de Goede goto exit; 3430554c0a3aSHans de Goede 3431554c0a3aSHans de Goede pxmitpriv = &(padapter->xmitpriv); 3432554c0a3aSHans de Goede pmlmeext = &(padapter->mlmeextpriv); 3433554c0a3aSHans de Goede pmlmeinfo = &(pmlmeext->mlmext_info); 3434554c0a3aSHans de Goede 3435554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3436554c0a3aSHans de Goede if (pmgntframe == NULL) 3437554c0a3aSHans de Goede goto exit; 3438554c0a3aSHans de Goede 3439554c0a3aSHans de Goede /* update attribute */ 3440554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3441554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3442554c0a3aSHans de Goede pattrib->retry_ctrl = false; 3443554c0a3aSHans de Goede 3444554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3445554c0a3aSHans de Goede 3446554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3447554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3448554c0a3aSHans de Goede 3449554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3450554c0a3aSHans de Goede *(fctrl) = 0; 3451554c0a3aSHans de Goede 3452554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 3453554c0a3aSHans de Goede SetFrDs(fctrl); 3454554c0a3aSHans de Goede else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 3455554c0a3aSHans de Goede SetToDs(fctrl); 3456554c0a3aSHans de Goede 3457554c0a3aSHans de Goede if (power_mode) 3458554c0a3aSHans de Goede SetPwrMgt(fctrl); 3459554c0a3aSHans de Goede 3460554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3461554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3462554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3463554c0a3aSHans de Goede 3464554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3465554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3466554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DATA_NULL); 3467554c0a3aSHans de Goede 3468554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3469554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3470554c0a3aSHans de Goede 3471554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3472554c0a3aSHans de Goede 3473554c0a3aSHans de Goede if (wait_ack) { 3474554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3475554c0a3aSHans de Goede } else { 3476554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3477554c0a3aSHans de Goede ret = _SUCCESS; 3478554c0a3aSHans de Goede } 3479554c0a3aSHans de Goede 3480554c0a3aSHans de Goede exit: 3481554c0a3aSHans de Goede return ret; 3482554c0a3aSHans de Goede } 3483554c0a3aSHans de Goede 3484554c0a3aSHans de Goede /* 3485554c0a3aSHans de Goede * [IMPORTANT] Don't call this function in interrupt context 3486554c0a3aSHans de Goede * 348768468503SAndreas Hellmich * When wait_ms > 0, this function should be called at process context 3488554c0a3aSHans de Goede * da == NULL for station mode 3489554c0a3aSHans de Goede */ 3490554c0a3aSHans de Goede int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) 3491554c0a3aSHans de Goede { 3492554c0a3aSHans de Goede int ret; 3493554c0a3aSHans de Goede int i = 0; 3494554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3495554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3496554c0a3aSHans de Goede struct sta_info *psta; 3497554c0a3aSHans de Goede 3498554c0a3aSHans de Goede 349968468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 35005947e900SNishka Dasgupta if (!da) 3501554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3502554c0a3aSHans de Goede 3503554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, da); 3504554c0a3aSHans de Goede if (psta) { 3505554c0a3aSHans de Goede if (power_mode) 3506554c0a3aSHans de Goede rtw_hal_macid_sleep(padapter, psta->mac_id); 3507554c0a3aSHans de Goede else 3508554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 3509554c0a3aSHans de Goede } else { 3510bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for %pM, skip macid %s!!\n", 3511554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup"); 3512554c0a3aSHans de Goede rtw_warn_on(1); 3513554c0a3aSHans de Goede } 3514554c0a3aSHans de Goede 3515554c0a3aSHans de Goede do { 35169cdb1928SSaiyam Doshi ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0); 3517554c0a3aSHans de Goede 3518554c0a3aSHans de Goede i++; 3519554c0a3aSHans de Goede 3520554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3521554c0a3aSHans de Goede break; 3522554c0a3aSHans de Goede 3523554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 3524554c0a3aSHans de Goede msleep(wait_ms); 3525554c0a3aSHans de Goede 3526554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3527554c0a3aSHans de Goede 3528554c0a3aSHans de Goede if (ret != _FAIL) { 3529554c0a3aSHans de Goede ret = _SUCCESS; 3530554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3531554c0a3aSHans de Goede goto exit; 3532554c0a3aSHans de Goede #endif 3533554c0a3aSHans de Goede } 3534554c0a3aSHans de Goede 3535554c0a3aSHans de Goede if (try_cnt && wait_ms) { 3536554c0a3aSHans de Goede if (da) 3537bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", 3538554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), 3539554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3540554c0a3aSHans de Goede else 3541554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", 3542554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), 3543554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3544554c0a3aSHans de Goede } 3545554c0a3aSHans de Goede exit: 3546554c0a3aSHans de Goede return ret; 3547554c0a3aSHans de Goede } 3548554c0a3aSHans de Goede 3549554c0a3aSHans de Goede /* 3550554c0a3aSHans de Goede * [IMPORTANT] This function run in interrupt context 3551554c0a3aSHans de Goede * 3552554c0a3aSHans de Goede * The null data packet would be sent without power bit, 3553554c0a3aSHans de Goede * and not guarantee success. 3554554c0a3aSHans de Goede */ 3555554c0a3aSHans de Goede s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da) 3556554c0a3aSHans de Goede { 3557554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 3558554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 3559554c0a3aSHans de Goede 3560554c0a3aSHans de Goede 3561554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 3562554c0a3aSHans de Goede pmlmeinfo = &pmlmeext->mlmext_info; 3563554c0a3aSHans de Goede 356468468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 35655947e900SNishka Dasgupta if (!da) 3566554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3567554c0a3aSHans de Goede 356863ff599aSNishka Dasgupta return _issue_nulldata(padapter, da, 0, false); 3569554c0a3aSHans de Goede } 3570554c0a3aSHans de Goede 357168468503SAndreas Hellmich /* when wait_ack is true, this function should be called at process context */ 357242b3b621SAishwarya Pant static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, 357342b3b621SAishwarya Pant u16 tid, bool wait_ack) 3574554c0a3aSHans de Goede { 3575554c0a3aSHans de Goede int ret = _FAIL; 3576554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3577554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3578554c0a3aSHans de Goede unsigned char *pframe; 3579554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3580554c0a3aSHans de Goede __le16 *fctrl; 3581554c0a3aSHans de Goede u16 *qc; 3582554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3583554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3584554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3585554c0a3aSHans de Goede 3586554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3587554c0a3aSHans de Goede 3588554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3589554c0a3aSHans de Goede if (pmgntframe == NULL) 3590554c0a3aSHans de Goede goto exit; 3591554c0a3aSHans de Goede 3592554c0a3aSHans de Goede /* update attribute */ 3593554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3594554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3595554c0a3aSHans de Goede 3596554c0a3aSHans de Goede pattrib->hdrlen += 2; 3597554c0a3aSHans de Goede pattrib->qos_en = true; 3598554c0a3aSHans de Goede pattrib->eosp = 1; 3599554c0a3aSHans de Goede pattrib->ack_policy = 0; 3600554c0a3aSHans de Goede pattrib->mdata = 0; 3601554c0a3aSHans de Goede 3602554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3603554c0a3aSHans de Goede 3604554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3605554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3606554c0a3aSHans de Goede 3607554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3608554c0a3aSHans de Goede *(fctrl) = 0; 3609554c0a3aSHans de Goede 3610554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 3611554c0a3aSHans de Goede SetFrDs(fctrl); 3612554c0a3aSHans de Goede else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 3613554c0a3aSHans de Goede SetToDs(fctrl); 3614554c0a3aSHans de Goede 3615554c0a3aSHans de Goede if (pattrib->mdata) 3616554c0a3aSHans de Goede SetMData(fctrl); 3617554c0a3aSHans de Goede 3618554c0a3aSHans de Goede qc = (unsigned short *)(pframe + pattrib->hdrlen - 2); 3619554c0a3aSHans de Goede 3620554c0a3aSHans de Goede SetPriority(qc, tid); 3621554c0a3aSHans de Goede 3622554c0a3aSHans de Goede SetEOSP(qc, pattrib->eosp); 3623554c0a3aSHans de Goede 3624554c0a3aSHans de Goede SetAckpolicy(qc, pattrib->ack_policy); 3625554c0a3aSHans de Goede 3626554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3627554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3628554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3629554c0a3aSHans de Goede 3630554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3631554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3632554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); 3633554c0a3aSHans de Goede 3634554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_qos_hdr); 3635554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); 3636554c0a3aSHans de Goede 3637554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3638554c0a3aSHans de Goede 3639554c0a3aSHans de Goede if (wait_ack) { 3640554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3641554c0a3aSHans de Goede } else { 3642554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3643554c0a3aSHans de Goede ret = _SUCCESS; 3644554c0a3aSHans de Goede } 3645554c0a3aSHans de Goede 3646554c0a3aSHans de Goede exit: 3647554c0a3aSHans de Goede return ret; 3648554c0a3aSHans de Goede } 3649554c0a3aSHans de Goede 365068468503SAndreas Hellmich /* when wait_ms >0 , this function should be called at process context */ 3651554c0a3aSHans de Goede /* da == NULL for station mode */ 3652554c0a3aSHans de Goede int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms) 3653554c0a3aSHans de Goede { 3654554c0a3aSHans de Goede int ret; 3655554c0a3aSHans de Goede int i = 0; 3656554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3657554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3658554c0a3aSHans de Goede 365968468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 36605947e900SNishka Dasgupta if (!da) 3661554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3662554c0a3aSHans de Goede 3663554c0a3aSHans de Goede do { 36649cdb1928SSaiyam Doshi ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0); 3665554c0a3aSHans de Goede 3666554c0a3aSHans de Goede i++; 3667554c0a3aSHans de Goede 3668554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3669554c0a3aSHans de Goede break; 3670554c0a3aSHans de Goede 3671554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 3672554c0a3aSHans de Goede msleep(wait_ms); 3673554c0a3aSHans de Goede 3674554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3675554c0a3aSHans de Goede 3676554c0a3aSHans de Goede if (ret != _FAIL) { 3677554c0a3aSHans de Goede ret = _SUCCESS; 3678554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3679554c0a3aSHans de Goede goto exit; 3680554c0a3aSHans de Goede #endif 3681554c0a3aSHans de Goede } 3682554c0a3aSHans de Goede 3683554c0a3aSHans de Goede if (try_cnt && wait_ms) { 3684554c0a3aSHans de Goede if (da) 3685bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", 3686554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), 3687554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3688554c0a3aSHans de Goede else 3689554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", 3690554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), 3691554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3692554c0a3aSHans de Goede } 3693554c0a3aSHans de Goede exit: 3694554c0a3aSHans de Goede return ret; 3695554c0a3aSHans de Goede } 3696554c0a3aSHans de Goede 369742b3b621SAishwarya Pant static int _issue_deauth(struct adapter *padapter, unsigned char *da, 369842b3b621SAishwarya Pant unsigned short reason, bool wait_ack) 3699554c0a3aSHans de Goede { 3700554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3701554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3702554c0a3aSHans de Goede unsigned char *pframe; 3703554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3704554c0a3aSHans de Goede __le16 *fctrl; 3705554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3706554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3707554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3708554c0a3aSHans de Goede int ret = _FAIL; 3709554c0a3aSHans de Goede __le16 le_tmp; 3710554c0a3aSHans de Goede 3711bbda3ac4SRoss Schmidt /* DBG_871X("%s to %pM\n", __func__, MAC_ARG(da)); */ 3712554c0a3aSHans de Goede 3713554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3714554c0a3aSHans de Goede if (pmgntframe == NULL) { 3715554c0a3aSHans de Goede goto exit; 3716554c0a3aSHans de Goede } 3717554c0a3aSHans de Goede 3718554c0a3aSHans de Goede /* update attribute */ 3719554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3720554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3721554c0a3aSHans de Goede pattrib->retry_ctrl = false; 3722554c0a3aSHans de Goede 3723554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3724554c0a3aSHans de Goede 3725554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3726554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3727554c0a3aSHans de Goede 3728554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3729554c0a3aSHans de Goede *(fctrl) = 0; 3730554c0a3aSHans de Goede 3731554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3732554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3733554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3734554c0a3aSHans de Goede 3735554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3736554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3737554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DEAUTH); 3738554c0a3aSHans de Goede 3739554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3740554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3741554c0a3aSHans de Goede 3742554c0a3aSHans de Goede le_tmp = cpu_to_le16(reason); 3743554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3744554c0a3aSHans de Goede 3745554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3746554c0a3aSHans de Goede 3747554c0a3aSHans de Goede 3748554c0a3aSHans de Goede if (wait_ack) { 3749554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3750554c0a3aSHans de Goede } else { 3751554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3752554c0a3aSHans de Goede ret = _SUCCESS; 3753554c0a3aSHans de Goede } 3754554c0a3aSHans de Goede 3755554c0a3aSHans de Goede exit: 3756554c0a3aSHans de Goede return ret; 3757554c0a3aSHans de Goede } 3758554c0a3aSHans de Goede 3759554c0a3aSHans de Goede int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason) 3760554c0a3aSHans de Goede { 3761bbda3ac4SRoss Schmidt DBG_871X("%s to %pM\n", __func__, MAC_ARG(da)); 3762554c0a3aSHans de Goede return _issue_deauth(padapter, da, reason, false); 3763554c0a3aSHans de Goede } 3764554c0a3aSHans de Goede 3765554c0a3aSHans de Goede int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt, 3766554c0a3aSHans de Goede int wait_ms) 3767554c0a3aSHans de Goede { 3768554c0a3aSHans de Goede int ret; 3769554c0a3aSHans de Goede int i = 0; 3770554c0a3aSHans de Goede 3771554c0a3aSHans de Goede do { 37729cdb1928SSaiyam Doshi ret = _issue_deauth(padapter, da, reason, wait_ms > 0); 3773554c0a3aSHans de Goede 3774554c0a3aSHans de Goede i++; 3775554c0a3aSHans de Goede 3776554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3777554c0a3aSHans de Goede break; 3778554c0a3aSHans de Goede 3779554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 37801c8cb89eSJia-Ju Bai mdelay(wait_ms); 3781554c0a3aSHans de Goede 3782554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3783554c0a3aSHans de Goede 3784554c0a3aSHans de Goede if (ret != _FAIL) { 3785554c0a3aSHans de Goede ret = _SUCCESS; 3786554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3787554c0a3aSHans de Goede goto exit; 3788554c0a3aSHans de Goede #endif 3789554c0a3aSHans de Goede } 3790554c0a3aSHans de Goede 3791554c0a3aSHans de Goede if (try_cnt && wait_ms) { 3792554c0a3aSHans de Goede if (da) 3793bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", 3794554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), 3795554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3796554c0a3aSHans de Goede else 3797554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", 3798554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), 3799554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3800554c0a3aSHans de Goede } 3801554c0a3aSHans de Goede exit: 3802554c0a3aSHans de Goede return ret; 3803554c0a3aSHans de Goede } 3804554c0a3aSHans de Goede 3805554c0a3aSHans de Goede void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid) 3806554c0a3aSHans de Goede { 3807554c0a3aSHans de Goede u8 category = RTW_WLAN_CATEGORY_SA_QUERY; 3808554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3809554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3810554c0a3aSHans de Goede u8 *pframe; 3811554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3812554c0a3aSHans de Goede __le16 *fctrl; 3813554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3814554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3815554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3816554c0a3aSHans de Goede __le16 le_tmp; 3817554c0a3aSHans de Goede 3818554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3819554c0a3aSHans de Goede 3820554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3821554c0a3aSHans de Goede if (pmgntframe == NULL) { 3822554c0a3aSHans de Goede DBG_871X("%s: alloc_mgtxmitframe fail\n", __func__); 3823554c0a3aSHans de Goede return; 3824554c0a3aSHans de Goede } 3825554c0a3aSHans de Goede 3826554c0a3aSHans de Goede /* update attribute */ 3827554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3828554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3829554c0a3aSHans de Goede 3830554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3831554c0a3aSHans de Goede 3832554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3833554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3834554c0a3aSHans de Goede 3835554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3836554c0a3aSHans de Goede *(fctrl) = 0; 3837554c0a3aSHans de Goede 3838554c0a3aSHans de Goede if (raddr) 3839554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); 3840554c0a3aSHans de Goede else 3841554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3842554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3843554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3844554c0a3aSHans de Goede 3845554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3846554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3847554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3848554c0a3aSHans de Goede 3849554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3850554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3851554c0a3aSHans de Goede 3852554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); 3853554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); 3854554c0a3aSHans de Goede 3855554c0a3aSHans de Goede switch (action) { 3856554c0a3aSHans de Goede case 0: /* SA Query req */ 3857554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen); 3858554c0a3aSHans de Goede pmlmeext->sa_query_seq++; 3859554c0a3aSHans de Goede /* send sa query request to AP, AP should reply sa query response in 1 second */ 3860554c0a3aSHans de Goede set_sa_query_timer(pmlmeext, 1000); 3861554c0a3aSHans de Goede break; 3862554c0a3aSHans de Goede 3863554c0a3aSHans de Goede case 1: /* SA Query rsp */ 3864554c0a3aSHans de Goede le_tmp = cpu_to_le16(tid); 3865554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen); 3866554c0a3aSHans de Goede break; 3867554c0a3aSHans de Goede default: 3868554c0a3aSHans de Goede break; 3869554c0a3aSHans de Goede } 3870554c0a3aSHans de Goede 3871554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3872554c0a3aSHans de Goede 3873554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3874554c0a3aSHans de Goede } 3875554c0a3aSHans de Goede 3876554c0a3aSHans de Goede void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status) 3877554c0a3aSHans de Goede { 3878554c0a3aSHans de Goede u8 category = RTW_WLAN_CATEGORY_BACK; 3879554c0a3aSHans de Goede u16 start_seq; 3880554c0a3aSHans de Goede u16 BA_para_set; 3881554c0a3aSHans de Goede u16 reason_code; 3882554c0a3aSHans de Goede u16 BA_timeout_value; 3883554c0a3aSHans de Goede u16 BA_starting_seqctrl = 0; 3884554c0a3aSHans de Goede enum HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor; 3885554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3886554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3887554c0a3aSHans de Goede u8 *pframe; 3888554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3889554c0a3aSHans de Goede __le16 *fctrl; 3890554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3891554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3892554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3893554c0a3aSHans de Goede struct sta_info *psta; 3894554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 3895554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 3896554c0a3aSHans de Goede __le16 le_tmp; 3897554c0a3aSHans de Goede 3898554c0a3aSHans de Goede DBG_871X("%s, category =%d, action =%d, status =%d\n", __func__, category, action, status); 3899554c0a3aSHans de Goede 3900554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 390141452327SVatsala Narang if (!pmgntframe) 3902554c0a3aSHans de Goede return; 3903554c0a3aSHans de Goede 3904554c0a3aSHans de Goede /* update attribute */ 3905554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3906554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3907554c0a3aSHans de Goede 3908554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3909554c0a3aSHans de Goede 3910554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3911554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3912554c0a3aSHans de Goede 3913554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3914554c0a3aSHans de Goede *(fctrl) = 0; 3915554c0a3aSHans de Goede 3916554c0a3aSHans de Goede /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ 3917554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); 3918554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3919554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3920554c0a3aSHans de Goede 3921554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3922554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3923554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3924554c0a3aSHans de Goede 3925554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3926554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3927554c0a3aSHans de Goede 3928554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); 3929554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); 3930554c0a3aSHans de Goede 3931554c0a3aSHans de Goede if (category == 3) { 3932554c0a3aSHans de Goede switch (action) { 3933554c0a3aSHans de Goede case 0: /* ADDBA req */ 3934554c0a3aSHans de Goede do { 3935554c0a3aSHans de Goede pmlmeinfo->dialogToken++; 3936554c0a3aSHans de Goede } while (pmlmeinfo->dialogToken == 0); 3937554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen)); 3938554c0a3aSHans de Goede 3939d312a47fSNishka Dasgupta if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) { 3940554c0a3aSHans de Goede /* A-MSDU NOT Supported */ 3941554c0a3aSHans de Goede BA_para_set = 0; 3942554c0a3aSHans de Goede /* immediate Block Ack */ 3943f36fa2d9SPayal Kshirsagar BA_para_set |= BIT(1) & IEEE80211_ADDBA_PARAM_POLICY_MASK; 3944554c0a3aSHans de Goede /* TID */ 3945554c0a3aSHans de Goede BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK; 3946554c0a3aSHans de Goede /* max buffer size is 8 MSDU */ 3947554c0a3aSHans de Goede BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3948554c0a3aSHans de Goede } else { 3949554c0a3aSHans de Goede BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */ 3950554c0a3aSHans de Goede } 3951554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 3952554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3953554c0a3aSHans de Goede 3954554c0a3aSHans de Goede BA_timeout_value = 5000;/* 5ms */ 3955554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_timeout_value); 3956554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3957554c0a3aSHans de Goede 3958554c0a3aSHans de Goede /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */ 3959554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, raddr); 396034557e23SIzabela Bakollari if (psta) { 3961554c0a3aSHans de Goede start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1; 3962554c0a3aSHans de Goede 3963554c0a3aSHans de Goede DBG_871X("BA_starting_seqctrl = %d for TID =%d\n", start_seq, status & 0x07); 3964554c0a3aSHans de Goede 3965554c0a3aSHans de Goede psta->BA_starting_seqctrl[status & 0x07] = start_seq; 3966554c0a3aSHans de Goede 3967554c0a3aSHans de Goede BA_starting_seqctrl = start_seq << 4; 3968554c0a3aSHans de Goede } 3969554c0a3aSHans de Goede 3970554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_starting_seqctrl); 3971554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3972554c0a3aSHans de Goede break; 3973554c0a3aSHans de Goede 3974554c0a3aSHans de Goede case 1: /* ADDBA rsp */ 3975554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen)); 3976554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen)); 3977554c0a3aSHans de Goede if (padapter->driver_rx_ampdu_factor != 0xFF) 3978554c0a3aSHans de Goede max_rx_ampdu_factor = 3979554c0a3aSHans de Goede (enum HT_CAP_AMPDU_FACTOR)padapter->driver_rx_ampdu_factor; 3980554c0a3aSHans de Goede else 3981554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, 3982554c0a3aSHans de Goede HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); 3983554c0a3aSHans de Goede 3984554c0a3aSHans de Goede if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor) 3985554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */ 3986554c0a3aSHans de Goede else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor) 3987554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */ 3988554c0a3aSHans de Goede else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor) 3989554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */ 3990554c0a3aSHans de Goede else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor) 3991554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */ 3992554c0a3aSHans de Goede else 3993554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */ 3994554c0a3aSHans de Goede 3995d312a47fSNishka Dasgupta if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter) && 3996554c0a3aSHans de Goede padapter->driver_rx_ampdu_factor == 0xFF) { 3997554c0a3aSHans de Goede /* max buffer size is 8 MSDU */ 3998554c0a3aSHans de Goede BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3999554c0a3aSHans de Goede BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 4000554c0a3aSHans de Goede } 4001554c0a3aSHans de Goede 4002554c0a3aSHans de Goede if (pregpriv->ampdu_amsdu == 0)/* disabled */ 4003554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set & ~BIT(0)); 4004554c0a3aSHans de Goede else if (pregpriv->ampdu_amsdu == 1)/* enabled */ 4005554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set | BIT(0)); 4006554c0a3aSHans de Goede else /* auto */ 4007554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 4008554c0a3aSHans de Goede 4009554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 4010554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen)); 4011554c0a3aSHans de Goede break; 4012554c0a3aSHans de Goede case 2:/* DELBA */ 4013554c0a3aSHans de Goede BA_para_set = (status & 0x1F) << 3; 4014554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 4015554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 4016554c0a3aSHans de Goede 4017554c0a3aSHans de Goede reason_code = 37; 4018554c0a3aSHans de Goede le_tmp = cpu_to_le16(reason_code); 4019554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 4020554c0a3aSHans de Goede break; 4021554c0a3aSHans de Goede default: 4022554c0a3aSHans de Goede break; 4023554c0a3aSHans de Goede } 4024554c0a3aSHans de Goede } 4025554c0a3aSHans de Goede 4026554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 4027554c0a3aSHans de Goede 4028554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 4029554c0a3aSHans de Goede } 4030554c0a3aSHans de Goede 4031554c0a3aSHans de Goede static void issue_action_BSSCoexistPacket(struct adapter *padapter) 4032554c0a3aSHans de Goede { 4033554c0a3aSHans de Goede struct list_head *plist, *phead; 4034554c0a3aSHans de Goede unsigned char category, action; 4035554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 4036554c0a3aSHans de Goede struct pkt_attrib *pattrib; 4037554c0a3aSHans de Goede unsigned char *pframe; 4038554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 4039554c0a3aSHans de Goede __le16 *fctrl; 4040554c0a3aSHans de Goede struct wlan_network *pnetwork = NULL; 4041554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 4042554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4043554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 4044554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4045554c0a3aSHans de Goede struct __queue *queue = &(pmlmepriv->scanned_queue); 4046554c0a3aSHans de Goede u8 InfoContent[16] = {0}; 4047554c0a3aSHans de Goede u8 ICS[8][15]; 4048554c0a3aSHans de Goede 4049554c0a3aSHans de Goede if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0)) 4050554c0a3aSHans de Goede return; 4051554c0a3aSHans de Goede 4052554c0a3aSHans de Goede if (true == pmlmeinfo->bwmode_updated) 4053554c0a3aSHans de Goede return; 4054554c0a3aSHans de Goede 4055554c0a3aSHans de Goede 4056554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 4057554c0a3aSHans de Goede 4058554c0a3aSHans de Goede 4059554c0a3aSHans de Goede category = RTW_WLAN_CATEGORY_PUBLIC; 4060554c0a3aSHans de Goede action = ACT_PUBLIC_BSSCOEXIST; 4061554c0a3aSHans de Goede 4062554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 4063554c0a3aSHans de Goede if (pmgntframe == NULL) { 4064554c0a3aSHans de Goede return; 4065554c0a3aSHans de Goede } 4066554c0a3aSHans de Goede 4067554c0a3aSHans de Goede /* update attribute */ 4068554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 4069554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 4070554c0a3aSHans de Goede 4071554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 4072554c0a3aSHans de Goede 4073554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 4074554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 4075554c0a3aSHans de Goede 4076554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 4077554c0a3aSHans de Goede *(fctrl) = 0; 4078554c0a3aSHans de Goede 4079554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 4080554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 4081554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 4082554c0a3aSHans de Goede 4083554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 4084554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 4085554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 4086554c0a3aSHans de Goede 4087554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 4088554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 4089554c0a3aSHans de Goede 4090554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); 4091554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); 4092554c0a3aSHans de Goede 4093554c0a3aSHans de Goede 4094554c0a3aSHans de Goede /* */ 4095554c0a3aSHans de Goede if (pmlmepriv->num_FortyMHzIntolerant > 0) { 4096554c0a3aSHans de Goede u8 iedata = 0; 4097554c0a3aSHans de Goede 4098554c0a3aSHans de Goede iedata |= BIT(2);/* 20 MHz BSS Width Request */ 4099554c0a3aSHans de Goede 4100554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen)); 4101554c0a3aSHans de Goede 4102554c0a3aSHans de Goede } 4103554c0a3aSHans de Goede 4104554c0a3aSHans de Goede 4105554c0a3aSHans de Goede /* */ 4106554c0a3aSHans de Goede memset(ICS, 0, sizeof(ICS)); 4107554c0a3aSHans de Goede if (pmlmepriv->num_sta_no_ht > 0) { 4108554c0a3aSHans de Goede int i; 4109554c0a3aSHans de Goede 4110554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 4111554c0a3aSHans de Goede 4112554c0a3aSHans de Goede phead = get_list_head(queue); 4113554c0a3aSHans de Goede plist = get_next(phead); 4114554c0a3aSHans de Goede 4115554c0a3aSHans de Goede while (1) { 4116554c0a3aSHans de Goede int len; 4117554c0a3aSHans de Goede u8 *p; 4118554c0a3aSHans de Goede struct wlan_bssid_ex *pbss_network; 4119554c0a3aSHans de Goede 4120554c0a3aSHans de Goede if (phead == plist) 4121554c0a3aSHans de Goede break; 4122554c0a3aSHans de Goede 4123554c0a3aSHans de Goede pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); 4124554c0a3aSHans de Goede 4125554c0a3aSHans de Goede plist = get_next(plist); 4126554c0a3aSHans de Goede 4127554c0a3aSHans de Goede pbss_network = (struct wlan_bssid_ex *)&pnetwork->network; 4128554c0a3aSHans de Goede 4129554c0a3aSHans de Goede p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_); 4130554c0a3aSHans de Goede if ((p == NULL) || (len == 0)) {/* non-HT */ 4131554c0a3aSHans de Goede 4132554c0a3aSHans de Goede if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14)) 4133554c0a3aSHans de Goede continue; 4134554c0a3aSHans de Goede 4135554c0a3aSHans de Goede ICS[0][pbss_network->Configuration.DSConfig] = 1; 4136554c0a3aSHans de Goede 4137554c0a3aSHans de Goede if (ICS[0][0] == 0) 4138554c0a3aSHans de Goede ICS[0][0] = 1; 4139554c0a3aSHans de Goede } 4140554c0a3aSHans de Goede 4141554c0a3aSHans de Goede } 4142554c0a3aSHans de Goede 4143554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 4144554c0a3aSHans de Goede 4145554c0a3aSHans de Goede 4146554c0a3aSHans de Goede for (i = 0; i < 8; i++) { 4147554c0a3aSHans de Goede if (ICS[i][0] == 1) { 4148554c0a3aSHans de Goede int j, k = 0; 4149554c0a3aSHans de Goede 4150554c0a3aSHans de Goede InfoContent[k] = i; 4151554c0a3aSHans de Goede /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */ 4152554c0a3aSHans de Goede k++; 4153554c0a3aSHans de Goede 4154554c0a3aSHans de Goede for (j = 1; j <= 14; j++) { 4155554c0a3aSHans de Goede if (ICS[i][j] == 1) { 4156554c0a3aSHans de Goede if (k < 16) { 4157554c0a3aSHans de Goede InfoContent[k] = j; /* channel number */ 4158554c0a3aSHans de Goede /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */ 4159554c0a3aSHans de Goede k++; 4160554c0a3aSHans de Goede } 4161554c0a3aSHans de Goede } 4162554c0a3aSHans de Goede } 4163554c0a3aSHans de Goede 4164554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen)); 4165554c0a3aSHans de Goede 4166554c0a3aSHans de Goede } 4167554c0a3aSHans de Goede 4168554c0a3aSHans de Goede } 4169554c0a3aSHans de Goede 4170554c0a3aSHans de Goede 4171554c0a3aSHans de Goede } 4172554c0a3aSHans de Goede 4173554c0a3aSHans de Goede 4174554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 4175554c0a3aSHans de Goede 4176554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 4177554c0a3aSHans de Goede } 4178554c0a3aSHans de Goede 4179554c0a3aSHans de Goede unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr) 4180554c0a3aSHans de Goede { 4181554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4182554c0a3aSHans de Goede struct sta_info *psta = NULL; 4183554c0a3aSHans de Goede /* struct recv_reorder_ctrl *preorder_ctrl; */ 4184554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4185554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4186554c0a3aSHans de Goede u16 tid; 4187554c0a3aSHans de Goede 4188554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 4189554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) 4190554c0a3aSHans de Goede return _SUCCESS; 4191554c0a3aSHans de Goede 4192554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, addr); 4193554c0a3aSHans de Goede if (psta == NULL) 4194554c0a3aSHans de Goede return _SUCCESS; 4195554c0a3aSHans de Goede 4196554c0a3aSHans de Goede /* DBG_871X("%s:%s\n", __func__, (initiator == 0)?"RX_DIR":"TX_DIR"); */ 4197554c0a3aSHans de Goede 4198554c0a3aSHans de Goede if (initiator == 0) {/* recipient */ 4199554c0a3aSHans de Goede for (tid = 0; tid < MAXTID; tid++) { 42000ad02fa8SGeorgiana Chelu if (psta->recvreorder_ctrl[tid].enable) { 4201554c0a3aSHans de Goede DBG_871X("rx agg disable tid(%d)\n", tid); 4202*f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F)); 4203554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].enable = false; 4204554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; 4205554c0a3aSHans de Goede #ifdef DBG_RX_SEQ 4206554c0a3aSHans de Goede DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__, 4207554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].indicate_seq); 4208554c0a3aSHans de Goede #endif 4209554c0a3aSHans de Goede } 4210554c0a3aSHans de Goede } 4211554c0a3aSHans de Goede } else if (initiator == 1) {/* originator */ 4212554c0a3aSHans de Goede /* DBG_871X("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap); */ 4213554c0a3aSHans de Goede for (tid = 0; tid < MAXTID; tid++) { 4214554c0a3aSHans de Goede if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { 4215554c0a3aSHans de Goede DBG_871X("tx agg disable tid(%d)\n", tid); 4216*f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F)); 4217554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 4218554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); 4219554c0a3aSHans de Goede 4220554c0a3aSHans de Goede } 4221554c0a3aSHans de Goede } 4222554c0a3aSHans de Goede } 4223554c0a3aSHans de Goede 4224554c0a3aSHans de Goede return _SUCCESS; 4225554c0a3aSHans de Goede 4226554c0a3aSHans de Goede } 4227554c0a3aSHans de Goede 4228554c0a3aSHans de Goede unsigned int send_beacon(struct adapter *padapter) 4229554c0a3aSHans de Goede { 4230554c0a3aSHans de Goede u8 bxmitok = false; 4231554c0a3aSHans de Goede int issue = 0; 4232554c0a3aSHans de Goede int poll = 0; 4233554c0a3aSHans de Goede unsigned long start = jiffies; 4234554c0a3aSHans de Goede 4235554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); 4236554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); 4237554c0a3aSHans de Goede do { 4238554c0a3aSHans de Goede issue_beacon(padapter, 100); 4239554c0a3aSHans de Goede issue++; 4240554c0a3aSHans de Goede do { 4241c22da34aSThomas Avery cond_resched(); 4242554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok)); 4243554c0a3aSHans de Goede poll++; 4244554c0a3aSHans de Goede } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 4245554c0a3aSHans de Goede 4246554c0a3aSHans de Goede } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 4247554c0a3aSHans de Goede 4248554c0a3aSHans de Goede if (padapter->bSurpriseRemoved || padapter->bDriverStopped) { 4249554c0a3aSHans de Goede return _FAIL; 4250554c0a3aSHans de Goede } 4251554c0a3aSHans de Goede 4252554c0a3aSHans de Goede 4253554c0a3aSHans de Goede if (false == bxmitok) { 4254554c0a3aSHans de Goede DBG_871X("%s fail! %u ms\n", __func__, jiffies_to_msecs(jiffies - start)); 4255554c0a3aSHans de Goede return _FAIL; 4256554c0a3aSHans de Goede } else { 4257554c0a3aSHans de Goede unsigned long passing_time = jiffies_to_msecs(jiffies - start); 4258554c0a3aSHans de Goede 4259554c0a3aSHans de Goede if (passing_time > 100 || issue > 3) 4260554c0a3aSHans de Goede DBG_871X("%s success, issue:%d, poll:%d, %lu ms\n", __func__, issue, poll, passing_time); 4261554c0a3aSHans de Goede /* else */ 4262554c0a3aSHans de Goede /* DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, passing_time); */ 4263554c0a3aSHans de Goede 4264554c0a3aSHans de Goede return _SUCCESS; 4265554c0a3aSHans de Goede } 4266554c0a3aSHans de Goede } 4267554c0a3aSHans de Goede 4268554c0a3aSHans de Goede /**************************************************************************** 4269554c0a3aSHans de Goede 427068468503SAndreas Hellmich Following are some utility functions for WiFi MLME 4271554c0a3aSHans de Goede 4272554c0a3aSHans de Goede *****************************************************************************/ 4273554c0a3aSHans de Goede 4274554c0a3aSHans de Goede void site_survey(struct adapter *padapter) 4275554c0a3aSHans de Goede { 4276554c0a3aSHans de Goede unsigned char survey_channel = 0, val8; 4277554c0a3aSHans de Goede RT_SCAN_TYPE ScanType = SCAN_PASSIVE; 4278554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4279554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4280554c0a3aSHans de Goede u32 initialgain = 0; 4281554c0a3aSHans de Goede u32 channel_scan_time_ms = 0; 4282554c0a3aSHans de Goede 4283554c0a3aSHans de Goede { 4284554c0a3aSHans de Goede struct rtw_ieee80211_channel *ch; 4285c926f022SSimran Singhal 4286554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) { 4287554c0a3aSHans de Goede ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx]; 4288554c0a3aSHans de Goede survey_channel = ch->hw_value; 4289554c0a3aSHans de Goede ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE; 4290554c0a3aSHans de Goede } 4291554c0a3aSHans de Goede } 4292554c0a3aSHans de Goede 4293554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u) at %dms, %c%c%c\n" 4294554c0a3aSHans de Goede , FUNC_ADPT_ARG(padapter) 4295554c0a3aSHans de Goede , survey_channel 4296554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.channel_idx 4297554c0a3aSHans de Goede , jiffies_to_msecs(jiffies - padapter->mlmepriv.scan_start_time) 4298554c0a3aSHans de Goede , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P' 4299554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' ' 4300554c0a3aSHans de Goede ); 4301554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 4302554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan); 4303554c0a3aSHans de Goede #endif 4304554c0a3aSHans de Goede 4305554c0a3aSHans de Goede if (survey_channel != 0) { 4306554c0a3aSHans de Goede /* PAUSE 4-AC Queue when site_survey */ 4307554c0a3aSHans de Goede /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 4308554c0a3aSHans de Goede /* val8 |= 0x0f; */ 4309554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 4310554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.channel_idx == 0) { 4311554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 4312554c0a3aSHans de Goede if (pmlmeext->fixed_chan != 0xff) 4313554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 4314554c0a3aSHans de Goede else 4315554c0a3aSHans de Goede #endif 4316554c0a3aSHans de Goede set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 4317554c0a3aSHans de Goede } else { 4318554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 4319554c0a3aSHans de Goede if (pmlmeext->fixed_chan != 0xff) 4320554c0a3aSHans de Goede SelectChannel(padapter, pmlmeext->fixed_chan); 4321554c0a3aSHans de Goede else 4322554c0a3aSHans de Goede #endif 4323554c0a3aSHans de Goede SelectChannel(padapter, survey_channel); 4324554c0a3aSHans de Goede } 4325554c0a3aSHans de Goede 4326554c0a3aSHans de Goede if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */ 4327554c0a3aSHans de Goede { 4328554c0a3aSHans de Goede int i; 4329c926f022SSimran Singhal 4330554c0a3aSHans de Goede for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { 4331554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) { 4332554c0a3aSHans de Goede /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ 4333554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec) 4334554c0a3aSHans de Goede issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); 4335554c0a3aSHans de Goede else 4336554c0a3aSHans de Goede issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0); 4337554c0a3aSHans de Goede issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); 4338554c0a3aSHans de Goede } 4339554c0a3aSHans de Goede } 4340554c0a3aSHans de Goede 4341554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { 4342554c0a3aSHans de Goede /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ 4343554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec) 4344554c0a3aSHans de Goede issue_probereq(padapter, NULL, NULL); 4345554c0a3aSHans de Goede else 4346554c0a3aSHans de Goede issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0); 4347554c0a3aSHans de Goede issue_probereq(padapter, NULL, NULL); 4348554c0a3aSHans de Goede } 4349554c0a3aSHans de Goede } 4350554c0a3aSHans de Goede } 4351554c0a3aSHans de Goede 4352554c0a3aSHans de Goede channel_scan_time_ms = pmlmeext->chan_scan_time; 4353554c0a3aSHans de Goede 4354554c0a3aSHans de Goede set_survey_timer(pmlmeext, channel_scan_time_ms); 4355554c0a3aSHans de Goede #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) 4356554c0a3aSHans de Goede { 4357554c0a3aSHans de Goede struct noise_info info; 4358c926f022SSimran Singhal 4359554c0a3aSHans de Goede info.bPauseDIG = false; 4360554c0a3aSHans de Goede info.IGIValue = 0; 4361554c0a3aSHans de Goede info.max_time = channel_scan_time_ms/2;/* ms */ 4362554c0a3aSHans de Goede info.chan = survey_channel; 4363554c0a3aSHans de Goede rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &info, false); 4364554c0a3aSHans de Goede } 4365554c0a3aSHans de Goede #endif 4366554c0a3aSHans de Goede 4367554c0a3aSHans de Goede } else { 4368554c0a3aSHans de Goede 4369554c0a3aSHans de Goede /* channel number is 0 or this channel is not valid. */ 4370554c0a3aSHans de Goede 4371554c0a3aSHans de Goede { 4372554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_COMPLETE; 4373554c0a3aSHans de Goede 4374554c0a3aSHans de Goede /* switch back to the original channel */ 4375554c0a3aSHans de Goede /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */ 4376554c0a3aSHans de Goede 4377554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 4378554c0a3aSHans de Goede 4379554c0a3aSHans de Goede /* flush 4-AC Queue after site_survey */ 4380554c0a3aSHans de Goede /* val8 = 0; */ 4381554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 4382554c0a3aSHans de Goede 4383554c0a3aSHans de Goede /* config MSR */ 4384554c0a3aSHans de Goede Set_MSR(padapter, (pmlmeinfo->state & 0x3)); 4385554c0a3aSHans de Goede 4386554c0a3aSHans de Goede initialgain = 0xff; /* restore RX GAIN */ 4387554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 4388554c0a3aSHans de Goede /* turn on dynamic functions */ 4389554c0a3aSHans de Goede Restore_DM_Func_Flag(padapter); 4390554c0a3aSHans de Goede /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */ 4391554c0a3aSHans de Goede 43920ad02fa8SGeorgiana Chelu if (is_client_associated_to_ap(padapter)) 4393554c0a3aSHans de Goede issue_nulldata(padapter, NULL, 0, 3, 500); 4394554c0a3aSHans de Goede 4395554c0a3aSHans de Goede val8 = 0; /* survey done */ 4396554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); 4397554c0a3aSHans de Goede 4398554c0a3aSHans de Goede report_surveydone_event(padapter); 4399554c0a3aSHans de Goede 4400554c0a3aSHans de Goede pmlmeext->chan_scan_time = SURVEY_TO; 4401554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_DISABLE; 4402554c0a3aSHans de Goede 4403554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4404554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4405554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4406554c0a3aSHans de Goede } 4407554c0a3aSHans de Goede } 4408554c0a3aSHans de Goede 4409554c0a3aSHans de Goede return; 4410554c0a3aSHans de Goede 4411554c0a3aSHans de Goede } 4412554c0a3aSHans de Goede 4413554c0a3aSHans de Goede /* collect bss info from Beacon and Probe request/response frames. */ 4414554c0a3aSHans de Goede u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid) 4415554c0a3aSHans de Goede { 4416554c0a3aSHans de Goede int i; 4417554c0a3aSHans de Goede u32 len; 4418554c0a3aSHans de Goede u8 *p; 4419554c0a3aSHans de Goede u16 val16, subtype; 4420554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 4421554c0a3aSHans de Goede u32 packet_len = precv_frame->u.hdr.len; 4422554c0a3aSHans de Goede u8 ie_offset; 4423554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 4424554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4425554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4426554c0a3aSHans de Goede __le32 le32_tmp; 4427554c0a3aSHans de Goede 4428554c0a3aSHans de Goede len = packet_len - sizeof(struct ieee80211_hdr_3addr); 4429554c0a3aSHans de Goede 4430554c0a3aSHans de Goede if (len > MAX_IE_SZ) { 4431554c0a3aSHans de Goede /* DBG_871X("IE too long for survey event\n"); */ 4432554c0a3aSHans de Goede return _FAIL; 4433554c0a3aSHans de Goede } 4434554c0a3aSHans de Goede 4435554c0a3aSHans de Goede memset(bssid, 0, sizeof(struct wlan_bssid_ex)); 4436554c0a3aSHans de Goede 4437554c0a3aSHans de Goede subtype = GetFrameSubType(pframe); 4438554c0a3aSHans de Goede 4439554c0a3aSHans de Goede if (subtype == WIFI_BEACON) { 4440554c0a3aSHans de Goede bssid->Reserved[0] = 1; 4441554c0a3aSHans de Goede ie_offset = _BEACON_IE_OFFSET_; 4442554c0a3aSHans de Goede } else { 4443554c0a3aSHans de Goede /* FIXME : more type */ 4444554c0a3aSHans de Goede if (subtype == WIFI_PROBERSP) { 4445554c0a3aSHans de Goede ie_offset = _PROBERSP_IE_OFFSET_; 4446554c0a3aSHans de Goede bssid->Reserved[0] = 3; 4447554c0a3aSHans de Goede } else if (subtype == WIFI_PROBEREQ) { 4448554c0a3aSHans de Goede ie_offset = _PROBEREQ_IE_OFFSET_; 4449554c0a3aSHans de Goede bssid->Reserved[0] = 2; 4450554c0a3aSHans de Goede } else { 4451554c0a3aSHans de Goede bssid->Reserved[0] = 0; 4452554c0a3aSHans de Goede ie_offset = _FIXED_IE_LENGTH_; 4453554c0a3aSHans de Goede } 4454554c0a3aSHans de Goede } 4455554c0a3aSHans de Goede 4456554c0a3aSHans de Goede bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len; 4457554c0a3aSHans de Goede 4458554c0a3aSHans de Goede /* below is to copy the information element */ 4459554c0a3aSHans de Goede bssid->IELength = len; 4460554c0a3aSHans de Goede memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); 4461554c0a3aSHans de Goede 4462554c0a3aSHans de Goede /* get the signal strength */ 4463554c0a3aSHans de Goede bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /* in dBM.raw data */ 4464554c0a3aSHans de Goede bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */ 4465554c0a3aSHans de Goede bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */ 4466554c0a3aSHans de Goede 4467554c0a3aSHans de Goede /* checking SSID */ 4468554c0a3aSHans de Goede p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset); 4469554c0a3aSHans de Goede if (p == NULL) { 4470554c0a3aSHans de Goede DBG_871X("marc: cannot find SSID for survey event\n"); 4471554c0a3aSHans de Goede return _FAIL; 4472554c0a3aSHans de Goede } 4473554c0a3aSHans de Goede 4474554c0a3aSHans de Goede if (*(p + 1)) { 4475554c0a3aSHans de Goede if (len > NDIS_802_11_LENGTH_SSID) { 4476554c0a3aSHans de Goede DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); 4477554c0a3aSHans de Goede return _FAIL; 4478554c0a3aSHans de Goede } 4479554c0a3aSHans de Goede memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1)); 4480554c0a3aSHans de Goede bssid->Ssid.SsidLength = *(p + 1); 4481554c0a3aSHans de Goede } else 4482554c0a3aSHans de Goede bssid->Ssid.SsidLength = 0; 4483554c0a3aSHans de Goede 4484554c0a3aSHans de Goede memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); 4485554c0a3aSHans de Goede 4486554c0a3aSHans de Goede /* checking rate info... */ 4487554c0a3aSHans de Goede i = 0; 4488554c0a3aSHans de Goede p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset); 448934557e23SIzabela Bakollari if (p) { 4490554c0a3aSHans de Goede if (len > NDIS_802_11_LENGTH_RATES_EX) { 4491554c0a3aSHans de Goede DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); 4492554c0a3aSHans de Goede return _FAIL; 4493554c0a3aSHans de Goede } 4494554c0a3aSHans de Goede memcpy(bssid->SupportedRates, (p + 2), len); 4495554c0a3aSHans de Goede i = len; 4496554c0a3aSHans de Goede } 4497554c0a3aSHans de Goede 4498554c0a3aSHans de Goede p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset); 449934557e23SIzabela Bakollari if (p) { 4500554c0a3aSHans de Goede if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) { 4501554c0a3aSHans de Goede DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); 4502554c0a3aSHans de Goede return _FAIL; 4503554c0a3aSHans de Goede } 4504554c0a3aSHans de Goede memcpy(bssid->SupportedRates + i, (p + 2), len); 4505554c0a3aSHans de Goede } 4506554c0a3aSHans de Goede 4507554c0a3aSHans de Goede bssid->NetworkTypeInUse = Ndis802_11OFDM24; 4508554c0a3aSHans de Goede 4509554c0a3aSHans de Goede if (bssid->IELength < 12) 4510554c0a3aSHans de Goede return _FAIL; 4511554c0a3aSHans de Goede 4512554c0a3aSHans de Goede /* Checking for DSConfig */ 4513554c0a3aSHans de Goede p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset); 4514554c0a3aSHans de Goede 4515554c0a3aSHans de Goede bssid->Configuration.DSConfig = 0; 4516554c0a3aSHans de Goede bssid->Configuration.Length = 0; 4517554c0a3aSHans de Goede 4518554c0a3aSHans de Goede if (p) { 4519554c0a3aSHans de Goede bssid->Configuration.DSConfig = *(p + 2); 4520554c0a3aSHans de Goede } else { 4521554c0a3aSHans de Goede /* In 5G, some ap do not have DSSET IE */ 4522554c0a3aSHans de Goede /* checking HT info for channel */ 4523554c0a3aSHans de Goede p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset); 4524554c0a3aSHans de Goede if (p) { 4525554c0a3aSHans de Goede struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2); 4526c926f022SSimran Singhal 4527554c0a3aSHans de Goede bssid->Configuration.DSConfig = HT_info->primary_channel; 4528554c0a3aSHans de Goede } else { /* use current channel */ 4529554c0a3aSHans de Goede bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter); 4530554c0a3aSHans de Goede } 4531554c0a3aSHans de Goede } 4532554c0a3aSHans de Goede 4533554c0a3aSHans de Goede memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2); 4534554c0a3aSHans de Goede bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp); 4535554c0a3aSHans de Goede 4536554c0a3aSHans de Goede val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid); 4537554c0a3aSHans de Goede 4538554c0a3aSHans de Goede if (val16 & BIT(0)) { 4539554c0a3aSHans de Goede bssid->InfrastructureMode = Ndis802_11Infrastructure; 4540554c0a3aSHans de Goede memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); 4541554c0a3aSHans de Goede } else { 4542554c0a3aSHans de Goede bssid->InfrastructureMode = Ndis802_11IBSS; 4543554c0a3aSHans de Goede memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); 4544554c0a3aSHans de Goede } 4545554c0a3aSHans de Goede 4546554c0a3aSHans de Goede if (val16 & BIT(4)) 4547554c0a3aSHans de Goede bssid->Privacy = 1; 4548554c0a3aSHans de Goede else 4549554c0a3aSHans de Goede bssid->Privacy = 0; 4550554c0a3aSHans de Goede 4551554c0a3aSHans de Goede bssid->Configuration.ATIMWindow = 0; 4552554c0a3aSHans de Goede 4553554c0a3aSHans de Goede /* 20/40 BSS Coexistence check */ 4554554c0a3aSHans de Goede if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) { 4555554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4556554c0a3aSHans de Goede 4557554c0a3aSHans de Goede p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset); 4558554c0a3aSHans de Goede if (p && len > 0) { 4559554c0a3aSHans de Goede struct HT_caps_element *pHT_caps; 4560c926f022SSimran Singhal 4561554c0a3aSHans de Goede pHT_caps = (struct HT_caps_element *)(p + 2); 4562554c0a3aSHans de Goede 4563554c0a3aSHans de Goede if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14)) 4564554c0a3aSHans de Goede pmlmepriv->num_FortyMHzIntolerant++; 4565554c0a3aSHans de Goede } else 4566554c0a3aSHans de Goede pmlmepriv->num_sta_no_ht++; 4567554c0a3aSHans de Goede } 4568554c0a3aSHans de Goede 4569554c0a3aSHans de Goede #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1 4570554c0a3aSHans de Goede if (strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) { 4571bbda3ac4SRoss Schmidt DBG_871X("Receiving %s(%pM, DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n" 4572554c0a3aSHans de Goede , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig 4573554c0a3aSHans de Goede , rtw_get_oper_ch(padapter) 4574554c0a3aSHans de Goede , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi 4575554c0a3aSHans de Goede ); 4576554c0a3aSHans de Goede } 4577554c0a3aSHans de Goede #endif 4578554c0a3aSHans de Goede 457968468503SAndreas Hellmich /* mark bss info receiving from nearby channel as SignalQuality 101 */ 4580554c0a3aSHans de Goede if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter)) 4581554c0a3aSHans de Goede bssid->PhyInfo.SignalQuality = 101; 4582554c0a3aSHans de Goede 4583554c0a3aSHans de Goede return _SUCCESS; 4584554c0a3aSHans de Goede } 4585554c0a3aSHans de Goede 4586554c0a3aSHans de Goede void start_create_ibss(struct adapter *padapter) 4587554c0a3aSHans de Goede { 4588554c0a3aSHans de Goede unsigned short caps; 4589554c0a3aSHans de Goede u8 val8; 4590554c0a3aSHans de Goede u8 join_type; 4591554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4592554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4593554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4594c926f022SSimran Singhal 4595554c0a3aSHans de Goede pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; 4596554c0a3aSHans de Goede pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); 4597554c0a3aSHans de Goede 4598554c0a3aSHans de Goede /* update wireless mode */ 4599554c0a3aSHans de Goede update_wireless_mode(padapter); 4600554c0a3aSHans de Goede 460168468503SAndreas Hellmich /* update capability */ 4602554c0a3aSHans de Goede caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); 4603554c0a3aSHans de Goede update_capinfo(padapter, caps); 4604554c0a3aSHans de Goede if (caps&cap_IBSS) {/* adhoc master */ 4605554c0a3aSHans de Goede val8 = 0xcf; 4606554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4607554c0a3aSHans de Goede 4608554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL); 4609554c0a3aSHans de Goede 4610554c0a3aSHans de Goede /* switch channel */ 4611554c0a3aSHans de Goede /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */ 4612554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 4613554c0a3aSHans de Goede 4614554c0a3aSHans de Goede beacon_timing_control(padapter); 4615554c0a3aSHans de Goede 4616554c0a3aSHans de Goede /* set msr to WIFI_FW_ADHOC_STATE */ 4617554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_ADHOC_STATE; 4618554c0a3aSHans de Goede Set_MSR(padapter, (pmlmeinfo->state & 0x3)); 4619554c0a3aSHans de Goede 4620554c0a3aSHans de Goede /* issue beacon */ 4621554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 4622554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n")); 4623554c0a3aSHans de Goede 4624554c0a3aSHans de Goede report_join_res(padapter, -1); 4625554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4626554c0a3aSHans de Goede } else { 4627554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress); 4628554c0a3aSHans de Goede join_type = 0; 4629554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 4630554c0a3aSHans de Goede 4631554c0a3aSHans de Goede report_join_res(padapter, 1); 4632554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 4633554c0a3aSHans de Goede rtw_indicate_connect(padapter); 4634554c0a3aSHans de Goede } 4635554c0a3aSHans de Goede } else { 4636554c0a3aSHans de Goede DBG_871X("start_create_ibss, invalid cap:%x\n", caps); 4637554c0a3aSHans de Goede return; 4638554c0a3aSHans de Goede } 4639554c0a3aSHans de Goede /* update bc/mc sta_info */ 4640554c0a3aSHans de Goede update_bmc_sta(padapter); 4641554c0a3aSHans de Goede 4642554c0a3aSHans de Goede } 4643554c0a3aSHans de Goede 4644554c0a3aSHans de Goede void start_clnt_join(struct adapter *padapter) 4645554c0a3aSHans de Goede { 4646554c0a3aSHans de Goede unsigned short caps; 4647554c0a3aSHans de Goede u8 val8; 4648554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4649554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4650554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4651554c0a3aSHans de Goede int beacon_timeout; 4652554c0a3aSHans de Goede 4653554c0a3aSHans de Goede /* update wireless mode */ 4654554c0a3aSHans de Goede update_wireless_mode(padapter); 4655554c0a3aSHans de Goede 465668468503SAndreas Hellmich /* update capability */ 4657554c0a3aSHans de Goede caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); 4658554c0a3aSHans de Goede update_capinfo(padapter, caps); 4659554c0a3aSHans de Goede if (caps&cap_ESS) { 4660554c0a3aSHans de Goede Set_MSR(padapter, WIFI_FW_STATION_STATE); 4661554c0a3aSHans de Goede 4662554c0a3aSHans de Goede val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; 4663554c0a3aSHans de Goede 4664554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4665554c0a3aSHans de Goede 4666554c0a3aSHans de Goede /* Because of AP's not receiving deauth before */ 4667554c0a3aSHans de Goede /* AP may: 1)not response auth or 2)deauth us after link is complete */ 4668554c0a3aSHans de Goede /* issue deauth before issuing auth to deal with the situation */ 4669554c0a3aSHans de Goede 4670554c0a3aSHans de Goede /* Commented by Albert 2012/07/21 */ 4671554c0a3aSHans de Goede /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */ 4672554c0a3aSHans de Goede { 4673554c0a3aSHans de Goede /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */ 4674554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); 4675554c0a3aSHans de Goede } 4676554c0a3aSHans de Goede 4677554c0a3aSHans de Goede /* here wait for receiving the beacon to start auth */ 4678554c0a3aSHans de Goede /* and enable a timer */ 4679554c0a3aSHans de Goede beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval); 4680554c0a3aSHans de Goede set_link_timer(pmlmeext, beacon_timeout); 4681554c0a3aSHans de Goede _set_timer(&padapter->mlmepriv.assoc_timer, 4682554c0a3aSHans de Goede (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout); 4683554c0a3aSHans de Goede 4684554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; 4685554c0a3aSHans de Goede } else if (caps&cap_IBSS) { /* adhoc client */ 4686554c0a3aSHans de Goede Set_MSR(padapter, WIFI_FW_ADHOC_STATE); 4687554c0a3aSHans de Goede 4688554c0a3aSHans de Goede val8 = 0xcf; 4689554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4690554c0a3aSHans de Goede 4691554c0a3aSHans de Goede beacon_timing_control(padapter); 4692554c0a3aSHans de Goede 4693554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_ADHOC_STATE; 4694554c0a3aSHans de Goede 4695554c0a3aSHans de Goede report_join_res(padapter, 1); 4696554c0a3aSHans de Goede } else { 4697554c0a3aSHans de Goede /* DBG_871X("marc: invalid cap:%x\n", caps); */ 4698554c0a3aSHans de Goede return; 4699554c0a3aSHans de Goede } 4700554c0a3aSHans de Goede 4701554c0a3aSHans de Goede } 4702554c0a3aSHans de Goede 4703554c0a3aSHans de Goede void start_clnt_auth(struct adapter *padapter) 4704554c0a3aSHans de Goede { 4705554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4706554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4707554c0a3aSHans de Goede 4708554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4709554c0a3aSHans de Goede 4710554c0a3aSHans de Goede pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); 4711554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_AUTH_STATE; 4712554c0a3aSHans de Goede 4713554c0a3aSHans de Goede pmlmeinfo->auth_seq = 1; 4714554c0a3aSHans de Goede pmlmeinfo->reauth_count = 0; 4715554c0a3aSHans de Goede pmlmeinfo->reassoc_count = 0; 4716554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 4717554c0a3aSHans de Goede pmlmeext->retry = 0; 4718554c0a3aSHans de Goede 4719554c0a3aSHans de Goede 4720554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "start auth\n"); 4721554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 4722554c0a3aSHans de Goede 4723554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 4724554c0a3aSHans de Goede 4725554c0a3aSHans de Goede } 4726554c0a3aSHans de Goede 4727554c0a3aSHans de Goede 4728554c0a3aSHans de Goede void start_clnt_assoc(struct adapter *padapter) 4729554c0a3aSHans de Goede { 4730554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4731554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4732554c0a3aSHans de Goede 4733554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4734554c0a3aSHans de Goede 4735554c0a3aSHans de Goede pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); 4736554c0a3aSHans de Goede pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); 4737554c0a3aSHans de Goede 4738554c0a3aSHans de Goede issue_assocreq(padapter); 4739554c0a3aSHans de Goede 4740554c0a3aSHans de Goede set_link_timer(pmlmeext, REASSOC_TO); 4741554c0a3aSHans de Goede } 4742554c0a3aSHans de Goede 4743554c0a3aSHans de Goede unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) 4744554c0a3aSHans de Goede { 4745554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4746554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4747554c0a3aSHans de Goede 4748554c0a3aSHans de Goede /* check A3 */ 4749554c0a3aSHans de Goede if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN))) 4750554c0a3aSHans de Goede return _SUCCESS; 4751554c0a3aSHans de Goede 4752554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 4753554c0a3aSHans de Goede 4754554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 4755554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { 4756554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4757554c0a3aSHans de Goede report_del_sta_event(padapter, MacAddr, reason); 4758554c0a3aSHans de Goede 4759554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { 4760554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4761554c0a3aSHans de Goede report_join_res(padapter, -2); 4762554c0a3aSHans de Goede } 4763554c0a3aSHans de Goede } 4764554c0a3aSHans de Goede 4765554c0a3aSHans de Goede return _SUCCESS; 4766554c0a3aSHans de Goede } 4767554c0a3aSHans de Goede 4768554c0a3aSHans de Goede static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid) 4769554c0a3aSHans de Goede { 4770554c0a3aSHans de Goede struct registry_priv *pregistrypriv; 4771554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 4772554c0a3aSHans de Goede RT_CHANNEL_INFO *chplan_new; 4773554c0a3aSHans de Goede u8 channel; 4774554c0a3aSHans de Goede u8 i; 4775554c0a3aSHans de Goede 4776554c0a3aSHans de Goede 4777554c0a3aSHans de Goede pregistrypriv = &padapter->registrypriv; 4778554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 4779554c0a3aSHans de Goede 4780554c0a3aSHans de Goede /* Adjust channel plan by AP Country IE */ 4781554c0a3aSHans de Goede if (pregistrypriv->enable80211d && 4782554c0a3aSHans de Goede (!pmlmeext->update_channel_plan_by_ap_done)) { 4783554c0a3aSHans de Goede u8 *ie, *p; 4784554c0a3aSHans de Goede u32 len; 4785554c0a3aSHans de Goede RT_CHANNEL_PLAN chplan_ap; 4786554c0a3aSHans de Goede RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM]; 4787554c0a3aSHans de Goede u8 country[4]; 4788554c0a3aSHans de Goede u8 fcn; /* first channel number */ 4789554c0a3aSHans de Goede u8 noc; /* number of channel */ 4790554c0a3aSHans de Goede u8 j, k; 4791554c0a3aSHans de Goede 4792554c0a3aSHans de Goede ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); 4793554c0a3aSHans de Goede if (!ie) 4794554c0a3aSHans de Goede return; 4795554c0a3aSHans de Goede if (len < 6) 4796554c0a3aSHans de Goede return; 4797554c0a3aSHans de Goede 4798554c0a3aSHans de Goede ie += 2; 4799554c0a3aSHans de Goede p = ie; 4800554c0a3aSHans de Goede ie += len; 4801554c0a3aSHans de Goede 4802554c0a3aSHans de Goede memset(country, 0, 4); 4803554c0a3aSHans de Goede memcpy(country, p, 3); 4804554c0a3aSHans de Goede p += 3; 4805554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, 4806554c0a3aSHans de Goede ("%s: 802.11d country =%s\n", __func__, country)); 4807554c0a3aSHans de Goede 4808554c0a3aSHans de Goede i = 0; 4809554c0a3aSHans de Goede while ((ie - p) >= 3) { 4810554c0a3aSHans de Goede fcn = *(p++); 4811554c0a3aSHans de Goede noc = *(p++); 4812554c0a3aSHans de Goede p++; 4813554c0a3aSHans de Goede 4814554c0a3aSHans de Goede for (j = 0; j < noc; j++) { 4815554c0a3aSHans de Goede if (fcn <= 14) 4816554c0a3aSHans de Goede channel = fcn + j; /* 2.4 GHz */ 4817554c0a3aSHans de Goede else 4818554c0a3aSHans de Goede channel = fcn + j*4; /* 5 GHz */ 4819554c0a3aSHans de Goede 4820554c0a3aSHans de Goede chplan_ap.Channel[i++] = channel; 4821554c0a3aSHans de Goede } 4822554c0a3aSHans de Goede } 4823554c0a3aSHans de Goede chplan_ap.Len = i; 4824554c0a3aSHans de Goede 4825f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4826554c0a3aSHans de Goede i = 0; 4827554c0a3aSHans de Goede DBG_871X("%s: AP[%s] channel plan {", __func__, bssid->Ssid.Ssid); 4828554c0a3aSHans de Goede while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) { 4829554c0a3aSHans de Goede DBG_8192C("%02d,", chplan_ap.Channel[i]); 4830554c0a3aSHans de Goede i++; 4831554c0a3aSHans de Goede } 4832554c0a3aSHans de Goede DBG_871X("}\n"); 4833554c0a3aSHans de Goede #endif 4834554c0a3aSHans de Goede 4835554c0a3aSHans de Goede memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta)); 4836f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4837554c0a3aSHans de Goede i = 0; 4838554c0a3aSHans de Goede DBG_871X("%s: STA channel plan {", __func__); 4839554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4840554c0a3aSHans de Goede DBG_871X("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType == SCAN_PASSIVE?'p':'a'); 4841554c0a3aSHans de Goede i++; 4842554c0a3aSHans de Goede } 4843554c0a3aSHans de Goede DBG_871X("}\n"); 4844554c0a3aSHans de Goede #endif 4845554c0a3aSHans de Goede 4846554c0a3aSHans de Goede memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set)); 4847554c0a3aSHans de Goede chplan_new = pmlmeext->channel_set; 4848554c0a3aSHans de Goede 4849554c0a3aSHans de Goede i = j = k = 0; 4850554c0a3aSHans de Goede if (pregistrypriv->wireless_mode & WIRELESS_11G) { 4851554c0a3aSHans de Goede do { 4852554c0a3aSHans de Goede if ((i == MAX_CHANNEL_NUM) || 4853554c0a3aSHans de Goede (chplan_sta[i].ChannelNum == 0) || 4854554c0a3aSHans de Goede (chplan_sta[i].ChannelNum > 14)) 4855554c0a3aSHans de Goede break; 4856554c0a3aSHans de Goede 4857554c0a3aSHans de Goede if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14)) 4858554c0a3aSHans de Goede break; 4859554c0a3aSHans de Goede 4860554c0a3aSHans de Goede if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { 4861554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4862554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4863554c0a3aSHans de Goede i++; 4864554c0a3aSHans de Goede j++; 4865554c0a3aSHans de Goede k++; 4866554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { 4867554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4868554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4869554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4870554c0a3aSHans de Goede i++; 4871554c0a3aSHans de Goede k++; 4872554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { 4873554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4874554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4875554c0a3aSHans de Goede j++; 4876554c0a3aSHans de Goede k++; 4877554c0a3aSHans de Goede } 4878554c0a3aSHans de Goede } while (1); 4879554c0a3aSHans de Goede 4880554c0a3aSHans de Goede /* change AP not support channel to Passive scan */ 4881554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && 4882554c0a3aSHans de Goede (chplan_sta[i].ChannelNum != 0) && 4883554c0a3aSHans de Goede (chplan_sta[i].ChannelNum <= 14)) { 4884554c0a3aSHans de Goede 4885554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4886554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4887554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4888554c0a3aSHans de Goede i++; 4889554c0a3aSHans de Goede k++; 4890554c0a3aSHans de Goede } 4891554c0a3aSHans de Goede 4892554c0a3aSHans de Goede /* add channel AP supported */ 4893554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { 4894554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4895554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4896554c0a3aSHans de Goede j++; 4897554c0a3aSHans de Goede k++; 4898554c0a3aSHans de Goede } 4899554c0a3aSHans de Goede } else { 4900554c0a3aSHans de Goede /* keep original STA 2.4G channel plan */ 4901554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && 4902554c0a3aSHans de Goede (chplan_sta[i].ChannelNum != 0) && 4903554c0a3aSHans de Goede (chplan_sta[i].ChannelNum <= 14)) { 4904554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4905554c0a3aSHans de Goede chplan_new[k].ScanType = chplan_sta[i].ScanType; 4906554c0a3aSHans de Goede i++; 4907554c0a3aSHans de Goede k++; 4908554c0a3aSHans de Goede } 4909554c0a3aSHans de Goede 4910554c0a3aSHans de Goede /* skip AP 2.4G channel plan */ 4911554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { 4912554c0a3aSHans de Goede j++; 4913554c0a3aSHans de Goede } 4914554c0a3aSHans de Goede } 4915554c0a3aSHans de Goede 4916554c0a3aSHans de Goede if (pregistrypriv->wireless_mode & WIRELESS_11A) { 4917554c0a3aSHans de Goede do { 4918554c0a3aSHans de Goede if ((i == MAX_CHANNEL_NUM) || 4919554c0a3aSHans de Goede (chplan_sta[i].ChannelNum == 0)) 4920554c0a3aSHans de Goede break; 4921554c0a3aSHans de Goede 4922554c0a3aSHans de Goede if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0)) 4923554c0a3aSHans de Goede break; 4924554c0a3aSHans de Goede 4925554c0a3aSHans de Goede if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { 4926554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4927554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4928554c0a3aSHans de Goede i++; 4929554c0a3aSHans de Goede j++; 4930554c0a3aSHans de Goede k++; 4931554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { 4932554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4933554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4934554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4935554c0a3aSHans de Goede i++; 4936554c0a3aSHans de Goede k++; 4937554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { 4938554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4939554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4940554c0a3aSHans de Goede j++; 4941554c0a3aSHans de Goede k++; 4942554c0a3aSHans de Goede } 4943554c0a3aSHans de Goede } while (1); 4944554c0a3aSHans de Goede 4945554c0a3aSHans de Goede /* change AP not support channel to Passive scan */ 4946554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4947554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4948554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4949554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4950554c0a3aSHans de Goede i++; 4951554c0a3aSHans de Goede k++; 4952554c0a3aSHans de Goede } 4953554c0a3aSHans de Goede 4954554c0a3aSHans de Goede /* add channel AP supported */ 4955554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) { 4956554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4957554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4958554c0a3aSHans de Goede j++; 4959554c0a3aSHans de Goede k++; 4960554c0a3aSHans de Goede } 4961554c0a3aSHans de Goede } else { 4962554c0a3aSHans de Goede /* keep original STA 5G channel plan */ 4963554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4964554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4965554c0a3aSHans de Goede chplan_new[k].ScanType = chplan_sta[i].ScanType; 4966554c0a3aSHans de Goede i++; 4967554c0a3aSHans de Goede k++; 4968554c0a3aSHans de Goede } 4969554c0a3aSHans de Goede } 4970554c0a3aSHans de Goede 4971554c0a3aSHans de Goede pmlmeext->update_channel_plan_by_ap_done = 1; 4972554c0a3aSHans de Goede 4973f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4974554c0a3aSHans de Goede k = 0; 4975554c0a3aSHans de Goede DBG_871X("%s: new STA channel plan {", __func__); 4976554c0a3aSHans de Goede while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) { 4977554c0a3aSHans de Goede DBG_871X("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType == SCAN_PASSIVE?'p':'c'); 4978554c0a3aSHans de Goede k++; 4979554c0a3aSHans de Goede } 4980554c0a3aSHans de Goede DBG_871X("}\n"); 4981554c0a3aSHans de Goede #endif 4982554c0a3aSHans de Goede } 4983554c0a3aSHans de Goede 4984554c0a3aSHans de Goede /* If channel is used by AP, set channel scan type to active */ 4985554c0a3aSHans de Goede channel = bssid->Configuration.DSConfig; 4986554c0a3aSHans de Goede chplan_new = pmlmeext->channel_set; 4987554c0a3aSHans de Goede i = 0; 4988554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) { 4989554c0a3aSHans de Goede if (chplan_new[i].ChannelNum == channel) { 4990554c0a3aSHans de Goede if (chplan_new[i].ScanType == SCAN_PASSIVE) { 4991554c0a3aSHans de Goede /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */ 4992554c0a3aSHans de Goede if (channel >= 52 && channel <= 144) 4993554c0a3aSHans de Goede break; 4994554c0a3aSHans de Goede 4995554c0a3aSHans de Goede chplan_new[i].ScanType = SCAN_ACTIVE; 4996554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, 4997554c0a3aSHans de Goede ("%s: change channel %d scan type from passive to active\n", 4998554c0a3aSHans de Goede __func__, channel)); 4999554c0a3aSHans de Goede } 5000554c0a3aSHans de Goede break; 5001554c0a3aSHans de Goede } 5002554c0a3aSHans de Goede i++; 5003554c0a3aSHans de Goede } 5004554c0a3aSHans de Goede } 5005554c0a3aSHans de Goede 5006554c0a3aSHans de Goede /**************************************************************************** 5007554c0a3aSHans de Goede 5008554c0a3aSHans de Goede Following are the functions to report events 5009554c0a3aSHans de Goede 5010554c0a3aSHans de Goede *****************************************************************************/ 5011554c0a3aSHans de Goede 5012554c0a3aSHans de Goede void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame) 5013554c0a3aSHans de Goede { 5014554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5015554c0a3aSHans de Goede u8 *pevtcmd; 5016554c0a3aSHans de Goede u32 cmdsz; 5017554c0a3aSHans de Goede struct survey_event *psurvey_evt; 5018554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5019554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 5020554c0a3aSHans de Goede struct cmd_priv *pcmdpriv; 5021554c0a3aSHans de Goede /* u8 *pframe = precv_frame->u.hdr.rx_data; */ 5022554c0a3aSHans de Goede /* uint len = precv_frame->u.hdr.len; */ 5023554c0a3aSHans de Goede 5024554c0a3aSHans de Goede if (!padapter) 5025554c0a3aSHans de Goede return; 5026554c0a3aSHans de Goede 5027554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 5028554c0a3aSHans de Goede pcmdpriv = &padapter->cmdpriv; 5029554c0a3aSHans de Goede 50302ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 503141452327SVatsala Narang if (!pcmd_obj) 5032554c0a3aSHans de Goede return; 5033554c0a3aSHans de Goede 5034554c0a3aSHans de Goede cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header)); 50352ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 503641452327SVatsala Narang if (!pevtcmd) { 50378f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5038554c0a3aSHans de Goede return; 5039554c0a3aSHans de Goede } 5040554c0a3aSHans de Goede 5041554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5042554c0a3aSHans de Goede 5043554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5044554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5045554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5046554c0a3aSHans de Goede 5047554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5048554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5049554c0a3aSHans de Goede 5050554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5051554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct survey_event); 5052554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); 5053554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5054554c0a3aSHans de Goede 5055554c0a3aSHans de Goede psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5056554c0a3aSHans de Goede 5057554c0a3aSHans de Goede if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) { 50588f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 50598f24f505SMadhumitha Prabakaran kfree(pevtcmd); 5060554c0a3aSHans de Goede return; 5061554c0a3aSHans de Goede } 5062554c0a3aSHans de Goede 5063554c0a3aSHans de Goede process_80211d(padapter, &psurvey_evt->bss); 5064554c0a3aSHans de Goede 5065554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5066554c0a3aSHans de Goede 5067554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt++; 5068554c0a3aSHans de Goede 5069554c0a3aSHans de Goede return; 5070554c0a3aSHans de Goede 5071554c0a3aSHans de Goede } 5072554c0a3aSHans de Goede 5073554c0a3aSHans de Goede void report_surveydone_event(struct adapter *padapter) 5074554c0a3aSHans de Goede { 5075554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5076554c0a3aSHans de Goede u8 *pevtcmd; 5077554c0a3aSHans de Goede u32 cmdsz; 5078554c0a3aSHans de Goede struct surveydone_event *psurveydone_evt; 5079554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5080554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5081554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5082554c0a3aSHans de Goede 50832ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 508441452327SVatsala Narang if (!pcmd_obj) 5085554c0a3aSHans de Goede return; 5086554c0a3aSHans de Goede 5087554c0a3aSHans de Goede cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header)); 50882ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 508941452327SVatsala Narang if (!pevtcmd) { 50908f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5091554c0a3aSHans de Goede return; 5092554c0a3aSHans de Goede } 5093554c0a3aSHans de Goede 5094554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5095554c0a3aSHans de Goede 5096554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5097554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5098554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5099554c0a3aSHans de Goede 5100554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5101554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5102554c0a3aSHans de Goede 5103554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5104554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct surveydone_event); 5105554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); 5106554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5107554c0a3aSHans de Goede 5108554c0a3aSHans de Goede psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5109554c0a3aSHans de Goede psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; 5110554c0a3aSHans de Goede 5111d0cc39cdSRoss Schmidt DBG_871X("survey done event(%x) band:%d for %s\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter)); 5112554c0a3aSHans de Goede 5113554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5114554c0a3aSHans de Goede 5115554c0a3aSHans de Goede return; 5116554c0a3aSHans de Goede 5117554c0a3aSHans de Goede } 5118554c0a3aSHans de Goede 5119554c0a3aSHans de Goede void report_join_res(struct adapter *padapter, int res) 5120554c0a3aSHans de Goede { 5121554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5122554c0a3aSHans de Goede u8 *pevtcmd; 5123554c0a3aSHans de Goede u32 cmdsz; 5124554c0a3aSHans de Goede struct joinbss_event *pjoinbss_evt; 5125554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5126554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5127554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5128554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5129554c0a3aSHans de Goede 51302ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 513141452327SVatsala Narang if (!pcmd_obj) 5132554c0a3aSHans de Goede return; 5133554c0a3aSHans de Goede 5134554c0a3aSHans de Goede cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header)); 51352ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 513641452327SVatsala Narang if (!pevtcmd) { 51378f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5138554c0a3aSHans de Goede return; 5139554c0a3aSHans de Goede } 5140554c0a3aSHans de Goede 5141554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5142554c0a3aSHans de Goede 5143554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5144554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5145554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5146554c0a3aSHans de Goede 5147554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5148554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5149554c0a3aSHans de Goede 5150554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5151554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct joinbss_event); 5152554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); 5153554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5154554c0a3aSHans de Goede 5155554c0a3aSHans de Goede pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5156554c0a3aSHans de Goede memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex)); 5157554c0a3aSHans de Goede pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = res; 5158554c0a3aSHans de Goede 5159554c0a3aSHans de Goede DBG_871X("report_join_res(%d)\n", res); 5160554c0a3aSHans de Goede 5161554c0a3aSHans de Goede 5162554c0a3aSHans de Goede rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network); 5163554c0a3aSHans de Goede 5164554c0a3aSHans de Goede 5165554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5166554c0a3aSHans de Goede 5167554c0a3aSHans de Goede return; 5168554c0a3aSHans de Goede 5169554c0a3aSHans de Goede } 5170554c0a3aSHans de Goede 5171554c0a3aSHans de Goede void report_wmm_edca_update(struct adapter *padapter) 5172554c0a3aSHans de Goede { 5173554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5174554c0a3aSHans de Goede u8 *pevtcmd; 5175554c0a3aSHans de Goede u32 cmdsz; 5176554c0a3aSHans de Goede struct wmm_event *pwmm_event; 5177554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5178554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5179554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5180554c0a3aSHans de Goede 51812ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 518241452327SVatsala Narang if (!pcmd_obj) 5183554c0a3aSHans de Goede return; 5184554c0a3aSHans de Goede 5185554c0a3aSHans de Goede cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header)); 51862ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 518741452327SVatsala Narang if (!pevtcmd) { 51888f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5189554c0a3aSHans de Goede return; 5190554c0a3aSHans de Goede } 5191554c0a3aSHans de Goede 5192554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5193554c0a3aSHans de Goede 5194554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5195554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5196554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5197554c0a3aSHans de Goede 5198554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5199554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5200554c0a3aSHans de Goede 5201554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5202554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct wmm_event); 5203554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM); 5204554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5205554c0a3aSHans de Goede 5206554c0a3aSHans de Goede pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5207554c0a3aSHans de Goede pwmm_event->wmm = 0; 5208554c0a3aSHans de Goede 5209554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5210554c0a3aSHans de Goede 5211554c0a3aSHans de Goede return; 5212554c0a3aSHans de Goede 5213554c0a3aSHans de Goede } 5214554c0a3aSHans de Goede 5215554c0a3aSHans de Goede void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) 5216554c0a3aSHans de Goede { 5217554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5218554c0a3aSHans de Goede u8 *pevtcmd; 5219554c0a3aSHans de Goede u32 cmdsz; 5220554c0a3aSHans de Goede struct sta_info *psta; 5221554c0a3aSHans de Goede int mac_id; 5222554c0a3aSHans de Goede struct stadel_event *pdel_sta_evt; 5223554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5224554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5225554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5226554c0a3aSHans de Goede 52272ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 5228554c0a3aSHans de Goede if (pcmd_obj == NULL) { 5229554c0a3aSHans de Goede return; 5230554c0a3aSHans de Goede } 5231554c0a3aSHans de Goede 5232554c0a3aSHans de Goede cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); 52332ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 5234554c0a3aSHans de Goede if (pevtcmd == NULL) { 52358f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5236554c0a3aSHans de Goede return; 5237554c0a3aSHans de Goede } 5238554c0a3aSHans de Goede 5239554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5240554c0a3aSHans de Goede 5241554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5242554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5243554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5244554c0a3aSHans de Goede 5245554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5246554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5247554c0a3aSHans de Goede 5248554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5249554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct stadel_event); 5250554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); 5251554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5252554c0a3aSHans de Goede 5253554c0a3aSHans de Goede pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5254554c0a3aSHans de Goede memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN); 5255554c0a3aSHans de Goede memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); 5256554c0a3aSHans de Goede 5257554c0a3aSHans de Goede 5258554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, MacAddr); 5259554c0a3aSHans de Goede if (psta) 5260554c0a3aSHans de Goede mac_id = (int)psta->mac_id; 5261554c0a3aSHans de Goede else 5262554c0a3aSHans de Goede mac_id = (-1); 5263554c0a3aSHans de Goede 5264554c0a3aSHans de Goede pdel_sta_evt->mac_id = mac_id; 5265554c0a3aSHans de Goede 5266554c0a3aSHans de Goede DBG_871X("report_del_sta_event: delete STA, mac_id =%d\n", mac_id); 5267554c0a3aSHans de Goede 5268554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5269554c0a3aSHans de Goede } 5270554c0a3aSHans de Goede 5271554c0a3aSHans de Goede void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx) 5272554c0a3aSHans de Goede { 5273554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5274554c0a3aSHans de Goede u8 *pevtcmd; 5275554c0a3aSHans de Goede u32 cmdsz; 5276554c0a3aSHans de Goede struct stassoc_event *padd_sta_evt; 5277554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5278554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5279554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5280554c0a3aSHans de Goede 52812ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 5282554c0a3aSHans de Goede if (pcmd_obj == NULL) 5283554c0a3aSHans de Goede return; 5284554c0a3aSHans de Goede 5285554c0a3aSHans de Goede cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header)); 52862ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 5287554c0a3aSHans de Goede if (pevtcmd == NULL) { 52888f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5289554c0a3aSHans de Goede return; 5290554c0a3aSHans de Goede } 5291554c0a3aSHans de Goede 5292554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5293554c0a3aSHans de Goede 5294554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5295554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5296554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5297554c0a3aSHans de Goede 5298554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5299554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5300554c0a3aSHans de Goede 5301554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5302554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct stassoc_event); 5303554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); 5304554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5305554c0a3aSHans de Goede 5306554c0a3aSHans de Goede padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5307554c0a3aSHans de Goede memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN); 5308554c0a3aSHans de Goede padd_sta_evt->cam_id = cam_idx; 5309554c0a3aSHans de Goede 5310554c0a3aSHans de Goede DBG_871X("report_add_sta_event: add STA\n"); 5311554c0a3aSHans de Goede 5312554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5313554c0a3aSHans de Goede } 5314554c0a3aSHans de Goede 5315554c0a3aSHans de Goede /**************************************************************************** 5316554c0a3aSHans de Goede 5317554c0a3aSHans de Goede Following are the event callback functions 5318554c0a3aSHans de Goede 5319554c0a3aSHans de Goede *****************************************************************************/ 5320554c0a3aSHans de Goede 5321554c0a3aSHans de Goede /* for sta/adhoc mode */ 5322554c0a3aSHans de Goede void update_sta_info(struct adapter *padapter, struct sta_info *psta) 5323554c0a3aSHans de Goede { 5324554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5325554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5326554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5327554c0a3aSHans de Goede 5328554c0a3aSHans de Goede /* ERP */ 5329554c0a3aSHans de Goede VCS_update(padapter, psta); 5330554c0a3aSHans de Goede 5331554c0a3aSHans de Goede /* HT */ 5332554c0a3aSHans de Goede if (pmlmepriv->htpriv.ht_option) { 5333554c0a3aSHans de Goede psta->htpriv.ht_option = true; 5334554c0a3aSHans de Goede 5335554c0a3aSHans de Goede psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; 5336554c0a3aSHans de Goede 5337554c0a3aSHans de Goede psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2; 5338554c0a3aSHans de Goede 5339554c0a3aSHans de Goede if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20)) 5340554c0a3aSHans de Goede psta->htpriv.sgi_20m = true; 5341554c0a3aSHans de Goede 5342554c0a3aSHans de Goede if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40)) 5343554c0a3aSHans de Goede psta->htpriv.sgi_40m = true; 5344554c0a3aSHans de Goede 5345554c0a3aSHans de Goede psta->qos_option = true; 5346554c0a3aSHans de Goede 5347554c0a3aSHans de Goede psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap; 5348554c0a3aSHans de Goede psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap; 5349554c0a3aSHans de Goede psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap; 5350554c0a3aSHans de Goede 5351c25d8a7dSRoss Schmidt memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct ieee80211_ht_cap)); 5352554c0a3aSHans de Goede } else { 5353554c0a3aSHans de Goede psta->htpriv.ht_option = false; 5354554c0a3aSHans de Goede 5355554c0a3aSHans de Goede psta->htpriv.ampdu_enable = false; 5356554c0a3aSHans de Goede 5357554c0a3aSHans de Goede psta->htpriv.sgi_20m = false; 5358554c0a3aSHans de Goede psta->htpriv.sgi_40m = false; 5359554c0a3aSHans de Goede psta->qos_option = false; 5360554c0a3aSHans de Goede 5361554c0a3aSHans de Goede } 5362554c0a3aSHans de Goede 5363554c0a3aSHans de Goede psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; 5364554c0a3aSHans de Goede 5365554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ 5366554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ 5367554c0a3aSHans de Goede 5368554c0a3aSHans de Goede psta->bw_mode = pmlmeext->cur_bwmode; 5369554c0a3aSHans de Goede 5370554c0a3aSHans de Goede /* QoS */ 5371554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option) 5372554c0a3aSHans de Goede psta->qos_option = true; 5373554c0a3aSHans de Goede 5374554c0a3aSHans de Goede update_ldpc_stbc_cap(psta); 5375554c0a3aSHans de Goede 5376554c0a3aSHans de Goede spin_lock_bh(&psta->lock); 5377554c0a3aSHans de Goede psta->state = _FW_LINKED; 5378554c0a3aSHans de Goede spin_unlock_bh(&psta->lock); 5379554c0a3aSHans de Goede 5380554c0a3aSHans de Goede } 5381554c0a3aSHans de Goede 5382554c0a3aSHans de Goede static void rtw_mlmeext_disconnect(struct adapter *padapter) 5383554c0a3aSHans de Goede { 5384554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 5385554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5386554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5387554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 5388554c0a3aSHans de Goede 5389554c0a3aSHans de Goede /* set_opmode_cmd(padapter, infra_client_with_mlme); */ 5390554c0a3aSHans de Goede 53914d17363dSAndreas Hellmich /* For safety, prevent from keeping macid sleep. 5392554c0a3aSHans de Goede * If we can sure all power mode enter/leave are paired, 5393554c0a3aSHans de Goede * this check can be removed. 5394554c0a3aSHans de Goede * Lucas@20131113 5395554c0a3aSHans de Goede */ 5396554c0a3aSHans de Goede /* wakeup macid after disconnect. */ 5397554c0a3aSHans de Goede { 5398554c0a3aSHans de Goede struct sta_info *psta; 5399c926f022SSimran Singhal 5400554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork)); 5401554c0a3aSHans de Goede if (psta) 5402554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 5403554c0a3aSHans de Goede } 5404554c0a3aSHans de Goede 5405554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); 5406554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); 5407554c0a3aSHans de Goede 5408554c0a3aSHans de Goede /* set MSR to no link state -> infra. mode */ 5409554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_STATION_); 5410554c0a3aSHans de Goede 5411554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5412554c0a3aSHans de Goede 5413554c0a3aSHans de Goede /* switch to the 20M Hz mode after disconnect */ 5414554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 5415554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 5416554c0a3aSHans de Goede 5417554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 5418554c0a3aSHans de Goede 5419554c0a3aSHans de Goede flush_all_cam_entry(padapter); 5420554c0a3aSHans de Goede 5421554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 5422554c0a3aSHans de Goede 5423554c0a3aSHans de Goede /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */ 5424554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; 5425554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0; 5426554c0a3aSHans de Goede 5427554c0a3aSHans de Goede } 5428554c0a3aSHans de Goede 5429554c0a3aSHans de Goede void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) 5430554c0a3aSHans de Goede { 5431554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5432554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5433554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 5434554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5435554c0a3aSHans de Goede u8 join_type; 5436554c0a3aSHans de Goede struct sta_info *psta; 5437c926f022SSimran Singhal 5438554c0a3aSHans de Goede if (join_res < 0) { 5439554c0a3aSHans de Goede join_type = 1; 5440554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5441554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); 5442554c0a3aSHans de Goede 5443554c0a3aSHans de Goede goto exit_mlmeext_joinbss_event_callback; 5444554c0a3aSHans de Goede } 5445554c0a3aSHans de Goede 5446554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) 5447554c0a3aSHans de Goede /* update bc/mc sta_info */ 5448554c0a3aSHans de Goede update_bmc_sta(padapter); 5449554c0a3aSHans de Goede 5450554c0a3aSHans de Goede 5451554c0a3aSHans de Goede /* turn on dynamic functions */ 5452554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); 5453554c0a3aSHans de Goede 545468468503SAndreas Hellmich /* update IOT-related issue */ 5455554c0a3aSHans de Goede update_IOT_info(padapter); 5456554c0a3aSHans de Goede 5457554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates); 5458554c0a3aSHans de Goede 5459554c0a3aSHans de Goede /* BCN interval */ 5460554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval)); 5461554c0a3aSHans de Goede 546268468503SAndreas Hellmich /* update capability */ 5463554c0a3aSHans de Goede update_capinfo(padapter, pmlmeinfo->capability); 5464554c0a3aSHans de Goede 5465554c0a3aSHans de Goede /* WMM, Update EDCA param */ 5466554c0a3aSHans de Goede WMMOnAssocRsp(padapter); 5467554c0a3aSHans de Goede 5468554c0a3aSHans de Goede /* HT */ 5469554c0a3aSHans de Goede HTOnAssocRsp(padapter); 5470554c0a3aSHans de Goede 5471554c0a3aSHans de Goede /* Set cur_channel&cur_bwmode&cur_ch_offset */ 5472554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 5473554c0a3aSHans de Goede 5474554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); 5475554c0a3aSHans de Goede if (psta) { /* only for infra. mode */ 5476554c0a3aSHans de Goede 5477554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; 5478554c0a3aSHans de Goede 5479554c0a3aSHans de Goede /* DBG_871X("set_sta_rate\n"); */ 5480554c0a3aSHans de Goede 5481554c0a3aSHans de Goede psta->wireless_mode = pmlmeext->cur_wireless_mode; 5482554c0a3aSHans de Goede 5483554c0a3aSHans de Goede /* set per sta rate after updating HT cap. */ 5484554c0a3aSHans de Goede set_sta_rate(padapter, psta); 5485554c0a3aSHans de Goede 5486554c0a3aSHans de Goede rtw_sta_media_status_rpt(padapter, psta, 1); 5487554c0a3aSHans de Goede 5488554c0a3aSHans de Goede /* wakeup macid after join bss successfully to ensure 5489554c0a3aSHans de Goede the subsequent data frames can be sent out normally */ 5490554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 5491554c0a3aSHans de Goede } 5492554c0a3aSHans de Goede 5493554c0a3aSHans de Goede join_type = 2; 5494554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5495554c0a3aSHans de Goede 5496554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 5497554c0a3aSHans de Goede /* correcting TSF */ 5498554c0a3aSHans de Goede correct_TSF(padapter, pmlmeext); 5499554c0a3aSHans de Goede 5500554c0a3aSHans de Goede /* set_link_timer(pmlmeext, DISCONNECT_TO); */ 5501554c0a3aSHans de Goede } 5502554c0a3aSHans de Goede 5503554c0a3aSHans de Goede if (get_iface_type(padapter) == IFACE_PORT0) 5504554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); 5505554c0a3aSHans de Goede 5506554c0a3aSHans de Goede exit_mlmeext_joinbss_event_callback: 5507554c0a3aSHans de Goede 5508554c0a3aSHans de Goede DBG_871X("=>%s\n", __func__); 5509554c0a3aSHans de Goede 5510554c0a3aSHans de Goede } 5511554c0a3aSHans de Goede 5512554c0a3aSHans de Goede /* currently only adhoc mode will go here */ 5513554c0a3aSHans de Goede void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta) 5514554c0a3aSHans de Goede { 5515554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 5516554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5517554c0a3aSHans de Goede u8 join_type; 5518554c0a3aSHans de Goede 5519554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 5520554c0a3aSHans de Goede 5521554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 5522554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */ 5523554c0a3aSHans de Goede 5524554c0a3aSHans de Goede /* nothing to do */ 5525554c0a3aSHans de Goede } else { /* adhoc client */ 5526554c0a3aSHans de Goede /* update TSF Value */ 5527554c0a3aSHans de Goede /* update_TSF(pmlmeext, pframe, len); */ 5528554c0a3aSHans de Goede 5529554c0a3aSHans de Goede /* correcting TSF */ 5530554c0a3aSHans de Goede correct_TSF(padapter, pmlmeext); 5531554c0a3aSHans de Goede 5532554c0a3aSHans de Goede /* start beacon */ 5533554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 5534554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].status = 0; 5535554c0a3aSHans de Goede 5536554c0a3aSHans de Goede pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE; 5537554c0a3aSHans de Goede 5538554c0a3aSHans de Goede return; 5539554c0a3aSHans de Goede } 5540554c0a3aSHans de Goede 5541554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 5542554c0a3aSHans de Goede 5543554c0a3aSHans de Goede } 5544554c0a3aSHans de Goede 5545554c0a3aSHans de Goede join_type = 2; 5546554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5547554c0a3aSHans de Goede } 5548554c0a3aSHans de Goede 5549554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; 5550554c0a3aSHans de Goede 5551554c0a3aSHans de Goede psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates); 5552554c0a3aSHans de Goede memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen); 5553554c0a3aSHans de Goede 5554554c0a3aSHans de Goede /* update adhoc sta_info */ 5555554c0a3aSHans de Goede update_sta_info(padapter, psta); 5556554c0a3aSHans de Goede 5557554c0a3aSHans de Goede rtw_hal_update_sta_rate_mask(padapter, psta); 5558554c0a3aSHans de Goede 5559554c0a3aSHans de Goede /* ToDo: HT for Ad-hoc */ 5560554c0a3aSHans de Goede psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel); 5561777a4334SNishka Dasgupta psta->raid = networktype_to_raid_ex(padapter, psta); 5562554c0a3aSHans de Goede 5563554c0a3aSHans de Goede /* rate radaptive */ 5564554c0a3aSHans de Goede Update_RA_Entry(padapter, psta); 5565554c0a3aSHans de Goede } 5566554c0a3aSHans de Goede 5567554c0a3aSHans de Goede void mlmeext_sta_del_event_callback(struct adapter *padapter) 5568554c0a3aSHans de Goede { 5569554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) 5570554c0a3aSHans de Goede rtw_mlmeext_disconnect(padapter); 5571554c0a3aSHans de Goede } 5572554c0a3aSHans de Goede 5573554c0a3aSHans de Goede /**************************************************************************** 5574554c0a3aSHans de Goede 5575554c0a3aSHans de Goede Following are the functions for the timer handlers 5576554c0a3aSHans de Goede 5577554c0a3aSHans de Goede *****************************************************************************/ 5578554c0a3aSHans de Goede void _linked_info_dump(struct adapter *padapter) 5579554c0a3aSHans de Goede { 5580554c0a3aSHans de Goede int i; 5581554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5582554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5583554c0a3aSHans de Goede int UndecoratedSmoothedPWDB; 5584554c0a3aSHans de Goede struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); 5585554c0a3aSHans de Goede 5586554c0a3aSHans de Goede if (padapter->bLinkInfoDump) { 5587554c0a3aSHans de Goede 5588d0cc39cdSRoss Schmidt DBG_871X("\n ============[%s] linked status check ===================\n", ADPT_ARG(padapter)); 5589554c0a3aSHans de Goede 5590554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 5591554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB); 5592554c0a3aSHans de Goede 5593bbda3ac4SRoss Schmidt DBG_871X("AP[%pM] - UndecoratedSmoothedPWDB:%d\n", 5594554c0a3aSHans de Goede MAC_ARG(padapter->mlmepriv.cur_network.network.MacAddress), UndecoratedSmoothedPWDB); 5595554c0a3aSHans de Goede } else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_) { 5596554c0a3aSHans de Goede struct list_head *phead, *plist; 5597554c0a3aSHans de Goede 5598554c0a3aSHans de Goede struct sta_info *psta = NULL; 5599554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5600554c0a3aSHans de Goede 5601554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 5602554c0a3aSHans de Goede phead = &pstapriv->asoc_list; 5603554c0a3aSHans de Goede plist = get_next(phead); 5604554c0a3aSHans de Goede while (phead != plist) { 5605554c0a3aSHans de Goede psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); 5606554c0a3aSHans de Goede plist = get_next(plist); 5607554c0a3aSHans de Goede 5608bbda3ac4SRoss Schmidt DBG_871X("STA[%pM]:UndecoratedSmoothedPWDB:%d\n", 5609554c0a3aSHans de Goede MAC_ARG(psta->hwaddr), psta->rssi_stat.UndecoratedSmoothedPWDB); 5610554c0a3aSHans de Goede } 5611554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 5612554c0a3aSHans de Goede 5613554c0a3aSHans de Goede } 5614554c0a3aSHans de Goede for (i = 0; i < NUM_STA; i++) { 56150ad02fa8SGeorgiana Chelu if (pdvobj->macid[i]) { 5616554c0a3aSHans de Goede if (i != 1) /* skip bc/mc sta */ 5617554c0a3aSHans de Goede /* tx info ============ */ 5618554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i); 5619554c0a3aSHans de Goede } 5620554c0a3aSHans de Goede } 5621554c0a3aSHans de Goede rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL); 5622554c0a3aSHans de Goede 5623554c0a3aSHans de Goede 5624554c0a3aSHans de Goede } 5625554c0a3aSHans de Goede 5626554c0a3aSHans de Goede 5627554c0a3aSHans de Goede } 5628554c0a3aSHans de Goede 5629554c0a3aSHans de Goede static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta) 5630554c0a3aSHans de Goede { 5631554c0a3aSHans de Goede u8 ret = false; 5632554c0a3aSHans de Goede 5633554c0a3aSHans de Goede #ifdef DBG_EXPIRATION_CHK 5634554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu" 5635554c0a3aSHans de Goede /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/ 5636554c0a3aSHans de Goede ", retry:%u\n" 5637554c0a3aSHans de Goede , FUNC_ADPT_ARG(padapter) 5638554c0a3aSHans de Goede , STA_RX_PKTS_DIFF_ARG(psta) 5639554c0a3aSHans de Goede , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts 5640554c0a3aSHans de Goede , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts 5641554c0a3aSHans de Goede /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts 5642554c0a3aSHans de Goede , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts 5643554c0a3aSHans de Goede , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts 5644554c0a3aSHans de Goede , pmlmeinfo->bcn_interval*/ 5645554c0a3aSHans de Goede , pmlmeext->retry 5646554c0a3aSHans de Goede ); 5647554c0a3aSHans de Goede 5648554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter) 5649554c0a3aSHans de Goede , padapter->xmitpriv.tx_pkts 5650554c0a3aSHans de Goede , pmlmeinfo->link_count 5651554c0a3aSHans de Goede ); 5652554c0a3aSHans de Goede #endif 5653554c0a3aSHans de Goede 5654554c0a3aSHans de Goede if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) 5655554c0a3aSHans de Goede && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) 5656554c0a3aSHans de Goede && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta) 5657554c0a3aSHans de Goede ) { 5658554c0a3aSHans de Goede ret = false; 5659554c0a3aSHans de Goede } else { 5660554c0a3aSHans de Goede ret = true; 5661554c0a3aSHans de Goede } 5662554c0a3aSHans de Goede 5663554c0a3aSHans de Goede sta_update_last_rx_pkts(psta); 5664554c0a3aSHans de Goede 5665554c0a3aSHans de Goede return ret; 5666554c0a3aSHans de Goede } 5667554c0a3aSHans de Goede 5668554c0a3aSHans de Goede void linked_status_chk(struct adapter *padapter) 5669554c0a3aSHans de Goede { 5670554c0a3aSHans de Goede u32 i; 5671554c0a3aSHans de Goede struct sta_info *psta; 5672554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 5673554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5674554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5675554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5676554c0a3aSHans de Goede 5677554c0a3aSHans de Goede 5678554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter)) { 5679554c0a3aSHans de Goede /* linked infrastructure client mode */ 5680554c0a3aSHans de Goede 5681554c0a3aSHans de Goede int tx_chk = _SUCCESS, rx_chk = _SUCCESS; 5682554c0a3aSHans de Goede int rx_chk_limit; 5683554c0a3aSHans de Goede int link_count_limit; 5684554c0a3aSHans de Goede 5685554c0a3aSHans de Goede #if defined(DBG_ROAMING_TEST) 5686554c0a3aSHans de Goede rx_chk_limit = 1; 5687554c0a3aSHans de Goede #else 5688554c0a3aSHans de Goede rx_chk_limit = 8; 5689554c0a3aSHans de Goede #endif 5690554c0a3aSHans de Goede link_count_limit = 7; /* 16 sec */ 5691554c0a3aSHans de Goede 5692554c0a3aSHans de Goede /* Marked by Kurt 20130715 */ 5693554c0a3aSHans de Goede /* For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, so we could not check rx limit that strictly. */ 5694554c0a3aSHans de Goede /* todo: To check why we under miracast session, rx_chk would be false */ 5695554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress); 569634557e23SIzabela Bakollari if (psta) { 5697554c0a3aSHans de Goede if (chk_ap_is_alive(padapter, psta) == false) 5698554c0a3aSHans de Goede rx_chk = _FAIL; 5699554c0a3aSHans de Goede 5700554c0a3aSHans de Goede if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts) 5701554c0a3aSHans de Goede tx_chk = _FAIL; 5702554c0a3aSHans de Goede 5703554c0a3aSHans de Goede { 5704554c0a3aSHans de Goede if (rx_chk != _SUCCESS) { 5705554c0a3aSHans de Goede if (pmlmeext->retry == 0) { 5706554c0a3aSHans de Goede #ifdef DBG_EXPIRATION_CHK 5707554c0a3aSHans de Goede DBG_871X("issue_probereq to trigger probersp, retry =%d\n", pmlmeext->retry); 5708554c0a3aSHans de Goede #endif 5709554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5710554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5711554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5712554c0a3aSHans de Goede } 5713554c0a3aSHans de Goede } 5714554c0a3aSHans de Goede 5715554c0a3aSHans de Goede if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) { 5716554c0a3aSHans de Goede #ifdef DBG_EXPIRATION_CHK 5717554c0a3aSHans de Goede DBG_871X("%s issue_nulldata 0\n", __func__); 5718554c0a3aSHans de Goede #endif 5719554c0a3aSHans de Goede tx_chk = issue_nulldata_in_interrupt(padapter, NULL); 5720554c0a3aSHans de Goede } 5721554c0a3aSHans de Goede } 5722554c0a3aSHans de Goede 5723554c0a3aSHans de Goede if (rx_chk == _FAIL) { 5724554c0a3aSHans de Goede pmlmeext->retry++; 5725554c0a3aSHans de Goede if (pmlmeext->retry > rx_chk_limit) { 5726554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n", 5727554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter)); 5728554c0a3aSHans de Goede receive_disconnect(padapter, pmlmeinfo->network.MacAddress 5729554c0a3aSHans de Goede , WLAN_REASON_EXPIRATION_CHK); 5730554c0a3aSHans de Goede return; 5731554c0a3aSHans de Goede } 5732554c0a3aSHans de Goede } else { 5733554c0a3aSHans de Goede pmlmeext->retry = 0; 5734554c0a3aSHans de Goede } 5735554c0a3aSHans de Goede 5736554c0a3aSHans de Goede if (tx_chk == _FAIL) { 5737554c0a3aSHans de Goede pmlmeinfo->link_count %= (link_count_limit+1); 5738554c0a3aSHans de Goede } else { 5739554c0a3aSHans de Goede pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts; 5740554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 5741554c0a3aSHans de Goede } 5742554c0a3aSHans de Goede 5743554c0a3aSHans de Goede } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */ 5744554c0a3aSHans de Goede } else if (is_client_associated_to_ibss(padapter)) { 5745554c0a3aSHans de Goede /* linked IBSS mode */ 5746554c0a3aSHans de Goede /* for each assoc list entry to check the rx pkt counter */ 5747554c0a3aSHans de Goede for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { 5748554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].status == 1) { 5749554c0a3aSHans de Goede psta = pmlmeinfo->FW_sta_info[i].psta; 5750554c0a3aSHans de Goede 5751554c0a3aSHans de Goede if (NULL == psta) 5752554c0a3aSHans de Goede continue; 5753554c0a3aSHans de Goede 5754554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) { 5755554c0a3aSHans de Goede 5756554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].retry < 3) { 5757554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry++; 5758554c0a3aSHans de Goede } else { 5759554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry = 0; 5760554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].status = 0; 5761554c0a3aSHans de Goede report_del_sta_event(padapter, psta->hwaddr 5762554c0a3aSHans de Goede , 65535/* indicate disconnect caused by no rx */ 5763554c0a3aSHans de Goede ); 5764554c0a3aSHans de Goede } 5765554c0a3aSHans de Goede } else { 5766554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry = 0; 5767554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta); 5768554c0a3aSHans de Goede } 5769554c0a3aSHans de Goede } 5770554c0a3aSHans de Goede } 5771554c0a3aSHans de Goede 5772554c0a3aSHans de Goede /* set_link_timer(pmlmeext, DISCONNECT_TO); */ 5773554c0a3aSHans de Goede 5774554c0a3aSHans de Goede } 5775554c0a3aSHans de Goede 5776554c0a3aSHans de Goede } 5777554c0a3aSHans de Goede 5778e8b1844aSKees Cook void survey_timer_hdl(struct timer_list *t) 5779554c0a3aSHans de Goede { 5780e8b1844aSKees Cook struct adapter *padapter = 5781e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.survey_timer); 5782554c0a3aSHans de Goede struct cmd_obj *ph2c; 5783554c0a3aSHans de Goede struct sitesurvey_parm *psurveyPara; 5784554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5785554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5786554c0a3aSHans de Goede 5787554c0a3aSHans de Goede /* DBG_871X("marc: survey timer\n"); */ 5788554c0a3aSHans de Goede 5789554c0a3aSHans de Goede /* issue rtw_sitesurvey_cmd */ 5790554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state > SCAN_START) { 5791554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 5792554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx++; 5793554c0a3aSHans de Goede } 5794554c0a3aSHans de Goede 57950ad02fa8SGeorgiana Chelu if (pmlmeext->scan_abort) { 5796554c0a3aSHans de Goede { 5797554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num; 5798554c0a3aSHans de Goede DBG_871X("%s idx:%d\n", __func__ 5799554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.channel_idx 5800554c0a3aSHans de Goede ); 5801554c0a3aSHans de Goede } 5802554c0a3aSHans de Goede 5803554c0a3aSHans de Goede pmlmeext->scan_abort = false;/* reset */ 5804554c0a3aSHans de Goede } 5805554c0a3aSHans de Goede 58062ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 5807554c0a3aSHans de Goede if (ph2c == NULL) { 5808554c0a3aSHans de Goede goto exit_survey_timer_hdl; 5809554c0a3aSHans de Goede } 5810554c0a3aSHans de Goede 58112ef2b7c2SJoe Perches psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); 5812554c0a3aSHans de Goede if (psurveyPara == NULL) { 58138f24f505SMadhumitha Prabakaran kfree(ph2c); 5814554c0a3aSHans de Goede goto exit_survey_timer_hdl; 5815554c0a3aSHans de Goede } 5816554c0a3aSHans de Goede 5817554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 5818554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, ph2c); 5819554c0a3aSHans de Goede } 5820554c0a3aSHans de Goede 5821554c0a3aSHans de Goede 5822554c0a3aSHans de Goede exit_survey_timer_hdl: 5823554c0a3aSHans de Goede 5824554c0a3aSHans de Goede return; 5825554c0a3aSHans de Goede } 5826554c0a3aSHans de Goede 5827e8b1844aSKees Cook void link_timer_hdl(struct timer_list *t) 5828554c0a3aSHans de Goede { 5829e8b1844aSKees Cook struct adapter *padapter = 5830e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.link_timer); 5831554c0a3aSHans de Goede /* static unsigned int rx_pkt = 0; */ 5832554c0a3aSHans de Goede /* static u64 tx_cnt = 0; */ 5833554c0a3aSHans de Goede /* struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); */ 5834554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5835554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5836554c0a3aSHans de Goede /* struct sta_priv *pstapriv = &padapter->stapriv; */ 5837554c0a3aSHans de Goede 5838554c0a3aSHans de Goede 5839554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { 5840554c0a3aSHans de Goede DBG_871X("link_timer_hdl:no beacon while connecting\n"); 5841554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5842554c0a3aSHans de Goede report_join_res(padapter, -3); 5843554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { 5844554c0a3aSHans de Goede /* re-auth timer */ 5845554c0a3aSHans de Goede if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { 5846554c0a3aSHans de Goede /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */ 5847554c0a3aSHans de Goede /* */ 5848554c0a3aSHans de Goede pmlmeinfo->state = 0; 5849554c0a3aSHans de Goede report_join_res(padapter, -1); 5850554c0a3aSHans de Goede return; 5851554c0a3aSHans de Goede /* */ 5852554c0a3aSHans de Goede /* else */ 5853554c0a3aSHans de Goede /* */ 5854554c0a3aSHans de Goede /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */ 5855554c0a3aSHans de Goede /* pmlmeinfo->reauth_count = 0; */ 5856554c0a3aSHans de Goede /* */ 5857554c0a3aSHans de Goede } 5858554c0a3aSHans de Goede 5859554c0a3aSHans de Goede DBG_871X("link_timer_hdl: auth timeout and try again\n"); 5860554c0a3aSHans de Goede pmlmeinfo->auth_seq = 1; 5861554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 5862554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 5863554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { 5864554c0a3aSHans de Goede /* re-assoc timer */ 5865554c0a3aSHans de Goede if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { 5866554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5867554c0a3aSHans de Goede report_join_res(padapter, -2); 5868554c0a3aSHans de Goede return; 5869554c0a3aSHans de Goede } 5870554c0a3aSHans de Goede 5871554c0a3aSHans de Goede DBG_871X("link_timer_hdl: assoc timeout and try again\n"); 5872554c0a3aSHans de Goede issue_assocreq(padapter); 5873554c0a3aSHans de Goede set_link_timer(pmlmeext, REASSOC_TO); 5874554c0a3aSHans de Goede } 5875554c0a3aSHans de Goede } 5876554c0a3aSHans de Goede 5877e8b1844aSKees Cook void addba_timer_hdl(struct timer_list *t) 5878554c0a3aSHans de Goede { 5879e8b1844aSKees Cook struct sta_info *psta = from_timer(psta, t, addba_retry_timer); 5880554c0a3aSHans de Goede struct ht_priv *phtpriv; 5881554c0a3aSHans de Goede 5882554c0a3aSHans de Goede if (!psta) 5883554c0a3aSHans de Goede return; 5884554c0a3aSHans de Goede 5885554c0a3aSHans de Goede phtpriv = &psta->htpriv; 5886554c0a3aSHans de Goede 58870ad02fa8SGeorgiana Chelu if (phtpriv->ht_option && phtpriv->ampdu_enable) { 5888554c0a3aSHans de Goede if (phtpriv->candidate_tid_bitmap) 5889554c0a3aSHans de Goede phtpriv->candidate_tid_bitmap = 0x0; 5890554c0a3aSHans de Goede 5891554c0a3aSHans de Goede } 5892554c0a3aSHans de Goede } 5893554c0a3aSHans de Goede 5894e8b1844aSKees Cook void sa_query_timer_hdl(struct timer_list *t) 5895554c0a3aSHans de Goede { 5896e8b1844aSKees Cook struct adapter *padapter = 5897e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.sa_query_timer); 5898554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 5899554c0a3aSHans de Goede /* disconnect */ 5900554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 5901554c0a3aSHans de Goede 59020ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, _FW_LINKED)) { 5903554c0a3aSHans de Goede rtw_disassoc_cmd(padapter, 0, true); 5904554c0a3aSHans de Goede rtw_indicate_disconnect(padapter); 5905554c0a3aSHans de Goede rtw_free_assoc_resources(padapter, 1); 5906554c0a3aSHans de Goede } 5907554c0a3aSHans de Goede 5908554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 5909554c0a3aSHans de Goede DBG_871X("SA query timeout disconnect\n"); 5910554c0a3aSHans de Goede } 5911554c0a3aSHans de Goede 5912554c0a3aSHans de Goede u8 NULL_hdl(struct adapter *padapter, u8 *pbuf) 5913554c0a3aSHans de Goede { 5914554c0a3aSHans de Goede return H2C_SUCCESS; 5915554c0a3aSHans de Goede } 5916554c0a3aSHans de Goede 5917554c0a3aSHans de Goede #ifdef CONFIG_AUTO_AP_MODE 5918554c0a3aSHans de Goede static int rtw_auto_ap_start_beacon(struct adapter *adapter) 5919554c0a3aSHans de Goede { 5920554c0a3aSHans de Goede int ret = 0; 5921554c0a3aSHans de Goede u8 *pbuf = NULL; 5922554c0a3aSHans de Goede uint len; 5923554c0a3aSHans de Goede u8 supportRate[16]; 5924554c0a3aSHans de Goede int sz = 0, rateLen; 5925554c0a3aSHans de Goede u8 *ie; 5926554c0a3aSHans de Goede u8 wireless_mode, oper_channel; 5927554c0a3aSHans de Goede u8 ssid[3] = {0}; /* hidden ssid */ 5928554c0a3aSHans de Goede u32 ssid_len = sizeof(ssid); 5929554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); 5930554c0a3aSHans de Goede 5931554c0a3aSHans de Goede 5932554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5933554c0a3aSHans de Goede return -EINVAL; 5934554c0a3aSHans de Goede 5935554c0a3aSHans de Goede 5936554c0a3aSHans de Goede len = 128; 5937554c0a3aSHans de Goede pbuf = rtw_zmalloc(len); 5938554c0a3aSHans de Goede if (!pbuf) 5939554c0a3aSHans de Goede return -ENOMEM; 5940554c0a3aSHans de Goede 5941554c0a3aSHans de Goede 5942554c0a3aSHans de Goede /* generate beacon */ 5943554c0a3aSHans de Goede ie = pbuf; 5944554c0a3aSHans de Goede 5945554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 5946554c0a3aSHans de Goede sz += 8; 5947554c0a3aSHans de Goede ie += sz; 5948554c0a3aSHans de Goede 5949554c0a3aSHans de Goede /* beacon interval : 2bytes */ 5950554c0a3aSHans de Goede *(u16 *)ie = cpu_to_le16((u16)100);/* BCN_INTERVAL = 100; */ 5951554c0a3aSHans de Goede sz += 2; 5952554c0a3aSHans de Goede ie += 2; 5953554c0a3aSHans de Goede 5954554c0a3aSHans de Goede /* capability info */ 5955554c0a3aSHans de Goede *(u16 *)ie = 0; 5956554c0a3aSHans de Goede *(u16 *)ie |= cpu_to_le16(cap_ESS); 5957554c0a3aSHans de Goede *(u16 *)ie |= cpu_to_le16(cap_ShortPremble); 5958554c0a3aSHans de Goede /* u16*)ie |= cpu_to_le16(cap_Privacy); */ 5959554c0a3aSHans de Goede sz += 2; 5960554c0a3aSHans de Goede ie += 2; 5961554c0a3aSHans de Goede 5962554c0a3aSHans de Goede /* SSID */ 5963554c0a3aSHans de Goede ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz); 5964554c0a3aSHans de Goede 5965554c0a3aSHans de Goede /* supported rates */ 5966554c0a3aSHans de Goede wireless_mode = WIRELESS_11BG_24N; 5967554c0a3aSHans de Goede rtw_set_supported_rate(supportRate, wireless_mode); 5968554c0a3aSHans de Goede rateLen = rtw_get_rateset_len(supportRate); 5969554c0a3aSHans de Goede if (rateLen > 8) { 5970554c0a3aSHans de Goede ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz); 5971554c0a3aSHans de Goede } else { 5972554c0a3aSHans de Goede ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz); 5973554c0a3aSHans de Goede } 5974554c0a3aSHans de Goede 5975554c0a3aSHans de Goede 5976554c0a3aSHans de Goede /* DS parameter set */ 5977554c0a3aSHans de Goede if (check_buddy_fwstate(adapter, _FW_LINKED) && 5978554c0a3aSHans de Goede check_buddy_fwstate(adapter, WIFI_STATION_STATE)) { 5979554c0a3aSHans de Goede struct adapter *pbuddystruct adapter = adapter->pbuddystruct adapter; 5980554c0a3aSHans de Goede struct mlme_ext_priv *pbuddy_mlmeext = &pbuddystruct adapter->mlmeextpriv; 5981554c0a3aSHans de Goede 5982554c0a3aSHans de Goede oper_channel = pbuddy_mlmeext->cur_channel; 5983554c0a3aSHans de Goede } else { 5984554c0a3aSHans de Goede oper_channel = adapter_to_dvobj(adapter)->oper_channel; 5985554c0a3aSHans de Goede } 5986554c0a3aSHans de Goede ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz); 5987554c0a3aSHans de Goede 5988554c0a3aSHans de Goede /* ext supported rates */ 5989554c0a3aSHans de Goede if (rateLen > 8) { 5990554c0a3aSHans de Goede ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz); 5991554c0a3aSHans de Goede } 5992554c0a3aSHans de Goede 5993554c0a3aSHans de Goede DBG_871X("%s, start auto ap beacon sz =%d\n", __func__, sz); 5994554c0a3aSHans de Goede 5995554c0a3aSHans de Goede /* lunch ap mode & start to issue beacon */ 5996554c0a3aSHans de Goede if (rtw_check_beacon_data(adapter, pbuf, sz) == _SUCCESS) { 5997554c0a3aSHans de Goede 5998554c0a3aSHans de Goede } else { 5999554c0a3aSHans de Goede ret = -EINVAL; 6000554c0a3aSHans de Goede } 6001554c0a3aSHans de Goede 6002554c0a3aSHans de Goede 6003554c0a3aSHans de Goede kfree(pbuf); 6004554c0a3aSHans de Goede 6005554c0a3aSHans de Goede return ret; 6006554c0a3aSHans de Goede 6007554c0a3aSHans de Goede } 6008554c0a3aSHans de Goede #endif/* CONFIG_AUTO_AP_MODE */ 6009554c0a3aSHans de Goede 6010554c0a3aSHans de Goede u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) 6011554c0a3aSHans de Goede { 6012554c0a3aSHans de Goede u8 type; 6013554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6014554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6015554c0a3aSHans de Goede struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; 6016554c0a3aSHans de Goede 6017554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) { 6018554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_AP_STATE; 6019554c0a3aSHans de Goede type = _HW_STATE_AP_; 6020554c0a3aSHans de Goede /* start_ap_mode(padapter); */ 6021554c0a3aSHans de Goede } else if (psetop->mode == Ndis802_11Infrastructure) { 6022554c0a3aSHans de Goede pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */ 6023554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */ 6024554c0a3aSHans de Goede type = _HW_STATE_STATION_; 6025554c0a3aSHans de Goede } else if (psetop->mode == Ndis802_11IBSS) { 6026554c0a3aSHans de Goede type = _HW_STATE_ADHOC_; 6027554c0a3aSHans de Goede } else { 6028554c0a3aSHans de Goede type = _HW_STATE_NOLINK_; 6029554c0a3aSHans de Goede } 6030554c0a3aSHans de Goede 6031554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type)); 6032eb569cc0SNishka Dasgupta /* Set_MSR(padapter, type); */ 6033554c0a3aSHans de Goede 6034554c0a3aSHans de Goede 6035554c0a3aSHans de Goede #ifdef CONFIG_AUTO_AP_MODE 6036554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) 6037554c0a3aSHans de Goede rtw_auto_ap_start_beacon(padapter); 6038554c0a3aSHans de Goede #endif 6039554c0a3aSHans de Goede 6040554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) { 6041554c0a3aSHans de Goede /* Do this after port switch to */ 6042554c0a3aSHans de Goede /* prevent from downloading rsvd page to wrong port */ 6043554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */ 6044554c0a3aSHans de Goede } 6045554c0a3aSHans de Goede 6046554c0a3aSHans de Goede return H2C_SUCCESS; 6047554c0a3aSHans de Goede 6048554c0a3aSHans de Goede } 6049554c0a3aSHans de Goede 6050554c0a3aSHans de Goede u8 createbss_hdl(struct adapter *padapter, u8 *pbuf) 6051554c0a3aSHans de Goede { 6052554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6053554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6054554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 6055554c0a3aSHans de Goede struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf; 6056554c0a3aSHans de Goede /* u32 initialgain; */ 6057554c0a3aSHans de Goede 6058554c0a3aSHans de Goede if (pmlmeinfo->state == WIFI_FW_AP_STATE) { 6059554c0a3aSHans de Goede struct wlan_bssid_ex *network = &padapter->mlmepriv.cur_network.network; 6060c926f022SSimran Singhal 6061554c0a3aSHans de Goede start_bss_network(padapter, (u8 *)network); 6062554c0a3aSHans de Goede return H2C_SUCCESS; 6063554c0a3aSHans de Goede } 6064554c0a3aSHans de Goede 6065554c0a3aSHans de Goede /* below is for ad-hoc master */ 6066554c0a3aSHans de Goede if (pparm->network.InfrastructureMode == Ndis802_11IBSS) { 6067554c0a3aSHans de Goede rtw_joinbss_reset(padapter); 6068554c0a3aSHans de Goede 6069554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 6070554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6071554c0a3aSHans de Goede pmlmeinfo->ERP_enable = 0; 6072554c0a3aSHans de Goede pmlmeinfo->WMM_enable = 0; 6073554c0a3aSHans de Goede pmlmeinfo->HT_enable = 0; 6074554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 0; 6075554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 0; 6076554c0a3aSHans de Goede pmlmeinfo->agg_enable_bitmap = 0; 6077554c0a3aSHans de Goede pmlmeinfo->candidate_tid_bitmap = 0; 6078554c0a3aSHans de Goede 6079554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 6080554c0a3aSHans de Goede Save_DM_Func_Flag(padapter); 6081554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); 6082554c0a3aSHans de Goede 6083554c0a3aSHans de Goede /* config the initial gain under linking, need to write the BB registers */ 6084554c0a3aSHans de Goede /* initialgain = 0x1E; */ 6085554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ 6086554c0a3aSHans de Goede 6087554c0a3aSHans de Goede /* cancel link timer */ 6088554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 6089554c0a3aSHans de Goede 6090554c0a3aSHans de Goede /* clear CAM */ 6091554c0a3aSHans de Goede flush_all_cam_entry(padapter); 6092554c0a3aSHans de Goede 6093554c0a3aSHans de Goede memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength)); 6094554c0a3aSHans de Goede pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; 6095554c0a3aSHans de Goede 6096554c0a3aSHans de Goede if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ 6097554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6098554c0a3aSHans de Goede 6099554c0a3aSHans de Goede memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); 6100554c0a3aSHans de Goede 6101554c0a3aSHans de Goede start_create_ibss(padapter); 6102554c0a3aSHans de Goede 6103554c0a3aSHans de Goede } 6104554c0a3aSHans de Goede 6105554c0a3aSHans de Goede return H2C_SUCCESS; 6106554c0a3aSHans de Goede 6107554c0a3aSHans de Goede } 6108554c0a3aSHans de Goede 6109554c0a3aSHans de Goede u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) 6110554c0a3aSHans de Goede { 6111554c0a3aSHans de Goede u8 join_type; 6112554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 6113554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 6114554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6115554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6116554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 6117554c0a3aSHans de Goede u32 i; 6118554c0a3aSHans de Goede u8 cbw40_enable = 0; 6119554c0a3aSHans de Goede /* u32 initialgain; */ 6120554c0a3aSHans de Goede /* u32 acparm; */ 6121554c0a3aSHans de Goede u8 ch, bw, offset; 6122554c0a3aSHans de Goede 6123554c0a3aSHans de Goede /* check already connecting to AP or not */ 6124554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { 6125554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_STATION_STATE) { 6126554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); 6127554c0a3aSHans de Goede } 6128554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 6129554c0a3aSHans de Goede 6130554c0a3aSHans de Goede /* clear CAM */ 6131554c0a3aSHans de Goede flush_all_cam_entry(padapter); 6132554c0a3aSHans de Goede 6133554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 6134554c0a3aSHans de Goede 6135554c0a3aSHans de Goede /* set MSR to nolink -> infra. mode */ 6136554c0a3aSHans de Goede /* Set_MSR(padapter, _HW_STATE_NOLINK_); */ 6137554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_STATION_); 6138554c0a3aSHans de Goede 6139554c0a3aSHans de Goede 6140554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); 6141554c0a3aSHans de Goede } 6142554c0a3aSHans de Goede 6143554c0a3aSHans de Goede rtw_joinbss_reset(padapter); 6144554c0a3aSHans de Goede 6145554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 6146554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6147554c0a3aSHans de Goede pmlmeinfo->ERP_enable = 0; 6148554c0a3aSHans de Goede pmlmeinfo->WMM_enable = 0; 6149554c0a3aSHans de Goede pmlmeinfo->HT_enable = 0; 6150554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 0; 6151554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 0; 6152554c0a3aSHans de Goede pmlmeinfo->agg_enable_bitmap = 0; 6153554c0a3aSHans de Goede pmlmeinfo->candidate_tid_bitmap = 0; 6154554c0a3aSHans de Goede pmlmeinfo->bwmode_updated = false; 6155554c0a3aSHans de Goede /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ 6156554c0a3aSHans de Goede pmlmeinfo->VHT_enable = 0; 6157554c0a3aSHans de Goede 6158554c0a3aSHans de Goede memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength)); 6159554c0a3aSHans de Goede pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; 6160554c0a3aSHans de Goede 6161554c0a3aSHans de Goede if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ 6162554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6163554c0a3aSHans de Goede 6164554c0a3aSHans de Goede memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); 6165554c0a3aSHans de Goede 6166554c0a3aSHans de Goede pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; 6167554c0a3aSHans de Goede pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); 6168554c0a3aSHans de Goede 6169554c0a3aSHans de Goede /* Check AP vendor to move rtw_joinbss_cmd() */ 6170554c0a3aSHans de Goede /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */ 6171554c0a3aSHans de Goede 6172554c0a3aSHans de Goede /* sizeof(struct ndis_802_11_fix_ie) */ 6173554c0a3aSHans de Goede for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) { 6174554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i); 6175554c0a3aSHans de Goede 6176554c0a3aSHans de Goede switch (pIE->ElementID) { 6177554c0a3aSHans de Goede case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */ 6178554c0a3aSHans de Goede if (!memcmp(pIE->data, WMM_OUI, 4)) 6179554c0a3aSHans de Goede WMM_param_handler(padapter, pIE); 6180554c0a3aSHans de Goede break; 6181554c0a3aSHans de Goede 6182554c0a3aSHans de Goede case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */ 6183554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 1; 6184554c0a3aSHans de Goede break; 6185554c0a3aSHans de Goede 6186554c0a3aSHans de Goede case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */ 6187554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 1; 6188554c0a3aSHans de Goede 6189554c0a3aSHans de Goede /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */ 6190554c0a3aSHans de Goede { 6191554c0a3aSHans de Goede struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data); 6192554c0a3aSHans de Goede 6193554c0a3aSHans de Goede if (pnetwork->Configuration.DSConfig > 14) { 6194554c0a3aSHans de Goede if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20) 6195554c0a3aSHans de Goede cbw40_enable = 1; 6196554c0a3aSHans de Goede } else { 6197554c0a3aSHans de Goede if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20) 6198554c0a3aSHans de Goede cbw40_enable = 1; 6199554c0a3aSHans de Goede } 6200554c0a3aSHans de Goede 6201554c0a3aSHans de Goede if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) { 6202554c0a3aSHans de Goede /* switch to the 40M Hz mode according to the AP */ 6203554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; 6204554c0a3aSHans de Goede switch (pht_info->infos[0] & 0x3) { 6205554c0a3aSHans de Goede case 1: 6206554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; 6207554c0a3aSHans de Goede break; 6208554c0a3aSHans de Goede 6209554c0a3aSHans de Goede case 3: 6210554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; 6211554c0a3aSHans de Goede break; 6212554c0a3aSHans de Goede 6213554c0a3aSHans de Goede default: 6214554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6215554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 6216554c0a3aSHans de Goede break; 6217554c0a3aSHans de Goede } 6218554c0a3aSHans de Goede 6219554c0a3aSHans de Goede DBG_871X("set HT ch/bw before connected\n"); 6220554c0a3aSHans de Goede } 6221554c0a3aSHans de Goede } 6222554c0a3aSHans de Goede break; 6223554c0a3aSHans de Goede default: 6224554c0a3aSHans de Goede break; 6225554c0a3aSHans de Goede } 6226554c0a3aSHans de Goede 6227554c0a3aSHans de Goede i += (pIE->Length + 2); 6228554c0a3aSHans de Goede } 6229554c0a3aSHans de Goede 6230554c0a3aSHans de Goede /* check channel, bandwidth, offset and switch */ 6231554c0a3aSHans de Goede if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) { 6232554c0a3aSHans de Goede report_join_res(padapter, (-4)); 6233554c0a3aSHans de Goede return H2C_SUCCESS; 6234554c0a3aSHans de Goede } 6235554c0a3aSHans de Goede 6236554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 6237554c0a3aSHans de Goede /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */ 6238554c0a3aSHans de Goede 6239554c0a3aSHans de Goede /* config the initial gain under linking, need to write the BB registers */ 6240554c0a3aSHans de Goede /* initialgain = 0x1E; */ 6241554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ 6242554c0a3aSHans de Goede 6243554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress); 6244554c0a3aSHans de Goede join_type = 0; 6245554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 6246554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL); 6247554c0a3aSHans de Goede 6248554c0a3aSHans de Goede set_channel_bwmode(padapter, ch, offset, bw); 6249554c0a3aSHans de Goede 6250554c0a3aSHans de Goede /* cancel link timer */ 6251554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 6252554c0a3aSHans de Goede 6253554c0a3aSHans de Goede start_clnt_join(padapter); 6254554c0a3aSHans de Goede 6255554c0a3aSHans de Goede return H2C_SUCCESS; 6256554c0a3aSHans de Goede 6257554c0a3aSHans de Goede } 6258554c0a3aSHans de Goede 6259554c0a3aSHans de Goede u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf) 6260554c0a3aSHans de Goede { 6261554c0a3aSHans de Goede struct disconnect_parm *param = (struct disconnect_parm *)pbuf; 6262554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6263554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6264554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 6265554c0a3aSHans de Goede u8 val8; 6266554c0a3aSHans de Goede 6267554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter)) { 6268554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100); 6269554c0a3aSHans de Goede } 6270554c0a3aSHans de Goede 6271554c0a3aSHans de Goede if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) { 6272554c0a3aSHans de Goede /* Stop BCN */ 6273554c0a3aSHans de Goede val8 = 0; 6274554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8)); 6275554c0a3aSHans de Goede } 6276554c0a3aSHans de Goede 6277554c0a3aSHans de Goede rtw_mlmeext_disconnect(padapter); 6278554c0a3aSHans de Goede 6279554c0a3aSHans de Goede rtw_free_uc_swdec_pending_queue(padapter); 6280554c0a3aSHans de Goede 6281554c0a3aSHans de Goede return H2C_SUCCESS; 6282554c0a3aSHans de Goede } 6283554c0a3aSHans de Goede 6284554c0a3aSHans de Goede static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out, 6285554c0a3aSHans de Goede u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num) 6286554c0a3aSHans de Goede { 6287554c0a3aSHans de Goede int i, j; 6288554c0a3aSHans de Goede int set_idx; 6289554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6290554c0a3aSHans de Goede 6291554c0a3aSHans de Goede /* clear first */ 6292554c0a3aSHans de Goede memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num); 6293554c0a3aSHans de Goede 6294554c0a3aSHans de Goede /* acquire channels from in */ 6295554c0a3aSHans de Goede j = 0; 6296554c0a3aSHans de Goede for (i = 0; i < in_num; i++) { 6297554c0a3aSHans de Goede 6298554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i])); 6299554c0a3aSHans de Goede 6300554c0a3aSHans de Goede set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value); 6301554c0a3aSHans de Goede if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) 6302554c0a3aSHans de Goede && set_idx >= 0 63030ad02fa8SGeorgiana Chelu && rtw_mlme_band_check(padapter, in[i].hw_value) 6304554c0a3aSHans de Goede ) { 6305554c0a3aSHans de Goede if (j >= out_num) { 6306554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", 6307554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), out_num); 6308554c0a3aSHans de Goede break; 6309554c0a3aSHans de Goede } 6310554c0a3aSHans de Goede 6311554c0a3aSHans de Goede memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel)); 6312554c0a3aSHans de Goede 6313554c0a3aSHans de Goede if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE) 6314554c0a3aSHans de Goede out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; 6315554c0a3aSHans de Goede 6316554c0a3aSHans de Goede j++; 6317554c0a3aSHans de Goede } 6318554c0a3aSHans de Goede if (j >= out_num) 6319554c0a3aSHans de Goede break; 6320554c0a3aSHans de Goede } 6321554c0a3aSHans de Goede 6322554c0a3aSHans de Goede /* if out is empty, use channel_set as default */ 6323554c0a3aSHans de Goede if (j == 0) { 6324554c0a3aSHans de Goede for (i = 0; i < pmlmeext->max_chan_nums; i++) { 6325554c0a3aSHans de Goede 6326554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum); 6327554c0a3aSHans de Goede 63280ad02fa8SGeorgiana Chelu if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum)) { 6329554c0a3aSHans de Goede 6330554c0a3aSHans de Goede if (j >= out_num) { 6331554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", 6332554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), out_num); 6333554c0a3aSHans de Goede break; 6334554c0a3aSHans de Goede } 6335554c0a3aSHans de Goede 6336554c0a3aSHans de Goede out[j].hw_value = pmlmeext->channel_set[i].ChannelNum; 6337554c0a3aSHans de Goede 6338554c0a3aSHans de Goede if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) 6339554c0a3aSHans de Goede out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; 6340554c0a3aSHans de Goede 6341554c0a3aSHans de Goede j++; 6342554c0a3aSHans de Goede } 6343554c0a3aSHans de Goede } 6344554c0a3aSHans de Goede } 6345554c0a3aSHans de Goede 6346554c0a3aSHans de Goede return j; 6347554c0a3aSHans de Goede } 6348554c0a3aSHans de Goede 6349554c0a3aSHans de Goede u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf) 6350554c0a3aSHans de Goede { 6351554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6352554c0a3aSHans de Goede struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; 6353554c0a3aSHans de Goede u8 bdelayscan = false; 6354554c0a3aSHans de Goede u8 val8; 6355554c0a3aSHans de Goede u32 initialgain; 6356554c0a3aSHans de Goede u32 i; 6357554c0a3aSHans de Goede 6358554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { 6359554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_START; 6360554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt = 0; 6361554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = 0; 6362554c0a3aSHans de Goede 6363554c0a3aSHans de Goede for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { 6364554c0a3aSHans de Goede if (pparm->ssid[i].SsidLength) { 6365554c0a3aSHans de Goede memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE); 6366554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength; 6367554c0a3aSHans de Goede } else { 6368554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0; 6369554c0a3aSHans de Goede } 6370554c0a3aSHans de Goede } 6371554c0a3aSHans de Goede 6372554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter 6373554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT 6374554c0a3aSHans de Goede , pparm->ch, pparm->ch_num 6375554c0a3aSHans de Goede ); 6376554c0a3aSHans de Goede 6377554c0a3aSHans de Goede pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode; 6378554c0a3aSHans de Goede 6379554c0a3aSHans de Goede /* issue null data if associating to the AP */ 63800ad02fa8SGeorgiana Chelu if (is_client_associated_to_ap(padapter)) { 6381554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_TXNULL; 6382554c0a3aSHans de Goede 6383554c0a3aSHans de Goede issue_nulldata(padapter, NULL, 1, 3, 500); 6384554c0a3aSHans de Goede 6385554c0a3aSHans de Goede bdelayscan = true; 6386554c0a3aSHans de Goede } 6387554c0a3aSHans de Goede if (bdelayscan) { 6388554c0a3aSHans de Goede /* delay 50ms to protect nulldata(1). */ 6389554c0a3aSHans de Goede set_survey_timer(pmlmeext, 50); 6390554c0a3aSHans de Goede return H2C_SUCCESS; 6391554c0a3aSHans de Goede } 6392554c0a3aSHans de Goede } 6393554c0a3aSHans de Goede 6394554c0a3aSHans de Goede if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) { 6395554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 6396554c0a3aSHans de Goede Save_DM_Func_Flag(padapter); 6397554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); 6398554c0a3aSHans de Goede 63994d17363dSAndreas Hellmich /* config the initial gain under scanning, need to write the BB 64004d17363dSAndreas Hellmich * registers 64014d17363dSAndreas Hellmich */ 6402554c0a3aSHans de Goede initialgain = 0x1e; 6403554c0a3aSHans de Goede 6404554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 6405554c0a3aSHans de Goede 6406554c0a3aSHans de Goede /* set MSR to no link state */ 6407554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_NOLINK_); 6408554c0a3aSHans de Goede 6409554c0a3aSHans de Goede val8 = 1; /* under site survey */ 6410554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); 6411554c0a3aSHans de Goede 6412554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_PROCESS; 6413554c0a3aSHans de Goede } 6414554c0a3aSHans de Goede 6415554c0a3aSHans de Goede site_survey(padapter); 6416554c0a3aSHans de Goede 6417554c0a3aSHans de Goede return H2C_SUCCESS; 6418554c0a3aSHans de Goede 6419554c0a3aSHans de Goede } 6420554c0a3aSHans de Goede 6421554c0a3aSHans de Goede u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf) 6422554c0a3aSHans de Goede { 6423554c0a3aSHans de Goede struct setauth_parm *pparm = (struct setauth_parm *)pbuf; 6424554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6425554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6426554c0a3aSHans de Goede 6427a65f0d18SVatsala Narang if (pparm->mode < 4) 6428554c0a3aSHans de Goede pmlmeinfo->auth_algo = pparm->mode; 6429554c0a3aSHans de Goede 6430554c0a3aSHans de Goede return H2C_SUCCESS; 6431554c0a3aSHans de Goede } 6432554c0a3aSHans de Goede 6433554c0a3aSHans de Goede u8 setkey_hdl(struct adapter *padapter, u8 *pbuf) 6434554c0a3aSHans de Goede { 6435554c0a3aSHans de Goede u16 ctrl = 0; 6436554c0a3aSHans de Goede s16 cam_id = 0; 6437554c0a3aSHans de Goede struct setkey_parm *pparm = (struct setkey_parm *)pbuf; 6438554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6439554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6440554c0a3aSHans de Goede unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 6441554c0a3aSHans de Goede u8 *addr; 6442554c0a3aSHans de Goede 6443554c0a3aSHans de Goede /* main tx key for wep. */ 6444554c0a3aSHans de Goede if (pparm->set_tx) 6445554c0a3aSHans de Goede pmlmeinfo->key_index = pparm->keyid; 6446554c0a3aSHans de Goede 6447554c0a3aSHans de Goede cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid); 6448554c0a3aSHans de Goede 6449554c0a3aSHans de Goede if (cam_id < 0) { 6450554c0a3aSHans de Goede } else { 6451554c0a3aSHans de Goede if (cam_id > 3) /* not default key, searched by A2 */ 6452554c0a3aSHans de Goede addr = get_bssid(&padapter->mlmepriv); 6453554c0a3aSHans de Goede else 6454554c0a3aSHans de Goede addr = null_addr; 6455554c0a3aSHans de Goede 6456554c0a3aSHans de Goede ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid; 6457554c0a3aSHans de Goede write_cam(padapter, cam_id, ctrl, addr, pparm->key); 6458bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:%pM, kid:%d, type:%s\n" 6459554c0a3aSHans de Goede , cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm)); 6460554c0a3aSHans de Goede } 6461554c0a3aSHans de Goede 6462554c0a3aSHans de Goede if (cam_id >= 0 && cam_id <= 3) 6463554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true); 6464554c0a3aSHans de Goede 6465554c0a3aSHans de Goede /* allow multicast packets to driver */ 6466554c0a3aSHans de Goede padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr); 6467554c0a3aSHans de Goede 6468554c0a3aSHans de Goede return H2C_SUCCESS; 6469554c0a3aSHans de Goede } 6470554c0a3aSHans de Goede 6471554c0a3aSHans de Goede u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) 6472554c0a3aSHans de Goede { 6473554c0a3aSHans de Goede u16 ctrl = 0; 6474554c0a3aSHans de Goede s16 cam_id = 0; 6475554c0a3aSHans de Goede u8 ret = H2C_SUCCESS; 6476554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6477554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6478554c0a3aSHans de Goede struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; 6479554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 6480554c0a3aSHans de Goede struct sta_info *psta; 6481554c0a3aSHans de Goede 6482554c0a3aSHans de Goede if (pparm->algorithm == _NO_PRIVACY_) 6483554c0a3aSHans de Goede goto write_to_cam; 6484554c0a3aSHans de Goede 6485554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, pparm->addr); 6486554c0a3aSHans de Goede if (!psta) { 6487bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "%s sta:%pM not found\n", __func__, MAC_ARG(pparm->addr)); 6488554c0a3aSHans de Goede ret = H2C_REJECTED; 6489554c0a3aSHans de Goede goto exit; 6490554c0a3aSHans de Goede } 6491554c0a3aSHans de Goede 6492554c0a3aSHans de Goede pmlmeinfo->enc_algo = pparm->algorithm; 6493554c0a3aSHans de Goede cam_id = rtw_camid_alloc(padapter, psta, 0); 6494554c0a3aSHans de Goede if (cam_id < 0) 6495554c0a3aSHans de Goede goto exit; 6496554c0a3aSHans de Goede 6497554c0a3aSHans de Goede write_to_cam: 6498554c0a3aSHans de Goede if (pparm->algorithm == _NO_PRIVACY_) { 6499554c0a3aSHans de Goede while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) { 6500bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "clear key for addr:%pM, camid:%d\n", MAC_ARG(pparm->addr), cam_id); 6501554c0a3aSHans de Goede clear_cam_entry(padapter, cam_id); 6502554c0a3aSHans de Goede rtw_camid_free(padapter, cam_id); 6503554c0a3aSHans de Goede } 6504554c0a3aSHans de Goede } else { 6505bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:%pM, kid:%d, type:%s\n", 6506554c0a3aSHans de Goede cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm)); 6507554c0a3aSHans de Goede ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid; 6508554c0a3aSHans de Goede write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); 6509554c0a3aSHans de Goede } 6510554c0a3aSHans de Goede ret = H2C_SUCCESS_RSP; 6511554c0a3aSHans de Goede 6512554c0a3aSHans de Goede exit: 6513554c0a3aSHans de Goede return ret; 6514554c0a3aSHans de Goede } 6515554c0a3aSHans de Goede 6516554c0a3aSHans de Goede u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf) 6517554c0a3aSHans de Goede { 6518554c0a3aSHans de Goede struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; 6519554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6520554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6521554c0a3aSHans de Goede 6522554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr); 6523554c0a3aSHans de Goede 6524554c0a3aSHans de Goede if (!psta) 6525554c0a3aSHans de Goede return H2C_SUCCESS; 6526554c0a3aSHans de Goede 6527554c0a3aSHans de Goede if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) || 6528554c0a3aSHans de Goede ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) { 6529554c0a3aSHans de Goede /* pmlmeinfo->ADDBA_retry_count = 0; */ 6530554c0a3aSHans de Goede /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */ 6531554c0a3aSHans de Goede /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */ 6532*f4acd33cSRoss Schmidt issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); 6533554c0a3aSHans de Goede /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */ 6534554c0a3aSHans de Goede _set_timer(&psta->addba_retry_timer, ADDBA_TO); 6535554c0a3aSHans de Goede } else { 6536554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); 6537554c0a3aSHans de Goede } 6538554c0a3aSHans de Goede return H2C_SUCCESS; 6539554c0a3aSHans de Goede } 6540554c0a3aSHans de Goede 6541554c0a3aSHans de Goede 6542554c0a3aSHans de Goede u8 chk_bmc_sleepq_cmd(struct adapter *padapter) 6543554c0a3aSHans de Goede { 6544554c0a3aSHans de Goede struct cmd_obj *ph2c; 6545554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 6546554c0a3aSHans de Goede u8 res = _SUCCESS; 6547554c0a3aSHans de Goede 65482ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 6549554c0a3aSHans de Goede if (ph2c == NULL) { 6550554c0a3aSHans de Goede res = _FAIL; 6551554c0a3aSHans de Goede goto exit; 6552554c0a3aSHans de Goede } 6553554c0a3aSHans de Goede 6554554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq)); 6555554c0a3aSHans de Goede 6556554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 6557554c0a3aSHans de Goede 6558554c0a3aSHans de Goede exit: 6559554c0a3aSHans de Goede return res; 6560554c0a3aSHans de Goede } 6561554c0a3aSHans de Goede 6562554c0a3aSHans de Goede u8 set_tx_beacon_cmd(struct adapter *padapter) 6563554c0a3aSHans de Goede { 6564554c0a3aSHans de Goede struct cmd_obj *ph2c; 6565554c0a3aSHans de Goede struct Tx_Beacon_param *ptxBeacon_parm; 6566554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 6567554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6568554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6569554c0a3aSHans de Goede u8 res = _SUCCESS; 6570554c0a3aSHans de Goede int len_diff = 0; 6571554c0a3aSHans de Goede 65722ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 6573554c0a3aSHans de Goede if (ph2c == NULL) { 6574554c0a3aSHans de Goede res = _FAIL; 6575554c0a3aSHans de Goede goto exit; 6576554c0a3aSHans de Goede } 6577554c0a3aSHans de Goede 65782ef2b7c2SJoe Perches ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param)); 6579554c0a3aSHans de Goede if (ptxBeacon_parm == NULL) { 65808f24f505SMadhumitha Prabakaran kfree(ph2c); 6581554c0a3aSHans de Goede res = _FAIL; 6582554c0a3aSHans de Goede goto exit; 6583554c0a3aSHans de Goede } 6584554c0a3aSHans de Goede 6585554c0a3aSHans de Goede memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex)); 6586554c0a3aSHans de Goede 6587554c0a3aSHans de Goede len_diff = update_hidden_ssid( 6588554c0a3aSHans de Goede ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_ 6589554c0a3aSHans de Goede , ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_ 6590554c0a3aSHans de Goede , pmlmeinfo->hidden_ssid_mode 6591554c0a3aSHans de Goede ); 6592554c0a3aSHans de Goede ptxBeacon_parm->network.IELength += len_diff; 6593554c0a3aSHans de Goede 6594554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon)); 6595554c0a3aSHans de Goede 6596554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 6597554c0a3aSHans de Goede 6598554c0a3aSHans de Goede exit: 6599554c0a3aSHans de Goede return res; 6600554c0a3aSHans de Goede } 6601554c0a3aSHans de Goede 6602554c0a3aSHans de Goede 6603554c0a3aSHans de Goede u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) 6604554c0a3aSHans de Goede { 6605554c0a3aSHans de Goede u8 evt_code, evt_seq; 6606554c0a3aSHans de Goede u16 evt_sz; 6607554c0a3aSHans de Goede uint *peventbuf; 6608554c0a3aSHans de Goede void (*event_callback)(struct adapter *dev, u8 *pbuf); 6609554c0a3aSHans de Goede struct evt_priv *pevt_priv = &(padapter->evtpriv); 6610554c0a3aSHans de Goede 6611554c0a3aSHans de Goede if (pbuf == NULL) 6612554c0a3aSHans de Goede goto _abort_event_; 6613554c0a3aSHans de Goede 6614554c0a3aSHans de Goede peventbuf = (uint *)pbuf; 6615554c0a3aSHans de Goede evt_sz = (u16)(*peventbuf&0xffff); 6616554c0a3aSHans de Goede evt_seq = (u8)((*peventbuf>>24)&0x7f); 6617554c0a3aSHans de Goede evt_code = (u8)((*peventbuf>>16)&0xff); 6618554c0a3aSHans de Goede 6619554c0a3aSHans de Goede 6620554c0a3aSHans de Goede #ifdef CHECK_EVENT_SEQ 6621554c0a3aSHans de Goede /* checking event sequence... */ 6622554c0a3aSHans de Goede if (evt_seq != (atomic_read(&pevt_priv->event_seq) & 0x7f)) { 6623103ab687SColin Ian King RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, 6624103ab687SColin Ian King ("Event Seq Error! %d vs %d\n", (evt_seq & 0x7f), 6625103ab687SColin Ian King (atomic_read(&pevt_priv->event_seq) & 0x7f))); 6626554c0a3aSHans de Goede 6627554c0a3aSHans de Goede pevt_priv->event_seq = (evt_seq+1)&0x7f; 6628554c0a3aSHans de Goede 6629554c0a3aSHans de Goede goto _abort_event_; 6630554c0a3aSHans de Goede } 6631554c0a3aSHans de Goede #endif 6632554c0a3aSHans de Goede 6633554c0a3aSHans de Goede /* checking if event code is valid */ 6634554c0a3aSHans de Goede if (evt_code >= MAX_C2HEVT) { 6635554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code)); 6636554c0a3aSHans de Goede goto _abort_event_; 6637554c0a3aSHans de Goede } 6638554c0a3aSHans de Goede 6639554c0a3aSHans de Goede /* checking if event size match the event parm size */ 6640554c0a3aSHans de Goede if ((wlanevents[evt_code].parmsize != 0) && 6641554c0a3aSHans de Goede (wlanevents[evt_code].parmsize != evt_sz)) { 6642554c0a3aSHans de Goede 6643554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n", 6644554c0a3aSHans de Goede evt_code, wlanevents[evt_code].parmsize, evt_sz)); 6645554c0a3aSHans de Goede goto _abort_event_; 6646554c0a3aSHans de Goede 6647554c0a3aSHans de Goede } 6648554c0a3aSHans de Goede 6649554c0a3aSHans de Goede atomic_inc(&pevt_priv->event_seq); 6650554c0a3aSHans de Goede 6651554c0a3aSHans de Goede peventbuf += 2; 6652554c0a3aSHans de Goede 6653554c0a3aSHans de Goede if (peventbuf) { 6654554c0a3aSHans de Goede event_callback = wlanevents[evt_code].event_callback; 6655554c0a3aSHans de Goede event_callback(padapter, (u8 *)peventbuf); 6656554c0a3aSHans de Goede 6657554c0a3aSHans de Goede pevt_priv->evt_done_cnt++; 6658554c0a3aSHans de Goede } 6659554c0a3aSHans de Goede 6660554c0a3aSHans de Goede 6661554c0a3aSHans de Goede _abort_event_: 6662554c0a3aSHans de Goede 6663554c0a3aSHans de Goede 6664554c0a3aSHans de Goede return H2C_SUCCESS; 6665554c0a3aSHans de Goede 6666554c0a3aSHans de Goede } 6667554c0a3aSHans de Goede 6668554c0a3aSHans de Goede u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf) 6669554c0a3aSHans de Goede { 6670554c0a3aSHans de Goede if (!pbuf) 6671554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6672554c0a3aSHans de Goede 6673554c0a3aSHans de Goede return H2C_SUCCESS; 6674554c0a3aSHans de Goede } 6675554c0a3aSHans de Goede 6676554c0a3aSHans de Goede u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) 6677554c0a3aSHans de Goede { 6678554c0a3aSHans de Goede struct sta_info *psta_bmc; 6679554c0a3aSHans de Goede struct list_head *xmitframe_plist, *xmitframe_phead; 6680554c0a3aSHans de Goede struct xmit_frame *pxmitframe = NULL; 6681554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 6682554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 6683554c0a3aSHans de Goede 6684554c0a3aSHans de Goede /* for BC/MC Frames */ 6685554c0a3aSHans de Goede psta_bmc = rtw_get_bcmc_stainfo(padapter); 6686554c0a3aSHans de Goede if (!psta_bmc) 6687554c0a3aSHans de Goede return H2C_SUCCESS; 6688554c0a3aSHans de Goede 6689554c0a3aSHans de Goede if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) { 6690554c0a3aSHans de Goede msleep(10);/* 10ms, ATIM(HIQ) Windows */ 6691554c0a3aSHans de Goede 6692554c0a3aSHans de Goede /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ 6693554c0a3aSHans de Goede spin_lock_bh(&pxmitpriv->lock); 6694554c0a3aSHans de Goede 6695554c0a3aSHans de Goede xmitframe_phead = get_list_head(&psta_bmc->sleep_q); 6696554c0a3aSHans de Goede xmitframe_plist = get_next(xmitframe_phead); 6697554c0a3aSHans de Goede 6698554c0a3aSHans de Goede while (xmitframe_phead != xmitframe_plist) { 6699554c0a3aSHans de Goede pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); 6700554c0a3aSHans de Goede 6701554c0a3aSHans de Goede xmitframe_plist = get_next(xmitframe_plist); 6702554c0a3aSHans de Goede 6703554c0a3aSHans de Goede list_del_init(&pxmitframe->list); 6704554c0a3aSHans de Goede 6705554c0a3aSHans de Goede psta_bmc->sleepq_len--; 6706554c0a3aSHans de Goede if (psta_bmc->sleepq_len > 0) 6707554c0a3aSHans de Goede pxmitframe->attrib.mdata = 1; 6708554c0a3aSHans de Goede else 6709554c0a3aSHans de Goede pxmitframe->attrib.mdata = 0; 6710554c0a3aSHans de Goede 6711554c0a3aSHans de Goede pxmitframe->attrib.triggered = 1; 6712554c0a3aSHans de Goede 67130ad02fa8SGeorgiana Chelu if (xmitframe_hiq_filter(pxmitframe)) 6714554c0a3aSHans de Goede pxmitframe->attrib.qsel = 0x11;/* HIQ */ 6715554c0a3aSHans de Goede 6716554c0a3aSHans de Goede rtw_hal_xmitframe_enqueue(padapter, pxmitframe); 6717554c0a3aSHans de Goede } 6718554c0a3aSHans de Goede 6719554c0a3aSHans de Goede /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ 6720554c0a3aSHans de Goede spin_unlock_bh(&pxmitpriv->lock); 6721554c0a3aSHans de Goede 6722554c0a3aSHans de Goede /* check hi queue and bmc_sleepq */ 6723554c0a3aSHans de Goede rtw_chk_hi_queue_cmd(padapter); 6724554c0a3aSHans de Goede } 6725554c0a3aSHans de Goede 6726554c0a3aSHans de Goede return H2C_SUCCESS; 6727554c0a3aSHans de Goede } 6728554c0a3aSHans de Goede 6729554c0a3aSHans de Goede u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf) 6730554c0a3aSHans de Goede { 6731554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 6732554c0a3aSHans de Goede DBG_871X("issue_beacon, fail!\n"); 6733554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6734554c0a3aSHans de Goede } 6735554c0a3aSHans de Goede 6736554c0a3aSHans de Goede /* tx bc/mc frames after update TIM */ 6737554c0a3aSHans de Goede chk_bmc_sleepq_hdl(padapter, NULL); 6738554c0a3aSHans de Goede 6739554c0a3aSHans de Goede return H2C_SUCCESS; 6740554c0a3aSHans de Goede } 6741554c0a3aSHans de Goede 6742554c0a3aSHans de Goede int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset) 6743554c0a3aSHans de Goede { 6744554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6745554c0a3aSHans de Goede unsigned char cur_ch = pmlmeext->cur_channel; 6746554c0a3aSHans de Goede unsigned char cur_bw = pmlmeext->cur_bwmode; 6747554c0a3aSHans de Goede unsigned char cur_ch_offset = pmlmeext->cur_ch_offset; 6748554c0a3aSHans de Goede bool connect_allow = true; 6749554c0a3aSHans de Goede 6750554c0a3aSHans de Goede if (!ch || !bw || !offset) { 6751554c0a3aSHans de Goede rtw_warn_on(1); 6752554c0a3aSHans de Goede connect_allow = false; 6753554c0a3aSHans de Goede } 6754554c0a3aSHans de Goede 67550ad02fa8SGeorgiana Chelu if (connect_allow) { 6756554c0a3aSHans de Goede DBG_871X("start_join_set_ch_bw: ch =%d, bwmode =%d, ch_offset =%d\n", cur_ch, cur_bw, cur_ch_offset); 6757554c0a3aSHans de Goede *ch = cur_ch; 6758554c0a3aSHans de Goede *bw = cur_bw; 6759554c0a3aSHans de Goede *offset = cur_ch_offset; 6760554c0a3aSHans de Goede } 6761554c0a3aSHans de Goede 676263a9c3edSJeeeun Evans return connect_allow ? _SUCCESS : _FAIL; 6763554c0a3aSHans de Goede } 6764554c0a3aSHans de Goede 6765554c0a3aSHans de Goede /* Find union about ch, bw, ch_offset of all linked/linking interfaces */ 6766554c0a3aSHans de Goede int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset) 6767554c0a3aSHans de Goede { 6768554c0a3aSHans de Goede struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); 6769554c0a3aSHans de Goede struct adapter *iface; 6770554c0a3aSHans de Goede 6771554c0a3aSHans de Goede if (ch) 6772554c0a3aSHans de Goede *ch = 0; 6773554c0a3aSHans de Goede if (bw) 6774554c0a3aSHans de Goede *bw = CHANNEL_WIDTH_20; 6775554c0a3aSHans de Goede if (offset) 6776554c0a3aSHans de Goede *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6777554c0a3aSHans de Goede 6778554c0a3aSHans de Goede iface = dvobj->padapters; 6779554c0a3aSHans de Goede 6780554c0a3aSHans de Goede if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING)) 6781554c0a3aSHans de Goede return 0; 6782554c0a3aSHans de Goede 6783554c0a3aSHans de Goede return 1; 6784554c0a3aSHans de Goede } 6785554c0a3aSHans de Goede 6786554c0a3aSHans de Goede u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf) 6787554c0a3aSHans de Goede { 6788554c0a3aSHans de Goede struct set_ch_parm *set_ch_parm; 6789554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6790554c0a3aSHans de Goede 6791554c0a3aSHans de Goede if (!pbuf) 6792554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6793554c0a3aSHans de Goede 6794554c0a3aSHans de Goede set_ch_parm = (struct set_ch_parm *)pbuf; 6795554c0a3aSHans de Goede 6796554c0a3aSHans de Goede DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n", 6797554c0a3aSHans de Goede FUNC_NDEV_ARG(padapter->pnetdev), 6798554c0a3aSHans de Goede set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset); 6799554c0a3aSHans de Goede 6800554c0a3aSHans de Goede pmlmeext->cur_channel = set_ch_parm->ch; 6801554c0a3aSHans de Goede pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; 6802554c0a3aSHans de Goede pmlmeext->cur_bwmode = set_ch_parm->bw; 6803554c0a3aSHans de Goede 6804554c0a3aSHans de Goede set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw); 6805554c0a3aSHans de Goede 6806554c0a3aSHans de Goede return H2C_SUCCESS; 6807554c0a3aSHans de Goede } 6808554c0a3aSHans de Goede 6809554c0a3aSHans de Goede u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf) 6810554c0a3aSHans de Goede { 6811554c0a3aSHans de Goede struct SetChannelPlan_param *setChannelPlan_param; 6812554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6813554c0a3aSHans de Goede 6814554c0a3aSHans de Goede if (!pbuf) 6815554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6816554c0a3aSHans de Goede 6817554c0a3aSHans de Goede setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; 6818554c0a3aSHans de Goede 6819554c0a3aSHans de Goede pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set); 6820554c0a3aSHans de Goede init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); 6821554c0a3aSHans de Goede 682234557e23SIzabela Bakollari if (padapter->rtw_wdev && padapter->rtw_wdev->wiphy) { 6823554c0a3aSHans de Goede struct regulatory_request request; 6824c926f022SSimran Singhal 6825554c0a3aSHans de Goede request.initiator = NL80211_REGDOM_SET_BY_DRIVER; 6826554c0a3aSHans de Goede rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request); 6827554c0a3aSHans de Goede } 6828554c0a3aSHans de Goede 6829554c0a3aSHans de Goede return H2C_SUCCESS; 6830554c0a3aSHans de Goede } 6831554c0a3aSHans de Goede 6832554c0a3aSHans de Goede u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf) 6833554c0a3aSHans de Goede { 6834554c0a3aSHans de Goede struct LedBlink_param *ledBlink_param; 6835554c0a3aSHans de Goede 6836554c0a3aSHans de Goede if (!pbuf) 6837554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6838554c0a3aSHans de Goede 6839554c0a3aSHans de Goede ledBlink_param = (struct LedBlink_param *)pbuf; 6840554c0a3aSHans de Goede return H2C_SUCCESS; 6841554c0a3aSHans de Goede } 6842554c0a3aSHans de Goede 6843554c0a3aSHans de Goede u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf) 6844554c0a3aSHans de Goede { 6845554c0a3aSHans de Goede return H2C_REJECTED; 6846554c0a3aSHans de Goede } 6847554c0a3aSHans de Goede 6848554c0a3aSHans de Goede /* TDLS_ESTABLISHED : write RCR DATA BIT */ 6849554c0a3aSHans de Goede /* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */ 6850554c0a3aSHans de Goede /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */ 6851554c0a3aSHans de Goede /* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */ 6852554c0a3aSHans de Goede /* TDLS_OFF_CH : first time set channel to off channel */ 6853554c0a3aSHans de Goede /* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */ 6854554c0a3aSHans de Goede /* TDLS_P_OFF_CH : periodically go to off channel */ 6855554c0a3aSHans de Goede /* TDLS_P_BASE_CH : periodically go back to base channel */ 6856554c0a3aSHans de Goede /* TDLS_RS_RCR : restore RCR */ 6857554c0a3aSHans de Goede /* TDLS_TEAR_STA : free tdls sta */ 6858554c0a3aSHans de Goede u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf) 6859554c0a3aSHans de Goede { 6860554c0a3aSHans de Goede return H2C_REJECTED; 6861554c0a3aSHans de Goede } 6862554c0a3aSHans de Goede 6863554c0a3aSHans de Goede u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf) 6864554c0a3aSHans de Goede { 6865554c0a3aSHans de Goede struct RunInThread_param *p; 6866554c0a3aSHans de Goede 6867554c0a3aSHans de Goede 6868554c0a3aSHans de Goede if (NULL == pbuf) 6869554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6870554c0a3aSHans de Goede p = (struct RunInThread_param *)pbuf; 6871554c0a3aSHans de Goede 6872554c0a3aSHans de Goede if (p->func) 6873554c0a3aSHans de Goede p->func(p->context); 6874554c0a3aSHans de Goede 6875554c0a3aSHans de Goede return H2C_SUCCESS; 6876554c0a3aSHans de Goede } 6877