1896 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.4 * All rights reserved.5 */6 7#include "cfg80211.h"8 9#define GO_NEG_REQ 0x0010#define GO_NEG_RSP 0x0111#define GO_NEG_CONF 0x0212#define P2P_INV_REQ 0x0313#define P2P_INV_RSP 0x0414 15#define WILC_INVALID_CHANNEL 016 17/* Operation at 2.4 GHz with channels 1-13 */18#define WILC_WLAN_OPERATING_CLASS_2_4GHZ 0x5119 20static const struct ieee80211_txrx_stypes21 wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = {22 [NL80211_IFTYPE_STATION] = {23 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |24 BIT(IEEE80211_STYPE_AUTH >> 4),25 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |26 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |27 BIT(IEEE80211_STYPE_AUTH >> 4)28 },29 [NL80211_IFTYPE_AP] = {30 .tx = 0xffff,31 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |32 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |33 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |34 BIT(IEEE80211_STYPE_DISASSOC >> 4) |35 BIT(IEEE80211_STYPE_AUTH >> 4) |36 BIT(IEEE80211_STYPE_DEAUTH >> 4) |37 BIT(IEEE80211_STYPE_ACTION >> 4)38 },39 [NL80211_IFTYPE_P2P_CLIENT] = {40 .tx = 0xffff,41 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |42 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |43 BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |44 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |45 BIT(IEEE80211_STYPE_DISASSOC >> 4) |46 BIT(IEEE80211_STYPE_AUTH >> 4) |47 BIT(IEEE80211_STYPE_DEAUTH >> 4)48 }49};50 51#ifdef CONFIG_PM52static const struct wiphy_wowlan_support wowlan_support = {53 .flags = WIPHY_WOWLAN_ANY54};55#endif56 57struct wilc_p2p_mgmt_data {58 int size;59 u8 *buff;60};61 62struct wilc_p2p_pub_act_frame {63 u8 category;64 u8 action;65 u8 oui[3];66 u8 oui_type;67 u8 oui_subtype;68 u8 dialog_token;69 u8 elem[];70} __packed;71 72struct wilc_vendor_specific_ie {73 u8 tag_number;74 u8 tag_len;75 u8 oui[3];76 u8 oui_type;77 u8 attr[];78} __packed;79 80struct wilc_attr_entry {81 u8 attr_type;82 __le16 attr_len;83 u8 val[];84} __packed;85 86struct wilc_attr_oper_ch {87 u8 attr_type;88 __le16 attr_len;89 u8 country_code[IEEE80211_COUNTRY_STRING_LEN];90 u8 op_class;91 u8 op_channel;92} __packed;93 94struct wilc_attr_ch_list {95 u8 attr_type;96 __le16 attr_len;97 u8 country_code[IEEE80211_COUNTRY_STRING_LEN];98 u8 elem[];99} __packed;100 101struct wilc_ch_list_elem {102 u8 op_class;103 u8 no_of_channels;104 u8 ch_list[];105} __packed;106 107static void cfg_scan_result(enum scan_event scan_event,108 struct wilc_rcvd_net_info *info,109 struct wilc_priv *priv)110{111 if (!priv->cfg_scanning)112 return;113 114 if (scan_event == SCAN_EVENT_NETWORK_FOUND) {115 s32 freq;116 struct ieee80211_channel *channel;117 struct cfg80211_bss *bss;118 struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy;119 120 if (!wiphy || !info)121 return;122 123 freq = ieee80211_channel_to_frequency((s32)info->ch,124 NL80211_BAND_2GHZ);125 channel = ieee80211_get_channel(wiphy, freq);126 if (!channel)127 return;128 129 bss = cfg80211_inform_bss_frame(wiphy, channel, info->mgmt,130 info->frame_len,131 (s32)info->rssi * 100,132 GFP_KERNEL);133 cfg80211_put_bss(wiphy, bss);134 } else if (scan_event == SCAN_EVENT_DONE) {135 mutex_lock(&priv->scan_req_lock);136 137 if (priv->scan_req) {138 struct cfg80211_scan_info info = {139 .aborted = false,140 };141 142 cfg80211_scan_done(priv->scan_req, &info);143 priv->cfg_scanning = false;144 priv->scan_req = NULL;145 }146 mutex_unlock(&priv->scan_req_lock);147 } else if (scan_event == SCAN_EVENT_ABORTED) {148 mutex_lock(&priv->scan_req_lock);149 150 if (priv->scan_req) {151 struct cfg80211_scan_info info = {152 .aborted = false,153 };154 155 cfg80211_scan_done(priv->scan_req, &info);156 priv->cfg_scanning = false;157 priv->scan_req = NULL;158 }159 mutex_unlock(&priv->scan_req_lock);160 }161}162 163static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,164 struct wilc_priv *priv)165{166 struct net_device *dev = priv->dev;167 struct wilc_vif *vif = netdev_priv(dev);168 struct wilc *wl = vif->wilc;169 struct host_if_drv *wfi_drv = priv->hif_drv;170 struct wilc_conn_info *conn_info = &wfi_drv->conn_info;171 struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;172 173 vif->connecting = false;174 175 if (conn_disconn_evt == CONN_DISCONN_EVENT_CONN_RESP) {176 u16 connect_status = conn_info->status;177 178 if (mac_status == WILC_MAC_STATUS_DISCONNECTED &&179 connect_status == WLAN_STATUS_SUCCESS) {180 connect_status = WLAN_STATUS_UNSPECIFIED_FAILURE;181 wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);182 183 if (vif->iftype != WILC_CLIENT_MODE)184 wl->sta_ch = WILC_INVALID_CHANNEL;185 186 netdev_err(dev, "Unspecified failure\n");187 }188 189 if (connect_status == WLAN_STATUS_SUCCESS)190 memcpy(priv->associated_bss, conn_info->bssid,191 ETH_ALEN);192 193 cfg80211_ref_bss(wiphy, vif->bss);194 cfg80211_connect_bss(dev, conn_info->bssid, vif->bss,195 conn_info->req_ies,196 conn_info->req_ies_len,197 conn_info->resp_ies,198 conn_info->resp_ies_len,199 connect_status, GFP_KERNEL,200 NL80211_TIMEOUT_UNSPECIFIED);201 202 vif->bss = NULL;203 } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) {204 u16 reason = 0;205 206 eth_zero_addr(priv->associated_bss);207 wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);208 209 if (vif->iftype != WILC_CLIENT_MODE) {210 wl->sta_ch = WILC_INVALID_CHANNEL;211 } else {212 if (wfi_drv->ifc_up)213 reason = 3;214 else215 reason = 1;216 }217 218 cfg80211_disconnected(dev, reason, NULL, 0, false, GFP_KERNEL);219 }220}221 222struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)223{224 struct wilc_vif *vif;225 226 vif = list_first_or_null_rcu(&wl->vif_list, typeof(*vif), list);227 if (!vif)228 return ERR_PTR(-EINVAL);229 230 return vif;231}232 233static int set_channel(struct wiphy *wiphy,234 struct cfg80211_chan_def *chandef)235{236 struct wilc *wl = wiphy_priv(wiphy);237 struct wilc_vif *vif;238 u32 channelnum;239 int result;240 int srcu_idx;241 242 srcu_idx = srcu_read_lock(&wl->srcu);243 vif = wilc_get_wl_to_vif(wl);244 if (IS_ERR(vif)) {245 srcu_read_unlock(&wl->srcu, srcu_idx);246 return PTR_ERR(vif);247 }248 249 channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);250 251 wl->op_ch = channelnum;252 result = wilc_set_mac_chnl_num(vif, channelnum);253 if (result)254 netdev_err(vif->ndev, "Error in setting channel\n");255 256 srcu_read_unlock(&wl->srcu, srcu_idx);257 return result;258}259 260static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)261{262 struct wilc_vif *vif = netdev_priv(request->wdev->netdev);263 struct wilc_priv *priv = &vif->priv;264 u32 i;265 int ret = 0;266 u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH];267 u8 scan_type;268 269 if (request->n_channels > WILC_MAX_NUM_SCANNED_CH) {270 netdev_err(vif->ndev, "Requested scanned channels over\n");271 return -EINVAL;272 }273 274 priv->scan_req = request;275 priv->cfg_scanning = true;276 for (i = 0; i < request->n_channels; i++) {277 u16 freq = request->channels[i]->center_freq;278 279 scan_ch_list[i] = ieee80211_frequency_to_channel(freq);280 }281 282 if (request->n_ssids)283 scan_type = WILC_FW_ACTIVE_SCAN;284 else285 scan_type = WILC_FW_PASSIVE_SCAN;286 287 ret = wilc_scan(vif, WILC_FW_USER_SCAN, scan_type,288 scan_ch_list, cfg_scan_result, request);289 290 if (ret) {291 priv->scan_req = NULL;292 priv->cfg_scanning = false;293 }294 295 return ret;296}297 298static int connect(struct wiphy *wiphy, struct net_device *dev,299 struct cfg80211_connect_params *sme)300{301 struct wilc_vif *vif = netdev_priv(dev);302 struct wilc_priv *priv = &vif->priv;303 struct host_if_drv *wfi_drv = priv->hif_drv;304 int ret;305 u32 i;306 u8 security = WILC_FW_SEC_NO;307 enum mfptype mfp_type = WILC_FW_MFP_NONE;308 enum authtype auth_type = WILC_FW_AUTH_ANY;309 u32 cipher_group;310 struct cfg80211_bss *bss;311 void *join_params;312 u8 ch;313 314 vif->connecting = true;315 316 cipher_group = sme->crypto.cipher_group;317 if (cipher_group != 0) {318 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {319 if (cipher_group == WLAN_CIPHER_SUITE_TKIP)320 security = WILC_FW_SEC_WPA2_TKIP;321 else322 security = WILC_FW_SEC_WPA2_AES;323 } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {324 if (cipher_group == WLAN_CIPHER_SUITE_TKIP)325 security = WILC_FW_SEC_WPA_TKIP;326 else327 security = WILC_FW_SEC_WPA_AES;328 } else {329 ret = -ENOTSUPP;330 netdev_err(dev, "%s: Unsupported cipher\n",331 __func__);332 goto out_error;333 }334 }335 336 if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) ||337 (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {338 for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) {339 u32 ciphers_pairwise = sme->crypto.ciphers_pairwise[i];340 341 if (ciphers_pairwise == WLAN_CIPHER_SUITE_TKIP)342 security |= WILC_FW_TKIP;343 else344 security |= WILC_FW_AES;345 }346 }347 348 switch (sme->auth_type) {349 case NL80211_AUTHTYPE_OPEN_SYSTEM:350 auth_type = WILC_FW_AUTH_OPEN_SYSTEM;351 break;352 353 case NL80211_AUTHTYPE_SAE:354 auth_type = WILC_FW_AUTH_SAE;355 if (sme->ssid_len) {356 memcpy(vif->auth.ssid.ssid, sme->ssid, sme->ssid_len);357 vif->auth.ssid.ssid_len = sme->ssid_len;358 }359 vif->auth.key_mgmt_suite = sme->crypto.akm_suites[0];360 ether_addr_copy(vif->auth.bssid, sme->bssid);361 break;362 363 default:364 break;365 }366 367 if (sme->crypto.n_akm_suites) {368 if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X)369 auth_type = WILC_FW_AUTH_IEEE8021;370 else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_PSK_SHA256)371 auth_type = WILC_FW_AUTH_OPEN_SYSTEM_SHA256;372 else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X_SHA256)373 auth_type = WILC_FW_AUTH_IEE8021X_SHA256;374 }375 376 if (wfi_drv->usr_scan_req.scan_result) {377 netdev_err(vif->ndev, "%s: Scan in progress\n", __func__);378 ret = -EBUSY;379 goto out_error;380 }381 382 bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid,383 sme->ssid_len, IEEE80211_BSS_TYPE_ANY,384 IEEE80211_PRIVACY(sme->privacy));385 if (!bss) {386 ret = -EINVAL;387 goto out_error;388 }389 390 if (ether_addr_equal_unaligned(vif->bssid, bss->bssid)) {391 ret = -EALREADY;392 goto out_put_bss;393 }394 395 join_params = wilc_parse_join_bss_param(bss, &sme->crypto);396 if (!join_params) {397 netdev_err(dev, "%s: failed to construct join param\n",398 __func__);399 ret = -EINVAL;400 goto out_put_bss;401 }402 403 ch = ieee80211_frequency_to_channel(bss->channel->center_freq);404 vif->wilc->op_ch = ch;405 if (vif->iftype != WILC_CLIENT_MODE)406 vif->wilc->sta_ch = ch;407 408 wilc_wlan_set_bssid(dev, bss->bssid, WILC_STATION_MODE);409 410 wfi_drv->conn_info.security = security;411 wfi_drv->conn_info.auth_type = auth_type;412 wfi_drv->conn_info.conn_result = cfg_connect_result;413 wfi_drv->conn_info.priv = priv;414 wfi_drv->conn_info.param = join_params;415 416 if (sme->mfp == NL80211_MFP_OPTIONAL)417 mfp_type = WILC_FW_MFP_OPTIONAL;418 else if (sme->mfp == NL80211_MFP_REQUIRED)419 mfp_type = WILC_FW_MFP_REQUIRED;420 421 wfi_drv->conn_info.mfp_type = mfp_type;422 423 ret = wilc_set_join_req(vif, bss->bssid, sme->ie, sme->ie_len);424 if (ret) {425 netdev_err(dev, "wilc_set_join_req(): Error\n");426 ret = -ENOENT;427 if (vif->iftype != WILC_CLIENT_MODE)428 vif->wilc->sta_ch = WILC_INVALID_CHANNEL;429 wilc_wlan_set_bssid(dev, NULL, WILC_STATION_MODE);430 wfi_drv->conn_info.conn_result = NULL;431 kfree(join_params);432 goto out_put_bss;433 }434 kfree(join_params);435 vif->bss = bss;436 cfg80211_put_bss(wiphy, bss);437 return 0;438 439out_put_bss:440 cfg80211_put_bss(wiphy, bss);441 442out_error:443 vif->connecting = false;444 return ret;445}446 447static int disconnect(struct wiphy *wiphy, struct net_device *dev,448 u16 reason_code)449{450 struct wilc_vif *vif = netdev_priv(dev);451 struct wilc_priv *priv = &vif->priv;452 struct wilc *wilc = vif->wilc;453 int ret;454 455 vif->connecting = false;456 457 if (!wilc)458 return -EIO;459 460 if (wilc->close) {461 /* already disconnected done */462 cfg80211_disconnected(dev, 0, NULL, 0, true, GFP_KERNEL);463 return 0;464 }465 466 if (vif->iftype != WILC_CLIENT_MODE)467 wilc->sta_ch = WILC_INVALID_CHANNEL;468 wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);469 470 priv->hif_drv->p2p_timeout = 0;471 472 ret = wilc_disconnect(vif);473 if (ret != 0) {474 netdev_err(priv->dev, "Error in disconnecting\n");475 ret = -EINVAL;476 }477 478 vif->bss = NULL;479 480 return ret;481}482 483static int wilc_wfi_cfg_allocate_wpa_entry(struct wilc_priv *priv, u8 idx)484{485 if (!priv->wilc_gtk[idx]) {486 priv->wilc_gtk[idx] = kzalloc(sizeof(*priv->wilc_gtk[idx]),487 GFP_KERNEL);488 if (!priv->wilc_gtk[idx])489 return -ENOMEM;490 }491 492 if (!priv->wilc_ptk[idx]) {493 priv->wilc_ptk[idx] = kzalloc(sizeof(*priv->wilc_ptk[idx]),494 GFP_KERNEL);495 if (!priv->wilc_ptk[idx])496 return -ENOMEM;497 }498 499 return 0;500}501 502static int wilc_wfi_cfg_allocate_wpa_igtk_entry(struct wilc_priv *priv, u8 idx)503{504 idx -= 4;505 if (!priv->wilc_igtk[idx]) {506 priv->wilc_igtk[idx] = kzalloc(sizeof(*priv->wilc_igtk[idx]),507 GFP_KERNEL);508 if (!priv->wilc_igtk[idx])509 return -ENOMEM;510 }511 return 0;512}513 514static int wilc_wfi_cfg_copy_wpa_info(struct wilc_wfi_key *key_info,515 struct key_params *params)516{517 kfree(key_info->key);518 519 key_info->key = kmemdup(params->key, params->key_len, GFP_KERNEL);520 if (!key_info->key)521 return -ENOMEM;522 523 kfree(key_info->seq);524 525 if (params->seq_len > 0) {526 key_info->seq = kmemdup(params->seq, params->seq_len,527 GFP_KERNEL);528 if (!key_info->seq)529 return -ENOMEM;530 }531 532 key_info->cipher = params->cipher;533 key_info->key_len = params->key_len;534 key_info->seq_len = params->seq_len;535 536 return 0;537}538 539static int add_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,540 u8 key_index, bool pairwise, const u8 *mac_addr,541 struct key_params *params)542 543{544 int ret = 0, keylen = params->key_len;545 const u8 *rx_mic = NULL;546 const u8 *tx_mic = NULL;547 u8 mode = WILC_FW_SEC_NO;548 u8 op_mode;549 struct wilc_vif *vif = netdev_priv(netdev);550 struct wilc_priv *priv = &vif->priv;551 struct wilc_wfi_key *key;552 553 switch (params->cipher) {554 case WLAN_CIPHER_SUITE_TKIP:555 case WLAN_CIPHER_SUITE_CCMP:556 if (priv->wdev.iftype == NL80211_IFTYPE_AP ||557 priv->wdev.iftype == NL80211_IFTYPE_P2P_GO) {558 struct wilc_wfi_key *key;559 560 ret = wilc_wfi_cfg_allocate_wpa_entry(priv, key_index);561 if (ret)562 return -ENOMEM;563 564 if (params->key_len > 16 &&565 params->cipher == WLAN_CIPHER_SUITE_TKIP) {566 tx_mic = params->key + 24;567 rx_mic = params->key + 16;568 keylen = params->key_len - 16;569 }570 571 if (!pairwise) {572 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)573 mode = WILC_FW_SEC_WPA_TKIP;574 else575 mode = WILC_FW_SEC_WPA2_AES;576 577 priv->wilc_groupkey = mode;578 579 key = priv->wilc_gtk[key_index];580 } else {581 if (params->cipher == WLAN_CIPHER_SUITE_TKIP)582 mode = WILC_FW_SEC_WPA_TKIP;583 else584 mode = priv->wilc_groupkey | WILC_FW_AES;585 586 key = priv->wilc_ptk[key_index];587 }588 ret = wilc_wfi_cfg_copy_wpa_info(key, params);589 if (ret)590 return -ENOMEM;591 592 op_mode = WILC_AP_MODE;593 } else {594 if (params->key_len > 16 &&595 params->cipher == WLAN_CIPHER_SUITE_TKIP) {596 rx_mic = params->key + 24;597 tx_mic = params->key + 16;598 keylen = params->key_len - 16;599 }600 601 op_mode = WILC_STATION_MODE;602 }603 604 if (!pairwise)605 ret = wilc_add_rx_gtk(vif, params->key, keylen,606 key_index, params->seq_len,607 params->seq, rx_mic, tx_mic,608 op_mode, mode);609 else610 ret = wilc_add_ptk(vif, params->key, keylen, mac_addr,611 rx_mic, tx_mic, op_mode, mode,612 key_index);613 614 break;615 case WLAN_CIPHER_SUITE_AES_CMAC:616 ret = wilc_wfi_cfg_allocate_wpa_igtk_entry(priv, key_index);617 if (ret)618 return -ENOMEM;619 620 key = priv->wilc_igtk[key_index - 4];621 ret = wilc_wfi_cfg_copy_wpa_info(key, params);622 if (ret)623 return -ENOMEM;624 625 if (priv->wdev.iftype == NL80211_IFTYPE_AP ||626 priv->wdev.iftype == NL80211_IFTYPE_P2P_GO)627 op_mode = WILC_AP_MODE;628 else629 op_mode = WILC_STATION_MODE;630 631 ret = wilc_add_igtk(vif, params->key, keylen, params->seq,632 params->seq_len, mac_addr, op_mode,633 key_index);634 break;635 636 default:637 netdev_err(netdev, "%s: Unsupported cipher\n", __func__);638 ret = -ENOTSUPP;639 }640 641 return ret;642}643 644static int del_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,645 u8 key_index,646 bool pairwise,647 const u8 *mac_addr)648{649 struct wilc_vif *vif = netdev_priv(netdev);650 struct wilc_priv *priv = &vif->priv;651 652 if (!pairwise && (key_index == 4 || key_index == 5)) {653 key_index -= 4;654 if (priv->wilc_igtk[key_index]) {655 kfree(priv->wilc_igtk[key_index]->key);656 priv->wilc_igtk[key_index]->key = NULL;657 kfree(priv->wilc_igtk[key_index]->seq);658 priv->wilc_igtk[key_index]->seq = NULL;659 kfree(priv->wilc_igtk[key_index]);660 priv->wilc_igtk[key_index] = NULL;661 }662 } else {663 if (priv->wilc_gtk[key_index]) {664 kfree(priv->wilc_gtk[key_index]->key);665 priv->wilc_gtk[key_index]->key = NULL;666 kfree(priv->wilc_gtk[key_index]->seq);667 priv->wilc_gtk[key_index]->seq = NULL;668 669 kfree(priv->wilc_gtk[key_index]);670 priv->wilc_gtk[key_index] = NULL;671 }672 if (priv->wilc_ptk[key_index]) {673 kfree(priv->wilc_ptk[key_index]->key);674 priv->wilc_ptk[key_index]->key = NULL;675 kfree(priv->wilc_ptk[key_index]->seq);676 priv->wilc_ptk[key_index]->seq = NULL;677 kfree(priv->wilc_ptk[key_index]);678 priv->wilc_ptk[key_index] = NULL;679 }680 }681 682 return 0;683}684 685static int get_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,686 u8 key_index, bool pairwise, const u8 *mac_addr,687 void *cookie,688 void (*callback)(void *cookie, struct key_params *))689{690 struct wilc_vif *vif = netdev_priv(netdev);691 struct wilc_priv *priv = &vif->priv;692 struct key_params key_params;693 694 if (!pairwise) {695 if (key_index == 4 || key_index == 5) {696 key_index -= 4;697 key_params.key = priv->wilc_igtk[key_index]->key;698 key_params.cipher = priv->wilc_igtk[key_index]->cipher;699 key_params.key_len = priv->wilc_igtk[key_index]->key_len;700 key_params.seq = priv->wilc_igtk[key_index]->seq;701 key_params.seq_len = priv->wilc_igtk[key_index]->seq_len;702 } else {703 key_params.key = priv->wilc_gtk[key_index]->key;704 key_params.cipher = priv->wilc_gtk[key_index]->cipher;705 key_params.key_len = priv->wilc_gtk[key_index]->key_len;706 key_params.seq = priv->wilc_gtk[key_index]->seq;707 key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;708 }709 } else {710 key_params.key = priv->wilc_ptk[key_index]->key;711 key_params.cipher = priv->wilc_ptk[key_index]->cipher;712 key_params.key_len = priv->wilc_ptk[key_index]->key_len;713 key_params.seq = priv->wilc_ptk[key_index]->seq;714 key_params.seq_len = priv->wilc_ptk[key_index]->seq_len;715 }716 717 callback(cookie, &key_params);718 719 return 0;720}721 722/* wiphy_new_nm() will WARNON if not present */723static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,724 int link_id, u8 key_index, bool unicast,725 bool multicast)726{727 return 0;728}729 730static int set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev,731 int link_id, u8 key_index)732{733 struct wilc_vif *vif = netdev_priv(netdev);734 735 return wilc_set_default_mgmt_key_index(vif, key_index);736}737 738static int get_station(struct wiphy *wiphy, struct net_device *dev,739 const u8 *mac, struct station_info *sinfo)740{741 struct wilc_vif *vif = netdev_priv(dev);742 struct wilc_priv *priv = &vif->priv;743 struct wilc *wilc = vif->wilc;744 u32 i = 0;745 u32 associatedsta = ~0;746 u32 inactive_time = 0;747 748 if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {749 for (i = 0; i < NUM_STA_ASSOCIATED; i++) {750 if (!(memcmp(mac,751 priv->assoc_stainfo.sta_associated_bss[i],752 ETH_ALEN))) {753 associatedsta = i;754 break;755 }756 }757 758 if (associatedsta == ~0) {759 netdev_err(dev, "sta required is not associated\n");760 return -ENOENT;761 }762 763 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);764 765 wilc_get_inactive_time(vif, mac, &inactive_time);766 sinfo->inactive_time = 1000 * inactive_time;767 } else if (vif->iftype == WILC_STATION_MODE) {768 struct rf_info stats;769 770 if (!wilc->initialized)771 return -EBUSY;772 773 wilc_get_statistics(vif, &stats);774 775 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL) |776 BIT_ULL(NL80211_STA_INFO_RX_PACKETS) |777 BIT_ULL(NL80211_STA_INFO_TX_PACKETS) |778 BIT_ULL(NL80211_STA_INFO_TX_FAILED) |779 BIT_ULL(NL80211_STA_INFO_TX_BITRATE);780 781 sinfo->signal = stats.rssi;782 sinfo->rx_packets = stats.rx_cnt;783 sinfo->tx_packets = stats.tx_cnt + stats.tx_fail_cnt;784 sinfo->tx_failed = stats.tx_fail_cnt;785 sinfo->txrate.legacy = stats.link_speed * 10;786 787 if (stats.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&788 stats.link_speed != DEFAULT_LINK_SPEED)789 wilc_enable_tcp_ack_filter(vif, true);790 else if (stats.link_speed != DEFAULT_LINK_SPEED)791 wilc_enable_tcp_ack_filter(vif, false);792 }793 return 0;794}795 796static int change_bss(struct wiphy *wiphy, struct net_device *dev,797 struct bss_parameters *params)798{799 return 0;800}801 802static int set_wiphy_params(struct wiphy *wiphy, u32 changed)803{804 int ret = -EINVAL;805 struct cfg_param_attr cfg_param_val;806 struct wilc *wl = wiphy_priv(wiphy);807 struct wilc_vif *vif;808 struct wilc_priv *priv;809 int srcu_idx;810 811 srcu_idx = srcu_read_lock(&wl->srcu);812 vif = wilc_get_wl_to_vif(wl);813 if (IS_ERR(vif))814 goto out;815 816 priv = &vif->priv;817 cfg_param_val.flag = 0;818 819 if (changed & WIPHY_PARAM_RETRY_SHORT) {820 netdev_dbg(vif->ndev,821 "Setting WIPHY_PARAM_RETRY_SHORT %d\n",822 wiphy->retry_short);823 cfg_param_val.flag |= WILC_CFG_PARAM_RETRY_SHORT;824 cfg_param_val.short_retry_limit = wiphy->retry_short;825 }826 if (changed & WIPHY_PARAM_RETRY_LONG) {827 netdev_dbg(vif->ndev,828 "Setting WIPHY_PARAM_RETRY_LONG %d\n",829 wiphy->retry_long);830 cfg_param_val.flag |= WILC_CFG_PARAM_RETRY_LONG;831 cfg_param_val.long_retry_limit = wiphy->retry_long;832 }833 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {834 if (wiphy->frag_threshold > 255 &&835 wiphy->frag_threshold < 7937) {836 netdev_dbg(vif->ndev,837 "Setting WIPHY_PARAM_FRAG_THRESHOLD %d\n",838 wiphy->frag_threshold);839 cfg_param_val.flag |= WILC_CFG_PARAM_FRAG_THRESHOLD;840 cfg_param_val.frag_threshold = wiphy->frag_threshold;841 } else {842 netdev_err(vif->ndev,843 "Fragmentation threshold out of range\n");844 goto out;845 }846 }847 848 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {849 if (wiphy->rts_threshold > 255) {850 netdev_dbg(vif->ndev,851 "Setting WIPHY_PARAM_RTS_THRESHOLD %d\n",852 wiphy->rts_threshold);853 cfg_param_val.flag |= WILC_CFG_PARAM_RTS_THRESHOLD;854 cfg_param_val.rts_threshold = wiphy->rts_threshold;855 } else {856 netdev_err(vif->ndev, "RTS threshold out of range\n");857 goto out;858 }859 }860 861 ret = wilc_hif_set_cfg(vif, &cfg_param_val);862 if (ret)863 netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");864 865out:866 srcu_read_unlock(&wl->srcu, srcu_idx);867 return ret;868}869 870static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,871 struct cfg80211_pmksa *pmksa)872{873 struct wilc_vif *vif = netdev_priv(netdev);874 struct wilc_priv *priv = &vif->priv;875 u32 i;876 int ret = 0;877 u8 flag = 0;878 879 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {880 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,881 ETH_ALEN)) {882 flag = PMKID_FOUND;883 break;884 }885 }886 if (i < WILC_MAX_NUM_PMKIDS) {887 memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,888 ETH_ALEN);889 memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,890 WLAN_PMKID_LEN);891 if (!(flag == PMKID_FOUND))892 priv->pmkid_list.numpmkid++;893 } else {894 netdev_err(netdev, "Invalid PMKID index\n");895 ret = -EINVAL;896 }897 898 if (!ret)899 ret = wilc_set_pmkid_info(vif, &priv->pmkid_list);900 901 return ret;902}903 904static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,905 struct cfg80211_pmksa *pmksa)906{907 u32 i;908 struct wilc_vif *vif = netdev_priv(netdev);909 struct wilc_priv *priv = &vif->priv;910 911 for (i = 0; i < priv->pmkid_list.numpmkid; i++) {912 if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,913 ETH_ALEN)) {914 memset(&priv->pmkid_list.pmkidlist[i], 0,915 sizeof(struct wilc_pmkid));916 break;917 }918 }919 920 if (i == priv->pmkid_list.numpmkid)921 return -EINVAL;922 923 for (; i < (priv->pmkid_list.numpmkid - 1); i++) {924 memcpy(priv->pmkid_list.pmkidlist[i].bssid,925 priv->pmkid_list.pmkidlist[i + 1].bssid,926 ETH_ALEN);927 memcpy(priv->pmkid_list.pmkidlist[i].pmkid,928 priv->pmkid_list.pmkidlist[i + 1].pmkid,929 WLAN_PMKID_LEN);930 }931 priv->pmkid_list.numpmkid--;932 933 return 0;934}935 936static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)937{938 struct wilc_vif *vif = netdev_priv(netdev);939 940 memset(&vif->priv.pmkid_list, 0, sizeof(struct wilc_pmkid_attr));941 942 return 0;943}944 945static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u32 len, u8 sta_ch)946{947 struct wilc_attr_entry *e;948 struct wilc_attr_ch_list *ch_list;949 struct wilc_attr_oper_ch *op_ch;950 u32 index = 0;951 u8 ch_list_idx = 0;952 u8 op_ch_idx = 0;953 954 if (sta_ch == WILC_INVALID_CHANNEL)955 return;956 957 while (index + sizeof(*e) <= len) {958 u16 attr_size;959 960 e = (struct wilc_attr_entry *)&buf[index];961 attr_size = le16_to_cpu(e->attr_len);962 963 if (index + sizeof(*e) + attr_size > len)964 return;965 966 if (e->attr_type == IEEE80211_P2P_ATTR_CHANNEL_LIST &&967 attr_size >= (sizeof(struct wilc_attr_ch_list) - sizeof(*e)))968 ch_list_idx = index;969 else if (e->attr_type == IEEE80211_P2P_ATTR_OPER_CHANNEL &&970 attr_size == (sizeof(struct wilc_attr_oper_ch) - sizeof(*e)))971 op_ch_idx = index;972 973 if (ch_list_idx && op_ch_idx)974 break;975 976 index += sizeof(*e) + attr_size;977 }978 979 if (ch_list_idx) {980 u16 elem_size;981 982 ch_list = (struct wilc_attr_ch_list *)&buf[ch_list_idx];983 /* the number of bytes following the final 'elem' member */984 elem_size = le16_to_cpu(ch_list->attr_len) -985 (sizeof(*ch_list) - sizeof(struct wilc_attr_entry));986 for (unsigned int i = 0; i < elem_size;) {987 struct wilc_ch_list_elem *e;988 989 e = (struct wilc_ch_list_elem *)(ch_list->elem + i);990 991 i += sizeof(*e);992 if (i > elem_size)993 break;994 995 i += e->no_of_channels;996 if (i > elem_size)997 break;998 999 if (e->op_class == WILC_WLAN_OPERATING_CLASS_2_4GHZ) {1000 memset(e->ch_list, sta_ch, e->no_of_channels);1001 break;1002 }1003 }1004 }1005 1006 if (op_ch_idx) {1007 op_ch = (struct wilc_attr_oper_ch *)&buf[op_ch_idx];1008 op_ch->op_class = WILC_WLAN_OPERATING_CLASS_2_4GHZ;1009 op_ch->op_channel = sta_ch;1010 }1011}1012 1013bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size)1014{1015 struct wilc *wl = vif->wilc;1016 struct wilc_priv *priv = &vif->priv;1017 int freq;1018 1019 freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ);1020 1021 return cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);1022}1023 1024void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)1025{1026 struct wilc *wl = vif->wilc;1027 struct wilc_priv *priv = &vif->priv;1028 struct host_if_drv *wfi_drv = priv->hif_drv;1029 struct ieee80211_mgmt *mgmt;1030 struct wilc_vendor_specific_ie *p;1031 struct wilc_p2p_pub_act_frame *d;1032 int ie_offset = offsetof(struct ieee80211_mgmt, u) + sizeof(*d);1033 const u8 *vendor_ie;1034 u32 header, pkt_offset;1035 s32 freq;1036 1037 header = get_unaligned_le32(buff - HOST_HDR_OFFSET);1038 pkt_offset = FIELD_GET(WILC_PKT_HDR_OFFSET_FIELD, header);1039 1040 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {1041 bool ack = false;1042 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)buff;1043 1044 if (ieee80211_is_probe_resp(hdr->frame_control) ||1045 pkt_offset & IS_MGMT_STATUS_SUCCES)1046 ack = true;1047 1048 cfg80211_mgmt_tx_status(&priv->wdev, priv->tx_cookie, buff,1049 size, ack, GFP_KERNEL);1050 return;1051 }1052 1053 freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ);1054 1055 mgmt = (struct ieee80211_mgmt *)buff;1056 if (!ieee80211_is_action(mgmt->frame_control))1057 goto out_rx_mgmt;1058 1059 if (priv->cfg_scanning &&1060 time_after_eq(jiffies, (unsigned long)wfi_drv->p2p_timeout)) {1061 netdev_dbg(vif->ndev, "Receiving action wrong ch\n");1062 return;1063 }1064 1065 if (!ieee80211_is_public_action((struct ieee80211_hdr *)buff, size))1066 goto out_rx_mgmt;1067 1068 d = (struct wilc_p2p_pub_act_frame *)(&mgmt->u.action);1069 if (d->oui_subtype != GO_NEG_REQ && d->oui_subtype != GO_NEG_RSP &&1070 d->oui_subtype != P2P_INV_REQ && d->oui_subtype != P2P_INV_RSP)1071 goto out_rx_mgmt;1072 1073 vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,1074 buff + ie_offset, size - ie_offset);1075 if (!vendor_ie)1076 goto out_rx_mgmt;1077 1078 p = (struct wilc_vendor_specific_ie *)vendor_ie;1079 wilc_wfi_cfg_parse_ch_attr(p->attr, p->tag_len - 4, vif->wilc->sta_ch);1080 1081out_rx_mgmt:1082 cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);1083}1084 1085static void wilc_wfi_mgmt_tx_complete(void *priv, int status)1086{1087 struct wilc_p2p_mgmt_data *pv_data = priv;1088 1089 kfree(pv_data->buff);1090 kfree(pv_data);1091}1092 1093static void wilc_wfi_remain_on_channel_expired(struct wilc_vif *vif, u64 cookie)1094{1095 struct wilc_priv *priv = &vif->priv;1096 struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params;1097 1098 if (cookie != params->listen_cookie)1099 return;1100 1101 priv->p2p_listen_state = false;1102 1103 cfg80211_remain_on_channel_expired(&priv->wdev, params->listen_cookie,1104 params->listen_ch, GFP_KERNEL);1105}1106 1107static int remain_on_channel(struct wiphy *wiphy,1108 struct wireless_dev *wdev,1109 struct ieee80211_channel *chan,1110 unsigned int duration, u64 *cookie)1111{1112 int ret = 0;1113 struct wilc_vif *vif = netdev_priv(wdev->netdev);1114 struct wilc_priv *priv = &vif->priv;1115 u64 id;1116 1117 if (wdev->iftype == NL80211_IFTYPE_AP) {1118 netdev_dbg(vif->ndev, "Required while in AP mode\n");1119 return ret;1120 }1121 1122 id = ++priv->inc_roc_cookie;1123 if (id == 0)1124 id = ++priv->inc_roc_cookie;1125 1126 ret = wilc_remain_on_channel(vif, id, chan->hw_value,1127 wilc_wfi_remain_on_channel_expired);1128 if (ret)1129 return ret;1130 1131 vif->wilc->op_ch = chan->hw_value;1132 1133 priv->remain_on_ch_params.listen_ch = chan;1134 priv->remain_on_ch_params.listen_cookie = id;1135 *cookie = id;1136 priv->p2p_listen_state = true;1137 priv->remain_on_ch_params.listen_duration = duration;1138 1139 cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL);1140 mod_timer(&vif->hif_drv->remain_on_ch_timer,1141 jiffies + msecs_to_jiffies(duration + 1000));1142 1143 return ret;1144}1145 1146static int cancel_remain_on_channel(struct wiphy *wiphy,1147 struct wireless_dev *wdev,1148 u64 cookie)1149{1150 struct wilc_vif *vif = netdev_priv(wdev->netdev);1151 struct wilc_priv *priv = &vif->priv;1152 1153 if (cookie != priv->remain_on_ch_params.listen_cookie)1154 return -ENOENT;1155 1156 return wilc_listen_state_expired(vif, cookie);1157}1158 1159static int mgmt_tx(struct wiphy *wiphy,1160 struct wireless_dev *wdev,1161 struct cfg80211_mgmt_tx_params *params,1162 u64 *cookie)1163{1164 struct ieee80211_channel *chan = params->chan;1165 unsigned int wait = params->wait;1166 const u8 *buf = params->buf;1167 size_t len = params->len;1168 const struct ieee80211_mgmt *mgmt;1169 struct wilc_p2p_mgmt_data *mgmt_tx;1170 struct wilc_vif *vif = netdev_priv(wdev->netdev);1171 struct wilc_priv *priv = &vif->priv;1172 struct host_if_drv *wfi_drv = priv->hif_drv;1173 struct wilc_vendor_specific_ie *p;1174 struct wilc_p2p_pub_act_frame *d;1175 int ie_offset = offsetof(struct ieee80211_mgmt, u) + sizeof(*d);1176 const u8 *vendor_ie;1177 int ret = 0;1178 1179 *cookie = get_random_u32();1180 priv->tx_cookie = *cookie;1181 mgmt = (const struct ieee80211_mgmt *)buf;1182 1183 if (!ieee80211_is_mgmt(mgmt->frame_control))1184 goto out;1185 1186 mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_KERNEL);1187 if (!mgmt_tx) {1188 ret = -ENOMEM;1189 goto out;1190 }1191 1192 mgmt_tx->buff = kmemdup(buf, len, GFP_KERNEL);1193 if (!mgmt_tx->buff) {1194 ret = -ENOMEM;1195 kfree(mgmt_tx);1196 goto out;1197 }1198 1199 mgmt_tx->size = len;1200 1201 if (ieee80211_is_probe_resp(mgmt->frame_control)) {1202 wilc_set_mac_chnl_num(vif, chan->hw_value);1203 vif->wilc->op_ch = chan->hw_value;1204 goto out_txq_add_pkt;1205 }1206 1207 if (!ieee80211_is_public_action((struct ieee80211_hdr *)buf, len)) {1208 if (chan)1209 wilc_set_mac_chnl_num(vif, chan->hw_value);1210 else1211 wilc_set_mac_chnl_num(vif, vif->wilc->op_ch);1212 1213 goto out_set_timeout;1214 }1215 1216 d = (struct wilc_p2p_pub_act_frame *)(&mgmt->u.action);1217 if (d->oui_type != WLAN_OUI_TYPE_WFA_P2P ||1218 d->oui_subtype != GO_NEG_CONF) {1219 wilc_set_mac_chnl_num(vif, chan->hw_value);1220 vif->wilc->op_ch = chan->hw_value;1221 }1222 1223 if (d->oui_subtype != P2P_INV_REQ && d->oui_subtype != P2P_INV_RSP)1224 goto out_set_timeout;1225 1226 vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,1227 mgmt_tx->buff + ie_offset,1228 len - ie_offset);1229 if (!vendor_ie)1230 goto out_set_timeout;1231 1232 p = (struct wilc_vendor_specific_ie *)vendor_ie;1233 wilc_wfi_cfg_parse_ch_attr(p->attr, p->tag_len - 4, vif->wilc->sta_ch);1234 1235out_set_timeout:1236 wfi_drv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));1237 1238out_txq_add_pkt:1239 1240 wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,1241 mgmt_tx->buff, mgmt_tx->size,1242 wilc_wfi_mgmt_tx_complete);1243 1244out:1245 1246 return ret;1247}1248 1249static int mgmt_tx_cancel_wait(struct wiphy *wiphy,1250 struct wireless_dev *wdev,1251 u64 cookie)1252{1253 struct wilc_vif *vif = netdev_priv(wdev->netdev);1254 struct wilc_priv *priv = &vif->priv;1255 struct host_if_drv *wfi_drv = priv->hif_drv;1256 1257 wfi_drv->p2p_timeout = jiffies;1258 1259 if (!priv->p2p_listen_state) {1260 struct wilc_wfi_p2p_listen_params *params;1261 1262 params = &priv->remain_on_ch_params;1263 1264 cfg80211_remain_on_channel_expired(wdev,1265 params->listen_cookie,1266 params->listen_ch,1267 GFP_KERNEL);1268 }1269 1270 return 0;1271}1272 1273void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy,1274 struct wireless_dev *wdev,1275 struct mgmt_frame_regs *upd)1276{1277 struct wilc *wl = wiphy_priv(wiphy);1278 struct wilc_vif *vif = netdev_priv(wdev->netdev);1279 u32 presp_bit = BIT(IEEE80211_STYPE_PROBE_REQ >> 4);1280 u32 action_bit = BIT(IEEE80211_STYPE_ACTION >> 4);1281 u32 pauth_bit = BIT(IEEE80211_STYPE_AUTH >> 4);1282 1283 if (wl->initialized) {1284 bool prev = vif->mgmt_reg_stypes & presp_bit;1285 bool now = upd->interface_stypes & presp_bit;1286 1287 if (now != prev)1288 wilc_frame_register(vif, IEEE80211_STYPE_PROBE_REQ, now);1289 1290 prev = vif->mgmt_reg_stypes & action_bit;1291 now = upd->interface_stypes & action_bit;1292 1293 if (now != prev)1294 wilc_frame_register(vif, IEEE80211_STYPE_ACTION, now);1295 1296 prev = vif->mgmt_reg_stypes & pauth_bit;1297 now = upd->interface_stypes & pauth_bit;1298 if (now != prev)1299 wilc_frame_register(vif, IEEE80211_STYPE_AUTH, now);1300 }1301 1302 vif->mgmt_reg_stypes =1303 upd->interface_stypes & (presp_bit | action_bit | pauth_bit);1304}1305 1306static int external_auth(struct wiphy *wiphy, struct net_device *dev,1307 struct cfg80211_external_auth_params *auth)1308{1309 struct wilc_vif *vif = netdev_priv(dev);1310 1311 if (auth->status == WLAN_STATUS_SUCCESS)1312 wilc_set_external_auth_param(vif, auth);1313 1314 return 0;1315}1316 1317static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,1318 s32 rssi_thold, u32 rssi_hyst)1319{1320 return 0;1321}1322 1323static int dump_station(struct wiphy *wiphy, struct net_device *dev,1324 int idx, u8 *mac, struct station_info *sinfo)1325{1326 struct wilc_vif *vif = netdev_priv(dev);1327 int ret;1328 1329 if (idx != 0)1330 return -ENOENT;1331 1332 ret = wilc_get_rssi(vif, &sinfo->signal);1333 if (ret)1334 return ret;1335 1336 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);1337 memcpy(mac, vif->priv.associated_bss, ETH_ALEN);1338 return 0;1339}1340 1341static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,1342 bool enabled, int timeout)1343{1344 struct wilc_vif *vif = netdev_priv(dev);1345 struct wilc_priv *priv = &vif->priv;1346 1347 if (!priv->hif_drv)1348 return -EIO;1349 1350 wilc_set_power_mgmt(vif, enabled, timeout);1351 1352 return 0;1353}1354 1355static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,1356 enum nl80211_iftype type,1357 struct vif_params *params)1358{1359 struct wilc *wl = wiphy_priv(wiphy);1360 struct wilc_vif *vif = netdev_priv(dev);1361 struct wilc_priv *priv = &vif->priv;1362 1363 switch (type) {1364 case NL80211_IFTYPE_STATION:1365 vif->connecting = false;1366 dev->ieee80211_ptr->iftype = type;1367 priv->wdev.iftype = type;1368 vif->monitor_flag = 0;1369 if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE)1370 wilc_wfi_deinit_mon_interface(wl, true);1371 vif->iftype = WILC_STATION_MODE;1372 1373 if (wl->initialized)1374 wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),1375 WILC_STATION_MODE, vif->idx);1376 1377 memset(priv->assoc_stainfo.sta_associated_bss, 0,1378 WILC_MAX_NUM_STA * ETH_ALEN);1379 break;1380 1381 case NL80211_IFTYPE_P2P_CLIENT:1382 vif->connecting = false;1383 dev->ieee80211_ptr->iftype = type;1384 priv->wdev.iftype = type;1385 vif->monitor_flag = 0;1386 vif->iftype = WILC_CLIENT_MODE;1387 1388 if (wl->initialized)1389 wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),1390 WILC_STATION_MODE, vif->idx);1391 break;1392 1393 case NL80211_IFTYPE_AP:1394 dev->ieee80211_ptr->iftype = type;1395 priv->wdev.iftype = type;1396 vif->iftype = WILC_AP_MODE;1397 1398 if (wl->initialized)1399 wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),1400 WILC_AP_MODE, vif->idx);1401 break;1402 1403 case NL80211_IFTYPE_P2P_GO:1404 dev->ieee80211_ptr->iftype = type;1405 priv->wdev.iftype = type;1406 vif->iftype = WILC_GO_MODE;1407 1408 if (wl->initialized)1409 wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),1410 WILC_AP_MODE, vif->idx);1411 break;1412 1413 default:1414 netdev_err(dev, "Unknown interface type= %d\n", type);1415 return -EINVAL;1416 }1417 1418 return 0;1419}1420 1421static int start_ap(struct wiphy *wiphy, struct net_device *dev,1422 struct cfg80211_ap_settings *settings)1423{1424 struct wilc_vif *vif = netdev_priv(dev);1425 int ret;1426 1427 ret = set_channel(wiphy, &settings->chandef);1428 if (ret != 0)1429 netdev_err(dev, "Error in setting channel\n");1430 1431 wilc_wlan_set_bssid(dev, dev->dev_addr, WILC_AP_MODE);1432 1433 return wilc_add_beacon(vif, settings->beacon_interval,1434 settings->dtim_period, &settings->beacon);1435}1436 1437static int change_beacon(struct wiphy *wiphy, struct net_device *dev,1438 struct cfg80211_ap_update *params)1439{1440 struct wilc_vif *vif = netdev_priv(dev);1441 1442 return wilc_add_beacon(vif, 0, 0, ¶ms->beacon);1443}1444 1445static int stop_ap(struct wiphy *wiphy, struct net_device *dev,1446 unsigned int link_id)1447{1448 int ret;1449 struct wilc_vif *vif = netdev_priv(dev);1450 1451 wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE);1452 1453 ret = wilc_del_beacon(vif);1454 1455 if (ret)1456 netdev_err(dev, "Host delete beacon fail\n");1457 1458 return ret;1459}1460 1461static int add_station(struct wiphy *wiphy, struct net_device *dev,1462 const u8 *mac, struct station_parameters *params)1463{1464 int ret = 0;1465 struct wilc_vif *vif = netdev_priv(dev);1466 struct wilc_priv *priv = &vif->priv;1467 1468 if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {1469 memcpy(priv->assoc_stainfo.sta_associated_bss[params->aid], mac,1470 ETH_ALEN);1471 1472 ret = wilc_add_station(vif, mac, params);1473 if (ret)1474 netdev_err(dev, "Host add station fail\n");1475 }1476 1477 return ret;1478}1479 1480static int del_station(struct wiphy *wiphy, struct net_device *dev,1481 struct station_del_parameters *params)1482{1483 const u8 *mac = params->mac;1484 int ret = 0;1485 struct wilc_vif *vif = netdev_priv(dev);1486 struct wilc_priv *priv = &vif->priv;1487 struct sta_info *info;1488 1489 if (!(vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE))1490 return ret;1491 1492 info = &priv->assoc_stainfo;1493 1494 if (!mac)1495 ret = wilc_del_allstation(vif, info->sta_associated_bss);1496 1497 ret = wilc_del_station(vif, mac);1498 if (ret)1499 netdev_err(dev, "Host delete station fail\n");1500 return ret;1501}1502 1503static int change_station(struct wiphy *wiphy, struct net_device *dev,1504 const u8 *mac, struct station_parameters *params)1505{1506 int ret = 0;1507 struct wilc_vif *vif = netdev_priv(dev);1508 1509 if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {1510 ret = wilc_edit_station(vif, mac, params);1511 if (ret)1512 netdev_err(dev, "Host edit station fail\n");1513 }1514 return ret;1515}1516 1517static struct wilc_vif *wilc_get_vif_from_type(struct wilc *wl, int type)1518{1519 struct wilc_vif *vif;1520 1521 wilc_for_each_vif(wl, vif) {1522 if (vif->iftype == type)1523 return vif;1524 }1525 1526 return NULL;1527}1528 1529static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,1530 const char *name,1531 unsigned char name_assign_type,1532 enum nl80211_iftype type,1533 struct vif_params *params)1534{1535 struct wilc *wl = wiphy_priv(wiphy);1536 struct wilc_vif *vif;1537 struct wireless_dev *wdev;1538 int iftype;1539 1540 if (type == NL80211_IFTYPE_MONITOR) {1541 struct net_device *ndev;1542 int srcu_idx;1543 1544 srcu_idx = srcu_read_lock(&wl->srcu);1545 vif = wilc_get_vif_from_type(wl, WILC_AP_MODE);1546 if (!vif) {1547 vif = wilc_get_vif_from_type(wl, WILC_GO_MODE);1548 if (!vif) {1549 srcu_read_unlock(&wl->srcu, srcu_idx);1550 goto validate_interface;1551 }1552 }1553 1554 if (vif->monitor_flag) {1555 srcu_read_unlock(&wl->srcu, srcu_idx);1556 goto validate_interface;1557 }1558 1559 ndev = wilc_wfi_init_mon_interface(wl, name, vif->ndev);1560 if (ndev) {1561 vif->monitor_flag = 1;1562 } else {1563 srcu_read_unlock(&wl->srcu, srcu_idx);1564 return ERR_PTR(-EINVAL);1565 }1566 1567 wdev = &vif->priv.wdev;1568 srcu_read_unlock(&wl->srcu, srcu_idx);1569 return wdev;1570 }1571 1572validate_interface:1573 mutex_lock(&wl->vif_mutex);1574 if (wl->vif_num == WILC_NUM_CONCURRENT_IFC) {1575 pr_err("Reached maximum number of interface\n");1576 mutex_unlock(&wl->vif_mutex);1577 return ERR_PTR(-EINVAL);1578 }1579 mutex_unlock(&wl->vif_mutex);1580 1581 switch (type) {1582 case NL80211_IFTYPE_STATION:1583 iftype = WILC_STATION_MODE;1584 break;1585 case NL80211_IFTYPE_AP:1586 iftype = WILC_AP_MODE;1587 break;1588 default:1589 return ERR_PTR(-EOPNOTSUPP);1590 }1591 1592 vif = wilc_netdev_ifc_init(wl, name, iftype, type, true);1593 if (IS_ERR(vif))1594 return ERR_CAST(vif);1595 1596 return &vif->priv.wdev;1597}1598 1599static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)1600{1601 struct wilc *wl = wiphy_priv(wiphy);1602 struct wilc_vif *vif;1603 1604 if (wdev->iftype == NL80211_IFTYPE_AP ||1605 wdev->iftype == NL80211_IFTYPE_P2P_GO)1606 wilc_wfi_deinit_mon_interface(wl, true);1607 vif = netdev_priv(wdev->netdev);1608 cfg80211_stop_iface(wiphy, wdev, GFP_KERNEL);1609 cfg80211_unregister_netdevice(vif->ndev);1610 vif->monitor_flag = 0;1611 1612 mutex_lock(&wl->vif_mutex);1613 list_del_rcu(&vif->list);1614 wl->vif_num--;1615 mutex_unlock(&wl->vif_mutex);1616 synchronize_srcu(&wl->srcu);1617 return 0;1618}1619 1620static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)1621{1622 struct wilc *wl = wiphy_priv(wiphy);1623 struct wilc_vif *vif;1624 int srcu_idx;1625 1626 srcu_idx = srcu_read_lock(&wl->srcu);1627 vif = wilc_get_wl_to_vif(wl);1628 if (IS_ERR(vif)) {1629 srcu_read_unlock(&wl->srcu, srcu_idx);1630 return;1631 }1632 1633 netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);1634 wilc_set_wowlan_trigger(vif, enabled);1635 srcu_read_unlock(&wl->srcu, srcu_idx);1636}1637 1638static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,1639 enum nl80211_tx_power_setting type, int mbm)1640{1641 int ret;1642 int srcu_idx;1643 s32 tx_power = MBM_TO_DBM(mbm);1644 struct wilc *wl = wiphy_priv(wiphy);1645 struct wilc_vif *vif;1646 1647 if (!wl->initialized)1648 return -EIO;1649 1650 srcu_idx = srcu_read_lock(&wl->srcu);1651 vif = wilc_get_wl_to_vif(wl);1652 if (IS_ERR(vif)) {1653 srcu_read_unlock(&wl->srcu, srcu_idx);1654 return -EINVAL;1655 }1656 1657 netdev_info(vif->ndev, "Setting tx power %d\n", tx_power);1658 if (tx_power < 0)1659 tx_power = 0;1660 else if (tx_power > 18)1661 tx_power = 18;1662 ret = wilc_set_tx_power(vif, tx_power);1663 if (ret)1664 netdev_err(vif->ndev, "Failed to set tx power\n");1665 srcu_read_unlock(&wl->srcu, srcu_idx);1666 1667 return ret;1668}1669 1670static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,1671 int *dbm)1672{1673 int ret;1674 struct wilc_vif *vif = netdev_priv(wdev->netdev);1675 struct wilc *wl = vif->wilc;1676 1677 /* If firmware is not started, return. */1678 if (!wl->initialized)1679 return -EIO;1680 1681 ret = wilc_get_tx_power(vif, (u8 *)dbm);1682 if (ret)1683 netdev_err(vif->ndev, "Failed to get tx power\n");1684 1685 return ret;1686}1687 1688static const struct cfg80211_ops wilc_cfg80211_ops = {1689 .set_monitor_channel = set_channel,1690 .scan = scan,1691 .connect = connect,1692 .disconnect = disconnect,1693 .add_key = add_key,1694 .del_key = del_key,1695 .get_key = get_key,1696 .set_default_key = set_default_key,1697 .set_default_mgmt_key = set_default_mgmt_key,1698 .add_virtual_intf = add_virtual_intf,1699 .del_virtual_intf = del_virtual_intf,1700 .change_virtual_intf = change_virtual_intf,1701 1702 .start_ap = start_ap,1703 .change_beacon = change_beacon,1704 .stop_ap = stop_ap,1705 .add_station = add_station,1706 .del_station = del_station,1707 .change_station = change_station,1708 .get_station = get_station,1709 .dump_station = dump_station,1710 .change_bss = change_bss,1711 .set_wiphy_params = set_wiphy_params,1712 1713 .external_auth = external_auth,1714 .set_pmksa = set_pmksa,1715 .del_pmksa = del_pmksa,1716 .flush_pmksa = flush_pmksa,1717 .remain_on_channel = remain_on_channel,1718 .cancel_remain_on_channel = cancel_remain_on_channel,1719 .mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,1720 .mgmt_tx = mgmt_tx,1721 .update_mgmt_frame_registrations = wilc_update_mgmt_frame_registrations,1722 .set_power_mgmt = set_power_mgmt,1723 .set_cqm_rssi_config = set_cqm_rssi_config,1724 1725 .set_wakeup = wilc_set_wakeup,1726 .set_tx_power = set_tx_power,1727 .get_tx_power = get_tx_power,1728 1729};1730 1731static void wlan_init_locks(struct wilc *wl)1732{1733 mutex_init(&wl->hif_cs);1734 mutex_init(&wl->rxq_cs);1735 mutex_init(&wl->cfg_cmd_lock);1736 mutex_init(&wl->vif_mutex);1737 mutex_init(&wl->deinit_lock);1738 1739 spin_lock_init(&wl->txq_spinlock);1740 mutex_init(&wl->txq_add_to_head_cs);1741 1742 init_completion(&wl->txq_event);1743 init_completion(&wl->cfg_event);1744 init_completion(&wl->sync_event);1745 init_completion(&wl->txq_thread_started);1746 init_srcu_struct(&wl->srcu);1747}1748 1749void wlan_deinit_locks(struct wilc *wilc)1750{1751 mutex_destroy(&wilc->hif_cs);1752 mutex_destroy(&wilc->rxq_cs);1753 mutex_destroy(&wilc->cfg_cmd_lock);1754 mutex_destroy(&wilc->txq_add_to_head_cs);1755 mutex_destroy(&wilc->vif_mutex);1756 mutex_destroy(&wilc->deinit_lock);1757 cleanup_srcu_struct(&wilc->srcu);1758}1759 1760int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,1761 const struct wilc_hif_func *ops)1762{1763 struct wilc *wl;1764 int ret, i;1765 1766 wl = wilc_create_wiphy(dev);1767 if (!wl)1768 return -EINVAL;1769 1770 wlan_init_locks(wl);1771 1772 ret = wilc_wlan_cfg_init(wl);1773 if (ret)1774 goto free_wl;1775 1776 *wilc = wl;1777 wl->io_type = io_type;1778 wl->hif_func = ops;1779 1780 for (i = 0; i < NQUEUES; i++)1781 INIT_LIST_HEAD(&wl->txq[i].txq_head.list);1782 1783 INIT_LIST_HEAD(&wl->rxq_head.list);1784 INIT_LIST_HEAD(&wl->vif_list);1785 1786 wl->hif_workqueue = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM,1787 wiphy_name(wl->wiphy));1788 if (!wl->hif_workqueue) {1789 ret = -ENOMEM;1790 goto free_cfg;1791 }1792 1793 return 0;1794 1795free_cfg:1796 wilc_wlan_cfg_deinit(wl);1797 1798free_wl:1799 wlan_deinit_locks(wl);1800 wiphy_unregister(wl->wiphy);1801 wiphy_free(wl->wiphy);1802 return ret;1803}1804EXPORT_SYMBOL_GPL(wilc_cfg80211_init);1805 1806struct wilc *wilc_create_wiphy(struct device *dev)1807{1808 struct wiphy *wiphy;1809 struct wilc *wl;1810 int ret;1811 1812 wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(*wl));1813 if (!wiphy)1814 return NULL;1815 1816 wl = wiphy_priv(wiphy);1817 1818 memcpy(wl->bitrates, wilc_bitrates, sizeof(wilc_bitrates));1819 memcpy(wl->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));1820 wl->band.bitrates = wl->bitrates;1821 wl->band.n_bitrates = ARRAY_SIZE(wl->bitrates);1822 wl->band.channels = wl->channels;1823 wl->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels);1824 1825 wl->band.ht_cap.ht_supported = 1;1826 wl->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);1827 wl->band.ht_cap.mcs.rx_mask[0] = 0xff;1828 wl->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;1829 wl->band.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;1830 1831 wiphy->bands[NL80211_BAND_2GHZ] = &wl->band;1832 1833 wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID;1834#ifdef CONFIG_PM1835 wiphy->wowlan = &wowlan_support;1836#endif1837 wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;1838 wiphy->max_scan_ie_len = 1000;1839 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;1840 memcpy(wl->cipher_suites, wilc_cipher_suites,1841 sizeof(wilc_cipher_suites));1842 wiphy->cipher_suites = wl->cipher_suites;1843 wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);1844 wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;1845 1846 wiphy->max_remain_on_channel_duration = 500;1847 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |1848 BIT(NL80211_IFTYPE_AP) |1849 BIT(NL80211_IFTYPE_MONITOR) |1850 BIT(NL80211_IFTYPE_P2P_GO) |1851 BIT(NL80211_IFTYPE_P2P_CLIENT);1852 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;1853 wiphy->features |= NL80211_FEATURE_SAE;1854 set_wiphy_dev(wiphy, dev);1855 wl->wiphy = wiphy;1856 ret = wiphy_register(wiphy);1857 if (ret) {1858 wiphy_free(wiphy);1859 return NULL;1860 }1861 return wl;1862}1863 1864int wilc_init_host_int(struct net_device *net)1865{1866 int ret;1867 struct wilc_vif *vif = netdev_priv(net);1868 struct wilc_priv *priv = &vif->priv;1869 1870 priv->p2p_listen_state = false;1871 1872 mutex_init(&priv->scan_req_lock);1873 ret = wilc_init(net, &priv->hif_drv);1874 if (ret)1875 netdev_err(net, "Error while initializing hostinterface\n");1876 1877 return ret;1878}1879 1880void wilc_deinit_host_int(struct net_device *net)1881{1882 int ret;1883 struct wilc_vif *vif = netdev_priv(net);1884 struct wilc_priv *priv = &vif->priv;1885 1886 priv->p2p_listen_state = false;1887 1888 flush_workqueue(vif->wilc->hif_workqueue);1889 mutex_destroy(&priv->scan_req_lock);1890 ret = wilc_deinit(vif);1891 1892 if (ret)1893 netdev_err(net, "Error while deinitializing host interface\n");1894}1895 1896