4932 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * NXP Wireless LAN device driver: CFG802114 *5 * Copyright 2011-2020 NXP6 */7 8#include "cfg80211.h"9#include "main.h"10#include "11n.h"11#include "wmm.h"12 13static char *reg_alpha2;14module_param(reg_alpha2, charp, 0);15 16static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {17 {18 .max = MWIFIEX_MAX_BSS_NUM,19 .types = BIT(NL80211_IFTYPE_STATION) |20 BIT(NL80211_IFTYPE_P2P_GO) |21 BIT(NL80211_IFTYPE_P2P_CLIENT) |22 BIT(NL80211_IFTYPE_AP),23 },24};25 26static const struct ieee80211_iface_combination27mwifiex_iface_comb_ap_sta = {28 .limits = mwifiex_ap_sta_limits,29 .num_different_channels = 1,30 .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),31 .max_interfaces = MWIFIEX_MAX_BSS_NUM,32 .beacon_int_infra_match = true,33 .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |34 BIT(NL80211_CHAN_WIDTH_20) |35 BIT(NL80211_CHAN_WIDTH_40),36};37 38static const struct ieee80211_iface_combination39mwifiex_iface_comb_ap_sta_vht = {40 .limits = mwifiex_ap_sta_limits,41 .num_different_channels = 1,42 .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),43 .max_interfaces = MWIFIEX_MAX_BSS_NUM,44 .beacon_int_infra_match = true,45 .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |46 BIT(NL80211_CHAN_WIDTH_20) |47 BIT(NL80211_CHAN_WIDTH_40) |48 BIT(NL80211_CHAN_WIDTH_80),49};50 51static const struct52ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = {53 .limits = mwifiex_ap_sta_limits,54 .num_different_channels = 2,55 .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),56 .max_interfaces = MWIFIEX_MAX_BSS_NUM,57 .beacon_int_infra_match = true,58};59 60/*61 * This function maps the nl802.11 channel type into driver channel type.62 *63 * The mapping is as follows -64 * NL80211_CHAN_NO_HT -> IEEE80211_HT_PARAM_CHA_SEC_NONE65 * NL80211_CHAN_HT20 -> IEEE80211_HT_PARAM_CHA_SEC_NONE66 * NL80211_CHAN_HT40PLUS -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE67 * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW68 * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE69 */70u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)71{72 switch (chan_type) {73 case NL80211_CHAN_NO_HT:74 case NL80211_CHAN_HT20:75 return IEEE80211_HT_PARAM_CHA_SEC_NONE;76 case NL80211_CHAN_HT40PLUS:77 return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;78 case NL80211_CHAN_HT40MINUS:79 return IEEE80211_HT_PARAM_CHA_SEC_BELOW;80 default:81 return IEEE80211_HT_PARAM_CHA_SEC_NONE;82 }83}84 85/* This function maps IEEE HT secondary channel type to NL80211 channel type86 */87u8 mwifiex_get_chan_type(struct mwifiex_private *priv)88{89 struct mwifiex_channel_band channel_band;90 int ret;91 92 ret = mwifiex_get_chan_info(priv, &channel_band);93 94 if (!ret) {95 switch (channel_band.band_config.chan_width) {96 case CHAN_BW_20MHZ:97 if (IS_11N_ENABLED(priv))98 return NL80211_CHAN_HT20;99 else100 return NL80211_CHAN_NO_HT;101 case CHAN_BW_40MHZ:102 if (channel_band.band_config.chan2_offset ==103 SEC_CHAN_ABOVE)104 return NL80211_CHAN_HT40PLUS;105 else106 return NL80211_CHAN_HT40MINUS;107 default:108 return NL80211_CHAN_HT20;109 }110 }111 112 return NL80211_CHAN_HT20;113}114 115/*116 * This function checks whether WEP is set.117 */118static int119mwifiex_is_alg_wep(u32 cipher)120{121 switch (cipher) {122 case WLAN_CIPHER_SUITE_WEP40:123 case WLAN_CIPHER_SUITE_WEP104:124 return 1;125 default:126 break;127 }128 129 return 0;130}131 132/*133 * This function retrieves the private structure from kernel wiphy structure.134 */135static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)136{137 return (void *) (*(unsigned long *) wiphy_priv(wiphy));138}139 140/*141 * CFG802.11 operation handler to delete a network key.142 */143static int144mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,145 int link_id, u8 key_index, bool pairwise,146 const u8 *mac_addr)147{148 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);149 static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};150 const u8 *peer_mac = pairwise ? mac_addr : bc_mac;151 152 if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {153 mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");154 return -EFAULT;155 }156 157 mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n");158 return 0;159}160 161/*162 * This function forms an skb for management frame.163 */164static int165mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)166{167 u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};168 u16 pkt_len;169 u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;170 171 pkt_len = len + ETH_ALEN;172 173 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +174 MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));175 memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));176 177 memcpy(skb_push(skb, sizeof(tx_control)),178 &tx_control, sizeof(tx_control));179 180 memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));181 182 /* Add packet data and address4 */183 skb_put_data(skb, buf, sizeof(struct ieee80211_hdr_3addr));184 skb_put_data(skb, addr, ETH_ALEN);185 skb_put_data(skb, buf + sizeof(struct ieee80211_hdr_3addr),186 len - sizeof(struct ieee80211_hdr_3addr));187 188 skb->priority = LOW_PRIO_TID;189 __net_timestamp(skb);190 191 return 0;192}193 194/*195 * CFG802.11 operation handler to transmit a management frame.196 */197static int198mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,199 struct cfg80211_mgmt_tx_params *params, u64 *cookie)200{201 const u8 *buf = params->buf;202 size_t len = params->len;203 struct sk_buff *skb;204 u16 pkt_len;205 const struct ieee80211_mgmt *mgmt;206 struct mwifiex_txinfo *tx_info;207 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);208 209 if (!buf || !len) {210 mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n");211 return -EFAULT;212 }213 214 mgmt = (const struct ieee80211_mgmt *)buf;215 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA &&216 ieee80211_is_probe_resp(mgmt->frame_control)) {217 /* Since we support offload probe resp, we need to skip probe218 * resp in AP or GO mode */219 mwifiex_dbg(priv->adapter, INFO,220 "info: skip to send probe resp in AP or GO mode\n");221 return 0;222 }223 224 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {225 if (ieee80211_is_auth(mgmt->frame_control))226 mwifiex_dbg(priv->adapter, MSG,227 "auth: send auth to %pM\n", mgmt->da);228 if (ieee80211_is_deauth(mgmt->frame_control))229 mwifiex_dbg(priv->adapter, MSG,230 "auth: send deauth to %pM\n", mgmt->da);231 if (ieee80211_is_disassoc(mgmt->frame_control))232 mwifiex_dbg(priv->adapter, MSG,233 "assoc: send disassoc to %pM\n", mgmt->da);234 if (ieee80211_is_assoc_resp(mgmt->frame_control))235 mwifiex_dbg(priv->adapter, MSG,236 "assoc: send assoc resp to %pM\n",237 mgmt->da);238 if (ieee80211_is_reassoc_resp(mgmt->frame_control))239 mwifiex_dbg(priv->adapter, MSG,240 "assoc: send reassoc resp to %pM\n",241 mgmt->da);242 }243 244 pkt_len = len + ETH_ALEN;245 skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +246 MWIFIEX_MGMT_FRAME_HEADER_SIZE +247 pkt_len + sizeof(pkt_len));248 249 if (!skb) {250 mwifiex_dbg(priv->adapter, ERROR,251 "allocate skb failed for management frame\n");252 return -ENOMEM;253 }254 255 tx_info = MWIFIEX_SKB_TXCB(skb);256 memset(tx_info, 0, sizeof(*tx_info));257 tx_info->bss_num = priv->bss_num;258 tx_info->bss_type = priv->bss_type;259 tx_info->pkt_len = pkt_len;260 261 mwifiex_form_mgmt_frame(skb, buf, len);262 *cookie = get_random_u32() | 1;263 264 if (ieee80211_is_action(mgmt->frame_control))265 skb = mwifiex_clone_skb_for_tx_status(priv,266 skb,267 MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie);268 else269 cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,270 GFP_ATOMIC);271 272 mwifiex_queue_tx_pkt(priv, skb);273 274 mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n");275 return 0;276}277 278/*279 * CFG802.11 operation handler to register a mgmt frame.280 */281static void282mwifiex_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,283 struct wireless_dev *wdev,284 struct mgmt_frame_regs *upd)285{286 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);287 u32 mask = upd->interface_stypes;288 289 if (mask != priv->mgmt_frame_mask) {290 priv->mgmt_frame_mask = mask;291 if (priv->host_mlme_reg)292 priv->mgmt_frame_mask |= HOST_MLME_MGMT_MASK;293 mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,294 HostCmd_ACT_GEN_SET, 0,295 &priv->mgmt_frame_mask, false);296 mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n");297 }298}299 300/*301 * CFG802.11 operation handler to remain on channel.302 */303static int304mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,305 struct wireless_dev *wdev,306 struct ieee80211_channel *chan,307 unsigned int duration, u64 *cookie)308{309 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);310 int ret;311 312 if (!chan || !cookie) {313 mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n");314 return -EINVAL;315 }316 317 if (priv->roc_cfg.cookie) {318 mwifiex_dbg(priv->adapter, INFO,319 "info: ongoing ROC, cookie = 0x%llx\n",320 priv->roc_cfg.cookie);321 return -EBUSY;322 }323 324 ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,325 duration);326 327 if (!ret) {328 *cookie = get_random_u32() | 1;329 priv->roc_cfg.cookie = *cookie;330 priv->roc_cfg.chan = *chan;331 332 cfg80211_ready_on_channel(wdev, *cookie, chan,333 duration, GFP_ATOMIC);334 335 mwifiex_dbg(priv->adapter, INFO,336 "info: ROC, cookie = 0x%llx\n", *cookie);337 }338 339 return ret;340}341 342/*343 * CFG802.11 operation handler to cancel remain on channel.344 */345static int346mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,347 struct wireless_dev *wdev, u64 cookie)348{349 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);350 int ret;351 352 if (cookie != priv->roc_cfg.cookie)353 return -ENOENT;354 355 ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,356 &priv->roc_cfg.chan, 0);357 358 if (!ret) {359 cfg80211_remain_on_channel_expired(wdev, cookie,360 &priv->roc_cfg.chan,361 GFP_ATOMIC);362 363 memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));364 365 mwifiex_dbg(priv->adapter, INFO,366 "info: cancel ROC, cookie = 0x%llx\n", cookie);367 }368 369 return ret;370}371 372/*373 * CFG802.11 operation handler to set Tx power.374 */375static int376mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,377 struct wireless_dev *wdev,378 enum nl80211_tx_power_setting type,379 int mbm)380{381 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);382 struct mwifiex_private *priv;383 struct mwifiex_power_cfg power_cfg;384 int dbm = MBM_TO_DBM(mbm);385 386 switch (type) {387 case NL80211_TX_POWER_FIXED:388 power_cfg.is_power_auto = 0;389 power_cfg.is_power_fixed = 1;390 power_cfg.power_level = dbm;391 break;392 case NL80211_TX_POWER_LIMITED:393 power_cfg.is_power_auto = 0;394 power_cfg.is_power_fixed = 0;395 power_cfg.power_level = dbm;396 break;397 case NL80211_TX_POWER_AUTOMATIC:398 power_cfg.is_power_auto = 1;399 break;400 }401 402 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);403 404 return mwifiex_set_tx_power(priv, &power_cfg);405}406 407/*408 * CFG802.11 operation handler to get Tx power.409 */410static int411mwifiex_cfg80211_get_tx_power(struct wiphy *wiphy,412 struct wireless_dev *wdev,413 int *dbm)414{415 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);416 struct mwifiex_private *priv = mwifiex_get_priv(adapter,417 MWIFIEX_BSS_ROLE_ANY);418 int ret = mwifiex_send_cmd(priv, HostCmd_CMD_RF_TX_PWR,419 HostCmd_ACT_GEN_GET, 0, NULL, true);420 421 if (ret < 0)422 return ret;423 424 /* tx_power_level is set in HostCmd_CMD_RF_TX_PWR command handler */425 *dbm = priv->tx_power_level;426 427 return 0;428}429 430/*431 * CFG802.11 operation handler to set Power Save option.432 *433 * The timeout value, if provided, is currently ignored.434 */435static int436mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,437 struct net_device *dev,438 bool enabled, int timeout)439{440 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);441 u32 ps_mode;442 443 if (timeout)444 mwifiex_dbg(priv->adapter, INFO,445 "info: ignore timeout value for IEEE Power Save\n");446 447 ps_mode = enabled;448 449 return mwifiex_drv_set_power(priv, &ps_mode);450}451 452/*453 * CFG802.11 operation handler to set the default network key.454 */455static int456mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,457 int link_id, u8 key_index, bool unicast,458 bool multicast)459{460 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);461 462 /* Return if WEP key not configured */463 if (!priv->sec_info.wep_enabled)464 return 0;465 466 if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {467 priv->wep_key_curr_index = key_index;468 } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,469 NULL, 0)) {470 mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n");471 return -EFAULT;472 }473 474 return 0;475}476 477/*478 * CFG802.11 operation handler to add a network key.479 */480static int481mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,482 int link_id, u8 key_index, bool pairwise,483 const u8 *mac_addr, struct key_params *params)484{485 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);486 struct mwifiex_wep_key *wep_key;487 static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};488 const u8 *peer_mac = pairwise ? mac_addr : bc_mac;489 490 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&491 (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||492 params->cipher == WLAN_CIPHER_SUITE_WEP104)) {493 if (params->key && params->key_len) {494 wep_key = &priv->wep_key[key_index];495 memset(wep_key, 0, sizeof(struct mwifiex_wep_key));496 memcpy(wep_key->key_material, params->key,497 params->key_len);498 wep_key->key_index = key_index;499 wep_key->key_length = params->key_len;500 priv->sec_info.wep_enabled = 1;501 }502 return 0;503 }504 505 if (mwifiex_set_encode(priv, params, params->key, params->key_len,506 key_index, peer_mac, 0)) {507 mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n");508 return -EFAULT;509 }510 511 return 0;512}513 514/*515 * CFG802.11 operation handler to set default mgmt key.516 */517static int518mwifiex_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,519 struct net_device *netdev,520 int link_id,521 u8 key_index)522{523 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);524 struct mwifiex_ds_encrypt_key encrypt_key;525 526 wiphy_dbg(wiphy, "set default mgmt key, key index=%d\n", key_index);527 528 if (priv->adapter->host_mlme_enabled)529 return 0;530 531 memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));532 encrypt_key.key_len = WLAN_KEY_LEN_CCMP;533 encrypt_key.key_index = key_index;534 encrypt_key.is_igtk_def_key = true;535 eth_broadcast_addr(encrypt_key.mac_addr);536 537 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,538 HostCmd_ACT_GEN_SET, true, &encrypt_key, true)) {539 mwifiex_dbg(priv->adapter, ERROR,540 "Sending KEY_MATERIAL command failed\n");541 return -1;542 }543 544 return 0;545}546 547/*548 * This function sends domain information to the firmware.549 *550 * The following information are passed to the firmware -551 * - Country codes552 * - Sub bands (first channel, number of channels, maximum Tx power)553 */554int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)555{556 u8 no_of_triplet = 0;557 struct ieee80211_country_ie_triplet *t;558 u8 no_of_parsed_chan = 0;559 u8 first_chan = 0, next_chan = 0, max_pwr = 0;560 u8 i, flag = 0;561 enum nl80211_band band;562 struct ieee80211_supported_band *sband;563 struct ieee80211_channel *ch;564 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);565 struct mwifiex_private *priv;566 struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;567 568 /* Set country code */569 domain_info->country_code[0] = adapter->country_code[0];570 domain_info->country_code[1] = adapter->country_code[1];571 domain_info->country_code[2] = ' ';572 573 band = mwifiex_band_to_radio_type(adapter->config_bands);574 if (!wiphy->bands[band]) {575 mwifiex_dbg(adapter, ERROR,576 "11D: setting domain info in FW\n");577 return -1;578 }579 580 sband = wiphy->bands[band];581 582 for (i = 0; i < sband->n_channels ; i++) {583 ch = &sband->channels[i];584 if (ch->flags & IEEE80211_CHAN_DISABLED)585 continue;586 587 if (!flag) {588 flag = 1;589 first_chan = (u32) ch->hw_value;590 next_chan = first_chan;591 max_pwr = ch->max_power;592 no_of_parsed_chan = 1;593 continue;594 }595 596 if (ch->hw_value == next_chan + 1 &&597 ch->max_power == max_pwr) {598 next_chan++;599 no_of_parsed_chan++;600 } else {601 t = &domain_info->triplet[no_of_triplet];602 t->chans.first_channel = first_chan;603 t->chans.num_channels = no_of_parsed_chan;604 t->chans.max_power = max_pwr;605 no_of_triplet++;606 first_chan = (u32) ch->hw_value;607 next_chan = first_chan;608 max_pwr = ch->max_power;609 no_of_parsed_chan = 1;610 }611 }612 613 if (flag) {614 t = &domain_info->triplet[no_of_triplet];615 t->chans.first_channel = first_chan;616 t->chans.num_channels = no_of_parsed_chan;617 t->chans.max_power = max_pwr;618 no_of_triplet++;619 }620 621 domain_info->no_of_triplet = no_of_triplet;622 623 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);624 625 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,626 HostCmd_ACT_GEN_SET, 0, NULL, false)) {627 mwifiex_dbg(adapter, INFO,628 "11D: setting domain info in FW\n");629 return -1;630 }631 632 return 0;633}634 635static void mwifiex_reg_apply_radar_flags(struct wiphy *wiphy)636{637 struct ieee80211_supported_band *sband;638 struct ieee80211_channel *chan;639 unsigned int i;640 641 if (!wiphy->bands[NL80211_BAND_5GHZ])642 return;643 sband = wiphy->bands[NL80211_BAND_5GHZ];644 645 for (i = 0; i < sband->n_channels; i++) {646 chan = &sband->channels[i];647 if ((!(chan->flags & IEEE80211_CHAN_DISABLED)) &&648 (chan->flags & IEEE80211_CHAN_RADAR))649 chan->flags |= IEEE80211_CHAN_NO_IR;650 }651}652 653/*654 * CFG802.11 regulatory domain callback function.655 *656 * This function is called when the regulatory domain is changed due to the657 * following reasons -658 * - Set by driver659 * - Set by system core660 * - Set by user661 * - Set bt Country IE662 */663static void mwifiex_reg_notifier(struct wiphy *wiphy,664 struct regulatory_request *request)665{666 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);667 struct mwifiex_private *priv = mwifiex_get_priv(adapter,668 MWIFIEX_BSS_ROLE_ANY);669 mwifiex_dbg(adapter, INFO,670 "info: cfg80211 regulatory domain callback for %c%c\n",671 request->alpha2[0], request->alpha2[1]);672 mwifiex_reg_apply_radar_flags(wiphy);673 674 switch (request->initiator) {675 case NL80211_REGDOM_SET_BY_DRIVER:676 case NL80211_REGDOM_SET_BY_CORE:677 case NL80211_REGDOM_SET_BY_USER:678 case NL80211_REGDOM_SET_BY_COUNTRY_IE:679 break;680 default:681 mwifiex_dbg(adapter, ERROR,682 "unknown regdom initiator: %d\n",683 request->initiator);684 return;685 }686 687 /* Don't send world or same regdom info to firmware */688 if (strncmp(request->alpha2, "00", 2) &&689 strncmp(request->alpha2, adapter->country_code,690 sizeof(request->alpha2))) {691 memcpy(adapter->country_code, request->alpha2,692 sizeof(request->alpha2));693 mwifiex_send_domain_info_cmd_fw(wiphy);694 mwifiex_dnld_txpwr_table(priv);695 }696}697 698/*699 * This function sets the fragmentation threshold.700 *701 * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE702 * and MWIFIEX_FRAG_MAX_VALUE.703 */704static int705mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)706{707 if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||708 frag_thr > MWIFIEX_FRAG_MAX_VALUE)709 frag_thr = MWIFIEX_FRAG_MAX_VALUE;710 711 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,712 HostCmd_ACT_GEN_SET, FRAG_THRESH_I,713 &frag_thr, true);714}715 716/*717 * This function sets the RTS threshold.718 719 * The rts value must lie between MWIFIEX_RTS_MIN_VALUE720 * and MWIFIEX_RTS_MAX_VALUE.721 */722static int723mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)724{725 if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)726 rts_thr = MWIFIEX_RTS_MAX_VALUE;727 728 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,729 HostCmd_ACT_GEN_SET, RTS_THRESH_I,730 &rts_thr, true);731}732 733/*734 * CFG802.11 operation handler to set wiphy parameters.735 *736 * This function can be used to set the RTS threshold and the737 * Fragmentation threshold of the driver.738 */739static int740mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)741{742 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);743 struct mwifiex_private *priv;744 struct mwifiex_uap_bss_param *bss_cfg;745 int ret;746 747 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);748 749 switch (priv->bss_role) {750 case MWIFIEX_BSS_ROLE_UAP:751 if (priv->bss_started) {752 mwifiex_dbg(adapter, ERROR,753 "cannot change wiphy params when bss started");754 return -EINVAL;755 }756 757 bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL);758 if (!bss_cfg)759 return -ENOMEM;760 761 mwifiex_set_sys_config_invalid_data(bss_cfg);762 763 if (changed & WIPHY_PARAM_RTS_THRESHOLD)764 bss_cfg->rts_threshold = wiphy->rts_threshold;765 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)766 bss_cfg->frag_threshold = wiphy->frag_threshold;767 if (changed & WIPHY_PARAM_RETRY_LONG)768 bss_cfg->retry_limit = wiphy->retry_long;769 770 ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,771 HostCmd_ACT_GEN_SET,772 UAP_BSS_PARAMS_I, bss_cfg,773 false);774 775 kfree(bss_cfg);776 if (ret) {777 mwifiex_dbg(adapter, ERROR,778 "Failed to set wiphy phy params\n");779 return ret;780 }781 break;782 783 case MWIFIEX_BSS_ROLE_STA:784 if (priv->media_connected) {785 mwifiex_dbg(adapter, ERROR,786 "cannot change wiphy params when connected");787 return -EINVAL;788 }789 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {790 ret = mwifiex_set_rts(priv,791 wiphy->rts_threshold);792 if (ret)793 return ret;794 }795 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {796 ret = mwifiex_set_frag(priv,797 wiphy->frag_threshold);798 if (ret)799 return ret;800 }801 break;802 }803 804 return 0;805}806 807static int808mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)809{810 u16 mode = P2P_MODE_DISABLE;811 812 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,813 HostCmd_ACT_GEN_SET, 0, &mode, true))814 return -1;815 816 return 0;817}818 819/*820 * This function initializes the functionalities for P2P client.821 * The P2P client initialization sequence is:822 * disable -> device -> client823 */824static int825mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)826{827 u16 mode;828 829 if (mwifiex_cfg80211_deinit_p2p(priv))830 return -1;831 832 mode = P2P_MODE_DEVICE;833 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,834 HostCmd_ACT_GEN_SET, 0, &mode, true))835 return -1;836 837 mode = P2P_MODE_CLIENT;838 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,839 HostCmd_ACT_GEN_SET, 0, &mode, true))840 return -1;841 842 return 0;843}844 845/*846 * This function initializes the functionalities for P2P GO.847 * The P2P GO initialization sequence is:848 * disable -> device -> GO849 */850static int851mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)852{853 u16 mode;854 855 if (mwifiex_cfg80211_deinit_p2p(priv))856 return -1;857 858 mode = P2P_MODE_DEVICE;859 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,860 HostCmd_ACT_GEN_SET, 0, &mode, true))861 return -1;862 863 mode = P2P_MODE_GO;864 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,865 HostCmd_ACT_GEN_SET, 0, &mode, true))866 return -1;867 868 return 0;869}870 871static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)872{873 struct mwifiex_adapter *adapter = priv->adapter;874 unsigned long flags;875 876 priv->host_mlme_reg = false;877 priv->mgmt_frame_mask = 0;878 if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,879 HostCmd_ACT_GEN_SET, 0,880 &priv->mgmt_frame_mask, false)) {881 mwifiex_dbg(adapter, ERROR,882 "could not unregister mgmt frame rx\n");883 return -1;884 }885 886 mwifiex_deauthenticate(priv, NULL);887 888 spin_lock_irqsave(&adapter->main_proc_lock, flags);889 adapter->main_locked = true;890 if (adapter->mwifiex_processing) {891 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);892 flush_workqueue(adapter->workqueue);893 } else {894 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);895 }896 897 spin_lock_bh(&adapter->rx_proc_lock);898 adapter->rx_locked = true;899 if (adapter->rx_processing) {900 spin_unlock_bh(&adapter->rx_proc_lock);901 flush_workqueue(adapter->rx_workqueue);902 } else {903 spin_unlock_bh(&adapter->rx_proc_lock);904 }905 906 mwifiex_free_priv(priv);907 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;908 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;909 priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;910 911 return 0;912}913 914static int915mwifiex_init_new_priv_params(struct mwifiex_private *priv,916 struct net_device *dev,917 enum nl80211_iftype type)918{919 struct mwifiex_adapter *adapter = priv->adapter;920 unsigned long flags;921 922 mwifiex_init_priv(priv);923 924 priv->bss_mode = type;925 priv->wdev.iftype = type;926 927 mwifiex_init_priv_params(priv, priv->netdev);928 priv->bss_started = 0;929 930 switch (type) {931 case NL80211_IFTYPE_STATION:932 case NL80211_IFTYPE_ADHOC:933 priv->bss_role = MWIFIEX_BSS_ROLE_STA;934 priv->bss_type = MWIFIEX_BSS_TYPE_STA;935 break;936 case NL80211_IFTYPE_P2P_CLIENT:937 priv->bss_role = MWIFIEX_BSS_ROLE_STA;938 priv->bss_type = MWIFIEX_BSS_TYPE_P2P;939 break;940 case NL80211_IFTYPE_P2P_GO:941 priv->bss_role = MWIFIEX_BSS_ROLE_UAP;942 priv->bss_type = MWIFIEX_BSS_TYPE_P2P;943 break;944 case NL80211_IFTYPE_AP:945 priv->bss_role = MWIFIEX_BSS_ROLE_UAP;946 priv->bss_type = MWIFIEX_BSS_TYPE_UAP;947 break;948 default:949 mwifiex_dbg(adapter, ERROR,950 "%s: changing to %d not supported\n",951 dev->name, type);952 return -EOPNOTSUPP;953 }954 955 priv->bss_num = mwifiex_get_unused_bss_num(adapter, priv->bss_type);956 957 spin_lock_irqsave(&adapter->main_proc_lock, flags);958 adapter->main_locked = false;959 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);960 961 spin_lock_bh(&adapter->rx_proc_lock);962 adapter->rx_locked = false;963 spin_unlock_bh(&adapter->rx_proc_lock);964 965 mwifiex_set_mac_address(priv, dev, false, NULL);966 967 return 0;968}969 970static bool971is_vif_type_change_allowed(struct mwifiex_adapter *adapter,972 enum nl80211_iftype old_iftype,973 enum nl80211_iftype new_iftype)974{975 switch (old_iftype) {976 case NL80211_IFTYPE_ADHOC:977 switch (new_iftype) {978 case NL80211_IFTYPE_STATION:979 return true;980 case NL80211_IFTYPE_P2P_CLIENT:981 case NL80211_IFTYPE_P2P_GO:982 return adapter->curr_iface_comb.p2p_intf !=983 adapter->iface_limit.p2p_intf;984 case NL80211_IFTYPE_AP:985 return adapter->curr_iface_comb.uap_intf !=986 adapter->iface_limit.uap_intf;987 default:988 return false;989 }990 991 case NL80211_IFTYPE_STATION:992 switch (new_iftype) {993 case NL80211_IFTYPE_ADHOC:994 return true;995 case NL80211_IFTYPE_P2P_CLIENT:996 case NL80211_IFTYPE_P2P_GO:997 return adapter->curr_iface_comb.p2p_intf !=998 adapter->iface_limit.p2p_intf;999 case NL80211_IFTYPE_AP:1000 return adapter->curr_iface_comb.uap_intf !=1001 adapter->iface_limit.uap_intf;1002 default:1003 return false;1004 }1005 1006 case NL80211_IFTYPE_AP:1007 switch (new_iftype) {1008 case NL80211_IFTYPE_ADHOC:1009 case NL80211_IFTYPE_STATION:1010 return adapter->curr_iface_comb.sta_intf !=1011 adapter->iface_limit.sta_intf;1012 case NL80211_IFTYPE_P2P_CLIENT:1013 case NL80211_IFTYPE_P2P_GO:1014 return adapter->curr_iface_comb.p2p_intf !=1015 adapter->iface_limit.p2p_intf;1016 default:1017 return false;1018 }1019 1020 case NL80211_IFTYPE_P2P_CLIENT:1021 switch (new_iftype) {1022 case NL80211_IFTYPE_ADHOC:1023 case NL80211_IFTYPE_STATION:1024 return true;1025 case NL80211_IFTYPE_P2P_GO:1026 return true;1027 case NL80211_IFTYPE_AP:1028 return adapter->curr_iface_comb.uap_intf !=1029 adapter->iface_limit.uap_intf;1030 default:1031 return false;1032 }1033 1034 case NL80211_IFTYPE_P2P_GO:1035 switch (new_iftype) {1036 case NL80211_IFTYPE_ADHOC:1037 case NL80211_IFTYPE_STATION:1038 return true;1039 case NL80211_IFTYPE_P2P_CLIENT:1040 return true;1041 case NL80211_IFTYPE_AP:1042 return adapter->curr_iface_comb.uap_intf !=1043 adapter->iface_limit.uap_intf;1044 default:1045 return false;1046 }1047 1048 default:1049 break;1050 }1051 1052 return false;1053}1054 1055static void1056update_vif_type_counter(struct mwifiex_adapter *adapter,1057 enum nl80211_iftype iftype,1058 int change)1059{1060 switch (iftype) {1061 case NL80211_IFTYPE_UNSPECIFIED:1062 case NL80211_IFTYPE_ADHOC:1063 case NL80211_IFTYPE_STATION:1064 adapter->curr_iface_comb.sta_intf += change;1065 break;1066 case NL80211_IFTYPE_AP:1067 adapter->curr_iface_comb.uap_intf += change;1068 break;1069 case NL80211_IFTYPE_P2P_CLIENT:1070 case NL80211_IFTYPE_P2P_GO:1071 adapter->curr_iface_comb.p2p_intf += change;1072 break;1073 default:1074 mwifiex_dbg(adapter, ERROR,1075 "%s: Unsupported iftype passed: %d\n",1076 __func__, iftype);1077 break;1078 }1079}1080 1081static int1082mwifiex_change_vif_to_p2p(struct net_device *dev,1083 enum nl80211_iftype curr_iftype,1084 enum nl80211_iftype type,1085 struct vif_params *params)1086{1087 struct mwifiex_private *priv;1088 struct mwifiex_adapter *adapter;1089 1090 priv = mwifiex_netdev_get_priv(dev);1091 1092 if (!priv)1093 return -1;1094 1095 adapter = priv->adapter;1096 1097 mwifiex_dbg(adapter, INFO,1098 "%s: changing role to p2p\n", dev->name);1099 1100 if (mwifiex_deinit_priv_params(priv))1101 return -1;1102 if (mwifiex_init_new_priv_params(priv, dev, type))1103 return -1;1104 1105 update_vif_type_counter(adapter, curr_iftype, -1);1106 update_vif_type_counter(adapter, type, +1);1107 dev->ieee80211_ptr->iftype = type;1108 1109 switch (type) {1110 case NL80211_IFTYPE_P2P_CLIENT:1111 if (mwifiex_cfg80211_init_p2p_client(priv))1112 return -EFAULT;1113 break;1114 case NL80211_IFTYPE_P2P_GO:1115 if (mwifiex_cfg80211_init_p2p_go(priv))1116 return -EFAULT;1117 break;1118 default:1119 mwifiex_dbg(adapter, ERROR,1120 "%s: changing to %d not supported\n",1121 dev->name, type);1122 return -EOPNOTSUPP;1123 }1124 1125 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1126 HostCmd_ACT_GEN_SET, 0, NULL, true))1127 return -1;1128 1129 if (mwifiex_sta_init_cmd(priv, false, false))1130 return -1;1131 1132 return 0;1133}1134 1135static int1136mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,1137 enum nl80211_iftype curr_iftype,1138 enum nl80211_iftype type,1139 struct vif_params *params)1140{1141 struct mwifiex_private *priv;1142 struct mwifiex_adapter *adapter;1143 1144 priv = mwifiex_netdev_get_priv(dev);1145 1146 if (!priv)1147 return -1;1148 1149 adapter = priv->adapter;1150 1151 if (type == NL80211_IFTYPE_STATION)1152 mwifiex_dbg(adapter, INFO,1153 "%s: changing role to station\n", dev->name);1154 else1155 mwifiex_dbg(adapter, INFO,1156 "%s: changing role to adhoc\n", dev->name);1157 1158 if (mwifiex_deinit_priv_params(priv))1159 return -1;1160 if (mwifiex_init_new_priv_params(priv, dev, type))1161 return -1;1162 1163 update_vif_type_counter(adapter, curr_iftype, -1);1164 update_vif_type_counter(adapter, type, +1);1165 dev->ieee80211_ptr->iftype = type;1166 1167 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1168 HostCmd_ACT_GEN_SET, 0, NULL, true))1169 return -1;1170 if (mwifiex_sta_init_cmd(priv, false, false))1171 return -1;1172 1173 return 0;1174}1175 1176static int1177mwifiex_change_vif_to_ap(struct net_device *dev,1178 enum nl80211_iftype curr_iftype,1179 enum nl80211_iftype type,1180 struct vif_params *params)1181{1182 struct mwifiex_private *priv;1183 struct mwifiex_adapter *adapter;1184 1185 priv = mwifiex_netdev_get_priv(dev);1186 1187 if (!priv)1188 return -1;1189 1190 adapter = priv->adapter;1191 1192 mwifiex_dbg(adapter, INFO,1193 "%s: changing role to AP\n", dev->name);1194 1195 if (mwifiex_deinit_priv_params(priv))1196 return -1;1197 if (mwifiex_init_new_priv_params(priv, dev, type))1198 return -1;1199 1200 update_vif_type_counter(adapter, curr_iftype, -1);1201 update_vif_type_counter(adapter, type, +1);1202 dev->ieee80211_ptr->iftype = type;1203 1204 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1205 HostCmd_ACT_GEN_SET, 0, NULL, true))1206 return -1;1207 if (mwifiex_sta_init_cmd(priv, false, false))1208 return -1;1209 1210 return 0;1211}1212/*1213 * CFG802.11 operation handler to change interface type.1214 */1215static int1216mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,1217 struct net_device *dev,1218 enum nl80211_iftype type,1219 struct vif_params *params)1220{1221 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1222 enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype;1223 1224 if (priv->scan_request) {1225 mwifiex_dbg(priv->adapter, ERROR,1226 "change virtual interface: scan in process\n");1227 return -EBUSY;1228 }1229 1230 if (type == NL80211_IFTYPE_UNSPECIFIED) {1231 mwifiex_dbg(priv->adapter, INFO,1232 "%s: no new type specified, keeping old type %d\n",1233 dev->name, curr_iftype);1234 return 0;1235 }1236 1237 if (curr_iftype == type) {1238 mwifiex_dbg(priv->adapter, INFO,1239 "%s: interface already is of type %d\n",1240 dev->name, curr_iftype);1241 return 0;1242 }1243 1244 if (!is_vif_type_change_allowed(priv->adapter, curr_iftype, type)) {1245 mwifiex_dbg(priv->adapter, ERROR,1246 "%s: change from type %d to %d is not allowed\n",1247 dev->name, curr_iftype, type);1248 return -EOPNOTSUPP;1249 }1250 1251 switch (curr_iftype) {1252 case NL80211_IFTYPE_ADHOC:1253 switch (type) {1254 case NL80211_IFTYPE_STATION:1255 priv->bss_mode = type;1256 priv->sec_info.authentication_mode =1257 NL80211_AUTHTYPE_OPEN_SYSTEM;1258 dev->ieee80211_ptr->iftype = type;1259 mwifiex_deauthenticate(priv, NULL);1260 return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1261 HostCmd_ACT_GEN_SET, 0, NULL,1262 true);1263 case NL80211_IFTYPE_P2P_CLIENT:1264 case NL80211_IFTYPE_P2P_GO:1265 return mwifiex_change_vif_to_p2p(dev, curr_iftype,1266 type, params);1267 case NL80211_IFTYPE_AP:1268 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,1269 params);1270 default:1271 goto errnotsupp;1272 }1273 1274 case NL80211_IFTYPE_STATION:1275 switch (type) {1276 case NL80211_IFTYPE_ADHOC:1277 priv->bss_mode = type;1278 priv->sec_info.authentication_mode =1279 NL80211_AUTHTYPE_OPEN_SYSTEM;1280 dev->ieee80211_ptr->iftype = type;1281 mwifiex_deauthenticate(priv, NULL);1282 return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1283 HostCmd_ACT_GEN_SET, 0, NULL,1284 true);1285 case NL80211_IFTYPE_P2P_CLIENT:1286 case NL80211_IFTYPE_P2P_GO:1287 return mwifiex_change_vif_to_p2p(dev, curr_iftype,1288 type, params);1289 case NL80211_IFTYPE_AP:1290 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,1291 params);1292 default:1293 goto errnotsupp;1294 }1295 1296 case NL80211_IFTYPE_AP:1297 switch (type) {1298 case NL80211_IFTYPE_ADHOC:1299 case NL80211_IFTYPE_STATION:1300 return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,1301 type, params);1302 break;1303 case NL80211_IFTYPE_P2P_CLIENT:1304 case NL80211_IFTYPE_P2P_GO:1305 return mwifiex_change_vif_to_p2p(dev, curr_iftype,1306 type, params);1307 default:1308 goto errnotsupp;1309 }1310 1311 case NL80211_IFTYPE_P2P_CLIENT:1312 if (mwifiex_cfg80211_deinit_p2p(priv))1313 return -EFAULT;1314 1315 switch (type) {1316 case NL80211_IFTYPE_ADHOC:1317 case NL80211_IFTYPE_STATION:1318 return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,1319 type, params);1320 case NL80211_IFTYPE_P2P_GO:1321 return mwifiex_change_vif_to_p2p(dev, curr_iftype,1322 type, params);1323 case NL80211_IFTYPE_AP:1324 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,1325 params);1326 default:1327 goto errnotsupp;1328 }1329 1330 case NL80211_IFTYPE_P2P_GO:1331 if (mwifiex_cfg80211_deinit_p2p(priv))1332 return -EFAULT;1333 1334 switch (type) {1335 case NL80211_IFTYPE_ADHOC:1336 case NL80211_IFTYPE_STATION:1337 return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,1338 type, params);1339 case NL80211_IFTYPE_P2P_CLIENT:1340 return mwifiex_change_vif_to_p2p(dev, curr_iftype,1341 type, params);1342 case NL80211_IFTYPE_AP:1343 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,1344 params);1345 default:1346 goto errnotsupp;1347 }1348 1349 default:1350 goto errnotsupp;1351 }1352 1353 1354 return 0;1355 1356errnotsupp:1357 mwifiex_dbg(priv->adapter, ERROR,1358 "unsupported interface type transition: %d to %d\n",1359 curr_iftype, type);1360 return -EOPNOTSUPP;1361}1362 1363static void1364mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 rateinfo, u8 htinfo,1365 struct rate_info *rate)1366{1367 struct mwifiex_adapter *adapter = priv->adapter;1368 1369 if (adapter->is_hw_11ac_capable) {1370 /* bit[1-0]: 00=LG 01=HT 10=VHT */1371 if (htinfo & BIT(0)) {1372 /* HT */1373 rate->mcs = rateinfo;1374 rate->flags |= RATE_INFO_FLAGS_MCS;1375 }1376 if (htinfo & BIT(1)) {1377 /* VHT */1378 rate->mcs = rateinfo & 0x0F;1379 rate->flags |= RATE_INFO_FLAGS_VHT_MCS;1380 }1381 1382 if (htinfo & (BIT(1) | BIT(0))) {1383 /* HT or VHT */1384 switch (htinfo & (BIT(3) | BIT(2))) {1385 case 0:1386 rate->bw = RATE_INFO_BW_20;1387 break;1388 case (BIT(2)):1389 rate->bw = RATE_INFO_BW_40;1390 break;1391 case (BIT(3)):1392 rate->bw = RATE_INFO_BW_80;1393 break;1394 case (BIT(3) | BIT(2)):1395 rate->bw = RATE_INFO_BW_160;1396 break;1397 }1398 1399 if (htinfo & BIT(4))1400 rate->flags |= RATE_INFO_FLAGS_SHORT_GI;1401 1402 if ((rateinfo >> 4) == 1)1403 rate->nss = 2;1404 else1405 rate->nss = 1;1406 }1407 } else {1408 /*1409 * Bit 0 in htinfo indicates that current rate is 11n. Valid1410 * MCS index values for us are 0 to 15.1411 */1412 if ((htinfo & BIT(0)) && (rateinfo < 16)) {1413 rate->mcs = rateinfo;1414 rate->flags |= RATE_INFO_FLAGS_MCS;1415 rate->bw = RATE_INFO_BW_20;1416 if (htinfo & BIT(1))1417 rate->bw = RATE_INFO_BW_40;1418 if (htinfo & BIT(2))1419 rate->flags |= RATE_INFO_FLAGS_SHORT_GI;1420 }1421 }1422 1423 /* Decode legacy rates for non-HT. */1424 if (!(htinfo & (BIT(0) | BIT(1)))) {1425 /* Bitrates in multiples of 100kb/s. */1426 static const int legacy_rates[] = {1427 [0] = 10,1428 [1] = 20,1429 [2] = 55,1430 [3] = 110,1431 [4] = 60, /* MWIFIEX_RATE_INDEX_OFDM0 */1432 [5] = 60,1433 [6] = 90,1434 [7] = 120,1435 [8] = 180,1436 [9] = 240,1437 [10] = 360,1438 [11] = 480,1439 [12] = 540,1440 };1441 if (rateinfo < ARRAY_SIZE(legacy_rates))1442 rate->legacy = legacy_rates[rateinfo];1443 }1444}1445 1446/*1447 * This function dumps the station information on a buffer.1448 *1449 * The following information are shown -1450 * - Total bytes transmitted1451 * - Total bytes received1452 * - Total packets transmitted1453 * - Total packets received1454 * - Signal quality level1455 * - Transmission rate1456 */1457static int1458mwifiex_dump_station_info(struct mwifiex_private *priv,1459 struct mwifiex_sta_node *node,1460 struct station_info *sinfo)1461{1462 u32 rate;1463 1464 sinfo->filled = BIT_ULL(NL80211_STA_INFO_RX_BYTES) | BIT_ULL(NL80211_STA_INFO_TX_BYTES) |1465 BIT_ULL(NL80211_STA_INFO_RX_PACKETS) | BIT_ULL(NL80211_STA_INFO_TX_PACKETS) |1466 BIT_ULL(NL80211_STA_INFO_TX_BITRATE) |1467 BIT_ULL(NL80211_STA_INFO_SIGNAL) | BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);1468 1469 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {1470 if (!node)1471 return -ENOENT;1472 1473 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) |1474 BIT_ULL(NL80211_STA_INFO_TX_FAILED);1475 sinfo->inactive_time =1476 jiffies_to_msecs(jiffies - node->stats.last_rx);1477 1478 sinfo->signal = node->stats.rssi;1479 sinfo->signal_avg = node->stats.rssi;1480 sinfo->rx_bytes = node->stats.rx_bytes;1481 sinfo->tx_bytes = node->stats.tx_bytes;1482 sinfo->rx_packets = node->stats.rx_packets;1483 sinfo->tx_packets = node->stats.tx_packets;1484 sinfo->tx_failed = node->stats.tx_failed;1485 1486 mwifiex_parse_htinfo(priv, priv->tx_rate,1487 node->stats.last_tx_htinfo,1488 &sinfo->txrate);1489 sinfo->txrate.legacy = node->stats.last_tx_rate * 5;1490 1491 return 0;1492 }1493 1494 /* Get signal information from the firmware */1495 if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,1496 HostCmd_ACT_GEN_GET, 0, NULL, true)) {1497 mwifiex_dbg(priv->adapter, ERROR,1498 "failed to get signal information\n");1499 return -EFAULT;1500 }1501 1502 if (mwifiex_drv_get_data_rate(priv, &rate)) {1503 mwifiex_dbg(priv->adapter, ERROR,1504 "getting data rate error\n");1505 return -EFAULT;1506 }1507 1508 /* Get DTIM period information from firmware */1509 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,1510 HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,1511 &priv->dtim_period, true);1512 1513 mwifiex_parse_htinfo(priv, priv->tx_rate, priv->tx_htinfo,1514 &sinfo->txrate);1515 1516 sinfo->signal_avg = priv->bcn_rssi_avg;1517 sinfo->rx_bytes = priv->stats.rx_bytes;1518 sinfo->tx_bytes = priv->stats.tx_bytes;1519 sinfo->rx_packets = priv->stats.rx_packets;1520 sinfo->tx_packets = priv->stats.tx_packets;1521 sinfo->signal = priv->bcn_rssi_avg;1522 /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */1523 sinfo->txrate.legacy = rate * 5;1524 1525 sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);1526 mwifiex_parse_htinfo(priv, priv->rxpd_rate, priv->rxpd_htinfo,1527 &sinfo->rxrate);1528 1529 if (priv->bss_mode == NL80211_IFTYPE_STATION) {1530 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BSS_PARAM);1531 sinfo->bss_param.flags = 0;1532 if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &1533 WLAN_CAPABILITY_SHORT_PREAMBLE)1534 sinfo->bss_param.flags |=1535 BSS_PARAM_FLAGS_SHORT_PREAMBLE;1536 if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &1537 WLAN_CAPABILITY_SHORT_SLOT_TIME)1538 sinfo->bss_param.flags |=1539 BSS_PARAM_FLAGS_SHORT_SLOT_TIME;1540 sinfo->bss_param.dtim_period = priv->dtim_period;1541 sinfo->bss_param.beacon_interval =1542 priv->curr_bss_params.bss_descriptor.beacon_period;1543 }1544 1545 return 0;1546}1547 1548/*1549 * CFG802.11 operation handler to get station information.1550 *1551 * This function only works in connected mode, and dumps the1552 * requested station information, if available.1553 */1554static int1555mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,1556 const u8 *mac, struct station_info *sinfo)1557{1558 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1559 1560 if (!priv->media_connected)1561 return -ENOENT;1562 if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))1563 return -ENOENT;1564 1565 return mwifiex_dump_station_info(priv, NULL, sinfo);1566}1567 1568/*1569 * CFG802.11 operation handler to dump station information.1570 */1571static int1572mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,1573 int idx, u8 *mac, struct station_info *sinfo)1574{1575 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1576 struct mwifiex_sta_node *node;1577 int i;1578 1579 if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&1580 priv->media_connected && idx == 0) {1581 ether_addr_copy(mac, priv->cfg_bssid);1582 return mwifiex_dump_station_info(priv, NULL, sinfo);1583 } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {1584 mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,1585 HostCmd_ACT_GEN_GET, 0, NULL, true);1586 1587 i = 0;1588 list_for_each_entry(node, &priv->sta_list, list) {1589 if (i++ != idx)1590 continue;1591 ether_addr_copy(mac, node->mac_addr);1592 return mwifiex_dump_station_info(priv, node, sinfo);1593 }1594 }1595 1596 return -ENOENT;1597}1598 1599static int1600mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,1601 int idx, struct survey_info *survey)1602{1603 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1604 struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;1605 enum nl80211_band band;1606 1607 mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx);1608 1609 memset(survey, 0, sizeof(struct survey_info));1610 1611 if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&1612 priv->media_connected && idx == 0) {1613 u8 curr_bss_band = priv->curr_bss_params.band;1614 u32 chan = priv->curr_bss_params.bss_descriptor.channel;1615 1616 band = mwifiex_band_to_radio_type(curr_bss_band);1617 survey->channel = ieee80211_get_channel(wiphy,1618 ieee80211_channel_to_frequency(chan, band));1619 1620 if (priv->bcn_nf_last) {1621 survey->filled = SURVEY_INFO_NOISE_DBM;1622 survey->noise = priv->bcn_nf_last;1623 }1624 return 0;1625 }1626 1627 if (idx >= priv->adapter->num_in_chan_stats)1628 return -ENOENT;1629 1630 if (!pchan_stats[idx].cca_scan_dur)1631 return 0;1632 1633 band = pchan_stats[idx].bandcfg;1634 survey->channel = ieee80211_get_channel(wiphy,1635 ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));1636 survey->filled = SURVEY_INFO_NOISE_DBM |1637 SURVEY_INFO_TIME |1638 SURVEY_INFO_TIME_BUSY;1639 survey->noise = pchan_stats[idx].noise;1640 survey->time = pchan_stats[idx].cca_scan_dur;1641 survey->time_busy = pchan_stats[idx].cca_busy_dur;1642 1643 return 0;1644}1645 1646/* Supported rates to be advertised to the cfg80211 */1647static struct ieee80211_rate mwifiex_rates[] = {1648 {.bitrate = 10, .hw_value = 2, },1649 {.bitrate = 20, .hw_value = 4, },1650 {.bitrate = 55, .hw_value = 11, },1651 {.bitrate = 110, .hw_value = 22, },1652 {.bitrate = 60, .hw_value = 12, },1653 {.bitrate = 90, .hw_value = 18, },1654 {.bitrate = 120, .hw_value = 24, },1655 {.bitrate = 180, .hw_value = 36, },1656 {.bitrate = 240, .hw_value = 48, },1657 {.bitrate = 360, .hw_value = 72, },1658 {.bitrate = 480, .hw_value = 96, },1659 {.bitrate = 540, .hw_value = 108, },1660};1661 1662/* Channel definitions to be advertised to cfg80211 */1663static struct ieee80211_channel mwifiex_channels_2ghz[] = {1664 {.center_freq = 2412, .hw_value = 1, },1665 {.center_freq = 2417, .hw_value = 2, },1666 {.center_freq = 2422, .hw_value = 3, },1667 {.center_freq = 2427, .hw_value = 4, },1668 {.center_freq = 2432, .hw_value = 5, },1669 {.center_freq = 2437, .hw_value = 6, },1670 {.center_freq = 2442, .hw_value = 7, },1671 {.center_freq = 2447, .hw_value = 8, },1672 {.center_freq = 2452, .hw_value = 9, },1673 {.center_freq = 2457, .hw_value = 10, },1674 {.center_freq = 2462, .hw_value = 11, },1675 {.center_freq = 2467, .hw_value = 12, },1676 {.center_freq = 2472, .hw_value = 13, },1677 {.center_freq = 2484, .hw_value = 14, },1678};1679 1680static struct ieee80211_supported_band mwifiex_band_2ghz = {1681 .channels = mwifiex_channels_2ghz,1682 .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),1683 .bitrates = mwifiex_rates,1684 .n_bitrates = ARRAY_SIZE(mwifiex_rates),1685};1686 1687static struct ieee80211_channel mwifiex_channels_5ghz[] = {1688 {.center_freq = 5040, .hw_value = 8, },1689 {.center_freq = 5060, .hw_value = 12, },1690 {.center_freq = 5080, .hw_value = 16, },1691 {.center_freq = 5170, .hw_value = 34, },1692 {.center_freq = 5190, .hw_value = 38, },1693 {.center_freq = 5210, .hw_value = 42, },1694 {.center_freq = 5230, .hw_value = 46, },1695 {.center_freq = 5180, .hw_value = 36, },1696 {.center_freq = 5200, .hw_value = 40, },1697 {.center_freq = 5220, .hw_value = 44, },1698 {.center_freq = 5240, .hw_value = 48, },1699 {.center_freq = 5260, .hw_value = 52, },1700 {.center_freq = 5280, .hw_value = 56, },1701 {.center_freq = 5300, .hw_value = 60, },1702 {.center_freq = 5320, .hw_value = 64, },1703 {.center_freq = 5500, .hw_value = 100, },1704 {.center_freq = 5520, .hw_value = 104, },1705 {.center_freq = 5540, .hw_value = 108, },1706 {.center_freq = 5560, .hw_value = 112, },1707 {.center_freq = 5580, .hw_value = 116, },1708 {.center_freq = 5600, .hw_value = 120, },1709 {.center_freq = 5620, .hw_value = 124, },1710 {.center_freq = 5640, .hw_value = 128, },1711 {.center_freq = 5660, .hw_value = 132, },1712 {.center_freq = 5680, .hw_value = 136, },1713 {.center_freq = 5700, .hw_value = 140, },1714 {.center_freq = 5745, .hw_value = 149, },1715 {.center_freq = 5765, .hw_value = 153, },1716 {.center_freq = 5785, .hw_value = 157, },1717 {.center_freq = 5805, .hw_value = 161, },1718 {.center_freq = 5825, .hw_value = 165, },1719};1720 1721static struct ieee80211_supported_band mwifiex_band_5ghz = {1722 .channels = mwifiex_channels_5ghz,1723 .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),1724 .bitrates = mwifiex_rates + 4,1725 .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,1726};1727 1728 1729/* Supported crypto cipher suits to be advertised to cfg80211 */1730static const u32 mwifiex_cipher_suites[] = {1731 WLAN_CIPHER_SUITE_WEP40,1732 WLAN_CIPHER_SUITE_WEP104,1733 WLAN_CIPHER_SUITE_TKIP,1734 WLAN_CIPHER_SUITE_CCMP,1735 WLAN_CIPHER_SUITE_SMS4,1736 WLAN_CIPHER_SUITE_AES_CMAC,1737};1738 1739/* Supported mgmt frame types to be advertised to cfg80211 */1740static const struct ieee80211_txrx_stypes1741mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {1742 [NL80211_IFTYPE_STATION] = {1743 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |1744 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),1745 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |1746 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),1747 },1748 [NL80211_IFTYPE_AP] = {1749 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |1750 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),1751 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |1752 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),1753 },1754 [NL80211_IFTYPE_P2P_CLIENT] = {1755 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |1756 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),1757 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |1758 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),1759 },1760 [NL80211_IFTYPE_P2P_GO] = {1761 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |1762 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),1763 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |1764 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),1765 },1766};1767 1768/*1769 * CFG802.11 operation handler for setting bit rates.1770 *1771 * Function configures data rates to firmware using bitrate mask1772 * provided by cfg80211.1773 */1774static int1775mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,1776 struct net_device *dev,1777 unsigned int link_id,1778 const u8 *peer,1779 const struct cfg80211_bitrate_mask *mask)1780{1781 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1782 u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];1783 enum nl80211_band band;1784 struct mwifiex_adapter *adapter = priv->adapter;1785 1786 if (!priv->media_connected) {1787 mwifiex_dbg(adapter, ERROR,1788 "Can not set Tx data rate in disconnected state\n");1789 return -EINVAL;1790 }1791 1792 band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);1793 1794 memset(bitmap_rates, 0, sizeof(bitmap_rates));1795 1796 /* Fill HR/DSSS rates. */1797 if (band == NL80211_BAND_2GHZ)1798 bitmap_rates[0] = mask->control[band].legacy & 0x000f;1799 1800 /* Fill OFDM rates */1801 if (band == NL80211_BAND_2GHZ)1802 bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;1803 else1804 bitmap_rates[1] = mask->control[band].legacy;1805 1806 /* Fill HT MCS rates */1807 bitmap_rates[2] = mask->control[band].ht_mcs[0];1808 if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)1809 bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;1810 1811 /* Fill VHT MCS rates */1812 if (adapter->fw_api_ver == MWIFIEX_FW_V15) {1813 bitmap_rates[10] = mask->control[band].vht_mcs[0];1814 if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)1815 bitmap_rates[11] = mask->control[band].vht_mcs[1];1816 }1817 1818 return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,1819 HostCmd_ACT_GEN_SET, 0, bitmap_rates, true);1820}1821 1822/*1823 * CFG802.11 operation handler for connection quality monitoring.1824 *1825 * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI1826 * events to FW.1827 */1828static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,1829 struct net_device *dev,1830 s32 rssi_thold, u32 rssi_hyst)1831{1832 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1833 struct mwifiex_ds_misc_subsc_evt subsc_evt;1834 1835 priv->cqm_rssi_thold = rssi_thold;1836 priv->cqm_rssi_hyst = rssi_hyst;1837 1838 memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));1839 subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;1840 1841 /* Subscribe/unsubscribe low and high rssi events */1842 if (rssi_thold && rssi_hyst) {1843 subsc_evt.action = HostCmd_ACT_BITWISE_SET;1844 subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold);1845 subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold);1846 subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;1847 subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;1848 return mwifiex_send_cmd(priv,1849 HostCmd_CMD_802_11_SUBSCRIBE_EVENT,1850 0, 0, &subsc_evt, true);1851 } else {1852 subsc_evt.action = HostCmd_ACT_BITWISE_CLR;1853 return mwifiex_send_cmd(priv,1854 HostCmd_CMD_802_11_SUBSCRIBE_EVENT,1855 0, 0, &subsc_evt, true);1856 }1857 1858 return 0;1859}1860 1861/* cfg80211 operation handler for change_beacon.1862 * Function retrieves and sets modified management IEs to FW.1863 */1864static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,1865 struct net_device *dev,1866 struct cfg80211_ap_update *params)1867{1868 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1869 struct mwifiex_adapter *adapter = priv->adapter;1870 struct cfg80211_beacon_data *data = ¶ms->beacon;1871 1872 mwifiex_cancel_scan(adapter);1873 1874 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {1875 mwifiex_dbg(priv->adapter, ERROR,1876 "%s: bss_type mismatched\n", __func__);1877 return -EINVAL;1878 }1879 1880 if (!priv->bss_started) {1881 mwifiex_dbg(priv->adapter, ERROR,1882 "%s: bss not started\n", __func__);1883 return -EINVAL;1884 }1885 1886 if (mwifiex_set_mgmt_ies(priv, data)) {1887 mwifiex_dbg(priv->adapter, ERROR,1888 "%s: setting mgmt ies failed\n", __func__);1889 return -EFAULT;1890 }1891 1892 return 0;1893}1894 1895/* cfg80211 operation handler for del_station.1896 * Function deauthenticates station which value is provided in mac parameter.1897 * If mac is NULL/broadcast, all stations in associated station list are1898 * deauthenticated. If bss is not started or there are no stations in1899 * associated stations list, no action is taken.1900 */1901static int1902mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,1903 struct station_del_parameters *params)1904{1905 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1906 struct mwifiex_sta_node *sta_node;1907 u8 deauth_mac[ETH_ALEN];1908 1909 if (!priv->bss_started && priv->wdev.links[0].cac_started) {1910 mwifiex_dbg(priv->adapter, INFO, "%s: abort CAC!\n", __func__);1911 mwifiex_abort_cac(priv);1912 }1913 1914 if (list_empty(&priv->sta_list) || !priv->bss_started)1915 return 0;1916 1917 if (!params->mac || is_broadcast_ether_addr(params->mac))1918 return 0;1919 1920 mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n",1921 __func__, params->mac);1922 1923 eth_zero_addr(deauth_mac);1924 1925 spin_lock_bh(&priv->sta_list_spinlock);1926 sta_node = mwifiex_get_sta_entry(priv, params->mac);1927 if (sta_node)1928 ether_addr_copy(deauth_mac, params->mac);1929 spin_unlock_bh(&priv->sta_list_spinlock);1930 1931 if (is_valid_ether_addr(deauth_mac)) {1932 if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,1933 HostCmd_ACT_GEN_SET, 0,1934 deauth_mac, true))1935 return -1;1936 }1937 1938 return 0;1939}1940 1941static int1942mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)1943{1944 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);1945 struct mwifiex_private *priv = mwifiex_get_priv(adapter,1946 MWIFIEX_BSS_ROLE_ANY);1947 struct mwifiex_ds_ant_cfg ant_cfg;1948 1949 if (!tx_ant || !rx_ant)1950 return -EOPNOTSUPP;1951 1952 if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {1953 /* Not a MIMO chip. User should provide specific antenna number1954 * for Tx/Rx path or enable all antennas for diversity1955 */1956 if (tx_ant != rx_ant)1957 return -EOPNOTSUPP;1958 1959 if ((tx_ant & (tx_ant - 1)) &&1960 (tx_ant != BIT(adapter->number_of_antenna) - 1))1961 return -EOPNOTSUPP;1962 1963 if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&1964 (priv->adapter->number_of_antenna > 1)) {1965 tx_ant = RF_ANTENNA_AUTO;1966 rx_ant = RF_ANTENNA_AUTO;1967 }1968 } else {1969 struct ieee80211_sta_ht_cap *ht_info;1970 int rx_mcs_supp;1971 enum nl80211_band band;1972 1973 if ((tx_ant == 0x1 && rx_ant == 0x1)) {1974 adapter->user_dev_mcs_support = HT_STREAM_1X1;1975 if (adapter->is_hw_11ac_capable)1976 adapter->usr_dot_11ac_mcs_support =1977 MWIFIEX_11AC_MCS_MAP_1X1;1978 } else {1979 adapter->user_dev_mcs_support = HT_STREAM_2X2;1980 if (adapter->is_hw_11ac_capable)1981 adapter->usr_dot_11ac_mcs_support =1982 MWIFIEX_11AC_MCS_MAP_2X2;1983 }1984 1985 for (band = 0; band < NUM_NL80211_BANDS; band++) {1986 if (!adapter->wiphy->bands[band])1987 continue;1988 1989 ht_info = &adapter->wiphy->bands[band]->ht_cap;1990 rx_mcs_supp =1991 GET_RXMCSSUPP(adapter->user_dev_mcs_support);1992 memset(&ht_info->mcs, 0, adapter->number_of_antenna);1993 memset(&ht_info->mcs, 0xff, rx_mcs_supp);1994 }1995 }1996 1997 ant_cfg.tx_ant = tx_ant;1998 ant_cfg.rx_ant = rx_ant;1999 2000 return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,2001 HostCmd_ACT_GEN_SET, 0, &ant_cfg, true);2002}2003 2004static int2005mwifiex_cfg80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)2006{2007 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);2008 struct mwifiex_private *priv = mwifiex_get_priv(adapter,2009 MWIFIEX_BSS_ROLE_ANY);2010 mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,2011 HostCmd_ACT_GEN_GET, 0, NULL, true);2012 2013 *tx_ant = priv->tx_ant;2014 *rx_ant = priv->rx_ant;2015 2016 return 0;2017}2018 2019/* cfg80211 operation handler for stop ap.2020 * Function stops BSS running at uAP interface.2021 */2022static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,2023 unsigned int link_id)2024{2025 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2026 2027 mwifiex_abort_cac(priv);2028 2029 if (mwifiex_del_mgmt_ies(priv))2030 mwifiex_dbg(priv->adapter, ERROR,2031 "Failed to delete mgmt IEs!\n");2032 2033 priv->ap_11n_enabled = 0;2034 memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg));2035 2036 if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,2037 HostCmd_ACT_GEN_SET, 0, NULL, true)) {2038 mwifiex_dbg(priv->adapter, ERROR,2039 "Failed to stop the BSS\n");2040 return -1;2041 }2042 2043 if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,2044 HostCmd_ACT_GEN_SET, 0, NULL, true)) {2045 mwifiex_dbg(priv->adapter, ERROR,2046 "Failed to reset BSS\n");2047 return -1;2048 }2049 2050 if (netif_carrier_ok(priv->netdev))2051 netif_carrier_off(priv->netdev);2052 mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);2053 2054 return 0;2055}2056 2057/* cfg80211 operation handler for start_ap.2058 * Function sets beacon period, DTIM period, SSID and security into2059 * AP config structure.2060 * AP is configured with these settings and BSS is started.2061 */2062static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,2063 struct net_device *dev,2064 struct cfg80211_ap_settings *params)2065{2066 struct mwifiex_uap_bss_param *bss_cfg;2067 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2068 2069 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)2070 return -1;2071 2072 bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);2073 if (!bss_cfg)2074 return -ENOMEM;2075 2076 mwifiex_set_sys_config_invalid_data(bss_cfg);2077 2078 memcpy(bss_cfg->mac_addr, priv->curr_addr, ETH_ALEN);2079 2080 if (params->beacon_interval)2081 bss_cfg->beacon_period = params->beacon_interval;2082 if (params->dtim_period)2083 bss_cfg->dtim_period = params->dtim_period;2084 2085 if (params->ssid && params->ssid_len) {2086 memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);2087 bss_cfg->ssid.ssid_len = params->ssid_len;2088 }2089 if (params->inactivity_timeout > 0) {2090 /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */2091 bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;2092 bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;2093 }2094 2095 switch (params->hidden_ssid) {2096 case NL80211_HIDDEN_SSID_NOT_IN_USE:2097 bss_cfg->bcast_ssid_ctl = 1;2098 break;2099 case NL80211_HIDDEN_SSID_ZERO_LEN:2100 bss_cfg->bcast_ssid_ctl = 0;2101 break;2102 case NL80211_HIDDEN_SSID_ZERO_CONTENTS:2103 bss_cfg->bcast_ssid_ctl = 2;2104 break;2105 default:2106 kfree(bss_cfg);2107 return -EINVAL;2108 }2109 2110 mwifiex_uap_set_channel(priv, bss_cfg, params->chandef);2111 mwifiex_set_uap_rates(bss_cfg, params);2112 2113 if (mwifiex_set_secure_params(priv, bss_cfg, params)) {2114 mwifiex_dbg(priv->adapter, ERROR,2115 "Failed to parse security parameters!\n");2116 goto out;2117 }2118 2119 mwifiex_set_ht_params(priv, bss_cfg, params);2120 2121 if (priv->adapter->is_hw_11ac_capable) {2122 mwifiex_set_vht_params(priv, bss_cfg, params);2123 mwifiex_set_vht_width(priv, params->chandef.width,2124 priv->ap_11ac_enabled);2125 }2126 2127 if (priv->ap_11ac_enabled)2128 mwifiex_set_11ac_ba_params(priv);2129 else2130 mwifiex_set_ba_params(priv);2131 2132 mwifiex_set_wmm_params(priv, bss_cfg, params);2133 2134 if (mwifiex_is_11h_active(priv))2135 mwifiex_set_tpc_params(priv, bss_cfg, params);2136 2137 if (mwifiex_is_11h_active(priv) &&2138 !cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef,2139 priv->bss_mode)) {2140 mwifiex_dbg(priv->adapter, INFO,2141 "Disable 11h extensions in FW\n");2142 if (mwifiex_11h_activate(priv, false)) {2143 mwifiex_dbg(priv->adapter, ERROR,2144 "Failed to disable 11h extensions!!");2145 goto out;2146 }2147 priv->state_11h.is_11h_active = false;2148 }2149 2150 mwifiex_config_uap_11d(priv, ¶ms->beacon);2151 2152 if (mwifiex_config_start_uap(priv, bss_cfg)) {2153 mwifiex_dbg(priv->adapter, ERROR,2154 "Failed to start AP\n");2155 goto out;2156 }2157 2158 if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon))2159 goto out;2160 2161 if (!netif_carrier_ok(priv->netdev))2162 netif_carrier_on(priv->netdev);2163 mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter);2164 2165 memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));2166 kfree(bss_cfg);2167 return 0;2168 2169out:2170 kfree(bss_cfg);2171 return -1;2172}2173 2174/*2175 * CFG802.11 operation handler for disconnection request.2176 *2177 * This function does not work when there is already a disconnection2178 * procedure going on.2179 */2180static int2181mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,2182 u16 reason_code)2183{2184 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2185 2186 if (!mwifiex_stop_bg_scan(priv))2187 cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);2188 2189 if (mwifiex_deauthenticate(priv, NULL))2190 return -EFAULT;2191 2192 eth_zero_addr(priv->cfg_bssid);2193 priv->hs2_enabled = false;2194 2195 return 0;2196}2197 2198/*2199 * This function informs the CFG802.11 subsystem of a new IBSS.2200 *2201 * The following information are sent to the CFG802.11 subsystem2202 * to register the new IBSS. If we do not register the new IBSS,2203 * a kernel panic will result.2204 * - SSID2205 * - SSID length2206 * - BSSID2207 * - Channel2208 */2209static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)2210{2211 struct ieee80211_channel *chan;2212 struct mwifiex_bss_info bss_info;2213 struct cfg80211_bss *bss;2214 int ie_len;2215 u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];2216 enum nl80211_band band;2217 2218 if (mwifiex_get_bss_info(priv, &bss_info))2219 return -1;2220 2221 ie_buf[0] = WLAN_EID_SSID;2222 ie_buf[1] = bss_info.ssid.ssid_len;2223 2224 memcpy(&ie_buf[sizeof(struct ieee_types_header)],2225 &bss_info.ssid.ssid, bss_info.ssid.ssid_len);2226 ie_len = ie_buf[1] + sizeof(struct ieee_types_header);2227 2228 band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);2229 chan = ieee80211_get_channel(priv->wdev.wiphy,2230 ieee80211_channel_to_frequency(bss_info.bss_chan,2231 band));2232 2233 bss = cfg80211_inform_bss(priv->wdev.wiphy, chan,2234 CFG80211_BSS_FTYPE_UNKNOWN,2235 bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,2236 0, ie_buf, ie_len, 0, GFP_KERNEL);2237 if (bss) {2238 cfg80211_put_bss(priv->wdev.wiphy, bss);2239 ether_addr_copy(priv->cfg_bssid, bss_info.bssid);2240 }2241 2242 return 0;2243}2244 2245/*2246 * This function connects with a BSS.2247 *2248 * This function handles both Infra and Ad-Hoc modes. It also performs2249 * validity checking on the provided parameters, disconnects from the2250 * current BSS (if any), sets up the association/scan parameters,2251 * including security settings, and performs specific SSID scan before2252 * trying to connect.2253 *2254 * For Infra mode, the function returns failure if the specified SSID2255 * is not found in scan table. However, for Ad-Hoc mode, it can create2256 * the IBSS if it does not exist. On successful completion in either case,2257 * the function notifies the CFG802.11 subsystem of the new BSS connection.2258 */2259static int2260mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,2261 const u8 *ssid, const u8 *bssid, int mode,2262 struct ieee80211_channel *channel,2263 struct cfg80211_connect_params *sme, bool privacy,2264 struct cfg80211_bss **sel_bss)2265{2266 struct cfg80211_ssid req_ssid;2267 int ret, auth_type = 0;2268 struct cfg80211_bss *bss = NULL;2269 u8 is_scanning_required = 0;2270 2271 memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));2272 2273 req_ssid.ssid_len = ssid_len;2274 if (ssid_len > IEEE80211_MAX_SSID_LEN) {2275 mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");2276 return -EINVAL;2277 }2278 2279 memcpy(req_ssid.ssid, ssid, ssid_len);2280 if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {2281 mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");2282 return -EINVAL;2283 }2284 2285 /* As this is new association, clear locally stored2286 * keys and security related flags */2287 priv->sec_info.wpa_enabled = false;2288 priv->sec_info.wpa2_enabled = false;2289 priv->wep_key_curr_index = 0;2290 priv->sec_info.encryption_mode = 0;2291 priv->sec_info.is_authtype_auto = 0;2292 ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);2293 2294 if (mode == NL80211_IFTYPE_ADHOC) {2295 u16 enable = true;2296 2297 /* set ibss coalescing_status */2298 ret = mwifiex_send_cmd(2299 priv,2300 HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,2301 HostCmd_ACT_GEN_SET, 0, &enable, true);2302 if (ret)2303 return ret;2304 2305 /* "privacy" is set only for ad-hoc mode */2306 if (privacy) {2307 /*2308 * Keep WLAN_CIPHER_SUITE_WEP104 for now so that2309 * the firmware can find a matching network from the2310 * scan. The cfg80211 does not give us the encryption2311 * mode at this stage so just setting it to WEP here.2312 */2313 priv->sec_info.encryption_mode =2314 WLAN_CIPHER_SUITE_WEP104;2315 priv->sec_info.authentication_mode =2316 NL80211_AUTHTYPE_OPEN_SYSTEM;2317 }2318 2319 goto done;2320 }2321 2322 /* Now handle infra mode. "sme" is valid for infra mode only */2323 if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {2324 auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;2325 priv->sec_info.is_authtype_auto = 1;2326 } else {2327 auth_type = sme->auth_type;2328 }2329 2330 if (sme->crypto.n_ciphers_pairwise) {2331 priv->sec_info.encryption_mode =2332 sme->crypto.ciphers_pairwise[0];2333 priv->sec_info.authentication_mode = auth_type;2334 }2335 2336 if (sme->crypto.cipher_group) {2337 priv->sec_info.encryption_mode = sme->crypto.cipher_group;2338 priv->sec_info.authentication_mode = auth_type;2339 }2340 if (sme->ie)2341 ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);2342 2343 if (sme->key) {2344 if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {2345 mwifiex_dbg(priv->adapter, INFO,2346 "info: setting wep encryption\t"2347 "with key len %d\n", sme->key_len);2348 priv->wep_key_curr_index = sme->key_idx;2349 ret = mwifiex_set_encode(priv, NULL, sme->key,2350 sme->key_len, sme->key_idx,2351 NULL, 0);2352 }2353 }2354done:2355 /*2356 * Scan entries are valid for some time (15 sec). So we can save one2357 * active scan time if we just try cfg80211_get_bss first. If it fails2358 * then request scan and cfg80211_get_bss() again for final output.2359 */2360 while (1) {2361 if (is_scanning_required) {2362 /* Do specific SSID scanning */2363 if (mwifiex_request_scan(priv, &req_ssid)) {2364 mwifiex_dbg(priv->adapter, ERROR, "scan error\n");2365 return -EFAULT;2366 }2367 }2368 2369 /* Find the BSS we want using available scan results */2370 if (mode == NL80211_IFTYPE_ADHOC)2371 bss = cfg80211_get_bss(priv->wdev.wiphy, channel,2372 bssid, ssid, ssid_len,2373 IEEE80211_BSS_TYPE_IBSS,2374 IEEE80211_PRIVACY_ANY);2375 else2376 bss = cfg80211_get_bss(priv->wdev.wiphy, channel,2377 bssid, ssid, ssid_len,2378 IEEE80211_BSS_TYPE_ESS,2379 IEEE80211_PRIVACY_ANY);2380 2381 if (!bss) {2382 if (is_scanning_required) {2383 mwifiex_dbg(priv->adapter, MSG,2384 "assoc: requested bss not found in scan results\n");2385 break;2386 }2387 is_scanning_required = 1;2388 } else {2389 mwifiex_dbg(priv->adapter, MSG,2390 "info: trying to associate to bssid %pM\n",2391 bss->bssid);2392 memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);2393 break;2394 }2395 }2396 2397 if (bss)2398 cfg80211_ref_bss(priv->adapter->wiphy, bss);2399 2400 ret = mwifiex_bss_start(priv, bss, &req_ssid);2401 if (ret)2402 goto cleanup;2403 2404 if (mode == NL80211_IFTYPE_ADHOC) {2405 /* Inform the BSS information to kernel, otherwise2406 * kernel will give a panic after successful assoc */2407 if (mwifiex_cfg80211_inform_ibss_bss(priv)) {2408 ret = -EFAULT;2409 goto cleanup;2410 }2411 }2412 2413 /* Pass the selected BSS entry to caller. */2414 if (sel_bss) {2415 *sel_bss = bss;2416 bss = NULL;2417 }2418 2419cleanup:2420 if (bss)2421 cfg80211_put_bss(priv->adapter->wiphy, bss);2422 return ret;2423}2424 2425/*2426 * CFG802.11 operation handler for association request.2427 *2428 * This function does not work when the current mode is set to Ad-Hoc, or2429 * when there is already an association procedure going on. The given BSS2430 * information is used to associate.2431 */2432static int2433mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,2434 struct cfg80211_connect_params *sme)2435{2436 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2437 struct mwifiex_adapter *adapter = priv->adapter;2438 struct cfg80211_bss *bss = NULL;2439 int ret;2440 2441 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {2442 mwifiex_dbg(adapter, ERROR,2443 "%s: reject infra assoc request in non-STA role\n",2444 dev->name);2445 return -EINVAL;2446 }2447 2448 if (priv->wdev.connected) {2449 mwifiex_dbg(adapter, ERROR,2450 "%s: already connected\n", dev->name);2451 return -EALREADY;2452 }2453 2454 if (priv->scan_block)2455 priv->scan_block = false;2456 2457 if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||2458 test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {2459 mwifiex_dbg(adapter, ERROR,2460 "%s: Ignore connection.\t"2461 "Card removed or FW in bad state\n",2462 dev->name);2463 return -EFAULT;2464 }2465 2466 mwifiex_dbg(adapter, INFO,2467 "info: Trying to associate to bssid %pM\n", sme->bssid);2468 2469 if (!mwifiex_stop_bg_scan(priv))2470 cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);2471 2472 ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,2473 priv->bss_mode, sme->channel, sme, 0,2474 &bss);2475 if (!ret) {2476 cfg80211_connect_bss(priv->netdev, priv->cfg_bssid, bss, NULL,2477 0, NULL, 0, WLAN_STATUS_SUCCESS,2478 GFP_KERNEL, NL80211_TIMEOUT_UNSPECIFIED);2479 mwifiex_dbg(priv->adapter, MSG,2480 "info: associated to bssid %pM successfully\n",2481 priv->cfg_bssid);2482 if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&2483 priv->adapter->auto_tdls &&2484 priv->bss_type == MWIFIEX_BSS_TYPE_STA)2485 mwifiex_setup_auto_tdls_timer(priv);2486 } else {2487 mwifiex_dbg(priv->adapter, ERROR,2488 "info: association to bssid %pM failed\n",2489 priv->cfg_bssid);2490 eth_zero_addr(priv->cfg_bssid);2491 2492 if (ret > 0)2493 cfg80211_connect_result(priv->netdev, priv->cfg_bssid,2494 NULL, 0, NULL, 0, ret,2495 GFP_KERNEL);2496 else2497 cfg80211_connect_result(priv->netdev, priv->cfg_bssid,2498 NULL, 0, NULL, 0,2499 WLAN_STATUS_UNSPECIFIED_FAILURE,2500 GFP_KERNEL);2501 }2502 2503 return 0;2504}2505 2506/*2507 * This function sets following parameters for ibss network.2508 * - channel2509 * - start band2510 * - 11n flag2511 * - secondary channel offset2512 */2513static int mwifiex_set_ibss_params(struct mwifiex_private *priv,2514 struct cfg80211_ibss_params *params)2515{2516 struct mwifiex_adapter *adapter = priv->adapter;2517 int index = 0, i;2518 u8 config_bands = 0;2519 2520 if (params->chandef.chan->band == NL80211_BAND_2GHZ) {2521 if (!params->basic_rates) {2522 config_bands = BAND_B | BAND_G;2523 } else {2524 for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {2525 /*2526 * Rates below 6 Mbps in the table are CCK2527 * rates; 802.11b and from 6 they are OFDM;2528 * 802.11G2529 */2530 if (mwifiex_rates[i].bitrate == 60) {2531 index = 1 << i;2532 break;2533 }2534 }2535 2536 if (params->basic_rates < index) {2537 config_bands = BAND_B;2538 } else {2539 config_bands = BAND_G;2540 if (params->basic_rates % index)2541 config_bands |= BAND_B;2542 }2543 }2544 2545 if (cfg80211_get_chandef_type(¶ms->chandef) !=2546 NL80211_CHAN_NO_HT)2547 config_bands |= BAND_G | BAND_GN;2548 } else {2549 if (cfg80211_get_chandef_type(¶ms->chandef) ==2550 NL80211_CHAN_NO_HT)2551 config_bands = BAND_A;2552 else2553 config_bands = BAND_AN | BAND_A;2554 }2555 2556 if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {2557 adapter->config_bands = config_bands;2558 adapter->adhoc_start_band = config_bands;2559 2560 if ((config_bands & BAND_GN) || (config_bands & BAND_AN))2561 adapter->adhoc_11n_enabled = true;2562 else2563 adapter->adhoc_11n_enabled = false;2564 }2565 2566 adapter->sec_chan_offset =2567 mwifiex_chan_type_to_sec_chan_offset(2568 cfg80211_get_chandef_type(¶ms->chandef));2569 priv->adhoc_channel = ieee80211_frequency_to_channel(2570 params->chandef.chan->center_freq);2571 2572 mwifiex_dbg(adapter, INFO,2573 "info: set ibss band %d, chan %d, chan offset %d\n",2574 config_bands, priv->adhoc_channel,2575 adapter->sec_chan_offset);2576 2577 return 0;2578}2579 2580/*2581 * CFG802.11 operation handler to join an IBSS.2582 *2583 * This function does not work in any mode other than Ad-Hoc, or if2584 * a join operation is already in progress.2585 */2586static int2587mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,2588 struct cfg80211_ibss_params *params)2589{2590 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2591 int ret = 0;2592 2593 if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {2594 mwifiex_dbg(priv->adapter, ERROR,2595 "request to join ibss received\t"2596 "when station is not in ibss mode\n");2597 goto done;2598 }2599 2600 mwifiex_dbg(priv->adapter, MSG, "info: trying to join to bssid %pM\n",2601 params->bssid);2602 2603 mwifiex_set_ibss_params(priv, params);2604 2605 ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,2606 params->bssid, priv->bss_mode,2607 params->chandef.chan, NULL,2608 params->privacy, NULL);2609done:2610 if (!ret) {2611 cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,2612 params->chandef.chan, GFP_KERNEL);2613 mwifiex_dbg(priv->adapter, MSG,2614 "info: joined/created adhoc network with bssid\t"2615 "%pM successfully\n", priv->cfg_bssid);2616 } else {2617 mwifiex_dbg(priv->adapter, ERROR,2618 "info: failed creating/joining adhoc network\n");2619 }2620 2621 return ret;2622}2623 2624/*2625 * CFG802.11 operation handler to leave an IBSS.2626 *2627 * This function does not work if a leave operation is2628 * already in progress.2629 */2630static int2631mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)2632{2633 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2634 2635 mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n",2636 priv->cfg_bssid);2637 if (mwifiex_deauthenticate(priv, NULL))2638 return -EFAULT;2639 2640 eth_zero_addr(priv->cfg_bssid);2641 2642 return 0;2643}2644 2645/*2646 * CFG802.11 operation handler for scan request.2647 *2648 * This function issues a scan request to the firmware based upon2649 * the user specified scan configuration. On successful completion,2650 * it also informs the results.2651 */2652static int2653mwifiex_cfg80211_scan(struct wiphy *wiphy,2654 struct cfg80211_scan_request *request)2655{2656 struct net_device *dev = request->wdev->netdev;2657 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2658 int i, offset, ret;2659 struct ieee80211_channel *chan;2660 struct ieee_types_header *ie;2661 struct mwifiex_user_scan_cfg *user_scan_cfg;2662 u8 mac_addr[ETH_ALEN];2663 2664 mwifiex_dbg(priv->adapter, CMD,2665 "info: received scan request on %s\n", dev->name);2666 2667 /* Block scan request if scan operation or scan cleanup when interface2668 * is disabled is in process2669 */2670 if (priv->scan_request || priv->scan_aborting) {2671 mwifiex_dbg(priv->adapter, WARN,2672 "cmd: Scan already in process..\n");2673 return -EBUSY;2674 }2675 2676 if (!priv->wdev.connected && priv->scan_block)2677 priv->scan_block = false;2678 2679 if (!mwifiex_stop_bg_scan(priv))2680 cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);2681 2682 user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);2683 if (!user_scan_cfg)2684 return -ENOMEM;2685 2686 priv->scan_request = request;2687 2688 if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {2689 get_random_mask_addr(mac_addr, request->mac_addr,2690 request->mac_addr_mask);2691 ether_addr_copy(request->mac_addr, mac_addr);2692 ether_addr_copy(user_scan_cfg->random_mac, mac_addr);2693 }2694 2695 user_scan_cfg->num_ssids = request->n_ssids;2696 user_scan_cfg->ssid_list = request->ssids;2697 2698 if (request->ie && request->ie_len) {2699 offset = 0;2700 for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {2701 if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)2702 continue;2703 priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;2704 ie = (struct ieee_types_header *)(request->ie + offset);2705 memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);2706 offset += sizeof(*ie) + ie->len;2707 2708 if (offset >= request->ie_len)2709 break;2710 }2711 }2712 2713 for (i = 0; i < min_t(u32, request->n_channels,2714 MWIFIEX_USER_SCAN_CHAN_MAX); i++) {2715 chan = request->channels[i];2716 user_scan_cfg->chan_list[i].chan_number = chan->hw_value;2717 user_scan_cfg->chan_list[i].radio_type = chan->band;2718 2719 if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)2720 user_scan_cfg->chan_list[i].scan_type =2721 MWIFIEX_SCAN_TYPE_PASSIVE;2722 else2723 user_scan_cfg->chan_list[i].scan_type =2724 MWIFIEX_SCAN_TYPE_ACTIVE;2725 2726 user_scan_cfg->chan_list[i].scan_time = 0;2727 }2728 2729 if (priv->adapter->scan_chan_gap_enabled &&2730 mwifiex_is_any_intf_active(priv))2731 user_scan_cfg->scan_chan_gap =2732 priv->adapter->scan_chan_gap_time;2733 2734 ret = mwifiex_scan_networks(priv, user_scan_cfg);2735 kfree(user_scan_cfg);2736 if (ret) {2737 mwifiex_dbg(priv->adapter, ERROR,2738 "scan failed: %d\n", ret);2739 priv->scan_aborting = false;2740 priv->scan_request = NULL;2741 return ret;2742 }2743 2744 if (request->ie && request->ie_len) {2745 for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {2746 if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {2747 priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;2748 memset(&priv->vs_ie[i].ie, 0,2749 MWIFIEX_MAX_VSIE_LEN);2750 }2751 }2752 }2753 return 0;2754}2755 2756/* CFG802.11 operation handler for sched_scan_start.2757 *2758 * This function issues a bgscan config request to the firmware based upon2759 * the user specified sched_scan configuration. On successful completion,2760 * firmware will generate BGSCAN_REPORT event, driver should issue bgscan2761 * query command to get sched_scan results from firmware.2762 */2763static int2764mwifiex_cfg80211_sched_scan_start(struct wiphy *wiphy,2765 struct net_device *dev,2766 struct cfg80211_sched_scan_request *request)2767{2768 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2769 int i, offset;2770 struct ieee80211_channel *chan;2771 struct mwifiex_bg_scan_cfg *bgscan_cfg;2772 struct ieee_types_header *ie;2773 2774 if (!request || (!request->n_ssids && !request->n_match_sets)) {2775 wiphy_err(wiphy, "%s : Invalid Sched_scan parameters",2776 __func__);2777 return -EINVAL;2778 }2779 2780 wiphy_info(wiphy, "sched_scan start : n_ssids=%d n_match_sets=%d ",2781 request->n_ssids, request->n_match_sets);2782 wiphy_info(wiphy, "n_channels=%d interval=%d ie_len=%d\n",2783 request->n_channels, request->scan_plans->interval,2784 (int)request->ie_len);2785 2786 bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);2787 if (!bgscan_cfg)2788 return -ENOMEM;2789 2790 if (priv->scan_request || priv->scan_aborting)2791 bgscan_cfg->start_later = true;2792 2793 bgscan_cfg->num_ssids = request->n_match_sets;2794 bgscan_cfg->ssid_list = request->match_sets;2795 2796 if (request->ie && request->ie_len) {2797 offset = 0;2798 for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {2799 if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)2800 continue;2801 priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_BGSCAN;2802 ie = (struct ieee_types_header *)(request->ie + offset);2803 memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);2804 offset += sizeof(*ie) + ie->len;2805 2806 if (offset >= request->ie_len)2807 break;2808 }2809 }2810 2811 for (i = 0; i < min_t(u32, request->n_channels,2812 MWIFIEX_BG_SCAN_CHAN_MAX); i++) {2813 chan = request->channels[i];2814 bgscan_cfg->chan_list[i].chan_number = chan->hw_value;2815 bgscan_cfg->chan_list[i].radio_type = chan->band;2816 2817 if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)2818 bgscan_cfg->chan_list[i].scan_type =2819 MWIFIEX_SCAN_TYPE_PASSIVE;2820 else2821 bgscan_cfg->chan_list[i].scan_type =2822 MWIFIEX_SCAN_TYPE_ACTIVE;2823 2824 bgscan_cfg->chan_list[i].scan_time = 0;2825 }2826 2827 bgscan_cfg->chan_per_scan = min_t(u32, request->n_channels,2828 MWIFIEX_BG_SCAN_CHAN_MAX);2829 2830 /* Use at least 15 second for per scan cycle */2831 bgscan_cfg->scan_interval = (request->scan_plans->interval >2832 MWIFIEX_BGSCAN_INTERVAL) ?2833 request->scan_plans->interval :2834 MWIFIEX_BGSCAN_INTERVAL;2835 2836 bgscan_cfg->repeat_count = MWIFIEX_BGSCAN_REPEAT_COUNT;2837 bgscan_cfg->report_condition = MWIFIEX_BGSCAN_SSID_MATCH |2838 MWIFIEX_BGSCAN_WAIT_ALL_CHAN_DONE;2839 bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;2840 bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;2841 bgscan_cfg->enable = true;2842 if (request->min_rssi_thold != NL80211_SCAN_RSSI_THOLD_OFF) {2843 bgscan_cfg->report_condition |= MWIFIEX_BGSCAN_SSID_RSSI_MATCH;2844 bgscan_cfg->rssi_threshold = request->min_rssi_thold;2845 }2846 2847 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,2848 HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {2849 kfree(bgscan_cfg);2850 return -EFAULT;2851 }2852 2853 priv->sched_scanning = true;2854 2855 kfree(bgscan_cfg);2856 return 0;2857}2858 2859/* CFG802.11 operation handler for sched_scan_stop.2860 *2861 * This function issues a bgscan config command to disable2862 * previous bgscan configuration in the firmware2863 */2864static int mwifiex_cfg80211_sched_scan_stop(struct wiphy *wiphy,2865 struct net_device *dev, u64 reqid)2866{2867 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2868 2869 wiphy_info(wiphy, "sched scan stop!");2870 mwifiex_stop_bg_scan(priv);2871 2872 return 0;2873}2874 2875static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,2876 struct mwifiex_private *priv)2877{2878 struct mwifiex_adapter *adapter = priv->adapter;2879 2880 vht_info->vht_supported = true;2881 2882 vht_info->cap = adapter->hw_dot_11ac_dev_cap;2883 /* Update MCS support for VHT */2884 vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(2885 adapter->hw_dot_11ac_mcs_support & 0xFFFF);2886 vht_info->vht_mcs.rx_highest = 0;2887 vht_info->vht_mcs.tx_mcs_map = cpu_to_le16(2888 adapter->hw_dot_11ac_mcs_support >> 16);2889 vht_info->vht_mcs.tx_highest = 0;2890}2891 2892/*2893 * This function sets up the CFG802.11 specific HT capability fields2894 * with default values.2895 *2896 * The following default values are set -2897 * - HT Supported = True2898 * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K2899 * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE2900 * - HT Capabilities supported by firmware2901 * - MCS information, Rx mask = 0xff2902 * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01)2903 */2904static void2905mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,2906 struct mwifiex_private *priv)2907{2908 int rx_mcs_supp;2909 struct ieee80211_mcs_info mcs_set;2910 u8 *mcs = (u8 *)&mcs_set;2911 struct mwifiex_adapter *adapter = priv->adapter;2912 2913 ht_info->ht_supported = true;2914 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;2915 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;2916 2917 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));2918 2919 /* Fill HT capability information */2920 if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))2921 ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;2922 else2923 ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;2924 2925 if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap))2926 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;2927 else2928 ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20;2929 2930 if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap))2931 ht_info->cap |= IEEE80211_HT_CAP_SGI_40;2932 else2933 ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40;2934 2935 if (adapter->user_dev_mcs_support == HT_STREAM_2X2)2936 ht_info->cap |= 2 << IEEE80211_HT_CAP_RX_STBC_SHIFT;2937 else2938 ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;2939 2940 if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap))2941 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;2942 else2943 ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;2944 2945 if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap))2946 ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;2947 else2948 ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD;2949 2950 if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap))2951 ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;2952 else2953 ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT;2954 2955 if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap))2956 ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;2957 else2958 ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING;2959 2960 ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;2961 ht_info->cap |= IEEE80211_HT_CAP_SM_PS;2962 2963 rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support);2964 /* Set MCS for 1x1/2x2 */2965 memset(mcs, 0xff, rx_mcs_supp);2966 /* Clear all the other values */2967 memset(&mcs[rx_mcs_supp], 0,2968 sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);2969 if (priv->bss_mode == NL80211_IFTYPE_STATION ||2970 ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))2971 /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */2972 SETHT_MCS32(mcs_set.rx_mask);2973 2974 memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info));2975 2976 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;2977}2978 2979/*2980 * create a new virtual interface with the given name and name assign type2981 */2982struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,2983 const char *name,2984 unsigned char name_assign_type,2985 enum nl80211_iftype type,2986 struct vif_params *params)2987{2988 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);2989 struct mwifiex_private *priv;2990 struct net_device *dev;2991 void *mdev_priv;2992 int ret;2993 2994 if (!adapter)2995 return ERR_PTR(-EFAULT);2996 2997 switch (type) {2998 case NL80211_IFTYPE_UNSPECIFIED:2999 case NL80211_IFTYPE_STATION:3000 case NL80211_IFTYPE_ADHOC:3001 if (adapter->curr_iface_comb.sta_intf ==3002 adapter->iface_limit.sta_intf) {3003 mwifiex_dbg(adapter, ERROR,3004 "cannot create multiple sta/adhoc ifaces\n");3005 return ERR_PTR(-EINVAL);3006 }3007 3008 priv = mwifiex_get_unused_priv_by_bss_type(3009 adapter, MWIFIEX_BSS_TYPE_STA);3010 if (!priv) {3011 mwifiex_dbg(adapter, ERROR,3012 "could not get free private struct\n");3013 return ERR_PTR(-EFAULT);3014 }3015 3016 priv->wdev.wiphy = wiphy;3017 priv->wdev.iftype = NL80211_IFTYPE_STATION;3018 3019 if (type == NL80211_IFTYPE_UNSPECIFIED)3020 priv->bss_mode = NL80211_IFTYPE_STATION;3021 else3022 priv->bss_mode = type;3023 3024 priv->bss_type = MWIFIEX_BSS_TYPE_STA;3025 priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;3026 priv->bss_priority = 0;3027 priv->bss_role = MWIFIEX_BSS_ROLE_STA;3028 3029 break;3030 case NL80211_IFTYPE_AP:3031 if (adapter->curr_iface_comb.uap_intf ==3032 adapter->iface_limit.uap_intf) {3033 mwifiex_dbg(adapter, ERROR,3034 "cannot create multiple AP ifaces\n");3035 return ERR_PTR(-EINVAL);3036 }3037 3038 priv = mwifiex_get_unused_priv_by_bss_type(3039 adapter, MWIFIEX_BSS_TYPE_UAP);3040 if (!priv) {3041 mwifiex_dbg(adapter, ERROR,3042 "could not get free private struct\n");3043 return ERR_PTR(-EFAULT);3044 }3045 3046 priv->wdev.wiphy = wiphy;3047 priv->wdev.iftype = NL80211_IFTYPE_AP;3048 3049 priv->bss_type = MWIFIEX_BSS_TYPE_UAP;3050 priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;3051 priv->bss_priority = 0;3052 priv->bss_role = MWIFIEX_BSS_ROLE_UAP;3053 priv->bss_started = 0;3054 priv->bss_mode = type;3055 3056 break;3057 case NL80211_IFTYPE_P2P_CLIENT:3058 if (adapter->curr_iface_comb.p2p_intf ==3059 adapter->iface_limit.p2p_intf) {3060 mwifiex_dbg(adapter, ERROR,3061 "cannot create multiple P2P ifaces\n");3062 return ERR_PTR(-EINVAL);3063 }3064 3065 priv = mwifiex_get_unused_priv_by_bss_type(3066 adapter, MWIFIEX_BSS_TYPE_P2P);3067 if (!priv) {3068 mwifiex_dbg(adapter, ERROR,3069 "could not get free private struct\n");3070 return ERR_PTR(-EFAULT);3071 }3072 3073 priv->wdev.wiphy = wiphy;3074 /* At start-up, wpa_supplicant tries to change the interface3075 * to NL80211_IFTYPE_STATION if it is not managed mode.3076 */3077 priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;3078 priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;3079 3080 /* Setting bss_type to P2P tells firmware that this interface3081 * is receiving P2P peers found during find phase and doing3082 * action frame handshake.3083 */3084 priv->bss_type = MWIFIEX_BSS_TYPE_P2P;3085 3086 priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;3087 priv->bss_priority = 0;3088 priv->bss_role = MWIFIEX_BSS_ROLE_STA;3089 priv->bss_started = 0;3090 3091 if (mwifiex_cfg80211_init_p2p_client(priv)) {3092 memset(&priv->wdev, 0, sizeof(priv->wdev));3093 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;3094 return ERR_PTR(-EFAULT);3095 }3096 3097 break;3098 default:3099 mwifiex_dbg(adapter, ERROR, "type not supported\n");3100 return ERR_PTR(-EINVAL);3101 }3102 3103 dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,3104 name_assign_type, ether_setup,3105 IEEE80211_NUM_ACS, 1);3106 if (!dev) {3107 mwifiex_dbg(adapter, ERROR,3108 "no memory available for netdevice\n");3109 ret = -ENOMEM;3110 goto err_alloc_netdev;3111 }3112 3113 mwifiex_init_priv_params(priv, dev);3114 3115 priv->netdev = dev;3116 3117 if (!adapter->mfg_mode) {3118 mwifiex_set_mac_address(priv, dev, false, NULL);3119 3120 ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,3121 HostCmd_ACT_GEN_SET, 0, NULL, true);3122 if (ret)3123 goto err_set_bss_mode;3124 3125 ret = mwifiex_sta_init_cmd(priv, false, false);3126 if (ret)3127 goto err_sta_init;3128 }3129 3130 mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv);3131 if (adapter->is_hw_11ac_capable)3132 mwifiex_setup_vht_caps(3133 &wiphy->bands[NL80211_BAND_2GHZ]->vht_cap, priv);3134 3135 if (adapter->config_bands & BAND_A)3136 mwifiex_setup_ht_caps(3137 &wiphy->bands[NL80211_BAND_5GHZ]->ht_cap, priv);3138 3139 if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable)3140 mwifiex_setup_vht_caps(3141 &wiphy->bands[NL80211_BAND_5GHZ]->vht_cap, priv);3142 3143 dev_net_set(dev, wiphy_net(wiphy));3144 dev->ieee80211_ptr = &priv->wdev;3145 dev->ieee80211_ptr->iftype = priv->bss_mode;3146 SET_NETDEV_DEV(dev, wiphy_dev(wiphy));3147 3148 dev->flags |= IFF_BROADCAST | IFF_MULTICAST;3149 dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;3150 dev->needed_headroom = MWIFIEX_MIN_DATA_HEADER_LEN;3151 dev->ethtool_ops = &mwifiex_ethtool_ops;3152 3153 mdev_priv = netdev_priv(dev);3154 *((unsigned long *) mdev_priv) = (unsigned long) priv;3155 3156 SET_NETDEV_DEV(dev, adapter->dev);3157 3158 priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",3159 WQ_HIGHPRI |3160 WQ_MEM_RECLAIM |3161 WQ_UNBOUND, 0, name);3162 if (!priv->dfs_cac_workqueue) {3163 mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");3164 ret = -ENOMEM;3165 goto err_alloc_cac;3166 }3167 3168 INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);3169 3170 priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",3171 WQ_HIGHPRI | WQ_UNBOUND |3172 WQ_MEM_RECLAIM, 0, name);3173 if (!priv->dfs_chan_sw_workqueue) {3174 mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n");3175 ret = -ENOMEM;3176 goto err_alloc_chsw;3177 }3178 3179 INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,3180 mwifiex_dfs_chan_sw_work_queue);3181 3182 mutex_init(&priv->async_mutex);3183 3184 /* Register network device */3185 if (cfg80211_register_netdevice(dev)) {3186 mwifiex_dbg(adapter, ERROR, "cannot register network device\n");3187 ret = -EFAULT;3188 goto err_reg_netdev;3189 }3190 3191 mwifiex_dbg(adapter, INFO,3192 "info: %s: Marvell 802.11 Adapter\n", dev->name);3193 3194#ifdef CONFIG_DEBUG_FS3195 mwifiex_dev_debugfs_init(priv);3196#endif3197 3198 update_vif_type_counter(adapter, type, +1);3199 3200 return &priv->wdev;3201 3202err_reg_netdev:3203 destroy_workqueue(priv->dfs_chan_sw_workqueue);3204 priv->dfs_chan_sw_workqueue = NULL;3205err_alloc_chsw:3206 destroy_workqueue(priv->dfs_cac_workqueue);3207 priv->dfs_cac_workqueue = NULL;3208err_alloc_cac:3209 free_netdev(dev);3210 priv->netdev = NULL;3211err_sta_init:3212err_set_bss_mode:3213err_alloc_netdev:3214 memset(&priv->wdev, 0, sizeof(priv->wdev));3215 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;3216 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;3217 return ERR_PTR(ret);3218}3219EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);3220 3221/*3222 * del_virtual_intf: remove the virtual interface determined by dev3223 */3224int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)3225{3226 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);3227 struct mwifiex_adapter *adapter = priv->adapter;3228 struct sk_buff *skb, *tmp;3229 3230#ifdef CONFIG_DEBUG_FS3231 mwifiex_dev_debugfs_remove(priv);3232#endif3233 3234 if (priv->sched_scanning)3235 priv->sched_scanning = false;3236 3237 mwifiex_stop_net_dev_queue(priv->netdev, adapter);3238 3239 skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) {3240 skb_unlink(skb, &priv->bypass_txq);3241 mwifiex_write_data_complete(priv->adapter, skb, 0, -1);3242 }3243 3244 if (netif_carrier_ok(priv->netdev))3245 netif_carrier_off(priv->netdev);3246 3247 if (wdev->netdev->reg_state == NETREG_REGISTERED)3248 cfg80211_unregister_netdevice(wdev->netdev);3249 3250 if (priv->dfs_cac_workqueue) {3251 destroy_workqueue(priv->dfs_cac_workqueue);3252 priv->dfs_cac_workqueue = NULL;3253 }3254 3255 if (priv->dfs_chan_sw_workqueue) {3256 destroy_workqueue(priv->dfs_chan_sw_workqueue);3257 priv->dfs_chan_sw_workqueue = NULL;3258 }3259 /* Clear the priv in adapter */3260 priv->netdev = NULL;3261 3262 update_vif_type_counter(adapter, priv->bss_mode, -1);3263 3264 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;3265 3266 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||3267 GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)3268 kfree(priv->hist_data);3269 3270 return 0;3271}3272EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);3273 3274static bool3275mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq,3276 u8 max_byte_seq)3277{3278 int j, k, valid_byte_cnt = 0;3279 bool dont_care_byte = false;3280 3281 for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {3282 for (k = 0; k < 8; k++) {3283 if (pat->mask[j] & 1 << k) {3284 memcpy(byte_seq + valid_byte_cnt,3285 &pat->pattern[j * 8 + k], 1);3286 valid_byte_cnt++;3287 if (dont_care_byte)3288 return false;3289 } else {3290 if (valid_byte_cnt)3291 dont_care_byte = true;3292 }3293 3294 /* wildcard bytes record as the offset3295 * before the valid byte3296 */3297 if (!valid_byte_cnt && !dont_care_byte)3298 pat->pkt_offset++;3299 3300 if (valid_byte_cnt > max_byte_seq)3301 return false;3302 }3303 }3304 3305 byte_seq[max_byte_seq] = valid_byte_cnt;3306 3307 return true;3308}3309 3310#ifdef CONFIG_PM3311static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv,3312 struct mwifiex_mef_entry *mef_entry)3313{3314 int i, filt_num = 0, num_ipv4 = 0;3315 struct in_device *in_dev;3316 struct in_ifaddr *ifa;3317 __be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR];3318 struct mwifiex_adapter *adapter = priv->adapter;3319 3320 mef_entry->mode = MEF_MODE_HOST_SLEEP;3321 mef_entry->action = MEF_ACTION_AUTO_ARP;3322 3323 /* Enable ARP offload feature */3324 memset(ips, 0, sizeof(ips));3325 for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {3326 if (adapter->priv[i]->netdev) {3327 in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev);3328 if (!in_dev)3329 continue;3330 ifa = rtnl_dereference(in_dev->ifa_list);3331 if (!ifa || !ifa->ifa_local)3332 continue;3333 ips[i] = ifa->ifa_local;3334 num_ipv4++;3335 }3336 }3337 3338 for (i = 0; i < num_ipv4; i++) {3339 if (!ips[i])3340 continue;3341 mef_entry->filter[filt_num].repeat = 1;3342 memcpy(mef_entry->filter[filt_num].byte_seq,3343 (u8 *)&ips[i], sizeof(ips[i]));3344 mef_entry->filter[filt_num].3345 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =3346 sizeof(ips[i]);3347 mef_entry->filter[filt_num].offset = 46;3348 mef_entry->filter[filt_num].filt_type = TYPE_EQ;3349 if (filt_num) {3350 mef_entry->filter[filt_num].filt_action =3351 TYPE_OR;3352 }3353 filt_num++;3354 }3355 3356 mef_entry->filter[filt_num].repeat = 1;3357 mef_entry->filter[filt_num].byte_seq[0] = 0x08;3358 mef_entry->filter[filt_num].byte_seq[1] = 0x06;3359 mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2;3360 mef_entry->filter[filt_num].offset = 20;3361 mef_entry->filter[filt_num].filt_type = TYPE_EQ;3362 mef_entry->filter[filt_num].filt_action = TYPE_AND;3363}3364 3365static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,3366 struct mwifiex_ds_mef_cfg *mef_cfg,3367 struct mwifiex_mef_entry *mef_entry,3368 struct cfg80211_wowlan *wowlan)3369{3370 int i, filt_num = 0, ret = 0;3371 bool first_pat = true;3372 u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];3373 static const u8 ipv4_mc_mac[] = {0x33, 0x33};3374 static const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};3375 3376 mef_entry->mode = MEF_MODE_HOST_SLEEP;3377 mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;3378 3379 for (i = 0; i < wowlan->n_patterns; i++) {3380 memset(byte_seq, 0, sizeof(byte_seq));3381 if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],3382 byte_seq,3383 MWIFIEX_MEF_MAX_BYTESEQ)) {3384 mwifiex_dbg(priv->adapter, ERROR,3385 "Pattern not supported\n");3386 return -EOPNOTSUPP;3387 }3388 3389 if (!wowlan->patterns[i].pkt_offset) {3390 if (is_unicast_ether_addr(byte_seq) &&3391 (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) {3392 mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;3393 continue;3394 } else if (is_broadcast_ether_addr(byte_seq)) {3395 mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST;3396 continue;3397 } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&3398 (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) ||3399 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&3400 (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) {3401 mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST;3402 continue;3403 }3404 }3405 mef_entry->filter[filt_num].repeat = 1;3406 mef_entry->filter[filt_num].offset =3407 wowlan->patterns[i].pkt_offset;3408 memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,3409 sizeof(byte_seq));3410 mef_entry->filter[filt_num].filt_type = TYPE_EQ;3411 3412 if (first_pat) {3413 first_pat = false;3414 mwifiex_dbg(priv->adapter, INFO, "Wake on patterns\n");3415 } else {3416 mef_entry->filter[filt_num].filt_action = TYPE_AND;3417 }3418 3419 filt_num++;3420 }3421 3422 if (wowlan->magic_pkt) {3423 mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;3424 mef_entry->filter[filt_num].repeat = 16;3425 memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,3426 ETH_ALEN);3427 mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =3428 ETH_ALEN;3429 mef_entry->filter[filt_num].offset = 28;3430 mef_entry->filter[filt_num].filt_type = TYPE_EQ;3431 if (filt_num)3432 mef_entry->filter[filt_num].filt_action = TYPE_OR;3433 3434 filt_num++;3435 mef_entry->filter[filt_num].repeat = 16;3436 memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,3437 ETH_ALEN);3438 mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =3439 ETH_ALEN;3440 mef_entry->filter[filt_num].offset = 56;3441 mef_entry->filter[filt_num].filt_type = TYPE_EQ;3442 mef_entry->filter[filt_num].filt_action = TYPE_OR;3443 mwifiex_dbg(priv->adapter, INFO, "Wake on magic packet\n");3444 }3445 return ret;3446}3447 3448static int mwifiex_set_mef_filter(struct mwifiex_private *priv,3449 struct cfg80211_wowlan *wowlan)3450{3451 int ret = 0, num_entries = 1;3452 struct mwifiex_ds_mef_cfg mef_cfg;3453 struct mwifiex_mef_entry *mef_entry;3454 3455 if (wowlan->n_patterns || wowlan->magic_pkt)3456 num_entries++;3457 3458 mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL);3459 if (!mef_entry)3460 return -ENOMEM;3461 3462 memset(&mef_cfg, 0, sizeof(mef_cfg));3463 mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST |3464 MWIFIEX_CRITERIA_UNICAST;3465 mef_cfg.num_entries = num_entries;3466 mef_cfg.mef_entry = mef_entry;3467 3468 mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]);3469 3470 if (wowlan->n_patterns || wowlan->magic_pkt) {3471 ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg,3472 &mef_entry[1], wowlan);3473 if (ret)3474 goto err;3475 }3476 3477 if (!mef_cfg.criteria)3478 mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |3479 MWIFIEX_CRITERIA_UNICAST |3480 MWIFIEX_CRITERIA_MULTICAST;3481 3482 ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG,3483 HostCmd_ACT_GEN_SET, 0,3484 &mef_cfg, true);3485 3486err:3487 kfree(mef_entry);3488 return ret;3489}3490 3491static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,3492 struct cfg80211_wowlan *wowlan)3493{3494 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);3495 struct mwifiex_ds_hs_cfg hs_cfg;3496 int i, ret = 0, retry_num = 10;3497 struct mwifiex_private *priv;3498 struct mwifiex_private *sta_priv =3499 mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);3500 3501 sta_priv->scan_aborting = true;3502 for (i = 0; i < adapter->priv_num; i++) {3503 priv = adapter->priv[i];3504 mwifiex_abort_cac(priv);3505 }3506 3507 mwifiex_cancel_all_pending_cmd(adapter);3508 3509 for (i = 0; i < adapter->priv_num; i++) {3510 priv = adapter->priv[i];3511 if (priv->netdev)3512 netif_device_detach(priv->netdev);3513 }3514 3515 for (i = 0; i < retry_num; i++) {3516 if (!mwifiex_wmm_lists_empty(adapter) ||3517 !mwifiex_bypass_txlist_empty(adapter) ||3518 !skb_queue_empty(&adapter->tx_data_q))3519 usleep_range(10000, 15000);3520 else3521 break;3522 }3523 3524 if (!wowlan) {3525 mwifiex_dbg(adapter, INFO,3526 "None of the WOWLAN triggers enabled\n");3527 ret = 0;3528 goto done;3529 }3530 3531 if (!sta_priv->media_connected && !wowlan->nd_config) {3532 mwifiex_dbg(adapter, ERROR,3533 "Can not configure WOWLAN in disconnected state\n");3534 ret = 0;3535 goto done;3536 }3537 3538 ret = mwifiex_set_mef_filter(sta_priv, wowlan);3539 if (ret) {3540 mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n");3541 goto done;3542 }3543 3544 memset(&hs_cfg, 0, sizeof(hs_cfg));3545 hs_cfg.conditions = le32_to_cpu(adapter->hs_cfg.conditions);3546 3547 if (wowlan->nd_config) {3548 mwifiex_dbg(adapter, INFO, "Wake on net detect\n");3549 hs_cfg.conditions |= HS_CFG_COND_MAC_EVENT;3550 mwifiex_cfg80211_sched_scan_start(wiphy, sta_priv->netdev,3551 wowlan->nd_config);3552 }3553 3554 if (wowlan->disconnect) {3555 hs_cfg.conditions |= HS_CFG_COND_MAC_EVENT;3556 mwifiex_dbg(sta_priv->adapter, INFO, "Wake on device disconnect\n");3557 }3558 3559 hs_cfg.is_invoke_hostcmd = false;3560 hs_cfg.gpio = adapter->hs_cfg.gpio;3561 hs_cfg.gap = adapter->hs_cfg.gap;3562 ret = mwifiex_set_hs_params(sta_priv, HostCmd_ACT_GEN_SET,3563 MWIFIEX_SYNC_CMD, &hs_cfg);3564 if (ret)3565 mwifiex_dbg(adapter, ERROR, "Failed to set HS params\n");3566 3567done:3568 sta_priv->scan_aborting = false;3569 return ret;3570}3571 3572static int mwifiex_cfg80211_resume(struct wiphy *wiphy)3573{3574 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);3575 struct mwifiex_private *priv;3576 struct mwifiex_ds_wakeup_reason wakeup_reason;3577 struct cfg80211_wowlan_wakeup wakeup_report;3578 int i;3579 bool report_wakeup_reason = true;3580 3581 for (i = 0; i < adapter->priv_num; i++) {3582 priv = adapter->priv[i];3583 if (priv->netdev)3584 netif_device_attach(priv->netdev);3585 }3586 3587 if (!wiphy->wowlan_config)3588 goto done;3589 3590 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);3591 mwifiex_get_wakeup_reason(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD,3592 &wakeup_reason);3593 memset(&wakeup_report, 0, sizeof(struct cfg80211_wowlan_wakeup));3594 3595 wakeup_report.pattern_idx = -1;3596 3597 switch (wakeup_reason.hs_wakeup_reason) {3598 case NO_HSWAKEUP_REASON:3599 break;3600 case BCAST_DATA_MATCHED:3601 break;3602 case MCAST_DATA_MATCHED:3603 break;3604 case UCAST_DATA_MATCHED:3605 break;3606 case MASKTABLE_EVENT_MATCHED:3607 break;3608 case NON_MASKABLE_EVENT_MATCHED:3609 if (wiphy->wowlan_config->disconnect)3610 wakeup_report.disconnect = true;3611 if (wiphy->wowlan_config->nd_config)3612 wakeup_report.net_detect = adapter->nd_info;3613 break;3614 case NON_MASKABLE_CONDITION_MATCHED:3615 break;3616 case MAGIC_PATTERN_MATCHED:3617 if (wiphy->wowlan_config->magic_pkt)3618 wakeup_report.magic_pkt = true;3619 if (wiphy->wowlan_config->n_patterns)3620 wakeup_report.pattern_idx = 1;3621 break;3622 case GTK_REKEY_FAILURE:3623 if (wiphy->wowlan_config->gtk_rekey_failure)3624 wakeup_report.gtk_rekey_failure = true;3625 break;3626 default:3627 report_wakeup_reason = false;3628 break;3629 }3630 3631 if (report_wakeup_reason)3632 cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report,3633 GFP_KERNEL);3634 3635done:3636 if (adapter->nd_info) {3637 for (i = 0 ; i < adapter->nd_info->n_matches ; i++)3638 kfree(adapter->nd_info->matches[i]);3639 kfree(adapter->nd_info);3640 adapter->nd_info = NULL;3641 }3642 3643 return 0;3644}3645 3646static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,3647 bool enabled)3648{3649 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);3650 3651 device_set_wakeup_enable(adapter->dev, enabled);3652}3653 3654static int mwifiex_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,3655 struct cfg80211_gtk_rekey_data *data)3656{3657 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3658 3659 if (!ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info))3660 return -EOPNOTSUPP;3661 3662 if (priv->adapter->host_mlme_enabled)3663 return 0;3664 3665 return mwifiex_send_cmd(priv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,3666 HostCmd_ACT_GEN_SET, 0, data, true);3667}3668 3669#endif3670 3671static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq)3672{3673 static const u8 ipv4_mc_mac[] = {0x33, 0x33};3674 static const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};3675 static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};3676 3677 if ((byte_seq[0] & 0x01) &&3678 (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1))3679 return PACKET_TYPE_UNICAST;3680 else if (!memcmp(byte_seq, bc_mac, 4))3681 return PACKET_TYPE_BROADCAST;3682 else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&3683 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) ||3684 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&3685 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3))3686 return PACKET_TYPE_MULTICAST;3687 3688 return 0;3689}3690 3691static int3692mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,3693 struct cfg80211_coalesce_rules *crule,3694 struct mwifiex_coalesce_rule *mrule)3695{3696 u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1];3697 struct filt_field_param *param;3698 int i;3699 3700 mrule->max_coalescing_delay = crule->delay;3701 3702 param = mrule->params;3703 3704 for (i = 0; i < crule->n_patterns; i++) {3705 memset(byte_seq, 0, sizeof(byte_seq));3706 if (!mwifiex_is_pattern_supported(&crule->patterns[i],3707 byte_seq,3708 MWIFIEX_COALESCE_MAX_BYTESEQ)) {3709 mwifiex_dbg(priv->adapter, ERROR,3710 "Pattern not supported\n");3711 return -EOPNOTSUPP;3712 }3713 3714 if (!crule->patterns[i].pkt_offset) {3715 u8 pkt_type;3716 3717 pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq);3718 if (pkt_type && mrule->pkt_type) {3719 mwifiex_dbg(priv->adapter, ERROR,3720 "Multiple packet types not allowed\n");3721 return -EOPNOTSUPP;3722 } else if (pkt_type) {3723 mrule->pkt_type = pkt_type;3724 continue;3725 }3726 }3727 3728 if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)3729 param->operation = RECV_FILTER_MATCH_TYPE_EQ;3730 else3731 param->operation = RECV_FILTER_MATCH_TYPE_NE;3732 3733 param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ];3734 memcpy(param->operand_byte_stream, byte_seq,3735 param->operand_len);3736 param->offset = crule->patterns[i].pkt_offset;3737 param++;3738 3739 mrule->num_of_fields++;3740 }3741 3742 if (!mrule->pkt_type) {3743 mwifiex_dbg(priv->adapter, ERROR,3744 "Packet type can not be determined\n");3745 return -EOPNOTSUPP;3746 }3747 3748 return 0;3749}3750 3751static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,3752 struct cfg80211_coalesce *coalesce)3753{3754 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);3755 int i, ret;3756 struct mwifiex_ds_coalesce_cfg coalesce_cfg;3757 struct mwifiex_private *priv =3758 mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);3759 3760 memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));3761 if (!coalesce) {3762 mwifiex_dbg(adapter, WARN,3763 "Disable coalesce and reset all previous rules\n");3764 return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,3765 HostCmd_ACT_GEN_SET, 0,3766 &coalesce_cfg, true);3767 }3768 3769 coalesce_cfg.num_of_rules = coalesce->n_rules;3770 for (i = 0; i < coalesce->n_rules; i++) {3771 ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i],3772 &coalesce_cfg.rule[i]);3773 if (ret) {3774 mwifiex_dbg(adapter, ERROR,3775 "Recheck the patterns provided for rule %d\n",3776 i + 1);3777 return ret;3778 }3779 }3780 3781 return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,3782 HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true);3783}3784 3785/* cfg80211 ops handler for tdls_mgmt.3786 * Function prepares TDLS action frame packets and forwards them to FW3787 */3788static int3789mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,3790 const u8 *peer, int link_id, u8 action_code,3791 u8 dialog_token, u16 status_code,3792 u32 peer_capability, bool initiator,3793 const u8 *extra_ies, size_t extra_ies_len)3794{3795 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3796 int ret;3797 3798 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))3799 return -EOPNOTSUPP;3800 3801 /* make sure we are in station mode and connected */3802 if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))3803 return -EOPNOTSUPP;3804 3805 switch (action_code) {3806 case WLAN_TDLS_SETUP_REQUEST:3807 mwifiex_dbg(priv->adapter, MSG,3808 "Send TDLS Setup Request to %pM status_code=%d\n",3809 peer, status_code);3810 mwifiex_add_auto_tdls_peer(priv, peer);3811 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3812 dialog_token, status_code,3813 extra_ies, extra_ies_len);3814 break;3815 case WLAN_TDLS_SETUP_RESPONSE:3816 mwifiex_add_auto_tdls_peer(priv, peer);3817 mwifiex_dbg(priv->adapter, MSG,3818 "Send TDLS Setup Response to %pM status_code=%d\n",3819 peer, status_code);3820 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3821 dialog_token, status_code,3822 extra_ies, extra_ies_len);3823 break;3824 case WLAN_TDLS_SETUP_CONFIRM:3825 mwifiex_dbg(priv->adapter, MSG,3826 "Send TDLS Confirm to %pM status_code=%d\n", peer,3827 status_code);3828 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3829 dialog_token, status_code,3830 extra_ies, extra_ies_len);3831 break;3832 case WLAN_TDLS_TEARDOWN:3833 mwifiex_dbg(priv->adapter, MSG,3834 "Send TDLS Tear down to %pM\n", peer);3835 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3836 dialog_token, status_code,3837 extra_ies, extra_ies_len);3838 break;3839 case WLAN_TDLS_DISCOVERY_REQUEST:3840 mwifiex_dbg(priv->adapter, MSG,3841 "Send TDLS Discovery Request to %pM\n", peer);3842 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3843 dialog_token, status_code,3844 extra_ies, extra_ies_len);3845 break;3846 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:3847 mwifiex_dbg(priv->adapter, MSG,3848 "Send TDLS Discovery Response to %pM\n", peer);3849 ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,3850 dialog_token, status_code,3851 extra_ies, extra_ies_len);3852 break;3853 default:3854 mwifiex_dbg(priv->adapter, ERROR,3855 "Unknown TDLS mgmt/action frame %pM\n", peer);3856 ret = -EINVAL;3857 break;3858 }3859 3860 return ret;3861}3862 3863static int3864mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,3865 const u8 *peer, enum nl80211_tdls_operation action)3866{3867 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3868 3869 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) ||3870 !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))3871 return -EOPNOTSUPP;3872 3873 /* make sure we are in station mode and connected */3874 if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))3875 return -EOPNOTSUPP;3876 3877 mwifiex_dbg(priv->adapter, MSG,3878 "TDLS peer=%pM, oper=%d\n", peer, action);3879 3880 switch (action) {3881 case NL80211_TDLS_ENABLE_LINK:3882 action = MWIFIEX_TDLS_ENABLE_LINK;3883 break;3884 case NL80211_TDLS_DISABLE_LINK:3885 action = MWIFIEX_TDLS_DISABLE_LINK;3886 break;3887 case NL80211_TDLS_TEARDOWN:3888 /* shouldn't happen!*/3889 mwifiex_dbg(priv->adapter, ERROR,3890 "tdls_oper: teardown from driver not supported\n");3891 return -EINVAL;3892 case NL80211_TDLS_SETUP:3893 /* shouldn't happen!*/3894 mwifiex_dbg(priv->adapter, ERROR,3895 "tdls_oper: setup from driver not supported\n");3896 return -EINVAL;3897 case NL80211_TDLS_DISCOVERY_REQ:3898 /* shouldn't happen!*/3899 mwifiex_dbg(priv->adapter, ERROR,3900 "tdls_oper: discovery from driver not supported\n");3901 return -EINVAL;3902 default:3903 mwifiex_dbg(priv->adapter, ERROR,3904 "tdls_oper: operation not supported\n");3905 return -EOPNOTSUPP;3906 }3907 3908 return mwifiex_tdls_oper(priv, peer, action);3909}3910 3911static int3912mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,3913 const u8 *addr, u8 oper_class,3914 struct cfg80211_chan_def *chandef)3915{3916 struct mwifiex_sta_node *sta_ptr;3917 u16 chan;3918 u8 second_chan_offset, band;3919 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3920 3921 spin_lock_bh(&priv->sta_list_spinlock);3922 sta_ptr = mwifiex_get_sta_entry(priv, addr);3923 if (!sta_ptr) {3924 spin_unlock_bh(&priv->sta_list_spinlock);3925 wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",3926 __func__, addr);3927 return -ENOENT;3928 }3929 3930 if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &3931 WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {3932 spin_unlock_bh(&priv->sta_list_spinlock);3933 wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);3934 return -ENOENT;3935 }3936 3937 if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||3938 sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {3939 spin_unlock_bh(&priv->sta_list_spinlock);3940 wiphy_err(wiphy, "channel switch is running, abort request\n");3941 return -EALREADY;3942 }3943 spin_unlock_bh(&priv->sta_list_spinlock);3944 3945 chan = chandef->chan->hw_value;3946 second_chan_offset = mwifiex_get_sec_chan_offset(chan);3947 band = chandef->chan->band;3948 mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band);3949 3950 return 0;3951}3952 3953static void3954mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,3955 struct net_device *dev,3956 const u8 *addr)3957{3958 struct mwifiex_sta_node *sta_ptr;3959 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3960 3961 spin_lock_bh(&priv->sta_list_spinlock);3962 sta_ptr = mwifiex_get_sta_entry(priv, addr);3963 if (!sta_ptr) {3964 spin_unlock_bh(&priv->sta_list_spinlock);3965 wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",3966 __func__, addr);3967 } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||3968 sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||3969 sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {3970 spin_unlock_bh(&priv->sta_list_spinlock);3971 wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",3972 addr);3973 } else {3974 spin_unlock_bh(&priv->sta_list_spinlock);3975 mwifiex_stop_tdls_cs(priv, addr);3976 }3977}3978 3979static int3980mwifiex_cfg80211_uap_add_station(struct mwifiex_private *priv, const u8 *mac,3981 struct station_parameters *params)3982{3983 struct mwifiex_sta_info add_sta;3984 int ret;3985 3986 memcpy(add_sta.peer_mac, mac, ETH_ALEN);3987 add_sta.params = params;3988 3989 ret = mwifiex_send_cmd(priv, HostCmd_CMD_ADD_NEW_STATION,3990 HostCmd_ACT_ADD_STA, 0, (void *)&add_sta, true);3991 3992 if (!ret) {3993 struct station_info *sinfo;3994 3995 sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);3996 if (!sinfo)3997 return -ENOMEM;3998 3999 cfg80211_new_sta(priv->netdev, mac, sinfo, GFP_KERNEL);4000 kfree(sinfo);4001 }4002 4003 return ret;4004}4005 4006static int4007mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,4008 const u8 *mac, struct station_parameters *params)4009{4010 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4011 4012 if (priv->adapter->host_mlme_enabled &&4013 (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP))4014 return mwifiex_cfg80211_uap_add_station(priv, mac, params);4015 4016 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))4017 return -EOPNOTSUPP;4018 4019 /* make sure we are in station mode and connected */4020 if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)4021 return -EOPNOTSUPP;4022 4023 return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);4024}4025 4026static int4027mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,4028 struct cfg80211_csa_settings *params)4029{4030 struct ieee_types_header *chsw_ie;4031 struct ieee80211_channel_sw_ie *channel_sw;4032 int chsw_msec;4033 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4034 4035 if (priv->adapter->scan_processing) {4036 mwifiex_dbg(priv->adapter, ERROR,4037 "radar detection: scan in process...\n");4038 return -EBUSY;4039 }4040 4041 if (priv->wdev.links[0].cac_started)4042 return -EBUSY;4043 4044 if (cfg80211_chandef_identical(¶ms->chandef,4045 &priv->dfs_chandef))4046 return -EINVAL;4047 4048 chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,4049 params->beacon_csa.tail,4050 params->beacon_csa.tail_len);4051 if (!chsw_ie) {4052 mwifiex_dbg(priv->adapter, ERROR,4053 "Could not parse channel switch announcement IE\n");4054 return -EINVAL;4055 }4056 4057 channel_sw = (void *)(chsw_ie + 1);4058 if (channel_sw->mode) {4059 if (netif_carrier_ok(priv->netdev))4060 netif_carrier_off(priv->netdev);4061 mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);4062 }4063 4064 if (mwifiex_del_mgmt_ies(priv))4065 mwifiex_dbg(priv->adapter, ERROR,4066 "Failed to delete mgmt IEs!\n");4067 4068 if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon_csa)) {4069 mwifiex_dbg(priv->adapter, ERROR,4070 "%s: setting mgmt ies failed\n", __func__);4071 return -EFAULT;4072 }4073 4074 memcpy(&priv->dfs_chandef, ¶ms->chandef, sizeof(priv->dfs_chandef));4075 memcpy(&priv->beacon_after, ¶ms->beacon_after,4076 sizeof(priv->beacon_after));4077 4078 chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100);4079 queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work,4080 msecs_to_jiffies(chsw_msec));4081 return 0;4082}4083 4084static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,4085 struct wireless_dev *wdev,4086 unsigned int link_id,4087 struct cfg80211_chan_def *chandef)4088{4089 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);4090 struct mwifiex_bssdescriptor *curr_bss;4091 struct ieee80211_channel *chan;4092 enum nl80211_channel_type chan_type;4093 enum nl80211_band band;4094 int freq;4095 int ret = -ENODATA;4096 4097 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&4098 cfg80211_chandef_valid(&priv->bss_chandef)) {4099 *chandef = priv->bss_chandef;4100 ret = 0;4101 } else if (priv->media_connected) {4102 curr_bss = &priv->curr_bss_params.bss_descriptor;4103 band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);4104 freq = ieee80211_channel_to_frequency(curr_bss->channel, band);4105 chan = ieee80211_get_channel(wiphy, freq);4106 4107 if (priv->ht_param_present) {4108 chan_type = mwifiex_get_chan_type(priv);4109 cfg80211_chandef_create(chandef, chan, chan_type);4110 } else {4111 cfg80211_chandef_create(chandef, chan,4112 NL80211_CHAN_NO_HT);4113 }4114 ret = 0;4115 }4116 4117 return ret;4118}4119 4120#ifdef CONFIG_NL80211_TESTMODE4121 4122enum mwifiex_tm_attr {4123 __MWIFIEX_TM_ATTR_INVALID = 0,4124 MWIFIEX_TM_ATTR_CMD = 1,4125 MWIFIEX_TM_ATTR_DATA = 2,4126 4127 /* keep last */4128 __MWIFIEX_TM_ATTR_AFTER_LAST,4129 MWIFIEX_TM_ATTR_MAX = __MWIFIEX_TM_ATTR_AFTER_LAST - 1,4130};4131 4132static const struct nla_policy mwifiex_tm_policy[MWIFIEX_TM_ATTR_MAX + 1] = {4133 [MWIFIEX_TM_ATTR_CMD] = { .type = NLA_U32 },4134 [MWIFIEX_TM_ATTR_DATA] = { .type = NLA_BINARY,4135 .len = MWIFIEX_SIZE_OF_CMD_BUFFER },4136};4137 4138enum mwifiex_tm_command {4139 MWIFIEX_TM_CMD_HOSTCMD = 0,4140};4141 4142static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,4143 void *data, int len)4144{4145 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);4146 struct mwifiex_ds_misc_cmd *hostcmd;4147 struct nlattr *tb[MWIFIEX_TM_ATTR_MAX + 1];4148 struct sk_buff *skb;4149 int err;4150 4151 if (!priv)4152 return -EINVAL;4153 4154 err = nla_parse_deprecated(tb, MWIFIEX_TM_ATTR_MAX, data, len,4155 mwifiex_tm_policy, NULL);4156 if (err)4157 return err;4158 4159 if (!tb[MWIFIEX_TM_ATTR_CMD])4160 return -EINVAL;4161 4162 switch (nla_get_u32(tb[MWIFIEX_TM_ATTR_CMD])) {4163 case MWIFIEX_TM_CMD_HOSTCMD:4164 if (!tb[MWIFIEX_TM_ATTR_DATA])4165 return -EINVAL;4166 4167 hostcmd = kzalloc(sizeof(*hostcmd), GFP_KERNEL);4168 if (!hostcmd)4169 return -ENOMEM;4170 4171 hostcmd->len = nla_len(tb[MWIFIEX_TM_ATTR_DATA]);4172 memcpy(hostcmd->cmd, nla_data(tb[MWIFIEX_TM_ATTR_DATA]),4173 hostcmd->len);4174 4175 if (mwifiex_send_cmd(priv, 0, 0, 0, hostcmd, true)) {4176 dev_err(priv->adapter->dev, "Failed to process hostcmd\n");4177 kfree(hostcmd);4178 return -EFAULT;4179 }4180 4181 /* process hostcmd response*/4182 skb = cfg80211_testmode_alloc_reply_skb(wiphy, hostcmd->len);4183 if (!skb) {4184 kfree(hostcmd);4185 return -ENOMEM;4186 }4187 err = nla_put(skb, MWIFIEX_TM_ATTR_DATA,4188 hostcmd->len, hostcmd->cmd);4189 if (err) {4190 kfree(hostcmd);4191 kfree_skb(skb);4192 return -EMSGSIZE;4193 }4194 4195 err = cfg80211_testmode_reply(skb);4196 kfree(hostcmd);4197 return err;4198 default:4199 return -EOPNOTSUPP;4200 }4201}4202#endif4203 4204static int4205mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,4206 struct net_device *dev,4207 struct cfg80211_chan_def *chandef,4208 u32 cac_time_ms, int link_id)4209{4210 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4211 struct mwifiex_radar_params radar_params;4212 4213 if (priv->adapter->scan_processing) {4214 mwifiex_dbg(priv->adapter, ERROR,4215 "radar detection: scan already in process...\n");4216 return -EBUSY;4217 }4218 4219 if (!mwifiex_is_11h_active(priv)) {4220 mwifiex_dbg(priv->adapter, INFO,4221 "Enable 11h extensions in FW\n");4222 if (mwifiex_11h_activate(priv, true)) {4223 mwifiex_dbg(priv->adapter, ERROR,4224 "Failed to activate 11h extensions!!");4225 return -1;4226 }4227 priv->state_11h.is_11h_active = true;4228 }4229 4230 memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));4231 radar_params.chandef = chandef;4232 radar_params.cac_time_ms = cac_time_ms;4233 4234 memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef));4235 4236 if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,4237 HostCmd_ACT_GEN_SET, 0, &radar_params, true))4238 return -1;4239 4240 queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work,4241 msecs_to_jiffies(cac_time_ms));4242 return 0;4243}4244 4245static int4246mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,4247 const u8 *mac,4248 struct station_parameters *params)4249{4250 int ret;4251 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4252 4253 if (priv->adapter->host_mlme_enabled &&4254 (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP))4255 return 0;4256 4257 /* we support change_station handler only for TDLS peers*/4258 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))4259 return -EOPNOTSUPP;4260 4261 /* make sure we are in station mode and connected */4262 if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)4263 return -EOPNOTSUPP;4264 4265 priv->sta_params = params;4266 4267 ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);4268 priv->sta_params = NULL;4269 4270 return ret;4271}4272 4273static int4274mwifiex_cfg80211_authenticate(struct wiphy *wiphy,4275 struct net_device *dev,4276 struct cfg80211_auth_request *req)4277{4278 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4279 struct mwifiex_adapter *adapter = priv->adapter;4280 struct sk_buff *skb;4281 u16 pkt_len, auth_alg;4282 int ret;4283 struct mwifiex_ieee80211_mgmt *mgmt;4284 struct mwifiex_txinfo *tx_info;4285 u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;4286 u8 trans = 1, status_code = 0;4287 u8 *varptr = NULL;4288 4289 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {4290 mwifiex_dbg(priv->adapter, ERROR, "Interface role is AP\n");4291 return -EFAULT;4292 }4293 4294 if (priv->wdev.iftype != NL80211_IFTYPE_STATION) {4295 mwifiex_dbg(priv->adapter, ERROR,4296 "Interface type is not correct (type %d)\n",4297 priv->wdev.iftype);4298 return -EINVAL;4299 }4300 4301 if (priv->auth_alg != WLAN_AUTH_SAE &&4302 (priv->auth_flag & HOST_MLME_AUTH_PENDING)) {4303 mwifiex_dbg(priv->adapter, ERROR, "Pending auth on going\n");4304 return -EBUSY;4305 }4306 4307 if (!priv->host_mlme_reg) {4308 priv->host_mlme_reg = true;4309 priv->mgmt_frame_mask |= HOST_MLME_MGMT_MASK;4310 mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,4311 HostCmd_ACT_GEN_SET, 0,4312 &priv->mgmt_frame_mask, false);4313 }4314 4315 switch (req->auth_type) {4316 case NL80211_AUTHTYPE_OPEN_SYSTEM:4317 auth_alg = WLAN_AUTH_OPEN;4318 break;4319 case NL80211_AUTHTYPE_SHARED_KEY:4320 auth_alg = WLAN_AUTH_SHARED_KEY;4321 break;4322 case NL80211_AUTHTYPE_FT:4323 auth_alg = WLAN_AUTH_FT;4324 break;4325 case NL80211_AUTHTYPE_NETWORK_EAP:4326 auth_alg = WLAN_AUTH_LEAP;4327 break;4328 case NL80211_AUTHTYPE_SAE:4329 auth_alg = WLAN_AUTH_SAE;4330 break;4331 default:4332 mwifiex_dbg(priv->adapter, ERROR,4333 "unsupported auth type=%d\n", req->auth_type);4334 return -EOPNOTSUPP;4335 }4336 4337 if (!priv->auth_flag) {4338 ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET,4339 req->bss->channel,4340 AUTH_TX_DEFAULT_WAIT_TIME);4341 4342 if (!ret) {4343 priv->roc_cfg.cookie = get_random_u32() | 1;4344 priv->roc_cfg.chan = *req->bss->channel;4345 } else {4346 return -EFAULT;4347 }4348 }4349 4350 priv->sec_info.authentication_mode = auth_alg;4351 4352 mwifiex_cancel_scan(adapter);4353 4354 pkt_len = (u16)req->ie_len + req->auth_data_len +4355 MWIFIEX_MGMT_HEADER_LEN + MWIFIEX_AUTH_BODY_LEN;4356 if (req->auth_data_len >= 4)4357 pkt_len -= 4;4358 4359 skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +4360 MWIFIEX_MGMT_FRAME_HEADER_SIZE +4361 pkt_len + sizeof(pkt_len));4362 if (!skb) {4363 mwifiex_dbg(priv->adapter, ERROR,4364 "allocate skb failed for management frame\n");4365 return -ENOMEM;4366 }4367 4368 tx_info = MWIFIEX_SKB_TXCB(skb);4369 memset(tx_info, 0, sizeof(*tx_info));4370 tx_info->bss_num = priv->bss_num;4371 tx_info->bss_type = priv->bss_type;4372 tx_info->pkt_len = pkt_len;4373 4374 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +4375 MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));4376 memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));4377 memcpy(skb_push(skb, sizeof(tx_control)),4378 &tx_control, sizeof(tx_control));4379 memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));4380 4381 mgmt = (struct mwifiex_ieee80211_mgmt *)skb_put(skb, pkt_len);4382 memset(mgmt, 0, pkt_len);4383 mgmt->frame_control =4384 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);4385 memcpy(mgmt->da, req->bss->bssid, ETH_ALEN);4386 memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);4387 memcpy(mgmt->bssid, req->bss->bssid, ETH_ALEN);4388 eth_broadcast_addr(mgmt->addr4);4389 4390 if (req->auth_data_len >= 4) {4391 if (req->auth_type == NL80211_AUTHTYPE_SAE) {4392 __le16 *pos = (__le16 *)req->auth_data;4393 4394 trans = le16_to_cpu(pos[0]);4395 status_code = le16_to_cpu(pos[1]);4396 }4397 memcpy((u8 *)(&mgmt->auth.variable), req->auth_data + 4,4398 req->auth_data_len - 4);4399 varptr = (u8 *)&mgmt->auth.variable +4400 (req->auth_data_len - 4);4401 }4402 4403 mgmt->auth.auth_alg = cpu_to_le16(auth_alg);4404 mgmt->auth.auth_transaction = cpu_to_le16(trans);4405 mgmt->auth.status_code = cpu_to_le16(status_code);4406 4407 if (req->ie && req->ie_len) {4408 if (!varptr)4409 varptr = (u8 *)&mgmt->auth.variable;4410 memcpy((u8 *)varptr, req->ie, req->ie_len);4411 }4412 4413 priv->auth_flag = HOST_MLME_AUTH_PENDING;4414 priv->auth_alg = auth_alg;4415 4416 skb->priority = WMM_HIGHEST_PRIORITY;4417 __net_timestamp(skb);4418 4419 mwifiex_dbg(priv->adapter, MSG,4420 "auth: send authentication to %pM\n", req->bss->bssid);4421 4422 mwifiex_queue_tx_pkt(priv, skb);4423 4424 return 0;4425}4426 4427static int4428mwifiex_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,4429 struct cfg80211_assoc_request *req)4430{4431 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4432 struct mwifiex_adapter *adapter = priv->adapter;4433 int ret;4434 struct cfg80211_ssid req_ssid;4435 const u8 *ssid_ie;4436 4437 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {4438 mwifiex_dbg(adapter, ERROR,4439 "%s: reject infra assoc request in non-STA role\n",4440 dev->name);4441 return -EINVAL;4442 }4443 4444 if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||4445 test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {4446 mwifiex_dbg(adapter, ERROR,4447 "%s: Ignore association.\t"4448 "Card removed or FW in bad state\n",4449 dev->name);4450 return -EFAULT;4451 }4452 4453 if (priv->auth_alg == WLAN_AUTH_SAE)4454 priv->auth_flag = HOST_MLME_AUTH_DONE;4455 4456 if (priv->auth_flag && !(priv->auth_flag & HOST_MLME_AUTH_DONE))4457 return -EBUSY;4458 4459 if (priv->roc_cfg.cookie) {4460 ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,4461 &priv->roc_cfg.chan, 0);4462 if (!ret)4463 memset(&priv->roc_cfg, 0,4464 sizeof(struct mwifiex_roc_cfg));4465 else4466 return -EFAULT;4467 }4468 4469 if (!mwifiex_stop_bg_scan(priv))4470 cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);4471 4472 memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));4473 rcu_read_lock();4474 ssid_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);4475 4476 if (!ssid_ie)4477 goto ssid_err;4478 4479 req_ssid.ssid_len = ssid_ie[1];4480 if (req_ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {4481 mwifiex_dbg(adapter, ERROR, "invalid SSID - aborting\n");4482 goto ssid_err;4483 }4484 4485 memcpy(req_ssid.ssid, ssid_ie + 2, req_ssid.ssid_len);4486 if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {4487 mwifiex_dbg(adapter, ERROR, "invalid SSID - aborting\n");4488 goto ssid_err;4489 }4490 rcu_read_unlock();4491 4492 /* As this is new association, clear locally stored4493 * keys and security related flags4494 */4495 priv->sec_info.wpa_enabled = false;4496 priv->sec_info.wpa2_enabled = false;4497 priv->wep_key_curr_index = 0;4498 priv->sec_info.encryption_mode = 0;4499 priv->sec_info.is_authtype_auto = 0;4500 if (mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1)) {4501 mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");4502 return -EFAULT;4503 }4504 4505 if (req->crypto.n_ciphers_pairwise)4506 priv->sec_info.encryption_mode =4507 req->crypto.ciphers_pairwise[0];4508 4509 if (req->crypto.cipher_group)4510 priv->sec_info.encryption_mode = req->crypto.cipher_group;4511 4512 if (req->ie)4513 mwifiex_set_gen_ie(priv, req->ie, req->ie_len);4514 4515 memcpy(priv->cfg_bssid, req->bss->bssid, ETH_ALEN);4516 4517 mwifiex_dbg(adapter, MSG,4518 "assoc: send association to %pM\n", req->bss->bssid);4519 4520 cfg80211_ref_bss(adapter->wiphy, req->bss);4521 ret = mwifiex_bss_start(priv, req->bss, &req_ssid);4522 if (ret) {4523 priv->auth_flag = 0;4524 priv->auth_alg = WLAN_AUTH_NONE;4525 eth_zero_addr(priv->cfg_bssid);4526 }4527 4528 if (priv->assoc_rsp_size) {4529 priv->req_bss = req->bss;4530 adapter->assoc_resp_received = true;4531 queue_work(adapter->host_mlme_workqueue,4532 &adapter->host_mlme_work);4533 }4534 4535 cfg80211_put_bss(priv->adapter->wiphy, req->bss);4536 4537 return 0;4538 4539ssid_err:4540 rcu_read_unlock();4541 return -EFAULT;4542}4543 4544static int4545mwifiex_cfg80211_deauthenticate(struct wiphy *wiphy,4546 struct net_device *dev,4547 struct cfg80211_deauth_request *req)4548{4549 return mwifiex_cfg80211_disconnect(wiphy, dev, req->reason_code);4550}4551 4552static int4553mwifiex_cfg80211_disassociate(struct wiphy *wiphy,4554 struct net_device *dev,4555 struct cfg80211_disassoc_request *req)4556{4557 return mwifiex_cfg80211_disconnect(wiphy, dev, req->reason_code);4558}4559 4560static int4561mwifiex_cfg80211_probe_client(struct wiphy *wiphy,4562 struct net_device *dev, const u8 *peer,4563 u64 *cookie)4564{4565 /* hostapd looks for NL80211_CMD_PROBE_CLIENT support; otherwise,4566 * it requires monitor-mode support (which mwifiex doesn't support).4567 * Provide fake probe_client support to work around this.4568 */4569 return -EOPNOTSUPP;4570}4571 4572/* station cfg80211 operations */4573static const struct cfg80211_ops mwifiex_cfg80211_ops = {4574 .add_virtual_intf = mwifiex_add_virtual_intf,4575 .del_virtual_intf = mwifiex_del_virtual_intf,4576 .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,4577 .scan = mwifiex_cfg80211_scan,4578 .connect = mwifiex_cfg80211_connect,4579 .disconnect = mwifiex_cfg80211_disconnect,4580 .get_station = mwifiex_cfg80211_get_station,4581 .dump_station = mwifiex_cfg80211_dump_station,4582 .dump_survey = mwifiex_cfg80211_dump_survey,4583 .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,4584 .join_ibss = mwifiex_cfg80211_join_ibss,4585 .leave_ibss = mwifiex_cfg80211_leave_ibss,4586 .add_key = mwifiex_cfg80211_add_key,4587 .del_key = mwifiex_cfg80211_del_key,4588 .set_default_mgmt_key = mwifiex_cfg80211_set_default_mgmt_key,4589 .mgmt_tx = mwifiex_cfg80211_mgmt_tx,4590 .update_mgmt_frame_registrations =4591 mwifiex_cfg80211_update_mgmt_frame_registrations,4592 .remain_on_channel = mwifiex_cfg80211_remain_on_channel,4593 .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,4594 .set_default_key = mwifiex_cfg80211_set_default_key,4595 .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,4596 .set_tx_power = mwifiex_cfg80211_set_tx_power,4597 .get_tx_power = mwifiex_cfg80211_get_tx_power,4598 .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,4599 .start_ap = mwifiex_cfg80211_start_ap,4600 .stop_ap = mwifiex_cfg80211_stop_ap,4601 .change_beacon = mwifiex_cfg80211_change_beacon,4602 .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,4603 .set_antenna = mwifiex_cfg80211_set_antenna,4604 .get_antenna = mwifiex_cfg80211_get_antenna,4605 .del_station = mwifiex_cfg80211_del_station,4606 .sched_scan_start = mwifiex_cfg80211_sched_scan_start,4607 .sched_scan_stop = mwifiex_cfg80211_sched_scan_stop,4608#ifdef CONFIG_PM4609 .suspend = mwifiex_cfg80211_suspend,4610 .resume = mwifiex_cfg80211_resume,4611 .set_wakeup = mwifiex_cfg80211_set_wakeup,4612 .set_rekey_data = mwifiex_set_rekey_data,4613#endif4614 .set_coalesce = mwifiex_cfg80211_set_coalesce,4615 .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,4616 .tdls_oper = mwifiex_cfg80211_tdls_oper,4617 .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch,4618 .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,4619 .add_station = mwifiex_cfg80211_add_station,4620 .change_station = mwifiex_cfg80211_change_station,4621 CFG80211_TESTMODE_CMD(mwifiex_tm_cmd)4622 .get_channel = mwifiex_cfg80211_get_channel,4623 .start_radar_detection = mwifiex_cfg80211_start_radar_detection,4624 .channel_switch = mwifiex_cfg80211_channel_switch,4625};4626 4627#ifdef CONFIG_PM4628static const struct wiphy_wowlan_support mwifiex_wowlan_support = {4629 .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT |4630 WIPHY_WOWLAN_NET_DETECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |4631 WIPHY_WOWLAN_GTK_REKEY_FAILURE,4632 .n_patterns = MWIFIEX_MEF_MAX_FILTERS,4633 .pattern_min_len = 1,4634 .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,4635 .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,4636 .max_nd_match_sets = MWIFIEX_MAX_ND_MATCH_SETS,4637};4638 4639static const struct wiphy_wowlan_support mwifiex_wowlan_support_no_gtk = {4640 .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT |4641 WIPHY_WOWLAN_NET_DETECT,4642 .n_patterns = MWIFIEX_MEF_MAX_FILTERS,4643 .pattern_min_len = 1,4644 .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,4645 .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,4646 .max_nd_match_sets = MWIFIEX_MAX_ND_MATCH_SETS,4647};4648#endif4649 4650static bool mwifiex_is_valid_alpha2(const char *alpha2)4651{4652 if (!alpha2 || strlen(alpha2) != 2)4653 return false;4654 4655 if (isalpha(alpha2[0]) && isalpha(alpha2[1]))4656 return true;4657 4658 return false;4659}4660 4661static const struct wiphy_coalesce_support mwifiex_coalesce_support = {4662 .n_rules = MWIFIEX_COALESCE_MAX_RULES,4663 .max_delay = MWIFIEX_MAX_COALESCING_DELAY,4664 .n_patterns = MWIFIEX_COALESCE_MAX_FILTERS,4665 .pattern_min_len = 1,4666 .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,4667 .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,4668};4669 4670int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)4671{4672 u32 n_channels_bg, n_channels_a = 0;4673 4674 n_channels_bg = mwifiex_band_2ghz.n_channels;4675 4676 if (adapter->config_bands & BAND_A)4677 n_channels_a = mwifiex_band_5ghz.n_channels;4678 4679 /* allocate twice the number total channels, since the driver issues an4680 * additional active scan request for hidden SSIDs on passive channels.4681 */4682 adapter->num_in_chan_stats = 2 * (n_channels_bg + n_channels_a);4683 adapter->chan_stats = vmalloc(array_size(sizeof(*adapter->chan_stats),4684 adapter->num_in_chan_stats));4685 4686 if (!adapter->chan_stats)4687 return -ENOMEM;4688 4689 return 0;4690}4691 4692/*4693 * This function registers the device with CFG802.11 subsystem.4694 *4695 * The function creates the wireless device/wiphy, populates it with4696 * default parameters and handler function pointers, and finally4697 * registers the device.4698 */4699 4700int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)4701{4702 int ret;4703 void *wdev_priv;4704 struct wiphy *wiphy;4705 struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];4706 u8 *country_code;4707 u32 thr, retry;4708 struct cfg80211_ops *ops;4709 4710 ops = devm_kmemdup(adapter->dev, &mwifiex_cfg80211_ops,4711 sizeof(mwifiex_cfg80211_ops), GFP_KERNEL);4712 if (!ops)4713 return -ENOMEM;4714 4715 /* create a new wiphy for use with cfg80211 */4716 wiphy = wiphy_new(ops, sizeof(struct mwifiex_adapter *));4717 if (!wiphy) {4718 mwifiex_dbg(adapter, ERROR,4719 "%s: creating new wiphy\n", __func__);4720 return -ENOMEM;4721 }4722 if (adapter->host_mlme_enabled) {4723 ops->auth = mwifiex_cfg80211_authenticate;4724 ops->assoc = mwifiex_cfg80211_associate;4725 ops->deauth = mwifiex_cfg80211_deauthenticate;4726 ops->disassoc = mwifiex_cfg80211_disassociate;4727 ops->disconnect = NULL;4728 ops->connect = NULL;4729 ops->probe_client = mwifiex_cfg80211_probe_client;4730 }4731 wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;4732 wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;4733 if (adapter->host_mlme_enabled) {4734 memcpy(adapter->mwifiex_mgmt_stypes,4735 mwifiex_mgmt_stypes,4736 NUM_NL80211_IFTYPES *4737 sizeof(struct ieee80211_txrx_stypes));4738 4739 adapter->mwifiex_mgmt_stypes[NL80211_IFTYPE_AP].tx = 0xffff;4740 adapter->mwifiex_mgmt_stypes[NL80211_IFTYPE_AP].rx =4741 BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |4742 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |4743 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |4744 BIT(IEEE80211_STYPE_DISASSOC >> 4) |4745 BIT(IEEE80211_STYPE_AUTH >> 4) |4746 BIT(IEEE80211_STYPE_DEAUTH >> 4) |4747 BIT(IEEE80211_STYPE_ACTION >> 4);4748 wiphy->mgmt_stypes = adapter->mwifiex_mgmt_stypes;4749 } else {4750 wiphy->mgmt_stypes = mwifiex_mgmt_stypes;4751 }4752 wiphy->max_remain_on_channel_duration = 5000;4753 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |4754 BIT(NL80211_IFTYPE_P2P_CLIENT) |4755 BIT(NL80211_IFTYPE_P2P_GO) |4756 BIT(NL80211_IFTYPE_AP);4757 4758 wiphy->max_num_akm_suites = CFG80211_MAX_NUM_AKM_SUITES;4759 4760 if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))4761 wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);4762 4763 wiphy->bands[NL80211_BAND_2GHZ] = devm_kmemdup(adapter->dev,4764 &mwifiex_band_2ghz,4765 sizeof(mwifiex_band_2ghz),4766 GFP_KERNEL);4767 if (!wiphy->bands[NL80211_BAND_2GHZ]) {4768 ret = -ENOMEM;4769 goto err;4770 }4771 4772 if (adapter->config_bands & BAND_A) {4773 wiphy->bands[NL80211_BAND_5GHZ] = devm_kmemdup(adapter->dev,4774 &mwifiex_band_5ghz,4775 sizeof(mwifiex_band_5ghz),4776 GFP_KERNEL);4777 if (!wiphy->bands[NL80211_BAND_5GHZ]) {4778 ret = -ENOMEM;4779 goto err;4780 }4781 } else {4782 wiphy->bands[NL80211_BAND_5GHZ] = NULL;4783 }4784 4785 if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))4786 wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;4787 else if (adapter->is_hw_11ac_capable)4788 wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_vht;4789 else4790 wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;4791 wiphy->n_iface_combinations = 1;4792 4793 if (adapter->max_sta_conn > adapter->max_p2p_conn)4794 wiphy->max_ap_assoc_sta = adapter->max_sta_conn;4795 else4796 wiphy->max_ap_assoc_sta = adapter->max_p2p_conn;4797 4798 /* Initialize cipher suits */4799 wiphy->cipher_suites = mwifiex_cipher_suites;4800 wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);4801 4802 if (adapter->regd) {4803 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |4804 REGULATORY_DISABLE_BEACON_HINTS |4805 REGULATORY_COUNTRY_IE_IGNORE;4806 wiphy_apply_custom_regulatory(wiphy, adapter->regd);4807 }4808 4809 ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);4810 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;4811 wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |4812 WIPHY_FLAG_AP_UAPSD |4813 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |4814 WIPHY_FLAG_HAS_CHANNEL_SWITCH |4815 WIPHY_FLAG_NETNS_OK |4816 WIPHY_FLAG_PS_ON_BY_DEFAULT;4817 4818 if (adapter->host_mlme_enabled)4819 wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS;4820 else4821 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;4822 4823 if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))4824 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |4825 WIPHY_FLAG_TDLS_EXTERNAL_SETUP;4826 4827#ifdef CONFIG_PM4828 if (ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info))4829 wiphy->wowlan = &mwifiex_wowlan_support;4830 else4831 wiphy->wowlan = &mwifiex_wowlan_support_no_gtk;4832#endif4833 4834 wiphy->coalesce = &mwifiex_coalesce_support;4835 4836 wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |4837 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |4838 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;4839 4840 wiphy->max_sched_scan_reqs = 1;4841 wiphy->max_sched_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;4842 wiphy->max_sched_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;4843 wiphy->max_match_sets = MWIFIEX_MAX_SSID_LIST_LENGTH;4844 4845 wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;4846 wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;4847 4848 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER |4849 NL80211_FEATURE_LOW_PRIORITY_SCAN |4850 NL80211_FEATURE_NEED_OBSS_SCAN;4851 4852 if (adapter->host_mlme_enabled)4853 wiphy->features |= NL80211_FEATURE_SAE;4854 4855 if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))4856 wiphy->features |= NL80211_FEATURE_HT_IBSS;4857 4858 if (ISSUPP_RANDOM_MAC(adapter->fw_cap_info))4859 wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |4860 NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |4861 NL80211_FEATURE_ND_RANDOM_MAC_ADDR;4862 4863 if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))4864 wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;4865 4866 if (adapter->fw_api_ver == MWIFIEX_FW_V15)4867 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;4868 4869 /* Reserve space for mwifiex specific private data for BSS */4870 wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);4871 4872 wiphy->reg_notifier = mwifiex_reg_notifier;4873 4874 /* Set struct mwifiex_adapter pointer in wiphy_priv */4875 wdev_priv = wiphy_priv(wiphy);4876 *(unsigned long *)wdev_priv = (unsigned long)adapter;4877 4878 set_wiphy_dev(wiphy, priv->adapter->dev);4879 4880 ret = wiphy_register(wiphy);4881 if (ret < 0) {4882 mwifiex_dbg(adapter, ERROR,4883 "%s: wiphy_register failed: %d\n", __func__, ret);4884 goto err;4885 }4886 4887 if (!adapter->regd) {4888 if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {4889 mwifiex_dbg(adapter, INFO,4890 "driver hint alpha2: %2.2s\n", reg_alpha2);4891 regulatory_hint(wiphy, reg_alpha2);4892 } else {4893 if (adapter->region_code == 0x00) {4894 mwifiex_dbg(adapter, WARN,4895 "Ignore world regulatory domain\n");4896 } else {4897 wiphy->regulatory_flags |=4898 REGULATORY_DISABLE_BEACON_HINTS |4899 REGULATORY_COUNTRY_IE_IGNORE;4900 country_code =4901 mwifiex_11d_code_2_region(4902 adapter->region_code);4903 if (country_code &&4904 regulatory_hint(wiphy, country_code))4905 mwifiex_dbg(priv->adapter, ERROR,4906 "regulatory_hint() failed\n");4907 }4908 }4909 }4910 4911 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,4912 HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true);4913 wiphy->frag_threshold = thr;4914 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,4915 HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true);4916 wiphy->rts_threshold = thr;4917 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,4918 HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true);4919 wiphy->retry_short = (u8) retry;4920 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,4921 HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true);4922 wiphy->retry_long = (u8) retry;4923 4924 adapter->wiphy = wiphy;4925 return ret;4926 4927err:4928 wiphy_free(wiphy);4929 4930 return ret;4931}4932