1*f79cbc77SKalle Valo // SPDX-License-Identifier: GPL-2.0-only 2*f79cbc77SKalle Valo /* 3*f79cbc77SKalle Valo * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211 4*f79cbc77SKalle Valo * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 5*f79cbc77SKalle Valo * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com> 6*f79cbc77SKalle Valo * Copyright (c) 2016 - 2017 Intel Deutschland GmbH 7*f79cbc77SKalle Valo * Copyright (C) 2018 - 2022 Intel Corporation 8*f79cbc77SKalle Valo */ 9*f79cbc77SKalle Valo 10*f79cbc77SKalle Valo /* 11*f79cbc77SKalle Valo * TODO: 12*f79cbc77SKalle Valo * - Add TSF sync and fix IBSS beacon transmission by adding 13*f79cbc77SKalle Valo * competition for "air time" at TBTT 14*f79cbc77SKalle Valo * - RX filtering based on filter configuration (data->rx_filter) 15*f79cbc77SKalle Valo */ 16*f79cbc77SKalle Valo 17*f79cbc77SKalle Valo #include <linux/list.h> 18*f79cbc77SKalle Valo #include <linux/slab.h> 19*f79cbc77SKalle Valo #include <linux/spinlock.h> 20*f79cbc77SKalle Valo #include <net/dst.h> 21*f79cbc77SKalle Valo #include <net/xfrm.h> 22*f79cbc77SKalle Valo #include <net/mac80211.h> 23*f79cbc77SKalle Valo #include <net/ieee80211_radiotap.h> 24*f79cbc77SKalle Valo #include <linux/if_arp.h> 25*f79cbc77SKalle Valo #include <linux/rtnetlink.h> 26*f79cbc77SKalle Valo #include <linux/etherdevice.h> 27*f79cbc77SKalle Valo #include <linux/platform_device.h> 28*f79cbc77SKalle Valo #include <linux/debugfs.h> 29*f79cbc77SKalle Valo #include <linux/module.h> 30*f79cbc77SKalle Valo #include <linux/ktime.h> 31*f79cbc77SKalle Valo #include <net/genetlink.h> 32*f79cbc77SKalle Valo #include <net/net_namespace.h> 33*f79cbc77SKalle Valo #include <net/netns/generic.h> 34*f79cbc77SKalle Valo #include <linux/rhashtable.h> 35*f79cbc77SKalle Valo #include <linux/nospec.h> 36*f79cbc77SKalle Valo #include <linux/virtio.h> 37*f79cbc77SKalle Valo #include <linux/virtio_ids.h> 38*f79cbc77SKalle Valo #include <linux/virtio_config.h> 39*f79cbc77SKalle Valo #include "mac80211_hwsim.h" 40*f79cbc77SKalle Valo 41*f79cbc77SKalle Valo #define WARN_QUEUE 100 42*f79cbc77SKalle Valo #define MAX_QUEUE 200 43*f79cbc77SKalle Valo 44*f79cbc77SKalle Valo MODULE_AUTHOR("Jouni Malinen"); 45*f79cbc77SKalle Valo MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); 46*f79cbc77SKalle Valo MODULE_LICENSE("GPL"); 47*f79cbc77SKalle Valo 48*f79cbc77SKalle Valo static int radios = 2; 49*f79cbc77SKalle Valo module_param(radios, int, 0444); 50*f79cbc77SKalle Valo MODULE_PARM_DESC(radios, "Number of simulated radios"); 51*f79cbc77SKalle Valo 52*f79cbc77SKalle Valo static int channels = 1; 53*f79cbc77SKalle Valo module_param(channels, int, 0444); 54*f79cbc77SKalle Valo MODULE_PARM_DESC(channels, "Number of concurrent channels"); 55*f79cbc77SKalle Valo 56*f79cbc77SKalle Valo static bool paged_rx = false; 57*f79cbc77SKalle Valo module_param(paged_rx, bool, 0644); 58*f79cbc77SKalle Valo MODULE_PARM_DESC(paged_rx, "Use paged SKBs for RX instead of linear ones"); 59*f79cbc77SKalle Valo 60*f79cbc77SKalle Valo static bool rctbl = false; 61*f79cbc77SKalle Valo module_param(rctbl, bool, 0444); 62*f79cbc77SKalle Valo MODULE_PARM_DESC(rctbl, "Handle rate control table"); 63*f79cbc77SKalle Valo 64*f79cbc77SKalle Valo static bool support_p2p_device = true; 65*f79cbc77SKalle Valo module_param(support_p2p_device, bool, 0444); 66*f79cbc77SKalle Valo MODULE_PARM_DESC(support_p2p_device, "Support P2P-Device interface type"); 67*f79cbc77SKalle Valo 68*f79cbc77SKalle Valo static bool mlo; 69*f79cbc77SKalle Valo module_param(mlo, bool, 0444); 70*f79cbc77SKalle Valo MODULE_PARM_DESC(mlo, "Support MLO"); 71*f79cbc77SKalle Valo 72*f79cbc77SKalle Valo /** 73*f79cbc77SKalle Valo * enum hwsim_regtest - the type of regulatory tests we offer 74*f79cbc77SKalle Valo * 75*f79cbc77SKalle Valo * These are the different values you can use for the regtest 76*f79cbc77SKalle Valo * module parameter. This is useful to help test world roaming 77*f79cbc77SKalle Valo * and the driver regulatory_hint() call and combinations of these. 78*f79cbc77SKalle Valo * If you want to do specific alpha2 regulatory domain tests simply 79*f79cbc77SKalle Valo * use the userspace regulatory request as that will be respected as 80*f79cbc77SKalle Valo * well without the need of this module parameter. This is designed 81*f79cbc77SKalle Valo * only for testing the driver regulatory request, world roaming 82*f79cbc77SKalle Valo * and all possible combinations. 83*f79cbc77SKalle Valo * 84*f79cbc77SKalle Valo * @HWSIM_REGTEST_DISABLED: No regulatory tests are performed, 85*f79cbc77SKalle Valo * this is the default value. 86*f79cbc77SKalle Valo * @HWSIM_REGTEST_DRIVER_REG_FOLLOW: Used for testing the driver regulatory 87*f79cbc77SKalle Valo * hint, only one driver regulatory hint will be sent as such the 88*f79cbc77SKalle Valo * secondary radios are expected to follow. 89*f79cbc77SKalle Valo * @HWSIM_REGTEST_DRIVER_REG_ALL: Used for testing the driver regulatory 90*f79cbc77SKalle Valo * request with all radios reporting the same regulatory domain. 91*f79cbc77SKalle Valo * @HWSIM_REGTEST_DIFF_COUNTRY: Used for testing the drivers calling 92*f79cbc77SKalle Valo * different regulatory domains requests. Expected behaviour is for 93*f79cbc77SKalle Valo * an intersection to occur but each device will still use their 94*f79cbc77SKalle Valo * respective regulatory requested domains. Subsequent radios will 95*f79cbc77SKalle Valo * use the resulting intersection. 96*f79cbc77SKalle Valo * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We accomplish 97*f79cbc77SKalle Valo * this by using a custom beacon-capable regulatory domain for the first 98*f79cbc77SKalle Valo * radio. All other device world roam. 99*f79cbc77SKalle Valo * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory 100*f79cbc77SKalle Valo * domain requests. All radios will adhere to this custom world regulatory 101*f79cbc77SKalle Valo * domain. 102*f79cbc77SKalle Valo * @HWSIM_REGTEST_CUSTOM_WORLD_2: Used for testing 2 custom world regulatory 103*f79cbc77SKalle Valo * domain requests. The first radio will adhere to the first custom world 104*f79cbc77SKalle Valo * regulatory domain, the second one to the second custom world regulatory 105*f79cbc77SKalle Valo * domain. All other devices will world roam. 106*f79cbc77SKalle Valo * @HWSIM_REGTEST_STRICT_FOLLOW: Used for testing strict regulatory domain 107*f79cbc77SKalle Valo * settings, only the first radio will send a regulatory domain request 108*f79cbc77SKalle Valo * and use strict settings. The rest of the radios are expected to follow. 109*f79cbc77SKalle Valo * @HWSIM_REGTEST_STRICT_ALL: Used for testing strict regulatory domain 110*f79cbc77SKalle Valo * settings. All radios will adhere to this. 111*f79cbc77SKalle Valo * @HWSIM_REGTEST_STRICT_AND_DRIVER_REG: Used for testing strict regulatory 112*f79cbc77SKalle Valo * domain settings, combined with secondary driver regulatory domain 113*f79cbc77SKalle Valo * settings. The first radio will get a strict regulatory domain setting 114*f79cbc77SKalle Valo * using the first driver regulatory request and the second radio will use 115*f79cbc77SKalle Valo * non-strict settings using the second driver regulatory request. All 116*f79cbc77SKalle Valo * other devices should follow the intersection created between the 117*f79cbc77SKalle Valo * first two. 118*f79cbc77SKalle Valo * @HWSIM_REGTEST_ALL: Used for testing every possible mix. You will need 119*f79cbc77SKalle Valo * at least 6 radios for a complete test. We will test in this order: 120*f79cbc77SKalle Valo * 1 - driver custom world regulatory domain 121*f79cbc77SKalle Valo * 2 - second custom world regulatory domain 122*f79cbc77SKalle Valo * 3 - first driver regulatory domain request 123*f79cbc77SKalle Valo * 4 - second driver regulatory domain request 124*f79cbc77SKalle Valo * 5 - strict regulatory domain settings using the third driver regulatory 125*f79cbc77SKalle Valo * domain request 126*f79cbc77SKalle Valo * 6 and on - should follow the intersection of the 3rd, 4rth and 5th radio 127*f79cbc77SKalle Valo * regulatory requests. 128*f79cbc77SKalle Valo */ 129*f79cbc77SKalle Valo enum hwsim_regtest { 130*f79cbc77SKalle Valo HWSIM_REGTEST_DISABLED = 0, 131*f79cbc77SKalle Valo HWSIM_REGTEST_DRIVER_REG_FOLLOW = 1, 132*f79cbc77SKalle Valo HWSIM_REGTEST_DRIVER_REG_ALL = 2, 133*f79cbc77SKalle Valo HWSIM_REGTEST_DIFF_COUNTRY = 3, 134*f79cbc77SKalle Valo HWSIM_REGTEST_WORLD_ROAM = 4, 135*f79cbc77SKalle Valo HWSIM_REGTEST_CUSTOM_WORLD = 5, 136*f79cbc77SKalle Valo HWSIM_REGTEST_CUSTOM_WORLD_2 = 6, 137*f79cbc77SKalle Valo HWSIM_REGTEST_STRICT_FOLLOW = 7, 138*f79cbc77SKalle Valo HWSIM_REGTEST_STRICT_ALL = 8, 139*f79cbc77SKalle Valo HWSIM_REGTEST_STRICT_AND_DRIVER_REG = 9, 140*f79cbc77SKalle Valo HWSIM_REGTEST_ALL = 10, 141*f79cbc77SKalle Valo }; 142*f79cbc77SKalle Valo 143*f79cbc77SKalle Valo /* Set to one of the HWSIM_REGTEST_* values above */ 144*f79cbc77SKalle Valo static int regtest = HWSIM_REGTEST_DISABLED; 145*f79cbc77SKalle Valo module_param(regtest, int, 0444); 146*f79cbc77SKalle Valo MODULE_PARM_DESC(regtest, "The type of regulatory test we want to run"); 147*f79cbc77SKalle Valo 148*f79cbc77SKalle Valo static const char *hwsim_alpha2s[] = { 149*f79cbc77SKalle Valo "FI", 150*f79cbc77SKalle Valo "AL", 151*f79cbc77SKalle Valo "US", 152*f79cbc77SKalle Valo "DE", 153*f79cbc77SKalle Valo "JP", 154*f79cbc77SKalle Valo "AL", 155*f79cbc77SKalle Valo }; 156*f79cbc77SKalle Valo 157*f79cbc77SKalle Valo static const struct ieee80211_regdomain hwsim_world_regdom_custom_01 = { 158*f79cbc77SKalle Valo .n_reg_rules = 5, 159*f79cbc77SKalle Valo .alpha2 = "99", 160*f79cbc77SKalle Valo .reg_rules = { 161*f79cbc77SKalle Valo REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), 162*f79cbc77SKalle Valo REG_RULE(2484-10, 2484+10, 40, 0, 20, 0), 163*f79cbc77SKalle Valo REG_RULE(5150-10, 5240+10, 40, 0, 30, 0), 164*f79cbc77SKalle Valo REG_RULE(5745-10, 5825+10, 40, 0, 30, 0), 165*f79cbc77SKalle Valo REG_RULE(5855-10, 5925+10, 40, 0, 33, 0), 166*f79cbc77SKalle Valo } 167*f79cbc77SKalle Valo }; 168*f79cbc77SKalle Valo 169*f79cbc77SKalle Valo static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { 170*f79cbc77SKalle Valo .n_reg_rules = 3, 171*f79cbc77SKalle Valo .alpha2 = "99", 172*f79cbc77SKalle Valo .reg_rules = { 173*f79cbc77SKalle Valo REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), 174*f79cbc77SKalle Valo REG_RULE(5725-10, 5850+10, 40, 0, 30, 175*f79cbc77SKalle Valo NL80211_RRF_NO_IR), 176*f79cbc77SKalle Valo REG_RULE(5855-10, 5925+10, 40, 0, 33, 0), 177*f79cbc77SKalle Valo } 178*f79cbc77SKalle Valo }; 179*f79cbc77SKalle Valo 180*f79cbc77SKalle Valo static const struct ieee80211_regdomain hwsim_world_regdom_custom_03 = { 181*f79cbc77SKalle Valo .n_reg_rules = 6, 182*f79cbc77SKalle Valo .alpha2 = "99", 183*f79cbc77SKalle Valo .reg_rules = { 184*f79cbc77SKalle Valo REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0), 185*f79cbc77SKalle Valo REG_RULE(2484 - 10, 2484 + 10, 40, 0, 20, 0), 186*f79cbc77SKalle Valo REG_RULE(5150 - 10, 5240 + 10, 40, 0, 30, 0), 187*f79cbc77SKalle Valo REG_RULE(5745 - 10, 5825 + 10, 40, 0, 30, 0), 188*f79cbc77SKalle Valo REG_RULE(5855 - 10, 5925 + 10, 40, 0, 33, 0), 189*f79cbc77SKalle Valo REG_RULE(5955 - 10, 7125 + 10, 320, 0, 33, 0), 190*f79cbc77SKalle Valo } 191*f79cbc77SKalle Valo }; 192*f79cbc77SKalle Valo 193*f79cbc77SKalle Valo static const struct ieee80211_regdomain *hwsim_world_regdom_custom[] = { 194*f79cbc77SKalle Valo &hwsim_world_regdom_custom_01, 195*f79cbc77SKalle Valo &hwsim_world_regdom_custom_02, 196*f79cbc77SKalle Valo &hwsim_world_regdom_custom_03, 197*f79cbc77SKalle Valo }; 198*f79cbc77SKalle Valo 199*f79cbc77SKalle Valo struct hwsim_vif_priv { 200*f79cbc77SKalle Valo u32 magic; 201*f79cbc77SKalle Valo u8 bssid[ETH_ALEN]; 202*f79cbc77SKalle Valo bool assoc; 203*f79cbc77SKalle Valo bool bcn_en; 204*f79cbc77SKalle Valo u16 aid; 205*f79cbc77SKalle Valo }; 206*f79cbc77SKalle Valo 207*f79cbc77SKalle Valo #define HWSIM_VIF_MAGIC 0x69537748 208*f79cbc77SKalle Valo 209*f79cbc77SKalle Valo static inline void hwsim_check_magic(struct ieee80211_vif *vif) 210*f79cbc77SKalle Valo { 211*f79cbc77SKalle Valo struct hwsim_vif_priv *vp = (void *)vif->drv_priv; 212*f79cbc77SKalle Valo WARN(vp->magic != HWSIM_VIF_MAGIC, 213*f79cbc77SKalle Valo "Invalid VIF (%p) magic %#x, %pM, %d/%d\n", 214*f79cbc77SKalle Valo vif, vp->magic, vif->addr, vif->type, vif->p2p); 215*f79cbc77SKalle Valo } 216*f79cbc77SKalle Valo 217*f79cbc77SKalle Valo static inline void hwsim_set_magic(struct ieee80211_vif *vif) 218*f79cbc77SKalle Valo { 219*f79cbc77SKalle Valo struct hwsim_vif_priv *vp = (void *)vif->drv_priv; 220*f79cbc77SKalle Valo vp->magic = HWSIM_VIF_MAGIC; 221*f79cbc77SKalle Valo } 222*f79cbc77SKalle Valo 223*f79cbc77SKalle Valo static inline void hwsim_clear_magic(struct ieee80211_vif *vif) 224*f79cbc77SKalle Valo { 225*f79cbc77SKalle Valo struct hwsim_vif_priv *vp = (void *)vif->drv_priv; 226*f79cbc77SKalle Valo vp->magic = 0; 227*f79cbc77SKalle Valo } 228*f79cbc77SKalle Valo 229*f79cbc77SKalle Valo struct hwsim_sta_priv { 230*f79cbc77SKalle Valo u32 magic; 231*f79cbc77SKalle Valo unsigned int last_link; 232*f79cbc77SKalle Valo u16 active_links_rx; 233*f79cbc77SKalle Valo }; 234*f79cbc77SKalle Valo 235*f79cbc77SKalle Valo #define HWSIM_STA_MAGIC 0x6d537749 236*f79cbc77SKalle Valo 237*f79cbc77SKalle Valo static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta) 238*f79cbc77SKalle Valo { 239*f79cbc77SKalle Valo struct hwsim_sta_priv *sp = (void *)sta->drv_priv; 240*f79cbc77SKalle Valo WARN_ON(sp->magic != HWSIM_STA_MAGIC); 241*f79cbc77SKalle Valo } 242*f79cbc77SKalle Valo 243*f79cbc77SKalle Valo static inline void hwsim_set_sta_magic(struct ieee80211_sta *sta) 244*f79cbc77SKalle Valo { 245*f79cbc77SKalle Valo struct hwsim_sta_priv *sp = (void *)sta->drv_priv; 246*f79cbc77SKalle Valo sp->magic = HWSIM_STA_MAGIC; 247*f79cbc77SKalle Valo } 248*f79cbc77SKalle Valo 249*f79cbc77SKalle Valo static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta) 250*f79cbc77SKalle Valo { 251*f79cbc77SKalle Valo struct hwsim_sta_priv *sp = (void *)sta->drv_priv; 252*f79cbc77SKalle Valo sp->magic = 0; 253*f79cbc77SKalle Valo } 254*f79cbc77SKalle Valo 255*f79cbc77SKalle Valo struct hwsim_chanctx_priv { 256*f79cbc77SKalle Valo u32 magic; 257*f79cbc77SKalle Valo }; 258*f79cbc77SKalle Valo 259*f79cbc77SKalle Valo #define HWSIM_CHANCTX_MAGIC 0x6d53774a 260*f79cbc77SKalle Valo 261*f79cbc77SKalle Valo static inline void hwsim_check_chanctx_magic(struct ieee80211_chanctx_conf *c) 262*f79cbc77SKalle Valo { 263*f79cbc77SKalle Valo struct hwsim_chanctx_priv *cp = (void *)c->drv_priv; 264*f79cbc77SKalle Valo WARN_ON(cp->magic != HWSIM_CHANCTX_MAGIC); 265*f79cbc77SKalle Valo } 266*f79cbc77SKalle Valo 267*f79cbc77SKalle Valo static inline void hwsim_set_chanctx_magic(struct ieee80211_chanctx_conf *c) 268*f79cbc77SKalle Valo { 269*f79cbc77SKalle Valo struct hwsim_chanctx_priv *cp = (void *)c->drv_priv; 270*f79cbc77SKalle Valo cp->magic = HWSIM_CHANCTX_MAGIC; 271*f79cbc77SKalle Valo } 272*f79cbc77SKalle Valo 273*f79cbc77SKalle Valo static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c) 274*f79cbc77SKalle Valo { 275*f79cbc77SKalle Valo struct hwsim_chanctx_priv *cp = (void *)c->drv_priv; 276*f79cbc77SKalle Valo cp->magic = 0; 277*f79cbc77SKalle Valo } 278*f79cbc77SKalle Valo 279*f79cbc77SKalle Valo static unsigned int hwsim_net_id; 280*f79cbc77SKalle Valo 281*f79cbc77SKalle Valo static DEFINE_IDA(hwsim_netgroup_ida); 282*f79cbc77SKalle Valo 283*f79cbc77SKalle Valo struct hwsim_net { 284*f79cbc77SKalle Valo int netgroup; 285*f79cbc77SKalle Valo u32 wmediumd; 286*f79cbc77SKalle Valo }; 287*f79cbc77SKalle Valo 288*f79cbc77SKalle Valo static inline int hwsim_net_get_netgroup(struct net *net) 289*f79cbc77SKalle Valo { 290*f79cbc77SKalle Valo struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id); 291*f79cbc77SKalle Valo 292*f79cbc77SKalle Valo return hwsim_net->netgroup; 293*f79cbc77SKalle Valo } 294*f79cbc77SKalle Valo 295*f79cbc77SKalle Valo static inline int hwsim_net_set_netgroup(struct net *net) 296*f79cbc77SKalle Valo { 297*f79cbc77SKalle Valo struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id); 298*f79cbc77SKalle Valo 299*f79cbc77SKalle Valo hwsim_net->netgroup = ida_alloc(&hwsim_netgroup_ida, GFP_KERNEL); 300*f79cbc77SKalle Valo return hwsim_net->netgroup >= 0 ? 0 : -ENOMEM; 301*f79cbc77SKalle Valo } 302*f79cbc77SKalle Valo 303*f79cbc77SKalle Valo static inline u32 hwsim_net_get_wmediumd(struct net *net) 304*f79cbc77SKalle Valo { 305*f79cbc77SKalle Valo struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id); 306*f79cbc77SKalle Valo 307*f79cbc77SKalle Valo return hwsim_net->wmediumd; 308*f79cbc77SKalle Valo } 309*f79cbc77SKalle Valo 310*f79cbc77SKalle Valo static inline void hwsim_net_set_wmediumd(struct net *net, u32 portid) 311*f79cbc77SKalle Valo { 312*f79cbc77SKalle Valo struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id); 313*f79cbc77SKalle Valo 314*f79cbc77SKalle Valo hwsim_net->wmediumd = portid; 315*f79cbc77SKalle Valo } 316*f79cbc77SKalle Valo 317*f79cbc77SKalle Valo static struct class *hwsim_class; 318*f79cbc77SKalle Valo 319*f79cbc77SKalle Valo static struct net_device *hwsim_mon; /* global monitor netdev */ 320*f79cbc77SKalle Valo 321*f79cbc77SKalle Valo #define CHAN2G(_freq) { \ 322*f79cbc77SKalle Valo .band = NL80211_BAND_2GHZ, \ 323*f79cbc77SKalle Valo .center_freq = (_freq), \ 324*f79cbc77SKalle Valo .hw_value = (_freq), \ 325*f79cbc77SKalle Valo } 326*f79cbc77SKalle Valo 327*f79cbc77SKalle Valo #define CHAN5G(_freq) { \ 328*f79cbc77SKalle Valo .band = NL80211_BAND_5GHZ, \ 329*f79cbc77SKalle Valo .center_freq = (_freq), \ 330*f79cbc77SKalle Valo .hw_value = (_freq), \ 331*f79cbc77SKalle Valo } 332*f79cbc77SKalle Valo 333*f79cbc77SKalle Valo #define CHAN6G(_freq) { \ 334*f79cbc77SKalle Valo .band = NL80211_BAND_6GHZ, \ 335*f79cbc77SKalle Valo .center_freq = (_freq), \ 336*f79cbc77SKalle Valo .hw_value = (_freq), \ 337*f79cbc77SKalle Valo } 338*f79cbc77SKalle Valo 339*f79cbc77SKalle Valo static const struct ieee80211_channel hwsim_channels_2ghz[] = { 340*f79cbc77SKalle Valo CHAN2G(2412), /* Channel 1 */ 341*f79cbc77SKalle Valo CHAN2G(2417), /* Channel 2 */ 342*f79cbc77SKalle Valo CHAN2G(2422), /* Channel 3 */ 343*f79cbc77SKalle Valo CHAN2G(2427), /* Channel 4 */ 344*f79cbc77SKalle Valo CHAN2G(2432), /* Channel 5 */ 345*f79cbc77SKalle Valo CHAN2G(2437), /* Channel 6 */ 346*f79cbc77SKalle Valo CHAN2G(2442), /* Channel 7 */ 347*f79cbc77SKalle Valo CHAN2G(2447), /* Channel 8 */ 348*f79cbc77SKalle Valo CHAN2G(2452), /* Channel 9 */ 349*f79cbc77SKalle Valo CHAN2G(2457), /* Channel 10 */ 350*f79cbc77SKalle Valo CHAN2G(2462), /* Channel 11 */ 351*f79cbc77SKalle Valo CHAN2G(2467), /* Channel 12 */ 352*f79cbc77SKalle Valo CHAN2G(2472), /* Channel 13 */ 353*f79cbc77SKalle Valo CHAN2G(2484), /* Channel 14 */ 354*f79cbc77SKalle Valo }; 355*f79cbc77SKalle Valo 356*f79cbc77SKalle Valo static const struct ieee80211_channel hwsim_channels_5ghz[] = { 357*f79cbc77SKalle Valo CHAN5G(5180), /* Channel 36 */ 358*f79cbc77SKalle Valo CHAN5G(5200), /* Channel 40 */ 359*f79cbc77SKalle Valo CHAN5G(5220), /* Channel 44 */ 360*f79cbc77SKalle Valo CHAN5G(5240), /* Channel 48 */ 361*f79cbc77SKalle Valo 362*f79cbc77SKalle Valo CHAN5G(5260), /* Channel 52 */ 363*f79cbc77SKalle Valo CHAN5G(5280), /* Channel 56 */ 364*f79cbc77SKalle Valo CHAN5G(5300), /* Channel 60 */ 365*f79cbc77SKalle Valo CHAN5G(5320), /* Channel 64 */ 366*f79cbc77SKalle Valo 367*f79cbc77SKalle Valo CHAN5G(5500), /* Channel 100 */ 368*f79cbc77SKalle Valo CHAN5G(5520), /* Channel 104 */ 369*f79cbc77SKalle Valo CHAN5G(5540), /* Channel 108 */ 370*f79cbc77SKalle Valo CHAN5G(5560), /* Channel 112 */ 371*f79cbc77SKalle Valo CHAN5G(5580), /* Channel 116 */ 372*f79cbc77SKalle Valo CHAN5G(5600), /* Channel 120 */ 373*f79cbc77SKalle Valo CHAN5G(5620), /* Channel 124 */ 374*f79cbc77SKalle Valo CHAN5G(5640), /* Channel 128 */ 375*f79cbc77SKalle Valo CHAN5G(5660), /* Channel 132 */ 376*f79cbc77SKalle Valo CHAN5G(5680), /* Channel 136 */ 377*f79cbc77SKalle Valo CHAN5G(5700), /* Channel 140 */ 378*f79cbc77SKalle Valo 379*f79cbc77SKalle Valo CHAN5G(5745), /* Channel 149 */ 380*f79cbc77SKalle Valo CHAN5G(5765), /* Channel 153 */ 381*f79cbc77SKalle Valo CHAN5G(5785), /* Channel 157 */ 382*f79cbc77SKalle Valo CHAN5G(5805), /* Channel 161 */ 383*f79cbc77SKalle Valo CHAN5G(5825), /* Channel 165 */ 384*f79cbc77SKalle Valo CHAN5G(5845), /* Channel 169 */ 385*f79cbc77SKalle Valo 386*f79cbc77SKalle Valo CHAN5G(5855), /* Channel 171 */ 387*f79cbc77SKalle Valo CHAN5G(5860), /* Channel 172 */ 388*f79cbc77SKalle Valo CHAN5G(5865), /* Channel 173 */ 389*f79cbc77SKalle Valo CHAN5G(5870), /* Channel 174 */ 390*f79cbc77SKalle Valo 391*f79cbc77SKalle Valo CHAN5G(5875), /* Channel 175 */ 392*f79cbc77SKalle Valo CHAN5G(5880), /* Channel 176 */ 393*f79cbc77SKalle Valo CHAN5G(5885), /* Channel 177 */ 394*f79cbc77SKalle Valo CHAN5G(5890), /* Channel 178 */ 395*f79cbc77SKalle Valo CHAN5G(5895), /* Channel 179 */ 396*f79cbc77SKalle Valo CHAN5G(5900), /* Channel 180 */ 397*f79cbc77SKalle Valo CHAN5G(5905), /* Channel 181 */ 398*f79cbc77SKalle Valo 399*f79cbc77SKalle Valo CHAN5G(5910), /* Channel 182 */ 400*f79cbc77SKalle Valo CHAN5G(5915), /* Channel 183 */ 401*f79cbc77SKalle Valo CHAN5G(5920), /* Channel 184 */ 402*f79cbc77SKalle Valo CHAN5G(5925), /* Channel 185 */ 403*f79cbc77SKalle Valo }; 404*f79cbc77SKalle Valo 405*f79cbc77SKalle Valo static const struct ieee80211_channel hwsim_channels_6ghz[] = { 406*f79cbc77SKalle Valo CHAN6G(5955), /* Channel 1 */ 407*f79cbc77SKalle Valo CHAN6G(5975), /* Channel 5 */ 408*f79cbc77SKalle Valo CHAN6G(5995), /* Channel 9 */ 409*f79cbc77SKalle Valo CHAN6G(6015), /* Channel 13 */ 410*f79cbc77SKalle Valo CHAN6G(6035), /* Channel 17 */ 411*f79cbc77SKalle Valo CHAN6G(6055), /* Channel 21 */ 412*f79cbc77SKalle Valo CHAN6G(6075), /* Channel 25 */ 413*f79cbc77SKalle Valo CHAN6G(6095), /* Channel 29 */ 414*f79cbc77SKalle Valo CHAN6G(6115), /* Channel 33 */ 415*f79cbc77SKalle Valo CHAN6G(6135), /* Channel 37 */ 416*f79cbc77SKalle Valo CHAN6G(6155), /* Channel 41 */ 417*f79cbc77SKalle Valo CHAN6G(6175), /* Channel 45 */ 418*f79cbc77SKalle Valo CHAN6G(6195), /* Channel 49 */ 419*f79cbc77SKalle Valo CHAN6G(6215), /* Channel 53 */ 420*f79cbc77SKalle Valo CHAN6G(6235), /* Channel 57 */ 421*f79cbc77SKalle Valo CHAN6G(6255), /* Channel 61 */ 422*f79cbc77SKalle Valo CHAN6G(6275), /* Channel 65 */ 423*f79cbc77SKalle Valo CHAN6G(6295), /* Channel 69 */ 424*f79cbc77SKalle Valo CHAN6G(6315), /* Channel 73 */ 425*f79cbc77SKalle Valo CHAN6G(6335), /* Channel 77 */ 426*f79cbc77SKalle Valo CHAN6G(6355), /* Channel 81 */ 427*f79cbc77SKalle Valo CHAN6G(6375), /* Channel 85 */ 428*f79cbc77SKalle Valo CHAN6G(6395), /* Channel 89 */ 429*f79cbc77SKalle Valo CHAN6G(6415), /* Channel 93 */ 430*f79cbc77SKalle Valo CHAN6G(6435), /* Channel 97 */ 431*f79cbc77SKalle Valo CHAN6G(6455), /* Channel 181 */ 432*f79cbc77SKalle Valo CHAN6G(6475), /* Channel 105 */ 433*f79cbc77SKalle Valo CHAN6G(6495), /* Channel 109 */ 434*f79cbc77SKalle Valo CHAN6G(6515), /* Channel 113 */ 435*f79cbc77SKalle Valo CHAN6G(6535), /* Channel 117 */ 436*f79cbc77SKalle Valo CHAN6G(6555), /* Channel 121 */ 437*f79cbc77SKalle Valo CHAN6G(6575), /* Channel 125 */ 438*f79cbc77SKalle Valo CHAN6G(6595), /* Channel 129 */ 439*f79cbc77SKalle Valo CHAN6G(6615), /* Channel 133 */ 440*f79cbc77SKalle Valo CHAN6G(6635), /* Channel 137 */ 441*f79cbc77SKalle Valo CHAN6G(6655), /* Channel 141 */ 442*f79cbc77SKalle Valo CHAN6G(6675), /* Channel 145 */ 443*f79cbc77SKalle Valo CHAN6G(6695), /* Channel 149 */ 444*f79cbc77SKalle Valo CHAN6G(6715), /* Channel 153 */ 445*f79cbc77SKalle Valo CHAN6G(6735), /* Channel 157 */ 446*f79cbc77SKalle Valo CHAN6G(6755), /* Channel 161 */ 447*f79cbc77SKalle Valo CHAN6G(6775), /* Channel 165 */ 448*f79cbc77SKalle Valo CHAN6G(6795), /* Channel 169 */ 449*f79cbc77SKalle Valo CHAN6G(6815), /* Channel 173 */ 450*f79cbc77SKalle Valo CHAN6G(6835), /* Channel 177 */ 451*f79cbc77SKalle Valo CHAN6G(6855), /* Channel 181 */ 452*f79cbc77SKalle Valo CHAN6G(6875), /* Channel 185 */ 453*f79cbc77SKalle Valo CHAN6G(6895), /* Channel 189 */ 454*f79cbc77SKalle Valo CHAN6G(6915), /* Channel 193 */ 455*f79cbc77SKalle Valo CHAN6G(6935), /* Channel 197 */ 456*f79cbc77SKalle Valo CHAN6G(6955), /* Channel 201 */ 457*f79cbc77SKalle Valo CHAN6G(6975), /* Channel 205 */ 458*f79cbc77SKalle Valo CHAN6G(6995), /* Channel 209 */ 459*f79cbc77SKalle Valo CHAN6G(7015), /* Channel 213 */ 460*f79cbc77SKalle Valo CHAN6G(7035), /* Channel 217 */ 461*f79cbc77SKalle Valo CHAN6G(7055), /* Channel 221 */ 462*f79cbc77SKalle Valo CHAN6G(7075), /* Channel 225 */ 463*f79cbc77SKalle Valo CHAN6G(7095), /* Channel 229 */ 464*f79cbc77SKalle Valo CHAN6G(7115), /* Channel 233 */ 465*f79cbc77SKalle Valo }; 466*f79cbc77SKalle Valo 467*f79cbc77SKalle Valo #define NUM_S1G_CHANS_US 51 468*f79cbc77SKalle Valo static struct ieee80211_channel hwsim_channels_s1g[NUM_S1G_CHANS_US]; 469*f79cbc77SKalle Valo 470*f79cbc77SKalle Valo static const struct ieee80211_sta_s1g_cap hwsim_s1g_cap = { 471*f79cbc77SKalle Valo .s1g = true, 472*f79cbc77SKalle Valo .cap = { S1G_CAP0_SGI_1MHZ | S1G_CAP0_SGI_2MHZ, 473*f79cbc77SKalle Valo 0, 474*f79cbc77SKalle Valo 0, 475*f79cbc77SKalle Valo S1G_CAP3_MAX_MPDU_LEN, 476*f79cbc77SKalle Valo 0, 477*f79cbc77SKalle Valo S1G_CAP5_AMPDU, 478*f79cbc77SKalle Valo 0, 479*f79cbc77SKalle Valo S1G_CAP7_DUP_1MHZ, 480*f79cbc77SKalle Valo S1G_CAP8_TWT_RESPOND | S1G_CAP8_TWT_REQUEST, 481*f79cbc77SKalle Valo 0}, 482*f79cbc77SKalle Valo .nss_mcs = { 0xfc | 1, /* MCS 7 for 1 SS */ 483*f79cbc77SKalle Valo /* RX Highest Supported Long GI Data Rate 0:7 */ 484*f79cbc77SKalle Valo 0, 485*f79cbc77SKalle Valo /* RX Highest Supported Long GI Data Rate 0:7 */ 486*f79cbc77SKalle Valo /* TX S1G MCS Map 0:6 */ 487*f79cbc77SKalle Valo 0xfa, 488*f79cbc77SKalle Valo /* TX S1G MCS Map :7 */ 489*f79cbc77SKalle Valo /* TX Highest Supported Long GI Data Rate 0:6 */ 490*f79cbc77SKalle Valo 0x80, 491*f79cbc77SKalle Valo /* TX Highest Supported Long GI Data Rate 7:8 */ 492*f79cbc77SKalle Valo /* Rx Single spatial stream and S1G-MCS Map for 1MHz */ 493*f79cbc77SKalle Valo /* Tx Single spatial stream and S1G-MCS Map for 1MHz */ 494*f79cbc77SKalle Valo 0 }, 495*f79cbc77SKalle Valo }; 496*f79cbc77SKalle Valo 497*f79cbc77SKalle Valo static void hwsim_init_s1g_channels(struct ieee80211_channel *chans) 498*f79cbc77SKalle Valo { 499*f79cbc77SKalle Valo int ch, freq; 500*f79cbc77SKalle Valo 501*f79cbc77SKalle Valo for (ch = 0; ch < NUM_S1G_CHANS_US; ch++) { 502*f79cbc77SKalle Valo freq = 902000 + (ch + 1) * 500; 503*f79cbc77SKalle Valo chans[ch].band = NL80211_BAND_S1GHZ; 504*f79cbc77SKalle Valo chans[ch].center_freq = KHZ_TO_MHZ(freq); 505*f79cbc77SKalle Valo chans[ch].freq_offset = freq % 1000; 506*f79cbc77SKalle Valo chans[ch].hw_value = ch + 1; 507*f79cbc77SKalle Valo } 508*f79cbc77SKalle Valo } 509*f79cbc77SKalle Valo 510*f79cbc77SKalle Valo static const struct ieee80211_rate hwsim_rates[] = { 511*f79cbc77SKalle Valo { .bitrate = 10 }, 512*f79cbc77SKalle Valo { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 513*f79cbc77SKalle Valo { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 514*f79cbc77SKalle Valo { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, 515*f79cbc77SKalle Valo { .bitrate = 60 }, 516*f79cbc77SKalle Valo { .bitrate = 90 }, 517*f79cbc77SKalle Valo { .bitrate = 120 }, 518*f79cbc77SKalle Valo { .bitrate = 180 }, 519*f79cbc77SKalle Valo { .bitrate = 240 }, 520*f79cbc77SKalle Valo { .bitrate = 360 }, 521*f79cbc77SKalle Valo { .bitrate = 480 }, 522*f79cbc77SKalle Valo { .bitrate = 540 } 523*f79cbc77SKalle Valo }; 524*f79cbc77SKalle Valo 525*f79cbc77SKalle Valo #define DEFAULT_RX_RSSI -50 526*f79cbc77SKalle Valo 527*f79cbc77SKalle Valo static const u32 hwsim_ciphers[] = { 528*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_WEP40, 529*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_WEP104, 530*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_TKIP, 531*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_CCMP, 532*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_CCMP_256, 533*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_GCMP, 534*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_GCMP_256, 535*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_AES_CMAC, 536*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_BIP_CMAC_256, 537*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_BIP_GMAC_128, 538*f79cbc77SKalle Valo WLAN_CIPHER_SUITE_BIP_GMAC_256, 539*f79cbc77SKalle Valo }; 540*f79cbc77SKalle Valo 541*f79cbc77SKalle Valo #define OUI_QCA 0x001374 542*f79cbc77SKalle Valo #define QCA_NL80211_SUBCMD_TEST 1 543*f79cbc77SKalle Valo enum qca_nl80211_vendor_subcmds { 544*f79cbc77SKalle Valo QCA_WLAN_VENDOR_ATTR_TEST = 8, 545*f79cbc77SKalle Valo QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_TEST 546*f79cbc77SKalle Valo }; 547*f79cbc77SKalle Valo 548*f79cbc77SKalle Valo static const struct nla_policy 549*f79cbc77SKalle Valo hwsim_vendor_test_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = { 550*f79cbc77SKalle Valo [QCA_WLAN_VENDOR_ATTR_MAX] = { .type = NLA_U32 }, 551*f79cbc77SKalle Valo }; 552*f79cbc77SKalle Valo 553*f79cbc77SKalle Valo static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy, 554*f79cbc77SKalle Valo struct wireless_dev *wdev, 555*f79cbc77SKalle Valo const void *data, int data_len) 556*f79cbc77SKalle Valo { 557*f79cbc77SKalle Valo struct sk_buff *skb; 558*f79cbc77SKalle Valo struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1]; 559*f79cbc77SKalle Valo int err; 560*f79cbc77SKalle Valo u32 val; 561*f79cbc77SKalle Valo 562*f79cbc77SKalle Valo err = nla_parse_deprecated(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, 563*f79cbc77SKalle Valo data_len, hwsim_vendor_test_policy, NULL); 564*f79cbc77SKalle Valo if (err) 565*f79cbc77SKalle Valo return err; 566*f79cbc77SKalle Valo if (!tb[QCA_WLAN_VENDOR_ATTR_TEST]) 567*f79cbc77SKalle Valo return -EINVAL; 568*f79cbc77SKalle Valo val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_TEST]); 569*f79cbc77SKalle Valo wiphy_dbg(wiphy, "%s: test=%u\n", __func__, val); 570*f79cbc77SKalle Valo 571*f79cbc77SKalle Valo /* Send a vendor event as a test. Note that this would not normally be 572*f79cbc77SKalle Valo * done within a command handler, but rather, based on some other 573*f79cbc77SKalle Valo * trigger. For simplicity, this command is used to trigger the event 574*f79cbc77SKalle Valo * here. 575*f79cbc77SKalle Valo * 576*f79cbc77SKalle Valo * event_idx = 0 (index in mac80211_hwsim_vendor_commands) 577*f79cbc77SKalle Valo */ 578*f79cbc77SKalle Valo skb = cfg80211_vendor_event_alloc(wiphy, wdev, 100, 0, GFP_KERNEL); 579*f79cbc77SKalle Valo if (skb) { 580*f79cbc77SKalle Valo /* skb_put() or nla_put() will fill up data within 581*f79cbc77SKalle Valo * NL80211_ATTR_VENDOR_DATA. 582*f79cbc77SKalle Valo */ 583*f79cbc77SKalle Valo 584*f79cbc77SKalle Valo /* Add vendor data */ 585*f79cbc77SKalle Valo nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1); 586*f79cbc77SKalle Valo 587*f79cbc77SKalle Valo /* Send the event - this will call nla_nest_end() */ 588*f79cbc77SKalle Valo cfg80211_vendor_event(skb, GFP_KERNEL); 589*f79cbc77SKalle Valo } 590*f79cbc77SKalle Valo 591*f79cbc77SKalle Valo /* Send a response to the command */ 592*f79cbc77SKalle Valo skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 10); 593*f79cbc77SKalle Valo if (!skb) 594*f79cbc77SKalle Valo return -ENOMEM; 595*f79cbc77SKalle Valo 596*f79cbc77SKalle Valo /* skb_put() or nla_put() will fill up data within 597*f79cbc77SKalle Valo * NL80211_ATTR_VENDOR_DATA 598*f79cbc77SKalle Valo */ 599*f79cbc77SKalle Valo nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 2); 600*f79cbc77SKalle Valo 601*f79cbc77SKalle Valo return cfg80211_vendor_cmd_reply(skb); 602*f79cbc77SKalle Valo } 603*f79cbc77SKalle Valo 604*f79cbc77SKalle Valo static struct wiphy_vendor_command mac80211_hwsim_vendor_commands[] = { 605*f79cbc77SKalle Valo { 606*f79cbc77SKalle Valo .info = { .vendor_id = OUI_QCA, 607*f79cbc77SKalle Valo .subcmd = QCA_NL80211_SUBCMD_TEST }, 608*f79cbc77SKalle Valo .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, 609*f79cbc77SKalle Valo .doit = mac80211_hwsim_vendor_cmd_test, 610*f79cbc77SKalle Valo .policy = hwsim_vendor_test_policy, 611*f79cbc77SKalle Valo .maxattr = QCA_WLAN_VENDOR_ATTR_MAX, 612*f79cbc77SKalle Valo } 613*f79cbc77SKalle Valo }; 614*f79cbc77SKalle Valo 615*f79cbc77SKalle Valo /* Advertise support vendor specific events */ 616*f79cbc77SKalle Valo static const struct nl80211_vendor_cmd_info mac80211_hwsim_vendor_events[] = { 617*f79cbc77SKalle Valo { .vendor_id = OUI_QCA, .subcmd = 1 }, 618*f79cbc77SKalle Valo }; 619*f79cbc77SKalle Valo 620*f79cbc77SKalle Valo static DEFINE_SPINLOCK(hwsim_radio_lock); 621*f79cbc77SKalle Valo static LIST_HEAD(hwsim_radios); 622*f79cbc77SKalle Valo static struct rhashtable hwsim_radios_rht; 623*f79cbc77SKalle Valo static int hwsim_radio_idx; 624*f79cbc77SKalle Valo static int hwsim_radios_generation = 1; 625*f79cbc77SKalle Valo 626*f79cbc77SKalle Valo static struct platform_driver mac80211_hwsim_driver = { 627*f79cbc77SKalle Valo .driver = { 628*f79cbc77SKalle Valo .name = "mac80211_hwsim", 629*f79cbc77SKalle Valo }, 630*f79cbc77SKalle Valo }; 631*f79cbc77SKalle Valo 632*f79cbc77SKalle Valo struct mac80211_hwsim_link_data { 633*f79cbc77SKalle Valo u32 link_id; 634*f79cbc77SKalle Valo u64 beacon_int /* beacon interval in us */; 635*f79cbc77SKalle Valo struct hrtimer beacon_timer; 636*f79cbc77SKalle Valo }; 637*f79cbc77SKalle Valo 638*f79cbc77SKalle Valo struct mac80211_hwsim_data { 639*f79cbc77SKalle Valo struct list_head list; 640*f79cbc77SKalle Valo struct rhash_head rht; 641*f79cbc77SKalle Valo struct ieee80211_hw *hw; 642*f79cbc77SKalle Valo struct device *dev; 643*f79cbc77SKalle Valo struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; 644*f79cbc77SKalle Valo struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; 645*f79cbc77SKalle Valo struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; 646*f79cbc77SKalle Valo struct ieee80211_channel channels_6ghz[ARRAY_SIZE(hwsim_channels_6ghz)]; 647*f79cbc77SKalle Valo struct ieee80211_channel channels_s1g[ARRAY_SIZE(hwsim_channels_s1g)]; 648*f79cbc77SKalle Valo struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; 649*f79cbc77SKalle Valo struct ieee80211_iface_combination if_combination; 650*f79cbc77SKalle Valo struct ieee80211_iface_limit if_limits[3]; 651*f79cbc77SKalle Valo int n_if_limits; 652*f79cbc77SKalle Valo 653*f79cbc77SKalle Valo u32 ciphers[ARRAY_SIZE(hwsim_ciphers)]; 654*f79cbc77SKalle Valo 655*f79cbc77SKalle Valo struct mac_address addresses[2]; 656*f79cbc77SKalle Valo int channels, idx; 657*f79cbc77SKalle Valo bool use_chanctx; 658*f79cbc77SKalle Valo bool destroy_on_close; 659*f79cbc77SKalle Valo u32 portid; 660*f79cbc77SKalle Valo char alpha2[2]; 661*f79cbc77SKalle Valo const struct ieee80211_regdomain *regd; 662*f79cbc77SKalle Valo 663*f79cbc77SKalle Valo struct ieee80211_channel *tmp_chan; 664*f79cbc77SKalle Valo struct ieee80211_channel *roc_chan; 665*f79cbc77SKalle Valo u32 roc_duration; 666*f79cbc77SKalle Valo struct delayed_work roc_start; 667*f79cbc77SKalle Valo struct delayed_work roc_done; 668*f79cbc77SKalle Valo struct delayed_work hw_scan; 669*f79cbc77SKalle Valo struct cfg80211_scan_request *hw_scan_request; 670*f79cbc77SKalle Valo struct ieee80211_vif *hw_scan_vif; 671*f79cbc77SKalle Valo int scan_chan_idx; 672*f79cbc77SKalle Valo u8 scan_addr[ETH_ALEN]; 673*f79cbc77SKalle Valo struct { 674*f79cbc77SKalle Valo struct ieee80211_channel *channel; 675*f79cbc77SKalle Valo unsigned long next_start, start, end; 676*f79cbc77SKalle Valo } survey_data[ARRAY_SIZE(hwsim_channels_2ghz) + 677*f79cbc77SKalle Valo ARRAY_SIZE(hwsim_channels_5ghz) + 678*f79cbc77SKalle Valo ARRAY_SIZE(hwsim_channels_6ghz)]; 679*f79cbc77SKalle Valo 680*f79cbc77SKalle Valo struct ieee80211_channel *channel; 681*f79cbc77SKalle Valo enum nl80211_chan_width bw; 682*f79cbc77SKalle Valo unsigned int rx_filter; 683*f79cbc77SKalle Valo bool started, idle, scanning; 684*f79cbc77SKalle Valo struct mutex mutex; 685*f79cbc77SKalle Valo enum ps_mode { 686*f79cbc77SKalle Valo PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL 687*f79cbc77SKalle Valo } ps; 688*f79cbc77SKalle Valo bool ps_poll_pending; 689*f79cbc77SKalle Valo struct dentry *debugfs; 690*f79cbc77SKalle Valo 691*f79cbc77SKalle Valo atomic_t pending_cookie; 692*f79cbc77SKalle Valo struct sk_buff_head pending; /* packets pending */ 693*f79cbc77SKalle Valo /* 694*f79cbc77SKalle Valo * Only radios in the same group can communicate together (the 695*f79cbc77SKalle Valo * channel has to match too). Each bit represents a group. A 696*f79cbc77SKalle Valo * radio can be in more than one group. 697*f79cbc77SKalle Valo */ 698*f79cbc77SKalle Valo u64 group; 699*f79cbc77SKalle Valo 700*f79cbc77SKalle Valo /* group shared by radios created in the same netns */ 701*f79cbc77SKalle Valo int netgroup; 702*f79cbc77SKalle Valo /* wmediumd portid responsible for netgroup of this radio */ 703*f79cbc77SKalle Valo u32 wmediumd; 704*f79cbc77SKalle Valo 705*f79cbc77SKalle Valo /* difference between this hw's clock and the real clock, in usecs */ 706*f79cbc77SKalle Valo s64 tsf_offset; 707*f79cbc77SKalle Valo s64 bcn_delta; 708*f79cbc77SKalle Valo /* absolute beacon transmission time. Used to cover up "tx" delay. */ 709*f79cbc77SKalle Valo u64 abs_bcn_ts; 710*f79cbc77SKalle Valo 711*f79cbc77SKalle Valo /* Stats */ 712*f79cbc77SKalle Valo u64 tx_pkts; 713*f79cbc77SKalle Valo u64 rx_pkts; 714*f79cbc77SKalle Valo u64 tx_bytes; 715*f79cbc77SKalle Valo u64 rx_bytes; 716*f79cbc77SKalle Valo u64 tx_dropped; 717*f79cbc77SKalle Valo u64 tx_failed; 718*f79cbc77SKalle Valo 719*f79cbc77SKalle Valo /* RSSI in rx status of the receiver */ 720*f79cbc77SKalle Valo int rx_rssi; 721*f79cbc77SKalle Valo 722*f79cbc77SKalle Valo struct mac80211_hwsim_link_data link_data[IEEE80211_MLD_MAX_NUM_LINKS]; 723*f79cbc77SKalle Valo }; 724*f79cbc77SKalle Valo 725*f79cbc77SKalle Valo static const struct rhashtable_params hwsim_rht_params = { 726*f79cbc77SKalle Valo .nelem_hint = 2, 727*f79cbc77SKalle Valo .automatic_shrinking = true, 728*f79cbc77SKalle Valo .key_len = ETH_ALEN, 729*f79cbc77SKalle Valo .key_offset = offsetof(struct mac80211_hwsim_data, addresses[1]), 730*f79cbc77SKalle Valo .head_offset = offsetof(struct mac80211_hwsim_data, rht), 731*f79cbc77SKalle Valo }; 732*f79cbc77SKalle Valo 733*f79cbc77SKalle Valo struct hwsim_radiotap_hdr { 734*f79cbc77SKalle Valo struct ieee80211_radiotap_header hdr; 735*f79cbc77SKalle Valo __le64 rt_tsft; 736*f79cbc77SKalle Valo u8 rt_flags; 737*f79cbc77SKalle Valo u8 rt_rate; 738*f79cbc77SKalle Valo __le16 rt_channel; 739*f79cbc77SKalle Valo __le16 rt_chbitmask; 740*f79cbc77SKalle Valo } __packed; 741*f79cbc77SKalle Valo 742*f79cbc77SKalle Valo struct hwsim_radiotap_ack_hdr { 743*f79cbc77SKalle Valo struct ieee80211_radiotap_header hdr; 744*f79cbc77SKalle Valo u8 rt_flags; 745*f79cbc77SKalle Valo u8 pad; 746*f79cbc77SKalle Valo __le16 rt_channel; 747*f79cbc77SKalle Valo __le16 rt_chbitmask; 748*f79cbc77SKalle Valo } __packed; 749*f79cbc77SKalle Valo 750*f79cbc77SKalle Valo /* MAC80211_HWSIM netlink family */ 751*f79cbc77SKalle Valo static struct genl_family hwsim_genl_family; 752*f79cbc77SKalle Valo 753*f79cbc77SKalle Valo enum hwsim_multicast_groups { 754*f79cbc77SKalle Valo HWSIM_MCGRP_CONFIG, 755*f79cbc77SKalle Valo }; 756*f79cbc77SKalle Valo 757*f79cbc77SKalle Valo static const struct genl_multicast_group hwsim_mcgrps[] = { 758*f79cbc77SKalle Valo [HWSIM_MCGRP_CONFIG] = { .name = "config", }, 759*f79cbc77SKalle Valo }; 760*f79cbc77SKalle Valo 761*f79cbc77SKalle Valo /* MAC80211_HWSIM netlink policy */ 762*f79cbc77SKalle Valo 763*f79cbc77SKalle Valo static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { 764*f79cbc77SKalle Valo [HWSIM_ATTR_ADDR_RECEIVER] = NLA_POLICY_ETH_ADDR_COMPAT, 765*f79cbc77SKalle Valo [HWSIM_ATTR_ADDR_TRANSMITTER] = NLA_POLICY_ETH_ADDR_COMPAT, 766*f79cbc77SKalle Valo [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY, 767*f79cbc77SKalle Valo .len = IEEE80211_MAX_DATA_LEN }, 768*f79cbc77SKalle Valo [HWSIM_ATTR_FLAGS] = { .type = NLA_U32 }, 769*f79cbc77SKalle Valo [HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 }, 770*f79cbc77SKalle Valo [HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 }, 771*f79cbc77SKalle Valo [HWSIM_ATTR_TX_INFO] = { .type = NLA_BINARY, 772*f79cbc77SKalle Valo .len = IEEE80211_TX_MAX_RATES * 773*f79cbc77SKalle Valo sizeof(struct hwsim_tx_rate)}, 774*f79cbc77SKalle Valo [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, 775*f79cbc77SKalle Valo [HWSIM_ATTR_CHANNELS] = { .type = NLA_U32 }, 776*f79cbc77SKalle Valo [HWSIM_ATTR_RADIO_ID] = { .type = NLA_U32 }, 777*f79cbc77SKalle Valo [HWSIM_ATTR_REG_HINT_ALPHA2] = { .type = NLA_STRING, .len = 2 }, 778*f79cbc77SKalle Valo [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, 779*f79cbc77SKalle Valo [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, 780*f79cbc77SKalle Valo [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, 781*f79cbc77SKalle Valo [HWSIM_ATTR_USE_CHANCTX] = { .type = NLA_FLAG }, 782*f79cbc77SKalle Valo [HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG }, 783*f79cbc77SKalle Valo [HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING }, 784*f79cbc77SKalle Valo [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG }, 785*f79cbc77SKalle Valo [HWSIM_ATTR_FREQ] = { .type = NLA_U32 }, 786*f79cbc77SKalle Valo [HWSIM_ATTR_TX_INFO_FLAGS] = { .type = NLA_BINARY }, 787*f79cbc77SKalle Valo [HWSIM_ATTR_PERM_ADDR] = NLA_POLICY_ETH_ADDR_COMPAT, 788*f79cbc77SKalle Valo [HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 }, 789*f79cbc77SKalle Valo [HWSIM_ATTR_CIPHER_SUPPORT] = { .type = NLA_BINARY }, 790*f79cbc77SKalle Valo [HWSIM_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, 791*f79cbc77SKalle Valo }; 792*f79cbc77SKalle Valo 793*f79cbc77SKalle Valo #if IS_REACHABLE(CONFIG_VIRTIO) 794*f79cbc77SKalle Valo 795*f79cbc77SKalle Valo /* MAC80211_HWSIM virtio queues */ 796*f79cbc77SKalle Valo static struct virtqueue *hwsim_vqs[HWSIM_NUM_VQS]; 797*f79cbc77SKalle Valo static bool hwsim_virtio_enabled; 798*f79cbc77SKalle Valo static DEFINE_SPINLOCK(hwsim_virtio_lock); 799*f79cbc77SKalle Valo 800*f79cbc77SKalle Valo static void hwsim_virtio_rx_work(struct work_struct *work); 801*f79cbc77SKalle Valo static DECLARE_WORK(hwsim_virtio_rx, hwsim_virtio_rx_work); 802*f79cbc77SKalle Valo 803*f79cbc77SKalle Valo static int hwsim_tx_virtio(struct mac80211_hwsim_data *data, 804*f79cbc77SKalle Valo struct sk_buff *skb) 805*f79cbc77SKalle Valo { 806*f79cbc77SKalle Valo struct scatterlist sg[1]; 807*f79cbc77SKalle Valo unsigned long flags; 808*f79cbc77SKalle Valo int err; 809*f79cbc77SKalle Valo 810*f79cbc77SKalle Valo spin_lock_irqsave(&hwsim_virtio_lock, flags); 811*f79cbc77SKalle Valo if (!hwsim_virtio_enabled) { 812*f79cbc77SKalle Valo err = -ENODEV; 813*f79cbc77SKalle Valo goto out_free; 814*f79cbc77SKalle Valo } 815*f79cbc77SKalle Valo 816*f79cbc77SKalle Valo sg_init_one(sg, skb->head, skb_end_offset(skb)); 817*f79cbc77SKalle Valo err = virtqueue_add_outbuf(hwsim_vqs[HWSIM_VQ_TX], sg, 1, skb, 818*f79cbc77SKalle Valo GFP_ATOMIC); 819*f79cbc77SKalle Valo if (err) 820*f79cbc77SKalle Valo goto out_free; 821*f79cbc77SKalle Valo virtqueue_kick(hwsim_vqs[HWSIM_VQ_TX]); 822*f79cbc77SKalle Valo spin_unlock_irqrestore(&hwsim_virtio_lock, flags); 823*f79cbc77SKalle Valo return 0; 824*f79cbc77SKalle Valo 825*f79cbc77SKalle Valo out_free: 826*f79cbc77SKalle Valo spin_unlock_irqrestore(&hwsim_virtio_lock, flags); 827*f79cbc77SKalle Valo nlmsg_free(skb); 828*f79cbc77SKalle Valo return err; 829*f79cbc77SKalle Valo } 830*f79cbc77SKalle Valo #else 831*f79cbc77SKalle Valo /* cause a linker error if this ends up being needed */ 832*f79cbc77SKalle Valo extern int hwsim_tx_virtio(struct mac80211_hwsim_data *data, 833*f79cbc77SKalle Valo struct sk_buff *skb); 834*f79cbc77SKalle Valo #define hwsim_virtio_enabled false 835*f79cbc77SKalle Valo #endif 836*f79cbc77SKalle Valo 837*f79cbc77SKalle Valo static int hwsim_get_chanwidth(enum nl80211_chan_width bw) 838*f79cbc77SKalle Valo { 839*f79cbc77SKalle Valo switch (bw) { 840*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_20_NOHT: 841*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_20: 842*f79cbc77SKalle Valo return 20; 843*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_40: 844*f79cbc77SKalle Valo return 40; 845*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_80: 846*f79cbc77SKalle Valo return 80; 847*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_80P80: 848*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_160: 849*f79cbc77SKalle Valo return 160; 850*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_320: 851*f79cbc77SKalle Valo return 320; 852*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_5: 853*f79cbc77SKalle Valo return 5; 854*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_10: 855*f79cbc77SKalle Valo return 10; 856*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_1: 857*f79cbc77SKalle Valo return 1; 858*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_2: 859*f79cbc77SKalle Valo return 2; 860*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_4: 861*f79cbc77SKalle Valo return 4; 862*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_8: 863*f79cbc77SKalle Valo return 8; 864*f79cbc77SKalle Valo case NL80211_CHAN_WIDTH_16: 865*f79cbc77SKalle Valo return 16; 866*f79cbc77SKalle Valo } 867*f79cbc77SKalle Valo 868*f79cbc77SKalle Valo return INT_MAX; 869*f79cbc77SKalle Valo } 870*f79cbc77SKalle Valo 871*f79cbc77SKalle Valo static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, 872*f79cbc77SKalle Valo struct sk_buff *skb, 873*f79cbc77SKalle Valo struct ieee80211_channel *chan); 874*f79cbc77SKalle Valo 875*f79cbc77SKalle Valo /* sysfs attributes */ 876*f79cbc77SKalle Valo static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) 877*f79cbc77SKalle Valo { 878*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 879*f79cbc77SKalle Valo struct hwsim_vif_priv *vp = (void *)vif->drv_priv; 880*f79cbc77SKalle Valo struct sk_buff *skb; 881*f79cbc77SKalle Valo struct ieee80211_pspoll *pspoll; 882*f79cbc77SKalle Valo 883*f79cbc77SKalle Valo if (!vp->assoc) 884*f79cbc77SKalle Valo return; 885*f79cbc77SKalle Valo 886*f79cbc77SKalle Valo wiphy_dbg(data->hw->wiphy, 887*f79cbc77SKalle Valo "%s: send PS-Poll to %pM for aid %d\n", 888*f79cbc77SKalle Valo __func__, vp->bssid, vp->aid); 889*f79cbc77SKalle Valo 890*f79cbc77SKalle Valo skb = dev_alloc_skb(sizeof(*pspoll)); 891*f79cbc77SKalle Valo if (!skb) 892*f79cbc77SKalle Valo return; 893*f79cbc77SKalle Valo pspoll = skb_put(skb, sizeof(*pspoll)); 894*f79cbc77SKalle Valo pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | 895*f79cbc77SKalle Valo IEEE80211_STYPE_PSPOLL | 896*f79cbc77SKalle Valo IEEE80211_FCTL_PM); 897*f79cbc77SKalle Valo pspoll->aid = cpu_to_le16(0xc000 | vp->aid); 898*f79cbc77SKalle Valo memcpy(pspoll->bssid, vp->bssid, ETH_ALEN); 899*f79cbc77SKalle Valo memcpy(pspoll->ta, mac, ETH_ALEN); 900*f79cbc77SKalle Valo 901*f79cbc77SKalle Valo rcu_read_lock(); 902*f79cbc77SKalle Valo mac80211_hwsim_tx_frame(data->hw, skb, 903*f79cbc77SKalle Valo rcu_dereference(vif->bss_conf.chanctx_conf)->def.chan); 904*f79cbc77SKalle Valo rcu_read_unlock(); 905*f79cbc77SKalle Valo } 906*f79cbc77SKalle Valo 907*f79cbc77SKalle Valo static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, 908*f79cbc77SKalle Valo struct ieee80211_vif *vif, int ps) 909*f79cbc77SKalle Valo { 910*f79cbc77SKalle Valo struct hwsim_vif_priv *vp = (void *)vif->drv_priv; 911*f79cbc77SKalle Valo struct sk_buff *skb; 912*f79cbc77SKalle Valo struct ieee80211_hdr *hdr; 913*f79cbc77SKalle Valo struct ieee80211_tx_info *cb; 914*f79cbc77SKalle Valo 915*f79cbc77SKalle Valo if (!vp->assoc) 916*f79cbc77SKalle Valo return; 917*f79cbc77SKalle Valo 918*f79cbc77SKalle Valo wiphy_dbg(data->hw->wiphy, 919*f79cbc77SKalle Valo "%s: send data::nullfunc to %pM ps=%d\n", 920*f79cbc77SKalle Valo __func__, vp->bssid, ps); 921*f79cbc77SKalle Valo 922*f79cbc77SKalle Valo skb = dev_alloc_skb(sizeof(*hdr)); 923*f79cbc77SKalle Valo if (!skb) 924*f79cbc77SKalle Valo return; 925*f79cbc77SKalle Valo hdr = skb_put(skb, sizeof(*hdr) - ETH_ALEN); 926*f79cbc77SKalle Valo hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | 927*f79cbc77SKalle Valo IEEE80211_STYPE_NULLFUNC | 928*f79cbc77SKalle Valo IEEE80211_FCTL_TODS | 929*f79cbc77SKalle Valo (ps ? IEEE80211_FCTL_PM : 0)); 930*f79cbc77SKalle Valo hdr->duration_id = cpu_to_le16(0); 931*f79cbc77SKalle Valo memcpy(hdr->addr1, vp->bssid, ETH_ALEN); 932*f79cbc77SKalle Valo memcpy(hdr->addr2, mac, ETH_ALEN); 933*f79cbc77SKalle Valo memcpy(hdr->addr3, vp->bssid, ETH_ALEN); 934*f79cbc77SKalle Valo 935*f79cbc77SKalle Valo cb = IEEE80211_SKB_CB(skb); 936*f79cbc77SKalle Valo cb->control.rates[0].count = 1; 937*f79cbc77SKalle Valo cb->control.rates[1].idx = -1; 938*f79cbc77SKalle Valo 939*f79cbc77SKalle Valo rcu_read_lock(); 940*f79cbc77SKalle Valo mac80211_hwsim_tx_frame(data->hw, skb, 941*f79cbc77SKalle Valo rcu_dereference(vif->bss_conf.chanctx_conf)->def.chan); 942*f79cbc77SKalle Valo rcu_read_unlock(); 943*f79cbc77SKalle Valo } 944*f79cbc77SKalle Valo 945*f79cbc77SKalle Valo 946*f79cbc77SKalle Valo static void hwsim_send_nullfunc_ps(void *dat, u8 *mac, 947*f79cbc77SKalle Valo struct ieee80211_vif *vif) 948*f79cbc77SKalle Valo { 949*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 950*f79cbc77SKalle Valo hwsim_send_nullfunc(data, mac, vif, 1); 951*f79cbc77SKalle Valo } 952*f79cbc77SKalle Valo 953*f79cbc77SKalle Valo static void hwsim_send_nullfunc_no_ps(void *dat, u8 *mac, 954*f79cbc77SKalle Valo struct ieee80211_vif *vif) 955*f79cbc77SKalle Valo { 956*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 957*f79cbc77SKalle Valo hwsim_send_nullfunc(data, mac, vif, 0); 958*f79cbc77SKalle Valo } 959*f79cbc77SKalle Valo 960*f79cbc77SKalle Valo static int hwsim_fops_ps_read(void *dat, u64 *val) 961*f79cbc77SKalle Valo { 962*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 963*f79cbc77SKalle Valo *val = data->ps; 964*f79cbc77SKalle Valo return 0; 965*f79cbc77SKalle Valo } 966*f79cbc77SKalle Valo 967*f79cbc77SKalle Valo static int hwsim_fops_ps_write(void *dat, u64 val) 968*f79cbc77SKalle Valo { 969*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 970*f79cbc77SKalle Valo enum ps_mode old_ps; 971*f79cbc77SKalle Valo 972*f79cbc77SKalle Valo if (val != PS_DISABLED && val != PS_ENABLED && val != PS_AUTO_POLL && 973*f79cbc77SKalle Valo val != PS_MANUAL_POLL) 974*f79cbc77SKalle Valo return -EINVAL; 975*f79cbc77SKalle Valo 976*f79cbc77SKalle Valo if (val == PS_MANUAL_POLL) { 977*f79cbc77SKalle Valo if (data->ps != PS_ENABLED) 978*f79cbc77SKalle Valo return -EINVAL; 979*f79cbc77SKalle Valo local_bh_disable(); 980*f79cbc77SKalle Valo ieee80211_iterate_active_interfaces_atomic( 981*f79cbc77SKalle Valo data->hw, IEEE80211_IFACE_ITER_NORMAL, 982*f79cbc77SKalle Valo hwsim_send_ps_poll, data); 983*f79cbc77SKalle Valo local_bh_enable(); 984*f79cbc77SKalle Valo return 0; 985*f79cbc77SKalle Valo } 986*f79cbc77SKalle Valo old_ps = data->ps; 987*f79cbc77SKalle Valo data->ps = val; 988*f79cbc77SKalle Valo 989*f79cbc77SKalle Valo local_bh_disable(); 990*f79cbc77SKalle Valo if (old_ps == PS_DISABLED && val != PS_DISABLED) { 991*f79cbc77SKalle Valo ieee80211_iterate_active_interfaces_atomic( 992*f79cbc77SKalle Valo data->hw, IEEE80211_IFACE_ITER_NORMAL, 993*f79cbc77SKalle Valo hwsim_send_nullfunc_ps, data); 994*f79cbc77SKalle Valo } else if (old_ps != PS_DISABLED && val == PS_DISABLED) { 995*f79cbc77SKalle Valo ieee80211_iterate_active_interfaces_atomic( 996*f79cbc77SKalle Valo data->hw, IEEE80211_IFACE_ITER_NORMAL, 997*f79cbc77SKalle Valo hwsim_send_nullfunc_no_ps, data); 998*f79cbc77SKalle Valo } 999*f79cbc77SKalle Valo local_bh_enable(); 1000*f79cbc77SKalle Valo 1001*f79cbc77SKalle Valo return 0; 1002*f79cbc77SKalle Valo } 1003*f79cbc77SKalle Valo 1004*f79cbc77SKalle Valo DEFINE_DEBUGFS_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, 1005*f79cbc77SKalle Valo "%llu\n"); 1006*f79cbc77SKalle Valo 1007*f79cbc77SKalle Valo static int hwsim_write_simulate_radar(void *dat, u64 val) 1008*f79cbc77SKalle Valo { 1009*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 1010*f79cbc77SKalle Valo 1011*f79cbc77SKalle Valo ieee80211_radar_detected(data->hw); 1012*f79cbc77SKalle Valo 1013*f79cbc77SKalle Valo return 0; 1014*f79cbc77SKalle Valo } 1015*f79cbc77SKalle Valo 1016*f79cbc77SKalle Valo DEFINE_DEBUGFS_ATTRIBUTE(hwsim_simulate_radar, NULL, 1017*f79cbc77SKalle Valo hwsim_write_simulate_radar, "%llu\n"); 1018*f79cbc77SKalle Valo 1019*f79cbc77SKalle Valo static int hwsim_fops_group_read(void *dat, u64 *val) 1020*f79cbc77SKalle Valo { 1021*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 1022*f79cbc77SKalle Valo *val = data->group; 1023*f79cbc77SKalle Valo return 0; 1024*f79cbc77SKalle Valo } 1025*f79cbc77SKalle Valo 1026*f79cbc77SKalle Valo static int hwsim_fops_group_write(void *dat, u64 val) 1027*f79cbc77SKalle Valo { 1028*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 1029*f79cbc77SKalle Valo data->group = val; 1030*f79cbc77SKalle Valo return 0; 1031*f79cbc77SKalle Valo } 1032*f79cbc77SKalle Valo 1033*f79cbc77SKalle Valo DEFINE_DEBUGFS_ATTRIBUTE(hwsim_fops_group, 1034*f79cbc77SKalle Valo hwsim_fops_group_read, hwsim_fops_group_write, 1035*f79cbc77SKalle Valo "%llx\n"); 1036*f79cbc77SKalle Valo 1037*f79cbc77SKalle Valo static int hwsim_fops_rx_rssi_read(void *dat, u64 *val) 1038*f79cbc77SKalle Valo { 1039*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 1040*f79cbc77SKalle Valo *val = data->rx_rssi; 1041*f79cbc77SKalle Valo return 0; 1042*f79cbc77SKalle Valo } 1043*f79cbc77SKalle Valo 1044*f79cbc77SKalle Valo static int hwsim_fops_rx_rssi_write(void *dat, u64 val) 1045*f79cbc77SKalle Valo { 1046*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = dat; 1047*f79cbc77SKalle Valo int rssi = (int)val; 1048*f79cbc77SKalle Valo 1049*f79cbc77SKalle Valo if (rssi >= 0 || rssi < -100) 1050*f79cbc77SKalle Valo return -EINVAL; 1051*f79cbc77SKalle Valo 1052*f79cbc77SKalle Valo data->rx_rssi = rssi; 1053*f79cbc77SKalle Valo return 0; 1054*f79cbc77SKalle Valo } 1055*f79cbc77SKalle Valo 1056*f79cbc77SKalle Valo DEFINE_DEBUGFS_ATTRIBUTE(hwsim_fops_rx_rssi, 1057*f79cbc77SKalle Valo hwsim_fops_rx_rssi_read, hwsim_fops_rx_rssi_write, 1058*f79cbc77SKalle Valo "%lld\n"); 1059*f79cbc77SKalle Valo 1060*f79cbc77SKalle Valo static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, 1061*f79cbc77SKalle Valo struct net_device *dev) 1062*f79cbc77SKalle Valo { 1063*f79cbc77SKalle Valo /* TODO: allow packet injection */ 1064*f79cbc77SKalle Valo dev_kfree_skb(skb); 1065*f79cbc77SKalle Valo return NETDEV_TX_OK; 1066*f79cbc77SKalle Valo } 1067*f79cbc77SKalle Valo 1068*f79cbc77SKalle Valo static inline u64 mac80211_hwsim_get_tsf_raw(void) 1069*f79cbc77SKalle Valo { 1070*f79cbc77SKalle Valo return ktime_to_us(ktime_get_real()); 1071*f79cbc77SKalle Valo } 1072*f79cbc77SKalle Valo 1073*f79cbc77SKalle Valo static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) 1074*f79cbc77SKalle Valo { 1075*f79cbc77SKalle Valo u64 now = mac80211_hwsim_get_tsf_raw(); 1076*f79cbc77SKalle Valo return cpu_to_le64(now + data->tsf_offset); 1077*f79cbc77SKalle Valo } 1078*f79cbc77SKalle Valo 1079*f79cbc77SKalle Valo static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, 1080*f79cbc77SKalle Valo struct ieee80211_vif *vif) 1081*f79cbc77SKalle Valo { 1082*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 1083*f79cbc77SKalle Valo return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); 1084*f79cbc77SKalle Valo } 1085*f79cbc77SKalle Valo 1086*f79cbc77SKalle Valo static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, 1087*f79cbc77SKalle Valo struct ieee80211_vif *vif, u64 tsf) 1088*f79cbc77SKalle Valo { 1089*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 1090*f79cbc77SKalle Valo u64 now = mac80211_hwsim_get_tsf(hw, vif); 1091*f79cbc77SKalle Valo /* MLD not supported here */ 1092*f79cbc77SKalle Valo u32 bcn_int = data->link_data[0].beacon_int; 1093*f79cbc77SKalle Valo u64 delta = abs(tsf - now); 1094*f79cbc77SKalle Valo 1095*f79cbc77SKalle Valo /* adjust after beaconing with new timestamp at old TBTT */ 1096*f79cbc77SKalle Valo if (tsf > now) { 1097*f79cbc77SKalle Valo data->tsf_offset += delta; 1098*f79cbc77SKalle Valo data->bcn_delta = do_div(delta, bcn_int); 1099*f79cbc77SKalle Valo } else { 1100*f79cbc77SKalle Valo data->tsf_offset -= delta; 1101*f79cbc77SKalle Valo data->bcn_delta = -(s64)do_div(delta, bcn_int); 1102*f79cbc77SKalle Valo } 1103*f79cbc77SKalle Valo } 1104*f79cbc77SKalle Valo 1105*f79cbc77SKalle Valo static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, 1106*f79cbc77SKalle Valo struct sk_buff *tx_skb, 1107*f79cbc77SKalle Valo struct ieee80211_channel *chan) 1108*f79cbc77SKalle Valo { 1109*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 1110*f79cbc77SKalle Valo struct sk_buff *skb; 1111*f79cbc77SKalle Valo struct hwsim_radiotap_hdr *hdr; 1112*f79cbc77SKalle Valo u16 flags, bitrate; 1113*f79cbc77SKalle Valo struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_skb); 1114*f79cbc77SKalle Valo struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); 1115*f79cbc77SKalle Valo 1116*f79cbc77SKalle Valo if (!txrate) 1117*f79cbc77SKalle Valo bitrate = 0; 1118*f79cbc77SKalle Valo else 1119*f79cbc77SKalle Valo bitrate = txrate->bitrate; 1120*f79cbc77SKalle Valo 1121*f79cbc77SKalle Valo if (!netif_running(hwsim_mon)) 1122*f79cbc77SKalle Valo return; 1123*f79cbc77SKalle Valo 1124*f79cbc77SKalle Valo skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); 1125*f79cbc77SKalle Valo if (skb == NULL) 1126*f79cbc77SKalle Valo return; 1127*f79cbc77SKalle Valo 1128*f79cbc77SKalle Valo hdr = skb_push(skb, sizeof(*hdr)); 1129*f79cbc77SKalle Valo hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION; 1130*f79cbc77SKalle Valo hdr->hdr.it_pad = 0; 1131*f79cbc77SKalle Valo hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); 1132*f79cbc77SKalle Valo hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | 1133*f79cbc77SKalle Valo (1 << IEEE80211_RADIOTAP_RATE) | 1134*f79cbc77SKalle Valo (1 << IEEE80211_RADIOTAP_TSFT) | 1135*f79cbc77SKalle Valo (1 << IEEE80211_RADIOTAP_CHANNEL)); 1136*f79cbc77SKalle Valo hdr->rt_tsft = __mac80211_hwsim_get_tsf(data); 1137*f79cbc77SKalle Valo hdr->rt_flags = 0; 1138*f79cbc77SKalle Valo hdr->rt_rate = bitrate / 5; 1139*f79cbc77SKalle Valo hdr->rt_channel = cpu_to_le16(chan->center_freq); 1140*f79cbc77SKalle Valo flags = IEEE80211_CHAN_2GHZ; 1141*f79cbc77SKalle Valo if (txrate && txrate->flags & IEEE80211_RATE_ERP_G) 1142*f79cbc77SKalle Valo flags |= IEEE80211_CHAN_OFDM; 1143*f79cbc77SKalle Valo else 1144*f79cbc77SKalle Valo flags |= IEEE80211_CHAN_CCK; 1145*f79cbc77SKalle Valo hdr->rt_chbitmask = cpu_to_le16(flags); 1146*f79cbc77SKalle Valo 1147*f79cbc77SKalle Valo skb->dev = hwsim_mon; 1148*f79cbc77SKalle Valo skb_reset_mac_header(skb); 1149*f79cbc77SKalle Valo skb->ip_summed = CHECKSUM_UNNECESSARY; 1150*f79cbc77SKalle Valo skb->pkt_type = PACKET_OTHERHOST; 1151*f79cbc77SKalle Valo skb->protocol = htons(ETH_P_802_2); 1152*f79cbc77SKalle Valo memset(skb->cb, 0, sizeof(skb->cb)); 1153*f79cbc77SKalle Valo netif_rx(skb); 1154*f79cbc77SKalle Valo } 1155*f79cbc77SKalle Valo 1156*f79cbc77SKalle Valo 1157*f79cbc77SKalle Valo static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan, 1158*f79cbc77SKalle Valo const u8 *addr) 1159*f79cbc77SKalle Valo { 1160*f79cbc77SKalle Valo struct sk_buff *skb; 1161*f79cbc77SKalle Valo struct hwsim_radiotap_ack_hdr *hdr; 1162*f79cbc77SKalle Valo u16 flags; 1163*f79cbc77SKalle Valo struct ieee80211_hdr *hdr11; 1164*f79cbc77SKalle Valo 1165*f79cbc77SKalle Valo if (!netif_running(hwsim_mon)) 1166*f79cbc77SKalle Valo return; 1167*f79cbc77SKalle Valo 1168*f79cbc77SKalle Valo skb = dev_alloc_skb(100); 1169*f79cbc77SKalle Valo if (skb == NULL) 1170*f79cbc77SKalle Valo return; 1171*f79cbc77SKalle Valo 1172*f79cbc77SKalle Valo hdr = skb_put(skb, sizeof(*hdr)); 1173*f79cbc77SKalle Valo hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION; 1174*f79cbc77SKalle Valo hdr->hdr.it_pad = 0; 1175*f79cbc77SKalle Valo hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); 1176*f79cbc77SKalle Valo hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | 1177*f79cbc77SKalle Valo (1 << IEEE80211_RADIOTAP_CHANNEL)); 1178*f79cbc77SKalle Valo hdr->rt_flags = 0; 1179*f79cbc77SKalle Valo hdr->pad = 0; 1180*f79cbc77SKalle Valo hdr->rt_channel = cpu_to_le16(chan->center_freq); 1181*f79cbc77SKalle Valo flags = IEEE80211_CHAN_2GHZ; 1182*f79cbc77SKalle Valo hdr->rt_chbitmask = cpu_to_le16(flags); 1183*f79cbc77SKalle Valo 1184*f79cbc77SKalle Valo hdr11 = skb_put(skb, 10); 1185*f79cbc77SKalle Valo hdr11->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | 1186*f79cbc77SKalle Valo IEEE80211_STYPE_ACK); 1187*f79cbc77SKalle Valo hdr11->duration_id = cpu_to_le16(0); 1188*f79cbc77SKalle Valo memcpy(hdr11->addr1, addr, ETH_ALEN); 1189*f79cbc77SKalle Valo 1190*f79cbc77SKalle Valo skb->dev = hwsim_mon; 1191*f79cbc77SKalle Valo skb_reset_mac_header(skb); 1192*f79cbc77SKalle Valo skb->ip_summed = CHECKSUM_UNNECESSARY; 1193*f79cbc77SKalle Valo skb->pkt_type = PACKET_OTHERHOST; 1194*f79cbc77SKalle Valo skb->protocol = htons(ETH_P_802_2); 1195*f79cbc77SKalle Valo memset(skb->cb, 0, sizeof(skb->cb)); 1196*f79cbc77SKalle Valo netif_rx(skb); 1197*f79cbc77SKalle Valo } 1198*f79cbc77SKalle Valo 1199*f79cbc77SKalle Valo struct mac80211_hwsim_addr_match_data { 1200*f79cbc77SKalle Valo u8 addr[ETH_ALEN]; 1201*f79cbc77SKalle Valo bool ret; 1202*f79cbc77SKalle Valo }; 1203*f79cbc77SKalle Valo 1204*f79cbc77SKalle Valo static void mac80211_hwsim_addr_iter(void *data, u8 *mac, 1205*f79cbc77SKalle Valo struct ieee80211_vif *vif) 1206*f79cbc77SKalle Valo { 1207*f79cbc77SKalle Valo int i; 1208*f79cbc77SKalle Valo struct mac80211_hwsim_addr_match_data *md = data; 1209*f79cbc77SKalle Valo 1210*f79cbc77SKalle Valo if (memcmp(mac, md->addr, ETH_ALEN) == 0) { 1211*f79cbc77SKalle Valo md->ret = true; 1212*f79cbc77SKalle Valo return; 1213*f79cbc77SKalle Valo } 1214*f79cbc77SKalle Valo 1215*f79cbc77SKalle Valo /* Match the link address */ 1216*f79cbc77SKalle Valo for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) { 1217*f79cbc77SKalle Valo struct ieee80211_bss_conf *conf; 1218*f79cbc77SKalle Valo 1219*f79cbc77SKalle Valo conf = rcu_dereference(vif->link_conf[i]); 1220*f79cbc77SKalle Valo if (!conf) 1221*f79cbc77SKalle Valo continue; 1222*f79cbc77SKalle Valo 1223*f79cbc77SKalle Valo if (memcmp(conf->addr, md->addr, ETH_ALEN) == 0) { 1224*f79cbc77SKalle Valo md->ret = true; 1225*f79cbc77SKalle Valo return; 1226*f79cbc77SKalle Valo } 1227*f79cbc77SKalle Valo } 1228*f79cbc77SKalle Valo } 1229*f79cbc77SKalle Valo 1230*f79cbc77SKalle Valo static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data, 1231*f79cbc77SKalle Valo const u8 *addr) 1232*f79cbc77SKalle Valo { 1233*f79cbc77SKalle Valo struct mac80211_hwsim_addr_match_data md = { 1234*f79cbc77SKalle Valo .ret = false, 1235*f79cbc77SKalle Valo }; 1236*f79cbc77SKalle Valo 1237*f79cbc77SKalle Valo if (data->scanning && memcmp(addr, data->scan_addr, ETH_ALEN) == 0) 1238*f79cbc77SKalle Valo return true; 1239*f79cbc77SKalle Valo 1240*f79cbc77SKalle Valo memcpy(md.addr, addr, ETH_ALEN); 1241*f79cbc77SKalle Valo 1242*f79cbc77SKalle Valo ieee80211_iterate_active_interfaces_atomic(data->hw, 1243*f79cbc77SKalle Valo IEEE80211_IFACE_ITER_NORMAL, 1244*f79cbc77SKalle Valo mac80211_hwsim_addr_iter, 1245*f79cbc77SKalle Valo &md); 1246*f79cbc77SKalle Valo 1247*f79cbc77SKalle Valo return md.ret; 1248*f79cbc77SKalle Valo } 1249*f79cbc77SKalle Valo 1250*f79cbc77SKalle Valo static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data, 1251*f79cbc77SKalle Valo struct sk_buff *skb) 1252*f79cbc77SKalle Valo { 1253*f79cbc77SKalle Valo switch (data->ps) { 1254*f79cbc77SKalle Valo case PS_DISABLED: 1255*f79cbc77SKalle Valo return true; 1256*f79cbc77SKalle Valo case PS_ENABLED: 1257*f79cbc77SKalle Valo return false; 1258*f79cbc77SKalle Valo case PS_AUTO_POLL: 1259*f79cbc77SKalle Valo /* TODO: accept (some) Beacons by default and other frames only 1260*f79cbc77SKalle Valo * if pending PS-Poll has been sent */ 1261*f79cbc77SKalle Valo return true; 1262*f79cbc77SKalle Valo case PS_MANUAL_POLL: 1263*f79cbc77SKalle Valo /* Allow unicast frames to own address if there is a pending 1264*f79cbc77SKalle Valo * PS-Poll */ 1265*f79cbc77SKalle Valo if (data->ps_poll_pending && 1266*f79cbc77SKalle Valo mac80211_hwsim_addr_match(data, skb->data + 4)) { 1267*f79cbc77SKalle Valo data->ps_poll_pending = false; 1268*f79cbc77SKalle Valo return true; 1269*f79cbc77SKalle Valo } 1270*f79cbc77SKalle Valo return false; 1271*f79cbc77SKalle Valo } 1272*f79cbc77SKalle Valo 1273*f79cbc77SKalle Valo return true; 1274*f79cbc77SKalle Valo } 1275*f79cbc77SKalle Valo 1276*f79cbc77SKalle Valo static int hwsim_unicast_netgroup(struct mac80211_hwsim_data *data, 1277*f79cbc77SKalle Valo struct sk_buff *skb, int portid) 1278*f79cbc77SKalle Valo { 1279*f79cbc77SKalle Valo struct net *net; 1280*f79cbc77SKalle Valo bool found = false; 1281*f79cbc77SKalle Valo int res = -ENOENT; 1282*f79cbc77SKalle Valo 1283*f79cbc77SKalle Valo rcu_read_lock(); 1284*f79cbc77SKalle Valo for_each_net_rcu(net) { 1285*f79cbc77SKalle Valo if (data->netgroup == hwsim_net_get_netgroup(net)) { 1286*f79cbc77SKalle Valo res = genlmsg_unicast(net, skb, portid); 1287*f79cbc77SKalle Valo found = true; 1288*f79cbc77SKalle Valo break; 1289*f79cbc77SKalle Valo } 1290*f79cbc77SKalle Valo } 1291*f79cbc77SKalle Valo rcu_read_unlock(); 1292*f79cbc77SKalle Valo 1293*f79cbc77SKalle Valo if (!found) 1294*f79cbc77SKalle Valo nlmsg_free(skb); 1295*f79cbc77SKalle Valo 1296*f79cbc77SKalle Valo return res; 1297*f79cbc77SKalle Valo } 1298*f79cbc77SKalle Valo 1299*f79cbc77SKalle Valo static void mac80211_hwsim_config_mac_nl(struct ieee80211_hw *hw, 1300*f79cbc77SKalle Valo const u8 *addr, bool add) 1301*f79cbc77SKalle Valo { 1302*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 1303*f79cbc77SKalle Valo u32 _portid = READ_ONCE(data->wmediumd); 1304*f79cbc77SKalle Valo struct sk_buff *skb; 1305*f79cbc77SKalle Valo void *msg_head; 1306*f79cbc77SKalle Valo 1307*f79cbc77SKalle Valo WARN_ON(!is_valid_ether_addr(addr)); 1308*f79cbc77SKalle Valo 1309*f79cbc77SKalle Valo if (!_portid && !hwsim_virtio_enabled) 1310*f79cbc77SKalle Valo return; 1311*f79cbc77SKalle Valo 1312*f79cbc77SKalle Valo skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1313*f79cbc77SKalle Valo if (!skb) 1314*f79cbc77SKalle Valo return; 1315*f79cbc77SKalle Valo 1316*f79cbc77SKalle Valo msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, 1317*f79cbc77SKalle Valo add ? HWSIM_CMD_ADD_MAC_ADDR : 1318*f79cbc77SKalle Valo HWSIM_CMD_DEL_MAC_ADDR); 1319*f79cbc77SKalle Valo if (!msg_head) { 1320*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: problem with msg_head\n"); 1321*f79cbc77SKalle Valo goto nla_put_failure; 1322*f79cbc77SKalle Valo } 1323*f79cbc77SKalle Valo 1324*f79cbc77SKalle Valo if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, 1325*f79cbc77SKalle Valo ETH_ALEN, data->addresses[1].addr)) 1326*f79cbc77SKalle Valo goto nla_put_failure; 1327*f79cbc77SKalle Valo 1328*f79cbc77SKalle Valo if (nla_put(skb, HWSIM_ATTR_ADDR_RECEIVER, ETH_ALEN, addr)) 1329*f79cbc77SKalle Valo goto nla_put_failure; 1330*f79cbc77SKalle Valo 1331*f79cbc77SKalle Valo genlmsg_end(skb, msg_head); 1332*f79cbc77SKalle Valo 1333*f79cbc77SKalle Valo if (hwsim_virtio_enabled) 1334*f79cbc77SKalle Valo hwsim_tx_virtio(data, skb); 1335*f79cbc77SKalle Valo else 1336*f79cbc77SKalle Valo hwsim_unicast_netgroup(data, skb, _portid); 1337*f79cbc77SKalle Valo return; 1338*f79cbc77SKalle Valo nla_put_failure: 1339*f79cbc77SKalle Valo nlmsg_free(skb); 1340*f79cbc77SKalle Valo } 1341*f79cbc77SKalle Valo 1342*f79cbc77SKalle Valo static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate) 1343*f79cbc77SKalle Valo { 1344*f79cbc77SKalle Valo u16 result = 0; 1345*f79cbc77SKalle Valo 1346*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_USE_RTS_CTS) 1347*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_USE_RTS_CTS; 1348*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) 1349*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT; 1350*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) 1351*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE; 1352*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_MCS) 1353*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_MCS; 1354*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD) 1355*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_GREEN_FIELD; 1356*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) 1357*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH; 1358*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_DUP_DATA) 1359*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_DUP_DATA; 1360*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_SHORT_GI) 1361*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_SHORT_GI; 1362*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_VHT_MCS) 1363*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_VHT_MCS; 1364*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) 1365*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH; 1366*f79cbc77SKalle Valo if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) 1367*f79cbc77SKalle Valo result |= MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH; 1368*f79cbc77SKalle Valo 1369*f79cbc77SKalle Valo return result; 1370*f79cbc77SKalle Valo } 1371*f79cbc77SKalle Valo 1372*f79cbc77SKalle Valo static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, 1373*f79cbc77SKalle Valo struct sk_buff *my_skb, 1374*f79cbc77SKalle Valo int dst_portid, 1375*f79cbc77SKalle Valo struct ieee80211_channel *channel) 1376*f79cbc77SKalle Valo { 1377*f79cbc77SKalle Valo struct sk_buff *skb; 1378*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 1379*f79cbc77SKalle Valo struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) my_skb->data; 1380*f79cbc77SKalle Valo struct ieee80211_tx_info *info = IEEE80211_SKB_CB(my_skb); 1381*f79cbc77SKalle Valo void *msg_head; 1382*f79cbc77SKalle Valo unsigned int hwsim_flags = 0; 1383*f79cbc77SKalle Valo int i; 1384*f79cbc77SKalle Valo struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES]; 1385*f79cbc77SKalle Valo struct hwsim_tx_rate_flag tx_attempts_flags[IEEE80211_TX_MAX_RATES]; 1386*f79cbc77SKalle Valo uintptr_t cookie; 1387*f79cbc77SKalle Valo 1388*f79cbc77SKalle Valo if (data->ps != PS_DISABLED) 1389*f79cbc77SKalle Valo hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); 1390*f79cbc77SKalle Valo /* If the queue contains MAX_QUEUE skb's drop some */ 1391*f79cbc77SKalle Valo if (skb_queue_len(&data->pending) >= MAX_QUEUE) { 1392*f79cbc77SKalle Valo /* Dropping until WARN_QUEUE level */ 1393*f79cbc77SKalle Valo while (skb_queue_len(&data->pending) >= WARN_QUEUE) { 1394*f79cbc77SKalle Valo ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); 1395*f79cbc77SKalle Valo data->tx_dropped++; 1396*f79cbc77SKalle Valo } 1397*f79cbc77SKalle Valo } 1398*f79cbc77SKalle Valo 1399*f79cbc77SKalle Valo skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1400*f79cbc77SKalle Valo if (skb == NULL) 1401*f79cbc77SKalle Valo goto nla_put_failure; 1402*f79cbc77SKalle Valo 1403*f79cbc77SKalle Valo msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, 1404*f79cbc77SKalle Valo HWSIM_CMD_FRAME); 1405*f79cbc77SKalle Valo if (msg_head == NULL) { 1406*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: problem with msg_head\n"); 1407*f79cbc77SKalle Valo goto nla_put_failure; 1408*f79cbc77SKalle Valo } 1409*f79cbc77SKalle Valo 1410*f79cbc77SKalle Valo if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, 1411*f79cbc77SKalle Valo ETH_ALEN, data->addresses[1].addr)) 1412*f79cbc77SKalle Valo goto nla_put_failure; 1413*f79cbc77SKalle Valo 1414*f79cbc77SKalle Valo /* We get the skb->data */ 1415*f79cbc77SKalle Valo if (nla_put(skb, HWSIM_ATTR_FRAME, my_skb->len, my_skb->data)) 1416*f79cbc77SKalle Valo goto nla_put_failure; 1417*f79cbc77SKalle Valo 1418*f79cbc77SKalle Valo /* We get the flags for this transmission, and we translate them to 1419*f79cbc77SKalle Valo wmediumd flags */ 1420*f79cbc77SKalle Valo 1421*f79cbc77SKalle Valo if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) 1422*f79cbc77SKalle Valo hwsim_flags |= HWSIM_TX_CTL_REQ_TX_STATUS; 1423*f79cbc77SKalle Valo 1424*f79cbc77SKalle Valo if (info->flags & IEEE80211_TX_CTL_NO_ACK) 1425*f79cbc77SKalle Valo hwsim_flags |= HWSIM_TX_CTL_NO_ACK; 1426*f79cbc77SKalle Valo 1427*f79cbc77SKalle Valo if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) 1428*f79cbc77SKalle Valo goto nla_put_failure; 1429*f79cbc77SKalle Valo 1430*f79cbc77SKalle Valo if (nla_put_u32(skb, HWSIM_ATTR_FREQ, channel->center_freq)) 1431*f79cbc77SKalle Valo goto nla_put_failure; 1432*f79cbc77SKalle Valo 1433*f79cbc77SKalle Valo /* We get the tx control (rate and retries) info*/ 1434*f79cbc77SKalle Valo 1435*f79cbc77SKalle Valo for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 1436*f79cbc77SKalle Valo tx_attempts[i].idx = info->status.rates[i].idx; 1437*f79cbc77SKalle Valo tx_attempts_flags[i].idx = info->status.rates[i].idx; 1438*f79cbc77SKalle Valo tx_attempts[i].count = info->status.rates[i].count; 1439*f79cbc77SKalle Valo tx_attempts_flags[i].flags = 1440*f79cbc77SKalle Valo trans_tx_rate_flags_ieee2hwsim( 1441*f79cbc77SKalle Valo &info->status.rates[i]); 1442*f79cbc77SKalle Valo } 1443*f79cbc77SKalle Valo 1444*f79cbc77SKalle Valo if (nla_put(skb, HWSIM_ATTR_TX_INFO, 1445*f79cbc77SKalle Valo sizeof(struct hwsim_tx_rate)*IEEE80211_TX_MAX_RATES, 1446*f79cbc77SKalle Valo tx_attempts)) 1447*f79cbc77SKalle Valo goto nla_put_failure; 1448*f79cbc77SKalle Valo 1449*f79cbc77SKalle Valo if (nla_put(skb, HWSIM_ATTR_TX_INFO_FLAGS, 1450*f79cbc77SKalle Valo sizeof(struct hwsim_tx_rate_flag) * IEEE80211_TX_MAX_RATES, 1451*f79cbc77SKalle Valo tx_attempts_flags)) 1452*f79cbc77SKalle Valo goto nla_put_failure; 1453*f79cbc77SKalle Valo 1454*f79cbc77SKalle Valo /* We create a cookie to identify this skb */ 1455*f79cbc77SKalle Valo cookie = atomic_inc_return(&data->pending_cookie); 1456*f79cbc77SKalle Valo info->rate_driver_data[0] = (void *)cookie; 1457*f79cbc77SKalle Valo if (nla_put_u64_64bit(skb, HWSIM_ATTR_COOKIE, cookie, HWSIM_ATTR_PAD)) 1458*f79cbc77SKalle Valo goto nla_put_failure; 1459*f79cbc77SKalle Valo 1460*f79cbc77SKalle Valo genlmsg_end(skb, msg_head); 1461*f79cbc77SKalle Valo 1462*f79cbc77SKalle Valo if (hwsim_virtio_enabled) { 1463*f79cbc77SKalle Valo if (hwsim_tx_virtio(data, skb)) 1464*f79cbc77SKalle Valo goto err_free_txskb; 1465*f79cbc77SKalle Valo } else { 1466*f79cbc77SKalle Valo if (hwsim_unicast_netgroup(data, skb, dst_portid)) 1467*f79cbc77SKalle Valo goto err_free_txskb; 1468*f79cbc77SKalle Valo } 1469*f79cbc77SKalle Valo 1470*f79cbc77SKalle Valo /* Enqueue the packet */ 1471*f79cbc77SKalle Valo skb_queue_tail(&data->pending, my_skb); 1472*f79cbc77SKalle Valo data->tx_pkts++; 1473*f79cbc77SKalle Valo data->tx_bytes += my_skb->len; 1474*f79cbc77SKalle Valo return; 1475*f79cbc77SKalle Valo 1476*f79cbc77SKalle Valo nla_put_failure: 1477*f79cbc77SKalle Valo nlmsg_free(skb); 1478*f79cbc77SKalle Valo err_free_txskb: 1479*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: error occurred in %s\n", __func__); 1480*f79cbc77SKalle Valo ieee80211_free_txskb(hw, my_skb); 1481*f79cbc77SKalle Valo data->tx_failed++; 1482*f79cbc77SKalle Valo } 1483*f79cbc77SKalle Valo 1484*f79cbc77SKalle Valo static bool hwsim_chans_compat(struct ieee80211_channel *c1, 1485*f79cbc77SKalle Valo struct ieee80211_channel *c2) 1486*f79cbc77SKalle Valo { 1487*f79cbc77SKalle Valo if (!c1 || !c2) 1488*f79cbc77SKalle Valo return false; 1489*f79cbc77SKalle Valo 1490*f79cbc77SKalle Valo return c1->center_freq == c2->center_freq; 1491*f79cbc77SKalle Valo } 1492*f79cbc77SKalle Valo 1493*f79cbc77SKalle Valo struct tx_iter_data { 1494*f79cbc77SKalle Valo struct ieee80211_channel *channel; 1495*f79cbc77SKalle Valo bool receive; 1496*f79cbc77SKalle Valo }; 1497*f79cbc77SKalle Valo 1498*f79cbc77SKalle Valo static void mac80211_hwsim_tx_iter(void *_data, u8 *addr, 1499*f79cbc77SKalle Valo struct ieee80211_vif *vif) 1500*f79cbc77SKalle Valo { 1501*f79cbc77SKalle Valo struct tx_iter_data *data = _data; 1502*f79cbc77SKalle Valo int i; 1503*f79cbc77SKalle Valo 1504*f79cbc77SKalle Valo for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) { 1505*f79cbc77SKalle Valo struct ieee80211_bss_conf *conf; 1506*f79cbc77SKalle Valo struct ieee80211_chanctx_conf *chanctx; 1507*f79cbc77SKalle Valo 1508*f79cbc77SKalle Valo conf = rcu_dereference(vif->link_conf[i]); 1509*f79cbc77SKalle Valo if (!conf) 1510*f79cbc77SKalle Valo continue; 1511*f79cbc77SKalle Valo 1512*f79cbc77SKalle Valo chanctx = rcu_dereference(conf->chanctx_conf); 1513*f79cbc77SKalle Valo if (!chanctx) 1514*f79cbc77SKalle Valo continue; 1515*f79cbc77SKalle Valo 1516*f79cbc77SKalle Valo if (!hwsim_chans_compat(data->channel, chanctx->def.chan)) 1517*f79cbc77SKalle Valo continue; 1518*f79cbc77SKalle Valo 1519*f79cbc77SKalle Valo data->receive = true; 1520*f79cbc77SKalle Valo return; 1521*f79cbc77SKalle Valo } 1522*f79cbc77SKalle Valo } 1523*f79cbc77SKalle Valo 1524*f79cbc77SKalle Valo static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb) 1525*f79cbc77SKalle Valo { 1526*f79cbc77SKalle Valo /* 1527*f79cbc77SKalle Valo * To enable this code, #define the HWSIM_RADIOTAP_OUI, 1528*f79cbc77SKalle Valo * e.g. like this: 1529*f79cbc77SKalle Valo * #define HWSIM_RADIOTAP_OUI "\x02\x00\x00" 1530*f79cbc77SKalle Valo * (but you should use a valid OUI, not that) 1531*f79cbc77SKalle Valo * 1532*f79cbc77SKalle Valo * If anyone wants to 'donate' a radiotap OUI/subns code 1533*f79cbc77SKalle Valo * please send a patch removing this #ifdef and changing 1534*f79cbc77SKalle Valo * the values accordingly. 1535*f79cbc77SKalle Valo */ 1536*f79cbc77SKalle Valo #ifdef HWSIM_RADIOTAP_OUI 1537*f79cbc77SKalle Valo struct ieee80211_radiotap_vendor_tlv *rtap; 1538*f79cbc77SKalle Valo static const char vendor_data[8] = "ABCDEFGH"; 1539*f79cbc77SKalle Valo 1540*f79cbc77SKalle Valo // Make sure no padding is needed 1541*f79cbc77SKalle Valo BUILD_BUG_ON(sizeof(vendor_data) % 4); 1542*f79cbc77SKalle Valo /* this is last radiotap info before the mac header, so 1543*f79cbc77SKalle Valo * skb_reset_mac_header for mac8022 to know the end of 1544*f79cbc77SKalle Valo * the radiotap TLV/beginning of the 802.11 header 1545*f79cbc77SKalle Valo */ 1546*f79cbc77SKalle Valo skb_reset_mac_header(skb); 1547*f79cbc77SKalle Valo 1548*f79cbc77SKalle Valo /* 1549*f79cbc77SKalle Valo * Note that this code requires the headroom in the SKB 1550*f79cbc77SKalle Valo * that was allocated earlier. 1551*f79cbc77SKalle Valo */ 1552*f79cbc77SKalle Valo rtap = skb_push(skb, sizeof(*rtap) + sizeof(vendor_data)); 1553*f79cbc77SKalle Valo 1554*f79cbc77SKalle Valo rtap->len = cpu_to_le16(sizeof(*rtap) - 1555*f79cbc77SKalle Valo sizeof(struct ieee80211_radiotap_tlv) + 1556*f79cbc77SKalle Valo sizeof(vendor_data)); 1557*f79cbc77SKalle Valo rtap->type = cpu_to_le16(IEEE80211_RADIOTAP_VENDOR_NAMESPACE); 1558*f79cbc77SKalle Valo 1559*f79cbc77SKalle Valo rtap->content.oui[0] = HWSIM_RADIOTAP_OUI[0]; 1560*f79cbc77SKalle Valo rtap->content.oui[1] = HWSIM_RADIOTAP_OUI[1]; 1561*f79cbc77SKalle Valo rtap->content.oui[2] = HWSIM_RADIOTAP_OUI[2]; 1562*f79cbc77SKalle Valo rtap->content.oui_subtype = 127; 1563*f79cbc77SKalle Valo /* clear reserved field */ 1564*f79cbc77SKalle Valo rtap->content.reserved = 0; 1565*f79cbc77SKalle Valo rtap->content.vendor_type = 0; 1566*f79cbc77SKalle Valo memcpy(rtap->content.data, vendor_data, sizeof(vendor_data)); 1567*f79cbc77SKalle Valo 1568*f79cbc77SKalle Valo IEEE80211_SKB_RXCB(skb)->flag |= RX_FLAG_RADIOTAP_TLV_AT_END; 1569*f79cbc77SKalle Valo #endif 1570*f79cbc77SKalle Valo } 1571*f79cbc77SKalle Valo 1572*f79cbc77SKalle Valo static void mac80211_hwsim_rx(struct mac80211_hwsim_data *data, 1573*f79cbc77SKalle Valo struct ieee80211_rx_status *rx_status, 1574*f79cbc77SKalle Valo struct sk_buff *skb) 1575*f79cbc77SKalle Valo { 1576*f79cbc77SKalle Valo struct ieee80211_hdr *hdr = (void *)skb->data; 1577*f79cbc77SKalle Valo 1578*f79cbc77SKalle Valo if (!ieee80211_has_morefrags(hdr->frame_control) && 1579*f79cbc77SKalle Valo !is_multicast_ether_addr(hdr->addr1) && 1580*f79cbc77SKalle Valo (ieee80211_is_mgmt(hdr->frame_control) || 1581*f79cbc77SKalle Valo ieee80211_is_data(hdr->frame_control))) { 1582*f79cbc77SKalle Valo struct ieee80211_sta *sta; 1583*f79cbc77SKalle Valo unsigned int link_id; 1584*f79cbc77SKalle Valo 1585*f79cbc77SKalle Valo rcu_read_lock(); 1586*f79cbc77SKalle Valo sta = ieee80211_find_sta_by_link_addrs(data->hw, hdr->addr2, 1587*f79cbc77SKalle Valo hdr->addr1, &link_id); 1588*f79cbc77SKalle Valo if (sta) { 1589*f79cbc77SKalle Valo struct hwsim_sta_priv *sp = (void *)sta->drv_priv; 1590*f79cbc77SKalle Valo 1591*f79cbc77SKalle Valo if (ieee80211_has_pm(hdr->frame_control)) 1592*f79cbc77SKalle Valo sp->active_links_rx &= ~BIT(link_id); 1593*f79cbc77SKalle Valo else 1594*f79cbc77SKalle Valo sp->active_links_rx |= BIT(link_id); 1595*f79cbc77SKalle Valo } 1596*f79cbc77SKalle Valo rcu_read_unlock(); 1597*f79cbc77SKalle Valo } 1598*f79cbc77SKalle Valo 1599*f79cbc77SKalle Valo memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); 1600*f79cbc77SKalle Valo 1601*f79cbc77SKalle Valo mac80211_hwsim_add_vendor_rtap(skb); 1602*f79cbc77SKalle Valo 1603*f79cbc77SKalle Valo data->rx_pkts++; 1604*f79cbc77SKalle Valo data->rx_bytes += skb->len; 1605*f79cbc77SKalle Valo ieee80211_rx_irqsafe(data->hw, skb); 1606*f79cbc77SKalle Valo } 1607*f79cbc77SKalle Valo 1608*f79cbc77SKalle Valo static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, 1609*f79cbc77SKalle Valo struct sk_buff *skb, 1610*f79cbc77SKalle Valo struct ieee80211_channel *chan) 1611*f79cbc77SKalle Valo { 1612*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv, *data2; 1613*f79cbc77SKalle Valo bool ack = false; 1614*f79cbc77SKalle Valo struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1615*f79cbc77SKalle Valo struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1616*f79cbc77SKalle Valo struct ieee80211_rx_status rx_status; 1617*f79cbc77SKalle Valo u64 now; 1618*f79cbc77SKalle Valo 1619*f79cbc77SKalle Valo memset(&rx_status, 0, sizeof(rx_status)); 1620*f79cbc77SKalle Valo rx_status.flag |= RX_FLAG_MACTIME_START; 1621*f79cbc77SKalle Valo rx_status.freq = chan->center_freq; 1622*f79cbc77SKalle Valo rx_status.freq_offset = chan->freq_offset ? 1 : 0; 1623*f79cbc77SKalle Valo rx_status.band = chan->band; 1624*f79cbc77SKalle Valo if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) { 1625*f79cbc77SKalle Valo rx_status.rate_idx = 1626*f79cbc77SKalle Valo ieee80211_rate_get_vht_mcs(&info->control.rates[0]); 1627*f79cbc77SKalle Valo rx_status.nss = 1628*f79cbc77SKalle Valo ieee80211_rate_get_vht_nss(&info->control.rates[0]); 1629*f79cbc77SKalle Valo rx_status.encoding = RX_ENC_VHT; 1630*f79cbc77SKalle Valo } else { 1631*f79cbc77SKalle Valo rx_status.rate_idx = info->control.rates[0].idx; 1632*f79cbc77SKalle Valo if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) 1633*f79cbc77SKalle Valo rx_status.encoding = RX_ENC_HT; 1634*f79cbc77SKalle Valo } 1635*f79cbc77SKalle Valo if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) 1636*f79cbc77SKalle Valo rx_status.bw = RATE_INFO_BW_40; 1637*f79cbc77SKalle Valo else if (info->control.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH) 1638*f79cbc77SKalle Valo rx_status.bw = RATE_INFO_BW_80; 1639*f79cbc77SKalle Valo else if (info->control.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH) 1640*f79cbc77SKalle Valo rx_status.bw = RATE_INFO_BW_160; 1641*f79cbc77SKalle Valo else 1642*f79cbc77SKalle Valo rx_status.bw = RATE_INFO_BW_20; 1643*f79cbc77SKalle Valo if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI) 1644*f79cbc77SKalle Valo rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI; 1645*f79cbc77SKalle Valo /* TODO: simulate optional packet loss */ 1646*f79cbc77SKalle Valo rx_status.signal = data->rx_rssi; 1647*f79cbc77SKalle Valo if (info->control.vif) 1648*f79cbc77SKalle Valo rx_status.signal += info->control.vif->bss_conf.txpower; 1649*f79cbc77SKalle Valo 1650*f79cbc77SKalle Valo if (data->ps != PS_DISABLED) 1651*f79cbc77SKalle Valo hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); 1652*f79cbc77SKalle Valo 1653*f79cbc77SKalle Valo /* release the skb's source info */ 1654*f79cbc77SKalle Valo skb_orphan(skb); 1655*f79cbc77SKalle Valo skb_dst_drop(skb); 1656*f79cbc77SKalle Valo skb->mark = 0; 1657*f79cbc77SKalle Valo skb_ext_reset(skb); 1658*f79cbc77SKalle Valo nf_reset_ct(skb); 1659*f79cbc77SKalle Valo 1660*f79cbc77SKalle Valo /* 1661*f79cbc77SKalle Valo * Get absolute mactime here so all HWs RX at the "same time", and 1662*f79cbc77SKalle Valo * absolute TX time for beacon mactime so the timestamp matches. 1663*f79cbc77SKalle Valo * Giving beacons a different mactime than non-beacons looks messy, but 1664*f79cbc77SKalle Valo * it helps the Toffset be exact and a ~10us mactime discrepancy 1665*f79cbc77SKalle Valo * probably doesn't really matter. 1666*f79cbc77SKalle Valo */ 1667*f79cbc77SKalle Valo if (ieee80211_is_beacon(hdr->frame_control) || 1668*f79cbc77SKalle Valo ieee80211_is_probe_resp(hdr->frame_control)) { 1669*f79cbc77SKalle Valo rx_status.boottime_ns = ktime_get_boottime_ns(); 1670*f79cbc77SKalle Valo now = data->abs_bcn_ts; 1671*f79cbc77SKalle Valo } else { 1672*f79cbc77SKalle Valo now = mac80211_hwsim_get_tsf_raw(); 1673*f79cbc77SKalle Valo } 1674*f79cbc77SKalle Valo 1675*f79cbc77SKalle Valo /* Copy skb to all enabled radios that are on the current frequency */ 1676*f79cbc77SKalle Valo spin_lock(&hwsim_radio_lock); 1677*f79cbc77SKalle Valo list_for_each_entry(data2, &hwsim_radios, list) { 1678*f79cbc77SKalle Valo struct sk_buff *nskb; 1679*f79cbc77SKalle Valo struct tx_iter_data tx_iter_data = { 1680*f79cbc77SKalle Valo .receive = false, 1681*f79cbc77SKalle Valo .channel = chan, 1682*f79cbc77SKalle Valo }; 1683*f79cbc77SKalle Valo 1684*f79cbc77SKalle Valo if (data == data2) 1685*f79cbc77SKalle Valo continue; 1686*f79cbc77SKalle Valo 1687*f79cbc77SKalle Valo if (!data2->started || (data2->idle && !data2->tmp_chan) || 1688*f79cbc77SKalle Valo !hwsim_ps_rx_ok(data2, skb)) 1689*f79cbc77SKalle Valo continue; 1690*f79cbc77SKalle Valo 1691*f79cbc77SKalle Valo if (!(data->group & data2->group)) 1692*f79cbc77SKalle Valo continue; 1693*f79cbc77SKalle Valo 1694*f79cbc77SKalle Valo if (data->netgroup != data2->netgroup) 1695*f79cbc77SKalle Valo continue; 1696*f79cbc77SKalle Valo 1697*f79cbc77SKalle Valo if (!hwsim_chans_compat(chan, data2->tmp_chan) && 1698*f79cbc77SKalle Valo !hwsim_chans_compat(chan, data2->channel)) { 1699*f79cbc77SKalle Valo ieee80211_iterate_active_interfaces_atomic( 1700*f79cbc77SKalle Valo data2->hw, IEEE80211_IFACE_ITER_NORMAL, 1701*f79cbc77SKalle Valo mac80211_hwsim_tx_iter, &tx_iter_data); 1702*f79cbc77SKalle Valo if (!tx_iter_data.receive) 1703*f79cbc77SKalle Valo continue; 1704*f79cbc77SKalle Valo } 1705*f79cbc77SKalle Valo 1706*f79cbc77SKalle Valo /* 1707*f79cbc77SKalle Valo * reserve some space for our vendor and the normal 1708*f79cbc77SKalle Valo * radiotap header, since we're copying anyway 1709*f79cbc77SKalle Valo */ 1710*f79cbc77SKalle Valo if (skb->len < PAGE_SIZE && paged_rx) { 1711*f79cbc77SKalle Valo struct page *page = alloc_page(GFP_ATOMIC); 1712*f79cbc77SKalle Valo 1713*f79cbc77SKalle Valo if (!page) 1714*f79cbc77SKalle Valo continue; 1715*f79cbc77SKalle Valo 1716*f79cbc77SKalle Valo nskb = dev_alloc_skb(128); 1717*f79cbc77SKalle Valo if (!nskb) { 1718*f79cbc77SKalle Valo __free_page(page); 1719*f79cbc77SKalle Valo continue; 1720*f79cbc77SKalle Valo } 1721*f79cbc77SKalle Valo 1722*f79cbc77SKalle Valo memcpy(page_address(page), skb->data, skb->len); 1723*f79cbc77SKalle Valo skb_add_rx_frag(nskb, 0, page, 0, skb->len, skb->len); 1724*f79cbc77SKalle Valo } else { 1725*f79cbc77SKalle Valo nskb = skb_copy(skb, GFP_ATOMIC); 1726*f79cbc77SKalle Valo if (!nskb) 1727*f79cbc77SKalle Valo continue; 1728*f79cbc77SKalle Valo } 1729*f79cbc77SKalle Valo 1730*f79cbc77SKalle Valo if (mac80211_hwsim_addr_match(data2, hdr->addr1)) 1731*f79cbc77SKalle Valo ack = true; 1732*f79cbc77SKalle Valo 1733*f79cbc77SKalle Valo rx_status.mactime = now + data2->tsf_offset; 1734*f79cbc77SKalle Valo 1735*f79cbc77SKalle Valo mac80211_hwsim_rx(data2, &rx_status, nskb); 1736*f79cbc77SKalle Valo } 1737*f79cbc77SKalle Valo spin_unlock(&hwsim_radio_lock); 1738*f79cbc77SKalle Valo 1739*f79cbc77SKalle Valo return ack; 1740*f79cbc77SKalle Valo } 1741*f79cbc77SKalle Valo 1742*f79cbc77SKalle Valo static struct ieee80211_bss_conf * 1743*f79cbc77SKalle Valo mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data, 1744*f79cbc77SKalle Valo struct ieee80211_vif *vif, 1745*f79cbc77SKalle Valo struct ieee80211_sta *sta, 1746*f79cbc77SKalle Valo struct ieee80211_hdr *hdr, 1747*f79cbc77SKalle Valo struct ieee80211_link_sta **link_sta) 1748*f79cbc77SKalle Valo { 1749*f79cbc77SKalle Valo struct hwsim_sta_priv *sp = (void *)sta->drv_priv; 1750*f79cbc77SKalle Valo int i; 1751*f79cbc77SKalle Valo 1752*f79cbc77SKalle Valo if (!vif->valid_links) 1753*f79cbc77SKalle Valo return &vif->bss_conf; 1754*f79cbc77SKalle Valo 1755*f79cbc77SKalle Valo WARN_ON(is_multicast_ether_addr(hdr->addr1)); 1756*f79cbc77SKalle Valo 1757*f79cbc77SKalle Valo if (WARN_ON_ONCE(!sta->valid_links)) 1758*f79cbc77SKalle Valo return &vif->bss_conf; 1759*f79cbc77SKalle Valo 1760*f79cbc77SKalle Valo for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) { 1761*f79cbc77SKalle Valo struct ieee80211_bss_conf *bss_conf; 1762*f79cbc77SKalle Valo unsigned int link_id; 1763*f79cbc77SKalle Valo 1764*f79cbc77SKalle Valo /* round-robin the available link IDs */ 1765*f79cbc77SKalle Valo link_id = (sp->last_link + i + 1) % ARRAY_SIZE(vif->link_conf); 1766*f79cbc77SKalle Valo 1767*f79cbc77SKalle Valo if (!(vif->active_links & BIT(link_id))) 1768*f79cbc77SKalle Valo continue; 1769*f79cbc77SKalle Valo 1770*f79cbc77SKalle Valo if (!(sp->active_links_rx & BIT(link_id))) 1771*f79cbc77SKalle Valo continue; 1772*f79cbc77SKalle Valo 1773*f79cbc77SKalle Valo *link_sta = rcu_dereference(sta->link[link_id]); 1774*f79cbc77SKalle Valo if (!*link_sta) 1775*f79cbc77SKalle Valo continue; 1776*f79cbc77SKalle Valo 1777*f79cbc77SKalle Valo bss_conf = rcu_dereference(vif->link_conf[link_id]); 1778*f79cbc77SKalle Valo if (WARN_ON_ONCE(!bss_conf)) 1779*f79cbc77SKalle Valo continue; 1780*f79cbc77SKalle Valo 1781*f79cbc77SKalle Valo /* can happen while switching links */ 1782*f79cbc77SKalle Valo if (!rcu_access_pointer(bss_conf->chanctx_conf)) 1783*f79cbc77SKalle Valo continue; 1784*f79cbc77SKalle Valo 1785*f79cbc77SKalle Valo sp->last_link = link_id; 1786*f79cbc77SKalle Valo return bss_conf; 1787*f79cbc77SKalle Valo } 1788*f79cbc77SKalle Valo 1789*f79cbc77SKalle Valo return NULL; 1790*f79cbc77SKalle Valo } 1791*f79cbc77SKalle Valo 1792*f79cbc77SKalle Valo static void mac80211_hwsim_tx(struct ieee80211_hw *hw, 1793*f79cbc77SKalle Valo struct ieee80211_tx_control *control, 1794*f79cbc77SKalle Valo struct sk_buff *skb) 1795*f79cbc77SKalle Valo { 1796*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 1797*f79cbc77SKalle Valo struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); 1798*f79cbc77SKalle Valo struct ieee80211_hdr *hdr = (void *)skb->data; 1799*f79cbc77SKalle Valo struct ieee80211_chanctx_conf *chanctx_conf; 1800*f79cbc77SKalle Valo struct ieee80211_channel *channel; 1801*f79cbc77SKalle Valo bool ack; 1802*f79cbc77SKalle Valo enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT; 1803*f79cbc77SKalle Valo u32 _portid, i; 1804*f79cbc77SKalle Valo 1805*f79cbc77SKalle Valo if (WARN_ON(skb->len < 10)) { 1806*f79cbc77SKalle Valo /* Should not happen; just a sanity check for addr1 use */ 1807*f79cbc77SKalle Valo ieee80211_free_txskb(hw, skb); 1808*f79cbc77SKalle Valo return; 1809*f79cbc77SKalle Valo } 1810*f79cbc77SKalle Valo 1811*f79cbc77SKalle Valo if (!data->use_chanctx) { 1812*f79cbc77SKalle Valo channel = data->channel; 1813*f79cbc77SKalle Valo confbw = data->bw; 1814*f79cbc77SKalle Valo } else if (txi->hw_queue == 4) { 1815*f79cbc77SKalle Valo channel = data->tmp_chan; 1816*f79cbc77SKalle Valo } else { 1817*f79cbc77SKalle Valo u8 link = u32_get_bits(IEEE80211_SKB_CB(skb)->control.flags, 1818*f79cbc77SKalle Valo IEEE80211_TX_CTRL_MLO_LINK); 1819*f79cbc77SKalle Valo struct ieee80211_vif *vif = txi->control.vif; 1820*f79cbc77SKalle Valo struct ieee80211_link_sta *link_sta = NULL; 1821*f79cbc77SKalle Valo struct ieee80211_sta *sta = control->sta; 1822*f79cbc77SKalle Valo struct ieee80211_bss_conf *bss_conf; 1823*f79cbc77SKalle Valo 1824*f79cbc77SKalle Valo if (link != IEEE80211_LINK_UNSPECIFIED) { 1825*f79cbc77SKalle Valo bss_conf = rcu_dereference(txi->control.vif->link_conf[link]); 1826*f79cbc77SKalle Valo if (sta) 1827*f79cbc77SKalle Valo link_sta = rcu_dereference(sta->link[link]); 1828*f79cbc77SKalle Valo } else { 1829*f79cbc77SKalle Valo bss_conf = mac80211_hwsim_select_tx_link(data, vif, sta, 1830*f79cbc77SKalle Valo hdr, &link_sta); 1831*f79cbc77SKalle Valo } 1832*f79cbc77SKalle Valo 1833*f79cbc77SKalle Valo if (WARN_ON(!bss_conf)) { 1834*f79cbc77SKalle Valo ieee80211_free_txskb(hw, skb); 1835*f79cbc77SKalle Valo return; 1836*f79cbc77SKalle Valo } 1837*f79cbc77SKalle Valo 1838*f79cbc77SKalle Valo if (sta && sta->mlo) { 1839*f79cbc77SKalle Valo if (WARN_ON(!link_sta)) { 1840*f79cbc77SKalle Valo ieee80211_free_txskb(hw, skb); 1841*f79cbc77SKalle Valo return; 1842*f79cbc77SKalle Valo } 1843*f79cbc77SKalle Valo /* address translation to link addresses on TX */ 1844*f79cbc77SKalle Valo ether_addr_copy(hdr->addr1, link_sta->addr); 1845*f79cbc77SKalle Valo ether_addr_copy(hdr->addr2, bss_conf->addr); 1846*f79cbc77SKalle Valo /* translate A3 only if it's the BSSID */ 1847*f79cbc77SKalle Valo if (!ieee80211_has_tods(hdr->frame_control) && 1848*f79cbc77SKalle Valo !ieee80211_has_fromds(hdr->frame_control)) { 1849*f79cbc77SKalle Valo if (ether_addr_equal(hdr->addr3, sta->addr)) 1850*f79cbc77SKalle Valo ether_addr_copy(hdr->addr3, link_sta->addr); 1851*f79cbc77SKalle Valo else if (ether_addr_equal(hdr->addr3, vif->addr)) 1852*f79cbc77SKalle Valo ether_addr_copy(hdr->addr3, bss_conf->addr); 1853*f79cbc77SKalle Valo } 1854*f79cbc77SKalle Valo /* no need to look at A4, if present it's SA */ 1855*f79cbc77SKalle Valo } 1856*f79cbc77SKalle Valo 1857*f79cbc77SKalle Valo chanctx_conf = rcu_dereference(bss_conf->chanctx_conf); 1858*f79cbc77SKalle Valo if (chanctx_conf) { 1859*f79cbc77SKalle Valo channel = chanctx_conf->def.chan; 1860*f79cbc77SKalle Valo confbw = chanctx_conf->def.width; 1861*f79cbc77SKalle Valo } else { 1862*f79cbc77SKalle Valo channel = NULL; 1863*f79cbc77SKalle Valo } 1864*f79cbc77SKalle Valo } 1865*f79cbc77SKalle Valo 1866*f79cbc77SKalle Valo if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) { 1867*f79cbc77SKalle Valo ieee80211_free_txskb(hw, skb); 1868*f79cbc77SKalle Valo return; 1869*f79cbc77SKalle Valo } 1870*f79cbc77SKalle Valo 1871*f79cbc77SKalle Valo if (data->idle && !data->tmp_chan) { 1872*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "Trying to TX when idle - reject\n"); 1873*f79cbc77SKalle Valo ieee80211_free_txskb(hw, skb); 1874*f79cbc77SKalle Valo return; 1875*f79cbc77SKalle Valo } 1876*f79cbc77SKalle Valo 1877*f79cbc77SKalle Valo if (txi->control.vif) 1878*f79cbc77SKalle Valo hwsim_check_magic(txi->control.vif); 1879*f79cbc77SKalle Valo if (control->sta) 1880*f79cbc77SKalle Valo hwsim_check_sta_magic(control->sta); 1881*f79cbc77SKalle Valo 1882*f79cbc77SKalle Valo if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE)) 1883*f79cbc77SKalle Valo ieee80211_get_tx_rates(txi->control.vif, control->sta, skb, 1884*f79cbc77SKalle Valo txi->control.rates, 1885*f79cbc77SKalle Valo ARRAY_SIZE(txi->control.rates)); 1886*f79cbc77SKalle Valo 1887*f79cbc77SKalle Valo for (i = 0; i < ARRAY_SIZE(txi->control.rates); i++) { 1888*f79cbc77SKalle Valo u16 rflags = txi->control.rates[i].flags; 1889*f79cbc77SKalle Valo /* initialize to data->bw for 5/10 MHz handling */ 1890*f79cbc77SKalle Valo enum nl80211_chan_width bw = data->bw; 1891*f79cbc77SKalle Valo 1892*f79cbc77SKalle Valo if (txi->control.rates[i].idx == -1) 1893*f79cbc77SKalle Valo break; 1894*f79cbc77SKalle Valo 1895*f79cbc77SKalle Valo if (rflags & IEEE80211_TX_RC_40_MHZ_WIDTH) 1896*f79cbc77SKalle Valo bw = NL80211_CHAN_WIDTH_40; 1897*f79cbc77SKalle Valo else if (rflags & IEEE80211_TX_RC_80_MHZ_WIDTH) 1898*f79cbc77SKalle Valo bw = NL80211_CHAN_WIDTH_80; 1899*f79cbc77SKalle Valo else if (rflags & IEEE80211_TX_RC_160_MHZ_WIDTH) 1900*f79cbc77SKalle Valo bw = NL80211_CHAN_WIDTH_160; 1901*f79cbc77SKalle Valo 1902*f79cbc77SKalle Valo if (WARN_ON(hwsim_get_chanwidth(bw) > hwsim_get_chanwidth(confbw))) 1903*f79cbc77SKalle Valo return; 1904*f79cbc77SKalle Valo } 1905*f79cbc77SKalle Valo 1906*f79cbc77SKalle Valo if (skb->len >= 24 + 8 && 1907*f79cbc77SKalle Valo ieee80211_is_probe_resp(hdr->frame_control)) { 1908*f79cbc77SKalle Valo /* fake header transmission time */ 1909*f79cbc77SKalle Valo struct ieee80211_mgmt *mgmt; 1910*f79cbc77SKalle Valo struct ieee80211_rate *txrate; 1911*f79cbc77SKalle Valo /* TODO: get MCS */ 1912*f79cbc77SKalle Valo int bitrate = 100; 1913*f79cbc77SKalle Valo u64 ts; 1914*f79cbc77SKalle Valo 1915*f79cbc77SKalle Valo mgmt = (struct ieee80211_mgmt *)skb->data; 1916*f79cbc77SKalle Valo txrate = ieee80211_get_tx_rate(hw, txi); 1917*f79cbc77SKalle Valo if (txrate) 1918*f79cbc77SKalle Valo bitrate = txrate->bitrate; 1919*f79cbc77SKalle Valo ts = mac80211_hwsim_get_tsf_raw(); 1920*f79cbc77SKalle Valo mgmt->u.probe_resp.timestamp = 1921*f79cbc77SKalle Valo cpu_to_le64(ts + data->tsf_offset + 1922*f79cbc77SKalle Valo 24 * 8 * 10 / bitrate); 1923*f79cbc77SKalle Valo } 1924*f79cbc77SKalle Valo 1925*f79cbc77SKalle Valo mac80211_hwsim_monitor_rx(hw, skb, channel); 1926*f79cbc77SKalle Valo 1927*f79cbc77SKalle Valo /* wmediumd mode check */ 1928*f79cbc77SKalle Valo _portid = READ_ONCE(data->wmediumd); 1929*f79cbc77SKalle Valo 1930*f79cbc77SKalle Valo if (_portid || hwsim_virtio_enabled) 1931*f79cbc77SKalle Valo return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, channel); 1932*f79cbc77SKalle Valo 1933*f79cbc77SKalle Valo /* NO wmediumd detected, perfect medium simulation */ 1934*f79cbc77SKalle Valo data->tx_pkts++; 1935*f79cbc77SKalle Valo data->tx_bytes += skb->len; 1936*f79cbc77SKalle Valo ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); 1937*f79cbc77SKalle Valo 1938*f79cbc77SKalle Valo if (ack && skb->len >= 16) 1939*f79cbc77SKalle Valo mac80211_hwsim_monitor_ack(channel, hdr->addr2); 1940*f79cbc77SKalle Valo 1941*f79cbc77SKalle Valo ieee80211_tx_info_clear_status(txi); 1942*f79cbc77SKalle Valo 1943*f79cbc77SKalle Valo /* frame was transmitted at most favorable rate at first attempt */ 1944*f79cbc77SKalle Valo txi->control.rates[0].count = 1; 1945*f79cbc77SKalle Valo txi->control.rates[1].idx = -1; 1946*f79cbc77SKalle Valo 1947*f79cbc77SKalle Valo if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) 1948*f79cbc77SKalle Valo txi->flags |= IEEE80211_TX_STAT_ACK; 1949*f79cbc77SKalle Valo ieee80211_tx_status_irqsafe(hw, skb); 1950*f79cbc77SKalle Valo } 1951*f79cbc77SKalle Valo 1952*f79cbc77SKalle Valo 1953*f79cbc77SKalle Valo static int mac80211_hwsim_start(struct ieee80211_hw *hw) 1954*f79cbc77SKalle Valo { 1955*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 1956*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "%s\n", __func__); 1957*f79cbc77SKalle Valo data->started = true; 1958*f79cbc77SKalle Valo return 0; 1959*f79cbc77SKalle Valo } 1960*f79cbc77SKalle Valo 1961*f79cbc77SKalle Valo 1962*f79cbc77SKalle Valo static void mac80211_hwsim_stop(struct ieee80211_hw *hw) 1963*f79cbc77SKalle Valo { 1964*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 1965*f79cbc77SKalle Valo int i; 1966*f79cbc77SKalle Valo 1967*f79cbc77SKalle Valo data->started = false; 1968*f79cbc77SKalle Valo 1969*f79cbc77SKalle Valo for (i = 0; i < ARRAY_SIZE(data->link_data); i++) 1970*f79cbc77SKalle Valo hrtimer_cancel(&data->link_data[i].beacon_timer); 1971*f79cbc77SKalle Valo 1972*f79cbc77SKalle Valo while (!skb_queue_empty(&data->pending)) 1973*f79cbc77SKalle Valo ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); 1974*f79cbc77SKalle Valo 1975*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "%s\n", __func__); 1976*f79cbc77SKalle Valo } 1977*f79cbc77SKalle Valo 1978*f79cbc77SKalle Valo 1979*f79cbc77SKalle Valo static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, 1980*f79cbc77SKalle Valo struct ieee80211_vif *vif) 1981*f79cbc77SKalle Valo { 1982*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", 1983*f79cbc77SKalle Valo __func__, ieee80211_vif_type_p2p(vif), 1984*f79cbc77SKalle Valo vif->addr); 1985*f79cbc77SKalle Valo hwsim_set_magic(vif); 1986*f79cbc77SKalle Valo 1987*f79cbc77SKalle Valo if (vif->type != NL80211_IFTYPE_MONITOR) 1988*f79cbc77SKalle Valo mac80211_hwsim_config_mac_nl(hw, vif->addr, true); 1989*f79cbc77SKalle Valo 1990*f79cbc77SKalle Valo vif->cab_queue = 0; 1991*f79cbc77SKalle Valo vif->hw_queue[IEEE80211_AC_VO] = 0; 1992*f79cbc77SKalle Valo vif->hw_queue[IEEE80211_AC_VI] = 1; 1993*f79cbc77SKalle Valo vif->hw_queue[IEEE80211_AC_BE] = 2; 1994*f79cbc77SKalle Valo vif->hw_queue[IEEE80211_AC_BK] = 3; 1995*f79cbc77SKalle Valo 1996*f79cbc77SKalle Valo return 0; 1997*f79cbc77SKalle Valo } 1998*f79cbc77SKalle Valo 1999*f79cbc77SKalle Valo 2000*f79cbc77SKalle Valo static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, 2001*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2002*f79cbc77SKalle Valo enum nl80211_iftype newtype, 2003*f79cbc77SKalle Valo bool newp2p) 2004*f79cbc77SKalle Valo { 2005*f79cbc77SKalle Valo newtype = ieee80211_iftype_p2p(newtype, newp2p); 2006*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, 2007*f79cbc77SKalle Valo "%s (old type=%d, new type=%d, mac_addr=%pM)\n", 2008*f79cbc77SKalle Valo __func__, ieee80211_vif_type_p2p(vif), 2009*f79cbc77SKalle Valo newtype, vif->addr); 2010*f79cbc77SKalle Valo hwsim_check_magic(vif); 2011*f79cbc77SKalle Valo 2012*f79cbc77SKalle Valo /* 2013*f79cbc77SKalle Valo * interface may change from non-AP to AP in 2014*f79cbc77SKalle Valo * which case this needs to be set up again 2015*f79cbc77SKalle Valo */ 2016*f79cbc77SKalle Valo vif->cab_queue = 0; 2017*f79cbc77SKalle Valo 2018*f79cbc77SKalle Valo return 0; 2019*f79cbc77SKalle Valo } 2020*f79cbc77SKalle Valo 2021*f79cbc77SKalle Valo static void mac80211_hwsim_remove_interface( 2022*f79cbc77SKalle Valo struct ieee80211_hw *hw, struct ieee80211_vif *vif) 2023*f79cbc77SKalle Valo { 2024*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", 2025*f79cbc77SKalle Valo __func__, ieee80211_vif_type_p2p(vif), 2026*f79cbc77SKalle Valo vif->addr); 2027*f79cbc77SKalle Valo hwsim_check_magic(vif); 2028*f79cbc77SKalle Valo hwsim_clear_magic(vif); 2029*f79cbc77SKalle Valo if (vif->type != NL80211_IFTYPE_MONITOR) 2030*f79cbc77SKalle Valo mac80211_hwsim_config_mac_nl(hw, vif->addr, false); 2031*f79cbc77SKalle Valo } 2032*f79cbc77SKalle Valo 2033*f79cbc77SKalle Valo static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, 2034*f79cbc77SKalle Valo struct sk_buff *skb, 2035*f79cbc77SKalle Valo struct ieee80211_channel *chan) 2036*f79cbc77SKalle Valo { 2037*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 2038*f79cbc77SKalle Valo u32 _portid = READ_ONCE(data->wmediumd); 2039*f79cbc77SKalle Valo 2040*f79cbc77SKalle Valo if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE)) { 2041*f79cbc77SKalle Valo struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); 2042*f79cbc77SKalle Valo ieee80211_get_tx_rates(txi->control.vif, NULL, skb, 2043*f79cbc77SKalle Valo txi->control.rates, 2044*f79cbc77SKalle Valo ARRAY_SIZE(txi->control.rates)); 2045*f79cbc77SKalle Valo } 2046*f79cbc77SKalle Valo 2047*f79cbc77SKalle Valo mac80211_hwsim_monitor_rx(hw, skb, chan); 2048*f79cbc77SKalle Valo 2049*f79cbc77SKalle Valo if (_portid || hwsim_virtio_enabled) 2050*f79cbc77SKalle Valo return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, chan); 2051*f79cbc77SKalle Valo 2052*f79cbc77SKalle Valo data->tx_pkts++; 2053*f79cbc77SKalle Valo data->tx_bytes += skb->len; 2054*f79cbc77SKalle Valo mac80211_hwsim_tx_frame_no_nl(hw, skb, chan); 2055*f79cbc77SKalle Valo dev_kfree_skb(skb); 2056*f79cbc77SKalle Valo } 2057*f79cbc77SKalle Valo 2058*f79cbc77SKalle Valo static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, 2059*f79cbc77SKalle Valo struct ieee80211_vif *vif) 2060*f79cbc77SKalle Valo { 2061*f79cbc77SKalle Valo struct mac80211_hwsim_link_data *link_data = arg; 2062*f79cbc77SKalle Valo u32 link_id = link_data->link_id; 2063*f79cbc77SKalle Valo struct ieee80211_bss_conf *link_conf; 2064*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = 2065*f79cbc77SKalle Valo container_of(link_data, struct mac80211_hwsim_data, 2066*f79cbc77SKalle Valo link_data[link_id]); 2067*f79cbc77SKalle Valo struct ieee80211_hw *hw = data->hw; 2068*f79cbc77SKalle Valo struct ieee80211_tx_info *info; 2069*f79cbc77SKalle Valo struct ieee80211_rate *txrate; 2070*f79cbc77SKalle Valo struct ieee80211_mgmt *mgmt; 2071*f79cbc77SKalle Valo struct sk_buff *skb; 2072*f79cbc77SKalle Valo /* TODO: get MCS */ 2073*f79cbc77SKalle Valo int bitrate = 100; 2074*f79cbc77SKalle Valo 2075*f79cbc77SKalle Valo hwsim_check_magic(vif); 2076*f79cbc77SKalle Valo 2077*f79cbc77SKalle Valo link_conf = rcu_dereference(vif->link_conf[link_id]); 2078*f79cbc77SKalle Valo if (!link_conf) 2079*f79cbc77SKalle Valo return; 2080*f79cbc77SKalle Valo 2081*f79cbc77SKalle Valo if (vif->type != NL80211_IFTYPE_AP && 2082*f79cbc77SKalle Valo vif->type != NL80211_IFTYPE_MESH_POINT && 2083*f79cbc77SKalle Valo vif->type != NL80211_IFTYPE_ADHOC && 2084*f79cbc77SKalle Valo vif->type != NL80211_IFTYPE_OCB) 2085*f79cbc77SKalle Valo return; 2086*f79cbc77SKalle Valo 2087*f79cbc77SKalle Valo skb = ieee80211_beacon_get(hw, vif, link_data->link_id); 2088*f79cbc77SKalle Valo if (skb == NULL) 2089*f79cbc77SKalle Valo return; 2090*f79cbc77SKalle Valo info = IEEE80211_SKB_CB(skb); 2091*f79cbc77SKalle Valo if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE)) 2092*f79cbc77SKalle Valo ieee80211_get_tx_rates(vif, NULL, skb, 2093*f79cbc77SKalle Valo info->control.rates, 2094*f79cbc77SKalle Valo ARRAY_SIZE(info->control.rates)); 2095*f79cbc77SKalle Valo 2096*f79cbc77SKalle Valo txrate = ieee80211_get_tx_rate(hw, info); 2097*f79cbc77SKalle Valo if (txrate) 2098*f79cbc77SKalle Valo bitrate = txrate->bitrate; 2099*f79cbc77SKalle Valo 2100*f79cbc77SKalle Valo mgmt = (struct ieee80211_mgmt *) skb->data; 2101*f79cbc77SKalle Valo /* fake header transmission time */ 2102*f79cbc77SKalle Valo data->abs_bcn_ts = mac80211_hwsim_get_tsf_raw(); 2103*f79cbc77SKalle Valo if (ieee80211_is_s1g_beacon(mgmt->frame_control)) { 2104*f79cbc77SKalle Valo struct ieee80211_ext *ext = (void *) mgmt; 2105*f79cbc77SKalle Valo 2106*f79cbc77SKalle Valo ext->u.s1g_beacon.timestamp = cpu_to_le32(data->abs_bcn_ts + 2107*f79cbc77SKalle Valo data->tsf_offset + 2108*f79cbc77SKalle Valo 10 * 8 * 10 / 2109*f79cbc77SKalle Valo bitrate); 2110*f79cbc77SKalle Valo } else { 2111*f79cbc77SKalle Valo mgmt->u.beacon.timestamp = cpu_to_le64(data->abs_bcn_ts + 2112*f79cbc77SKalle Valo data->tsf_offset + 2113*f79cbc77SKalle Valo 24 * 8 * 10 / 2114*f79cbc77SKalle Valo bitrate); 2115*f79cbc77SKalle Valo } 2116*f79cbc77SKalle Valo 2117*f79cbc77SKalle Valo mac80211_hwsim_tx_frame(hw, skb, 2118*f79cbc77SKalle Valo rcu_dereference(link_conf->chanctx_conf)->def.chan); 2119*f79cbc77SKalle Valo 2120*f79cbc77SKalle Valo while ((skb = ieee80211_get_buffered_bc(hw, vif)) != NULL) { 2121*f79cbc77SKalle Valo mac80211_hwsim_tx_frame(hw, skb, 2122*f79cbc77SKalle Valo rcu_dereference(link_conf->chanctx_conf)->def.chan); 2123*f79cbc77SKalle Valo } 2124*f79cbc77SKalle Valo 2125*f79cbc77SKalle Valo if (link_conf->csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) 2126*f79cbc77SKalle Valo ieee80211_csa_finish(vif); 2127*f79cbc77SKalle Valo } 2128*f79cbc77SKalle Valo 2129*f79cbc77SKalle Valo static enum hrtimer_restart 2130*f79cbc77SKalle Valo mac80211_hwsim_beacon(struct hrtimer *timer) 2131*f79cbc77SKalle Valo { 2132*f79cbc77SKalle Valo struct mac80211_hwsim_link_data *link_data = 2133*f79cbc77SKalle Valo container_of(timer, struct mac80211_hwsim_link_data, beacon_timer); 2134*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = 2135*f79cbc77SKalle Valo container_of(link_data, struct mac80211_hwsim_data, 2136*f79cbc77SKalle Valo link_data[link_data->link_id]); 2137*f79cbc77SKalle Valo struct ieee80211_hw *hw = data->hw; 2138*f79cbc77SKalle Valo u64 bcn_int = link_data->beacon_int; 2139*f79cbc77SKalle Valo 2140*f79cbc77SKalle Valo if (!data->started) 2141*f79cbc77SKalle Valo return HRTIMER_NORESTART; 2142*f79cbc77SKalle Valo 2143*f79cbc77SKalle Valo ieee80211_iterate_active_interfaces_atomic( 2144*f79cbc77SKalle Valo hw, IEEE80211_IFACE_ITER_NORMAL, 2145*f79cbc77SKalle Valo mac80211_hwsim_beacon_tx, link_data); 2146*f79cbc77SKalle Valo 2147*f79cbc77SKalle Valo /* beacon at new TBTT + beacon interval */ 2148*f79cbc77SKalle Valo if (data->bcn_delta) { 2149*f79cbc77SKalle Valo bcn_int -= data->bcn_delta; 2150*f79cbc77SKalle Valo data->bcn_delta = 0; 2151*f79cbc77SKalle Valo } 2152*f79cbc77SKalle Valo hrtimer_forward_now(&link_data->beacon_timer, 2153*f79cbc77SKalle Valo ns_to_ktime(bcn_int * NSEC_PER_USEC)); 2154*f79cbc77SKalle Valo return HRTIMER_RESTART; 2155*f79cbc77SKalle Valo } 2156*f79cbc77SKalle Valo 2157*f79cbc77SKalle Valo static const char * const hwsim_chanwidths[] = { 2158*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_5] = "ht5", 2159*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_10] = "ht10", 2160*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_20_NOHT] = "noht", 2161*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_20] = "ht20", 2162*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_40] = "ht40", 2163*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_80] = "vht80", 2164*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_80P80] = "vht80p80", 2165*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_160] = "vht160", 2166*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_1] = "1MHz", 2167*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_2] = "2MHz", 2168*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_4] = "4MHz", 2169*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_8] = "8MHz", 2170*f79cbc77SKalle Valo [NL80211_CHAN_WIDTH_16] = "16MHz", 2171*f79cbc77SKalle Valo }; 2172*f79cbc77SKalle Valo 2173*f79cbc77SKalle Valo static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) 2174*f79cbc77SKalle Valo { 2175*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 2176*f79cbc77SKalle Valo struct ieee80211_conf *conf = &hw->conf; 2177*f79cbc77SKalle Valo static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { 2178*f79cbc77SKalle Valo [IEEE80211_SMPS_AUTOMATIC] = "auto", 2179*f79cbc77SKalle Valo [IEEE80211_SMPS_OFF] = "off", 2180*f79cbc77SKalle Valo [IEEE80211_SMPS_STATIC] = "static", 2181*f79cbc77SKalle Valo [IEEE80211_SMPS_DYNAMIC] = "dynamic", 2182*f79cbc77SKalle Valo }; 2183*f79cbc77SKalle Valo int idx; 2184*f79cbc77SKalle Valo 2185*f79cbc77SKalle Valo if (conf->chandef.chan) 2186*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, 2187*f79cbc77SKalle Valo "%s (freq=%d(%d - %d)/%s idle=%d ps=%d smps=%s)\n", 2188*f79cbc77SKalle Valo __func__, 2189*f79cbc77SKalle Valo conf->chandef.chan->center_freq, 2190*f79cbc77SKalle Valo conf->chandef.center_freq1, 2191*f79cbc77SKalle Valo conf->chandef.center_freq2, 2192*f79cbc77SKalle Valo hwsim_chanwidths[conf->chandef.width], 2193*f79cbc77SKalle Valo !!(conf->flags & IEEE80211_CONF_IDLE), 2194*f79cbc77SKalle Valo !!(conf->flags & IEEE80211_CONF_PS), 2195*f79cbc77SKalle Valo smps_modes[conf->smps_mode]); 2196*f79cbc77SKalle Valo else 2197*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, 2198*f79cbc77SKalle Valo "%s (freq=0 idle=%d ps=%d smps=%s)\n", 2199*f79cbc77SKalle Valo __func__, 2200*f79cbc77SKalle Valo !!(conf->flags & IEEE80211_CONF_IDLE), 2201*f79cbc77SKalle Valo !!(conf->flags & IEEE80211_CONF_PS), 2202*f79cbc77SKalle Valo smps_modes[conf->smps_mode]); 2203*f79cbc77SKalle Valo 2204*f79cbc77SKalle Valo data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); 2205*f79cbc77SKalle Valo 2206*f79cbc77SKalle Valo WARN_ON(conf->chandef.chan && data->use_chanctx); 2207*f79cbc77SKalle Valo 2208*f79cbc77SKalle Valo mutex_lock(&data->mutex); 2209*f79cbc77SKalle Valo if (data->scanning && conf->chandef.chan) { 2210*f79cbc77SKalle Valo for (idx = 0; idx < ARRAY_SIZE(data->survey_data); idx++) { 2211*f79cbc77SKalle Valo if (data->survey_data[idx].channel == data->channel) { 2212*f79cbc77SKalle Valo data->survey_data[idx].start = 2213*f79cbc77SKalle Valo data->survey_data[idx].next_start; 2214*f79cbc77SKalle Valo data->survey_data[idx].end = jiffies; 2215*f79cbc77SKalle Valo break; 2216*f79cbc77SKalle Valo } 2217*f79cbc77SKalle Valo } 2218*f79cbc77SKalle Valo 2219*f79cbc77SKalle Valo data->channel = conf->chandef.chan; 2220*f79cbc77SKalle Valo data->bw = conf->chandef.width; 2221*f79cbc77SKalle Valo 2222*f79cbc77SKalle Valo for (idx = 0; idx < ARRAY_SIZE(data->survey_data); idx++) { 2223*f79cbc77SKalle Valo if (data->survey_data[idx].channel && 2224*f79cbc77SKalle Valo data->survey_data[idx].channel != data->channel) 2225*f79cbc77SKalle Valo continue; 2226*f79cbc77SKalle Valo data->survey_data[idx].channel = data->channel; 2227*f79cbc77SKalle Valo data->survey_data[idx].next_start = jiffies; 2228*f79cbc77SKalle Valo break; 2229*f79cbc77SKalle Valo } 2230*f79cbc77SKalle Valo } else { 2231*f79cbc77SKalle Valo data->channel = conf->chandef.chan; 2232*f79cbc77SKalle Valo data->bw = conf->chandef.width; 2233*f79cbc77SKalle Valo } 2234*f79cbc77SKalle Valo mutex_unlock(&data->mutex); 2235*f79cbc77SKalle Valo 2236*f79cbc77SKalle Valo for (idx = 0; idx < ARRAY_SIZE(data->link_data); idx++) { 2237*f79cbc77SKalle Valo struct mac80211_hwsim_link_data *link_data = 2238*f79cbc77SKalle Valo &data->link_data[idx]; 2239*f79cbc77SKalle Valo 2240*f79cbc77SKalle Valo if (!data->started || !link_data->beacon_int) { 2241*f79cbc77SKalle Valo hrtimer_cancel(&link_data->beacon_timer); 2242*f79cbc77SKalle Valo } else if (!hrtimer_is_queued(&link_data->beacon_timer)) { 2243*f79cbc77SKalle Valo u64 tsf = mac80211_hwsim_get_tsf(hw, NULL); 2244*f79cbc77SKalle Valo u32 bcn_int = link_data->beacon_int; 2245*f79cbc77SKalle Valo u64 until_tbtt = bcn_int - do_div(tsf, bcn_int); 2246*f79cbc77SKalle Valo 2247*f79cbc77SKalle Valo hrtimer_start(&link_data->beacon_timer, 2248*f79cbc77SKalle Valo ns_to_ktime(until_tbtt * NSEC_PER_USEC), 2249*f79cbc77SKalle Valo HRTIMER_MODE_REL_SOFT); 2250*f79cbc77SKalle Valo } 2251*f79cbc77SKalle Valo } 2252*f79cbc77SKalle Valo 2253*f79cbc77SKalle Valo return 0; 2254*f79cbc77SKalle Valo } 2255*f79cbc77SKalle Valo 2256*f79cbc77SKalle Valo 2257*f79cbc77SKalle Valo static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, 2258*f79cbc77SKalle Valo unsigned int changed_flags, 2259*f79cbc77SKalle Valo unsigned int *total_flags,u64 multicast) 2260*f79cbc77SKalle Valo { 2261*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 2262*f79cbc77SKalle Valo 2263*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "%s\n", __func__); 2264*f79cbc77SKalle Valo 2265*f79cbc77SKalle Valo data->rx_filter = 0; 2266*f79cbc77SKalle Valo if (*total_flags & FIF_ALLMULTI) 2267*f79cbc77SKalle Valo data->rx_filter |= FIF_ALLMULTI; 2268*f79cbc77SKalle Valo if (*total_flags & FIF_MCAST_ACTION) 2269*f79cbc77SKalle Valo data->rx_filter |= FIF_MCAST_ACTION; 2270*f79cbc77SKalle Valo 2271*f79cbc77SKalle Valo *total_flags = data->rx_filter; 2272*f79cbc77SKalle Valo } 2273*f79cbc77SKalle Valo 2274*f79cbc77SKalle Valo static void mac80211_hwsim_bcn_en_iter(void *data, u8 *mac, 2275*f79cbc77SKalle Valo struct ieee80211_vif *vif) 2276*f79cbc77SKalle Valo { 2277*f79cbc77SKalle Valo unsigned int *count = data; 2278*f79cbc77SKalle Valo struct hwsim_vif_priv *vp = (void *)vif->drv_priv; 2279*f79cbc77SKalle Valo 2280*f79cbc77SKalle Valo if (vp->bcn_en) 2281*f79cbc77SKalle Valo (*count)++; 2282*f79cbc77SKalle Valo } 2283*f79cbc77SKalle Valo 2284*f79cbc77SKalle Valo static void mac80211_hwsim_vif_info_changed(struct ieee80211_hw *hw, 2285*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2286*f79cbc77SKalle Valo u64 changed) 2287*f79cbc77SKalle Valo { 2288*f79cbc77SKalle Valo struct hwsim_vif_priv *vp = (void *)vif->drv_priv; 2289*f79cbc77SKalle Valo 2290*f79cbc77SKalle Valo hwsim_check_magic(vif); 2291*f79cbc77SKalle Valo 2292*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "%s(changed=0x%llx vif->addr=%pM)\n", 2293*f79cbc77SKalle Valo __func__, changed, vif->addr); 2294*f79cbc77SKalle Valo 2295*f79cbc77SKalle Valo if (changed & BSS_CHANGED_ASSOC) { 2296*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " ASSOC: assoc=%d aid=%d\n", 2297*f79cbc77SKalle Valo vif->cfg.assoc, vif->cfg.aid); 2298*f79cbc77SKalle Valo vp->assoc = vif->cfg.assoc; 2299*f79cbc77SKalle Valo vp->aid = vif->cfg.aid; 2300*f79cbc77SKalle Valo } 2301*f79cbc77SKalle Valo } 2302*f79cbc77SKalle Valo 2303*f79cbc77SKalle Valo static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw, 2304*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2305*f79cbc77SKalle Valo struct ieee80211_bss_conf *info, 2306*f79cbc77SKalle Valo u64 changed) 2307*f79cbc77SKalle Valo { 2308*f79cbc77SKalle Valo struct hwsim_vif_priv *vp = (void *)vif->drv_priv; 2309*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 2310*f79cbc77SKalle Valo unsigned int link_id = info->link_id; 2311*f79cbc77SKalle Valo struct mac80211_hwsim_link_data *link_data = &data->link_data[link_id]; 2312*f79cbc77SKalle Valo 2313*f79cbc77SKalle Valo hwsim_check_magic(vif); 2314*f79cbc77SKalle Valo 2315*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "%s(changed=0x%llx vif->addr=%pM, link id %u)\n", 2316*f79cbc77SKalle Valo __func__, (unsigned long long)changed, vif->addr, link_id); 2317*f79cbc77SKalle Valo 2318*f79cbc77SKalle Valo if (changed & BSS_CHANGED_BSSID) { 2319*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "%s: BSSID changed: %pM\n", 2320*f79cbc77SKalle Valo __func__, info->bssid); 2321*f79cbc77SKalle Valo memcpy(vp->bssid, info->bssid, ETH_ALEN); 2322*f79cbc77SKalle Valo } 2323*f79cbc77SKalle Valo 2324*f79cbc77SKalle Valo if (changed & BSS_CHANGED_BEACON_ENABLED) { 2325*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " BCN EN: %d (BI=%u)\n", 2326*f79cbc77SKalle Valo info->enable_beacon, info->beacon_int); 2327*f79cbc77SKalle Valo vp->bcn_en = info->enable_beacon; 2328*f79cbc77SKalle Valo if (data->started && 2329*f79cbc77SKalle Valo !hrtimer_is_queued(&link_data->beacon_timer) && 2330*f79cbc77SKalle Valo info->enable_beacon) { 2331*f79cbc77SKalle Valo u64 tsf, until_tbtt; 2332*f79cbc77SKalle Valo u32 bcn_int; 2333*f79cbc77SKalle Valo link_data->beacon_int = info->beacon_int * 1024; 2334*f79cbc77SKalle Valo tsf = mac80211_hwsim_get_tsf(hw, vif); 2335*f79cbc77SKalle Valo bcn_int = link_data->beacon_int; 2336*f79cbc77SKalle Valo until_tbtt = bcn_int - do_div(tsf, bcn_int); 2337*f79cbc77SKalle Valo 2338*f79cbc77SKalle Valo hrtimer_start(&link_data->beacon_timer, 2339*f79cbc77SKalle Valo ns_to_ktime(until_tbtt * NSEC_PER_USEC), 2340*f79cbc77SKalle Valo HRTIMER_MODE_REL_SOFT); 2341*f79cbc77SKalle Valo } else if (!info->enable_beacon) { 2342*f79cbc77SKalle Valo unsigned int count = 0; 2343*f79cbc77SKalle Valo ieee80211_iterate_active_interfaces_atomic( 2344*f79cbc77SKalle Valo data->hw, IEEE80211_IFACE_ITER_NORMAL, 2345*f79cbc77SKalle Valo mac80211_hwsim_bcn_en_iter, &count); 2346*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " beaconing vifs remaining: %u", 2347*f79cbc77SKalle Valo count); 2348*f79cbc77SKalle Valo if (count == 0) { 2349*f79cbc77SKalle Valo hrtimer_cancel(&link_data->beacon_timer); 2350*f79cbc77SKalle Valo link_data->beacon_int = 0; 2351*f79cbc77SKalle Valo } 2352*f79cbc77SKalle Valo } 2353*f79cbc77SKalle Valo } 2354*f79cbc77SKalle Valo 2355*f79cbc77SKalle Valo if (changed & BSS_CHANGED_ERP_CTS_PROT) { 2356*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " ERP_CTS_PROT: %d\n", 2357*f79cbc77SKalle Valo info->use_cts_prot); 2358*f79cbc77SKalle Valo } 2359*f79cbc77SKalle Valo 2360*f79cbc77SKalle Valo if (changed & BSS_CHANGED_ERP_PREAMBLE) { 2361*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " ERP_PREAMBLE: %d\n", 2362*f79cbc77SKalle Valo info->use_short_preamble); 2363*f79cbc77SKalle Valo } 2364*f79cbc77SKalle Valo 2365*f79cbc77SKalle Valo if (changed & BSS_CHANGED_ERP_SLOT) { 2366*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " ERP_SLOT: %d\n", info->use_short_slot); 2367*f79cbc77SKalle Valo } 2368*f79cbc77SKalle Valo 2369*f79cbc77SKalle Valo if (changed & BSS_CHANGED_HT) { 2370*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " HT: op_mode=0x%x\n", 2371*f79cbc77SKalle Valo info->ht_operation_mode); 2372*f79cbc77SKalle Valo } 2373*f79cbc77SKalle Valo 2374*f79cbc77SKalle Valo if (changed & BSS_CHANGED_BASIC_RATES) { 2375*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " BASIC_RATES: 0x%llx\n", 2376*f79cbc77SKalle Valo (unsigned long long) info->basic_rates); 2377*f79cbc77SKalle Valo } 2378*f79cbc77SKalle Valo 2379*f79cbc77SKalle Valo if (changed & BSS_CHANGED_TXPOWER) 2380*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, " TX Power: %d dBm\n", info->txpower); 2381*f79cbc77SKalle Valo } 2382*f79cbc77SKalle Valo 2383*f79cbc77SKalle Valo static void 2384*f79cbc77SKalle Valo mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw, 2385*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2386*f79cbc77SKalle Valo struct ieee80211_sta *sta, 2387*f79cbc77SKalle Valo u32 changed) 2388*f79cbc77SKalle Valo { 2389*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = hw->priv; 2390*f79cbc77SKalle Valo u32 bw = U32_MAX; 2391*f79cbc77SKalle Valo int link_id; 2392*f79cbc77SKalle Valo 2393*f79cbc77SKalle Valo rcu_read_lock(); 2394*f79cbc77SKalle Valo for (link_id = 0; 2395*f79cbc77SKalle Valo link_id < ARRAY_SIZE(vif->link_conf); 2396*f79cbc77SKalle Valo link_id++) { 2397*f79cbc77SKalle Valo enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT; 2398*f79cbc77SKalle Valo struct ieee80211_bss_conf *vif_conf; 2399*f79cbc77SKalle Valo struct ieee80211_link_sta *link_sta; 2400*f79cbc77SKalle Valo 2401*f79cbc77SKalle Valo link_sta = rcu_dereference(sta->link[link_id]); 2402*f79cbc77SKalle Valo 2403*f79cbc77SKalle Valo if (!link_sta) 2404*f79cbc77SKalle Valo continue; 2405*f79cbc77SKalle Valo 2406*f79cbc77SKalle Valo switch (link_sta->bandwidth) { 2407*f79cbc77SKalle Valo #define C(_bw) case IEEE80211_STA_RX_BW_##_bw: bw = _bw; break 2408*f79cbc77SKalle Valo C(20); 2409*f79cbc77SKalle Valo C(40); 2410*f79cbc77SKalle Valo C(80); 2411*f79cbc77SKalle Valo C(160); 2412*f79cbc77SKalle Valo C(320); 2413*f79cbc77SKalle Valo #undef C 2414*f79cbc77SKalle Valo } 2415*f79cbc77SKalle Valo 2416*f79cbc77SKalle Valo if (!data->use_chanctx) { 2417*f79cbc77SKalle Valo confbw = data->bw; 2418*f79cbc77SKalle Valo } else { 2419*f79cbc77SKalle Valo struct ieee80211_chanctx_conf *chanctx_conf; 2420*f79cbc77SKalle Valo 2421*f79cbc77SKalle Valo vif_conf = rcu_dereference(vif->link_conf[link_id]); 2422*f79cbc77SKalle Valo if (WARN_ON(!vif_conf)) 2423*f79cbc77SKalle Valo continue; 2424*f79cbc77SKalle Valo 2425*f79cbc77SKalle Valo chanctx_conf = rcu_dereference(vif_conf->chanctx_conf); 2426*f79cbc77SKalle Valo 2427*f79cbc77SKalle Valo if (!WARN_ON(!chanctx_conf)) 2428*f79cbc77SKalle Valo confbw = chanctx_conf->def.width; 2429*f79cbc77SKalle Valo } 2430*f79cbc77SKalle Valo 2431*f79cbc77SKalle Valo WARN(bw > hwsim_get_chanwidth(confbw), 2432*f79cbc77SKalle Valo "intf %pM [link=%d]: bad STA %pM bandwidth %d MHz (%d) > channel config %d MHz (%d)\n", 2433*f79cbc77SKalle Valo vif->addr, link_id, sta->addr, bw, sta->deflink.bandwidth, 2434*f79cbc77SKalle Valo hwsim_get_chanwidth(data->bw), data->bw); 2435*f79cbc77SKalle Valo 2436*f79cbc77SKalle Valo 2437*f79cbc77SKalle Valo } 2438*f79cbc77SKalle Valo rcu_read_unlock(); 2439*f79cbc77SKalle Valo 2440*f79cbc77SKalle Valo 2441*f79cbc77SKalle Valo } 2442*f79cbc77SKalle Valo 2443*f79cbc77SKalle Valo static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, 2444*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2445*f79cbc77SKalle Valo struct ieee80211_sta *sta) 2446*f79cbc77SKalle Valo { 2447*f79cbc77SKalle Valo struct hwsim_sta_priv *sp = (void *)sta->drv_priv; 2448*f79cbc77SKalle Valo 2449*f79cbc77SKalle Valo hwsim_check_magic(vif); 2450*f79cbc77SKalle Valo hwsim_set_sta_magic(sta); 2451*f79cbc77SKalle Valo mac80211_hwsim_sta_rc_update(hw, vif, sta, 0); 2452*f79cbc77SKalle Valo 2453*f79cbc77SKalle Valo if (sta->valid_links) { 2454*f79cbc77SKalle Valo WARN(hweight16(sta->valid_links) > 1, 2455*f79cbc77SKalle Valo "expect to add STA with single link, have 0x%x\n", 2456*f79cbc77SKalle Valo sta->valid_links); 2457*f79cbc77SKalle Valo sp->active_links_rx = sta->valid_links; 2458*f79cbc77SKalle Valo } 2459*f79cbc77SKalle Valo 2460*f79cbc77SKalle Valo return 0; 2461*f79cbc77SKalle Valo } 2462*f79cbc77SKalle Valo 2463*f79cbc77SKalle Valo static int mac80211_hwsim_sta_remove(struct ieee80211_hw *hw, 2464*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2465*f79cbc77SKalle Valo struct ieee80211_sta *sta) 2466*f79cbc77SKalle Valo { 2467*f79cbc77SKalle Valo hwsim_check_magic(vif); 2468*f79cbc77SKalle Valo hwsim_clear_sta_magic(sta); 2469*f79cbc77SKalle Valo 2470*f79cbc77SKalle Valo return 0; 2471*f79cbc77SKalle Valo } 2472*f79cbc77SKalle Valo 2473*f79cbc77SKalle Valo static int mac80211_hwsim_sta_state(struct ieee80211_hw *hw, 2474*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2475*f79cbc77SKalle Valo struct ieee80211_sta *sta, 2476*f79cbc77SKalle Valo enum ieee80211_sta_state old_state, 2477*f79cbc77SKalle Valo enum ieee80211_sta_state new_state) 2478*f79cbc77SKalle Valo { 2479*f79cbc77SKalle Valo if (new_state == IEEE80211_STA_NOTEXIST) 2480*f79cbc77SKalle Valo return mac80211_hwsim_sta_remove(hw, vif, sta); 2481*f79cbc77SKalle Valo 2482*f79cbc77SKalle Valo if (old_state == IEEE80211_STA_NOTEXIST) 2483*f79cbc77SKalle Valo return mac80211_hwsim_sta_add(hw, vif, sta); 2484*f79cbc77SKalle Valo 2485*f79cbc77SKalle Valo /* 2486*f79cbc77SKalle Valo * when client is authorized (AP station marked as such), 2487*f79cbc77SKalle Valo * enable all links 2488*f79cbc77SKalle Valo */ 2489*f79cbc77SKalle Valo if (vif->type == NL80211_IFTYPE_STATION && 2490*f79cbc77SKalle Valo new_state == IEEE80211_STA_AUTHORIZED && !sta->tdls) 2491*f79cbc77SKalle Valo ieee80211_set_active_links_async(vif, vif->valid_links); 2492*f79cbc77SKalle Valo 2493*f79cbc77SKalle Valo return 0; 2494*f79cbc77SKalle Valo } 2495*f79cbc77SKalle Valo 2496*f79cbc77SKalle Valo static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, 2497*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2498*f79cbc77SKalle Valo enum sta_notify_cmd cmd, 2499*f79cbc77SKalle Valo struct ieee80211_sta *sta) 2500*f79cbc77SKalle Valo { 2501*f79cbc77SKalle Valo hwsim_check_magic(vif); 2502*f79cbc77SKalle Valo 2503*f79cbc77SKalle Valo switch (cmd) { 2504*f79cbc77SKalle Valo case STA_NOTIFY_SLEEP: 2505*f79cbc77SKalle Valo case STA_NOTIFY_AWAKE: 2506*f79cbc77SKalle Valo /* TODO: make good use of these flags */ 2507*f79cbc77SKalle Valo break; 2508*f79cbc77SKalle Valo default: 2509*f79cbc77SKalle Valo WARN(1, "Invalid sta notify: %d\n", cmd); 2510*f79cbc77SKalle Valo break; 2511*f79cbc77SKalle Valo } 2512*f79cbc77SKalle Valo } 2513*f79cbc77SKalle Valo 2514*f79cbc77SKalle Valo static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw, 2515*f79cbc77SKalle Valo struct ieee80211_sta *sta, 2516*f79cbc77SKalle Valo bool set) 2517*f79cbc77SKalle Valo { 2518*f79cbc77SKalle Valo hwsim_check_sta_magic(sta); 2519*f79cbc77SKalle Valo return 0; 2520*f79cbc77SKalle Valo } 2521*f79cbc77SKalle Valo 2522*f79cbc77SKalle Valo static int mac80211_hwsim_conf_tx(struct ieee80211_hw *hw, 2523*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2524*f79cbc77SKalle Valo unsigned int link_id, u16 queue, 2525*f79cbc77SKalle Valo const struct ieee80211_tx_queue_params *params) 2526*f79cbc77SKalle Valo { 2527*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, 2528*f79cbc77SKalle Valo "%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n", 2529*f79cbc77SKalle Valo __func__, queue, 2530*f79cbc77SKalle Valo params->txop, params->cw_min, 2531*f79cbc77SKalle Valo params->cw_max, params->aifs); 2532*f79cbc77SKalle Valo return 0; 2533*f79cbc77SKalle Valo } 2534*f79cbc77SKalle Valo 2535*f79cbc77SKalle Valo static int mac80211_hwsim_get_survey(struct ieee80211_hw *hw, int idx, 2536*f79cbc77SKalle Valo struct survey_info *survey) 2537*f79cbc77SKalle Valo { 2538*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = hw->priv; 2539*f79cbc77SKalle Valo 2540*f79cbc77SKalle Valo if (idx < 0 || idx >= ARRAY_SIZE(hwsim->survey_data)) 2541*f79cbc77SKalle Valo return -ENOENT; 2542*f79cbc77SKalle Valo 2543*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2544*f79cbc77SKalle Valo survey->channel = hwsim->survey_data[idx].channel; 2545*f79cbc77SKalle Valo if (!survey->channel) { 2546*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2547*f79cbc77SKalle Valo return -ENOENT; 2548*f79cbc77SKalle Valo } 2549*f79cbc77SKalle Valo 2550*f79cbc77SKalle Valo /* 2551*f79cbc77SKalle Valo * Magically conjured dummy values --- this is only ok for simulated hardware. 2552*f79cbc77SKalle Valo * 2553*f79cbc77SKalle Valo * A real driver which cannot determine real values noise MUST NOT 2554*f79cbc77SKalle Valo * report any, especially not a magically conjured ones :-) 2555*f79cbc77SKalle Valo */ 2556*f79cbc77SKalle Valo survey->filled = SURVEY_INFO_NOISE_DBM | 2557*f79cbc77SKalle Valo SURVEY_INFO_TIME | 2558*f79cbc77SKalle Valo SURVEY_INFO_TIME_BUSY; 2559*f79cbc77SKalle Valo survey->noise = -92; 2560*f79cbc77SKalle Valo survey->time = 2561*f79cbc77SKalle Valo jiffies_to_msecs(hwsim->survey_data[idx].end - 2562*f79cbc77SKalle Valo hwsim->survey_data[idx].start); 2563*f79cbc77SKalle Valo /* report 12.5% of channel time is used */ 2564*f79cbc77SKalle Valo survey->time_busy = survey->time/8; 2565*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2566*f79cbc77SKalle Valo 2567*f79cbc77SKalle Valo return 0; 2568*f79cbc77SKalle Valo } 2569*f79cbc77SKalle Valo 2570*f79cbc77SKalle Valo #ifdef CONFIG_NL80211_TESTMODE 2571*f79cbc77SKalle Valo /* 2572*f79cbc77SKalle Valo * This section contains example code for using netlink 2573*f79cbc77SKalle Valo * attributes with the testmode command in nl80211. 2574*f79cbc77SKalle Valo */ 2575*f79cbc77SKalle Valo 2576*f79cbc77SKalle Valo /* These enums need to be kept in sync with userspace */ 2577*f79cbc77SKalle Valo enum hwsim_testmode_attr { 2578*f79cbc77SKalle Valo __HWSIM_TM_ATTR_INVALID = 0, 2579*f79cbc77SKalle Valo HWSIM_TM_ATTR_CMD = 1, 2580*f79cbc77SKalle Valo HWSIM_TM_ATTR_PS = 2, 2581*f79cbc77SKalle Valo 2582*f79cbc77SKalle Valo /* keep last */ 2583*f79cbc77SKalle Valo __HWSIM_TM_ATTR_AFTER_LAST, 2584*f79cbc77SKalle Valo HWSIM_TM_ATTR_MAX = __HWSIM_TM_ATTR_AFTER_LAST - 1 2585*f79cbc77SKalle Valo }; 2586*f79cbc77SKalle Valo 2587*f79cbc77SKalle Valo enum hwsim_testmode_cmd { 2588*f79cbc77SKalle Valo HWSIM_TM_CMD_SET_PS = 0, 2589*f79cbc77SKalle Valo HWSIM_TM_CMD_GET_PS = 1, 2590*f79cbc77SKalle Valo HWSIM_TM_CMD_STOP_QUEUES = 2, 2591*f79cbc77SKalle Valo HWSIM_TM_CMD_WAKE_QUEUES = 3, 2592*f79cbc77SKalle Valo }; 2593*f79cbc77SKalle Valo 2594*f79cbc77SKalle Valo static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = { 2595*f79cbc77SKalle Valo [HWSIM_TM_ATTR_CMD] = { .type = NLA_U32 }, 2596*f79cbc77SKalle Valo [HWSIM_TM_ATTR_PS] = { .type = NLA_U32 }, 2597*f79cbc77SKalle Valo }; 2598*f79cbc77SKalle Valo 2599*f79cbc77SKalle Valo static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, 2600*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2601*f79cbc77SKalle Valo void *data, int len) 2602*f79cbc77SKalle Valo { 2603*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = hw->priv; 2604*f79cbc77SKalle Valo struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1]; 2605*f79cbc77SKalle Valo struct sk_buff *skb; 2606*f79cbc77SKalle Valo int err, ps; 2607*f79cbc77SKalle Valo 2608*f79cbc77SKalle Valo err = nla_parse_deprecated(tb, HWSIM_TM_ATTR_MAX, data, len, 2609*f79cbc77SKalle Valo hwsim_testmode_policy, NULL); 2610*f79cbc77SKalle Valo if (err) 2611*f79cbc77SKalle Valo return err; 2612*f79cbc77SKalle Valo 2613*f79cbc77SKalle Valo if (!tb[HWSIM_TM_ATTR_CMD]) 2614*f79cbc77SKalle Valo return -EINVAL; 2615*f79cbc77SKalle Valo 2616*f79cbc77SKalle Valo switch (nla_get_u32(tb[HWSIM_TM_ATTR_CMD])) { 2617*f79cbc77SKalle Valo case HWSIM_TM_CMD_SET_PS: 2618*f79cbc77SKalle Valo if (!tb[HWSIM_TM_ATTR_PS]) 2619*f79cbc77SKalle Valo return -EINVAL; 2620*f79cbc77SKalle Valo ps = nla_get_u32(tb[HWSIM_TM_ATTR_PS]); 2621*f79cbc77SKalle Valo return hwsim_fops_ps_write(hwsim, ps); 2622*f79cbc77SKalle Valo case HWSIM_TM_CMD_GET_PS: 2623*f79cbc77SKalle Valo skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 2624*f79cbc77SKalle Valo nla_total_size(sizeof(u32))); 2625*f79cbc77SKalle Valo if (!skb) 2626*f79cbc77SKalle Valo return -ENOMEM; 2627*f79cbc77SKalle Valo if (nla_put_u32(skb, HWSIM_TM_ATTR_PS, hwsim->ps)) 2628*f79cbc77SKalle Valo goto nla_put_failure; 2629*f79cbc77SKalle Valo return cfg80211_testmode_reply(skb); 2630*f79cbc77SKalle Valo case HWSIM_TM_CMD_STOP_QUEUES: 2631*f79cbc77SKalle Valo ieee80211_stop_queues(hw); 2632*f79cbc77SKalle Valo return 0; 2633*f79cbc77SKalle Valo case HWSIM_TM_CMD_WAKE_QUEUES: 2634*f79cbc77SKalle Valo ieee80211_wake_queues(hw); 2635*f79cbc77SKalle Valo return 0; 2636*f79cbc77SKalle Valo default: 2637*f79cbc77SKalle Valo return -EOPNOTSUPP; 2638*f79cbc77SKalle Valo } 2639*f79cbc77SKalle Valo 2640*f79cbc77SKalle Valo nla_put_failure: 2641*f79cbc77SKalle Valo kfree_skb(skb); 2642*f79cbc77SKalle Valo return -ENOBUFS; 2643*f79cbc77SKalle Valo } 2644*f79cbc77SKalle Valo #endif 2645*f79cbc77SKalle Valo 2646*f79cbc77SKalle Valo static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, 2647*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2648*f79cbc77SKalle Valo struct ieee80211_ampdu_params *params) 2649*f79cbc77SKalle Valo { 2650*f79cbc77SKalle Valo struct ieee80211_sta *sta = params->sta; 2651*f79cbc77SKalle Valo enum ieee80211_ampdu_mlme_action action = params->action; 2652*f79cbc77SKalle Valo u16 tid = params->tid; 2653*f79cbc77SKalle Valo 2654*f79cbc77SKalle Valo switch (action) { 2655*f79cbc77SKalle Valo case IEEE80211_AMPDU_TX_START: 2656*f79cbc77SKalle Valo return IEEE80211_AMPDU_TX_START_IMMEDIATE; 2657*f79cbc77SKalle Valo case IEEE80211_AMPDU_TX_STOP_CONT: 2658*f79cbc77SKalle Valo case IEEE80211_AMPDU_TX_STOP_FLUSH: 2659*f79cbc77SKalle Valo case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 2660*f79cbc77SKalle Valo ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 2661*f79cbc77SKalle Valo break; 2662*f79cbc77SKalle Valo case IEEE80211_AMPDU_TX_OPERATIONAL: 2663*f79cbc77SKalle Valo break; 2664*f79cbc77SKalle Valo case IEEE80211_AMPDU_RX_START: 2665*f79cbc77SKalle Valo case IEEE80211_AMPDU_RX_STOP: 2666*f79cbc77SKalle Valo break; 2667*f79cbc77SKalle Valo default: 2668*f79cbc77SKalle Valo return -EOPNOTSUPP; 2669*f79cbc77SKalle Valo } 2670*f79cbc77SKalle Valo 2671*f79cbc77SKalle Valo return 0; 2672*f79cbc77SKalle Valo } 2673*f79cbc77SKalle Valo 2674*f79cbc77SKalle Valo static void mac80211_hwsim_flush(struct ieee80211_hw *hw, 2675*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2676*f79cbc77SKalle Valo u32 queues, bool drop) 2677*f79cbc77SKalle Valo { 2678*f79cbc77SKalle Valo /* Not implemented, queues only on kernel side */ 2679*f79cbc77SKalle Valo } 2680*f79cbc77SKalle Valo 2681*f79cbc77SKalle Valo static void hw_scan_work(struct work_struct *work) 2682*f79cbc77SKalle Valo { 2683*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = 2684*f79cbc77SKalle Valo container_of(work, struct mac80211_hwsim_data, hw_scan.work); 2685*f79cbc77SKalle Valo struct cfg80211_scan_request *req = hwsim->hw_scan_request; 2686*f79cbc77SKalle Valo int dwell, i; 2687*f79cbc77SKalle Valo 2688*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2689*f79cbc77SKalle Valo if (hwsim->scan_chan_idx >= req->n_channels) { 2690*f79cbc77SKalle Valo struct cfg80211_scan_info info = { 2691*f79cbc77SKalle Valo .aborted = false, 2692*f79cbc77SKalle Valo }; 2693*f79cbc77SKalle Valo 2694*f79cbc77SKalle Valo wiphy_dbg(hwsim->hw->wiphy, "hw scan complete\n"); 2695*f79cbc77SKalle Valo ieee80211_scan_completed(hwsim->hw, &info); 2696*f79cbc77SKalle Valo hwsim->hw_scan_request = NULL; 2697*f79cbc77SKalle Valo hwsim->hw_scan_vif = NULL; 2698*f79cbc77SKalle Valo hwsim->tmp_chan = NULL; 2699*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2700*f79cbc77SKalle Valo mac80211_hwsim_config_mac_nl(hwsim->hw, hwsim->scan_addr, 2701*f79cbc77SKalle Valo false); 2702*f79cbc77SKalle Valo return; 2703*f79cbc77SKalle Valo } 2704*f79cbc77SKalle Valo 2705*f79cbc77SKalle Valo wiphy_dbg(hwsim->hw->wiphy, "hw scan %d MHz\n", 2706*f79cbc77SKalle Valo req->channels[hwsim->scan_chan_idx]->center_freq); 2707*f79cbc77SKalle Valo 2708*f79cbc77SKalle Valo hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx]; 2709*f79cbc77SKalle Valo if (hwsim->tmp_chan->flags & (IEEE80211_CHAN_NO_IR | 2710*f79cbc77SKalle Valo IEEE80211_CHAN_RADAR) || 2711*f79cbc77SKalle Valo !req->n_ssids) { 2712*f79cbc77SKalle Valo dwell = 120; 2713*f79cbc77SKalle Valo } else { 2714*f79cbc77SKalle Valo dwell = 30; 2715*f79cbc77SKalle Valo /* send probes */ 2716*f79cbc77SKalle Valo for (i = 0; i < req->n_ssids; i++) { 2717*f79cbc77SKalle Valo struct sk_buff *probe; 2718*f79cbc77SKalle Valo struct ieee80211_mgmt *mgmt; 2719*f79cbc77SKalle Valo 2720*f79cbc77SKalle Valo probe = ieee80211_probereq_get(hwsim->hw, 2721*f79cbc77SKalle Valo hwsim->scan_addr, 2722*f79cbc77SKalle Valo req->ssids[i].ssid, 2723*f79cbc77SKalle Valo req->ssids[i].ssid_len, 2724*f79cbc77SKalle Valo req->ie_len); 2725*f79cbc77SKalle Valo if (!probe) 2726*f79cbc77SKalle Valo continue; 2727*f79cbc77SKalle Valo 2728*f79cbc77SKalle Valo mgmt = (struct ieee80211_mgmt *) probe->data; 2729*f79cbc77SKalle Valo memcpy(mgmt->da, req->bssid, ETH_ALEN); 2730*f79cbc77SKalle Valo memcpy(mgmt->bssid, req->bssid, ETH_ALEN); 2731*f79cbc77SKalle Valo 2732*f79cbc77SKalle Valo if (req->ie_len) 2733*f79cbc77SKalle Valo skb_put_data(probe, req->ie, req->ie_len); 2734*f79cbc77SKalle Valo 2735*f79cbc77SKalle Valo rcu_read_lock(); 2736*f79cbc77SKalle Valo if (!ieee80211_tx_prepare_skb(hwsim->hw, 2737*f79cbc77SKalle Valo hwsim->hw_scan_vif, 2738*f79cbc77SKalle Valo probe, 2739*f79cbc77SKalle Valo hwsim->tmp_chan->band, 2740*f79cbc77SKalle Valo NULL)) { 2741*f79cbc77SKalle Valo rcu_read_unlock(); 2742*f79cbc77SKalle Valo kfree_skb(probe); 2743*f79cbc77SKalle Valo continue; 2744*f79cbc77SKalle Valo } 2745*f79cbc77SKalle Valo 2746*f79cbc77SKalle Valo local_bh_disable(); 2747*f79cbc77SKalle Valo mac80211_hwsim_tx_frame(hwsim->hw, probe, 2748*f79cbc77SKalle Valo hwsim->tmp_chan); 2749*f79cbc77SKalle Valo rcu_read_unlock(); 2750*f79cbc77SKalle Valo local_bh_enable(); 2751*f79cbc77SKalle Valo } 2752*f79cbc77SKalle Valo } 2753*f79cbc77SKalle Valo ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 2754*f79cbc77SKalle Valo msecs_to_jiffies(dwell)); 2755*f79cbc77SKalle Valo hwsim->survey_data[hwsim->scan_chan_idx].channel = hwsim->tmp_chan; 2756*f79cbc77SKalle Valo hwsim->survey_data[hwsim->scan_chan_idx].start = jiffies; 2757*f79cbc77SKalle Valo hwsim->survey_data[hwsim->scan_chan_idx].end = 2758*f79cbc77SKalle Valo jiffies + msecs_to_jiffies(dwell); 2759*f79cbc77SKalle Valo hwsim->scan_chan_idx++; 2760*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2761*f79cbc77SKalle Valo } 2762*f79cbc77SKalle Valo 2763*f79cbc77SKalle Valo static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, 2764*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2765*f79cbc77SKalle Valo struct ieee80211_scan_request *hw_req) 2766*f79cbc77SKalle Valo { 2767*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = hw->priv; 2768*f79cbc77SKalle Valo struct cfg80211_scan_request *req = &hw_req->req; 2769*f79cbc77SKalle Valo 2770*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2771*f79cbc77SKalle Valo if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) { 2772*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2773*f79cbc77SKalle Valo return -EBUSY; 2774*f79cbc77SKalle Valo } 2775*f79cbc77SKalle Valo hwsim->hw_scan_request = req; 2776*f79cbc77SKalle Valo hwsim->hw_scan_vif = vif; 2777*f79cbc77SKalle Valo hwsim->scan_chan_idx = 0; 2778*f79cbc77SKalle Valo if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) 2779*f79cbc77SKalle Valo get_random_mask_addr(hwsim->scan_addr, 2780*f79cbc77SKalle Valo hw_req->req.mac_addr, 2781*f79cbc77SKalle Valo hw_req->req.mac_addr_mask); 2782*f79cbc77SKalle Valo else 2783*f79cbc77SKalle Valo memcpy(hwsim->scan_addr, vif->addr, ETH_ALEN); 2784*f79cbc77SKalle Valo memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); 2785*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2786*f79cbc77SKalle Valo 2787*f79cbc77SKalle Valo mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true); 2788*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "hwsim hw_scan request\n"); 2789*f79cbc77SKalle Valo 2790*f79cbc77SKalle Valo ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0); 2791*f79cbc77SKalle Valo 2792*f79cbc77SKalle Valo return 0; 2793*f79cbc77SKalle Valo } 2794*f79cbc77SKalle Valo 2795*f79cbc77SKalle Valo static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw, 2796*f79cbc77SKalle Valo struct ieee80211_vif *vif) 2797*f79cbc77SKalle Valo { 2798*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = hw->priv; 2799*f79cbc77SKalle Valo struct cfg80211_scan_info info = { 2800*f79cbc77SKalle Valo .aborted = true, 2801*f79cbc77SKalle Valo }; 2802*f79cbc77SKalle Valo 2803*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "hwsim cancel_hw_scan\n"); 2804*f79cbc77SKalle Valo 2805*f79cbc77SKalle Valo cancel_delayed_work_sync(&hwsim->hw_scan); 2806*f79cbc77SKalle Valo 2807*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2808*f79cbc77SKalle Valo ieee80211_scan_completed(hwsim->hw, &info); 2809*f79cbc77SKalle Valo hwsim->tmp_chan = NULL; 2810*f79cbc77SKalle Valo hwsim->hw_scan_request = NULL; 2811*f79cbc77SKalle Valo hwsim->hw_scan_vif = NULL; 2812*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2813*f79cbc77SKalle Valo } 2814*f79cbc77SKalle Valo 2815*f79cbc77SKalle Valo static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw, 2816*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2817*f79cbc77SKalle Valo const u8 *mac_addr) 2818*f79cbc77SKalle Valo { 2819*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = hw->priv; 2820*f79cbc77SKalle Valo 2821*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2822*f79cbc77SKalle Valo 2823*f79cbc77SKalle Valo if (hwsim->scanning) { 2824*f79cbc77SKalle Valo pr_debug("two hwsim sw_scans detected!\n"); 2825*f79cbc77SKalle Valo goto out; 2826*f79cbc77SKalle Valo } 2827*f79cbc77SKalle Valo 2828*f79cbc77SKalle Valo pr_debug("hwsim sw_scan request, prepping stuff\n"); 2829*f79cbc77SKalle Valo 2830*f79cbc77SKalle Valo memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); 2831*f79cbc77SKalle Valo mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true); 2832*f79cbc77SKalle Valo hwsim->scanning = true; 2833*f79cbc77SKalle Valo memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); 2834*f79cbc77SKalle Valo 2835*f79cbc77SKalle Valo out: 2836*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2837*f79cbc77SKalle Valo } 2838*f79cbc77SKalle Valo 2839*f79cbc77SKalle Valo static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw, 2840*f79cbc77SKalle Valo struct ieee80211_vif *vif) 2841*f79cbc77SKalle Valo { 2842*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = hw->priv; 2843*f79cbc77SKalle Valo 2844*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2845*f79cbc77SKalle Valo 2846*f79cbc77SKalle Valo pr_debug("hwsim sw_scan_complete\n"); 2847*f79cbc77SKalle Valo hwsim->scanning = false; 2848*f79cbc77SKalle Valo mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, false); 2849*f79cbc77SKalle Valo eth_zero_addr(hwsim->scan_addr); 2850*f79cbc77SKalle Valo 2851*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2852*f79cbc77SKalle Valo } 2853*f79cbc77SKalle Valo 2854*f79cbc77SKalle Valo static void hw_roc_start(struct work_struct *work) 2855*f79cbc77SKalle Valo { 2856*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = 2857*f79cbc77SKalle Valo container_of(work, struct mac80211_hwsim_data, roc_start.work); 2858*f79cbc77SKalle Valo 2859*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2860*f79cbc77SKalle Valo 2861*f79cbc77SKalle Valo wiphy_dbg(hwsim->hw->wiphy, "hwsim ROC begins\n"); 2862*f79cbc77SKalle Valo hwsim->tmp_chan = hwsim->roc_chan; 2863*f79cbc77SKalle Valo ieee80211_ready_on_channel(hwsim->hw); 2864*f79cbc77SKalle Valo 2865*f79cbc77SKalle Valo ieee80211_queue_delayed_work(hwsim->hw, &hwsim->roc_done, 2866*f79cbc77SKalle Valo msecs_to_jiffies(hwsim->roc_duration)); 2867*f79cbc77SKalle Valo 2868*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2869*f79cbc77SKalle Valo } 2870*f79cbc77SKalle Valo 2871*f79cbc77SKalle Valo static void hw_roc_done(struct work_struct *work) 2872*f79cbc77SKalle Valo { 2873*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = 2874*f79cbc77SKalle Valo container_of(work, struct mac80211_hwsim_data, roc_done.work); 2875*f79cbc77SKalle Valo 2876*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2877*f79cbc77SKalle Valo ieee80211_remain_on_channel_expired(hwsim->hw); 2878*f79cbc77SKalle Valo hwsim->tmp_chan = NULL; 2879*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2880*f79cbc77SKalle Valo 2881*f79cbc77SKalle Valo wiphy_dbg(hwsim->hw->wiphy, "hwsim ROC expired\n"); 2882*f79cbc77SKalle Valo } 2883*f79cbc77SKalle Valo 2884*f79cbc77SKalle Valo static int mac80211_hwsim_roc(struct ieee80211_hw *hw, 2885*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2886*f79cbc77SKalle Valo struct ieee80211_channel *chan, 2887*f79cbc77SKalle Valo int duration, 2888*f79cbc77SKalle Valo enum ieee80211_roc_type type) 2889*f79cbc77SKalle Valo { 2890*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = hw->priv; 2891*f79cbc77SKalle Valo 2892*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2893*f79cbc77SKalle Valo if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) { 2894*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2895*f79cbc77SKalle Valo return -EBUSY; 2896*f79cbc77SKalle Valo } 2897*f79cbc77SKalle Valo 2898*f79cbc77SKalle Valo hwsim->roc_chan = chan; 2899*f79cbc77SKalle Valo hwsim->roc_duration = duration; 2900*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2901*f79cbc77SKalle Valo 2902*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "hwsim ROC (%d MHz, %d ms)\n", 2903*f79cbc77SKalle Valo chan->center_freq, duration); 2904*f79cbc77SKalle Valo ieee80211_queue_delayed_work(hw, &hwsim->roc_start, HZ/50); 2905*f79cbc77SKalle Valo 2906*f79cbc77SKalle Valo return 0; 2907*f79cbc77SKalle Valo } 2908*f79cbc77SKalle Valo 2909*f79cbc77SKalle Valo static int mac80211_hwsim_croc(struct ieee80211_hw *hw, 2910*f79cbc77SKalle Valo struct ieee80211_vif *vif) 2911*f79cbc77SKalle Valo { 2912*f79cbc77SKalle Valo struct mac80211_hwsim_data *hwsim = hw->priv; 2913*f79cbc77SKalle Valo 2914*f79cbc77SKalle Valo cancel_delayed_work_sync(&hwsim->roc_start); 2915*f79cbc77SKalle Valo cancel_delayed_work_sync(&hwsim->roc_done); 2916*f79cbc77SKalle Valo 2917*f79cbc77SKalle Valo mutex_lock(&hwsim->mutex); 2918*f79cbc77SKalle Valo hwsim->tmp_chan = NULL; 2919*f79cbc77SKalle Valo mutex_unlock(&hwsim->mutex); 2920*f79cbc77SKalle Valo 2921*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "hwsim ROC canceled\n"); 2922*f79cbc77SKalle Valo 2923*f79cbc77SKalle Valo return 0; 2924*f79cbc77SKalle Valo } 2925*f79cbc77SKalle Valo 2926*f79cbc77SKalle Valo static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, 2927*f79cbc77SKalle Valo struct ieee80211_chanctx_conf *ctx) 2928*f79cbc77SKalle Valo { 2929*f79cbc77SKalle Valo hwsim_set_chanctx_magic(ctx); 2930*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, 2931*f79cbc77SKalle Valo "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", 2932*f79cbc77SKalle Valo ctx->def.chan->center_freq, ctx->def.width, 2933*f79cbc77SKalle Valo ctx->def.center_freq1, ctx->def.center_freq2); 2934*f79cbc77SKalle Valo return 0; 2935*f79cbc77SKalle Valo } 2936*f79cbc77SKalle Valo 2937*f79cbc77SKalle Valo static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, 2938*f79cbc77SKalle Valo struct ieee80211_chanctx_conf *ctx) 2939*f79cbc77SKalle Valo { 2940*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, 2941*f79cbc77SKalle Valo "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", 2942*f79cbc77SKalle Valo ctx->def.chan->center_freq, ctx->def.width, 2943*f79cbc77SKalle Valo ctx->def.center_freq1, ctx->def.center_freq2); 2944*f79cbc77SKalle Valo hwsim_check_chanctx_magic(ctx); 2945*f79cbc77SKalle Valo hwsim_clear_chanctx_magic(ctx); 2946*f79cbc77SKalle Valo } 2947*f79cbc77SKalle Valo 2948*f79cbc77SKalle Valo static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw, 2949*f79cbc77SKalle Valo struct ieee80211_chanctx_conf *ctx, 2950*f79cbc77SKalle Valo u32 changed) 2951*f79cbc77SKalle Valo { 2952*f79cbc77SKalle Valo hwsim_check_chanctx_magic(ctx); 2953*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, 2954*f79cbc77SKalle Valo "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", 2955*f79cbc77SKalle Valo ctx->def.chan->center_freq, ctx->def.width, 2956*f79cbc77SKalle Valo ctx->def.center_freq1, ctx->def.center_freq2); 2957*f79cbc77SKalle Valo } 2958*f79cbc77SKalle Valo 2959*f79cbc77SKalle Valo static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw, 2960*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2961*f79cbc77SKalle Valo struct ieee80211_bss_conf *link_conf, 2962*f79cbc77SKalle Valo struct ieee80211_chanctx_conf *ctx) 2963*f79cbc77SKalle Valo { 2964*f79cbc77SKalle Valo hwsim_check_magic(vif); 2965*f79cbc77SKalle Valo hwsim_check_chanctx_magic(ctx); 2966*f79cbc77SKalle Valo 2967*f79cbc77SKalle Valo /* if we activate a link while already associated wake it up */ 2968*f79cbc77SKalle Valo if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc) { 2969*f79cbc77SKalle Valo struct sk_buff *skb; 2970*f79cbc77SKalle Valo 2971*f79cbc77SKalle Valo skb = ieee80211_nullfunc_get(hw, vif, link_conf->link_id, true); 2972*f79cbc77SKalle Valo if (skb) { 2973*f79cbc77SKalle Valo local_bh_disable(); 2974*f79cbc77SKalle Valo mac80211_hwsim_tx_frame(hw, skb, ctx->def.chan); 2975*f79cbc77SKalle Valo local_bh_enable(); 2976*f79cbc77SKalle Valo } 2977*f79cbc77SKalle Valo } 2978*f79cbc77SKalle Valo 2979*f79cbc77SKalle Valo return 0; 2980*f79cbc77SKalle Valo } 2981*f79cbc77SKalle Valo 2982*f79cbc77SKalle Valo static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw, 2983*f79cbc77SKalle Valo struct ieee80211_vif *vif, 2984*f79cbc77SKalle Valo struct ieee80211_bss_conf *link_conf, 2985*f79cbc77SKalle Valo struct ieee80211_chanctx_conf *ctx) 2986*f79cbc77SKalle Valo { 2987*f79cbc77SKalle Valo hwsim_check_magic(vif); 2988*f79cbc77SKalle Valo hwsim_check_chanctx_magic(ctx); 2989*f79cbc77SKalle Valo 2990*f79cbc77SKalle Valo /* if we deactivate a link while associated suspend it first */ 2991*f79cbc77SKalle Valo if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc) { 2992*f79cbc77SKalle Valo struct sk_buff *skb; 2993*f79cbc77SKalle Valo 2994*f79cbc77SKalle Valo skb = ieee80211_nullfunc_get(hw, vif, link_conf->link_id, true); 2995*f79cbc77SKalle Valo if (skb) { 2996*f79cbc77SKalle Valo struct ieee80211_hdr *hdr = (void *)skb->data; 2997*f79cbc77SKalle Valo 2998*f79cbc77SKalle Valo hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); 2999*f79cbc77SKalle Valo 3000*f79cbc77SKalle Valo local_bh_disable(); 3001*f79cbc77SKalle Valo mac80211_hwsim_tx_frame(hw, skb, ctx->def.chan); 3002*f79cbc77SKalle Valo local_bh_enable(); 3003*f79cbc77SKalle Valo } 3004*f79cbc77SKalle Valo } 3005*f79cbc77SKalle Valo } 3006*f79cbc77SKalle Valo 3007*f79cbc77SKalle Valo static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = { 3008*f79cbc77SKalle Valo "tx_pkts_nic", 3009*f79cbc77SKalle Valo "tx_bytes_nic", 3010*f79cbc77SKalle Valo "rx_pkts_nic", 3011*f79cbc77SKalle Valo "rx_bytes_nic", 3012*f79cbc77SKalle Valo "d_tx_dropped", 3013*f79cbc77SKalle Valo "d_tx_failed", 3014*f79cbc77SKalle Valo "d_ps_mode", 3015*f79cbc77SKalle Valo "d_group", 3016*f79cbc77SKalle Valo }; 3017*f79cbc77SKalle Valo 3018*f79cbc77SKalle Valo #define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats) 3019*f79cbc77SKalle Valo 3020*f79cbc77SKalle Valo static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw, 3021*f79cbc77SKalle Valo struct ieee80211_vif *vif, 3022*f79cbc77SKalle Valo u32 sset, u8 *data) 3023*f79cbc77SKalle Valo { 3024*f79cbc77SKalle Valo if (sset == ETH_SS_STATS) 3025*f79cbc77SKalle Valo memcpy(data, *mac80211_hwsim_gstrings_stats, 3026*f79cbc77SKalle Valo sizeof(mac80211_hwsim_gstrings_stats)); 3027*f79cbc77SKalle Valo } 3028*f79cbc77SKalle Valo 3029*f79cbc77SKalle Valo static int mac80211_hwsim_get_et_sset_count(struct ieee80211_hw *hw, 3030*f79cbc77SKalle Valo struct ieee80211_vif *vif, int sset) 3031*f79cbc77SKalle Valo { 3032*f79cbc77SKalle Valo if (sset == ETH_SS_STATS) 3033*f79cbc77SKalle Valo return MAC80211_HWSIM_SSTATS_LEN; 3034*f79cbc77SKalle Valo return 0; 3035*f79cbc77SKalle Valo } 3036*f79cbc77SKalle Valo 3037*f79cbc77SKalle Valo static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw, 3038*f79cbc77SKalle Valo struct ieee80211_vif *vif, 3039*f79cbc77SKalle Valo struct ethtool_stats *stats, u64 *data) 3040*f79cbc77SKalle Valo { 3041*f79cbc77SKalle Valo struct mac80211_hwsim_data *ar = hw->priv; 3042*f79cbc77SKalle Valo int i = 0; 3043*f79cbc77SKalle Valo 3044*f79cbc77SKalle Valo data[i++] = ar->tx_pkts; 3045*f79cbc77SKalle Valo data[i++] = ar->tx_bytes; 3046*f79cbc77SKalle Valo data[i++] = ar->rx_pkts; 3047*f79cbc77SKalle Valo data[i++] = ar->rx_bytes; 3048*f79cbc77SKalle Valo data[i++] = ar->tx_dropped; 3049*f79cbc77SKalle Valo data[i++] = ar->tx_failed; 3050*f79cbc77SKalle Valo data[i++] = ar->ps; 3051*f79cbc77SKalle Valo data[i++] = ar->group; 3052*f79cbc77SKalle Valo 3053*f79cbc77SKalle Valo WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); 3054*f79cbc77SKalle Valo } 3055*f79cbc77SKalle Valo 3056*f79cbc77SKalle Valo static int mac80211_hwsim_tx_last_beacon(struct ieee80211_hw *hw) 3057*f79cbc77SKalle Valo { 3058*f79cbc77SKalle Valo return 1; 3059*f79cbc77SKalle Valo } 3060*f79cbc77SKalle Valo 3061*f79cbc77SKalle Valo static int mac80211_hwsim_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 3062*f79cbc77SKalle Valo { 3063*f79cbc77SKalle Valo return -EOPNOTSUPP; 3064*f79cbc77SKalle Valo } 3065*f79cbc77SKalle Valo 3066*f79cbc77SKalle Valo static int mac80211_hwsim_change_vif_links(struct ieee80211_hw *hw, 3067*f79cbc77SKalle Valo struct ieee80211_vif *vif, 3068*f79cbc77SKalle Valo u16 old_links, u16 new_links, 3069*f79cbc77SKalle Valo struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS]) 3070*f79cbc77SKalle Valo { 3071*f79cbc77SKalle Valo unsigned long rem = old_links & ~new_links; 3072*f79cbc77SKalle Valo unsigned long add = new_links & ~old_links; 3073*f79cbc77SKalle Valo int i; 3074*f79cbc77SKalle Valo 3075*f79cbc77SKalle Valo if (!old_links) 3076*f79cbc77SKalle Valo rem |= BIT(0); 3077*f79cbc77SKalle Valo if (!new_links) 3078*f79cbc77SKalle Valo add |= BIT(0); 3079*f79cbc77SKalle Valo 3080*f79cbc77SKalle Valo for_each_set_bit(i, &rem, IEEE80211_MLD_MAX_NUM_LINKS) 3081*f79cbc77SKalle Valo mac80211_hwsim_config_mac_nl(hw, old[i]->addr, false); 3082*f79cbc77SKalle Valo 3083*f79cbc77SKalle Valo for_each_set_bit(i, &add, IEEE80211_MLD_MAX_NUM_LINKS) { 3084*f79cbc77SKalle Valo struct ieee80211_bss_conf *link_conf; 3085*f79cbc77SKalle Valo 3086*f79cbc77SKalle Valo link_conf = link_conf_dereference_protected(vif, i); 3087*f79cbc77SKalle Valo if (WARN_ON(!link_conf)) 3088*f79cbc77SKalle Valo continue; 3089*f79cbc77SKalle Valo 3090*f79cbc77SKalle Valo mac80211_hwsim_config_mac_nl(hw, link_conf->addr, true); 3091*f79cbc77SKalle Valo } 3092*f79cbc77SKalle Valo 3093*f79cbc77SKalle Valo return 0; 3094*f79cbc77SKalle Valo } 3095*f79cbc77SKalle Valo 3096*f79cbc77SKalle Valo static int mac80211_hwsim_change_sta_links(struct ieee80211_hw *hw, 3097*f79cbc77SKalle Valo struct ieee80211_vif *vif, 3098*f79cbc77SKalle Valo struct ieee80211_sta *sta, 3099*f79cbc77SKalle Valo u16 old_links, u16 new_links) 3100*f79cbc77SKalle Valo { 3101*f79cbc77SKalle Valo struct hwsim_sta_priv *sp = (void *)sta->drv_priv; 3102*f79cbc77SKalle Valo 3103*f79cbc77SKalle Valo hwsim_check_sta_magic(sta); 3104*f79cbc77SKalle Valo 3105*f79cbc77SKalle Valo if (vif->type == NL80211_IFTYPE_STATION) 3106*f79cbc77SKalle Valo sp->active_links_rx = new_links; 3107*f79cbc77SKalle Valo 3108*f79cbc77SKalle Valo return 0; 3109*f79cbc77SKalle Valo } 3110*f79cbc77SKalle Valo 3111*f79cbc77SKalle Valo #define HWSIM_COMMON_OPS \ 3112*f79cbc77SKalle Valo .tx = mac80211_hwsim_tx, \ 3113*f79cbc77SKalle Valo .wake_tx_queue = ieee80211_handle_wake_tx_queue, \ 3114*f79cbc77SKalle Valo .start = mac80211_hwsim_start, \ 3115*f79cbc77SKalle Valo .stop = mac80211_hwsim_stop, \ 3116*f79cbc77SKalle Valo .add_interface = mac80211_hwsim_add_interface, \ 3117*f79cbc77SKalle Valo .change_interface = mac80211_hwsim_change_interface, \ 3118*f79cbc77SKalle Valo .remove_interface = mac80211_hwsim_remove_interface, \ 3119*f79cbc77SKalle Valo .config = mac80211_hwsim_config, \ 3120*f79cbc77SKalle Valo .configure_filter = mac80211_hwsim_configure_filter, \ 3121*f79cbc77SKalle Valo .vif_cfg_changed = mac80211_hwsim_vif_info_changed, \ 3122*f79cbc77SKalle Valo .link_info_changed = mac80211_hwsim_link_info_changed, \ 3123*f79cbc77SKalle Valo .tx_last_beacon = mac80211_hwsim_tx_last_beacon, \ 3124*f79cbc77SKalle Valo .sta_notify = mac80211_hwsim_sta_notify, \ 3125*f79cbc77SKalle Valo .sta_rc_update = mac80211_hwsim_sta_rc_update, \ 3126*f79cbc77SKalle Valo .conf_tx = mac80211_hwsim_conf_tx, \ 3127*f79cbc77SKalle Valo .get_survey = mac80211_hwsim_get_survey, \ 3128*f79cbc77SKalle Valo CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) \ 3129*f79cbc77SKalle Valo .ampdu_action = mac80211_hwsim_ampdu_action, \ 3130*f79cbc77SKalle Valo .flush = mac80211_hwsim_flush, \ 3131*f79cbc77SKalle Valo .get_et_sset_count = mac80211_hwsim_get_et_sset_count, \ 3132*f79cbc77SKalle Valo .get_et_stats = mac80211_hwsim_get_et_stats, \ 3133*f79cbc77SKalle Valo .get_et_strings = mac80211_hwsim_get_et_strings, 3134*f79cbc77SKalle Valo 3135*f79cbc77SKalle Valo #define HWSIM_NON_MLO_OPS \ 3136*f79cbc77SKalle Valo .sta_add = mac80211_hwsim_sta_add, \ 3137*f79cbc77SKalle Valo .sta_remove = mac80211_hwsim_sta_remove, \ 3138*f79cbc77SKalle Valo .set_tim = mac80211_hwsim_set_tim, \ 3139*f79cbc77SKalle Valo .get_tsf = mac80211_hwsim_get_tsf, \ 3140*f79cbc77SKalle Valo .set_tsf = mac80211_hwsim_set_tsf, 3141*f79cbc77SKalle Valo 3142*f79cbc77SKalle Valo static const struct ieee80211_ops mac80211_hwsim_ops = { 3143*f79cbc77SKalle Valo HWSIM_COMMON_OPS 3144*f79cbc77SKalle Valo HWSIM_NON_MLO_OPS 3145*f79cbc77SKalle Valo .sw_scan_start = mac80211_hwsim_sw_scan, 3146*f79cbc77SKalle Valo .sw_scan_complete = mac80211_hwsim_sw_scan_complete, 3147*f79cbc77SKalle Valo }; 3148*f79cbc77SKalle Valo 3149*f79cbc77SKalle Valo #define HWSIM_CHANCTX_OPS \ 3150*f79cbc77SKalle Valo .hw_scan = mac80211_hwsim_hw_scan, \ 3151*f79cbc77SKalle Valo .cancel_hw_scan = mac80211_hwsim_cancel_hw_scan, \ 3152*f79cbc77SKalle Valo .remain_on_channel = mac80211_hwsim_roc, \ 3153*f79cbc77SKalle Valo .cancel_remain_on_channel = mac80211_hwsim_croc, \ 3154*f79cbc77SKalle Valo .add_chanctx = mac80211_hwsim_add_chanctx, \ 3155*f79cbc77SKalle Valo .remove_chanctx = mac80211_hwsim_remove_chanctx, \ 3156*f79cbc77SKalle Valo .change_chanctx = mac80211_hwsim_change_chanctx, \ 3157*f79cbc77SKalle Valo .assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx,\ 3158*f79cbc77SKalle Valo .unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx, 3159*f79cbc77SKalle Valo 3160*f79cbc77SKalle Valo static const struct ieee80211_ops mac80211_hwsim_mchan_ops = { 3161*f79cbc77SKalle Valo HWSIM_COMMON_OPS 3162*f79cbc77SKalle Valo HWSIM_NON_MLO_OPS 3163*f79cbc77SKalle Valo HWSIM_CHANCTX_OPS 3164*f79cbc77SKalle Valo }; 3165*f79cbc77SKalle Valo 3166*f79cbc77SKalle Valo static const struct ieee80211_ops mac80211_hwsim_mlo_ops = { 3167*f79cbc77SKalle Valo HWSIM_COMMON_OPS 3168*f79cbc77SKalle Valo HWSIM_CHANCTX_OPS 3169*f79cbc77SKalle Valo .set_rts_threshold = mac80211_hwsim_set_rts_threshold, 3170*f79cbc77SKalle Valo .change_vif_links = mac80211_hwsim_change_vif_links, 3171*f79cbc77SKalle Valo .change_sta_links = mac80211_hwsim_change_sta_links, 3172*f79cbc77SKalle Valo .sta_state = mac80211_hwsim_sta_state, 3173*f79cbc77SKalle Valo }; 3174*f79cbc77SKalle Valo 3175*f79cbc77SKalle Valo struct hwsim_new_radio_params { 3176*f79cbc77SKalle Valo unsigned int channels; 3177*f79cbc77SKalle Valo const char *reg_alpha2; 3178*f79cbc77SKalle Valo const struct ieee80211_regdomain *regd; 3179*f79cbc77SKalle Valo bool reg_strict; 3180*f79cbc77SKalle Valo bool p2p_device; 3181*f79cbc77SKalle Valo bool use_chanctx; 3182*f79cbc77SKalle Valo bool destroy_on_close; 3183*f79cbc77SKalle Valo const char *hwname; 3184*f79cbc77SKalle Valo bool no_vif; 3185*f79cbc77SKalle Valo const u8 *perm_addr; 3186*f79cbc77SKalle Valo u32 iftypes; 3187*f79cbc77SKalle Valo u32 *ciphers; 3188*f79cbc77SKalle Valo u8 n_ciphers; 3189*f79cbc77SKalle Valo bool mlo; 3190*f79cbc77SKalle Valo }; 3191*f79cbc77SKalle Valo 3192*f79cbc77SKalle Valo static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, 3193*f79cbc77SKalle Valo struct genl_info *info) 3194*f79cbc77SKalle Valo { 3195*f79cbc77SKalle Valo if (info) 3196*f79cbc77SKalle Valo genl_notify(&hwsim_genl_family, mcast_skb, info, 3197*f79cbc77SKalle Valo HWSIM_MCGRP_CONFIG, GFP_KERNEL); 3198*f79cbc77SKalle Valo else 3199*f79cbc77SKalle Valo genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0, 3200*f79cbc77SKalle Valo HWSIM_MCGRP_CONFIG, GFP_KERNEL); 3201*f79cbc77SKalle Valo } 3202*f79cbc77SKalle Valo 3203*f79cbc77SKalle Valo static int append_radio_msg(struct sk_buff *skb, int id, 3204*f79cbc77SKalle Valo struct hwsim_new_radio_params *param) 3205*f79cbc77SKalle Valo { 3206*f79cbc77SKalle Valo int ret; 3207*f79cbc77SKalle Valo 3208*f79cbc77SKalle Valo ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id); 3209*f79cbc77SKalle Valo if (ret < 0) 3210*f79cbc77SKalle Valo return ret; 3211*f79cbc77SKalle Valo 3212*f79cbc77SKalle Valo if (param->channels) { 3213*f79cbc77SKalle Valo ret = nla_put_u32(skb, HWSIM_ATTR_CHANNELS, param->channels); 3214*f79cbc77SKalle Valo if (ret < 0) 3215*f79cbc77SKalle Valo return ret; 3216*f79cbc77SKalle Valo } 3217*f79cbc77SKalle Valo 3218*f79cbc77SKalle Valo if (param->reg_alpha2) { 3219*f79cbc77SKalle Valo ret = nla_put(skb, HWSIM_ATTR_REG_HINT_ALPHA2, 2, 3220*f79cbc77SKalle Valo param->reg_alpha2); 3221*f79cbc77SKalle Valo if (ret < 0) 3222*f79cbc77SKalle Valo return ret; 3223*f79cbc77SKalle Valo } 3224*f79cbc77SKalle Valo 3225*f79cbc77SKalle Valo if (param->regd) { 3226*f79cbc77SKalle Valo int i; 3227*f79cbc77SKalle Valo 3228*f79cbc77SKalle Valo for (i = 0; i < ARRAY_SIZE(hwsim_world_regdom_custom); i++) { 3229*f79cbc77SKalle Valo if (hwsim_world_regdom_custom[i] != param->regd) 3230*f79cbc77SKalle Valo continue; 3231*f79cbc77SKalle Valo 3232*f79cbc77SKalle Valo ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i); 3233*f79cbc77SKalle Valo if (ret < 0) 3234*f79cbc77SKalle Valo return ret; 3235*f79cbc77SKalle Valo break; 3236*f79cbc77SKalle Valo } 3237*f79cbc77SKalle Valo } 3238*f79cbc77SKalle Valo 3239*f79cbc77SKalle Valo if (param->reg_strict) { 3240*f79cbc77SKalle Valo ret = nla_put_flag(skb, HWSIM_ATTR_REG_STRICT_REG); 3241*f79cbc77SKalle Valo if (ret < 0) 3242*f79cbc77SKalle Valo return ret; 3243*f79cbc77SKalle Valo } 3244*f79cbc77SKalle Valo 3245*f79cbc77SKalle Valo if (param->p2p_device) { 3246*f79cbc77SKalle Valo ret = nla_put_flag(skb, HWSIM_ATTR_SUPPORT_P2P_DEVICE); 3247*f79cbc77SKalle Valo if (ret < 0) 3248*f79cbc77SKalle Valo return ret; 3249*f79cbc77SKalle Valo } 3250*f79cbc77SKalle Valo 3251*f79cbc77SKalle Valo if (param->use_chanctx) { 3252*f79cbc77SKalle Valo ret = nla_put_flag(skb, HWSIM_ATTR_USE_CHANCTX); 3253*f79cbc77SKalle Valo if (ret < 0) 3254*f79cbc77SKalle Valo return ret; 3255*f79cbc77SKalle Valo } 3256*f79cbc77SKalle Valo 3257*f79cbc77SKalle Valo if (param->hwname) { 3258*f79cbc77SKalle Valo ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, 3259*f79cbc77SKalle Valo strlen(param->hwname), param->hwname); 3260*f79cbc77SKalle Valo if (ret < 0) 3261*f79cbc77SKalle Valo return ret; 3262*f79cbc77SKalle Valo } 3263*f79cbc77SKalle Valo 3264*f79cbc77SKalle Valo return 0; 3265*f79cbc77SKalle Valo } 3266*f79cbc77SKalle Valo 3267*f79cbc77SKalle Valo static void hwsim_mcast_new_radio(int id, struct genl_info *info, 3268*f79cbc77SKalle Valo struct hwsim_new_radio_params *param) 3269*f79cbc77SKalle Valo { 3270*f79cbc77SKalle Valo struct sk_buff *mcast_skb; 3271*f79cbc77SKalle Valo void *data; 3272*f79cbc77SKalle Valo 3273*f79cbc77SKalle Valo mcast_skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 3274*f79cbc77SKalle Valo if (!mcast_skb) 3275*f79cbc77SKalle Valo return; 3276*f79cbc77SKalle Valo 3277*f79cbc77SKalle Valo data = genlmsg_put(mcast_skb, 0, 0, &hwsim_genl_family, 0, 3278*f79cbc77SKalle Valo HWSIM_CMD_NEW_RADIO); 3279*f79cbc77SKalle Valo if (!data) 3280*f79cbc77SKalle Valo goto out_err; 3281*f79cbc77SKalle Valo 3282*f79cbc77SKalle Valo if (append_radio_msg(mcast_skb, id, param) < 0) 3283*f79cbc77SKalle Valo goto out_err; 3284*f79cbc77SKalle Valo 3285*f79cbc77SKalle Valo genlmsg_end(mcast_skb, data); 3286*f79cbc77SKalle Valo 3287*f79cbc77SKalle Valo hwsim_mcast_config_msg(mcast_skb, info); 3288*f79cbc77SKalle Valo return; 3289*f79cbc77SKalle Valo 3290*f79cbc77SKalle Valo out_err: 3291*f79cbc77SKalle Valo nlmsg_free(mcast_skb); 3292*f79cbc77SKalle Valo } 3293*f79cbc77SKalle Valo 3294*f79cbc77SKalle Valo static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = { 3295*f79cbc77SKalle Valo { 3296*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_STATION), 3297*f79cbc77SKalle Valo .he_cap = { 3298*f79cbc77SKalle Valo .has_he = true, 3299*f79cbc77SKalle Valo .he_cap_elem = { 3300*f79cbc77SKalle Valo .mac_cap_info[0] = 3301*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 3302*f79cbc77SKalle Valo .mac_cap_info[1] = 3303*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | 3304*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 3305*f79cbc77SKalle Valo .mac_cap_info[2] = 3306*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_BSR | 3307*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_MU_CASCADING | 3308*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 3309*f79cbc77SKalle Valo .mac_cap_info[3] = 3310*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 3311*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 3312*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 3313*f79cbc77SKalle Valo .phy_cap_info[1] = 3314*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 3315*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 3316*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 3317*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 3318*f79cbc77SKalle Valo .phy_cap_info[2] = 3319*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | 3320*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | 3321*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | 3322*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | 3323*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, 3324*f79cbc77SKalle Valo 3325*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 3326*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 3327*f79cbc77SKalle Valo * threshold information are not supported 3328*f79cbc77SKalle Valo */ 3329*f79cbc77SKalle Valo }, 3330*f79cbc77SKalle Valo .he_mcs_nss_supp = { 3331*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 3332*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 3333*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xffff), 3334*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xffff), 3335*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xffff), 3336*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xffff), 3337*f79cbc77SKalle Valo }, 3338*f79cbc77SKalle Valo }, 3339*f79cbc77SKalle Valo .eht_cap = { 3340*f79cbc77SKalle Valo .has_eht = true, 3341*f79cbc77SKalle Valo .eht_cap_elem = { 3342*f79cbc77SKalle Valo .mac_cap_info[0] = 3343*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | 3344*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_OM_CONTROL | 3345*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, 3346*f79cbc77SKalle Valo .phy_cap_info[0] = 3347*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | 3348*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | 3349*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | 3350*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | 3351*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE, 3352*f79cbc77SKalle Valo .phy_cap_info[3] = 3353*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | 3354*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | 3355*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | 3356*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | 3357*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | 3358*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | 3359*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, 3360*f79cbc77SKalle Valo .phy_cap_info[4] = 3361*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | 3362*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP | 3363*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | 3364*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | 3365*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK, 3366*f79cbc77SKalle Valo .phy_cap_info[5] = 3367*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | 3368*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | 3369*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | 3370*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT | 3371*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK | 3372*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK, 3373*f79cbc77SKalle Valo .phy_cap_info[6] = 3374*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK | 3375*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK, 3376*f79cbc77SKalle Valo .phy_cap_info[7] = 3377*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW, 3378*f79cbc77SKalle Valo }, 3379*f79cbc77SKalle Valo 3380*f79cbc77SKalle Valo /* For all MCS and bandwidth, set 8 NSS for both Tx and 3381*f79cbc77SKalle Valo * Rx 3382*f79cbc77SKalle Valo */ 3383*f79cbc77SKalle Valo .eht_mcs_nss_supp = { 3384*f79cbc77SKalle Valo /* 3385*f79cbc77SKalle Valo * Since B0, B1, B2 and B3 are not set in 3386*f79cbc77SKalle Valo * the supported channel width set field in the 3387*f79cbc77SKalle Valo * HE PHY capabilities information field the 3388*f79cbc77SKalle Valo * device is a 20MHz only device on 2.4GHz band. 3389*f79cbc77SKalle Valo */ 3390*f79cbc77SKalle Valo .only_20mhz = { 3391*f79cbc77SKalle Valo .rx_tx_mcs7_max_nss = 0x88, 3392*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3393*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3394*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3395*f79cbc77SKalle Valo }, 3396*f79cbc77SKalle Valo }, 3397*f79cbc77SKalle Valo /* PPE threshold information is not supported */ 3398*f79cbc77SKalle Valo }, 3399*f79cbc77SKalle Valo }, 3400*f79cbc77SKalle Valo { 3401*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_AP), 3402*f79cbc77SKalle Valo .he_cap = { 3403*f79cbc77SKalle Valo .has_he = true, 3404*f79cbc77SKalle Valo .he_cap_elem = { 3405*f79cbc77SKalle Valo .mac_cap_info[0] = 3406*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 3407*f79cbc77SKalle Valo .mac_cap_info[1] = 3408*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | 3409*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 3410*f79cbc77SKalle Valo .mac_cap_info[2] = 3411*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_BSR | 3412*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_MU_CASCADING | 3413*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 3414*f79cbc77SKalle Valo .mac_cap_info[3] = 3415*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 3416*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 3417*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 3418*f79cbc77SKalle Valo .phy_cap_info[1] = 3419*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 3420*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 3421*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 3422*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 3423*f79cbc77SKalle Valo .phy_cap_info[2] = 3424*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | 3425*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | 3426*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | 3427*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | 3428*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, 3429*f79cbc77SKalle Valo 3430*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 3431*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 3432*f79cbc77SKalle Valo * threshold information are not supported 3433*f79cbc77SKalle Valo */ 3434*f79cbc77SKalle Valo }, 3435*f79cbc77SKalle Valo .he_mcs_nss_supp = { 3436*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 3437*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 3438*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xffff), 3439*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xffff), 3440*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xffff), 3441*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xffff), 3442*f79cbc77SKalle Valo }, 3443*f79cbc77SKalle Valo }, 3444*f79cbc77SKalle Valo .eht_cap = { 3445*f79cbc77SKalle Valo .has_eht = true, 3446*f79cbc77SKalle Valo .eht_cap_elem = { 3447*f79cbc77SKalle Valo .mac_cap_info[0] = 3448*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | 3449*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_OM_CONTROL | 3450*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, 3451*f79cbc77SKalle Valo .phy_cap_info[0] = 3452*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | 3453*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | 3454*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | 3455*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | 3456*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE, 3457*f79cbc77SKalle Valo .phy_cap_info[3] = 3458*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | 3459*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | 3460*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | 3461*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | 3462*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | 3463*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | 3464*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, 3465*f79cbc77SKalle Valo .phy_cap_info[4] = 3466*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | 3467*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP | 3468*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | 3469*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | 3470*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK, 3471*f79cbc77SKalle Valo .phy_cap_info[5] = 3472*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | 3473*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | 3474*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | 3475*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT | 3476*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK | 3477*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK, 3478*f79cbc77SKalle Valo .phy_cap_info[6] = 3479*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK | 3480*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK, 3481*f79cbc77SKalle Valo .phy_cap_info[7] = 3482*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW, 3483*f79cbc77SKalle Valo }, 3484*f79cbc77SKalle Valo 3485*f79cbc77SKalle Valo /* For all MCS and bandwidth, set 8 NSS for both Tx and 3486*f79cbc77SKalle Valo * Rx 3487*f79cbc77SKalle Valo */ 3488*f79cbc77SKalle Valo .eht_mcs_nss_supp = { 3489*f79cbc77SKalle Valo /* 3490*f79cbc77SKalle Valo * Since B0, B1, B2 and B3 are not set in 3491*f79cbc77SKalle Valo * the supported channel width set field in the 3492*f79cbc77SKalle Valo * HE PHY capabilities information field the 3493*f79cbc77SKalle Valo * device is a 20MHz only device on 2.4GHz band. 3494*f79cbc77SKalle Valo */ 3495*f79cbc77SKalle Valo .only_20mhz = { 3496*f79cbc77SKalle Valo .rx_tx_mcs7_max_nss = 0x88, 3497*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3498*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3499*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3500*f79cbc77SKalle Valo }, 3501*f79cbc77SKalle Valo }, 3502*f79cbc77SKalle Valo /* PPE threshold information is not supported */ 3503*f79cbc77SKalle Valo }, 3504*f79cbc77SKalle Valo }, 3505*f79cbc77SKalle Valo #ifdef CONFIG_MAC80211_MESH 3506*f79cbc77SKalle Valo { 3507*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_MESH_POINT), 3508*f79cbc77SKalle Valo .he_cap = { 3509*f79cbc77SKalle Valo .has_he = true, 3510*f79cbc77SKalle Valo .he_cap_elem = { 3511*f79cbc77SKalle Valo .mac_cap_info[0] = 3512*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 3513*f79cbc77SKalle Valo .mac_cap_info[1] = 3514*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 3515*f79cbc77SKalle Valo .mac_cap_info[2] = 3516*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 3517*f79cbc77SKalle Valo .mac_cap_info[3] = 3518*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 3519*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 3520*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 3521*f79cbc77SKalle Valo .phy_cap_info[1] = 3522*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 3523*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 3524*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 3525*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 3526*f79cbc77SKalle Valo .phy_cap_info[2] = 0, 3527*f79cbc77SKalle Valo 3528*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 3529*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 3530*f79cbc77SKalle Valo * threshold information are not supported 3531*f79cbc77SKalle Valo */ 3532*f79cbc77SKalle Valo }, 3533*f79cbc77SKalle Valo .he_mcs_nss_supp = { 3534*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 3535*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 3536*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xffff), 3537*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xffff), 3538*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xffff), 3539*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xffff), 3540*f79cbc77SKalle Valo }, 3541*f79cbc77SKalle Valo }, 3542*f79cbc77SKalle Valo }, 3543*f79cbc77SKalle Valo #endif 3544*f79cbc77SKalle Valo }; 3545*f79cbc77SKalle Valo 3546*f79cbc77SKalle Valo static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = { 3547*f79cbc77SKalle Valo { 3548*f79cbc77SKalle Valo /* TODO: should we support other types, e.g., P2P? */ 3549*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_STATION), 3550*f79cbc77SKalle Valo .he_cap = { 3551*f79cbc77SKalle Valo .has_he = true, 3552*f79cbc77SKalle Valo .he_cap_elem = { 3553*f79cbc77SKalle Valo .mac_cap_info[0] = 3554*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 3555*f79cbc77SKalle Valo .mac_cap_info[1] = 3556*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | 3557*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 3558*f79cbc77SKalle Valo .mac_cap_info[2] = 3559*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_BSR | 3560*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_MU_CASCADING | 3561*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 3562*f79cbc77SKalle Valo .mac_cap_info[3] = 3563*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 3564*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 3565*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 3566*f79cbc77SKalle Valo .phy_cap_info[0] = 3567*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | 3568*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | 3569*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, 3570*f79cbc77SKalle Valo .phy_cap_info[1] = 3571*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 3572*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 3573*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 3574*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 3575*f79cbc77SKalle Valo .phy_cap_info[2] = 3576*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | 3577*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | 3578*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | 3579*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | 3580*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, 3581*f79cbc77SKalle Valo 3582*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 3583*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 3584*f79cbc77SKalle Valo * threshold information are not supported 3585*f79cbc77SKalle Valo */ 3586*f79cbc77SKalle Valo }, 3587*f79cbc77SKalle Valo .he_mcs_nss_supp = { 3588*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 3589*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 3590*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xfffa), 3591*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xfffa), 3592*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xfffa), 3593*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xfffa), 3594*f79cbc77SKalle Valo }, 3595*f79cbc77SKalle Valo }, 3596*f79cbc77SKalle Valo .eht_cap = { 3597*f79cbc77SKalle Valo .has_eht = true, 3598*f79cbc77SKalle Valo .eht_cap_elem = { 3599*f79cbc77SKalle Valo .mac_cap_info[0] = 3600*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | 3601*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_OM_CONTROL | 3602*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, 3603*f79cbc77SKalle Valo .phy_cap_info[0] = 3604*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | 3605*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | 3606*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | 3607*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | 3608*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE | 3609*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK, 3610*f79cbc77SKalle Valo .phy_cap_info[1] = 3611*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK | 3612*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK, 3613*f79cbc77SKalle Valo .phy_cap_info[2] = 3614*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK | 3615*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK, 3616*f79cbc77SKalle Valo .phy_cap_info[3] = 3617*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | 3618*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | 3619*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | 3620*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | 3621*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | 3622*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | 3623*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, 3624*f79cbc77SKalle Valo .phy_cap_info[4] = 3625*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | 3626*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP | 3627*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | 3628*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | 3629*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK, 3630*f79cbc77SKalle Valo .phy_cap_info[5] = 3631*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | 3632*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | 3633*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | 3634*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT | 3635*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK | 3636*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK, 3637*f79cbc77SKalle Valo .phy_cap_info[6] = 3638*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK | 3639*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK, 3640*f79cbc77SKalle Valo .phy_cap_info[7] = 3641*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW | 3642*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | 3643*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | 3644*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | 3645*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ, 3646*f79cbc77SKalle Valo }, 3647*f79cbc77SKalle Valo 3648*f79cbc77SKalle Valo /* For all MCS and bandwidth, set 8 NSS for both Tx and 3649*f79cbc77SKalle Valo * Rx 3650*f79cbc77SKalle Valo */ 3651*f79cbc77SKalle Valo .eht_mcs_nss_supp = { 3652*f79cbc77SKalle Valo /* 3653*f79cbc77SKalle Valo * As B1 and B2 are set in the supported 3654*f79cbc77SKalle Valo * channel width set field in the HE PHY 3655*f79cbc77SKalle Valo * capabilities information field include all 3656*f79cbc77SKalle Valo * the following MCS/NSS. 3657*f79cbc77SKalle Valo */ 3658*f79cbc77SKalle Valo .bw._80 = { 3659*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3660*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3661*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3662*f79cbc77SKalle Valo }, 3663*f79cbc77SKalle Valo .bw._160 = { 3664*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3665*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3666*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3667*f79cbc77SKalle Valo }, 3668*f79cbc77SKalle Valo }, 3669*f79cbc77SKalle Valo /* PPE threshold information is not supported */ 3670*f79cbc77SKalle Valo }, 3671*f79cbc77SKalle Valo }, 3672*f79cbc77SKalle Valo { 3673*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_AP), 3674*f79cbc77SKalle Valo .he_cap = { 3675*f79cbc77SKalle Valo .has_he = true, 3676*f79cbc77SKalle Valo .he_cap_elem = { 3677*f79cbc77SKalle Valo .mac_cap_info[0] = 3678*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 3679*f79cbc77SKalle Valo .mac_cap_info[1] = 3680*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | 3681*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 3682*f79cbc77SKalle Valo .mac_cap_info[2] = 3683*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_BSR | 3684*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_MU_CASCADING | 3685*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 3686*f79cbc77SKalle Valo .mac_cap_info[3] = 3687*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 3688*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 3689*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 3690*f79cbc77SKalle Valo .phy_cap_info[0] = 3691*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | 3692*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | 3693*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, 3694*f79cbc77SKalle Valo .phy_cap_info[1] = 3695*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 3696*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 3697*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 3698*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 3699*f79cbc77SKalle Valo .phy_cap_info[2] = 3700*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | 3701*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | 3702*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | 3703*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | 3704*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, 3705*f79cbc77SKalle Valo 3706*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 3707*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 3708*f79cbc77SKalle Valo * threshold information are not supported 3709*f79cbc77SKalle Valo */ 3710*f79cbc77SKalle Valo }, 3711*f79cbc77SKalle Valo .he_mcs_nss_supp = { 3712*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 3713*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 3714*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xfffa), 3715*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xfffa), 3716*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xfffa), 3717*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xfffa), 3718*f79cbc77SKalle Valo }, 3719*f79cbc77SKalle Valo }, 3720*f79cbc77SKalle Valo .eht_cap = { 3721*f79cbc77SKalle Valo .has_eht = true, 3722*f79cbc77SKalle Valo .eht_cap_elem = { 3723*f79cbc77SKalle Valo .mac_cap_info[0] = 3724*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | 3725*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_OM_CONTROL | 3726*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, 3727*f79cbc77SKalle Valo .phy_cap_info[0] = 3728*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | 3729*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | 3730*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | 3731*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | 3732*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE | 3733*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK, 3734*f79cbc77SKalle Valo .phy_cap_info[1] = 3735*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK | 3736*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK, 3737*f79cbc77SKalle Valo .phy_cap_info[2] = 3738*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK | 3739*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK, 3740*f79cbc77SKalle Valo .phy_cap_info[3] = 3741*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | 3742*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | 3743*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | 3744*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | 3745*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | 3746*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | 3747*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, 3748*f79cbc77SKalle Valo .phy_cap_info[4] = 3749*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | 3750*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP | 3751*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | 3752*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | 3753*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK, 3754*f79cbc77SKalle Valo .phy_cap_info[5] = 3755*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | 3756*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | 3757*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | 3758*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT | 3759*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK | 3760*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK, 3761*f79cbc77SKalle Valo .phy_cap_info[6] = 3762*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK | 3763*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK, 3764*f79cbc77SKalle Valo .phy_cap_info[7] = 3765*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW | 3766*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | 3767*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | 3768*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | 3769*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ, 3770*f79cbc77SKalle Valo }, 3771*f79cbc77SKalle Valo 3772*f79cbc77SKalle Valo /* For all MCS and bandwidth, set 8 NSS for both Tx and 3773*f79cbc77SKalle Valo * Rx 3774*f79cbc77SKalle Valo */ 3775*f79cbc77SKalle Valo .eht_mcs_nss_supp = { 3776*f79cbc77SKalle Valo /* 3777*f79cbc77SKalle Valo * As B1 and B2 are set in the supported 3778*f79cbc77SKalle Valo * channel width set field in the HE PHY 3779*f79cbc77SKalle Valo * capabilities information field include all 3780*f79cbc77SKalle Valo * the following MCS/NSS. 3781*f79cbc77SKalle Valo */ 3782*f79cbc77SKalle Valo .bw._80 = { 3783*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3784*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3785*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3786*f79cbc77SKalle Valo }, 3787*f79cbc77SKalle Valo .bw._160 = { 3788*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3789*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3790*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3791*f79cbc77SKalle Valo }, 3792*f79cbc77SKalle Valo }, 3793*f79cbc77SKalle Valo /* PPE threshold information is not supported */ 3794*f79cbc77SKalle Valo }, 3795*f79cbc77SKalle Valo }, 3796*f79cbc77SKalle Valo #ifdef CONFIG_MAC80211_MESH 3797*f79cbc77SKalle Valo { 3798*f79cbc77SKalle Valo /* TODO: should we support other types, e.g., IBSS?*/ 3799*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_MESH_POINT), 3800*f79cbc77SKalle Valo .he_cap = { 3801*f79cbc77SKalle Valo .has_he = true, 3802*f79cbc77SKalle Valo .he_cap_elem = { 3803*f79cbc77SKalle Valo .mac_cap_info[0] = 3804*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 3805*f79cbc77SKalle Valo .mac_cap_info[1] = 3806*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 3807*f79cbc77SKalle Valo .mac_cap_info[2] = 3808*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 3809*f79cbc77SKalle Valo .mac_cap_info[3] = 3810*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 3811*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 3812*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 3813*f79cbc77SKalle Valo .phy_cap_info[0] = 3814*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | 3815*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | 3816*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, 3817*f79cbc77SKalle Valo .phy_cap_info[1] = 3818*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 3819*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 3820*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 3821*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 3822*f79cbc77SKalle Valo .phy_cap_info[2] = 0, 3823*f79cbc77SKalle Valo 3824*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 3825*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 3826*f79cbc77SKalle Valo * threshold information are not supported 3827*f79cbc77SKalle Valo */ 3828*f79cbc77SKalle Valo }, 3829*f79cbc77SKalle Valo .he_mcs_nss_supp = { 3830*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 3831*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 3832*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xfffa), 3833*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xfffa), 3834*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xfffa), 3835*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xfffa), 3836*f79cbc77SKalle Valo }, 3837*f79cbc77SKalle Valo }, 3838*f79cbc77SKalle Valo }, 3839*f79cbc77SKalle Valo #endif 3840*f79cbc77SKalle Valo }; 3841*f79cbc77SKalle Valo 3842*f79cbc77SKalle Valo static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = { 3843*f79cbc77SKalle Valo { 3844*f79cbc77SKalle Valo /* TODO: should we support other types, e.g., P2P? */ 3845*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_STATION), 3846*f79cbc77SKalle Valo .he_6ghz_capa = { 3847*f79cbc77SKalle Valo .capa = cpu_to_le16(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START | 3848*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP | 3849*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN | 3850*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_SM_PS | 3851*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_RD_RESPONDER | 3852*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | 3853*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS), 3854*f79cbc77SKalle Valo }, 3855*f79cbc77SKalle Valo .he_cap = { 3856*f79cbc77SKalle Valo .has_he = true, 3857*f79cbc77SKalle Valo .he_cap_elem = { 3858*f79cbc77SKalle Valo .mac_cap_info[0] = 3859*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 3860*f79cbc77SKalle Valo .mac_cap_info[1] = 3861*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | 3862*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 3863*f79cbc77SKalle Valo .mac_cap_info[2] = 3864*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_BSR | 3865*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_MU_CASCADING | 3866*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 3867*f79cbc77SKalle Valo .mac_cap_info[3] = 3868*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 3869*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 3870*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 3871*f79cbc77SKalle Valo .phy_cap_info[0] = 3872*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | 3873*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | 3874*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, 3875*f79cbc77SKalle Valo .phy_cap_info[1] = 3876*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 3877*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 3878*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 3879*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 3880*f79cbc77SKalle Valo .phy_cap_info[2] = 3881*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | 3882*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | 3883*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | 3884*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | 3885*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, 3886*f79cbc77SKalle Valo 3887*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 3888*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 3889*f79cbc77SKalle Valo * threshold information are not supported 3890*f79cbc77SKalle Valo */ 3891*f79cbc77SKalle Valo }, 3892*f79cbc77SKalle Valo .he_mcs_nss_supp = { 3893*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 3894*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 3895*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xfffa), 3896*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xfffa), 3897*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xfffa), 3898*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xfffa), 3899*f79cbc77SKalle Valo }, 3900*f79cbc77SKalle Valo }, 3901*f79cbc77SKalle Valo .eht_cap = { 3902*f79cbc77SKalle Valo .has_eht = true, 3903*f79cbc77SKalle Valo .eht_cap_elem = { 3904*f79cbc77SKalle Valo .mac_cap_info[0] = 3905*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | 3906*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_OM_CONTROL | 3907*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, 3908*f79cbc77SKalle Valo .phy_cap_info[0] = 3909*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ | 3910*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | 3911*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | 3912*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | 3913*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | 3914*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE | 3915*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK, 3916*f79cbc77SKalle Valo .phy_cap_info[1] = 3917*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK | 3918*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK | 3919*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK, 3920*f79cbc77SKalle Valo .phy_cap_info[2] = 3921*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK | 3922*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK | 3923*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK, 3924*f79cbc77SKalle Valo .phy_cap_info[3] = 3925*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | 3926*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | 3927*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | 3928*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | 3929*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | 3930*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | 3931*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, 3932*f79cbc77SKalle Valo .phy_cap_info[4] = 3933*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | 3934*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP | 3935*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | 3936*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | 3937*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK, 3938*f79cbc77SKalle Valo .phy_cap_info[5] = 3939*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | 3940*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | 3941*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | 3942*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT | 3943*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK | 3944*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK, 3945*f79cbc77SKalle Valo .phy_cap_info[6] = 3946*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK | 3947*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK | 3948*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP, 3949*f79cbc77SKalle Valo .phy_cap_info[7] = 3950*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW | 3951*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | 3952*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | 3953*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ | 3954*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | 3955*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | 3956*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ, 3957*f79cbc77SKalle Valo }, 3958*f79cbc77SKalle Valo 3959*f79cbc77SKalle Valo /* For all MCS and bandwidth, set 8 NSS for both Tx and 3960*f79cbc77SKalle Valo * Rx 3961*f79cbc77SKalle Valo */ 3962*f79cbc77SKalle Valo .eht_mcs_nss_supp = { 3963*f79cbc77SKalle Valo /* 3964*f79cbc77SKalle Valo * As B1 and B2 are set in the supported 3965*f79cbc77SKalle Valo * channel width set field in the HE PHY 3966*f79cbc77SKalle Valo * capabilities information field and 320MHz in 3967*f79cbc77SKalle Valo * 6GHz is supported include all the following 3968*f79cbc77SKalle Valo * MCS/NSS. 3969*f79cbc77SKalle Valo */ 3970*f79cbc77SKalle Valo .bw._80 = { 3971*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3972*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3973*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3974*f79cbc77SKalle Valo }, 3975*f79cbc77SKalle Valo .bw._160 = { 3976*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3977*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3978*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3979*f79cbc77SKalle Valo }, 3980*f79cbc77SKalle Valo .bw._320 = { 3981*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 3982*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 3983*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 3984*f79cbc77SKalle Valo }, 3985*f79cbc77SKalle Valo }, 3986*f79cbc77SKalle Valo /* PPE threshold information is not supported */ 3987*f79cbc77SKalle Valo }, 3988*f79cbc77SKalle Valo }, 3989*f79cbc77SKalle Valo { 3990*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_AP), 3991*f79cbc77SKalle Valo .he_6ghz_capa = { 3992*f79cbc77SKalle Valo .capa = cpu_to_le16(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START | 3993*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP | 3994*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN | 3995*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_SM_PS | 3996*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_RD_RESPONDER | 3997*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | 3998*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS), 3999*f79cbc77SKalle Valo }, 4000*f79cbc77SKalle Valo .he_cap = { 4001*f79cbc77SKalle Valo .has_he = true, 4002*f79cbc77SKalle Valo .he_cap_elem = { 4003*f79cbc77SKalle Valo .mac_cap_info[0] = 4004*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 4005*f79cbc77SKalle Valo .mac_cap_info[1] = 4006*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | 4007*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 4008*f79cbc77SKalle Valo .mac_cap_info[2] = 4009*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_BSR | 4010*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_MU_CASCADING | 4011*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 4012*f79cbc77SKalle Valo .mac_cap_info[3] = 4013*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 4014*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 4015*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 4016*f79cbc77SKalle Valo .phy_cap_info[0] = 4017*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | 4018*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | 4019*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, 4020*f79cbc77SKalle Valo .phy_cap_info[1] = 4021*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 4022*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 4023*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 4024*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 4025*f79cbc77SKalle Valo .phy_cap_info[2] = 4026*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | 4027*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | 4028*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | 4029*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | 4030*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, 4031*f79cbc77SKalle Valo 4032*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 4033*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 4034*f79cbc77SKalle Valo * threshold information are not supported 4035*f79cbc77SKalle Valo */ 4036*f79cbc77SKalle Valo }, 4037*f79cbc77SKalle Valo .he_mcs_nss_supp = { 4038*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 4039*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 4040*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xfffa), 4041*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xfffa), 4042*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xfffa), 4043*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xfffa), 4044*f79cbc77SKalle Valo }, 4045*f79cbc77SKalle Valo }, 4046*f79cbc77SKalle Valo .eht_cap = { 4047*f79cbc77SKalle Valo .has_eht = true, 4048*f79cbc77SKalle Valo .eht_cap_elem = { 4049*f79cbc77SKalle Valo .mac_cap_info[0] = 4050*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | 4051*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_OM_CONTROL | 4052*f79cbc77SKalle Valo IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1, 4053*f79cbc77SKalle Valo .phy_cap_info[0] = 4054*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ | 4055*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | 4056*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | 4057*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | 4058*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER | 4059*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE | 4060*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK, 4061*f79cbc77SKalle Valo .phy_cap_info[1] = 4062*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK | 4063*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK | 4064*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK, 4065*f79cbc77SKalle Valo .phy_cap_info[2] = 4066*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK | 4067*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK | 4068*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK, 4069*f79cbc77SKalle Valo .phy_cap_info[3] = 4070*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | 4071*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | 4072*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | 4073*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | 4074*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | 4075*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | 4076*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, 4077*f79cbc77SKalle Valo .phy_cap_info[4] = 4078*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | 4079*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP | 4080*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | 4081*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI | 4082*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK, 4083*f79cbc77SKalle Valo .phy_cap_info[5] = 4084*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | 4085*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | 4086*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | 4087*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT | 4088*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK | 4089*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK, 4090*f79cbc77SKalle Valo .phy_cap_info[6] = 4091*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK | 4092*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK | 4093*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP, 4094*f79cbc77SKalle Valo .phy_cap_info[7] = 4095*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW | 4096*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ | 4097*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ | 4098*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ | 4099*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | 4100*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | 4101*f79cbc77SKalle Valo IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ, 4102*f79cbc77SKalle Valo }, 4103*f79cbc77SKalle Valo 4104*f79cbc77SKalle Valo /* For all MCS and bandwidth, set 8 NSS for both Tx and 4105*f79cbc77SKalle Valo * Rx 4106*f79cbc77SKalle Valo */ 4107*f79cbc77SKalle Valo .eht_mcs_nss_supp = { 4108*f79cbc77SKalle Valo /* 4109*f79cbc77SKalle Valo * As B1 and B2 are set in the supported 4110*f79cbc77SKalle Valo * channel width set field in the HE PHY 4111*f79cbc77SKalle Valo * capabilities information field and 320MHz in 4112*f79cbc77SKalle Valo * 6GHz is supported include all the following 4113*f79cbc77SKalle Valo * MCS/NSS. 4114*f79cbc77SKalle Valo */ 4115*f79cbc77SKalle Valo .bw._80 = { 4116*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 4117*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 4118*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 4119*f79cbc77SKalle Valo }, 4120*f79cbc77SKalle Valo .bw._160 = { 4121*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 4122*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 4123*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 4124*f79cbc77SKalle Valo }, 4125*f79cbc77SKalle Valo .bw._320 = { 4126*f79cbc77SKalle Valo .rx_tx_mcs9_max_nss = 0x88, 4127*f79cbc77SKalle Valo .rx_tx_mcs11_max_nss = 0x88, 4128*f79cbc77SKalle Valo .rx_tx_mcs13_max_nss = 0x88, 4129*f79cbc77SKalle Valo }, 4130*f79cbc77SKalle Valo }, 4131*f79cbc77SKalle Valo /* PPE threshold information is not supported */ 4132*f79cbc77SKalle Valo }, 4133*f79cbc77SKalle Valo }, 4134*f79cbc77SKalle Valo #ifdef CONFIG_MAC80211_MESH 4135*f79cbc77SKalle Valo { 4136*f79cbc77SKalle Valo /* TODO: should we support other types, e.g., IBSS?*/ 4137*f79cbc77SKalle Valo .types_mask = BIT(NL80211_IFTYPE_MESH_POINT), 4138*f79cbc77SKalle Valo .he_6ghz_capa = { 4139*f79cbc77SKalle Valo .capa = cpu_to_le16(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START | 4140*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP | 4141*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN | 4142*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_SM_PS | 4143*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_RD_RESPONDER | 4144*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS | 4145*f79cbc77SKalle Valo IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS), 4146*f79cbc77SKalle Valo }, 4147*f79cbc77SKalle Valo .he_cap = { 4148*f79cbc77SKalle Valo .has_he = true, 4149*f79cbc77SKalle Valo .he_cap_elem = { 4150*f79cbc77SKalle Valo .mac_cap_info[0] = 4151*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP0_HTC_HE, 4152*f79cbc77SKalle Valo .mac_cap_info[1] = 4153*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, 4154*f79cbc77SKalle Valo .mac_cap_info[2] = 4155*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP2_ACK_EN, 4156*f79cbc77SKalle Valo .mac_cap_info[3] = 4157*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_OMI_CONTROL | 4158*f79cbc77SKalle Valo IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3, 4159*f79cbc77SKalle Valo .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU, 4160*f79cbc77SKalle Valo .phy_cap_info[0] = 4161*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | 4162*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | 4163*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, 4164*f79cbc77SKalle Valo .phy_cap_info[1] = 4165*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | 4166*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | 4167*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | 4168*f79cbc77SKalle Valo IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, 4169*f79cbc77SKalle Valo .phy_cap_info[2] = 0, 4170*f79cbc77SKalle Valo 4171*f79cbc77SKalle Valo /* Leave all the other PHY capability bytes 4172*f79cbc77SKalle Valo * unset, as DCM, beam forming, RU and PPE 4173*f79cbc77SKalle Valo * threshold information are not supported 4174*f79cbc77SKalle Valo */ 4175*f79cbc77SKalle Valo }, 4176*f79cbc77SKalle Valo .he_mcs_nss_supp = { 4177*f79cbc77SKalle Valo .rx_mcs_80 = cpu_to_le16(0xfffa), 4178*f79cbc77SKalle Valo .tx_mcs_80 = cpu_to_le16(0xfffa), 4179*f79cbc77SKalle Valo .rx_mcs_160 = cpu_to_le16(0xfffa), 4180*f79cbc77SKalle Valo .tx_mcs_160 = cpu_to_le16(0xfffa), 4181*f79cbc77SKalle Valo .rx_mcs_80p80 = cpu_to_le16(0xfffa), 4182*f79cbc77SKalle Valo .tx_mcs_80p80 = cpu_to_le16(0xfffa), 4183*f79cbc77SKalle Valo }, 4184*f79cbc77SKalle Valo }, 4185*f79cbc77SKalle Valo }, 4186*f79cbc77SKalle Valo #endif 4187*f79cbc77SKalle Valo }; 4188*f79cbc77SKalle Valo 4189*f79cbc77SKalle Valo static void mac80211_hwsim_sband_capab(struct ieee80211_supported_band *sband) 4190*f79cbc77SKalle Valo { 4191*f79cbc77SKalle Valo u16 n_iftype_data; 4192*f79cbc77SKalle Valo 4193*f79cbc77SKalle Valo if (sband->band == NL80211_BAND_2GHZ) { 4194*f79cbc77SKalle Valo n_iftype_data = ARRAY_SIZE(sband_capa_2ghz); 4195*f79cbc77SKalle Valo sband->iftype_data = 4196*f79cbc77SKalle Valo (struct ieee80211_sband_iftype_data *)sband_capa_2ghz; 4197*f79cbc77SKalle Valo } else if (sband->band == NL80211_BAND_5GHZ) { 4198*f79cbc77SKalle Valo n_iftype_data = ARRAY_SIZE(sband_capa_5ghz); 4199*f79cbc77SKalle Valo sband->iftype_data = 4200*f79cbc77SKalle Valo (struct ieee80211_sband_iftype_data *)sband_capa_5ghz; 4201*f79cbc77SKalle Valo } else if (sband->band == NL80211_BAND_6GHZ) { 4202*f79cbc77SKalle Valo n_iftype_data = ARRAY_SIZE(sband_capa_6ghz); 4203*f79cbc77SKalle Valo sband->iftype_data = 4204*f79cbc77SKalle Valo (struct ieee80211_sband_iftype_data *)sband_capa_6ghz; 4205*f79cbc77SKalle Valo } else { 4206*f79cbc77SKalle Valo return; 4207*f79cbc77SKalle Valo } 4208*f79cbc77SKalle Valo 4209*f79cbc77SKalle Valo sband->n_iftype_data = n_iftype_data; 4210*f79cbc77SKalle Valo } 4211*f79cbc77SKalle Valo 4212*f79cbc77SKalle Valo #ifdef CONFIG_MAC80211_MESH 4213*f79cbc77SKalle Valo #define HWSIM_MESH_BIT BIT(NL80211_IFTYPE_MESH_POINT) 4214*f79cbc77SKalle Valo #else 4215*f79cbc77SKalle Valo #define HWSIM_MESH_BIT 0 4216*f79cbc77SKalle Valo #endif 4217*f79cbc77SKalle Valo 4218*f79cbc77SKalle Valo #define HWSIM_DEFAULT_IF_LIMIT \ 4219*f79cbc77SKalle Valo (BIT(NL80211_IFTYPE_STATION) | \ 4220*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_P2P_CLIENT) | \ 4221*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_AP) | \ 4222*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_P2P_GO) | \ 4223*f79cbc77SKalle Valo HWSIM_MESH_BIT) 4224*f79cbc77SKalle Valo 4225*f79cbc77SKalle Valo #define HWSIM_IFTYPE_SUPPORT_MASK \ 4226*f79cbc77SKalle Valo (BIT(NL80211_IFTYPE_STATION) | \ 4227*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_AP) | \ 4228*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_P2P_CLIENT) | \ 4229*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_P2P_GO) | \ 4230*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_ADHOC) | \ 4231*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_MESH_POINT) | \ 4232*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_OCB)) 4233*f79cbc77SKalle Valo 4234*f79cbc77SKalle Valo static int mac80211_hwsim_new_radio(struct genl_info *info, 4235*f79cbc77SKalle Valo struct hwsim_new_radio_params *param) 4236*f79cbc77SKalle Valo { 4237*f79cbc77SKalle Valo int err; 4238*f79cbc77SKalle Valo u8 addr[ETH_ALEN]; 4239*f79cbc77SKalle Valo struct mac80211_hwsim_data *data; 4240*f79cbc77SKalle Valo struct ieee80211_hw *hw; 4241*f79cbc77SKalle Valo enum nl80211_band band; 4242*f79cbc77SKalle Valo const struct ieee80211_ops *ops = &mac80211_hwsim_ops; 4243*f79cbc77SKalle Valo struct net *net; 4244*f79cbc77SKalle Valo int idx, i; 4245*f79cbc77SKalle Valo int n_limits = 0; 4246*f79cbc77SKalle Valo 4247*f79cbc77SKalle Valo if (WARN_ON(param->channels > 1 && !param->use_chanctx)) 4248*f79cbc77SKalle Valo return -EINVAL; 4249*f79cbc77SKalle Valo 4250*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 4251*f79cbc77SKalle Valo idx = hwsim_radio_idx++; 4252*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 4253*f79cbc77SKalle Valo 4254*f79cbc77SKalle Valo if (param->mlo) 4255*f79cbc77SKalle Valo ops = &mac80211_hwsim_mlo_ops; 4256*f79cbc77SKalle Valo else if (param->use_chanctx) 4257*f79cbc77SKalle Valo ops = &mac80211_hwsim_mchan_ops; 4258*f79cbc77SKalle Valo hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname); 4259*f79cbc77SKalle Valo if (!hw) { 4260*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: ieee80211_alloc_hw failed\n"); 4261*f79cbc77SKalle Valo err = -ENOMEM; 4262*f79cbc77SKalle Valo goto failed; 4263*f79cbc77SKalle Valo } 4264*f79cbc77SKalle Valo 4265*f79cbc77SKalle Valo /* ieee80211_alloc_hw_nm may have used a default name */ 4266*f79cbc77SKalle Valo param->hwname = wiphy_name(hw->wiphy); 4267*f79cbc77SKalle Valo 4268*f79cbc77SKalle Valo if (info) 4269*f79cbc77SKalle Valo net = genl_info_net(info); 4270*f79cbc77SKalle Valo else 4271*f79cbc77SKalle Valo net = &init_net; 4272*f79cbc77SKalle Valo wiphy_net_set(hw->wiphy, net); 4273*f79cbc77SKalle Valo 4274*f79cbc77SKalle Valo data = hw->priv; 4275*f79cbc77SKalle Valo data->hw = hw; 4276*f79cbc77SKalle Valo 4277*f79cbc77SKalle Valo data->dev = device_create(hwsim_class, NULL, 0, hw, "hwsim%d", idx); 4278*f79cbc77SKalle Valo if (IS_ERR(data->dev)) { 4279*f79cbc77SKalle Valo printk(KERN_DEBUG 4280*f79cbc77SKalle Valo "mac80211_hwsim: device_create failed (%ld)\n", 4281*f79cbc77SKalle Valo PTR_ERR(data->dev)); 4282*f79cbc77SKalle Valo err = -ENOMEM; 4283*f79cbc77SKalle Valo goto failed_drvdata; 4284*f79cbc77SKalle Valo } 4285*f79cbc77SKalle Valo data->dev->driver = &mac80211_hwsim_driver.driver; 4286*f79cbc77SKalle Valo err = device_bind_driver(data->dev); 4287*f79cbc77SKalle Valo if (err != 0) { 4288*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: device_bind_driver failed (%d)\n", 4289*f79cbc77SKalle Valo err); 4290*f79cbc77SKalle Valo goto failed_bind; 4291*f79cbc77SKalle Valo } 4292*f79cbc77SKalle Valo 4293*f79cbc77SKalle Valo skb_queue_head_init(&data->pending); 4294*f79cbc77SKalle Valo 4295*f79cbc77SKalle Valo SET_IEEE80211_DEV(hw, data->dev); 4296*f79cbc77SKalle Valo if (!param->perm_addr) { 4297*f79cbc77SKalle Valo eth_zero_addr(addr); 4298*f79cbc77SKalle Valo addr[0] = 0x02; 4299*f79cbc77SKalle Valo addr[3] = idx >> 8; 4300*f79cbc77SKalle Valo addr[4] = idx; 4301*f79cbc77SKalle Valo memcpy(data->addresses[0].addr, addr, ETH_ALEN); 4302*f79cbc77SKalle Valo /* Why need here second address ? */ 4303*f79cbc77SKalle Valo memcpy(data->addresses[1].addr, addr, ETH_ALEN); 4304*f79cbc77SKalle Valo data->addresses[1].addr[0] |= 0x40; 4305*f79cbc77SKalle Valo hw->wiphy->n_addresses = 2; 4306*f79cbc77SKalle Valo hw->wiphy->addresses = data->addresses; 4307*f79cbc77SKalle Valo /* possible address clash is checked at hash table insertion */ 4308*f79cbc77SKalle Valo } else { 4309*f79cbc77SKalle Valo memcpy(data->addresses[0].addr, param->perm_addr, ETH_ALEN); 4310*f79cbc77SKalle Valo /* compatibility with automatically generated mac addr */ 4311*f79cbc77SKalle Valo memcpy(data->addresses[1].addr, param->perm_addr, ETH_ALEN); 4312*f79cbc77SKalle Valo hw->wiphy->n_addresses = 2; 4313*f79cbc77SKalle Valo hw->wiphy->addresses = data->addresses; 4314*f79cbc77SKalle Valo } 4315*f79cbc77SKalle Valo 4316*f79cbc77SKalle Valo data->channels = param->channels; 4317*f79cbc77SKalle Valo data->use_chanctx = param->use_chanctx; 4318*f79cbc77SKalle Valo data->idx = idx; 4319*f79cbc77SKalle Valo data->destroy_on_close = param->destroy_on_close; 4320*f79cbc77SKalle Valo if (info) 4321*f79cbc77SKalle Valo data->portid = info->snd_portid; 4322*f79cbc77SKalle Valo 4323*f79cbc77SKalle Valo /* setup interface limits, only on interface types we support */ 4324*f79cbc77SKalle Valo if (param->iftypes & BIT(NL80211_IFTYPE_ADHOC)) { 4325*f79cbc77SKalle Valo data->if_limits[n_limits].max = 1; 4326*f79cbc77SKalle Valo data->if_limits[n_limits].types = BIT(NL80211_IFTYPE_ADHOC); 4327*f79cbc77SKalle Valo n_limits++; 4328*f79cbc77SKalle Valo } 4329*f79cbc77SKalle Valo 4330*f79cbc77SKalle Valo if (param->iftypes & HWSIM_DEFAULT_IF_LIMIT) { 4331*f79cbc77SKalle Valo data->if_limits[n_limits].max = 2048; 4332*f79cbc77SKalle Valo /* 4333*f79cbc77SKalle Valo * For this case, we may only support a subset of 4334*f79cbc77SKalle Valo * HWSIM_DEFAULT_IF_LIMIT, therefore we only want to add the 4335*f79cbc77SKalle Valo * bits that both param->iftype & HWSIM_DEFAULT_IF_LIMIT have. 4336*f79cbc77SKalle Valo */ 4337*f79cbc77SKalle Valo data->if_limits[n_limits].types = 4338*f79cbc77SKalle Valo HWSIM_DEFAULT_IF_LIMIT & param->iftypes; 4339*f79cbc77SKalle Valo n_limits++; 4340*f79cbc77SKalle Valo } 4341*f79cbc77SKalle Valo 4342*f79cbc77SKalle Valo if (param->iftypes & BIT(NL80211_IFTYPE_P2P_DEVICE)) { 4343*f79cbc77SKalle Valo data->if_limits[n_limits].max = 1; 4344*f79cbc77SKalle Valo data->if_limits[n_limits].types = 4345*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_P2P_DEVICE); 4346*f79cbc77SKalle Valo n_limits++; 4347*f79cbc77SKalle Valo } 4348*f79cbc77SKalle Valo 4349*f79cbc77SKalle Valo if (data->use_chanctx) { 4350*f79cbc77SKalle Valo hw->wiphy->max_scan_ssids = 255; 4351*f79cbc77SKalle Valo hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; 4352*f79cbc77SKalle Valo hw->wiphy->max_remain_on_channel_duration = 1000; 4353*f79cbc77SKalle Valo data->if_combination.radar_detect_widths = 0; 4354*f79cbc77SKalle Valo data->if_combination.num_different_channels = data->channels; 4355*f79cbc77SKalle Valo } else { 4356*f79cbc77SKalle Valo data->if_combination.num_different_channels = 1; 4357*f79cbc77SKalle Valo data->if_combination.radar_detect_widths = 4358*f79cbc77SKalle Valo BIT(NL80211_CHAN_WIDTH_5) | 4359*f79cbc77SKalle Valo BIT(NL80211_CHAN_WIDTH_10) | 4360*f79cbc77SKalle Valo BIT(NL80211_CHAN_WIDTH_20_NOHT) | 4361*f79cbc77SKalle Valo BIT(NL80211_CHAN_WIDTH_20) | 4362*f79cbc77SKalle Valo BIT(NL80211_CHAN_WIDTH_40) | 4363*f79cbc77SKalle Valo BIT(NL80211_CHAN_WIDTH_80) | 4364*f79cbc77SKalle Valo BIT(NL80211_CHAN_WIDTH_160); 4365*f79cbc77SKalle Valo } 4366*f79cbc77SKalle Valo 4367*f79cbc77SKalle Valo if (!n_limits) { 4368*f79cbc77SKalle Valo err = -EINVAL; 4369*f79cbc77SKalle Valo goto failed_hw; 4370*f79cbc77SKalle Valo } 4371*f79cbc77SKalle Valo 4372*f79cbc77SKalle Valo data->if_combination.max_interfaces = 0; 4373*f79cbc77SKalle Valo for (i = 0; i < n_limits; i++) 4374*f79cbc77SKalle Valo data->if_combination.max_interfaces += 4375*f79cbc77SKalle Valo data->if_limits[i].max; 4376*f79cbc77SKalle Valo 4377*f79cbc77SKalle Valo data->if_combination.n_limits = n_limits; 4378*f79cbc77SKalle Valo data->if_combination.limits = data->if_limits; 4379*f79cbc77SKalle Valo 4380*f79cbc77SKalle Valo /* 4381*f79cbc77SKalle Valo * If we actually were asked to support combinations, 4382*f79cbc77SKalle Valo * advertise them - if there's only a single thing like 4383*f79cbc77SKalle Valo * only IBSS then don't advertise it as combinations. 4384*f79cbc77SKalle Valo */ 4385*f79cbc77SKalle Valo if (data->if_combination.max_interfaces > 1) { 4386*f79cbc77SKalle Valo hw->wiphy->iface_combinations = &data->if_combination; 4387*f79cbc77SKalle Valo hw->wiphy->n_iface_combinations = 1; 4388*f79cbc77SKalle Valo } 4389*f79cbc77SKalle Valo 4390*f79cbc77SKalle Valo if (param->ciphers) { 4391*f79cbc77SKalle Valo memcpy(data->ciphers, param->ciphers, 4392*f79cbc77SKalle Valo param->n_ciphers * sizeof(u32)); 4393*f79cbc77SKalle Valo hw->wiphy->cipher_suites = data->ciphers; 4394*f79cbc77SKalle Valo hw->wiphy->n_cipher_suites = param->n_ciphers; 4395*f79cbc77SKalle Valo } 4396*f79cbc77SKalle Valo 4397*f79cbc77SKalle Valo data->rx_rssi = DEFAULT_RX_RSSI; 4398*f79cbc77SKalle Valo 4399*f79cbc77SKalle Valo INIT_DELAYED_WORK(&data->roc_start, hw_roc_start); 4400*f79cbc77SKalle Valo INIT_DELAYED_WORK(&data->roc_done, hw_roc_done); 4401*f79cbc77SKalle Valo INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work); 4402*f79cbc77SKalle Valo 4403*f79cbc77SKalle Valo hw->queues = 5; 4404*f79cbc77SKalle Valo hw->offchannel_tx_hw_queue = 4; 4405*f79cbc77SKalle Valo 4406*f79cbc77SKalle Valo ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); 4407*f79cbc77SKalle Valo ieee80211_hw_set(hw, CHANCTX_STA_CSA); 4408*f79cbc77SKalle Valo ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); 4409*f79cbc77SKalle Valo ieee80211_hw_set(hw, QUEUE_CONTROL); 4410*f79cbc77SKalle Valo ieee80211_hw_set(hw, WANT_MONITOR_VIF); 4411*f79cbc77SKalle Valo ieee80211_hw_set(hw, AMPDU_AGGREGATION); 4412*f79cbc77SKalle Valo ieee80211_hw_set(hw, MFP_CAPABLE); 4413*f79cbc77SKalle Valo ieee80211_hw_set(hw, SIGNAL_DBM); 4414*f79cbc77SKalle Valo ieee80211_hw_set(hw, SUPPORTS_PS); 4415*f79cbc77SKalle Valo ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); 4416*f79cbc77SKalle Valo ieee80211_hw_set(hw, TDLS_WIDER_BW); 4417*f79cbc77SKalle Valo ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); 4418*f79cbc77SKalle Valo 4419*f79cbc77SKalle Valo if (param->mlo) { 4420*f79cbc77SKalle Valo hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO; 4421*f79cbc77SKalle Valo ieee80211_hw_set(hw, HAS_RATE_CONTROL); 4422*f79cbc77SKalle Valo ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); 4423*f79cbc77SKalle Valo ieee80211_hw_set(hw, CONNECTION_MONITOR); 4424*f79cbc77SKalle Valo ieee80211_hw_set(hw, AP_LINK_PS); 4425*f79cbc77SKalle Valo } else { 4426*f79cbc77SKalle Valo ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); 4427*f79cbc77SKalle Valo ieee80211_hw_set(hw, PS_NULLFUNC_STACK); 4428*f79cbc77SKalle Valo if (rctbl) 4429*f79cbc77SKalle Valo ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); 4430*f79cbc77SKalle Valo } 4431*f79cbc77SKalle Valo 4432*f79cbc77SKalle Valo hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; 4433*f79cbc77SKalle Valo hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | 4434*f79cbc77SKalle Valo WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | 4435*f79cbc77SKalle Valo WIPHY_FLAG_AP_UAPSD | 4436*f79cbc77SKalle Valo WIPHY_FLAG_SUPPORTS_5_10_MHZ | 4437*f79cbc77SKalle Valo WIPHY_FLAG_HAS_CHANNEL_SWITCH; 4438*f79cbc77SKalle Valo hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | 4439*f79cbc77SKalle Valo NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | 4440*f79cbc77SKalle Valo NL80211_FEATURE_STATIC_SMPS | 4441*f79cbc77SKalle Valo NL80211_FEATURE_DYNAMIC_SMPS | 4442*f79cbc77SKalle Valo NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; 4443*f79cbc77SKalle Valo wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); 4444*f79cbc77SKalle Valo wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION); 4445*f79cbc77SKalle Valo wiphy_ext_feature_set(hw->wiphy, 4446*f79cbc77SKalle Valo NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS); 4447*f79cbc77SKalle Valo wiphy_ext_feature_set(hw->wiphy, 4448*f79cbc77SKalle Valo NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); 4449*f79cbc77SKalle Valo 4450*f79cbc77SKalle Valo wiphy_ext_feature_set(hw->wiphy, 4451*f79cbc77SKalle Valo NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT); 4452*f79cbc77SKalle Valo 4453*f79cbc77SKalle Valo hw->wiphy->interface_modes = param->iftypes; 4454*f79cbc77SKalle Valo 4455*f79cbc77SKalle Valo /* ask mac80211 to reserve space for magic */ 4456*f79cbc77SKalle Valo hw->vif_data_size = sizeof(struct hwsim_vif_priv); 4457*f79cbc77SKalle Valo hw->sta_data_size = sizeof(struct hwsim_sta_priv); 4458*f79cbc77SKalle Valo hw->chanctx_data_size = sizeof(struct hwsim_chanctx_priv); 4459*f79cbc77SKalle Valo 4460*f79cbc77SKalle Valo memcpy(data->channels_2ghz, hwsim_channels_2ghz, 4461*f79cbc77SKalle Valo sizeof(hwsim_channels_2ghz)); 4462*f79cbc77SKalle Valo memcpy(data->channels_5ghz, hwsim_channels_5ghz, 4463*f79cbc77SKalle Valo sizeof(hwsim_channels_5ghz)); 4464*f79cbc77SKalle Valo memcpy(data->channels_6ghz, hwsim_channels_6ghz, 4465*f79cbc77SKalle Valo sizeof(hwsim_channels_6ghz)); 4466*f79cbc77SKalle Valo memcpy(data->channels_s1g, hwsim_channels_s1g, 4467*f79cbc77SKalle Valo sizeof(hwsim_channels_s1g)); 4468*f79cbc77SKalle Valo memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); 4469*f79cbc77SKalle Valo 4470*f79cbc77SKalle Valo for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { 4471*f79cbc77SKalle Valo struct ieee80211_supported_band *sband = &data->bands[band]; 4472*f79cbc77SKalle Valo 4473*f79cbc77SKalle Valo sband->band = band; 4474*f79cbc77SKalle Valo 4475*f79cbc77SKalle Valo switch (band) { 4476*f79cbc77SKalle Valo case NL80211_BAND_2GHZ: 4477*f79cbc77SKalle Valo sband->channels = data->channels_2ghz; 4478*f79cbc77SKalle Valo sband->n_channels = ARRAY_SIZE(hwsim_channels_2ghz); 4479*f79cbc77SKalle Valo sband->bitrates = data->rates; 4480*f79cbc77SKalle Valo sband->n_bitrates = ARRAY_SIZE(hwsim_rates); 4481*f79cbc77SKalle Valo break; 4482*f79cbc77SKalle Valo case NL80211_BAND_5GHZ: 4483*f79cbc77SKalle Valo sband->channels = data->channels_5ghz; 4484*f79cbc77SKalle Valo sband->n_channels = ARRAY_SIZE(hwsim_channels_5ghz); 4485*f79cbc77SKalle Valo sband->bitrates = data->rates + 4; 4486*f79cbc77SKalle Valo sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; 4487*f79cbc77SKalle Valo 4488*f79cbc77SKalle Valo sband->vht_cap.vht_supported = true; 4489*f79cbc77SKalle Valo sband->vht_cap.cap = 4490*f79cbc77SKalle Valo IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | 4491*f79cbc77SKalle Valo IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | 4492*f79cbc77SKalle Valo IEEE80211_VHT_CAP_RXLDPC | 4493*f79cbc77SKalle Valo IEEE80211_VHT_CAP_SHORT_GI_80 | 4494*f79cbc77SKalle Valo IEEE80211_VHT_CAP_SHORT_GI_160 | 4495*f79cbc77SKalle Valo IEEE80211_VHT_CAP_TXSTBC | 4496*f79cbc77SKalle Valo IEEE80211_VHT_CAP_RXSTBC_4 | 4497*f79cbc77SKalle Valo IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; 4498*f79cbc77SKalle Valo sband->vht_cap.vht_mcs.rx_mcs_map = 4499*f79cbc77SKalle Valo cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | 4500*f79cbc77SKalle Valo IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | 4501*f79cbc77SKalle Valo IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | 4502*f79cbc77SKalle Valo IEEE80211_VHT_MCS_SUPPORT_0_9 << 6 | 4503*f79cbc77SKalle Valo IEEE80211_VHT_MCS_SUPPORT_0_9 << 8 | 4504*f79cbc77SKalle Valo IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | 4505*f79cbc77SKalle Valo IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | 4506*f79cbc77SKalle Valo IEEE80211_VHT_MCS_SUPPORT_0_9 << 14); 4507*f79cbc77SKalle Valo sband->vht_cap.vht_mcs.tx_mcs_map = 4508*f79cbc77SKalle Valo sband->vht_cap.vht_mcs.rx_mcs_map; 4509*f79cbc77SKalle Valo break; 4510*f79cbc77SKalle Valo case NL80211_BAND_6GHZ: 4511*f79cbc77SKalle Valo sband->channels = data->channels_6ghz; 4512*f79cbc77SKalle Valo sband->n_channels = ARRAY_SIZE(hwsim_channels_6ghz); 4513*f79cbc77SKalle Valo sband->bitrates = data->rates + 4; 4514*f79cbc77SKalle Valo sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4; 4515*f79cbc77SKalle Valo break; 4516*f79cbc77SKalle Valo case NL80211_BAND_S1GHZ: 4517*f79cbc77SKalle Valo memcpy(&sband->s1g_cap, &hwsim_s1g_cap, 4518*f79cbc77SKalle Valo sizeof(sband->s1g_cap)); 4519*f79cbc77SKalle Valo sband->channels = data->channels_s1g; 4520*f79cbc77SKalle Valo sband->n_channels = ARRAY_SIZE(hwsim_channels_s1g); 4521*f79cbc77SKalle Valo break; 4522*f79cbc77SKalle Valo default: 4523*f79cbc77SKalle Valo continue; 4524*f79cbc77SKalle Valo } 4525*f79cbc77SKalle Valo 4526*f79cbc77SKalle Valo if (band != NL80211_BAND_6GHZ){ 4527*f79cbc77SKalle Valo sband->ht_cap.ht_supported = true; 4528*f79cbc77SKalle Valo sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 4529*f79cbc77SKalle Valo IEEE80211_HT_CAP_GRN_FLD | 4530*f79cbc77SKalle Valo IEEE80211_HT_CAP_SGI_20 | 4531*f79cbc77SKalle Valo IEEE80211_HT_CAP_SGI_40 | 4532*f79cbc77SKalle Valo IEEE80211_HT_CAP_DSSSCCK40; 4533*f79cbc77SKalle Valo sband->ht_cap.ampdu_factor = 0x3; 4534*f79cbc77SKalle Valo sband->ht_cap.ampdu_density = 0x6; 4535*f79cbc77SKalle Valo memset(&sband->ht_cap.mcs, 0, 4536*f79cbc77SKalle Valo sizeof(sband->ht_cap.mcs)); 4537*f79cbc77SKalle Valo sband->ht_cap.mcs.rx_mask[0] = 0xff; 4538*f79cbc77SKalle Valo sband->ht_cap.mcs.rx_mask[1] = 0xff; 4539*f79cbc77SKalle Valo sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 4540*f79cbc77SKalle Valo } 4541*f79cbc77SKalle Valo 4542*f79cbc77SKalle Valo mac80211_hwsim_sband_capab(sband); 4543*f79cbc77SKalle Valo 4544*f79cbc77SKalle Valo hw->wiphy->bands[band] = sband; 4545*f79cbc77SKalle Valo } 4546*f79cbc77SKalle Valo 4547*f79cbc77SKalle Valo /* By default all radios belong to the first group */ 4548*f79cbc77SKalle Valo data->group = 1; 4549*f79cbc77SKalle Valo mutex_init(&data->mutex); 4550*f79cbc77SKalle Valo 4551*f79cbc77SKalle Valo data->netgroup = hwsim_net_get_netgroup(net); 4552*f79cbc77SKalle Valo data->wmediumd = hwsim_net_get_wmediumd(net); 4553*f79cbc77SKalle Valo 4554*f79cbc77SKalle Valo /* Enable frame retransmissions for lossy channels */ 4555*f79cbc77SKalle Valo hw->max_rates = 4; 4556*f79cbc77SKalle Valo hw->max_rate_tries = 11; 4557*f79cbc77SKalle Valo 4558*f79cbc77SKalle Valo hw->wiphy->vendor_commands = mac80211_hwsim_vendor_commands; 4559*f79cbc77SKalle Valo hw->wiphy->n_vendor_commands = 4560*f79cbc77SKalle Valo ARRAY_SIZE(mac80211_hwsim_vendor_commands); 4561*f79cbc77SKalle Valo hw->wiphy->vendor_events = mac80211_hwsim_vendor_events; 4562*f79cbc77SKalle Valo hw->wiphy->n_vendor_events = ARRAY_SIZE(mac80211_hwsim_vendor_events); 4563*f79cbc77SKalle Valo 4564*f79cbc77SKalle Valo if (param->reg_strict) 4565*f79cbc77SKalle Valo hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; 4566*f79cbc77SKalle Valo if (param->regd) { 4567*f79cbc77SKalle Valo data->regd = param->regd; 4568*f79cbc77SKalle Valo hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; 4569*f79cbc77SKalle Valo wiphy_apply_custom_regulatory(hw->wiphy, param->regd); 4570*f79cbc77SKalle Valo /* give the regulatory workqueue a chance to run */ 4571*f79cbc77SKalle Valo schedule_timeout_interruptible(1); 4572*f79cbc77SKalle Valo } 4573*f79cbc77SKalle Valo 4574*f79cbc77SKalle Valo if (param->no_vif) 4575*f79cbc77SKalle Valo ieee80211_hw_set(hw, NO_AUTO_VIF); 4576*f79cbc77SKalle Valo 4577*f79cbc77SKalle Valo wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); 4578*f79cbc77SKalle Valo 4579*f79cbc77SKalle Valo for (i = 0; i < ARRAY_SIZE(data->link_data); i++) { 4580*f79cbc77SKalle Valo hrtimer_init(&data->link_data[i].beacon_timer, CLOCK_MONOTONIC, 4581*f79cbc77SKalle Valo HRTIMER_MODE_ABS_SOFT); 4582*f79cbc77SKalle Valo data->link_data[i].beacon_timer.function = 4583*f79cbc77SKalle Valo mac80211_hwsim_beacon; 4584*f79cbc77SKalle Valo data->link_data[i].link_id = i; 4585*f79cbc77SKalle Valo } 4586*f79cbc77SKalle Valo 4587*f79cbc77SKalle Valo err = ieee80211_register_hw(hw); 4588*f79cbc77SKalle Valo if (err < 0) { 4589*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: ieee80211_register_hw failed (%d)\n", 4590*f79cbc77SKalle Valo err); 4591*f79cbc77SKalle Valo goto failed_hw; 4592*f79cbc77SKalle Valo } 4593*f79cbc77SKalle Valo 4594*f79cbc77SKalle Valo wiphy_dbg(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); 4595*f79cbc77SKalle Valo 4596*f79cbc77SKalle Valo if (param->reg_alpha2) { 4597*f79cbc77SKalle Valo data->alpha2[0] = param->reg_alpha2[0]; 4598*f79cbc77SKalle Valo data->alpha2[1] = param->reg_alpha2[1]; 4599*f79cbc77SKalle Valo regulatory_hint(hw->wiphy, param->reg_alpha2); 4600*f79cbc77SKalle Valo } 4601*f79cbc77SKalle Valo 4602*f79cbc77SKalle Valo data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); 4603*f79cbc77SKalle Valo debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); 4604*f79cbc77SKalle Valo debugfs_create_file("group", 0666, data->debugfs, data, 4605*f79cbc77SKalle Valo &hwsim_fops_group); 4606*f79cbc77SKalle Valo debugfs_create_file("rx_rssi", 0666, data->debugfs, data, 4607*f79cbc77SKalle Valo &hwsim_fops_rx_rssi); 4608*f79cbc77SKalle Valo if (!data->use_chanctx) 4609*f79cbc77SKalle Valo debugfs_create_file("dfs_simulate_radar", 0222, 4610*f79cbc77SKalle Valo data->debugfs, 4611*f79cbc77SKalle Valo data, &hwsim_simulate_radar); 4612*f79cbc77SKalle Valo 4613*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 4614*f79cbc77SKalle Valo err = rhashtable_insert_fast(&hwsim_radios_rht, &data->rht, 4615*f79cbc77SKalle Valo hwsim_rht_params); 4616*f79cbc77SKalle Valo if (err < 0) { 4617*f79cbc77SKalle Valo if (info) { 4618*f79cbc77SKalle Valo GENL_SET_ERR_MSG(info, "perm addr already present"); 4619*f79cbc77SKalle Valo NL_SET_BAD_ATTR(info->extack, 4620*f79cbc77SKalle Valo info->attrs[HWSIM_ATTR_PERM_ADDR]); 4621*f79cbc77SKalle Valo } 4622*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 4623*f79cbc77SKalle Valo goto failed_final_insert; 4624*f79cbc77SKalle Valo } 4625*f79cbc77SKalle Valo 4626*f79cbc77SKalle Valo list_add_tail(&data->list, &hwsim_radios); 4627*f79cbc77SKalle Valo hwsim_radios_generation++; 4628*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 4629*f79cbc77SKalle Valo 4630*f79cbc77SKalle Valo hwsim_mcast_new_radio(idx, info, param); 4631*f79cbc77SKalle Valo 4632*f79cbc77SKalle Valo return idx; 4633*f79cbc77SKalle Valo 4634*f79cbc77SKalle Valo failed_final_insert: 4635*f79cbc77SKalle Valo debugfs_remove_recursive(data->debugfs); 4636*f79cbc77SKalle Valo ieee80211_unregister_hw(data->hw); 4637*f79cbc77SKalle Valo failed_hw: 4638*f79cbc77SKalle Valo device_release_driver(data->dev); 4639*f79cbc77SKalle Valo failed_bind: 4640*f79cbc77SKalle Valo device_unregister(data->dev); 4641*f79cbc77SKalle Valo failed_drvdata: 4642*f79cbc77SKalle Valo ieee80211_free_hw(hw); 4643*f79cbc77SKalle Valo failed: 4644*f79cbc77SKalle Valo return err; 4645*f79cbc77SKalle Valo } 4646*f79cbc77SKalle Valo 4647*f79cbc77SKalle Valo static void hwsim_mcast_del_radio(int id, const char *hwname, 4648*f79cbc77SKalle Valo struct genl_info *info) 4649*f79cbc77SKalle Valo { 4650*f79cbc77SKalle Valo struct sk_buff *skb; 4651*f79cbc77SKalle Valo void *data; 4652*f79cbc77SKalle Valo int ret; 4653*f79cbc77SKalle Valo 4654*f79cbc77SKalle Valo skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 4655*f79cbc77SKalle Valo if (!skb) 4656*f79cbc77SKalle Valo return; 4657*f79cbc77SKalle Valo 4658*f79cbc77SKalle Valo data = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, 4659*f79cbc77SKalle Valo HWSIM_CMD_DEL_RADIO); 4660*f79cbc77SKalle Valo if (!data) 4661*f79cbc77SKalle Valo goto error; 4662*f79cbc77SKalle Valo 4663*f79cbc77SKalle Valo ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id); 4664*f79cbc77SKalle Valo if (ret < 0) 4665*f79cbc77SKalle Valo goto error; 4666*f79cbc77SKalle Valo 4667*f79cbc77SKalle Valo ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, strlen(hwname), 4668*f79cbc77SKalle Valo hwname); 4669*f79cbc77SKalle Valo if (ret < 0) 4670*f79cbc77SKalle Valo goto error; 4671*f79cbc77SKalle Valo 4672*f79cbc77SKalle Valo genlmsg_end(skb, data); 4673*f79cbc77SKalle Valo 4674*f79cbc77SKalle Valo hwsim_mcast_config_msg(skb, info); 4675*f79cbc77SKalle Valo 4676*f79cbc77SKalle Valo return; 4677*f79cbc77SKalle Valo 4678*f79cbc77SKalle Valo error: 4679*f79cbc77SKalle Valo nlmsg_free(skb); 4680*f79cbc77SKalle Valo } 4681*f79cbc77SKalle Valo 4682*f79cbc77SKalle Valo static void mac80211_hwsim_del_radio(struct mac80211_hwsim_data *data, 4683*f79cbc77SKalle Valo const char *hwname, 4684*f79cbc77SKalle Valo struct genl_info *info) 4685*f79cbc77SKalle Valo { 4686*f79cbc77SKalle Valo hwsim_mcast_del_radio(data->idx, hwname, info); 4687*f79cbc77SKalle Valo debugfs_remove_recursive(data->debugfs); 4688*f79cbc77SKalle Valo ieee80211_unregister_hw(data->hw); 4689*f79cbc77SKalle Valo device_release_driver(data->dev); 4690*f79cbc77SKalle Valo device_unregister(data->dev); 4691*f79cbc77SKalle Valo ieee80211_free_hw(data->hw); 4692*f79cbc77SKalle Valo } 4693*f79cbc77SKalle Valo 4694*f79cbc77SKalle Valo static int mac80211_hwsim_get_radio(struct sk_buff *skb, 4695*f79cbc77SKalle Valo struct mac80211_hwsim_data *data, 4696*f79cbc77SKalle Valo u32 portid, u32 seq, 4697*f79cbc77SKalle Valo struct netlink_callback *cb, int flags) 4698*f79cbc77SKalle Valo { 4699*f79cbc77SKalle Valo void *hdr; 4700*f79cbc77SKalle Valo struct hwsim_new_radio_params param = { }; 4701*f79cbc77SKalle Valo int res = -EMSGSIZE; 4702*f79cbc77SKalle Valo 4703*f79cbc77SKalle Valo hdr = genlmsg_put(skb, portid, seq, &hwsim_genl_family, flags, 4704*f79cbc77SKalle Valo HWSIM_CMD_GET_RADIO); 4705*f79cbc77SKalle Valo if (!hdr) 4706*f79cbc77SKalle Valo return -EMSGSIZE; 4707*f79cbc77SKalle Valo 4708*f79cbc77SKalle Valo if (cb) 4709*f79cbc77SKalle Valo genl_dump_check_consistent(cb, hdr); 4710*f79cbc77SKalle Valo 4711*f79cbc77SKalle Valo if (data->alpha2[0] && data->alpha2[1]) 4712*f79cbc77SKalle Valo param.reg_alpha2 = data->alpha2; 4713*f79cbc77SKalle Valo 4714*f79cbc77SKalle Valo param.reg_strict = !!(data->hw->wiphy->regulatory_flags & 4715*f79cbc77SKalle Valo REGULATORY_STRICT_REG); 4716*f79cbc77SKalle Valo param.p2p_device = !!(data->hw->wiphy->interface_modes & 4717*f79cbc77SKalle Valo BIT(NL80211_IFTYPE_P2P_DEVICE)); 4718*f79cbc77SKalle Valo param.use_chanctx = data->use_chanctx; 4719*f79cbc77SKalle Valo param.regd = data->regd; 4720*f79cbc77SKalle Valo param.channels = data->channels; 4721*f79cbc77SKalle Valo param.hwname = wiphy_name(data->hw->wiphy); 4722*f79cbc77SKalle Valo 4723*f79cbc77SKalle Valo res = append_radio_msg(skb, data->idx, ¶m); 4724*f79cbc77SKalle Valo if (res < 0) 4725*f79cbc77SKalle Valo goto out_err; 4726*f79cbc77SKalle Valo 4727*f79cbc77SKalle Valo genlmsg_end(skb, hdr); 4728*f79cbc77SKalle Valo return 0; 4729*f79cbc77SKalle Valo 4730*f79cbc77SKalle Valo out_err: 4731*f79cbc77SKalle Valo genlmsg_cancel(skb, hdr); 4732*f79cbc77SKalle Valo return res; 4733*f79cbc77SKalle Valo } 4734*f79cbc77SKalle Valo 4735*f79cbc77SKalle Valo static void mac80211_hwsim_free(void) 4736*f79cbc77SKalle Valo { 4737*f79cbc77SKalle Valo struct mac80211_hwsim_data *data; 4738*f79cbc77SKalle Valo 4739*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 4740*f79cbc77SKalle Valo while ((data = list_first_entry_or_null(&hwsim_radios, 4741*f79cbc77SKalle Valo struct mac80211_hwsim_data, 4742*f79cbc77SKalle Valo list))) { 4743*f79cbc77SKalle Valo list_del(&data->list); 4744*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 4745*f79cbc77SKalle Valo mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), 4746*f79cbc77SKalle Valo NULL); 4747*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 4748*f79cbc77SKalle Valo } 4749*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 4750*f79cbc77SKalle Valo class_destroy(hwsim_class); 4751*f79cbc77SKalle Valo } 4752*f79cbc77SKalle Valo 4753*f79cbc77SKalle Valo static const struct net_device_ops hwsim_netdev_ops = { 4754*f79cbc77SKalle Valo .ndo_start_xmit = hwsim_mon_xmit, 4755*f79cbc77SKalle Valo .ndo_set_mac_address = eth_mac_addr, 4756*f79cbc77SKalle Valo .ndo_validate_addr = eth_validate_addr, 4757*f79cbc77SKalle Valo }; 4758*f79cbc77SKalle Valo 4759*f79cbc77SKalle Valo static void hwsim_mon_setup(struct net_device *dev) 4760*f79cbc77SKalle Valo { 4761*f79cbc77SKalle Valo u8 addr[ETH_ALEN]; 4762*f79cbc77SKalle Valo 4763*f79cbc77SKalle Valo dev->netdev_ops = &hwsim_netdev_ops; 4764*f79cbc77SKalle Valo dev->needs_free_netdev = true; 4765*f79cbc77SKalle Valo ether_setup(dev); 4766*f79cbc77SKalle Valo dev->priv_flags |= IFF_NO_QUEUE; 4767*f79cbc77SKalle Valo dev->type = ARPHRD_IEEE80211_RADIOTAP; 4768*f79cbc77SKalle Valo eth_zero_addr(addr); 4769*f79cbc77SKalle Valo addr[0] = 0x12; 4770*f79cbc77SKalle Valo eth_hw_addr_set(dev, addr); 4771*f79cbc77SKalle Valo } 4772*f79cbc77SKalle Valo 4773*f79cbc77SKalle Valo static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(const u8 *addr) 4774*f79cbc77SKalle Valo { 4775*f79cbc77SKalle Valo return rhashtable_lookup_fast(&hwsim_radios_rht, 4776*f79cbc77SKalle Valo addr, 4777*f79cbc77SKalle Valo hwsim_rht_params); 4778*f79cbc77SKalle Valo } 4779*f79cbc77SKalle Valo 4780*f79cbc77SKalle Valo static void hwsim_register_wmediumd(struct net *net, u32 portid) 4781*f79cbc77SKalle Valo { 4782*f79cbc77SKalle Valo struct mac80211_hwsim_data *data; 4783*f79cbc77SKalle Valo 4784*f79cbc77SKalle Valo hwsim_net_set_wmediumd(net, portid); 4785*f79cbc77SKalle Valo 4786*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 4787*f79cbc77SKalle Valo list_for_each_entry(data, &hwsim_radios, list) { 4788*f79cbc77SKalle Valo if (data->netgroup == hwsim_net_get_netgroup(net)) 4789*f79cbc77SKalle Valo data->wmediumd = portid; 4790*f79cbc77SKalle Valo } 4791*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 4792*f79cbc77SKalle Valo } 4793*f79cbc77SKalle Valo 4794*f79cbc77SKalle Valo static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, 4795*f79cbc77SKalle Valo struct genl_info *info) 4796*f79cbc77SKalle Valo { 4797*f79cbc77SKalle Valo 4798*f79cbc77SKalle Valo struct ieee80211_hdr *hdr; 4799*f79cbc77SKalle Valo struct mac80211_hwsim_data *data2; 4800*f79cbc77SKalle Valo struct ieee80211_tx_info *txi; 4801*f79cbc77SKalle Valo struct hwsim_tx_rate *tx_attempts; 4802*f79cbc77SKalle Valo u64 ret_skb_cookie; 4803*f79cbc77SKalle Valo struct sk_buff *skb, *tmp; 4804*f79cbc77SKalle Valo const u8 *src; 4805*f79cbc77SKalle Valo unsigned int hwsim_flags; 4806*f79cbc77SKalle Valo int i; 4807*f79cbc77SKalle Valo unsigned long flags; 4808*f79cbc77SKalle Valo bool found = false; 4809*f79cbc77SKalle Valo 4810*f79cbc77SKalle Valo if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || 4811*f79cbc77SKalle Valo !info->attrs[HWSIM_ATTR_FLAGS] || 4812*f79cbc77SKalle Valo !info->attrs[HWSIM_ATTR_COOKIE] || 4813*f79cbc77SKalle Valo !info->attrs[HWSIM_ATTR_SIGNAL] || 4814*f79cbc77SKalle Valo !info->attrs[HWSIM_ATTR_TX_INFO]) 4815*f79cbc77SKalle Valo goto out; 4816*f79cbc77SKalle Valo 4817*f79cbc77SKalle Valo src = (void *)nla_data(info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]); 4818*f79cbc77SKalle Valo hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]); 4819*f79cbc77SKalle Valo ret_skb_cookie = nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]); 4820*f79cbc77SKalle Valo 4821*f79cbc77SKalle Valo data2 = get_hwsim_data_ref_from_addr(src); 4822*f79cbc77SKalle Valo if (!data2) 4823*f79cbc77SKalle Valo goto out; 4824*f79cbc77SKalle Valo 4825*f79cbc77SKalle Valo if (!hwsim_virtio_enabled) { 4826*f79cbc77SKalle Valo if (hwsim_net_get_netgroup(genl_info_net(info)) != 4827*f79cbc77SKalle Valo data2->netgroup) 4828*f79cbc77SKalle Valo goto out; 4829*f79cbc77SKalle Valo 4830*f79cbc77SKalle Valo if (info->snd_portid != data2->wmediumd) 4831*f79cbc77SKalle Valo goto out; 4832*f79cbc77SKalle Valo } 4833*f79cbc77SKalle Valo 4834*f79cbc77SKalle Valo /* look for the skb matching the cookie passed back from user */ 4835*f79cbc77SKalle Valo spin_lock_irqsave(&data2->pending.lock, flags); 4836*f79cbc77SKalle Valo skb_queue_walk_safe(&data2->pending, skb, tmp) { 4837*f79cbc77SKalle Valo uintptr_t skb_cookie; 4838*f79cbc77SKalle Valo 4839*f79cbc77SKalle Valo txi = IEEE80211_SKB_CB(skb); 4840*f79cbc77SKalle Valo skb_cookie = (uintptr_t)txi->rate_driver_data[0]; 4841*f79cbc77SKalle Valo 4842*f79cbc77SKalle Valo if (skb_cookie == ret_skb_cookie) { 4843*f79cbc77SKalle Valo __skb_unlink(skb, &data2->pending); 4844*f79cbc77SKalle Valo found = true; 4845*f79cbc77SKalle Valo break; 4846*f79cbc77SKalle Valo } 4847*f79cbc77SKalle Valo } 4848*f79cbc77SKalle Valo spin_unlock_irqrestore(&data2->pending.lock, flags); 4849*f79cbc77SKalle Valo 4850*f79cbc77SKalle Valo /* not found */ 4851*f79cbc77SKalle Valo if (!found) 4852*f79cbc77SKalle Valo goto out; 4853*f79cbc77SKalle Valo 4854*f79cbc77SKalle Valo /* Tx info received because the frame was broadcasted on user space, 4855*f79cbc77SKalle Valo so we get all the necessary info: tx attempts and skb control buff */ 4856*f79cbc77SKalle Valo 4857*f79cbc77SKalle Valo tx_attempts = (struct hwsim_tx_rate *)nla_data( 4858*f79cbc77SKalle Valo info->attrs[HWSIM_ATTR_TX_INFO]); 4859*f79cbc77SKalle Valo 4860*f79cbc77SKalle Valo /* now send back TX status */ 4861*f79cbc77SKalle Valo txi = IEEE80211_SKB_CB(skb); 4862*f79cbc77SKalle Valo 4863*f79cbc77SKalle Valo ieee80211_tx_info_clear_status(txi); 4864*f79cbc77SKalle Valo 4865*f79cbc77SKalle Valo for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 4866*f79cbc77SKalle Valo txi->status.rates[i].idx = tx_attempts[i].idx; 4867*f79cbc77SKalle Valo txi->status.rates[i].count = tx_attempts[i].count; 4868*f79cbc77SKalle Valo } 4869*f79cbc77SKalle Valo 4870*f79cbc77SKalle Valo txi->status.ack_signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); 4871*f79cbc77SKalle Valo 4872*f79cbc77SKalle Valo if (!(hwsim_flags & HWSIM_TX_CTL_NO_ACK) && 4873*f79cbc77SKalle Valo (hwsim_flags & HWSIM_TX_STAT_ACK)) { 4874*f79cbc77SKalle Valo if (skb->len >= 16) { 4875*f79cbc77SKalle Valo hdr = (struct ieee80211_hdr *) skb->data; 4876*f79cbc77SKalle Valo mac80211_hwsim_monitor_ack(data2->channel, 4877*f79cbc77SKalle Valo hdr->addr2); 4878*f79cbc77SKalle Valo } 4879*f79cbc77SKalle Valo txi->flags |= IEEE80211_TX_STAT_ACK; 4880*f79cbc77SKalle Valo } 4881*f79cbc77SKalle Valo 4882*f79cbc77SKalle Valo if (hwsim_flags & HWSIM_TX_CTL_NO_ACK) 4883*f79cbc77SKalle Valo txi->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; 4884*f79cbc77SKalle Valo 4885*f79cbc77SKalle Valo ieee80211_tx_status_irqsafe(data2->hw, skb); 4886*f79cbc77SKalle Valo return 0; 4887*f79cbc77SKalle Valo out: 4888*f79cbc77SKalle Valo return -EINVAL; 4889*f79cbc77SKalle Valo 4890*f79cbc77SKalle Valo } 4891*f79cbc77SKalle Valo 4892*f79cbc77SKalle Valo static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, 4893*f79cbc77SKalle Valo struct genl_info *info) 4894*f79cbc77SKalle Valo { 4895*f79cbc77SKalle Valo struct mac80211_hwsim_data *data2; 4896*f79cbc77SKalle Valo struct ieee80211_rx_status rx_status; 4897*f79cbc77SKalle Valo struct ieee80211_hdr *hdr; 4898*f79cbc77SKalle Valo const u8 *dst; 4899*f79cbc77SKalle Valo int frame_data_len; 4900*f79cbc77SKalle Valo void *frame_data; 4901*f79cbc77SKalle Valo struct sk_buff *skb = NULL; 4902*f79cbc77SKalle Valo struct ieee80211_channel *channel = NULL; 4903*f79cbc77SKalle Valo 4904*f79cbc77SKalle Valo if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || 4905*f79cbc77SKalle Valo !info->attrs[HWSIM_ATTR_FRAME] || 4906*f79cbc77SKalle Valo !info->attrs[HWSIM_ATTR_RX_RATE] || 4907*f79cbc77SKalle Valo !info->attrs[HWSIM_ATTR_SIGNAL]) 4908*f79cbc77SKalle Valo goto out; 4909*f79cbc77SKalle Valo 4910*f79cbc77SKalle Valo dst = (void *)nla_data(info->attrs[HWSIM_ATTR_ADDR_RECEIVER]); 4911*f79cbc77SKalle Valo frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]); 4912*f79cbc77SKalle Valo frame_data = (void *)nla_data(info->attrs[HWSIM_ATTR_FRAME]); 4913*f79cbc77SKalle Valo 4914*f79cbc77SKalle Valo /* Allocate new skb here */ 4915*f79cbc77SKalle Valo skb = alloc_skb(frame_data_len, GFP_KERNEL); 4916*f79cbc77SKalle Valo if (skb == NULL) 4917*f79cbc77SKalle Valo goto err; 4918*f79cbc77SKalle Valo 4919*f79cbc77SKalle Valo if (frame_data_len > IEEE80211_MAX_DATA_LEN) 4920*f79cbc77SKalle Valo goto err; 4921*f79cbc77SKalle Valo 4922*f79cbc77SKalle Valo /* Copy the data */ 4923*f79cbc77SKalle Valo skb_put_data(skb, frame_data, frame_data_len); 4924*f79cbc77SKalle Valo 4925*f79cbc77SKalle Valo data2 = get_hwsim_data_ref_from_addr(dst); 4926*f79cbc77SKalle Valo if (!data2) 4927*f79cbc77SKalle Valo goto out; 4928*f79cbc77SKalle Valo 4929*f79cbc77SKalle Valo if (data2->use_chanctx) { 4930*f79cbc77SKalle Valo if (data2->tmp_chan) 4931*f79cbc77SKalle Valo channel = data2->tmp_chan; 4932*f79cbc77SKalle Valo } else { 4933*f79cbc77SKalle Valo channel = data2->channel; 4934*f79cbc77SKalle Valo } 4935*f79cbc77SKalle Valo 4936*f79cbc77SKalle Valo if (!hwsim_virtio_enabled) { 4937*f79cbc77SKalle Valo if (hwsim_net_get_netgroup(genl_info_net(info)) != 4938*f79cbc77SKalle Valo data2->netgroup) 4939*f79cbc77SKalle Valo goto out; 4940*f79cbc77SKalle Valo 4941*f79cbc77SKalle Valo if (info->snd_portid != data2->wmediumd) 4942*f79cbc77SKalle Valo goto out; 4943*f79cbc77SKalle Valo } 4944*f79cbc77SKalle Valo 4945*f79cbc77SKalle Valo /* check if radio is configured properly */ 4946*f79cbc77SKalle Valo 4947*f79cbc77SKalle Valo if ((data2->idle && !data2->tmp_chan) || !data2->started) 4948*f79cbc77SKalle Valo goto out; 4949*f79cbc77SKalle Valo 4950*f79cbc77SKalle Valo /* A frame is received from user space */ 4951*f79cbc77SKalle Valo memset(&rx_status, 0, sizeof(rx_status)); 4952*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_FREQ]) { 4953*f79cbc77SKalle Valo struct tx_iter_data iter_data = {}; 4954*f79cbc77SKalle Valo 4955*f79cbc77SKalle Valo /* throw away off-channel packets, but allow both the temporary 4956*f79cbc77SKalle Valo * ("hw" scan/remain-on-channel), regular channels and links, 4957*f79cbc77SKalle Valo * since the internal datapath also allows this 4958*f79cbc77SKalle Valo */ 4959*f79cbc77SKalle Valo rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]); 4960*f79cbc77SKalle Valo 4961*f79cbc77SKalle Valo iter_data.channel = ieee80211_get_channel(data2->hw->wiphy, 4962*f79cbc77SKalle Valo rx_status.freq); 4963*f79cbc77SKalle Valo if (!iter_data.channel) 4964*f79cbc77SKalle Valo goto out; 4965*f79cbc77SKalle Valo rx_status.band = iter_data.channel->band; 4966*f79cbc77SKalle Valo 4967*f79cbc77SKalle Valo mutex_lock(&data2->mutex); 4968*f79cbc77SKalle Valo if (!hwsim_chans_compat(iter_data.channel, channel)) { 4969*f79cbc77SKalle Valo ieee80211_iterate_active_interfaces_atomic( 4970*f79cbc77SKalle Valo data2->hw, IEEE80211_IFACE_ITER_NORMAL, 4971*f79cbc77SKalle Valo mac80211_hwsim_tx_iter, &iter_data); 4972*f79cbc77SKalle Valo if (!iter_data.receive) { 4973*f79cbc77SKalle Valo mutex_unlock(&data2->mutex); 4974*f79cbc77SKalle Valo goto out; 4975*f79cbc77SKalle Valo } 4976*f79cbc77SKalle Valo } 4977*f79cbc77SKalle Valo mutex_unlock(&data2->mutex); 4978*f79cbc77SKalle Valo } else if (!channel) { 4979*f79cbc77SKalle Valo goto out; 4980*f79cbc77SKalle Valo } else { 4981*f79cbc77SKalle Valo rx_status.freq = channel->center_freq; 4982*f79cbc77SKalle Valo rx_status.band = channel->band; 4983*f79cbc77SKalle Valo } 4984*f79cbc77SKalle Valo 4985*f79cbc77SKalle Valo rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); 4986*f79cbc77SKalle Valo if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates) 4987*f79cbc77SKalle Valo goto out; 4988*f79cbc77SKalle Valo rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); 4989*f79cbc77SKalle Valo 4990*f79cbc77SKalle Valo hdr = (void *)skb->data; 4991*f79cbc77SKalle Valo 4992*f79cbc77SKalle Valo if (ieee80211_is_beacon(hdr->frame_control) || 4993*f79cbc77SKalle Valo ieee80211_is_probe_resp(hdr->frame_control)) 4994*f79cbc77SKalle Valo rx_status.boottime_ns = ktime_get_boottime_ns(); 4995*f79cbc77SKalle Valo 4996*f79cbc77SKalle Valo mac80211_hwsim_rx(data2, &rx_status, skb); 4997*f79cbc77SKalle Valo 4998*f79cbc77SKalle Valo return 0; 4999*f79cbc77SKalle Valo err: 5000*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: error occurred in %s\n", __func__); 5001*f79cbc77SKalle Valo out: 5002*f79cbc77SKalle Valo dev_kfree_skb(skb); 5003*f79cbc77SKalle Valo return -EINVAL; 5004*f79cbc77SKalle Valo } 5005*f79cbc77SKalle Valo 5006*f79cbc77SKalle Valo static int hwsim_register_received_nl(struct sk_buff *skb_2, 5007*f79cbc77SKalle Valo struct genl_info *info) 5008*f79cbc77SKalle Valo { 5009*f79cbc77SKalle Valo struct net *net = genl_info_net(info); 5010*f79cbc77SKalle Valo struct mac80211_hwsim_data *data; 5011*f79cbc77SKalle Valo int chans = 1; 5012*f79cbc77SKalle Valo 5013*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 5014*f79cbc77SKalle Valo list_for_each_entry(data, &hwsim_radios, list) 5015*f79cbc77SKalle Valo chans = max(chans, data->channels); 5016*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 5017*f79cbc77SKalle Valo 5018*f79cbc77SKalle Valo /* In the future we should revise the userspace API and allow it 5019*f79cbc77SKalle Valo * to set a flag that it does support multi-channel, then we can 5020*f79cbc77SKalle Valo * let this pass conditionally on the flag. 5021*f79cbc77SKalle Valo * For current userspace, prohibit it since it won't work right. 5022*f79cbc77SKalle Valo */ 5023*f79cbc77SKalle Valo if (chans > 1) 5024*f79cbc77SKalle Valo return -EOPNOTSUPP; 5025*f79cbc77SKalle Valo 5026*f79cbc77SKalle Valo if (hwsim_net_get_wmediumd(net)) 5027*f79cbc77SKalle Valo return -EBUSY; 5028*f79cbc77SKalle Valo 5029*f79cbc77SKalle Valo hwsim_register_wmediumd(net, info->snd_portid); 5030*f79cbc77SKalle Valo 5031*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: received a REGISTER, " 5032*f79cbc77SKalle Valo "switching to wmediumd mode with pid %d\n", info->snd_portid); 5033*f79cbc77SKalle Valo 5034*f79cbc77SKalle Valo return 0; 5035*f79cbc77SKalle Valo } 5036*f79cbc77SKalle Valo 5037*f79cbc77SKalle Valo /* ensures ciphers only include ciphers listed in 'hwsim_ciphers' array */ 5038*f79cbc77SKalle Valo static bool hwsim_known_ciphers(const u32 *ciphers, int n_ciphers) 5039*f79cbc77SKalle Valo { 5040*f79cbc77SKalle Valo int i; 5041*f79cbc77SKalle Valo 5042*f79cbc77SKalle Valo for (i = 0; i < n_ciphers; i++) { 5043*f79cbc77SKalle Valo int j; 5044*f79cbc77SKalle Valo int found = 0; 5045*f79cbc77SKalle Valo 5046*f79cbc77SKalle Valo for (j = 0; j < ARRAY_SIZE(hwsim_ciphers); j++) { 5047*f79cbc77SKalle Valo if (ciphers[i] == hwsim_ciphers[j]) { 5048*f79cbc77SKalle Valo found = 1; 5049*f79cbc77SKalle Valo break; 5050*f79cbc77SKalle Valo } 5051*f79cbc77SKalle Valo } 5052*f79cbc77SKalle Valo 5053*f79cbc77SKalle Valo if (!found) 5054*f79cbc77SKalle Valo return false; 5055*f79cbc77SKalle Valo } 5056*f79cbc77SKalle Valo 5057*f79cbc77SKalle Valo return true; 5058*f79cbc77SKalle Valo } 5059*f79cbc77SKalle Valo 5060*f79cbc77SKalle Valo static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) 5061*f79cbc77SKalle Valo { 5062*f79cbc77SKalle Valo struct hwsim_new_radio_params param = { 0 }; 5063*f79cbc77SKalle Valo const char *hwname = NULL; 5064*f79cbc77SKalle Valo int ret; 5065*f79cbc77SKalle Valo 5066*f79cbc77SKalle Valo param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; 5067*f79cbc77SKalle Valo param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; 5068*f79cbc77SKalle Valo param.channels = channels; 5069*f79cbc77SKalle Valo param.destroy_on_close = 5070*f79cbc77SKalle Valo info->attrs[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE]; 5071*f79cbc77SKalle Valo 5072*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_CHANNELS]) 5073*f79cbc77SKalle Valo param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); 5074*f79cbc77SKalle Valo 5075*f79cbc77SKalle Valo if (param.channels < 1) { 5076*f79cbc77SKalle Valo GENL_SET_ERR_MSG(info, "must have at least one channel"); 5077*f79cbc77SKalle Valo return -EINVAL; 5078*f79cbc77SKalle Valo } 5079*f79cbc77SKalle Valo 5080*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_NO_VIF]) 5081*f79cbc77SKalle Valo param.no_vif = true; 5082*f79cbc77SKalle Valo 5083*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) 5084*f79cbc77SKalle Valo param.use_chanctx = true; 5085*f79cbc77SKalle Valo else 5086*f79cbc77SKalle Valo param.use_chanctx = (param.channels > 1); 5087*f79cbc77SKalle Valo 5088*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) 5089*f79cbc77SKalle Valo param.reg_alpha2 = 5090*f79cbc77SKalle Valo nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); 5091*f79cbc77SKalle Valo 5092*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { 5093*f79cbc77SKalle Valo u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); 5094*f79cbc77SKalle Valo 5095*f79cbc77SKalle Valo if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) 5096*f79cbc77SKalle Valo return -EINVAL; 5097*f79cbc77SKalle Valo 5098*f79cbc77SKalle Valo idx = array_index_nospec(idx, 5099*f79cbc77SKalle Valo ARRAY_SIZE(hwsim_world_regdom_custom)); 5100*f79cbc77SKalle Valo param.regd = hwsim_world_regdom_custom[idx]; 5101*f79cbc77SKalle Valo } 5102*f79cbc77SKalle Valo 5103*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_PERM_ADDR]) { 5104*f79cbc77SKalle Valo if (!is_valid_ether_addr( 5105*f79cbc77SKalle Valo nla_data(info->attrs[HWSIM_ATTR_PERM_ADDR]))) { 5106*f79cbc77SKalle Valo GENL_SET_ERR_MSG(info,"MAC is no valid source addr"); 5107*f79cbc77SKalle Valo NL_SET_BAD_ATTR(info->extack, 5108*f79cbc77SKalle Valo info->attrs[HWSIM_ATTR_PERM_ADDR]); 5109*f79cbc77SKalle Valo return -EINVAL; 5110*f79cbc77SKalle Valo } 5111*f79cbc77SKalle Valo 5112*f79cbc77SKalle Valo param.perm_addr = nla_data(info->attrs[HWSIM_ATTR_PERM_ADDR]); 5113*f79cbc77SKalle Valo } 5114*f79cbc77SKalle Valo 5115*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_IFTYPE_SUPPORT]) { 5116*f79cbc77SKalle Valo param.iftypes = 5117*f79cbc77SKalle Valo nla_get_u32(info->attrs[HWSIM_ATTR_IFTYPE_SUPPORT]); 5118*f79cbc77SKalle Valo 5119*f79cbc77SKalle Valo if (param.iftypes & ~HWSIM_IFTYPE_SUPPORT_MASK) { 5120*f79cbc77SKalle Valo NL_SET_ERR_MSG_ATTR(info->extack, 5121*f79cbc77SKalle Valo info->attrs[HWSIM_ATTR_IFTYPE_SUPPORT], 5122*f79cbc77SKalle Valo "cannot support more iftypes than kernel"); 5123*f79cbc77SKalle Valo return -EINVAL; 5124*f79cbc77SKalle Valo } 5125*f79cbc77SKalle Valo } else { 5126*f79cbc77SKalle Valo param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK; 5127*f79cbc77SKalle Valo } 5128*f79cbc77SKalle Valo 5129*f79cbc77SKalle Valo /* ensure both flag and iftype support is honored */ 5130*f79cbc77SKalle Valo if (param.p2p_device || 5131*f79cbc77SKalle Valo param.iftypes & BIT(NL80211_IFTYPE_P2P_DEVICE)) { 5132*f79cbc77SKalle Valo param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); 5133*f79cbc77SKalle Valo param.p2p_device = true; 5134*f79cbc77SKalle Valo } 5135*f79cbc77SKalle Valo 5136*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]) { 5137*f79cbc77SKalle Valo u32 len = nla_len(info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]); 5138*f79cbc77SKalle Valo 5139*f79cbc77SKalle Valo param.ciphers = 5140*f79cbc77SKalle Valo nla_data(info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]); 5141*f79cbc77SKalle Valo 5142*f79cbc77SKalle Valo if (len % sizeof(u32)) { 5143*f79cbc77SKalle Valo NL_SET_ERR_MSG_ATTR(info->extack, 5144*f79cbc77SKalle Valo info->attrs[HWSIM_ATTR_CIPHER_SUPPORT], 5145*f79cbc77SKalle Valo "bad cipher list length"); 5146*f79cbc77SKalle Valo return -EINVAL; 5147*f79cbc77SKalle Valo } 5148*f79cbc77SKalle Valo 5149*f79cbc77SKalle Valo param.n_ciphers = len / sizeof(u32); 5150*f79cbc77SKalle Valo 5151*f79cbc77SKalle Valo if (param.n_ciphers > ARRAY_SIZE(hwsim_ciphers)) { 5152*f79cbc77SKalle Valo NL_SET_ERR_MSG_ATTR(info->extack, 5153*f79cbc77SKalle Valo info->attrs[HWSIM_ATTR_CIPHER_SUPPORT], 5154*f79cbc77SKalle Valo "too many ciphers specified"); 5155*f79cbc77SKalle Valo return -EINVAL; 5156*f79cbc77SKalle Valo } 5157*f79cbc77SKalle Valo 5158*f79cbc77SKalle Valo if (!hwsim_known_ciphers(param.ciphers, param.n_ciphers)) { 5159*f79cbc77SKalle Valo NL_SET_ERR_MSG_ATTR(info->extack, 5160*f79cbc77SKalle Valo info->attrs[HWSIM_ATTR_CIPHER_SUPPORT], 5161*f79cbc77SKalle Valo "unsupported ciphers specified"); 5162*f79cbc77SKalle Valo return -EINVAL; 5163*f79cbc77SKalle Valo } 5164*f79cbc77SKalle Valo } 5165*f79cbc77SKalle Valo 5166*f79cbc77SKalle Valo param.mlo = info->attrs[HWSIM_ATTR_MLO_SUPPORT]; 5167*f79cbc77SKalle Valo 5168*f79cbc77SKalle Valo if (param.mlo) 5169*f79cbc77SKalle Valo param.use_chanctx = true; 5170*f79cbc77SKalle Valo 5171*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { 5172*f79cbc77SKalle Valo hwname = kstrndup((char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]), 5173*f79cbc77SKalle Valo nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), 5174*f79cbc77SKalle Valo GFP_KERNEL); 5175*f79cbc77SKalle Valo if (!hwname) 5176*f79cbc77SKalle Valo return -ENOMEM; 5177*f79cbc77SKalle Valo param.hwname = hwname; 5178*f79cbc77SKalle Valo } 5179*f79cbc77SKalle Valo 5180*f79cbc77SKalle Valo ret = mac80211_hwsim_new_radio(info, ¶m); 5181*f79cbc77SKalle Valo kfree(hwname); 5182*f79cbc77SKalle Valo return ret; 5183*f79cbc77SKalle Valo } 5184*f79cbc77SKalle Valo 5185*f79cbc77SKalle Valo static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) 5186*f79cbc77SKalle Valo { 5187*f79cbc77SKalle Valo struct mac80211_hwsim_data *data; 5188*f79cbc77SKalle Valo s64 idx = -1; 5189*f79cbc77SKalle Valo const char *hwname = NULL; 5190*f79cbc77SKalle Valo 5191*f79cbc77SKalle Valo if (info->attrs[HWSIM_ATTR_RADIO_ID]) { 5192*f79cbc77SKalle Valo idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); 5193*f79cbc77SKalle Valo } else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { 5194*f79cbc77SKalle Valo hwname = kstrndup((char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]), 5195*f79cbc77SKalle Valo nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), 5196*f79cbc77SKalle Valo GFP_KERNEL); 5197*f79cbc77SKalle Valo if (!hwname) 5198*f79cbc77SKalle Valo return -ENOMEM; 5199*f79cbc77SKalle Valo } else 5200*f79cbc77SKalle Valo return -EINVAL; 5201*f79cbc77SKalle Valo 5202*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 5203*f79cbc77SKalle Valo list_for_each_entry(data, &hwsim_radios, list) { 5204*f79cbc77SKalle Valo if (idx >= 0) { 5205*f79cbc77SKalle Valo if (data->idx != idx) 5206*f79cbc77SKalle Valo continue; 5207*f79cbc77SKalle Valo } else { 5208*f79cbc77SKalle Valo if (!hwname || 5209*f79cbc77SKalle Valo strcmp(hwname, wiphy_name(data->hw->wiphy))) 5210*f79cbc77SKalle Valo continue; 5211*f79cbc77SKalle Valo } 5212*f79cbc77SKalle Valo 5213*f79cbc77SKalle Valo if (!net_eq(wiphy_net(data->hw->wiphy), genl_info_net(info))) 5214*f79cbc77SKalle Valo continue; 5215*f79cbc77SKalle Valo 5216*f79cbc77SKalle Valo list_del(&data->list); 5217*f79cbc77SKalle Valo rhashtable_remove_fast(&hwsim_radios_rht, &data->rht, 5218*f79cbc77SKalle Valo hwsim_rht_params); 5219*f79cbc77SKalle Valo hwsim_radios_generation++; 5220*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 5221*f79cbc77SKalle Valo mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), 5222*f79cbc77SKalle Valo info); 5223*f79cbc77SKalle Valo kfree(hwname); 5224*f79cbc77SKalle Valo return 0; 5225*f79cbc77SKalle Valo } 5226*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 5227*f79cbc77SKalle Valo 5228*f79cbc77SKalle Valo kfree(hwname); 5229*f79cbc77SKalle Valo return -ENODEV; 5230*f79cbc77SKalle Valo } 5231*f79cbc77SKalle Valo 5232*f79cbc77SKalle Valo static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info) 5233*f79cbc77SKalle Valo { 5234*f79cbc77SKalle Valo struct mac80211_hwsim_data *data; 5235*f79cbc77SKalle Valo struct sk_buff *skb; 5236*f79cbc77SKalle Valo int idx, res = -ENODEV; 5237*f79cbc77SKalle Valo 5238*f79cbc77SKalle Valo if (!info->attrs[HWSIM_ATTR_RADIO_ID]) 5239*f79cbc77SKalle Valo return -EINVAL; 5240*f79cbc77SKalle Valo idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); 5241*f79cbc77SKalle Valo 5242*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 5243*f79cbc77SKalle Valo list_for_each_entry(data, &hwsim_radios, list) { 5244*f79cbc77SKalle Valo if (data->idx != idx) 5245*f79cbc77SKalle Valo continue; 5246*f79cbc77SKalle Valo 5247*f79cbc77SKalle Valo if (!net_eq(wiphy_net(data->hw->wiphy), genl_info_net(info))) 5248*f79cbc77SKalle Valo continue; 5249*f79cbc77SKalle Valo 5250*f79cbc77SKalle Valo skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 5251*f79cbc77SKalle Valo if (!skb) { 5252*f79cbc77SKalle Valo res = -ENOMEM; 5253*f79cbc77SKalle Valo goto out_err; 5254*f79cbc77SKalle Valo } 5255*f79cbc77SKalle Valo 5256*f79cbc77SKalle Valo res = mac80211_hwsim_get_radio(skb, data, info->snd_portid, 5257*f79cbc77SKalle Valo info->snd_seq, NULL, 0); 5258*f79cbc77SKalle Valo if (res < 0) { 5259*f79cbc77SKalle Valo nlmsg_free(skb); 5260*f79cbc77SKalle Valo goto out_err; 5261*f79cbc77SKalle Valo } 5262*f79cbc77SKalle Valo 5263*f79cbc77SKalle Valo res = genlmsg_reply(skb, info); 5264*f79cbc77SKalle Valo break; 5265*f79cbc77SKalle Valo } 5266*f79cbc77SKalle Valo 5267*f79cbc77SKalle Valo out_err: 5268*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 5269*f79cbc77SKalle Valo 5270*f79cbc77SKalle Valo return res; 5271*f79cbc77SKalle Valo } 5272*f79cbc77SKalle Valo 5273*f79cbc77SKalle Valo static int hwsim_dump_radio_nl(struct sk_buff *skb, 5274*f79cbc77SKalle Valo struct netlink_callback *cb) 5275*f79cbc77SKalle Valo { 5276*f79cbc77SKalle Valo int last_idx = cb->args[0] - 1; 5277*f79cbc77SKalle Valo struct mac80211_hwsim_data *data = NULL; 5278*f79cbc77SKalle Valo int res = 0; 5279*f79cbc77SKalle Valo void *hdr; 5280*f79cbc77SKalle Valo 5281*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 5282*f79cbc77SKalle Valo cb->seq = hwsim_radios_generation; 5283*f79cbc77SKalle Valo 5284*f79cbc77SKalle Valo if (last_idx >= hwsim_radio_idx-1) 5285*f79cbc77SKalle Valo goto done; 5286*f79cbc77SKalle Valo 5287*f79cbc77SKalle Valo list_for_each_entry(data, &hwsim_radios, list) { 5288*f79cbc77SKalle Valo if (data->idx <= last_idx) 5289*f79cbc77SKalle Valo continue; 5290*f79cbc77SKalle Valo 5291*f79cbc77SKalle Valo if (!net_eq(wiphy_net(data->hw->wiphy), sock_net(skb->sk))) 5292*f79cbc77SKalle Valo continue; 5293*f79cbc77SKalle Valo 5294*f79cbc77SKalle Valo res = mac80211_hwsim_get_radio(skb, data, 5295*f79cbc77SKalle Valo NETLINK_CB(cb->skb).portid, 5296*f79cbc77SKalle Valo cb->nlh->nlmsg_seq, cb, 5297*f79cbc77SKalle Valo NLM_F_MULTI); 5298*f79cbc77SKalle Valo if (res < 0) 5299*f79cbc77SKalle Valo break; 5300*f79cbc77SKalle Valo 5301*f79cbc77SKalle Valo last_idx = data->idx; 5302*f79cbc77SKalle Valo } 5303*f79cbc77SKalle Valo 5304*f79cbc77SKalle Valo cb->args[0] = last_idx + 1; 5305*f79cbc77SKalle Valo 5306*f79cbc77SKalle Valo /* list changed, but no new element sent, set interrupted flag */ 5307*f79cbc77SKalle Valo if (skb->len == 0 && cb->prev_seq && cb->seq != cb->prev_seq) { 5308*f79cbc77SKalle Valo hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, 5309*f79cbc77SKalle Valo cb->nlh->nlmsg_seq, &hwsim_genl_family, 5310*f79cbc77SKalle Valo NLM_F_MULTI, HWSIM_CMD_GET_RADIO); 5311*f79cbc77SKalle Valo if (hdr) { 5312*f79cbc77SKalle Valo genl_dump_check_consistent(cb, hdr); 5313*f79cbc77SKalle Valo genlmsg_end(skb, hdr); 5314*f79cbc77SKalle Valo } else { 5315*f79cbc77SKalle Valo res = -EMSGSIZE; 5316*f79cbc77SKalle Valo } 5317*f79cbc77SKalle Valo } 5318*f79cbc77SKalle Valo 5319*f79cbc77SKalle Valo done: 5320*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 5321*f79cbc77SKalle Valo return res ?: skb->len; 5322*f79cbc77SKalle Valo } 5323*f79cbc77SKalle Valo 5324*f79cbc77SKalle Valo /* Generic Netlink operations array */ 5325*f79cbc77SKalle Valo static const struct genl_small_ops hwsim_ops[] = { 5326*f79cbc77SKalle Valo { 5327*f79cbc77SKalle Valo .cmd = HWSIM_CMD_REGISTER, 5328*f79cbc77SKalle Valo .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5329*f79cbc77SKalle Valo .doit = hwsim_register_received_nl, 5330*f79cbc77SKalle Valo .flags = GENL_UNS_ADMIN_PERM, 5331*f79cbc77SKalle Valo }, 5332*f79cbc77SKalle Valo { 5333*f79cbc77SKalle Valo .cmd = HWSIM_CMD_FRAME, 5334*f79cbc77SKalle Valo .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5335*f79cbc77SKalle Valo .doit = hwsim_cloned_frame_received_nl, 5336*f79cbc77SKalle Valo }, 5337*f79cbc77SKalle Valo { 5338*f79cbc77SKalle Valo .cmd = HWSIM_CMD_TX_INFO_FRAME, 5339*f79cbc77SKalle Valo .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5340*f79cbc77SKalle Valo .doit = hwsim_tx_info_frame_received_nl, 5341*f79cbc77SKalle Valo }, 5342*f79cbc77SKalle Valo { 5343*f79cbc77SKalle Valo .cmd = HWSIM_CMD_NEW_RADIO, 5344*f79cbc77SKalle Valo .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5345*f79cbc77SKalle Valo .doit = hwsim_new_radio_nl, 5346*f79cbc77SKalle Valo .flags = GENL_UNS_ADMIN_PERM, 5347*f79cbc77SKalle Valo }, 5348*f79cbc77SKalle Valo { 5349*f79cbc77SKalle Valo .cmd = HWSIM_CMD_DEL_RADIO, 5350*f79cbc77SKalle Valo .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5351*f79cbc77SKalle Valo .doit = hwsim_del_radio_nl, 5352*f79cbc77SKalle Valo .flags = GENL_UNS_ADMIN_PERM, 5353*f79cbc77SKalle Valo }, 5354*f79cbc77SKalle Valo { 5355*f79cbc77SKalle Valo .cmd = HWSIM_CMD_GET_RADIO, 5356*f79cbc77SKalle Valo .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5357*f79cbc77SKalle Valo .doit = hwsim_get_radio_nl, 5358*f79cbc77SKalle Valo .dumpit = hwsim_dump_radio_nl, 5359*f79cbc77SKalle Valo }, 5360*f79cbc77SKalle Valo }; 5361*f79cbc77SKalle Valo 5362*f79cbc77SKalle Valo static struct genl_family hwsim_genl_family __ro_after_init = { 5363*f79cbc77SKalle Valo .name = "MAC80211_HWSIM", 5364*f79cbc77SKalle Valo .version = 1, 5365*f79cbc77SKalle Valo .maxattr = HWSIM_ATTR_MAX, 5366*f79cbc77SKalle Valo .policy = hwsim_genl_policy, 5367*f79cbc77SKalle Valo .netnsok = true, 5368*f79cbc77SKalle Valo .module = THIS_MODULE, 5369*f79cbc77SKalle Valo .small_ops = hwsim_ops, 5370*f79cbc77SKalle Valo .n_small_ops = ARRAY_SIZE(hwsim_ops), 5371*f79cbc77SKalle Valo .resv_start_op = HWSIM_CMD_DEL_MAC_ADDR + 1, 5372*f79cbc77SKalle Valo .mcgrps = hwsim_mcgrps, 5373*f79cbc77SKalle Valo .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps), 5374*f79cbc77SKalle Valo }; 5375*f79cbc77SKalle Valo 5376*f79cbc77SKalle Valo static void remove_user_radios(u32 portid) 5377*f79cbc77SKalle Valo { 5378*f79cbc77SKalle Valo struct mac80211_hwsim_data *entry, *tmp; 5379*f79cbc77SKalle Valo LIST_HEAD(list); 5380*f79cbc77SKalle Valo 5381*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 5382*f79cbc77SKalle Valo list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) { 5383*f79cbc77SKalle Valo if (entry->destroy_on_close && entry->portid == portid) { 5384*f79cbc77SKalle Valo list_move(&entry->list, &list); 5385*f79cbc77SKalle Valo rhashtable_remove_fast(&hwsim_radios_rht, &entry->rht, 5386*f79cbc77SKalle Valo hwsim_rht_params); 5387*f79cbc77SKalle Valo hwsim_radios_generation++; 5388*f79cbc77SKalle Valo } 5389*f79cbc77SKalle Valo } 5390*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 5391*f79cbc77SKalle Valo 5392*f79cbc77SKalle Valo list_for_each_entry_safe(entry, tmp, &list, list) { 5393*f79cbc77SKalle Valo list_del(&entry->list); 5394*f79cbc77SKalle Valo mac80211_hwsim_del_radio(entry, wiphy_name(entry->hw->wiphy), 5395*f79cbc77SKalle Valo NULL); 5396*f79cbc77SKalle Valo } 5397*f79cbc77SKalle Valo } 5398*f79cbc77SKalle Valo 5399*f79cbc77SKalle Valo static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, 5400*f79cbc77SKalle Valo unsigned long state, 5401*f79cbc77SKalle Valo void *_notify) 5402*f79cbc77SKalle Valo { 5403*f79cbc77SKalle Valo struct netlink_notify *notify = _notify; 5404*f79cbc77SKalle Valo 5405*f79cbc77SKalle Valo if (state != NETLINK_URELEASE) 5406*f79cbc77SKalle Valo return NOTIFY_DONE; 5407*f79cbc77SKalle Valo 5408*f79cbc77SKalle Valo remove_user_radios(notify->portid); 5409*f79cbc77SKalle Valo 5410*f79cbc77SKalle Valo if (notify->portid == hwsim_net_get_wmediumd(notify->net)) { 5411*f79cbc77SKalle Valo printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" 5412*f79cbc77SKalle Valo " socket, switching to perfect channel medium\n"); 5413*f79cbc77SKalle Valo hwsim_register_wmediumd(notify->net, 0); 5414*f79cbc77SKalle Valo } 5415*f79cbc77SKalle Valo return NOTIFY_DONE; 5416*f79cbc77SKalle Valo 5417*f79cbc77SKalle Valo } 5418*f79cbc77SKalle Valo 5419*f79cbc77SKalle Valo static struct notifier_block hwsim_netlink_notifier = { 5420*f79cbc77SKalle Valo .notifier_call = mac80211_hwsim_netlink_notify, 5421*f79cbc77SKalle Valo }; 5422*f79cbc77SKalle Valo 5423*f79cbc77SKalle Valo static int __init hwsim_init_netlink(void) 5424*f79cbc77SKalle Valo { 5425*f79cbc77SKalle Valo int rc; 5426*f79cbc77SKalle Valo 5427*f79cbc77SKalle Valo printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); 5428*f79cbc77SKalle Valo 5429*f79cbc77SKalle Valo rc = genl_register_family(&hwsim_genl_family); 5430*f79cbc77SKalle Valo if (rc) 5431*f79cbc77SKalle Valo goto failure; 5432*f79cbc77SKalle Valo 5433*f79cbc77SKalle Valo rc = netlink_register_notifier(&hwsim_netlink_notifier); 5434*f79cbc77SKalle Valo if (rc) { 5435*f79cbc77SKalle Valo genl_unregister_family(&hwsim_genl_family); 5436*f79cbc77SKalle Valo goto failure; 5437*f79cbc77SKalle Valo } 5438*f79cbc77SKalle Valo 5439*f79cbc77SKalle Valo return 0; 5440*f79cbc77SKalle Valo 5441*f79cbc77SKalle Valo failure: 5442*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: error occurred in %s\n", __func__); 5443*f79cbc77SKalle Valo return -EINVAL; 5444*f79cbc77SKalle Valo } 5445*f79cbc77SKalle Valo 5446*f79cbc77SKalle Valo static __net_init int hwsim_init_net(struct net *net) 5447*f79cbc77SKalle Valo { 5448*f79cbc77SKalle Valo return hwsim_net_set_netgroup(net); 5449*f79cbc77SKalle Valo } 5450*f79cbc77SKalle Valo 5451*f79cbc77SKalle Valo static void __net_exit hwsim_exit_net(struct net *net) 5452*f79cbc77SKalle Valo { 5453*f79cbc77SKalle Valo struct mac80211_hwsim_data *data, *tmp; 5454*f79cbc77SKalle Valo LIST_HEAD(list); 5455*f79cbc77SKalle Valo 5456*f79cbc77SKalle Valo spin_lock_bh(&hwsim_radio_lock); 5457*f79cbc77SKalle Valo list_for_each_entry_safe(data, tmp, &hwsim_radios, list) { 5458*f79cbc77SKalle Valo if (!net_eq(wiphy_net(data->hw->wiphy), net)) 5459*f79cbc77SKalle Valo continue; 5460*f79cbc77SKalle Valo 5461*f79cbc77SKalle Valo /* Radios created in init_net are returned to init_net. */ 5462*f79cbc77SKalle Valo if (data->netgroup == hwsim_net_get_netgroup(&init_net)) 5463*f79cbc77SKalle Valo continue; 5464*f79cbc77SKalle Valo 5465*f79cbc77SKalle Valo list_move(&data->list, &list); 5466*f79cbc77SKalle Valo rhashtable_remove_fast(&hwsim_radios_rht, &data->rht, 5467*f79cbc77SKalle Valo hwsim_rht_params); 5468*f79cbc77SKalle Valo hwsim_radios_generation++; 5469*f79cbc77SKalle Valo } 5470*f79cbc77SKalle Valo spin_unlock_bh(&hwsim_radio_lock); 5471*f79cbc77SKalle Valo 5472*f79cbc77SKalle Valo list_for_each_entry_safe(data, tmp, &list, list) { 5473*f79cbc77SKalle Valo list_del(&data->list); 5474*f79cbc77SKalle Valo mac80211_hwsim_del_radio(data, 5475*f79cbc77SKalle Valo wiphy_name(data->hw->wiphy), 5476*f79cbc77SKalle Valo NULL); 5477*f79cbc77SKalle Valo } 5478*f79cbc77SKalle Valo 5479*f79cbc77SKalle Valo ida_free(&hwsim_netgroup_ida, hwsim_net_get_netgroup(net)); 5480*f79cbc77SKalle Valo } 5481*f79cbc77SKalle Valo 5482*f79cbc77SKalle Valo static struct pernet_operations hwsim_net_ops = { 5483*f79cbc77SKalle Valo .init = hwsim_init_net, 5484*f79cbc77SKalle Valo .exit = hwsim_exit_net, 5485*f79cbc77SKalle Valo .id = &hwsim_net_id, 5486*f79cbc77SKalle Valo .size = sizeof(struct hwsim_net), 5487*f79cbc77SKalle Valo }; 5488*f79cbc77SKalle Valo 5489*f79cbc77SKalle Valo static void hwsim_exit_netlink(void) 5490*f79cbc77SKalle Valo { 5491*f79cbc77SKalle Valo /* unregister the notifier */ 5492*f79cbc77SKalle Valo netlink_unregister_notifier(&hwsim_netlink_notifier); 5493*f79cbc77SKalle Valo /* unregister the family */ 5494*f79cbc77SKalle Valo genl_unregister_family(&hwsim_genl_family); 5495*f79cbc77SKalle Valo } 5496*f79cbc77SKalle Valo 5497*f79cbc77SKalle Valo #if IS_REACHABLE(CONFIG_VIRTIO) 5498*f79cbc77SKalle Valo static void hwsim_virtio_tx_done(struct virtqueue *vq) 5499*f79cbc77SKalle Valo { 5500*f79cbc77SKalle Valo unsigned int len; 5501*f79cbc77SKalle Valo struct sk_buff *skb; 5502*f79cbc77SKalle Valo unsigned long flags; 5503*f79cbc77SKalle Valo 5504*f79cbc77SKalle Valo spin_lock_irqsave(&hwsim_virtio_lock, flags); 5505*f79cbc77SKalle Valo while ((skb = virtqueue_get_buf(vq, &len))) 5506*f79cbc77SKalle Valo nlmsg_free(skb); 5507*f79cbc77SKalle Valo spin_unlock_irqrestore(&hwsim_virtio_lock, flags); 5508*f79cbc77SKalle Valo } 5509*f79cbc77SKalle Valo 5510*f79cbc77SKalle Valo static int hwsim_virtio_handle_cmd(struct sk_buff *skb) 5511*f79cbc77SKalle Valo { 5512*f79cbc77SKalle Valo struct nlmsghdr *nlh; 5513*f79cbc77SKalle Valo struct genlmsghdr *gnlh; 5514*f79cbc77SKalle Valo struct nlattr *tb[HWSIM_ATTR_MAX + 1]; 5515*f79cbc77SKalle Valo struct genl_info info = {}; 5516*f79cbc77SKalle Valo int err; 5517*f79cbc77SKalle Valo 5518*f79cbc77SKalle Valo nlh = nlmsg_hdr(skb); 5519*f79cbc77SKalle Valo gnlh = nlmsg_data(nlh); 5520*f79cbc77SKalle Valo 5521*f79cbc77SKalle Valo if (skb->len < nlh->nlmsg_len) 5522*f79cbc77SKalle Valo return -EINVAL; 5523*f79cbc77SKalle Valo 5524*f79cbc77SKalle Valo err = genlmsg_parse(nlh, &hwsim_genl_family, tb, HWSIM_ATTR_MAX, 5525*f79cbc77SKalle Valo hwsim_genl_policy, NULL); 5526*f79cbc77SKalle Valo if (err) { 5527*f79cbc77SKalle Valo pr_err_ratelimited("hwsim: genlmsg_parse returned %d\n", err); 5528*f79cbc77SKalle Valo return err; 5529*f79cbc77SKalle Valo } 5530*f79cbc77SKalle Valo 5531*f79cbc77SKalle Valo info.attrs = tb; 5532*f79cbc77SKalle Valo 5533*f79cbc77SKalle Valo switch (gnlh->cmd) { 5534*f79cbc77SKalle Valo case HWSIM_CMD_FRAME: 5535*f79cbc77SKalle Valo hwsim_cloned_frame_received_nl(skb, &info); 5536*f79cbc77SKalle Valo break; 5537*f79cbc77SKalle Valo case HWSIM_CMD_TX_INFO_FRAME: 5538*f79cbc77SKalle Valo hwsim_tx_info_frame_received_nl(skb, &info); 5539*f79cbc77SKalle Valo break; 5540*f79cbc77SKalle Valo default: 5541*f79cbc77SKalle Valo pr_err_ratelimited("hwsim: invalid cmd: %d\n", gnlh->cmd); 5542*f79cbc77SKalle Valo return -EPROTO; 5543*f79cbc77SKalle Valo } 5544*f79cbc77SKalle Valo return 0; 5545*f79cbc77SKalle Valo } 5546*f79cbc77SKalle Valo 5547*f79cbc77SKalle Valo static void hwsim_virtio_rx_work(struct work_struct *work) 5548*f79cbc77SKalle Valo { 5549*f79cbc77SKalle Valo struct virtqueue *vq; 5550*f79cbc77SKalle Valo unsigned int len; 5551*f79cbc77SKalle Valo struct sk_buff *skb; 5552*f79cbc77SKalle Valo struct scatterlist sg[1]; 5553*f79cbc77SKalle Valo int err; 5554*f79cbc77SKalle Valo unsigned long flags; 5555*f79cbc77SKalle Valo 5556*f79cbc77SKalle Valo spin_lock_irqsave(&hwsim_virtio_lock, flags); 5557*f79cbc77SKalle Valo if (!hwsim_virtio_enabled) 5558*f79cbc77SKalle Valo goto out_unlock; 5559*f79cbc77SKalle Valo 5560*f79cbc77SKalle Valo skb = virtqueue_get_buf(hwsim_vqs[HWSIM_VQ_RX], &len); 5561*f79cbc77SKalle Valo if (!skb) 5562*f79cbc77SKalle Valo goto out_unlock; 5563*f79cbc77SKalle Valo spin_unlock_irqrestore(&hwsim_virtio_lock, flags); 5564*f79cbc77SKalle Valo 5565*f79cbc77SKalle Valo skb->data = skb->head; 5566*f79cbc77SKalle Valo skb_reset_tail_pointer(skb); 5567*f79cbc77SKalle Valo skb_put(skb, len); 5568*f79cbc77SKalle Valo hwsim_virtio_handle_cmd(skb); 5569*f79cbc77SKalle Valo 5570*f79cbc77SKalle Valo spin_lock_irqsave(&hwsim_virtio_lock, flags); 5571*f79cbc77SKalle Valo if (!hwsim_virtio_enabled) { 5572*f79cbc77SKalle Valo nlmsg_free(skb); 5573*f79cbc77SKalle Valo goto out_unlock; 5574*f79cbc77SKalle Valo } 5575*f79cbc77SKalle Valo vq = hwsim_vqs[HWSIM_VQ_RX]; 5576*f79cbc77SKalle Valo sg_init_one(sg, skb->head, skb_end_offset(skb)); 5577*f79cbc77SKalle Valo err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_ATOMIC); 5578*f79cbc77SKalle Valo if (WARN(err, "virtqueue_add_inbuf returned %d\n", err)) 5579*f79cbc77SKalle Valo nlmsg_free(skb); 5580*f79cbc77SKalle Valo else 5581*f79cbc77SKalle Valo virtqueue_kick(vq); 5582*f79cbc77SKalle Valo schedule_work(&hwsim_virtio_rx); 5583*f79cbc77SKalle Valo 5584*f79cbc77SKalle Valo out_unlock: 5585*f79cbc77SKalle Valo spin_unlock_irqrestore(&hwsim_virtio_lock, flags); 5586*f79cbc77SKalle Valo } 5587*f79cbc77SKalle Valo 5588*f79cbc77SKalle Valo static void hwsim_virtio_rx_done(struct virtqueue *vq) 5589*f79cbc77SKalle Valo { 5590*f79cbc77SKalle Valo schedule_work(&hwsim_virtio_rx); 5591*f79cbc77SKalle Valo } 5592*f79cbc77SKalle Valo 5593*f79cbc77SKalle Valo static int init_vqs(struct virtio_device *vdev) 5594*f79cbc77SKalle Valo { 5595*f79cbc77SKalle Valo vq_callback_t *callbacks[HWSIM_NUM_VQS] = { 5596*f79cbc77SKalle Valo [HWSIM_VQ_TX] = hwsim_virtio_tx_done, 5597*f79cbc77SKalle Valo [HWSIM_VQ_RX] = hwsim_virtio_rx_done, 5598*f79cbc77SKalle Valo }; 5599*f79cbc77SKalle Valo const char *names[HWSIM_NUM_VQS] = { 5600*f79cbc77SKalle Valo [HWSIM_VQ_TX] = "tx", 5601*f79cbc77SKalle Valo [HWSIM_VQ_RX] = "rx", 5602*f79cbc77SKalle Valo }; 5603*f79cbc77SKalle Valo 5604*f79cbc77SKalle Valo return virtio_find_vqs(vdev, HWSIM_NUM_VQS, 5605*f79cbc77SKalle Valo hwsim_vqs, callbacks, names, NULL); 5606*f79cbc77SKalle Valo } 5607*f79cbc77SKalle Valo 5608*f79cbc77SKalle Valo static int fill_vq(struct virtqueue *vq) 5609*f79cbc77SKalle Valo { 5610*f79cbc77SKalle Valo int i, err; 5611*f79cbc77SKalle Valo struct sk_buff *skb; 5612*f79cbc77SKalle Valo struct scatterlist sg[1]; 5613*f79cbc77SKalle Valo 5614*f79cbc77SKalle Valo for (i = 0; i < virtqueue_get_vring_size(vq); i++) { 5615*f79cbc77SKalle Valo skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 5616*f79cbc77SKalle Valo if (!skb) 5617*f79cbc77SKalle Valo return -ENOMEM; 5618*f79cbc77SKalle Valo 5619*f79cbc77SKalle Valo sg_init_one(sg, skb->head, skb_end_offset(skb)); 5620*f79cbc77SKalle Valo err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL); 5621*f79cbc77SKalle Valo if (err) { 5622*f79cbc77SKalle Valo nlmsg_free(skb); 5623*f79cbc77SKalle Valo return err; 5624*f79cbc77SKalle Valo } 5625*f79cbc77SKalle Valo } 5626*f79cbc77SKalle Valo virtqueue_kick(vq); 5627*f79cbc77SKalle Valo return 0; 5628*f79cbc77SKalle Valo } 5629*f79cbc77SKalle Valo 5630*f79cbc77SKalle Valo static void remove_vqs(struct virtio_device *vdev) 5631*f79cbc77SKalle Valo { 5632*f79cbc77SKalle Valo int i; 5633*f79cbc77SKalle Valo 5634*f79cbc77SKalle Valo virtio_reset_device(vdev); 5635*f79cbc77SKalle Valo 5636*f79cbc77SKalle Valo for (i = 0; i < ARRAY_SIZE(hwsim_vqs); i++) { 5637*f79cbc77SKalle Valo struct virtqueue *vq = hwsim_vqs[i]; 5638*f79cbc77SKalle Valo struct sk_buff *skb; 5639*f79cbc77SKalle Valo 5640*f79cbc77SKalle Valo while ((skb = virtqueue_detach_unused_buf(vq))) 5641*f79cbc77SKalle Valo nlmsg_free(skb); 5642*f79cbc77SKalle Valo } 5643*f79cbc77SKalle Valo 5644*f79cbc77SKalle Valo vdev->config->del_vqs(vdev); 5645*f79cbc77SKalle Valo } 5646*f79cbc77SKalle Valo 5647*f79cbc77SKalle Valo static int hwsim_virtio_probe(struct virtio_device *vdev) 5648*f79cbc77SKalle Valo { 5649*f79cbc77SKalle Valo int err; 5650*f79cbc77SKalle Valo unsigned long flags; 5651*f79cbc77SKalle Valo 5652*f79cbc77SKalle Valo spin_lock_irqsave(&hwsim_virtio_lock, flags); 5653*f79cbc77SKalle Valo if (hwsim_virtio_enabled) { 5654*f79cbc77SKalle Valo spin_unlock_irqrestore(&hwsim_virtio_lock, flags); 5655*f79cbc77SKalle Valo return -EEXIST; 5656*f79cbc77SKalle Valo } 5657*f79cbc77SKalle Valo spin_unlock_irqrestore(&hwsim_virtio_lock, flags); 5658*f79cbc77SKalle Valo 5659*f79cbc77SKalle Valo err = init_vqs(vdev); 5660*f79cbc77SKalle Valo if (err) 5661*f79cbc77SKalle Valo return err; 5662*f79cbc77SKalle Valo 5663*f79cbc77SKalle Valo virtio_device_ready(vdev); 5664*f79cbc77SKalle Valo 5665*f79cbc77SKalle Valo err = fill_vq(hwsim_vqs[HWSIM_VQ_RX]); 5666*f79cbc77SKalle Valo if (err) 5667*f79cbc77SKalle Valo goto out_remove; 5668*f79cbc77SKalle Valo 5669*f79cbc77SKalle Valo spin_lock_irqsave(&hwsim_virtio_lock, flags); 5670*f79cbc77SKalle Valo hwsim_virtio_enabled = true; 5671*f79cbc77SKalle Valo spin_unlock_irqrestore(&hwsim_virtio_lock, flags); 5672*f79cbc77SKalle Valo 5673*f79cbc77SKalle Valo schedule_work(&hwsim_virtio_rx); 5674*f79cbc77SKalle Valo return 0; 5675*f79cbc77SKalle Valo 5676*f79cbc77SKalle Valo out_remove: 5677*f79cbc77SKalle Valo remove_vqs(vdev); 5678*f79cbc77SKalle Valo return err; 5679*f79cbc77SKalle Valo } 5680*f79cbc77SKalle Valo 5681*f79cbc77SKalle Valo static void hwsim_virtio_remove(struct virtio_device *vdev) 5682*f79cbc77SKalle Valo { 5683*f79cbc77SKalle Valo hwsim_virtio_enabled = false; 5684*f79cbc77SKalle Valo 5685*f79cbc77SKalle Valo cancel_work_sync(&hwsim_virtio_rx); 5686*f79cbc77SKalle Valo 5687*f79cbc77SKalle Valo remove_vqs(vdev); 5688*f79cbc77SKalle Valo } 5689*f79cbc77SKalle Valo 5690*f79cbc77SKalle Valo /* MAC80211_HWSIM virtio device id table */ 5691*f79cbc77SKalle Valo static const struct virtio_device_id id_table[] = { 5692*f79cbc77SKalle Valo { VIRTIO_ID_MAC80211_HWSIM, VIRTIO_DEV_ANY_ID }, 5693*f79cbc77SKalle Valo { 0 } 5694*f79cbc77SKalle Valo }; 5695*f79cbc77SKalle Valo MODULE_DEVICE_TABLE(virtio, id_table); 5696*f79cbc77SKalle Valo 5697*f79cbc77SKalle Valo static struct virtio_driver virtio_hwsim = { 5698*f79cbc77SKalle Valo .driver.name = KBUILD_MODNAME, 5699*f79cbc77SKalle Valo .driver.owner = THIS_MODULE, 5700*f79cbc77SKalle Valo .id_table = id_table, 5701*f79cbc77SKalle Valo .probe = hwsim_virtio_probe, 5702*f79cbc77SKalle Valo .remove = hwsim_virtio_remove, 5703*f79cbc77SKalle Valo }; 5704*f79cbc77SKalle Valo 5705*f79cbc77SKalle Valo static int hwsim_register_virtio_driver(void) 5706*f79cbc77SKalle Valo { 5707*f79cbc77SKalle Valo return register_virtio_driver(&virtio_hwsim); 5708*f79cbc77SKalle Valo } 5709*f79cbc77SKalle Valo 5710*f79cbc77SKalle Valo static void hwsim_unregister_virtio_driver(void) 5711*f79cbc77SKalle Valo { 5712*f79cbc77SKalle Valo unregister_virtio_driver(&virtio_hwsim); 5713*f79cbc77SKalle Valo } 5714*f79cbc77SKalle Valo #else 5715*f79cbc77SKalle Valo static inline int hwsim_register_virtio_driver(void) 5716*f79cbc77SKalle Valo { 5717*f79cbc77SKalle Valo return 0; 5718*f79cbc77SKalle Valo } 5719*f79cbc77SKalle Valo 5720*f79cbc77SKalle Valo static inline void hwsim_unregister_virtio_driver(void) 5721*f79cbc77SKalle Valo { 5722*f79cbc77SKalle Valo } 5723*f79cbc77SKalle Valo #endif 5724*f79cbc77SKalle Valo 5725*f79cbc77SKalle Valo static int __init init_mac80211_hwsim(void) 5726*f79cbc77SKalle Valo { 5727*f79cbc77SKalle Valo int i, err; 5728*f79cbc77SKalle Valo 5729*f79cbc77SKalle Valo if (radios < 0 || radios > 100) 5730*f79cbc77SKalle Valo return -EINVAL; 5731*f79cbc77SKalle Valo 5732*f79cbc77SKalle Valo if (channels < 1) 5733*f79cbc77SKalle Valo return -EINVAL; 5734*f79cbc77SKalle Valo 5735*f79cbc77SKalle Valo err = rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params); 5736*f79cbc77SKalle Valo if (err) 5737*f79cbc77SKalle Valo return err; 5738*f79cbc77SKalle Valo 5739*f79cbc77SKalle Valo err = register_pernet_device(&hwsim_net_ops); 5740*f79cbc77SKalle Valo if (err) 5741*f79cbc77SKalle Valo goto out_free_rht; 5742*f79cbc77SKalle Valo 5743*f79cbc77SKalle Valo err = platform_driver_register(&mac80211_hwsim_driver); 5744*f79cbc77SKalle Valo if (err) 5745*f79cbc77SKalle Valo goto out_unregister_pernet; 5746*f79cbc77SKalle Valo 5747*f79cbc77SKalle Valo err = hwsim_init_netlink(); 5748*f79cbc77SKalle Valo if (err) 5749*f79cbc77SKalle Valo goto out_unregister_driver; 5750*f79cbc77SKalle Valo 5751*f79cbc77SKalle Valo err = hwsim_register_virtio_driver(); 5752*f79cbc77SKalle Valo if (err) 5753*f79cbc77SKalle Valo goto out_exit_netlink; 5754*f79cbc77SKalle Valo 5755*f79cbc77SKalle Valo hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); 5756*f79cbc77SKalle Valo if (IS_ERR(hwsim_class)) { 5757*f79cbc77SKalle Valo err = PTR_ERR(hwsim_class); 5758*f79cbc77SKalle Valo goto out_exit_virtio; 5759*f79cbc77SKalle Valo } 5760*f79cbc77SKalle Valo 5761*f79cbc77SKalle Valo hwsim_init_s1g_channels(hwsim_channels_s1g); 5762*f79cbc77SKalle Valo 5763*f79cbc77SKalle Valo for (i = 0; i < radios; i++) { 5764*f79cbc77SKalle Valo struct hwsim_new_radio_params param = { 0 }; 5765*f79cbc77SKalle Valo 5766*f79cbc77SKalle Valo param.channels = channels; 5767*f79cbc77SKalle Valo 5768*f79cbc77SKalle Valo switch (regtest) { 5769*f79cbc77SKalle Valo case HWSIM_REGTEST_DIFF_COUNTRY: 5770*f79cbc77SKalle Valo if (i < ARRAY_SIZE(hwsim_alpha2s)) 5771*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[i]; 5772*f79cbc77SKalle Valo break; 5773*f79cbc77SKalle Valo case HWSIM_REGTEST_DRIVER_REG_FOLLOW: 5774*f79cbc77SKalle Valo if (!i) 5775*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[0]; 5776*f79cbc77SKalle Valo break; 5777*f79cbc77SKalle Valo case HWSIM_REGTEST_STRICT_ALL: 5778*f79cbc77SKalle Valo param.reg_strict = true; 5779*f79cbc77SKalle Valo fallthrough; 5780*f79cbc77SKalle Valo case HWSIM_REGTEST_DRIVER_REG_ALL: 5781*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[0]; 5782*f79cbc77SKalle Valo break; 5783*f79cbc77SKalle Valo case HWSIM_REGTEST_WORLD_ROAM: 5784*f79cbc77SKalle Valo if (i == 0) 5785*f79cbc77SKalle Valo param.regd = &hwsim_world_regdom_custom_01; 5786*f79cbc77SKalle Valo break; 5787*f79cbc77SKalle Valo case HWSIM_REGTEST_CUSTOM_WORLD: 5788*f79cbc77SKalle Valo param.regd = &hwsim_world_regdom_custom_01; 5789*f79cbc77SKalle Valo break; 5790*f79cbc77SKalle Valo case HWSIM_REGTEST_CUSTOM_WORLD_2: 5791*f79cbc77SKalle Valo if (i == 0) 5792*f79cbc77SKalle Valo param.regd = &hwsim_world_regdom_custom_01; 5793*f79cbc77SKalle Valo else if (i == 1) 5794*f79cbc77SKalle Valo param.regd = &hwsim_world_regdom_custom_02; 5795*f79cbc77SKalle Valo break; 5796*f79cbc77SKalle Valo case HWSIM_REGTEST_STRICT_FOLLOW: 5797*f79cbc77SKalle Valo if (i == 0) { 5798*f79cbc77SKalle Valo param.reg_strict = true; 5799*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[0]; 5800*f79cbc77SKalle Valo } 5801*f79cbc77SKalle Valo break; 5802*f79cbc77SKalle Valo case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: 5803*f79cbc77SKalle Valo if (i == 0) { 5804*f79cbc77SKalle Valo param.reg_strict = true; 5805*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[0]; 5806*f79cbc77SKalle Valo } else if (i == 1) { 5807*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[1]; 5808*f79cbc77SKalle Valo } 5809*f79cbc77SKalle Valo break; 5810*f79cbc77SKalle Valo case HWSIM_REGTEST_ALL: 5811*f79cbc77SKalle Valo switch (i) { 5812*f79cbc77SKalle Valo case 0: 5813*f79cbc77SKalle Valo param.regd = &hwsim_world_regdom_custom_01; 5814*f79cbc77SKalle Valo break; 5815*f79cbc77SKalle Valo case 1: 5816*f79cbc77SKalle Valo param.regd = &hwsim_world_regdom_custom_02; 5817*f79cbc77SKalle Valo break; 5818*f79cbc77SKalle Valo case 2: 5819*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[0]; 5820*f79cbc77SKalle Valo break; 5821*f79cbc77SKalle Valo case 3: 5822*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[1]; 5823*f79cbc77SKalle Valo break; 5824*f79cbc77SKalle Valo case 4: 5825*f79cbc77SKalle Valo param.reg_strict = true; 5826*f79cbc77SKalle Valo param.reg_alpha2 = hwsim_alpha2s[2]; 5827*f79cbc77SKalle Valo break; 5828*f79cbc77SKalle Valo } 5829*f79cbc77SKalle Valo break; 5830*f79cbc77SKalle Valo default: 5831*f79cbc77SKalle Valo break; 5832*f79cbc77SKalle Valo } 5833*f79cbc77SKalle Valo 5834*f79cbc77SKalle Valo param.p2p_device = support_p2p_device; 5835*f79cbc77SKalle Valo param.mlo = mlo; 5836*f79cbc77SKalle Valo param.use_chanctx = channels > 1 || mlo; 5837*f79cbc77SKalle Valo param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK; 5838*f79cbc77SKalle Valo if (param.p2p_device) 5839*f79cbc77SKalle Valo param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); 5840*f79cbc77SKalle Valo 5841*f79cbc77SKalle Valo err = mac80211_hwsim_new_radio(NULL, ¶m); 5842*f79cbc77SKalle Valo if (err < 0) 5843*f79cbc77SKalle Valo goto out_free_radios; 5844*f79cbc77SKalle Valo } 5845*f79cbc77SKalle Valo 5846*f79cbc77SKalle Valo hwsim_mon = alloc_netdev(0, "hwsim%d", NET_NAME_UNKNOWN, 5847*f79cbc77SKalle Valo hwsim_mon_setup); 5848*f79cbc77SKalle Valo if (hwsim_mon == NULL) { 5849*f79cbc77SKalle Valo err = -ENOMEM; 5850*f79cbc77SKalle Valo goto out_free_radios; 5851*f79cbc77SKalle Valo } 5852*f79cbc77SKalle Valo 5853*f79cbc77SKalle Valo rtnl_lock(); 5854*f79cbc77SKalle Valo err = dev_alloc_name(hwsim_mon, hwsim_mon->name); 5855*f79cbc77SKalle Valo if (err < 0) { 5856*f79cbc77SKalle Valo rtnl_unlock(); 5857*f79cbc77SKalle Valo goto out_free_mon; 5858*f79cbc77SKalle Valo } 5859*f79cbc77SKalle Valo 5860*f79cbc77SKalle Valo err = register_netdevice(hwsim_mon); 5861*f79cbc77SKalle Valo if (err < 0) { 5862*f79cbc77SKalle Valo rtnl_unlock(); 5863*f79cbc77SKalle Valo goto out_free_mon; 5864*f79cbc77SKalle Valo } 5865*f79cbc77SKalle Valo rtnl_unlock(); 5866*f79cbc77SKalle Valo 5867*f79cbc77SKalle Valo return 0; 5868*f79cbc77SKalle Valo 5869*f79cbc77SKalle Valo out_free_mon: 5870*f79cbc77SKalle Valo free_netdev(hwsim_mon); 5871*f79cbc77SKalle Valo out_free_radios: 5872*f79cbc77SKalle Valo mac80211_hwsim_free(); 5873*f79cbc77SKalle Valo out_exit_virtio: 5874*f79cbc77SKalle Valo hwsim_unregister_virtio_driver(); 5875*f79cbc77SKalle Valo out_exit_netlink: 5876*f79cbc77SKalle Valo hwsim_exit_netlink(); 5877*f79cbc77SKalle Valo out_unregister_driver: 5878*f79cbc77SKalle Valo platform_driver_unregister(&mac80211_hwsim_driver); 5879*f79cbc77SKalle Valo out_unregister_pernet: 5880*f79cbc77SKalle Valo unregister_pernet_device(&hwsim_net_ops); 5881*f79cbc77SKalle Valo out_free_rht: 5882*f79cbc77SKalle Valo rhashtable_destroy(&hwsim_radios_rht); 5883*f79cbc77SKalle Valo return err; 5884*f79cbc77SKalle Valo } 5885*f79cbc77SKalle Valo module_init(init_mac80211_hwsim); 5886*f79cbc77SKalle Valo 5887*f79cbc77SKalle Valo static void __exit exit_mac80211_hwsim(void) 5888*f79cbc77SKalle Valo { 5889*f79cbc77SKalle Valo pr_debug("mac80211_hwsim: unregister radios\n"); 5890*f79cbc77SKalle Valo 5891*f79cbc77SKalle Valo hwsim_unregister_virtio_driver(); 5892*f79cbc77SKalle Valo hwsim_exit_netlink(); 5893*f79cbc77SKalle Valo 5894*f79cbc77SKalle Valo mac80211_hwsim_free(); 5895*f79cbc77SKalle Valo 5896*f79cbc77SKalle Valo rhashtable_destroy(&hwsim_radios_rht); 5897*f79cbc77SKalle Valo unregister_netdev(hwsim_mon); 5898*f79cbc77SKalle Valo platform_driver_unregister(&mac80211_hwsim_driver); 5899*f79cbc77SKalle Valo unregister_pernet_device(&hwsim_net_ops); 5900*f79cbc77SKalle Valo } 5901*f79cbc77SKalle Valo module_exit(exit_mac80211_hwsim); 5902